The TLS code is scaring me and I don't trust it.

Hopefully the impact it had on non-tls code has been shaken out.
(There was at least one bug / crash due to this, since been fixed.)

That being said, I'm running this in production since some time
without issues.

OK florian

On Thu, Sep 12, 2019 at 12:26:40PM +0100, Stuart Henderson wrote:
> Any comments, test reports, objections or OKs?
> 
> Changes since the version we have:
> 
> 4.2.2 - Bug fixes only:
> 
> Fix #20: CVE-2019-13207 Stack-based Buffer Overflow in the 
> dname_concatenate() function. Reported by Frederic Cambus. It causes the zone 
> parser to crash on a malformed zone file, with assertions enabled, an 
> assertion catches it.
> Fix #19: Out-of-bounds read caused by improper validation of array index. 
> Reported by Frederic Cambus. The zone parser fails on type SIG because of 
> mismatched definition with RRSIG.
> PR #23: Fix typo in nsd.conf man-page.
> Fix that NSD warns for wrong length of the hash in SSHFP records.
> Fix #25: NSD doesn't refresh zones after extended downtime, it refreshes the 
> old zones.
> Set no renegotiation on the SSL context to stop client session renegotiation.
> Fix #29: SSHFP check NULL pointer dereference.
> Fix #30: SSHFP check failure due to missing domain name.
> Fix to timeval_add in minievent for remaining second in microseconds.
> PR #31: nsd-control: Add missing stdio header.
> PR #32: tsig: Fix compilation without HAVE_SSL.
> Cleanup tls context on xfrd exit.
> Fix #33: Fix segfault in service of remaining streams on exit.
> Fix error message for out of zone data to have more information.
> 
> 4.2.1 -
> 
> Features:
> 
> Added num.tls and num.tls6 stat counters.
> PR #12: send-buffer-size, receive-buffer-size, tcp-reject-overflow options 
> for nsd.conf, from Jeroen Koekkoek.
> Fix #14, tcp connections have 1/10 to be active and have to work every 
> second, and then they get time to complete during a reload, this is a process 
> that lingers with the old version during a version update.
> 
> Bug Fixes:
> 
> Fix #13: Stray dot at the end of some log entries, removes dot after updated 
> serial number in log entry.
> Fix TLS cipher selection, the previous was redundant, prefers 
> CHACHA20-POLY1305 over AESGCM and was not as readable as it could be.
> Consolidate server tls context create and remote control context create, with 
> hardening for the remote control tls context too.
> Fix to init event structure for reassignment.
> Fix to init event not pointer, in reassignment.
> Fix #15: crash in SSL library, initialize variables for TCP access when TLS 
> is configured.
> Fix tls handshake event callback function mistake, reported by Mykhailo 
> Danylenko.
> Initialize event structures before event_set, to stop uninitialized values 
> from setting event library lists and assertions, that would sometimes also 
> show after event_del.
> Do not use symbol from libc, instead use own replacement, if not available, 
> for accept4.
> Fix output of nsd-checkconf -h.
> 
> 4.2.0 -
> 
> Features:
> 
> Print IP address when bind socket fails with error.
> Fix #4249: The option hide-identity: yes stops NSD from responding with the 
> hostname for chaos class queries. Implements the RFC4892 security 
> considerations.
> Patch to add support for TCP Fast Open, from Sara Dickinson (Sinodun).
> Patch to add support for tls service on a specified tls port, from Sara 
> Dickinson (Sinodun).
> Use travis for build check, initial unit test and clang analysis.
> TLS OCSP stapling support, enabled with tls-service-ocsp: filename, patch 
> from Andreas Schulze.
> 
> Bug Fixes:
> 
> Fix to delete unused zparser.default_apex member.
> Fix that the TLS handshake routine sets the correct event to continue when 
> done.
> Fix that TLS renegotiation calls the read and write routines again with the 
> same parameters when the desired event has been satisfied.
> Fix that TCP Fastopen has better error message and supports OSX.
> Fix to avoid buffer alloc with global buffer in tls write handler.
> Fix to initialize event structure when accepting TCP connection.
> Disable TLS1.0, TLS1.1 and weak ciphers, enable CIPHER_SERVER_PREFERENCE, 
> patch from Andreas Schulze.
> further setup ssl ctx after the keys are loaded, for ECDH.
> Fix #10: Fix memory leaks caused by duplicate rr and include instructions.
> Fix to define _OPENBSD_SOURCE to get reallocarray on NetBSD.
> 
> 
>  config.h.in        |   25 +
>  configlexer.lex    |    8 
>  configparser.y     |   81 +++
>  configure          |  181 ++++++--
>  configure.ac       |   65 ++
>  dns.c              |    8 
>  ipc.c              |    9 
>  mini_event.c       |    5 
>  nsd-checkconf.8.in |    2 
>  nsd-checkconf.c    |   21 
>  nsd-checkzone.8.in |    2 
>  nsd-checkzone.c    |    4 
>  nsd-control.8.in   |   10 
>  nsd-control.c      |    8 
>  nsd.8.in           |    4 
>  nsd.c              |   12 
>  nsd.conf.5.in      |   51 ++
>  nsd.conf.sample.in |   24 +
>  nsd.h              |   15 
>  options.c          |    8 
>  options.h          |   13 
>  query.c            |   10 
>  remote.c           |   87 ---
>  server.c           | 1183 
> ++++++++++++++++++++++++++++++++++++++++++++++++++---
>  tsig.c             |   55 ++
>  util.c             |   29 +
>  util.h             |    9 
>  xfrd-disk.c        |    7 
>  xfrd-notify.c      |    6 
>  xfrd-tcp.c         |    2 
>  xfrd.c             |   13 
>  zlexer.lex         |    4 
>  zonec.c            |   49 ++
>  zonec.h            |    3 
>  zparser.y          |    9 
>  35 files changed, 1818 insertions(+), 204 deletions(-)
> 
> 
> 
> Index: config.h.in
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/config.h.in,v
> retrieving revision 1.29
> diff -u -p -r1.29 config.h.in
> --- config.h.in       30 Mar 2019 01:20:29 -0000      1.29
> +++ config.h.in       12 Sep 2019 11:25:03 -0000
> @@ -76,6 +76,14 @@
>  /* if time.h provides ctime_r prototype */
>  #undef HAVE_CTIME_R_PROTO
>  
> +/* Define to 1 if you have the declaration of `SSL_CTX_set_ecdh_auto', and to
> +   0 if you don't. */
> +#undef HAVE_DECL_SSL_CTX_SET_ECDH_AUTO
> +
> +/* Define to 1 if you have the declaration of `SSL_CTX_set_tmp_ecdh', and to > 0
> +   if you don't. */
> +#undef HAVE_DECL_SSL_CTX_SET_TMP_ECDH
> +
>  /* Define to 1 if you have the `dup2' function. */
>  #undef HAVE_DUP2
>  
> @@ -221,6 +229,9 @@
>  /* Define to 1 if you have the `OPENSSL_init_ssl' function. */
>  #undef HAVE_OPENSSL_INIT_SSL
>  
> +/* Define to 1 if you have the <openssl/ocsp.h> header file. */
> +#undef HAVE_OPENSSL_OCSP_H
> +
>  /* Define to 1 if you have the <openssl/rand.h> header file. */
>  #undef HAVE_OPENSSL_RAND_H
>  
> @@ -239,7 +250,7 @@
>  /* Define to 1 if you have the `pwrite' function. */
>  #undef HAVE_PWRITE
>  
> -/* Define to 1 if you have the `reallocarray' function. */
> +/* If we have reallocarray(3) */
>  #undef HAVE_REALLOCARRAY
>  
>  /* Define if recvmmsg is implemented */
> @@ -281,6 +292,9 @@
>  /* Define if you have the SSL libraries installed. */
>  #undef HAVE_SSL
>  
> +/* Define to 1 if you have the `SSL_CTX_set_security_level' function. */
> +#undef HAVE_SSL_CTX_SET_SECURITY_LEVEL
> +
>  /* Define to 1 if you have the <stdarg.h> header file. */
>  #undef HAVE_STDARG_H
>  
> @@ -507,6 +521,9 @@
>  /* Define to the default tcp timeout. */
>  #undef TCP_TIMEOUT
>  
> +/* Define to the default DNS over TLS port. */
> +#undef TLS_PORT
> +
>  /* Define to the default maximum udp message length. */
>  #undef UDP_MAX_MESSAGE_LEN
>  
> @@ -550,6 +567,9 @@
>  #endif
>  
>  
> +/* Define this to enable TCP fast open. */
> +#undef USE_TCP_FASTOPEN
> +
>  /* Define this to enable per-zone statistics gathering. */
>  #undef USE_ZONE_STATS
>  
> @@ -687,6 +707,9 @@
>  #  endif
>  #  ifndef _BSD_SOURCE
>  #    define _BSD_SOURCE 1
> +#  endif
> +#  ifndef _OPENBSD_SOURCE
> +#    define _OPENBSD_SOURCE 1
>  #  endif
>  #  ifndef _DEFAULT_SOURCE
>  #    define _DEFAULT_SOURCE 1
> Index: configlexer.lex
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/configlexer.lex,v
> retrieving revision 1.11
> diff -u -p -r1.11 configlexer.lex
> --- configlexer.lex   10 Dec 2018 16:09:11 -0000      1.11
> +++ configlexer.lex   12 Sep 2019 11:25:03 -0000
> @@ -201,9 +201,12 @@ ip-address{COLON}        { LEXOUT(("v(%s) ", yy
>  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;}
> +send-buffer-size{COLON}      { LEXOUT(("v(%s) ", yytext)); return 
> VAR_SEND_BUFFER_SIZE;}
> +receive-buffer-size{COLON}   { LEXOUT(("v(%s) ", yytext)); return 
> VAR_RECEIVE_BUFFER_SIZE;}
>  debug-mode{COLON}    { LEXOUT(("v(%s) ", yytext)); return VAR_DEBUG_MODE;}
>  use-systemd{COLON}   { LEXOUT(("v(%s) ", yytext)); return VAR_USE_SYSTEMD;}
>  hide-version{COLON}  { LEXOUT(("v(%s) ", yytext)); return VAR_HIDE_VERSION;}
> +hide-identity{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_HIDE_IDENTITY;}
>  ip4-only{COLON}              { LEXOUT(("v(%s) ", yytext)); return 
> VAR_IP4_ONLY;}
>  ip6-only{COLON}              { LEXOUT(("v(%s) ", yytext)); return 
> VAR_IP6_ONLY;}
>  do-ip4{COLON}                { LEXOUT(("v(%s) ", yytext)); return 
> VAR_DO_IP4;}
> @@ -215,6 +218,7 @@ nsid{COLON}               { LEXOUT(("v(%s) ", yytext)
>  logfile{COLON}               { LEXOUT(("v(%s) ", yytext)); return 
> VAR_LOGFILE;}
>  server-count{COLON}  { LEXOUT(("v(%s) ", yytext)); return VAR_SERVER_COUNT;}
>  tcp-count{COLON}     { LEXOUT(("v(%s) ", yytext)); return VAR_TCP_COUNT;}
> +tcp-reject-overflow{COLON}   { LEXOUT(("v(%s) ", yytext)); return 
> VAR_TCP_REJECT_OVERFLOW;}
>  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;}
> @@ -287,6 +291,10 @@ min-refresh-time{COLON}  { LEXOUT(("v(%s)
>  max-retry-time{COLON}        { LEXOUT(("v(%s) ", yytext)); return 
> VAR_MAX_RETRY_TIME;}
>  min-retry-time{COLON}        { LEXOUT(("v(%s) ", yytext)); return 
> VAR_MIN_RETRY_TIME;}
>  multi-master-check{COLON}      { LEXOUT(("v(%s) ", yytext)); return 
> VAR_MULTI_MASTER_CHECK;}
> +tls-service-key{COLON} { LEXOUT(("v(%s) ", yytext)); return 
> VAR_TLS_SERVICE_KEY;}
> +tls-service-ocsp{COLON}      { LEXOUT(("v(%s) ", yytext)); return 
> VAR_TLS_SERVICE_OCSP;}
> +tls-service-pem{COLON} { LEXOUT(("v(%s) ", yytext)); return 
> VAR_TLS_SERVICE_PEM;}
> +tls-port{COLON}        { LEXOUT(("v(%s) ", yytext)); return VAR_TLS_PORT;}
>  {NEWLINE}            { LEXOUT(("NL\n")); cfg_parser->line++;}
>  
>       /* Quoted strings. Strip leading and ending quotes */
> Index: configparser.y
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/configparser.y,v
> retrieving revision 1.23
> diff -u -p -r1.23 configparser.y
> --- configparser.y    10 Dec 2018 16:09:11 -0000      1.23
> +++ configparser.y    12 Sep 2019 11:25:03 -0000
> @@ -59,7 +59,7 @@ extern config_parser_state_type* cfg_par
>  %token VAR_KEY
>  %token VAR_ALGORITHM VAR_SECRET
>  %token VAR_AXFR VAR_UDP
> -%token VAR_VERBOSITY VAR_HIDE_VERSION
> +%token VAR_VERBOSITY VAR_HIDE_VERSION VAR_HIDE_IDENTITY
>  %token VAR_PATTERN VAR_INCLUDEPATTERN VAR_ZONELISTFILE
>  %token VAR_REMOTE_CONTROL VAR_CONTROL_ENABLE VAR_CONTROL_INTERFACE
>  %token VAR_CONTROL_PORT VAR_SERVER_KEY_FILE VAR_SERVER_CERT_FILE
> @@ -76,6 +76,9 @@ extern config_parser_state_type* cfg_par
>  %token VAR_DNSTAP_SEND_IDENTITY VAR_DNSTAP_SEND_VERSION VAR_DNSTAP_IDENTITY
>  %token VAR_DNSTAP_VERSION VAR_DNSTAP_LOG_AUTH_QUERY_MESSAGES
>  %token VAR_DNSTAP_LOG_AUTH_RESPONSE_MESSAGES
> +%token VAR_TLS_SERVICE_KEY VAR_TLS_SERVICE_OCSP VAR_TLS_SERVICE_PEM 
> VAR_TLS_PORT
> +%token VAR_SEND_BUFFER_SIZE VAR_RECEIVE_BUFFER_SIZE
> +%token VAR_TCP_REJECT_OVERFLOW
>  
>  %%
>  toplevelvars: /* empty */ | toplevelvars toplevelvar ;
> @@ -107,7 +110,11 @@ content_server: server_ip_address | serv
>       server_zonefiles_check | server_do_ip4 | server_do_ip6 |
>       server_zonefiles_write | server_log_time_ascii | server_round_robin |
>       server_reuseport | server_version | server_ip_freebind |
> -     server_minimal_responses | server_refuse_any | server_use_systemd;
> +     server_tls_service_key | server_tls_service_pem | server_tls_port |
> +     server_minimal_responses | server_refuse_any | server_use_systemd |
> +     server_hide_identity | server_tls_service_ocsp |
> +     server_send_buffer_size | server_receive_buffer_size |
> +     server_tcp_reject_overflow;
>  server_ip_address: VAR_IP_ADDRESS STRING 
>       { 
>               OUTYY(("P(server_ip_address:%s)\n", $2)); 
> @@ -138,14 +145,32 @@ server_ip_transparent: VAR_IP_TRANSPAREN
>               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)); 
> +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_send_buffer_size: VAR_SEND_BUFFER_SIZE STRING
> +     {
> +             int sz = atoi($2);
> +             OUTYY(("P(server_send_buffer_size:%s)\n", $2));
> +             if(sz < 0)
> +                     yyerror("non-negative number expected");
> +             else cfg_parser->opt->send_buffer_size = sz;
> +     }
> +     ;
> +server_receive_buffer_size: VAR_RECEIVE_BUFFER_SIZE STRING
> +     {
> +             int sz = atoi($2);
> +             OUTYY(("P(server_receive_buffer_size:%s)\n", $2));
> +             if(sz < 0)
> +                     yyerror("non-negative number expected");
> +             else cfg_parser->opt->receive_buffer_size = sz;
> +     }
> +     ;
>  server_debug_mode: VAR_DEBUG_MODE STRING 
>       { 
>               OUTYY(("P(server_debug_mode:%s)\n", $2)); 
> @@ -175,6 +200,14 @@ server_hide_version: VAR_HIDE_VERSION ST
>               else cfg_parser->opt->hide_version = (strcmp($2, "yes")==0);
>       }
>       ;
> +server_hide_identity: VAR_HIDE_IDENTITY STRING 
> +     { 
> +             OUTYY(("P(server_hide_identity:%s)\n", $2)); 
> +             if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
> +                     yyerror("expected yes or no.");
> +             else cfg_parser->opt->hide_identity = (strcmp($2, "yes")==0);
> +     }
> +     ;
>  server_ip4_only: VAR_IP4_ONLY STRING 
>       { 
>               /* for backwards compatibility in config file with NSD3 */
> @@ -339,6 +372,17 @@ server_tcp_count: VAR_TCP_COUNT STRING
>               else cfg_parser->opt->tcp_count = atoi($2);
>       }
>       ;
> +server_tcp_reject_overflow: VAR_TCP_REJECT_OVERFLOW STRING
> +     {
> +             OUTYY(("P(server_reject_overflow_tcp:%s)\n", $2));
> +             if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) {
> +                     yyerror("tcp-reject-overflow: expected yes or no.");
> +             } else {
> +                     cfg_parser->opt->tcp_reject_overflow =
> +                             (strcmp($2, "yes")==0);
> +             }
> +     }
> +     ;
>  server_pidfile: VAR_PIDFILE STRING
>       { 
>               OUTYY(("P(server_pidfile:%s)\n", $2)); 
> @@ -529,7 +573,30 @@ server_zonefiles_write: VAR_ZONEFILES_WR
>               else cfg_parser->opt->zonefiles_write = atoi($2);
>       }
>       ;
> -
> +server_tls_service_key: VAR_TLS_SERVICE_KEY STRING
> +     {
> +             OUTYY(("P(server_tls_service_key:%s)\n", $2));
> +             cfg_parser->opt->tls_service_key = 
> region_strdup(cfg_parser->opt->region, $2);
> +     }
> +     ;
> +server_tls_service_ocsp: VAR_TLS_SERVICE_OCSP STRING
> +     {
> +             OUTYY(("P(server_tls_service_ocsp:%s)\n", $2));
> +             cfg_parser->opt->tls_service_ocsp = 
> region_strdup(cfg_parser->opt->region, $2);
> +     }
> +     ;
> +server_tls_service_pem: VAR_TLS_SERVICE_PEM STRING
> +     {
> +             OUTYY(("P(server_tls_service_pem:%s)\n", $2));
> +             cfg_parser->opt->tls_service_pem = 
> region_strdup(cfg_parser->opt->region, $2);
> +     }
> +     ;
> +server_tls_port: VAR_TLS_PORT STRING
> +     {
> +             OUTYY(("P(server_tls_port:%s)\n", $2));
> +             cfg_parser->opt->tls_port = 
> region_strdup(cfg_parser->opt->region, $2);
> +     }
> +     ;
>  rcstart: VAR_REMOTE_CONTROL
>       {
>               OUTYY(("\nP(remote-control:)\n"));
> @@ -714,7 +781,7 @@ zone_config_item: zone_zonefile | zone_a
>       zone_outgoing_interface | zone_allow_axfr_fallback | include_pattern |
>       zone_rrl_whitelist | zone_zonestats | zone_max_refresh_time |
>       zone_min_refresh_time | zone_max_retry_time | zone_min_retry_time |
> -       zone_size_limit_xfr | zone_multi_master_check;
> +     zone_size_limit_xfr | zone_multi_master_check;
>  pattern_name: VAR_NAME STRING
>       { 
>               OUTYY(("P(pattern_name:%s)\n", $2)); 
> Index: configure
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/configure,v
> retrieving revision 1.42
> diff -u -p -r1.42 configure
> --- configure 30 Mar 2019 01:20:29 -0000      1.42
> +++ configure 12 Sep 2019 11:25:03 -0000
> @@ -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.27.
> +# Generated by GNU Autoconf 2.69 for NSD 4.2.2.
>  #
>  # Report bugs to <[email protected]>.
>  #
> @@ -580,8 +580,8 @@ MAKEFLAGS=
>  # Identity of this package.
>  PACKAGE_NAME='NSD'
>  PACKAGE_TARNAME='nsd'
> -PACKAGE_VERSION='4.1.27'
> -PACKAGE_STRING='NSD 4.1.27'
> +PACKAGE_VERSION='4.2.2'
> +PACKAGE_STRING='NSD 4.2.2'
>  PACKAGE_BUGREPORT='[email protected]'
>  PACKAGE_URL=''
>  
> @@ -744,6 +744,7 @@ with_dnstap_socket_path
>  with_protobuf_c
>  with_libfstrm
>  enable_systemd
> +enable_tcp_fastopen
>  '
>        ac_precious_vars='build_alias
>  host_alias
> @@ -1296,7 +1297,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.27 to adapt to many kinds of systems.
> +\`configure' configures NSD 4.2.2 to adapt to many kinds of systems.
>  
>  Usage: $0 [OPTION]... [VAR=VALUE]...
>  
> @@ -1357,7 +1358,7 @@ fi
>  
>  if test -n "$ac_init_help"; then
>    case $ac_init_help in
> -     short | recursive ) echo "Configuration of NSD 4.1.27:";;
> +     short | recursive ) echo "Configuration of NSD 4.2.2:";;
>     esac
>    cat <<\_ACEOF
>  
> @@ -1398,6 +1399,7 @@ Optional Features:
>                            but unaligned reads.
>    --enable-dnstap         Enable dnstap support (requires fstrm, protobuf-c)
>    --enable-systemd        compile with systemd support
> +  --enable-tcp-fastopen   Enable TCP Fast Open
>  
>  Optional Packages:
>    --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
> @@ -1512,7 +1514,7 @@ fi
>  test -n "$ac_init_help" && exit $ac_status
>  if $ac_init_version; then
>    cat <<\_ACEOF
> -NSD configure 4.1.27
> +NSD configure 4.2.2
>  generated by GNU Autoconf 2.69
>  
>  Copyright (C) 2012 Free Software Foundation, Inc.
> @@ -2221,7 +2223,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.27, which was
> +It was created by NSD $as_me 4.2.2, which was
>  generated by GNU Autoconf 2.69.  Invocation command line was
>  
>    $ $0 $@
> @@ -8340,20 +8342,44 @@ esac
>  fi
>  
>  
> -ac_fn_c_check_func "$LINENO" "reallocarray" "ac_cv_func_reallocarray"
> -if test "x$ac_cv_func_reallocarray" = xyes; then :
> -  $as_echo "#define HAVE_REALLOCARRAY 1" >>confdefs.h
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for reallocarray" >&5
> +$as_echo_n "checking for reallocarray... " >&6; }
> +cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> +/* end confdefs.h.  */
> +$ac_includes_default
> +
> +#ifndef _OPENBSD_SOURCE
> +#define _OPENBSD_SOURCE 1
> +#endif
> +#include <stdlib.h>
> +int main(void) {
> +     void* p = reallocarray(NULL, 10, 100);
> +     free(p);
> +     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; }
> +
> +$as_echo "#define HAVE_REALLOCARRAY 1" >>confdefs.h
> +
>  
>  else
> -  case " $LIBOBJS " in
> +
> +     { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +     case " $LIBOBJS " in
>    *" reallocarray.$ac_objext "* ) ;;
>    *) LIBOBJS="$LIBOBJS reallocarray.$ac_objext"
>   ;;
>  esac
>  
> -fi
> -
>  
> +fi
> +rm -f core conftest.err conftest.$ac_objext \
> +    conftest$ac_exeext conftest.$ac_ext
>  
>  #
>  # Check for b64_ntop (and assume result applies to b64_pton as well).
> @@ -8536,6 +8562,11 @@ _ACEOF
>  
>  
>  cat >>confdefs.h <<_ACEOF
> +#define TLS_PORT "853"
> +_ACEOF
> +
> +
> +cat >>confdefs.h <<_ACEOF
>  #define MAXSYSLOGMSGLEN 512
>  _ACEOF
>  
> @@ -9104,56 +9135,93 @@ fi
>       fi
>       SSL_LIBS="-lssl"
>  
> -     for ac_header in openssl/ssl.h
> +     for ac_header in openssl/ssl.h openssl/err.h openssl/rand.h 
> openssl/ocsp.h
>  do :
> -  ac_fn_c_check_header_compile "$LINENO" "openssl/ssl.h" 
> "ac_cv_header_openssl_ssl_h" "$ac_includes_default
> +  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
> +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" 
> "$ac_includes_default
>  "
> -if test "x$ac_cv_header_openssl_ssl_h" = xyes; then :
> +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
>    cat >>confdefs.h <<_ACEOF
> -#define HAVE_OPENSSL_SSL_H 1
> +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
>  _ACEOF
>  
>  fi
>  
>  done
>  
> -     for ac_header in openssl/err.h
> +     for ac_func in HMAC_CTX_reset HMAC_CTX_new EVP_cleanup 
> ERR_load_crypto_strings OPENSSL_init_crypto SSL_CTX_set_security_level
>  do :
> -  ac_fn_c_check_header_compile "$LINENO" "openssl/err.h" 
> "ac_cv_header_openssl_err_h" "$ac_includes_default
> -"
> -if test "x$ac_cv_header_openssl_err_h" = xyes; then :
> +  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 HAVE_OPENSSL_ERR_H 1
> +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
>  _ACEOF
>  
>  fi
> -
>  done
>  
> -     for ac_header in openssl/rand.h
> -do :
> -  ac_fn_c_check_header_compile "$LINENO" "openssl/rand.h" 
> "ac_cv_header_openssl_rand_h" "$ac_includes_default
> +     ac_fn_c_check_decl "$LINENO" "SSL_CTX_set_ecdh_auto" 
> "ac_cv_have_decl_SSL_CTX_set_ecdh_auto" "
> +$ac_includes_default
> +#ifdef HAVE_OPENSSL_ERR_H
> +#include <openssl/err.h>
> +#endif
> +
> +#ifdef HAVE_OPENSSL_RAND_H
> +#include <openssl/rand.h>
> +#endif
> +
> +#ifdef HAVE_OPENSSL_CONF_H
> +#include <openssl/conf.h>
> +#endif
> +
> +#ifdef HAVE_OPENSSL_ENGINE_H
> +#include <openssl/engine.h>
> +#endif
> +#include <openssl/ssl.h>
> +#include <openssl/evp.h>
> +
>  "
> -if test "x$ac_cv_header_openssl_rand_h" = xyes; then :
> -  cat >>confdefs.h <<_ACEOF
> -#define HAVE_OPENSSL_RAND_H 1
> +if test "x$ac_cv_have_decl_SSL_CTX_set_ecdh_auto" = xyes; then :
> +  ac_have_decl=1
> +else
> +  ac_have_decl=0
> +fi
> +
> +cat >>confdefs.h <<_ACEOF
> +#define HAVE_DECL_SSL_CTX_SET_ECDH_AUTO $ac_have_decl
>  _ACEOF
> +ac_fn_c_check_decl "$LINENO" "SSL_CTX_set_tmp_ecdh" 
> "ac_cv_have_decl_SSL_CTX_set_tmp_ecdh" "
> +$ac_includes_default
> +#ifdef HAVE_OPENSSL_ERR_H
> +#include <openssl/err.h>
> +#endif
>  
> -fi
> +#ifdef HAVE_OPENSSL_RAND_H
> +#include <openssl/rand.h>
> +#endif
>  
> -done
> +#ifdef HAVE_OPENSSL_CONF_H
> +#include <openssl/conf.h>
> +#endif
>  
> -     for ac_func in HMAC_CTX_reset HMAC_CTX_new EVP_cleanup 
> ERR_load_crypto_strings OPENSSL_init_crypto
> -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
> +#ifdef HAVE_OPENSSL_ENGINE_H
> +#include <openssl/engine.h>
> +#endif
> +#include <openssl/ssl.h>
> +#include <openssl/evp.h>
>  
> +"
> +if test "x$ac_cv_have_decl_SSL_CTX_set_tmp_ecdh" = xyes; then :
> +  ac_have_decl=1
> +else
> +  ac_have_decl=0
>  fi
> -done
> +
> +cat >>confdefs.h <<_ACEOF
> +#define HAVE_DECL_SSL_CTX_SET_TMP_ECDH $ac_have_decl
> +_ACEOF
> +
>  
>  
>       BAKLIBS="$LIBS"
> @@ -9174,6 +9242,8 @@ 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;}
> +     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: No SSL, therefore TLS 
> is disabled" >&5
> +$as_echo "$as_me: WARNING: No SSL, therefore TLS is disabled" >&2;}
>  fi
>  
>  # Check whether --enable-nsec3 was given.
> @@ -9648,6 +9718,33 @@ fi
>  
>  # Include systemd.m4 - end
>  
> +# Check whether --enable-tcp-fastopen was given.
> +if test "${enable_tcp_fastopen+set}" = set; then :
> +  enableval=$enable_tcp_fastopen;
> +fi
> +
> +case "$enable_tcp_fastopen" in
> +       yes)
> +             ac_fn_c_check_decl "$LINENO" "TCP_FASTOPEN" 
> "ac_cv_have_decl_TCP_FASTOPEN" "$ac_includes_default
> +#include <netinet/tcp.h>
> +
> +"
> +if test "x$ac_cv_have_decl_TCP_FASTOPEN" = xyes; then :
> +
> +else
> +  as_fn_error $? "TCP Fast Open is not available: please rerun without 
> --enable-tcp-fastopen" "$LINENO" 5
> +fi
> +
> +
> +cat >>confdefs.h <<_ACEOF
> +#define USE_TCP_FASTOPEN 1
> +_ACEOF
> +
> +               ;;
> +       no|*)
> +               ;;
> +esac
> +
>  
>  
>  
> @@ -10194,7 +10291,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
>  # 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.27, which was
> +This file was extended by NSD $as_me 4.2.2, which was
>  generated by GNU Autoconf 2.69.  Invocation command line was
>  
>    CONFIG_FILES    = $CONFIG_FILES
> @@ -10256,7 +10353,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.27
> +NSD config.status 4.2.2
>  configured by $0, generated by GNU Autoconf 2.69,
>    with options \\"\$ac_cs_config\\"
>  
> Index: configure.ac
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/configure.ac,v
> retrieving revision 1.42
> diff -u -p -r1.42 configure.ac
> --- configure.ac      30 Mar 2019 01:20:29 -0000      1.42
> +++ configure.ac      12 Sep 2019 11:25:03 -0000
> @@ -5,7 +5,7 @@ dnl
>  sinclude(acx_nlnetlabs.m4)
>  sinclude(dnstap/dnstap.m4)
>  
> -AC_INIT(NSD,4.1.27,[email protected])
> +AC_INIT(NSD,4.2.2,[email protected])
>  AC_CONFIG_HEADER([config.h])
>  
>  CFLAGS="$CFLAGS"
> @@ -689,7 +689,24 @@ AC_REPLACE_FUNCS(strlcpy)
>  AC_REPLACE_FUNCS(strptime)
>  AC_REPLACE_FUNCS(pselect)
>  AC_REPLACE_FUNCS(memmove)
> -AC_REPLACE_FUNCS(reallocarray)
> +AC_MSG_CHECKING([for reallocarray])
> +AC_LINK_IFELSE([AC_LANG_SOURCE(AC_INCLUDES_DEFAULT
> +[[
> +#ifndef _OPENBSD_SOURCE
> +#define _OPENBSD_SOURCE 1
> +#endif
> +#include <stdlib.h>
> +int main(void) {
> +     void* p = reallocarray(NULL, 10, 100);
> +     free(p);
> +     return 0;
> +}
> +]])], [AC_MSG_RESULT(yes)
> +     AC_DEFINE(HAVE_REALLOCARRAY, 1, [If we have reallocarray(3)])
> +], [
> +     AC_MSG_RESULT(no)
> +     AC_LIBOBJ(reallocarray)
> +])
>  
>  #
>  # Check for b64_ntop (and assume result applies to b64_pton as well).
> @@ -755,6 +772,7 @@ AC_DEFINE_UNQUOTED([TCP_MAX_MESSAGE_LEN]
>  AC_DEFINE_UNQUOTED([UDP_PORT], ["53"], [Define to the default udp port.])
>  AC_DEFINE_UNQUOTED([UDP_MAX_MESSAGE_LEN], [512], [Define to the default 
> maximum udp message length.])
>  AC_DEFINE_UNQUOTED([EDNS_MAX_MESSAGE_LEN], [4096], [Define to the default 
> maximum message length with EDNS.])
> +AC_DEFINE_UNQUOTED([TLS_PORT], ["853"], [Define to the default DNS over TLS 
> port.])
>  AC_DEFINE_UNQUOTED([MAXSYSLOGMSGLEN], [512], [Define to the maximum message 
> length to pass to syslog.])
>  AC_DEFINE_UNQUOTED([NSD_CONTROL_PORT], [8952], [Define to the default 
> nsd-control port.])
>  AC_DEFINE_UNQUOTED([NSD_CONTROL_VERSION], [1], [Define to nsd-control proto 
> version.])
> @@ -893,10 +911,29 @@ if test x$HAVE_SSL = x"yes"; then
>       fi
>       SSL_LIBS="-lssl"
>       AC_SUBST(SSL_LIBS)
> -     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 EVP_cleanup 
> ERR_load_crypto_strings OPENSSL_init_crypto])
> +     AC_CHECK_HEADERS([openssl/ssl.h openssl/err.h openssl/rand.h 
> openssl/ocsp.h],,, [AC_INCLUDES_DEFAULT])
> +     AC_CHECK_FUNCS([HMAC_CTX_reset HMAC_CTX_new EVP_cleanup 
> ERR_load_crypto_strings OPENSSL_init_crypto SSL_CTX_set_security_level])
> +     AC_CHECK_DECLS([SSL_CTX_set_ecdh_auto,SSL_CTX_set_tmp_ecdh], [], [], [
> +AC_INCLUDES_DEFAULT
> +#ifdef HAVE_OPENSSL_ERR_H
> +#include <openssl/err.h>
> +#endif
> +
> +#ifdef HAVE_OPENSSL_RAND_H
> +#include <openssl/rand.h>
> +#endif
> +
> +#ifdef HAVE_OPENSSL_CONF_H
> +#include <openssl/conf.h>
> +#endif
> +
> +#ifdef HAVE_OPENSSL_ENGINE_H
> +#include <openssl/engine.h>
> +#endif
> +#include <openssl/ssl.h>
> +#include <openssl/evp.h>
> +])
> +
>  
>       BAKLIBS="$LIBS"
>       LIBS="-lssl $LIBS"
> @@ -905,6 +942,7 @@ if test x$HAVE_SSL = x"yes"; then
>  
>  else
>       AC_MSG_WARN([No SSL, therefore remote-control is disabled])
> +     AC_MSG_WARN([No SSL, therefore TLS is disabled])
>  fi
>  
>  AC_ARG_ENABLE(nsec3, AC_HELP_STRING([--disable-nsec3], [Disable NSEC3 
> support]))
> @@ -987,6 +1025,18 @@ dt_DNSTAP([${localstatedir}/run/nsd-dnst
>  sinclude(systemd.m4)
>  # Include systemd.m4 - end
>  
> +AC_ARG_ENABLE(tcp-fastopen, AC_HELP_STRING([--enable-tcp-fastopen], [Enable 
> TCP Fast Open]))
> +case "$enable_tcp_fastopen" in
> +       yes)
> +             AC_CHECK_DECL([TCP_FASTOPEN], [], [AC_MSG_ERROR([TCP Fast Open 
> is not available: please rerun without --enable-tcp-fastopen])], 
> [AC_INCLUDES_DEFAULT
> +#include <netinet/tcp.h>
> +             ])
> +               AC_DEFINE_UNQUOTED([USE_TCP_FASTOPEN], [1], [Define this to 
> enable TCP fast open.])
> +               ;;
> +       no|*)
> +               ;;
> +esac
> +
>  AH_BOTTOM([
>  /* define before includes as it specifies what standard to use. */
>  #if (defined(HAVE_PSELECT) && !defined (HAVE_PSELECT_PROTO)) \
> @@ -1000,6 +1050,9 @@ AH_BOTTOM([
>  #  endif
>  #  ifndef _BSD_SOURCE
>  #    define _BSD_SOURCE 1
> +#  endif
> +#  ifndef _OPENBSD_SOURCE
> +#    define _OPENBSD_SOURCE 1
>  #  endif
>  #  ifndef _DEFAULT_SOURCE
>  #    define _DEFAULT_SOURCE 1
> Index: dns.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/dns.c,v
> retrieving revision 1.18
> diff -u -p -r1.18 dns.c
> --- dns.c     16 Aug 2018 17:56:18 -0000      1.18
> +++ dns.c     12 Sep 2019 11:25:03 -0000
> @@ -121,10 +121,10 @@ static rrtype_descriptor_type rrtype_des
>       { TYPE_SIG, "SIG", T_SIG, 9, 9,
>         { RDATA_WF_SHORT, RDATA_WF_BYTE, RDATA_WF_BYTE, RDATA_WF_LONG,
>           RDATA_WF_LONG, RDATA_WF_LONG, RDATA_WF_SHORT,
> -         RDATA_WF_UNCOMPRESSED_DNAME, RDATA_WF_BINARY },
> -       { RDATA_ZF_RRTYPE, RDATA_ZF_BYTE, RDATA_ZF_BYTE, RDATA_ZF_PERIOD,
> -         RDATA_ZF_TIME, RDATA_ZF_TIME, RDATA_ZF_SHORT, RDATA_ZF_DNAME,
> -         RDATA_ZF_BASE64 } },
> +         RDATA_WF_LITERAL_DNAME, RDATA_WF_BINARY },
> +       { RDATA_ZF_RRTYPE, RDATA_ZF_ALGORITHM, RDATA_ZF_BYTE, RDATA_ZF_PERIOD,
> +         RDATA_ZF_TIME, RDATA_ZF_TIME, RDATA_ZF_SHORT,
> +         RDATA_ZF_LITERAL_DNAME, RDATA_ZF_BASE64 } },
>       /* 25 */
>       { TYPE_KEY, "KEY", T_KEY, 4, 4,
>         { RDATA_WF_SHORT, RDATA_WF_BYTE, RDATA_WF_BYTE, RDATA_WF_BINARY },
> Index: ipc.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/ipc.c,v
> retrieving revision 1.6
> diff -u -p -r1.6 ipc.c
> --- ipc.c     10 Dec 2018 16:09:11 -0000      1.6
> +++ ipc.c     12 Sep 2019 11:25:03 -0000
> @@ -37,6 +37,7 @@ ipc_child_quit(struct nsd* nsd)
>  {
>       /* call shutdown and quit routines */
>       nsd->mode = NSD_QUIT;
> +     service_remaining_tcp(nsd);
>  #ifdef       BIND8_STATS
>       bind8_stats(nsd);
>  #endif /* BIND8_STATS */
> @@ -267,6 +268,8 @@ stats_add(struct nsdst* total, struct ns
>       total->qudp6 += s->qudp6;
>       total->ctcp += s->ctcp;
>       total->ctcp6 += s->ctcp6;
> +     total->ctls += s->ctls;
> +     total->ctls6 += s->ctls6;
>       for(i=0; i<sizeof(total->rcode)/sizeof(stc_type); i++)
>               total->rcode[i] += s->rcode[i];
>       for(i=0; i<sizeof(total->opcode)/sizeof(stc_type); i++)
> @@ -298,6 +301,8 @@ stats_subtract(struct nsdst* total, stru
>       total->qudp6 -= s->qudp6;
>       total->ctcp -= s->ctcp;
>       total->ctcp6 -= s->ctcp6;
> +     total->ctls -= s->ctls;
> +     total->ctls6 -= s->ctls6;
>       for(i=0; i<sizeof(total->rcode)/sizeof(stc_type); i++)
>               total->rcode[i] -= s->rcode[i];
>       for(i=0; i<sizeof(total->opcode)/sizeof(stc_type); i++)
> @@ -324,7 +329,8 @@ read_child_stats(struct nsd* nsd, struct
>                       "%d: %s", (int)child->pid, strerror(errno));
>       } else {
>               stats_add(&nsd->st, &s);
> -             child->query_count = s.qudp + s.qudp6 + s.ctcp + s.ctcp6;
> +             child->query_count = s.qudp + s.qudp6 + s.ctcp + s.ctcp6
> +                     + s.ctls + s.ctls6;
>               /* we know that the child is going to close the connection
>                * now (this is an ACK of the QUIT_W_STATS so we know the
>                * child is done, no longer sending e.g. NOTIFY contents) */
> @@ -593,6 +599,7 @@ ipc_xfrd_set_listening(struct xfrd_state
>       int fd = xfrd->ipc_handler.ev_fd;
>       struct event_base* base = xfrd->event_base;
>       event_del(&xfrd->ipc_handler);
> +     memset(&xfrd->ipc_handler, 0, sizeof(xfrd->ipc_handler));
>       event_set(&xfrd->ipc_handler, fd, mode, xfrd_handle_ipc, xfrd);
>       if(event_base_set(base, &xfrd->ipc_handler) != 0)
>               log_msg(LOG_ERR, "ipc: cannot set event_base");
> Index: mini_event.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/mini_event.c,v
> retrieving revision 1.2
> diff -u -p -r1.2 mini_event.c
> --- mini_event.c      17 Feb 2017 20:04:45 -0000      1.2
> +++ mini_event.c      12 Sep 2019 11:25:03 -0000
> @@ -304,8 +304,7 @@ event_base_free(struct event_base* base)
>  {
>       if(!base)
>               return;
> -     if(base->times)
> -             free(base->times);
> +     /* base->times is allocated in region and is freed with the region */
>       if(base->fds)
>               free(base->fds);
>       if(base->signals)
> @@ -362,7 +361,7 @@ event_add(struct event* ev, struct timev
>               struct timeval* now = ev->ev_base->time_tv;
>               ev->ev_timeout.tv_sec = tv->tv_sec + now->tv_sec;
>               ev->ev_timeout.tv_usec = tv->tv_usec + now->tv_usec;
> -             while(ev->ev_timeout.tv_usec > 1000000) {
> +             while(ev->ev_timeout.tv_usec >= 1000000) {
>                       ev->ev_timeout.tv_usec -= 1000000;
>                       ev->ev_timeout.tv_sec++;
>               }
> Index: nsd-checkconf.8.in
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/nsd-checkconf.8.in,v
> retrieving revision 1.25
> diff -u -p -r1.25 nsd-checkconf.8.in
> --- nsd-checkconf.8.in        30 Mar 2019 01:20:29 -0000      1.25
> +++ nsd-checkconf.8.in        12 Sep 2019 11:25:03 -0000
> @@ -1,4 +1,4 @@
> -.TH "nsd\-checkconf" "8" "Mar 25, 2019" "NLnet Labs" "nsd 4.1.27"
> +.TH "nsd\-checkconf" "8" "Aug 19, 2019" "NLnet Labs" "nsd 4.2.2"
>  .\" Copyright (c) 2001\-2008, NLnet Labs. All rights reserved.
>  .\" See LICENSE for the license.
>  .SH "NAME"
> Index: nsd-checkconf.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/nsd-checkconf.c,v
> retrieving revision 1.23
> diff -u -p -r1.23 nsd-checkconf.c
> --- nsd-checkconf.c   10 Dec 2018 16:09:11 -0000      1.23
> +++ nsd-checkconf.c   12 Sep 2019 11:25:03 -0000
> @@ -366,11 +366,13 @@ config_print_zone(nsd_options_type* opt,
>               SERV_GET_BIN(do_ip6, o);
>               SERV_GET_BIN(reuseport, o);
>               SERV_GET_BIN(hide_version, o);
> +             SERV_GET_BIN(hide_identity, o);
>               SERV_GET_BIN(zonefiles_check, o);
>               SERV_GET_BIN(log_time_ascii, o);
>               SERV_GET_BIN(round_robin, o);
>               SERV_GET_BIN(minimal_responses, o);
>               SERV_GET_BIN(refuse_any, o);
> +             SERV_GET_BIN(tcp_reject_overflow, o);
>               /* str */
>               SERV_GET_PATH(final, database, o);
>               SERV_GET_STR(identity, o);
> @@ -385,6 +387,10 @@ config_print_zone(nsd_options_type* opt,
>               SERV_GET_PATH(final, xfrdir, o);
>               SERV_GET_PATH(final, zonelistfile, o);
>               SERV_GET_STR(port, o);
> +             SERV_GET_STR(tls_service_key, o);
> +             SERV_GET_STR(tls_service_ocsp, o);
> +             SERV_GET_STR(tls_service_pem, o);
> +             SERV_GET_STR(tls_port, o);
>               /* int */
>               SERV_GET_INT(server_count, o);
>               SERV_GET_INT(tcp_count, o);
> @@ -397,6 +403,8 @@ config_print_zone(nsd_options_type* opt,
>               SERV_GET_INT(statistics, o);
>               SERV_GET_INT(xfrd_reload_timeout, o);
>               SERV_GET_INT(verbosity, o);
> +             SERV_GET_INT(send_buffer_size, o);
> +             SERV_GET_INT(receive_buffer_size, o);
>  #ifdef RATELIMIT
>               SERV_GET_INT(rrl_size, o);
>               SERV_GET_INT(rrl_ratelimit, o);
> @@ -493,7 +501,12 @@ config_test_print_server(nsd_options_typ
>       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");
> +     printf("\tsend-buffer-size: %d\n", opt->send_buffer_size);
> +     printf("\treceive-buffer-size: %d\n", opt->receive_buffer_size);
>       printf("\thide-version: %s\n", opt->hide_version?"yes":"no");
> +     printf("\thide-identity: %s\n", opt->hide_identity?"yes":"no");
> +     printf("\ttcp-reject-overflow: %s\n",
> +             opt->tcp_reject_overflow ? "yes" : "no");
>       print_string_var("database:", opt->database);
>       print_string_var("identity:", opt->identity);
>       print_string_var("version:", opt->version);
> @@ -536,6 +549,10 @@ config_test_print_server(nsd_options_typ
>  #endif
>       printf("\tzonefiles-check: %s\n", opt->zonefiles_check?"yes":"no");
>       printf("\tzonefiles-write: %d\n", opt->zonefiles_write);
> +     print_string_var("tls-service-key:", opt->tls_service_key);
> +     print_string_var("tls-service-pem:", opt->tls_service_pem);
> +     print_string_var("tls-service-ocsp:", opt->tls_service_ocsp);
> +     print_string_var("tls-port:", opt->tls_port);
>  
>  #ifdef USE_DNSTAP
>       printf("\ndnstap:\n");
> @@ -581,7 +598,6 @@ config_test_print_server(nsd_options_typ
>               print_string_var("name:", zone->name);
>               print_zone_content_elems(zone->pattern);
>       }
> -
>  }
>  
>  static int
> @@ -720,7 +736,7 @@ main(int argc, char* argv[])
>       log_init("nsd-checkconf");
>  
>       /* Parse the command line... */
> -     while ((c = getopt(argc, argv, "vfo:a:p:s:z:")) != -1) {
> +     while ((c = getopt(argc, argv, "vfho:a:p:s:z:")) != -1) {
>               switch (c) {
>               case 'v':
>                       verbose = 1;
> @@ -753,6 +769,7 @@ main(int argc, char* argv[])
>               case 'z':
>                       conf_zone = optarg;
>                       break;
> +             case 'h':
>               default:
>                       usage();
>               };
> Index: nsd-checkzone.8.in
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/nsd-checkzone.8.in,v
> retrieving revision 1.9
> diff -u -p -r1.9 nsd-checkzone.8.in
> --- nsd-checkzone.8.in        30 Mar 2019 01:20:29 -0000      1.9
> +++ nsd-checkzone.8.in        12 Sep 2019 11:25:03 -0000
> @@ -1,4 +1,4 @@
> -.TH "nsd\-checkzone" "8" "Mar 25, 2019" "NLnet Labs" "nsd 4.1.27"
> +.TH "nsd\-checkzone" "8" "Aug 19, 2019" "NLnet Labs" "nsd 4.2.2"
>  .\" Copyright (c) 2014, NLnet Labs. All rights reserved.
>  .\" See LICENSE for the license.
>  .SH "NAME"
> Index: nsd-checkzone.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/nsd-checkzone.c,v
> retrieving revision 1.3
> diff -u -p -r1.3 nsd-checkzone.c
> --- nsd-checkzone.c   29 Sep 2018 17:17:54 -0000      1.3
> +++ nsd-checkzone.c   12 Sep 2019 11:25:03 -0000
> @@ -61,6 +61,10 @@ check_zone(struct nsd* nsd, const char* 
>       errors = zonec_read(name, fname, zone);
>       if(errors > 0) {
>               printf("zone %s file %s has %u errors\n", name, fname, errors);
> +#ifdef MEMCLEAN /* otherwise, the OS collects memory pages */
> +             namedb_close(nsd->db);
> +             region_destroy(nsd->options->region);
> +#endif
>               exit(1);
>       }
>       printf("zone %s is ok\n", name);
> Index: nsd-control.8.in
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/nsd-control.8.in,v
> retrieving revision 1.13
> diff -u -p -r1.13 nsd-control.8.in
> --- nsd-control.8.in  30 Mar 2019 01:20:29 -0000      1.13
> +++ nsd-control.8.in  12 Sep 2019 11:25:03 -0000
> @@ -1,4 +1,4 @@
> -.TH "nsd\-control" "8" "Mar 25, 2019" "NLnet Labs" "nsd 4.1.27"
> +.TH "nsd\-control" "8" "Aug 19, 2019" "NLnet Labs" "nsd 4.2.2"
>  .\" Copyright (c) 2011, NLnet Labs. All rights reserved.
>  .\" See LICENSE for the license.
>  .SH "NAME"
> @@ -192,7 +192,7 @@ After running the script as root, turn o
>  The \fIstats\fR command shows a number of statistic counters.
>  .TP
>  .I num.queries
> -number of queries received (the tcp and udp queries added up).
> +number of queries received (the tls, tcp and udp queries added up).
>  .TP
>  .I serverX.queries
>  number of queries handled by the server process.  The number of
> @@ -252,6 +252,12 @@ number of connections over TCP ip4.
>  .TP
>  .I num.tcp6
>  number of connections over TCP ip6.
> +.TP
> +.I num.tls
> +number of connections over TLS ip4.  TLS queries are not part of num.tcp.
> +.TP
> +.I num.tls6
> +number of connections over TLS ip6.  TLS queries are not part of num.tcp6.
>  .TP
>  .I num.answer_wo_aa
>  number of answers with NOERROR rcode and without AA flag, this includes the 
> referrals.
> Index: nsd-control.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/nsd-control.c,v
> retrieving revision 1.8
> diff -u -p -r1.8 nsd-control.c
> --- nsd-control.c     30 Mar 2019 01:20:29 -0000      1.8
> +++ nsd-control.c     12 Sep 2019 11:25:03 -0000
> @@ -42,8 +42,8 @@
>   */
>  
>  #include "config.h"
> +#include <stdio.h>
>  #ifdef HAVE_SSL
> -
>  #include <sys/types.h>
>  #include <unistd.h>
>  #include <string.h>
> @@ -163,6 +163,12 @@ setup_ctx(struct nsd_options* cfg)
>          if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
>               != SSL_OP_NO_SSLv3)
>               ssl_err("could not set SSL_OP_NO_SSLv3");
> +#if defined(SSL_OP_NO_RENEGOTIATION)
> +     /* disable client renegotiation */
> +     if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) &
> +             SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION)
> +             ssl_err("could not set SSL_OP_NO_RENEGOTIATION");
> +#endif
>       if(!SSL_CTX_use_certificate_file(ctx,c_cert,SSL_FILETYPE_PEM))
>               ssl_path_err("Error setting up SSL_CTX client cert", c_cert);
>       if(!SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM))
> Index: nsd.8.in
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/nsd.8.in,v
> retrieving revision 1.26
> diff -u -p -r1.26 nsd.8.in
> --- nsd.8.in  30 Mar 2019 01:20:29 -0000      1.26
> +++ nsd.8.in  12 Sep 2019 11:25:03 -0000
> @@ -1,9 +1,9 @@
> -.TH "NSD" "8" "Mar 25, 2019" "NLnet Labs" "NSD 4.1.27"
> +.TH "NSD" "8" "Aug 19, 2019" "NLnet Labs" "NSD 4.2.2"
>  .\" 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.27.
> +\- Name Server Daemon (NSD) version 4.2.2.
>  .SH "SYNOPSIS"
>  .B nsd
>  .RB [ \-4 ] 
> Index: nsd.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/nsd.c,v
> retrieving revision 1.33
> diff -u -p -r1.33 nsd.c
> --- nsd.c     30 Mar 2019 01:20:29 -0000      1.33
> +++ nsd.c     12 Sep 2019 11:25:03 -0000
> @@ -661,6 +661,9 @@ main(int argc, char *argv[])
>       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;
> +#ifdef HAVE_SSL
> +     nsd.tls_ctx = NULL;
> +#endif
>  
>       if(udp_port == 0)
>       {
> @@ -942,10 +945,19 @@ main(int argc, char *argv[])
>                       "not be started", argv0);
>       }
>  #if defined(HAVE_SSL)
> +     if(nsd.options->control_enable || (nsd.options->tls_service_key && 
> nsd.options->tls_service_key[0])) {
> +             perform_openssl_init();
> +     }
>       if(nsd.options->control_enable) {
>               /* read ssl keys while superuser and outside chroot */
>               if(!(nsd.rc = daemon_remote_create(nsd.options)))
>                       error("could not perform remote control setup");
> +     }
> +     if(nsd.options->tls_service_key && nsd.options->tls_service_key[0]
> +        && nsd.options->tls_service_pem && nsd.options->tls_service_pem[0]) {
> +             if(!(nsd.tls_ctx = server_tls_ctx_create(&nsd, NULL,
> +                     nsd.options->tls_service_ocsp)))
> +                     error("could not set up tls SSL_CTX");
>       }
>  #endif /* HAVE_SSL */
>  
> Index: nsd.conf.5.in
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/nsd.conf.5.in,v
> retrieving revision 1.31
> diff -u -p -r1.31 nsd.conf.5.in
> --- nsd.conf.5.in     30 Mar 2019 01:20:29 -0000      1.31
> +++ nsd.conf.5.in     12 Sep 2019 11:25:03 -0000
> @@ -1,4 +1,4 @@
> -.TH "nsd.conf" "5" "Mar 25, 2019" "NLnet Labs" "nsd 4.1.27"
> +.TH "nsd.conf" "5" "Aug 19, 2019" "NLnet Labs" "nsd 4.2.2"
>  .\" Copyright (c) 2001\-2008, NLnet Labs. All rights reserved.
>  .\" See LICENSE for the license.
>  .SH "NAME"
> @@ -149,7 +149,7 @@ clause. There may only be one 
>  clause.
>  .TP
>  .B ip\-address:\fR <ip4 or ip6>[@port]
> -NSD will bind to the listed ip\-address. Can be give multiple times 
> +NSD will bind to the listed ip\-address. Can be given multiple times 
>  to bind multiple ip\-addresses. Optionally, a port number can be given.
>  If none are given NSD listens to the wildcard interface. Same as commandline 
> option 
>  .BR \-a.
> @@ -181,6 +181,12 @@ than 1 (such as, equal to the number of 
>  It works on Linux, but does not work on FreeBSD, and likely does not
>  work on other systems.
>  .TP
> +.B send\-buffer\-size:\fR <number>
> +Set the send buffer size for query-servicing sockets.  Set to 0 to use the 
> default settings.
> +.TP
> +.B receive\-buffer\-size:\fR <number>
> +Set the receive buffer size for query-servicing sockets.  Set to 0 to use 
> the default settings.
> +.TP
>  .B debug\-mode:\fR <yes or no>
>  Turns on debugging mode for nsd, does not fork a daemon process. 
>  Default is no. Same as commandline option
> @@ -217,6 +223,7 @@ Returns the specified identity when aske
>  Default is the name as returned by gethostname(3). Same as 
>  commandline option 
>  .BR \-i .
> +See hide\-identity to set the server to not respond to such queries.
>  .TP
>  .B version:\fR <string>
>  Returns the specified version string when asked for CH TXT version.server,
> @@ -244,6 +251,10 @@ The maximum number of concurrent, active
>  Default is 100. Same as commandline option
>  .BR \-n .
>  .TP
> +.B tcp\-reject\-overflow:\fR <yes or no>
> +If set to yes, TCP connections made beyond the maximum set by tcp-count will
> +be dropped immediately (accepted and closed).  Default is no.
> +.TP
>  .B tcp\-query\-count:\fR <number>
>  The maximum number of queries served on a single TCP connection.
>  Default is 0, meaning there is no maximum.
> @@ -359,6 +370,10 @@ And notify refusal, and axfr request ref
>  Prevent NSD from replying with the version string on CHAOS class 
>  queries.  Default is no.
>  .TP
> +.B hide\-identity:\fR <yes or no>
> +Prevent NSD from replying with the identity string on CHAOS class 
> +queries.  Default is no.
> +.TP
>  .B log\-time\-ascii:\fR <yes or no>
>  Log time in ascii, if "no" then in seconds epoch.  Default is yes.
>  This chooses the format when logging to file.  The printout via syslog
> @@ -436,6 +451,38 @@ whitelisted. Default @ratelimit_default@
>  specific queries to receive this qps limit instead of the normal limit.
>  With the value 0 the rate is unlimited.
>  .\" rrlend
> +.TP
> +.B tls\-service\-key:\fR <filename>
> +If enabled, the server provides TLS service on TCP sockets with the TLS
> +service port number.  The port number (853) is configured with tls\-port.
> +To turn it on, create an interface: option line in config with @port
> +appended to the IP-address.  This creates the extra socket on which the
> +DNS over TLS service is provided.
> +.IP
> +The file is the private key for the TLS session. The public certificate is
> +in the tls-service-pem file. Default is "", turned off. Requires a
> +restart (a reload is not enough) if changed, because the private key is
> +read while root permissions are held and before chroot (if any).
> +.TP
> +.B tls\-service\-pem:\fR <filename>
> +The public key certificate pem file for the tls service. Default is "", 
> turned off.
> +.TP
> +.B tls\-service\-ocsp:\fR <filename>
> +The ocsp pem file for the tls service, for OCSP stapling.  Default is "",
> +turned off.  An external process prepares and updates the OCSP stapling data.
> +Like this,
> +.RS 9
> +openssl ocsp -no_nonce \\
> +   -respout /path/to/ocsp.pem \\
> +   -CAfile /path/to/ca_and_any_intermediate.pem \\
> +   -issuer /path/to/direct_issuer.pem \\
> +   -cert /path/to/cert.pem \\
> +   -url "$( openssl x509 -noout -text -in /path/to/cert.pem | grep 'OCSP - 
> URI:' | cut -d: -f2,3 )"
> +.RE
> +.TP
> +.B tls\-port:\fR <number>
> +The port number on which to provide TCP TLS service, default is 853, only
> +interfaces configured with that port number as @number get DNS over TLS 
> service.
>  .SS "Remote Control"
>  The
>  .B remote\-control:
> Index: nsd.conf.sample.in
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/nsd.conf.sample.in,v
> retrieving revision 1.10
> diff -u -p -r1.10 nsd.conf.sample.in
> --- nsd.conf.sample.in        10 Dec 2018 16:09:11 -0000      1.10
> +++ nsd.conf.sample.in        12 Sep 2019 11:25:03 -0000
> @@ -33,6 +33,14 @@ server:
>       # use the reuseport socket option for performance. Default no.
>       # reuseport: no
>  
> +     # override maximum socket send buffer size.  Default of 0 results in
> +     # send buffer size being set to 1048576 (bytes).
> +     # send-buffer-size: 1048576
> +
> +     # override maximum socket receive buffer size. Default of 0 results in
> +     # receive buffer size being set to 1048576 (bytes).
> +     # receive-buffer-size: 1048576
> +
>       # enable debug mode, does not fork daemon process into the background.
>       # debug-mode: no
>  
> @@ -85,6 +93,9 @@ server:
>       # don't answer VERSION.BIND and VERSION.SERVER CHAOS class queries
>       # hide-version: no
>  
> +     # don't answer HOSTNAME.BIND and ID.SERVER CHAOS class queries
> +     # hide-identity: no
> +
>       # version string the server responds with for chaos queries.
>       # default is 'NSD x.y.z' with the server's version number.
>       # version: "NSD"
> @@ -98,6 +109,11 @@ server:
>       # Maximum number of concurrent TCP connections per server.
>       # tcp-count: 100
>  
> +     # Accept (and immediately close) TCP connections after maximum number
> +     # of connections is reached to prevent kernel connection queue from
> +     # growing.
> +     # tcp-reject-overflow: no
> +
>       # Maximum number of queries served on a single TCP connection.
>       # By default 0, which means no maximum.
>       # tcp-query-count: 0
> @@ -188,6 +204,14 @@ server:
>       # dnstap-version: ""
>       # dnstap-log-auth-query-messages: no
>       # dnstap-log-auth-response-messages: no
> +
> +     # Service clients over TLS (on the TCP sockets), with plain DNS inside
> +     # the TLS stream. Give the certificate to use and private key.
> +     # Default is "" (disabled). Requires restart to take effect.
> +     # tls-service-key: "path/to/privatekeyfile.key"
> +     # tls-service-pem: "path/to/publiccertfile.pem"
> +     # tls-service-ocsp: "path/to/ocsp.pem"
> +     # tls-port: 853
>  
>  # Remote control config section. 
>  remote-control:
> Index: nsd.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/nsd.h,v
> retrieving revision 1.6
> diff -u -p -r1.6 nsd.h
> --- nsd.h     10 Dec 2018 16:09:11 -0000      1.6
> +++ nsd.h     12 Sep 2019 11:25:03 -0000
> @@ -11,6 +11,9 @@
>  #define      _NSD_H_
>  
>  #include <signal.h>
> +#ifdef HAVE_OPENSSL_SSL_H
> +#include <openssl/ssl.h>
> +#endif
>  
>  #include "dns.h"
>  #include "edns.h"
> @@ -244,6 +247,7 @@ struct    nsd
>               stc_type qclass[4];     /* Class IN or Class CH or other */
>               stc_type qudp, qudp6;   /* Number of queries udp and udp6 */
>               stc_type ctcp, ctcp6;   /* Number of tcp and tcp6 connections */
> +             stc_type ctls, ctls6;   /* Number of tls and tls6 connections */
>               stc_type rcode[17], opcode[6]; /* Rcodes & opcodes */
>               /* Dropped, truncated, queries for nonconfigured zone, tx 
> errors */
>               stc_type dropped, truncated, wrongzone, txerr, rxerr;
> @@ -276,6 +280,11 @@ struct   nsd
>       unsigned int err_limit_count;
>  
>       struct nsd_options* options;
> +
> +#ifdef HAVE_SSL
> +     /* TLS specific configuration */
> +     SSL_CTX *tls_ctx;
> +#endif
>  };
>  
>  extern struct nsd nsd;
> @@ -295,6 +304,7 @@ void server_child(struct nsd *nsd);
>  void server_shutdown(struct nsd *nsd) ATTR_NORETURN;
>  void server_close_all_sockets(struct nsd_socket sockets[], size_t n);
>  struct event_base* nsd_child_event_base(void);
> +void service_remaining_tcp(struct nsd* nsd);
>  /* extra domain numbers for temporary domains */
>  #define EXTRA_DOMAIN_NUMBERS 1024
>  #define SLOW_ACCEPT_TIMEOUT 2 /* in seconds */
> @@ -311,6 +321,11 @@ void server_prepare_xfrd(struct nsd *nsd
>  void server_start_xfrd(struct nsd *nsd, int del_db, int reload_active);
>  /* send SOA serial numbers to xfrd */
>  void server_send_soa_xfrd(struct nsd *nsd, int shortsoa);
> +#ifdef HAVE_SSL
> +SSL_CTX* server_tls_ctx_setup(char* key, char* pem, char* verifypem);
> +SSL_CTX* server_tls_ctx_create(struct nsd *nsd, char* verifypem, char* 
> ocspfile);
> +void perform_openssl_init(void);
> +#endif
>  ssize_t block_read(struct nsd* nsd, int s, void* p, ssize_t sz, int timeout);
>  
>  #endif       /* _NSD_H_ */
> Index: options.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/options.c,v
> retrieving revision 1.15
> diff -u -p -r1.15 options.c
> --- options.c 10 Dec 2018 16:09:11 -0000      1.15
> +++ options.c 12 Sep 2019 11:25:03 -0000
> @@ -52,9 +52,12 @@ nsd_options_create(region_type* region)
>       opt->ip_addresses = NULL;
>       opt->ip_transparent = 0;
>       opt->ip_freebind = 0;
> +     opt->send_buffer_size = 0;
> +     opt->receive_buffer_size = 0;
>       opt->debug_mode = 0;
>       opt->verbosity = 0;
>       opt->hide_version = 0;
> +     opt->hide_identity = 0;
>       opt->do_ip4 = 1;
>       opt->do_ip6 = 1;
>       opt->database = DBFILE;
> @@ -68,6 +71,7 @@ nsd_options_create(region_type* region)
>       opt->refuse_any = 1;
>       opt->server_count = 1;
>       opt->tcp_count = 100;
> +     opt->tcp_reject_overflow = 0;
>       opt->tcp_query_count = 0;
>       opt->tcp_timeout = TCP_TIMEOUT;
>       opt->tcp_mss = 0;
> @@ -113,6 +117,10 @@ nsd_options_create(region_type* region)
>               opt->zonefiles_write = ZONEFILES_WRITE_INTERVAL;
>       else    opt->zonefiles_write = 0;
>       opt->xfrd_reload_timeout = 1;
> +     opt->tls_service_key = NULL;
> +     opt->tls_service_ocsp = NULL;
> +     opt->tls_service_pem = NULL;
> +     opt->tls_port = TLS_PORT;
>       opt->control_enable = 0;
>       opt->control_interface = NULL;
>       opt->control_port = NSD_CONTROL_PORT;
> Index: options.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/options.h,v
> retrieving revision 1.14
> diff -u -p -r1.14 options.h
> --- options.h 30 Mar 2019 01:20:29 -0000      1.14
> +++ options.h 12 Sep 2019 11:25:03 -0000
> @@ -61,9 +61,12 @@ struct nsd_options {
>  
>       int ip_transparent;
>       int ip_freebind;
> +     int send_buffer_size;
> +     int receive_buffer_size;
>       int debug_mode;
>       int verbosity;
>       int hide_version;
> +     int hide_identity;
>       int do_ip4;
>       int do_ip6;
>       const char* database;
> @@ -72,6 +75,7 @@ struct nsd_options {
>       const char* logfile;
>       int server_count;
>       int tcp_count;
> +     int tcp_reject_overflow;
>       int tcp_query_count;
>       int tcp_timeout;
>       int tcp_mss;
> @@ -96,6 +100,15 @@ struct nsd_options {
>       int minimal_responses;
>       int refuse_any;
>       int reuseport;
> +
> +     /* private key file for TLS */
> +     char* tls_service_key;
> +     /* ocsp stapling file for TLS */
> +     char* tls_service_ocsp;
> +     /* certificate file for TLS */
> +     char* tls_service_pem;
> +     /* TLS dedicated port */
> +     const char* tls_port;
>  
>          /** remote control section. enable toggle. */
>       int control_enable;
> Index: query.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/query.c,v
> retrieving revision 1.31
> diff -u -p -r1.31 query.c
> --- query.c   30 Mar 2019 01:22:12 -0000      1.31
> +++ query.c   12 Sep 2019 11:25:03 -0000
> @@ -530,13 +530,17 @@ answer_chaos(struct nsd *nsd, query_type
>                   (q->qname->name_size ==  15
>                    && memcmp(dname_name(q->qname), "\010hostname\004bind", 
> 15) == 0))
>               {
> -                     /* Add ID */
> -                     query_addtxt(q,
> +                     if(!nsd->options->hide_identity) {
> +                             /* Add ID */
> +                             query_addtxt(q,
>                                    buffer_begin(q->packet) + QHEADERSZ,
>                                    CLASS_CH,
>                                    0,
>                                    nsd->identity);
> -                     ANCOUNT_SET(q->packet, ANCOUNT(q->packet) + 1);
> +                             ANCOUNT_SET(q->packet, ANCOUNT(q->packet) + 1);
> +                     } else {
> +                             RCODE_SET(q->packet, RCODE_REFUSE);
> +                     }
>               } else if ((q->qname->name_size == 16
>                           && memcmp(dname_name(q->qname), 
> "\007version\006server", 16) == 0) ||
>                          (q->qname->name_size == 14
> Index: remote.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/remote.c,v
> retrieving revision 1.17
> diff -u -p -r1.17 remote.c
> --- remote.c  30 Mar 2019 01:20:29 -0000      1.17
> +++ remote.c  12 Sep 2019 11:25:03 -0000
> @@ -252,48 +252,13 @@ timeval_subtract(struct timeval* d, cons
>  static int
>  remote_setup_ctx(struct daemon_remote* rc, struct nsd_options* cfg)
>  {
> -     char* s_cert;
> -     char* s_key;
> -     rc->ctx = SSL_CTX_new(SSLv23_server_method());
> +     char* s_cert = cfg->server_cert_file;
> +     char* s_key = cfg->server_key_file;
> +     rc->ctx = server_tls_ctx_setup(s_key, s_cert, s_cert);
>       if(!rc->ctx) {
> -             log_crypto_err("could not SSL_CTX_new");
> +             log_msg(LOG_ERR, "could not setup remote control TLS context");
>               return 0;
>       }
> -     /* no SSLv2, SSLv3 because has defects */
> -     if((SSL_CTX_set_options(rc->ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
> -             != SSL_OP_NO_SSLv2){
> -             log_crypto_err("could not set SSL_OP_NO_SSLv2");
> -             return 0;
> -     }
> -     if((SSL_CTX_set_options(rc->ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
> -             != SSL_OP_NO_SSLv3){
> -             log_crypto_err("could not set SSL_OP_NO_SSLv3");
> -             return 0;
> -     }
> -     s_cert = cfg->server_cert_file;
> -     s_key = cfg->server_key_file;
> -     VERBOSITY(2, (LOG_INFO, "setup SSL certificates"));
> -     if (!SSL_CTX_use_certificate_file(rc->ctx,s_cert,SSL_FILETYPE_PEM)) {
> -             log_msg(LOG_ERR, "Error for server-cert-file: %s", s_cert);
> -             log_crypto_err("Error in SSL_CTX use_certificate_file");
> -             return 0;
> -     }
> -     if(!SSL_CTX_use_PrivateKey_file(rc->ctx,s_key,SSL_FILETYPE_PEM)) {
> -             log_msg(LOG_ERR, "Error for server-key-file: %s", s_key);
> -             log_crypto_err("Error in SSL_CTX use_PrivateKey_file");
> -             return 0;
> -     }
> -     if(!SSL_CTX_check_private_key(rc->ctx)) {
> -             log_msg(LOG_ERR, "Error for server-key-file: %s", s_key);
> -             log_crypto_err("Error in SSL_CTX check_private_key");
> -             return 0;
> -     }
> -     if(!SSL_CTX_load_verify_locations(rc->ctx, s_cert, NULL)) {
> -             log_crypto_err("Error setting up SSL_CTX verify locations");
> -             return 0;
> -     }
> -     SSL_CTX_set_client_CA_list(rc->ctx, SSL_load_client_CA_file(s_cert));
> -     SSL_CTX_set_verify(rc->ctx, SSL_VERIFY_PEER, NULL);
>       return 1;
>  }
>  
> @@ -305,38 +270,6 @@ daemon_remote_create(struct nsd_options*
>       rc->max_active = 10;
>       assert(cfg->control_enable);
>  
> -     /* init SSL library */
> -#ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
> -     ERR_load_crypto_strings();
> -#endif
> -     ERR_load_SSL_strings();
> -#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
> -     OpenSSL_add_all_algorithms();
> -#else
> -     OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
> -             | OPENSSL_INIT_ADD_ALL_DIGESTS
> -             | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
> -#endif
> -#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
> -     (void)SSL_library_init();
> -#else
> -     OPENSSL_init_ssl(0, NULL);
> -#endif
> -
> -     if(!RAND_status()) {
> -             /* try to seed it */
> -             unsigned char buf[256];
> -             unsigned int v, seed=(unsigned)time(NULL) ^ (unsigned)getpid();
> -             size_t i;
> -             v = seed;
> -             for(i=0; i<256/sizeof(v); i++) {
> -                     memmove(buf+i*sizeof(v), &v, sizeof(v));
> -                     v = v*seed + (unsigned int)i;
> -             }
> -             RAND_seed(buf, 256);
> -             log_msg(LOG_WARNING, "warning: no entropy, seeding openssl PRNG 
> with time");
> -     }
> -
>       if(options_remote_is_address(cfg)) {
>               if(!remote_setup_ctx(rc, cfg)) {
>                       daemon_remote_delete(rc);
> @@ -593,6 +526,7 @@ daemon_remote_attach(struct daemon_remot
>       for(p = rc->accept_list; p; p = p->next) {
>               /* add event */
>               fd = p->c.ev_fd;
> +             memset(&p->c, 0, sizeof(p->c));
>               event_set(&p->c, fd, EV_PERSIST|EV_READ, remote_accept_callback,
>                       p);
>               if(event_base_set(xfrd->event_base, &p->c) != 0)
> @@ -670,6 +604,7 @@ remote_accept_callback(int fd, short eve
>       n->tval.tv_usec = 0L;
>       n->fd = newfd;
>  
> +     memset(&n->c, 0, sizeof(n->c));
>       event_set(&n->c, newfd, EV_PERSIST|EV_TIMEOUT|EV_READ,
>               remote_control_callback, n);
>       if(event_base_set(xfrd->event_base, &n->c) != 0) {
> @@ -2372,6 +2307,7 @@ remote_handshake_later(struct daemon_rem
>               }
>               s->shake_state = rc_hs_read;
>               event_del(&s->c);
> +             memset(&s->c, 0, sizeof(s->c));
>               event_set(&s->c, fd, EV_PERSIST|EV_TIMEOUT|EV_READ,
>                       remote_control_callback, s);
>               if(event_base_set(xfrd->event_base, &s->c) != 0)
> @@ -2386,6 +2322,7 @@ remote_handshake_later(struct daemon_rem
>               }
>               s->shake_state = rc_hs_write;
>               event_del(&s->c);
> +             memset(&s->c, 0, sizeof(s->c));
>               event_set(&s->c, fd, EV_PERSIST|EV_TIMEOUT|EV_WRITE,
>                       remote_control_callback, s);
>               if(event_base_set(xfrd->event_base, &s->c) != 0)
> @@ -2553,6 +2490,12 @@ print_stat_block(RES* ssl, char* n, char
>       /* ctcp6 */
>       if(!ssl_printf(ssl, "%s%snum.tcp6=%lu\n", n, d, (unsigned 
> long)st->ctcp6))
>               return;
> +     /* ctls */
> +     if(!ssl_printf(ssl, "%s%snum.tls=%lu\n", n, d, (unsigned long)st->ctls))
> +             return;
> +     /* ctls6 */
> +     if(!ssl_printf(ssl, "%s%snum.tls6=%lu\n", n, d, (unsigned 
> long)st->ctls6))
> +             return;
>  
>       /* nona */
>       if(!ssl_printf(ssl, "%s%snum.answer_wo_aa=%lu\n", n, d,
> @@ -2640,7 +2583,7 @@ zonestat_print(RES* ssl, xfrd_state_type
>               /* stat0 contains the details that we want to print */
>               if(!ssl_printf(ssl, "%s%snum.queries=%lu\n", name, ".",
>                       (unsigned long)(stat0.qudp + stat0.qudp6 + stat0.ctcp +
> -                             stat0.ctcp6)))
> +                             stat0.ctcp6 + stat0.ctls + stat0.ctls6)))
>                       return;
>               print_stat_block(ssl, name, ".", &stat0);
>       }
> Index: server.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/server.c,v
> retrieving revision 1.35
> diff -u -p -r1.35 server.c
> --- server.c  30 Mar 2019 01:20:29 -0000      1.35
> +++ server.c  12 Sep 2019 11:25:03 -0000
> @@ -16,6 +16,9 @@
>  #include <sys/wait.h>
>  
>  #include <netinet/in.h>
> +#ifdef USE_TCP_FASTOPEN
> +  #include <netinet/tcp.h>
> +#endif
>  #include <arpa/inet.h>
>  
>  #include <assert.h>
> @@ -40,6 +43,15 @@
>  #ifdef HAVE_OPENSSL_RAND_H
>  #include <openssl/rand.h>
>  #endif
> +#ifdef HAVE_OPENSSL_SSL_H
> +#include <openssl/ssl.h>
> +#endif
> +#ifdef HAVE_OPENSSL_ERR_H
> +#include <openssl/err.h>
> +#endif
> +#ifdef HAVE_OPENSSL_OCSP_H
> +#include <openssl/ocsp.h>
> +#endif
>  #ifndef USE_MINI_EVENT
>  #  ifdef HAVE_EVENT_H
>  #    include <event.h>
> @@ -71,6 +83,11 @@
>  
>  #define RELOAD_SYNC_TIMEOUT 25 /* seconds */
>  
> +#ifdef USE_TCP_FASTOPEN
> +  #define TCP_FASTOPEN_FILE "/proc/sys/net/ipv4/tcp_fastopen"
> +  #define TCP_FASTOPEN_SERVER_BIT_MASK 0x2
> +#endif
> +
>  /*
>   * Data for the UDP handlers.
>   */
> @@ -86,6 +103,10 @@ struct tcp_accept_handler_data {
>       struct nsd_socket  *socket;
>       int event_added;
>       struct event       event;
> +#ifdef HAVE_SSL
> +     /* handler accepts TLS connections on the dedicated port */
> +     int tls_accept;
> +#endif
>  };
>  
>  /*
> @@ -99,6 +120,11 @@ static struct tcp_accept_handler_data*    t
>  static struct event slowaccept_event;
>  static int slowaccept;
>  
> +#ifdef HAVE_SSL
> +static unsigned char *ocspdata = NULL;
> +static long ocspdata_len = 0;
> +#endif
> +
>  #ifndef NONBLOCKING_IS_BROKEN
>  #  define NUM_RECV_PER_SELECT 100
>  #endif
> @@ -170,7 +196,23 @@ struct tcp_handler_data
>        * The timeout in msec for this tcp connection
>        */
>       int     tcp_timeout;
> +#ifdef HAVE_SSL
> +     /*
> +      * TLS object.
> +      */
> +     SSL* tls;
> +
> +     /*
> +      * TLS handshake state.
> +      */
> +     enum { tls_hs_none, tls_hs_read, tls_hs_write,
> +             tls_hs_read_event, tls_hs_write_event } shake_state;
> +#endif
> +     /* list of connections, for service of remaining tcp channels */
> +     struct tcp_handler_data *prev, *next;
>  };
> +/* global that is the list of active tcp channels */
> +static struct tcp_handler_data *tcp_active_list = NULL;
>  
>  /*
>   * Handle incoming queries on the UDP server sockets.
> @@ -202,6 +244,29 @@ static void handle_tcp_reading(int fd, s
>   */
>  static void handle_tcp_writing(int fd, short event, void* arg);
>  
> +#ifdef HAVE_SSL
> +/* Create SSL object and associate fd */
> +static SSL* incoming_ssl_fd(SSL_CTX* ctx, int fd);
> +/*
> + * Handle TLS handshake. May be called multiple times if incomplete.
> + */
> +static int tls_handshake(struct tcp_handler_data* data, int fd, int writing);
> +
> +/*
> + * Handle incoming queries on a TLS over TCP connection.  The TLS
> + * connections are configured to be non-blocking and the handler may
> + * be called multiple times before a complete query is received.
> + */
> +static void handle_tls_reading(int fd, short event, void* arg);
> +
> +/*
> + * Handle outgoing responses on a TLS over TCP connection.  The TLS
> + * connections are configured to be non-blocking and the handler may
> + * be called multiple times before a complete response is sent.
> + */
> +static void handle_tls_writing(int fd, short event, void* arg);
> +#endif
> +
>  /*
>   * Send all children the quit nonblocking, then close pipe.
>   */
> @@ -224,6 +289,34 @@ static uint32_t compression_table_capaci
>  static uint32_t compression_table_size = 0;
>  static domain_type* compressed_dnames[MAXRRSPP];
>  
> +#ifdef USE_TCP_FASTOPEN
> +/* Checks to see if the kernel value must be manually changed in order for
> +   TCP Fast Open to support server mode */
> +static void report_tcp_fastopen_config() {
> +
> +     int tcp_fastopen_fp;
> +     uint8_t tcp_fastopen_value;
> +
> +     if ( (tcp_fastopen_fp = open(TCP_FASTOPEN_FILE, O_RDONLY)) == -1 ) {
> +             log_msg(LOG_INFO,"Error opening " TCP_FASTOPEN_FILE ": %s\n", 
> strerror(errno));
> +     }
> +     if (read(tcp_fastopen_fp, &tcp_fastopen_value, 1) == -1 ) {
> +             log_msg(LOG_INFO,"Error reading " TCP_FASTOPEN_FILE ": %s\n", 
> strerror(errno));
> +             close(tcp_fastopen_fp);
> +     }
> +     if (!(tcp_fastopen_value & TCP_FASTOPEN_SERVER_BIT_MASK)) {
> +             log_msg(LOG_WARNING, "Error: TCP Fast Open support is available 
> and configured in NSD by default.\n");
> +             log_msg(LOG_WARNING, "However the kernel paramenters are not 
> configured to support TCP_FASTOPEN in server mode.\n");
> +             log_msg(LOG_WARNING, "To enable TFO use the command:");
> +             log_msg(LOG_WARNING, "  'sudo sysctl -w 
> net.ipv4.tcp_fastopen=2' for pure server mode or\n");
> +             log_msg(LOG_WARNING, "  'sudo sysctl -w 
> net.ipv4.tcp_fastopen=3' for both client and server mode\n");
> +             log_msg(LOG_WARNING, "NSD will not have TCP Fast Open available 
> until this change is made.\n");
> +             close(tcp_fastopen_fp);
> +     }
> +     close(tcp_fastopen_fp);
> +}
> +#endif
> +
>  /*
>   * Remove the specified pid from the list of child pids.  Returns -1 if
>   * the pid is not in the list, child_num otherwise.  The field is set to 0.
> @@ -577,6 +670,9 @@ server_init_ifs(struct nsd *nsd, size_t 
>  #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) || defined(SO_BINDANY))
>       int on = 1;
>  #endif
> +#ifdef USE_TCP_FASTOPEN
> +     int qlen;
> +#endif
>  
>       /* UDP */
>  
> @@ -638,60 +734,62 @@ server_init_ifs(struct nsd *nsd, size_t 
>  #else
>               (void)reuseport_works;
>  #endif /* SO_REUSEPORT */
> -#if defined(SO_RCVBUF) || defined(SO_SNDBUF)
> -     if(1) {
> -     int rcv = 1*1024*1024;
> -     int snd = 1*1024*1024;
> -
> -#ifdef SO_RCVBUF
> +#if defined(SO_RCVBUF)
> +     {
> +             int rcv = 1*1024*1024;
> +             if (nsd->options->receive_buffer_size > 0) {
> +                     rcv = nsd->options->receive_buffer_size;
> +             }
>  #  ifdef SO_RCVBUFFORCE
> -     if(setsockopt(nsd->udp[i].s, SOL_SOCKET, SO_RCVBUFFORCE, (void*)&rcv,
> -             (socklen_t)sizeof(rcv)) < 0) {
> -             if(errno != EPERM && errno != ENOBUFS) {
> -                     log_msg(LOG_ERR, "setsockopt(..., SO_RCVBUFFORCE, "
> +             if(setsockopt(nsd->udp[i].s, SOL_SOCKET, SO_RCVBUFFORCE, 
> (void*)&rcv,
> +                     (socklen_t)sizeof(rcv)) < 0) {
> +                     if(errno != EPERM && errno != ENOBUFS) {
> +                             log_msg(LOG_ERR, "setsockopt(..., 
> SO_RCVBUFFORCE, "
>                                          "...) failed: %s", strerror(errno));
> -                     return -1;
> -             } 
> +                             return -1;
> +                     }
> +             }
>  #  else
> -     if(1) {
> -#  endif /* SO_RCVBUFFORCE */
>               if(setsockopt(nsd->udp[i].s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv,
> -                      (socklen_t)sizeof(rcv)) < 0) {
> +                     (socklen_t)sizeof(rcv)) < 0) {
>                       if(errno != ENOBUFS && errno != ENOSYS) {
>                               log_msg(LOG_ERR, "setsockopt(..., SO_RCVBUF, "
>                                          "...) failed: %s", strerror(errno));
>                               return -1;
>                       }
>               }
> +#  endif /* SO_RCVBUFFORCE */
>       }
>  #endif /* SO_RCVBUF */
>  
>  #ifdef SO_SNDBUF
> +     {
> +             int snd = 1*1024*1024;
> +             if (nsd->options->send_buffer_size > 0) {
> +                     snd = nsd->options->send_buffer_size;
> +             }
>  #  ifdef SO_SNDBUFFORCE
> -     if(setsockopt(nsd->udp[i].s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd,
> -             (socklen_t)sizeof(snd)) < 0) {
> -             if(errno != EPERM && errno != ENOBUFS) {
> -                     log_msg(LOG_ERR, "setsockopt(..., SO_SNDBUFFORCE, "
> +             if(setsockopt(nsd->udp[i].s, SOL_SOCKET, SO_SNDBUFFORCE, 
> (void*)&snd,
> +                     (socklen_t)sizeof(snd)) < 0) {
> +                     if(errno != EPERM && errno != ENOBUFS) {
> +                             log_msg(LOG_ERR, "setsockopt(..., 
> SO_SNDBUFFORCE, "
>                                          "...) failed: %s", strerror(errno));
> -                     return -1;
> -             } 
> +                             return -1;
> +                     }
> +             }
>  #  else
> -     if(1) {
> -#  endif /* SO_SNDBUFFORCE */
>               if(setsockopt(nsd->udp[i].s, SOL_SOCKET, SO_SNDBUF, (void*)&snd,
> -                      (socklen_t)sizeof(snd)) < 0) {
> +                     (socklen_t)sizeof(snd)) < 0) {
>                       if(errno != ENOBUFS && errno != ENOSYS) {
>                               log_msg(LOG_ERR, "setsockopt(..., SO_SNDBUF, "
>                                          "...) failed: %s", strerror(errno));
>                               return -1;
>                       }
>               }
> +#  endif /* SO_SNDBUFFFORCE */
>       }
>  #endif /* SO_SNDBUF */
>  
> -     }
> -#endif /* defined(SO_RCVBUF) || defined(SO_SNDBUF) */
> -
>  #if defined(INET6)
>               if (addr->ai_family == AF_INET6) {
>  # if defined(IPV6_V6ONLY)
> @@ -837,13 +935,19 @@ server_init_ifs(struct nsd *nsd, size_t 
>  
>               if (
>                       bind(nsd->udp[i].s, (struct sockaddr *) addr->ai_addr, 
> addr->ai_addrlen) != 0) {
> -                     log_msg(LOG_ERR, "can't bind udp socket: %s", 
> strerror(errno));
> +                     char buf[256];
> +                     addrport2str((void*)addr->ai_addr, buf, sizeof(buf));
> +                     log_msg(LOG_ERR, "can't bind udp socket %s: %s", buf, 
> strerror(errno));
>                       return -1;
>               }
>       }
>  
>       /* TCP */
>  
> +#ifdef USE_TCP_FASTOPEN
> +     report_tcp_fastopen_config();
> +#endif
> +
>       /* Make a socket... */
>       for (i = from; i < to; i++) {
>               /* for reuseports copy socket specs of first entries */
> @@ -974,10 +1078,40 @@ server_init_ifs(struct nsd *nsd, size_t 
>  
>               if(
>                       bind(nsd->tcp[i].s, (struct sockaddr *) addr->ai_addr, 
> addr->ai_addrlen) != 0) {
> -                     log_msg(LOG_ERR, "can't bind tcp socket: %s", 
> strerror(errno));
> +                     char buf[256];
> +                     addrport2str((void*)addr->ai_addr, buf, sizeof(buf));
> +                     log_msg(LOG_ERR, "can't bind tcp socket %s: %s", buf, 
> strerror(errno));
>                       return -1;
>               }
>  
> +#ifdef USE_TCP_FASTOPEN
> +             /* qlen specifies how many outstanding TFO requests to allow. 
> Limit is a defense
> +                against IP spoofing attacks as suggested in RFC7413 */
> +#ifdef __APPLE__
> +             /* OS X implementation only supports qlen of 1 via this call. 
> Actual
> +                value is configured by the net.inet.tcp.fastopen_backlog 
> kernel parm. */
> +             qlen = 1;
> +#else
> +             /* 5 is recommended on linux */
> +             qlen = 5;
> +#endif
> +             if ((setsockopt(nsd->tcp[i].s, IPPROTO_TCP, TCP_FASTOPEN, 
> &qlen, sizeof(qlen))) == -1 ) {
> +#ifdef ENOPROTOOPT
> +                /* squelch ENOPROTOOPT: freebsd server mode with kernel 
> support
> +                   disabled, except when verbosity enabled for debugging */
> +                    if(errno != ENOPROTOOPT || verbosity >= 3) {
> +#endif
> +                     if(errno == EPERM) {
> +                             log_msg(LOG_ERR, "Setting TCP Fast Open as 
> server failed: %s ; this could likely be because sysctl 
> net.inet.tcp.fastopen.enabled, net.inet.tcp.fastopen.server_enable, or 
> net.ipv4.tcp_fastopen is disabled", strerror(errno));
> +                     } else {
> +                             log_msg(LOG_ERR, "Setting TCP Fast Open as 
> server failed: %s", strerror(errno));
> +                     }
> +#ifdef ENOPROTOOPT
> +                 }
> +#endif
> +             }
> +#endif
> +
>               /* Listen to it... */
>               if (listen(nsd->tcp[i].s, TCP_BACKLOG) == -1) {
>                       log_msg(LOG_ERR, "can't listen: %s", strerror(errno));
> @@ -1039,9 +1173,12 @@ server_prepare(struct nsd *nsd)
>  #else
>       uint32_t v = getpid() ^ time(NULL);
>       srandom((unsigned long)v);
> +#  ifdef HAVE_SSL
>       if(RAND_status() && RAND_bytes((unsigned char*)&v, sizeof(v)) > 0)
>               hash_set_raninit(v);
> -     else    hash_set_raninit(random());
> +     else
> +#  endif
> +             hash_set_raninit(random());
>  #endif
>       rrl_mmap_init(nsd->child_count, nsd->options->rrl_size,
>               nsd->options->rrl_ratelimit,
> @@ -1149,6 +1286,8 @@ server_shutdown(struct nsd *nsd)
>       tsig_finalize();
>  #ifdef HAVE_SSL
>       daemon_remote_delete(nsd->rc); /* ssl-delete secret keys */
> +     if (nsd->tls_ctx)
> +             SSL_CTX_free(nsd->tls_ctx);
>  #endif
>  
>  #ifdef MEMCLEAN /* OS collects memory pages */
> @@ -1381,6 +1520,306 @@ server_send_soa_xfrd(struct nsd* nsd, in
>       }
>  }
>  
> +#ifdef HAVE_SSL
> +void
> +log_crypto_err(const char* str)
> +{
> +     /* error:[error code]:[library name]:[function name]:[reason string] */
> +     char buf[128];
> +     unsigned long e;
> +     ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
> +     log_msg(LOG_ERR, "%s crypto %s", str, buf);
> +     while( (e=ERR_get_error()) ) {
> +             ERR_error_string_n(e, buf, sizeof(buf));
> +             log_msg(LOG_ERR, "and additionally crypto %s", buf);
> +     }
> +}
> +
> +void
> +perform_openssl_init(void)
> +{
> +     /* init SSL library */
> +#ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
> +     ERR_load_crypto_strings();
> +#endif
> +     ERR_load_SSL_strings();
> +#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
> +     OpenSSL_add_all_algorithms();
> +#else
> +     OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
> +             | OPENSSL_INIT_ADD_ALL_DIGESTS
> +             | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
> +#endif
> +#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
> +     (void)SSL_library_init();
> +#else
> +     OPENSSL_init_ssl(0, NULL);
> +#endif
> +
> +     if(!RAND_status()) {
> +             /* try to seed it */
> +             unsigned char buf[256];
> +             unsigned int v, seed=(unsigned)time(NULL) ^ (unsigned)getpid();
> +             size_t i;
> +             v = seed;
> +             for(i=0; i<256/sizeof(v); i++) {
> +                     memmove(buf+i*sizeof(v), &v, sizeof(v));
> +                     v = v*seed + (unsigned int)i;
> +             }
> +             RAND_seed(buf, 256);
> +             log_msg(LOG_WARNING, "warning: no entropy, seeding openssl PRNG 
> with time");
> +     }
> +}
> +
> +static int
> +get_ocsp(char *filename, unsigned char **ocsp)
> +{
> +     BIO *bio;
> +     OCSP_RESPONSE *response;
> +     int len = -1;
> +     unsigned char *p, *buf;
> +     assert(filename);
> +
> +     if ((bio = BIO_new_file(filename, "r")) == NULL) {
> +             log_crypto_err("get_ocsp: BIO_new_file failed");
> +             return -1;
> +     }
> +
> +     if ((response = d2i_OCSP_RESPONSE_bio(bio, NULL)) == NULL) {
> +             log_crypto_err("get_ocsp: d2i_OCSP_RESPONSE_bio failed");
> +             BIO_free(bio);
> +             return -1;
> +     }
> +
> +     if ((len = i2d_OCSP_RESPONSE(response, NULL)) <= 0) {
> +             log_crypto_err("get_ocsp: i2d_OCSP_RESPONSE #1 failed");
> +             OCSP_RESPONSE_free(response);
> +             BIO_free(bio);
> +             return -1;
> +     }
> +
> +     if ((buf = malloc((size_t) len)) == NULL) {
> +             log_msg(LOG_ERR, "get_ocsp: malloc failed");
> +             OCSP_RESPONSE_free(response);
> +             BIO_free(bio);
> +             return -1;
> +     }
> +
> +     p = buf;
> +     if ((len = i2d_OCSP_RESPONSE(response, &p)) <= 0) {
> +             log_crypto_err("get_ocsp: i2d_OCSP_RESPONSE #2 failed");
> +             free(buf);
> +             OCSP_RESPONSE_free(response);
> +             BIO_free(bio);
> +             return -1;
> +     }
> +
> +     OCSP_RESPONSE_free(response);
> +     BIO_free(bio);
> +
> +     *ocsp = buf;
> +     return len;
> +}
> +
> +/* further setup ssl ctx after the keys are loaded */
> +static void
> +listen_sslctx_setup_2(void* ctxt)
> +{
> +     SSL_CTX* ctx = (SSL_CTX*)ctxt;
> +     (void)ctx;
> +#if HAVE_DECL_SSL_CTX_SET_ECDH_AUTO
> +     if(!SSL_CTX_set_ecdh_auto(ctx,1)) {
> +             log_crypto_err("Error in SSL_CTX_ecdh_auto, not enabling 
> ECDHE");
> +     }
> +#elif defined(HAVE_DECL_SSL_CTX_SET_TMP_ECDH) && 
> defined(NID_X9_62_prime256v1)
> +     if(1) {
> +             EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
> +             if (!ecdh) {
> +                     log_crypto_err("could not find p256, not enabling 
> ECDHE");
> +             } else {
> +                     if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) {
> +                             log_crypto_err("Error in SSL_CTX_set_tmp_ecdh, 
> not enabling ECDHE");
> +                     }
> +                     EC_KEY_free (ecdh);
> +             }
> +     }
> +#endif
> +}
> +
> +static int
> +add_ocsp_data_cb(SSL *s, void* ATTR_UNUSED(arg))
> +{
> +     if(ocspdata) {
> +             unsigned char *p;
> +             if ((p=malloc(ocspdata_len)) == NULL) {
> +                     log_msg(LOG_ERR, "add_ocsp_data_cb: malloc failure");
> +                     return SSL_TLSEXT_ERR_NOACK;
> +             }
> +             memcpy(p, ocspdata, ocspdata_len);
> +             if ((SSL_set_tlsext_status_ocsp_resp(s, p, ocspdata_len)) != 1) 
> {
> +                     log_crypto_err("Error in 
> SSL_set_tlsext_status_ocsp_resp");
> +                     free(p);
> +                     return SSL_TLSEXT_ERR_NOACK;
> +             }
> +             return SSL_TLSEXT_ERR_OK;
> +     } else {
> +             return SSL_TLSEXT_ERR_NOACK;
> +     }
> +}
> +
> +SSL_CTX*
> +server_tls_ctx_setup(char* key, char* pem, char* verifypem)
> +{
> +     SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
> +     if(!ctx) {
> +             log_crypto_err("could not SSL_CTX_new");
> +             return NULL;
> +     }
> +     /* no SSLv2, SSLv3 because has defects */
> +     if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) != 
> SSL_OP_NO_SSLv2){
> +             log_crypto_err("could not set SSL_OP_NO_SSLv2");
> +             SSL_CTX_free(ctx);
> +             return NULL;
> +     }
> +     if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
> +             != SSL_OP_NO_SSLv3){
> +             log_crypto_err("could not set SSL_OP_NO_SSLv3");
> +             SSL_CTX_free(ctx);
> +             return 0;
> +     }
> +#if defined(SSL_OP_NO_TLSv1) && defined(SSL_OP_NO_TLSv1_1)
> +     /* if we have tls 1.1 disable 1.0 */
> +     if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1) & SSL_OP_NO_TLSv1)
> +             != SSL_OP_NO_TLSv1){
> +             log_crypto_err("could not set SSL_OP_NO_TLSv1");
> +             SSL_CTX_free(ctx);
> +             return 0;
> +     }
> +#endif
> +#if defined(SSL_OP_NO_TLSv1_1) && defined(SSL_OP_NO_TLSv1_2)
> +     /* if we have tls 1.2 disable 1.1 */
> +     if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1) & SSL_OP_NO_TLSv1_1)
> +             != SSL_OP_NO_TLSv1_1){
> +             log_crypto_err("could not set SSL_OP_NO_TLSv1_1");
> +             SSL_CTX_free(ctx);
> +             return 0;
> +     }
> +#endif
> +#if defined(SSL_OP_NO_RENEGOTIATION)
> +     /* disable client renegotiation */
> +     if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) &
> +             SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) {
> +             log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION");
> +             SSL_CTX_free(ctx);
> +             return 0;
> +     }
> +#endif
> +#if defined(SHA256_DIGEST_LENGTH) && defined(SSL_TXT_CHACHA20)
> +     /* if we have sha256, set the cipher list to have no known vulns */
> +     if(!SSL_CTX_set_cipher_list(ctx, "ECDHE+AESGCM:ECDHE+CHACHA20"))
> +             log_crypto_err("could not set cipher list with 
> SSL_CTX_set_cipher_list");
> +#endif
> +     if((SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE) &
> +             SSL_OP_CIPHER_SERVER_PREFERENCE) !=
> +             SSL_OP_CIPHER_SERVER_PREFERENCE) {
> +             log_crypto_err("could not set SSL_OP_CIPHER_SERVER_PREFERENCE");
> +             SSL_CTX_free(ctx);
> +             return 0;
> +     }
> +#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
> +     SSL_CTX_set_security_level(ctx, 0);
> +#endif
> +     if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) {
> +             log_msg(LOG_ERR, "error for cert file: %s", pem);
> +             log_crypto_err("error in SSL_CTX use_certificate_chain_file");
> +             SSL_CTX_free(ctx);
> +             return NULL;
> +     }
> +     if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
> +             log_msg(LOG_ERR, "error for private key file: %s", key);
> +             log_crypto_err("Error in SSL_CTX use_PrivateKey_file");
> +             SSL_CTX_free(ctx);
> +             return NULL;
> +     }
> +     if(!SSL_CTX_check_private_key(ctx)) {
> +             log_msg(LOG_ERR, "error for key file: %s", key);
> +             log_crypto_err("Error in SSL_CTX check_private_key");
> +             SSL_CTX_free(ctx);
> +             return NULL;
> +     }
> +     listen_sslctx_setup_2(ctx);
> +     if(verifypem && verifypem[0]) {
> +             if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
> +                     log_crypto_err("Error in SSL_CTX verify locations");
> +                     SSL_CTX_free(ctx);
> +                     return NULL;
> +             }
> +             SSL_CTX_set_client_CA_list(ctx, 
> SSL_load_client_CA_file(verifypem));
> +             SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
> +     }
> +     return ctx;
> +}
> +
> +SSL_CTX*
> +server_tls_ctx_create(struct nsd* nsd, char* verifypem, char* ocspfile)
> +{
> +     char *key, *pem;
> +     SSL_CTX *ctx;
> +
> +     key = nsd->options->tls_service_key;
> +     pem = nsd->options->tls_service_pem;
> +     if(!key || key[0] == 0) {
> +             log_msg(LOG_ERR, "error: no tls-service-key file specified");
> +             return NULL;
> +     }
> +     if(!pem || pem[0] == 0) {
> +             log_msg(LOG_ERR, "error: no tls-service-pem file specified");
> +             return NULL;
> +     }
> +
> +     /* NOTE:This mimics the existing code in Unbound 1.5.1 by supporting 
> SSL but
> +      * raft-ietf-uta-tls-bcp-08 recommends only using TLSv1.2*/
> +     ctx = server_tls_ctx_setup(key, pem, verifypem);
> +     if(!ctx) {
> +             log_msg(LOG_ERR, "could not setup server TLS context");
> +             return NULL;
> +     }
> +     if(ocspfile && ocspfile[0]) {
> +             if ((ocspdata_len = get_ocsp(ocspfile, &ocspdata)) < 0) {
> +                     log_crypto_err("Error reading OCSPfile");
> +                     SSL_CTX_free(ctx);
> +                     return NULL;
> +             } else {
> +                     VERBOSITY(2, (LOG_INFO, "ocspfile %s loaded", 
> ocspfile));
> +                     if(!SSL_CTX_set_tlsext_status_cb(ctx, 
> add_ocsp_data_cb)) {
> +                             log_crypto_err("Error in 
> SSL_CTX_set_tlsext_status_cb");
> +                             SSL_CTX_free(ctx);
> +                             return NULL;
> +                     }
> +             }
> +     }
> +     return ctx;
> +}
> +
> +/* check if tcp_handler_accept_data created for TLS dedicated port */
> +int
> +using_tls_port(struct sockaddr* addr, const char* tls_port)
> +{
> +     in_port_t port = 0;
> +
> +     if (addr->sa_family == AF_INET)
> +             port = ((struct sockaddr_in*)addr)->sin_port;
> +#ifndef HAVE_STRUCT_SOCKADDR_IN6
> +     else
> +             port = ((struct sockaddr_in6*)addr)->sin6_port;
> +#endif /* HAVE_STRUCT_SOCKADDR_IN6 */
> +     if (atoi(tls_port) == ntohs(port))
> +             return 1;
> +
> +     return 0;
> +}
> +#endif
> +
>  /* pass timeout=-1 for blocking. Returns size, 0, -1(err), or -2(timeout) */
>  ssize_t
>  block_read(struct nsd* nsd, int s, void* p, ssize_t sz, int timeout)
> @@ -2108,6 +2547,7 @@ server_child(struct nsd *nsd)
>  
>               handler = (struct event*) region_alloc(
>                       server_region, sizeof(*handler));
> +             memset(handler, 0, sizeof(*handler));
>               event_set(handler, nsd->this_child->parent_fd, EV_PERSIST|
>                       EV_READ, child_handle_parent_command, user_data);
>               if(event_base_set(event_base, handler) != 0)
> @@ -2162,6 +2602,7 @@ server_child(struct nsd *nsd)
>  
>                       handler = (struct event*) region_alloc(
>                               server_region, sizeof(*handler));
> +                     memset(handler, 0, sizeof(*handler));
>                       event_set(handler, nsd->udp[i].s, EV_PERSIST|EV_READ,
>                               handle_udp, data);
>                       if(event_base_set(event_base, handler) != 0)
> @@ -2187,6 +2628,20 @@ server_child(struct nsd *nsd)
>                               &tcp_accept_handlers[i-from];
>                       data->nsd = nsd;
>                       data->socket = &nsd->tcp[i];
> +#ifdef HAVE_SSL
> +                     if (nsd->tls_ctx && nsd->options->tls_port && 
> using_tls_port(
> +                         data->socket->addr->ai_addr, 
> nsd->options->tls_port)) {
> +                             data->tls_accept = 1;
> +                             if(verbosity >= 2) {
> +                                     char buf[48];
> +                                     addrport2str((struct 
> sockaddr_storage*)data->socket->addr->ai_addr, buf, sizeof(buf));
> +                                     VERBOSITY(2, (LOG_NOTICE, "setup TCP 
> for TLS service on interface %s", buf));
> +                             }
> +                     }
> +                     else
> +                             data->tls_accept = 0;
> +#endif
> +                     memset(handler, 0, sizeof(*handler));
>                       event_set(handler, nsd->tcp[i].s, EV_PERSIST|EV_READ,
>                               handle_tcp_accept, data);
>                       if(event_base_set(event_base, handler) != 0)
> @@ -2247,6 +2702,7 @@ server_child(struct nsd *nsd)
>               }
>       }
>  
> +     service_remaining_tcp(nsd);
>  #ifdef       BIND8_STATS
>       bind8_stats(nsd);
>  #endif /* BIND8_STATS */
> @@ -2261,6 +2717,114 @@ server_child(struct nsd *nsd)
>       server_shutdown(nsd);
>  }
>  
> +static void remaining_tcp_timeout(int ATTR_UNUSED(fd), short event, void* 
> arg)
> +{
> +     int* timed_out = (int*)arg;
> +        assert(event & EV_TIMEOUT);
> +     /* wake up the service tcp thread, note event is no longer
> +      * registered */
> +     *timed_out = 1;
> +}
> +
> +void
> +service_remaining_tcp(struct nsd* nsd)
> +{
> +     struct tcp_handler_data* p;
> +     struct event_base* event_base;
> +     /* check if it is needed */
> +     if(nsd->current_tcp_count == 0 || tcp_active_list == NULL)
> +             return;
> +     VERBOSITY(4, (LOG_INFO, "service remaining TCP connections"));
> +
> +     /* setup event base */
> +     event_base = nsd_child_event_base();
> +     if(!event_base) {
> +             log_msg(LOG_ERR, "nsd remain tcp could not create event base");
> +             return;
> +     }
> +     /* register tcp connections */
> +     for(p = tcp_active_list; p != NULL; p = p->next) {
> +             struct timeval timeout;
> +             int fd = p->event.ev_fd;
> +#ifdef USE_MINI_EVENT
> +             short event = p->event.ev_flags & (EV_READ|EV_WRITE);
> +#else
> +             short event = p->event.ev_events & (EV_READ|EV_WRITE);
> +#endif
> +             void (*fn)(int, short, void*);
> +#ifdef HAVE_SSL
> +             if(p->tls) {
> +                     if((event&EV_READ))
> +                             fn = handle_tls_reading;
> +                     else    fn = handle_tls_writing;
> +             } else {
> +#endif
> +                     if((event&EV_READ))
> +                             fn = handle_tcp_reading;
> +                     else    fn = handle_tcp_writing;
> +#ifdef HAVE_SSL
> +             }
> +#endif
> +
> +             /* set timeout to 1/10 second */
> +             if(p->tcp_timeout > 100)
> +                     p->tcp_timeout = 100;
> +             timeout.tv_sec = p->tcp_timeout / 1000;
> +             timeout.tv_usec = (p->tcp_timeout % 1000)*1000;
> +             event_del(&p->event);
> +             memset(&p->event, 0, sizeof(p->event));
> +             event_set(&p->event, fd, EV_PERSIST | event | EV_TIMEOUT,
> +                     fn, p);
> +             if(event_base_set(event_base, &p->event) != 0)
> +                     log_msg(LOG_ERR, "event base set failed");
> +             if(event_add(&p->event, &timeout) != 0)
> +                     log_msg(LOG_ERR, "event add failed");
> +     }
> +
> +     /* handle it */
> +     while(nsd->current_tcp_count > 0) {
> +             mode_t m = server_signal_mode(nsd);
> +             struct event timeout;
> +             struct timeval tv;
> +             int timed_out = 0;
> +             if(m == NSD_QUIT || m == NSD_SHUTDOWN ||
> +                     m == NSD_REAP_CHILDREN) {
> +                     /* quit */
> +                     break;
> +             }
> +             /* timer */
> +             /* have to do something every second */
> +             tv.tv_sec = 1;
> +             tv.tv_usec = 0;
> +             memset(&timeout, 0, sizeof(timeout));
> +             event_set(&timeout, -1, EV_TIMEOUT, remaining_tcp_timeout,
> +                     &timed_out);
> +             if(event_base_set(event_base, &timeout) != 0)
> +                     log_msg(LOG_ERR, "remaintcp timer: event_base_set 
> failed");
> +             if(event_add(&timeout, &tv) != 0)
> +                     log_msg(LOG_ERR, "remaintcp timer: event_add failed");
> +
> +             /* service loop */
> +             if(event_base_loop(event_base, EVLOOP_ONCE) == -1) {
> +                     if (errno != EINTR) {
> +                             log_msg(LOG_ERR, "dispatch failed: %s", 
> strerror(errno));
> +                             break;
> +                     }
> +             }
> +             if(!timed_out) {
> +                     event_del(&timeout);
> +             } else {
> +                     /* timed out, quit */
> +                     VERBOSITY(4, (LOG_INFO, "service remaining TCP 
> connections: timed out, quit"));
> +                     break;
> +             }
> +     }
> +#ifdef MEMCLEAN
> +     event_base_free(event_base);
> +#endif
> +     /* continue to quit after return */
> +}
> +
>  #if defined(HAVE_SENDMMSG) && !defined(NONBLOCKING_IS_BROKEN) && 
> defined(HAVE_RECVMMSG)
>  static void
>  handle_udp(int fd, short event, void* arg)
> @@ -2552,12 +3116,48 @@ handle_udp(int fd, short event, void* ar
>  }
>  #endif /* defined(HAVE_SENDMMSG) && !defined(NONBLOCKING_IS_BROKEN) && 
> defined(HAVE_RECVMMSG) */
>  
> +#ifdef HAVE_SSL
> +/*
> + * Setup an event for the tcp handler.
> + */
> +static void
> +tcp_handler_setup_event(struct tcp_handler_data* data, void (*fn)(int, 
> short, void *),
> +       int fd, short event)
> +{
> +     struct timeval timeout;
> +     struct event_base* ev_base;
> +
> +     timeout.tv_sec = data->nsd->tcp_timeout;
> +     timeout.tv_usec = 0L;
> +
> +     ev_base = data->event.ev_base;
> +     event_del(&data->event);
> +     memset(&data->event, 0, sizeof(data->event));
> +     event_set(&data->event, fd, event, fn, data);
> +     if(event_base_set(ev_base, &data->event) != 0)
> +             log_msg(LOG_ERR, "event base set failed");
> +     if(event_add(&data->event, &timeout) != 0)
> +             log_msg(LOG_ERR, "event add failed");
> +}
> +#endif /* HAVE_SSL */
>  
>  static void
>  cleanup_tcp_handler(struct tcp_handler_data* data)
>  {
>       event_del(&data->event);
> +#ifdef HAVE_SSL
> +     if(data->tls) {
> +             SSL_shutdown(data->tls);
> +             SSL_free(data->tls);
> +             data->tls = NULL;
> +     }
> +#endif
>       close(data->event.ev_fd);
> +     if(data->prev)
> +             data->prev->next = data->next;
> +     else    tcp_active_list = data->next;
> +     if(data->next)
> +             data->next->prev = data->prev;
>  
>       /*
>        * Enable the TCP accept handlers when the current number of
> @@ -2593,7 +3193,7 @@ handle_tcp_reading(int fd, short event, 
>  
>       if (data->nsd->tcp_query_count > 0 &&
>               data->query_count >= data->nsd->tcp_query_count) {
> -             /* No more queries allowed on this tcp connection.  */
> +             /* No more queries allowed on this tcp connection. */
>               cleanup_tcp_handler(data);
>               return;
>       }
> @@ -2770,6 +3370,15 @@ handle_tcp_reading(int fd, short event, 
>       /* Switch to the tcp write handler.  */
>       buffer_flip(data->query->packet);
>       data->query->tcplen = buffer_remaining(data->query->packet);
> +#ifdef BIND8_STATS
> +     /* Account the rcode & TC... */
> +     STATUP2(data->nsd, rcode, RCODE(data->query->packet));
> +     ZTATUP2(data->nsd, data->query->zone, rcode, 
> RCODE(data->query->packet));
> +     if (TC(data->query->packet)) {
> +             STATUP(data->nsd, truncated);
> +             ZTATUP(data->nsd, data->query->zone, truncated);
> +     }
> +#endif /* BIND8_STATS */
>  #ifdef USE_DNSTAP
>       dt_collector_submit_auth_response(data->nsd, &data->query->addr,
>               data->query->addrlen, data->query->tcp, data->query->packet,
> @@ -2782,8 +3391,9 @@ handle_tcp_reading(int fd, short event, 
>  
>       ev_base = data->event.ev_base;
>       event_del(&data->event);
> -     event_set(&data->event, fd, EV_PERSIST | EV_WRITE | EV_TIMEOUT,
> -             handle_tcp_writing, data);
> +     memset(&data->event, 0, sizeof(data->event));
> +     event_set(&data->event, fd, EV_PERSIST | EV_READ | EV_TIMEOUT,
> +             handle_tcp_reading, data);
>       if(event_base_set(ev_base, &data->event) != 0)
>               log_msg(LOG_ERR, "event base set tcpr failed");
>       if(event_add(&data->event, &timeout) != 0)
> @@ -2914,6 +3524,7 @@ handle_tcp_writing(int fd, short event, 
>                       timeout.tv_usec = (data->tcp_timeout % 1000)*1000;
>                       ev_base = data->event.ev_base;
>                       event_del(&data->event);
> +                     memset(&data->event, 0, sizeof(data->event));
>                       event_set(&data->event, fd, EV_PERSIST | EV_WRITE | 
> EV_TIMEOUT,
>                               handle_tcp_writing, data);
>                       if(event_base_set(ev_base, &data->event) != 0)
> @@ -2945,6 +3556,7 @@ handle_tcp_writing(int fd, short event, 
>       timeout.tv_usec = (data->tcp_timeout % 1000)*1000;
>       ev_base = data->event.ev_base;
>       event_del(&data->event);
> +     memset(&data->event, 0, sizeof(data->event));
>       event_set(&data->event, fd, EV_PERSIST | EV_READ | EV_TIMEOUT,
>               handle_tcp_reading, data);
>       if(event_base_set(ev_base, &data->event) != 0)
> @@ -2953,6 +3565,428 @@ handle_tcp_writing(int fd, short event, 
>               log_msg(LOG_ERR, "event add tcpw failed");
>  }
>  
> +#ifdef HAVE_SSL
> +/** create SSL object and associate fd */
> +static SSL*
> +incoming_ssl_fd(SSL_CTX* ctx, int fd)
> +{
> +     SSL* ssl = SSL_new((SSL_CTX*)ctx);
> +     if(!ssl) {
> +             log_crypto_err("could not SSL_new");
> +             return NULL;
> +     }
> +     SSL_set_accept_state(ssl);
> +     (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
> +     if(!SSL_set_fd(ssl, fd)) {
> +             log_crypto_err("could not SSL_set_fd");
> +             SSL_free(ssl);
> +             return NULL;
> +     }
> +     return ssl;
> +}
> +
> +/** TLS handshake to upgrade TCP connection */
> +static int
> +tls_handshake(struct tcp_handler_data* data, int fd, int writing)
> +{
> +     int r;
> +     if(data->shake_state == tls_hs_read_event) {
> +             /* read condition satisfied back to writing */
> +             tcp_handler_setup_event(data, handle_tls_writing, fd, 
> EV_PERSIST|EV_TIMEOUT|EV_WRITE);
> +             data->shake_state = tls_hs_none;
> +             return 1;
> +     }
> +     if(data->shake_state == tls_hs_write_event) {
> +             /* write condition satisfied back to reading */
> +             tcp_handler_setup_event(data, handle_tls_reading, fd, 
> EV_PERSIST|EV_TIMEOUT|EV_READ);
> +             data->shake_state = tls_hs_none;
> +             return 1;
> +     }
> +
> +     /* (continue to) setup the TLS connection */
> +     ERR_clear_error();
> +     r = SSL_do_handshake(data->tls);
> +
> +     if(r != 1) {
> +             int want = SSL_get_error(data->tls, r);
> +             if(want == SSL_ERROR_WANT_READ) {
> +                     if(data->shake_state == tls_hs_read) {
> +                             /* try again later */
> +                             return 1;
> +                     }
> +                     data->shake_state = tls_hs_read;
> +                     /* switch back to reading mode */
> +                     tcp_handler_setup_event(data, handle_tls_reading, fd, 
> EV_PERSIST|EV_TIMEOUT|EV_READ);
> +                     return 1;
> +             } else if(want == SSL_ERROR_WANT_WRITE) {
> +                     if(data->shake_state == tls_hs_write) {
> +                             /* try again later */
> +                             return 1;
> +                     }
> +                     data->shake_state = tls_hs_write;
> +                     /* switch back to writing mode */
> +                     tcp_handler_setup_event(data, handle_tls_writing, fd, 
> EV_PERSIST|EV_TIMEOUT|EV_WRITE);
> +                     return 1;
> +             } else {
> +                     if(r == 0)
> +                             VERBOSITY(3, (LOG_ERR, "TLS handshake: 
> connection closed prematurely"));
> +                     cleanup_tcp_handler(data);
> +                     VERBOSITY(3, (LOG_ERR, "TLS handshake failed"));
> +                     return 0;
> +             }
> +     }
> +
> +     /* Use to log successful upgrade for testing - could be removed*/
> +     VERBOSITY(3, (LOG_INFO, "TLS handshake succeeded."));
> +     /* set back to the event we need to have when reading (or writing) */
> +     if(data->shake_state == tls_hs_read && writing) {
> +             tcp_handler_setup_event(data, handle_tls_writing, fd, 
> EV_PERSIST|EV_TIMEOUT|EV_WRITE);
> +     } else if(data->shake_state == tls_hs_write && !writing) {
> +             tcp_handler_setup_event(data, handle_tls_reading, fd, 
> EV_PERSIST|EV_TIMEOUT|EV_READ);
> +     }
> +     data->shake_state = tls_hs_none;
> +     return 1;
> +}
> +
> +/** handle TLS reading of incoming query */
> +static void
> +handle_tls_reading(int fd, short event, void* arg)
> +{
> +     struct tcp_handler_data *data = (struct tcp_handler_data *) arg;
> +     ssize_t received;
> +
> +     if ((event & EV_TIMEOUT)) {
> +             /* Connection timed out.  */
> +             cleanup_tcp_handler(data);
> +             return;
> +     }
> +
> +     if (data->nsd->tcp_query_count > 0 &&
> +         data->query_count >= data->nsd->tcp_query_count) {
> +             /* No more queries allowed on this tcp connection. */
> +             cleanup_tcp_handler(data);
> +             return;
> +     }
> +
> +     assert((event & EV_READ));
> +
> +     if (data->bytes_transmitted == 0) {
> +             query_reset(data->query, TCP_MAX_MESSAGE_LEN, 1);
> +     }
> +
> +     if(data->shake_state != tls_hs_none) {
> +             if(!tls_handshake(data, fd, 0))
> +                     return;
> +             if(data->shake_state != tls_hs_none)
> +                     return;
> +     }
> +
> +     /*
> +      * Check if we received the leading packet length bytes yet.
> +      */
> +     if(data->bytes_transmitted < sizeof(uint16_t)) {
> +             ERR_clear_error();
> +             if((received=SSL_read(data->tls, (char *) &data->query->tcplen
> +                 + data->bytes_transmitted,
> +                 sizeof(uint16_t) - data->bytes_transmitted)) <= 0) {
> +                     int want = SSL_get_error(data->tls, received);
> +                     if(want == SSL_ERROR_ZERO_RETURN) {
> +                             cleanup_tcp_handler(data);
> +                             return; /* shutdown, closed */
> +                     } else if(want == SSL_ERROR_WANT_READ) {
> +                             /* wants to be called again */
> +                             return;
> +                     }
> +                     else if(want == SSL_ERROR_WANT_WRITE) {
> +                             /* switch to writing */
> +                             data->shake_state = tls_hs_write_event;
> +                             tcp_handler_setup_event(data, 
> handle_tls_writing, fd, EV_PERSIST | EV_WRITE | EV_TIMEOUT);
> +                             return;
> +                     }
> +                     cleanup_tcp_handler(data);
> +                     log_crypto_err("could not SSL_read");
> +                     return;
> +             }
> +
> +             data->bytes_transmitted += received;
> +             if (data->bytes_transmitted < sizeof(uint16_t)) {
> +                     /*
> +                      * Not done with the tcplen yet, wait for more
> +                      * data to become available.
> +                      */
> +                     return;
> +             }
> +
> +             assert(data->bytes_transmitted == sizeof(uint16_t));
> +
> +             data->query->tcplen = ntohs(data->query->tcplen);
> +
> +             /*
> +              * Minimum query size is:
> +              *
> +              *     Size of the header (12)
> +              *   + Root domain name   (1)
> +              *   + Query class        (2)
> +              *   + Query type         (2)
> +              */
> +             if (data->query->tcplen < QHEADERSZ + 1 + sizeof(uint16_t) + 
> sizeof(uint16_t)) {
> +                     VERBOSITY(2, (LOG_WARNING, "packet too small, dropping 
> tcp connection"));
> +                     cleanup_tcp_handler(data);
> +                     return;
> +             }
> +
> +             if (data->query->tcplen > data->query->maxlen) {
> +                     VERBOSITY(2, (LOG_WARNING, "insufficient tcp buffer, 
> dropping connection"));
> +                     cleanup_tcp_handler(data);
> +                     return;
> +             }
> +
> +             buffer_set_limit(data->query->packet, data->query->tcplen);
> +     }
> +
> +     assert(buffer_remaining(data->query->packet) > 0);
> +
> +     /* Read the (remaining) query data.  */
> +     ERR_clear_error();
> +     received = SSL_read(data->tls, 
> (void*)buffer_current(data->query->packet),
> +                         (int)buffer_remaining(data->query->packet));
> +     if(received <= 0) {
> +             int want = SSL_get_error(data->tls, received);
> +             if(want == SSL_ERROR_ZERO_RETURN) {
> +                     cleanup_tcp_handler(data);
> +                     return; /* shutdown, closed */
> +             } else if(want == SSL_ERROR_WANT_READ) {
> +                     /* wants to be called again */
> +                     return;
> +             }
> +             else if(want == SSL_ERROR_WANT_WRITE) {
> +                     /* switch back writing */
> +                     data->shake_state = tls_hs_write_event;
> +                     tcp_handler_setup_event(data, handle_tls_writing, fd, 
> EV_PERSIST | EV_WRITE | EV_TIMEOUT);
> +                     return;
> +             }
> +             cleanup_tcp_handler(data);
> +             log_crypto_err("could not SSL_read");
> +             return;
> +     }
> +
> +     data->bytes_transmitted += received;
> +     buffer_skip(data->query->packet, received);
> +     if (buffer_remaining(data->query->packet) > 0) {
> +             /*
> +              * Message not yet complete, wait for more data to
> +              * become available.
> +              */
> +             return;
> +     }
> +
> +     assert(buffer_position(data->query->packet) == data->query->tcplen);
> +
> +     /* Account... */
> +#ifndef INET6
> +     STATUP(data->nsd, ctls);
> +#else
> +     if (data->query->addr.ss_family == AF_INET) {
> +             STATUP(data->nsd, ctls);
> +     } else if (data->query->addr.ss_family == AF_INET6) {
> +             STATUP(data->nsd, ctls6);
> +     }
> +#endif
> +
> +     /* We have a complete query, process it.  */
> +
> +     /* tcp-query-count: handle query counter ++ */
> +     data->query_count++;
> +
> +     buffer_flip(data->query->packet);
> +#ifdef USE_DNSTAP
> +     dt_collector_submit_auth_query(data->nsd, &data->query->addr,
> +             data->query->addrlen, data->query->tcp, data->query->packet);
> +#endif /* USE_DNSTAP */
> +     data->query_state = server_process_query(data->nsd, data->query);
> +     if (data->query_state == QUERY_DISCARDED) {
> +             /* Drop the packet and the entire connection... */
> +             STATUP(data->nsd, dropped);
> +             ZTATUP(data->nsd, data->query->zone, dropped);
> +             cleanup_tcp_handler(data);
> +             return;
> +     }
> +
> +#ifdef BIND8_STATS
> +     if (RCODE(data->query->packet) == RCODE_OK
> +         && !AA(data->query->packet))
> +     {
> +             STATUP(data->nsd, nona);
> +             ZTATUP(data->nsd, data->query->zone, nona);
> +     }
> +#endif /* BIND8_STATS */
> +
> +#ifdef USE_ZONE_STATS
> +#ifndef INET6
> +     ZTATUP(data->nsd, data->query->zone, ctls);
> +#else
> +     if (data->query->addr.ss_family == AF_INET) {
> +             ZTATUP(data->nsd, data->query->zone, ctls);
> +     } else if (data->query->addr.ss_family == AF_INET6) {
> +             ZTATUP(data->nsd, data->query->zone, ctls6);
> +     }
> +#endif
> +#endif /* USE_ZONE_STATS */
> +
> +     query_add_optional(data->query, data->nsd);
> +
> +     /* Switch to the tcp write handler.  */
> +     buffer_flip(data->query->packet);
> +     data->query->tcplen = buffer_remaining(data->query->packet);
> +#ifdef BIND8_STATS
> +     /* Account the rcode & TC... */
> +     STATUP2(data->nsd, rcode, RCODE(data->query->packet));
> +     ZTATUP2(data->nsd, data->query->zone, rcode, 
> RCODE(data->query->packet));
> +     if (TC(data->query->packet)) {
> +             STATUP(data->nsd, truncated);
> +             ZTATUP(data->nsd, data->query->zone, truncated);
> +     }
> +#endif /* BIND8_STATS */
> +#ifdef USE_DNSTAP
> +     dt_collector_submit_auth_response(data->nsd, &data->query->addr,
> +             data->query->addrlen, data->query->tcp, data->query->packet,
> +             data->query->zone);
> +#endif /* USE_DNSTAP */
> +     data->bytes_transmitted = 0;
> +
> +     tcp_handler_setup_event(data, handle_tls_writing, fd, EV_PERSIST | 
> EV_WRITE | EV_TIMEOUT);
> +
> +     /* see if we can write the answer right away(usually so,EAGAIN ifnot)*/
> +     handle_tls_writing(fd, EV_WRITE, data);
> +}
> +
> +/** handle TLS writing of outgoing response */
> +static void
> +handle_tls_writing(int fd, short event, void* arg)
> +{
> +     struct tcp_handler_data *data = (struct tcp_handler_data *) arg;
> +     ssize_t sent;
> +     struct query *q = data->query;
> +     /* static variable that holds reassembly buffer used to put the
> +      * TCP length in front of the packet, like writev. */
> +     static buffer_type* global_tls_temp_buffer = NULL;
> +     buffer_type* write_buffer;
> +
> +     if ((event & EV_TIMEOUT)) {
> +             /* Connection timed out.  */
> +             cleanup_tcp_handler(data);
> +             return;
> +     }
> +
> +     assert((event & EV_WRITE));
> +
> +     if(data->shake_state != tls_hs_none) {
> +             if(!tls_handshake(data, fd, 1))
> +                     return;
> +             if(data->shake_state != tls_hs_none)
> +                     return;
> +     }
> +
> +     (void)SSL_set_mode(data->tls, SSL_MODE_ENABLE_PARTIAL_WRITE);
> +
> +     /* If we are writing the start of a message, we must include the length
> +      * this is done with a copy into write_buffer. */
> +     write_buffer = NULL;
> +     if (data->bytes_transmitted == 0) {
> +             if(!global_tls_temp_buffer) {
> +                     /* gets deallocated when nsd shuts down from
> +                      * nsd.region */
> +                     global_tls_temp_buffer = buffer_create(nsd.region,
> +                             QIOBUFSZ + sizeof(q->tcplen));
> +                     if (!global_tls_temp_buffer) {
> +                             return;
> +                     }
> +             }
> +             write_buffer = global_tls_temp_buffer;
> +             buffer_clear(write_buffer);
> +             buffer_write_u16(write_buffer, q->tcplen);
> +             buffer_write(write_buffer, buffer_current(q->packet),
> +                     (int)buffer_remaining(q->packet));
> +             buffer_flip(write_buffer);
> +     } else {
> +             write_buffer = q->packet;
> +     }
> +
> +     /* Write the response */
> +     ERR_clear_error();
> +     sent = SSL_write(data->tls, buffer_current(write_buffer), 
> buffer_remaining(write_buffer));
> +     if(sent <= 0) {
> +             int want = SSL_get_error(data->tls, sent);
> +             if(want == SSL_ERROR_ZERO_RETURN) {
> +                     cleanup_tcp_handler(data);
> +                     /* closed */
> +             } else if(want == SSL_ERROR_WANT_READ) {
> +                     /* switch back to reading */
> +                     data->shake_state = tls_hs_read_event;
> +                     tcp_handler_setup_event(data, handle_tls_reading, fd, 
> EV_PERSIST | EV_READ | EV_TIMEOUT);
> +             } else if(want != SSL_ERROR_WANT_WRITE) {
> +                     cleanup_tcp_handler(data);
> +                     log_crypto_err("could not SSL_write");
> +             }
> +             return;
> +     }
> +
> +     buffer_skip(write_buffer, sent);
> +     if(buffer_remaining(write_buffer) != 0) {
> +             /* If not all sent, sync up the real buffer if it wasn't used.*/
> +             if (data->bytes_transmitted == 0 && (ssize_t)sent > 
> (ssize_t)sizeof(q->tcplen)) {
> +                     buffer_skip(q->packet, (ssize_t)sent - 
> (ssize_t)sizeof(q->tcplen));
> +             }
> +     }
> +
> +     data->bytes_transmitted += sent;
> +     if (data->bytes_transmitted < q->tcplen + sizeof(q->tcplen)) {
> +             /*
> +              * Still more data to write when socket becomes
> +              * writable again.
> +              */
> +             return;
> +     }
> +
> +     assert(data->bytes_transmitted == q->tcplen + sizeof(q->tcplen));
> +
> +     if (data->query_state == QUERY_IN_AXFR) {
> +             /* Continue processing AXFR and writing back results.  */
> +             buffer_clear(q->packet);
> +             data->query_state = query_axfr(data->nsd, q);
> +             if (data->query_state != QUERY_PROCESSED) {
> +                     query_add_optional(data->query, data->nsd);
> +
> +                     /* Reset data. */
> +                     buffer_flip(q->packet);
> +                     q->tcplen = buffer_remaining(q->packet);
> +                     data->bytes_transmitted = 0;
> +                     /* Reset to writing mode.  */
> +                     tcp_handler_setup_event(data, handle_tls_writing, fd, 
> EV_PERSIST | EV_WRITE | EV_TIMEOUT);
> +
> +                     /*
> +                      * Write data if/when the socket is writable
> +                      * again.
> +                      */
> +                     return;
> +             }
> +     }
> +
> +     /*
> +      * Done sending, wait for the next request to arrive on the
> +      * TCP socket by installing the TCP read handler.
> +      */
> +     if (data->nsd->tcp_query_count > 0 &&
> +             data->query_count >= data->nsd->tcp_query_count) {
> +
> +             (void) shutdown(fd, SHUT_WR);
> +     }
> +
> +     data->bytes_transmitted = 0;
> +
> +     tcp_handler_setup_event(data, handle_tls_reading, fd, EV_PERSIST | 
> EV_READ | EV_TIMEOUT);
> +}
> +#endif
>  
>  static void
>  handle_slowaccept_timeout(int ATTR_UNUSED(fd), short ATTR_UNUSED(event),
> @@ -2964,6 +3998,26 @@ handle_slowaccept_timeout(int ATTR_UNUSE
>       }
>  }
>  
> +static int perform_accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
> +{
> +#ifndef HAVE_ACCEPT4
> +     int s = accept(fd, addr, addrlen);
> +     if (s != -1) {
> +             if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
> +                     log_msg(LOG_ERR, "fcntl failed: %s", strerror(errno));
> +                     close(s);
> +                     s = -1;
> +                     errno=EINTR; /* stop error printout as error in accept4
> +                             by setting this errno, it omits printout, in
> +                             later code that calls nsd_accept4 */
> +             }
> +     }
> +     return s;
> +#else
> +     return accept4(fd, addr, addrlen, SOCK_NONBLOCK);
> +#endif /* HAVE_ACCEPT4 */
> +}
> +
>  /*
>   * Handle an incoming TCP connection.  The connection is accepted and
>   * a new TCP reader event handler is added.  The TCP handler
> @@ -2975,6 +4029,7 @@ handle_tcp_accept(int fd, short event, v
>       struct tcp_accept_handler_data *data
>               = (struct tcp_accept_handler_data *) arg;
>       int s;
> +     int reject = 0;
>       struct tcp_handler_data *tcp_data;
>       region_type *tcp_region;
>  #ifdef INET6
> @@ -2990,16 +4045,15 @@ handle_tcp_accept(int fd, short event, v
>       }
>  
>       if (data->nsd->current_tcp_count >= data->nsd->maximum_tcp_count) {
> -             return;
> +             reject = data->nsd->options->tcp_reject_overflow;
> +             if (!reject) {
> +                     return;
> +             }
>       }
>  
>       /* Accept it... */
>       addrlen = sizeof(addr);
> -#ifndef HAVE_ACCEPT4
> -     s = accept(fd, (struct sockaddr *) &addr, &addrlen);
> -#else
> -     s = accept4(fd, (struct sockaddr *) &addr, &addrlen, SOCK_NONBLOCK);
> -#endif
> +     s = perform_accept(fd, (struct sockaddr *) &addr, &addrlen);
>       if (s == -1) {
>               /**
>                * EMFILE and ENFILE is a signal that the limit of open
> @@ -3014,6 +4068,8 @@ handle_tcp_accept(int fd, short event, v
>                               configure_handler_event_types(0);
>                               tv.tv_sec = SLOW_ACCEPT_TIMEOUT;
>                               tv.tv_usec = 0L;
> +                             memset(&slowaccept_event, 0,
> +                                     sizeof(slowaccept_event));
>                               event_set(&slowaccept_event, -1, EV_TIMEOUT,
>                                       handle_slowaccept_timeout, NULL);
>                               (void)event_base_set(data->event.ev_base,
> @@ -3036,13 +4092,11 @@ handle_tcp_accept(int fd, short event, v
>               return;
>       }
>  
> -#ifndef HAVE_ACCEPT4
> -     if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
> -             log_msg(LOG_ERR, "fcntl failed: %s", strerror(errno));
> +     if (reject) {
> +             shutdown(s, SHUT_RDWR);
>               close(s);
>               return;
>       }
> -#endif
>  
>       /*
>        * This region is deallocated when the TCP connection is
> @@ -3056,6 +4110,12 @@ handle_tcp_accept(int fd, short event, v
>               compression_table_size, compressed_dnames);
>       tcp_data->nsd = data->nsd;
>       tcp_data->query_count = 0;
> +#ifdef HAVE_SSL
> +     tcp_data->shake_state = tls_hs_none;
> +     tcp_data->tls = NULL;
> +#endif
> +     tcp_data->prev = NULL;
> +     tcp_data->next = NULL;
>  
>       tcp_data->query_state = QUERY_PROCESSED;
>       tcp_data->bytes_transmitted = 0;
> @@ -3067,11 +4127,29 @@ handle_tcp_accept(int fd, short event, v
>               /* very busy, give smaller timeout */
>               tcp_data->tcp_timeout = 200;
>       }
> +     memset(&tcp_data->event, 0, sizeof(tcp_data->event));
>       timeout.tv_sec = tcp_data->tcp_timeout / 1000;
>       timeout.tv_usec = (tcp_data->tcp_timeout % 1000)*1000;
>  
> -     event_set(&tcp_data->event, s, EV_PERSIST | EV_READ | EV_TIMEOUT,
> -             handle_tcp_reading, tcp_data);
> +#ifdef HAVE_SSL
> +     if (data->tls_accept) {
> +             tcp_data->tls = incoming_ssl_fd(tcp_data->nsd->tls_ctx, s);
> +             if(!tcp_data->tls) {
> +                     close(s);
> +                     return;
> +             }
> +             tcp_data->shake_state = tls_hs_read;
> +             memset(&tcp_data->event, 0, sizeof(tcp_data->event));
> +             event_set(&tcp_data->event, s, EV_PERSIST | EV_READ | 
> EV_TIMEOUT,
> +                       handle_tls_reading, tcp_data);
> +     } else {
> +#endif
> +             memset(&tcp_data->event, 0, sizeof(tcp_data->event));
> +             event_set(&tcp_data->event, s, EV_PERSIST | EV_READ | 
> EV_TIMEOUT,
> +                       handle_tcp_reading, tcp_data);
> +#ifdef HAVE_SSL
> +     }
> +#endif
>       if(event_base_set(data->event.ev_base, &tcp_data->event) != 0) {
>               log_msg(LOG_ERR, "cannot set tcp event base");
>               close(s);
> @@ -3084,14 +4162,26 @@ handle_tcp_accept(int fd, short event, v
>               region_destroy(tcp_region);
>               return;
>       }
> +     if(tcp_active_list) {
> +             tcp_active_list->prev = tcp_data;
> +             tcp_data->next = tcp_active_list;
> +     }
> +     tcp_active_list = tcp_data;
>  
>       /*
>        * Keep track of the total number of TCP handlers installed so
>        * we can stop accepting connections when the maximum number
>        * of simultaneous TCP connections is reached.
> +      *
> +      * If tcp-reject-overflow is enabled, however, then we do not
> +      * change the handler event type; we keep it as-is and accept
> +      * overflow TCP connections only so that we can forcibly kill
> +      * them off.
>        */
>       ++data->nsd->current_tcp_count;
> -     if (data->nsd->current_tcp_count == data->nsd->maximum_tcp_count) {
> +     if (!data->nsd->options->tcp_reject_overflow &&
> +          data->nsd->current_tcp_count == data->nsd->maximum_tcp_count)
> +     {
>               configure_handler_event_types(0);
>       }
>  }
> @@ -3165,6 +4255,7 @@ configure_handler_event_types(short even
>                       struct event_base* base = handler->ev_base;
>                       if(tcp_accept_handlers[i].event_added)
>                               event_del(handler);
> +                     memset(handler, 0, sizeof(*handler));
>                       event_set(handler, fd, event_types,
>                               handle_tcp_accept, &tcp_accept_handlers[i]);
>                       if(event_base_set(base, handler) != 0)
> Index: tsig.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/tsig.c,v
> retrieving revision 1.5
> diff -u -p -r1.5 tsig.c
> --- tsig.c    30 Jul 2018 08:57:09 -0000      1.5
> +++ tsig.c    12 Sep 2019 11:25:03 -0000
> @@ -19,6 +19,61 @@
>  #include "query.h"
>  #include "rbtree.h"
>  
> +#ifndef HAVE_SSL
> +/* we need fixed time compare */
> +#define CRYPTO_memcmp memcmp_fixedtime
> +int memcmp_fixedtime(const void *s1, const void *s2, size_t n)
> +{
> +     size_t i;
> +     const uint8_t* u1 = (const uint8_t*)s1;
> +     const uint8_t* u2 = (const uint8_t*)s2;
> +     int ret = 0, haveit = 0, bret = 0, bhaveit = 0;
> +     /* this routine loops for every byte in the strings.
> +      * every loop, it tests ==, < and >.  All three.  One succeeds,
> +      * as every time it must be equal, smaller or larger.  The one
> +      * that succeeds has one if-comparison and two assignments. */
> +     for(i=0; i<n; i++) {
> +             if(u1[i] == u2[i]) {
> +                     /* waste time equal to < and > statements */
> +                     if(haveit) {
> +                             bret = -1; /* waste time */
> +                             bhaveit = 1;
> +                     } else {
> +                             bret = 1; /* waste time */
> +                             bhaveit = 1;
> +                     }
> +             }
> +             if(u1[i] < u2[i]) {
> +                     if(haveit) {
> +                             bret = -1; /* waste time equal to the else */
> +                             bhaveit = 1;
> +                     } else {
> +                             ret = -1;
> +                             haveit = 1;
> +                     }
> +             }
> +             if(u1[i] > u2[i]) {
> +                     if(haveit) {
> +                             bret = 1; /* waste time equal to the else */
> +                             bhaveit = 1;
> +                     } else {
> +                             ret = 1;
> +                             haveit = 1;
> +                     }
> +             }
> +     }
> +     /* use the variables to stop the compiler from excluding them */
> +     if(bhaveit) {
> +             if(bret == -2)
> +                     ret = 0; /* never happens */
> +     } else {
> +             if(bret == -2)
> +                     ret = 0; /* never happens */
> +     }
> +     return ret;
> +}
> +#endif
> +
>  static region_type *tsig_region;
>  
>  struct tsig_key_table
> Index: util.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/util.c,v
> retrieving revision 1.21
> diff -u -p -r1.21 util.c
> --- util.c    29 Sep 2018 17:17:54 -0000      1.21
> +++ util.c    12 Sep 2019 11:25:03 -0000
> @@ -1087,6 +1087,35 @@ addr2str(
>  }
>  
>  void
> +addrport2str(
> +#ifdef INET6
> +     struct sockaddr_storage *addr
> +#else
> +     struct sockaddr_in *addr
> +#endif
> +     , char* str, size_t len)
> +{
> +     char ip[256];
> +#ifdef INET6
> +     if (addr->ss_family == AF_INET6) {
> +             if (!inet_ntop(AF_INET6,
> +                     &((struct sockaddr_in6 *)addr)->sin6_addr, ip, 
> sizeof(ip)))
> +                     strlcpy(ip, "[unknown ip6, inet_ntop failed]", 
> sizeof(ip));
> +             /* append port number */
> +             snprintf(str, len, "%s@%u", ip,
> +                     (unsigned)ntohs(((struct sockaddr_in6 
> *)addr)->sin6_port));
> +             return;
> +     } else
> +#endif
> +     if (!inet_ntop(AF_INET, &((struct sockaddr_in *)addr)->sin_addr,
> +             ip, sizeof(ip)))
> +             strlcpy(ip, "[unknown ip4, inet_ntop failed]", sizeof(ip));
> +     /* append port number */
> +     snprintf(str, len, "%s@%u", ip,
> +             (unsigned)ntohs(((struct sockaddr_in *)addr)->sin_port));
> +}
> +
> +void
>  append_trailing_slash(const char** dirname, region_type* region)
>  {
>       int l = strlen(*dirname);
> Index: util.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/util.h,v
> retrieving revision 1.13
> diff -u -p -r1.13 util.h
> --- util.h    29 Sep 2018 17:17:54 -0000      1.13
> +++ util.h    12 Sep 2019 11:25:03 -0000
> @@ -410,6 +410,15 @@ void addr2str(
>  #endif
>       , char* str, size_t len);
>  
> +/* print addr@port */
> +void addrport2str(
> +#ifdef INET6
> +     struct sockaddr_storage *addr
> +#else
> +     struct sockaddr_in *addr
> +#endif
> +     , char* str, size_t len);
> +
>  /** copy dirname string and append slash.  Previous dirname is leaked,
>   * but it is to be used once, at startup, for chroot */
>  void append_trailing_slash(const char** dirname, struct region* region);
> Index: xfrd-disk.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/xfrd-disk.c,v
> retrieving revision 1.12
> diff -u -p -r1.12 xfrd-disk.c
> --- xfrd-disk.c       17 May 2018 18:58:40 -0000      1.12
> +++ xfrd-disk.c       12 Sep 2019 11:25:03 -0000
> @@ -289,6 +289,13 @@ xfrd_read_state(struct xfrd_state* xfrd)
>                       zone->state = xfrd_zone_refreshing;
>                       xfrd_set_refresh_now(zone);
>               }
> +             if(timeout != 0 && filetime + timeout < (uint32_t)xfrd_time()) {
> +                     /* timeout is in the past, refresh the zone */
> +                     timeout = 0;
> +                     if(zone->state == xfrd_zone_ok)
> +                             zone->state = xfrd_zone_refreshing;
> +                     xfrd_set_refresh_now(zone);
> +             }
>  
>               /* There is a soa && current time is past expiry point */
>               if(soa_disk_acquired_read!=0 &&
> Index: xfrd-notify.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/xfrd-notify.c,v
> retrieving revision 1.3
> diff -u -p -r1.3 xfrd-notify.c
> --- xfrd-notify.c     3 Feb 2018 11:03:51 -0000       1.3
> +++ xfrd-notify.c     12 Sep 2019 11:25:03 -0000
> @@ -382,6 +382,8 @@ notify_setup_event(struct notify_zone* z
>                       event_del(&zone->notify_send_handler);
>               }
>               zone->notify_timeout.tv_sec = XFRD_NOTIFY_RETRY_TIMOUT;
> +             memset(&zone->notify_send_handler, 0,
> +                     sizeof(zone->notify_send_handler));
>               event_set(&zone->notify_send_handler, fd, EV_READ | EV_TIMEOUT,
>                       xfrd_handle_notify_send, zone);
>               if(event_base_set(xfrd->event_base, &zone->notify_send_handler) 
> != 0)
> @@ -396,6 +398,8 @@ notify_setup_event(struct notify_zone* z
>                       event_del(&zone->notify_send6_handler);
>               }
>               zone->notify_timeout.tv_sec = XFRD_NOTIFY_RETRY_TIMOUT;
> +             memset(&zone->notify_send6_handler, 0,
> +                     sizeof(zone->notify_send6_handler));
>               event_set(&zone->notify_send6_handler, fd, EV_READ | EV_TIMEOUT,
>                       xfrd_handle_notify_send, zone);
>               if(event_base_set(xfrd->event_base, 
> &zone->notify_send6_handler) != 0)
> @@ -465,6 +469,8 @@ setup_notify_active(struct notify_zone* 
>  
>       if(zone->notify_send_enable)
>               notify_send_disable(zone);
> +     memset(&zone->notify_send_handler, 0,
> +             sizeof(zone->notify_send_handler));
>       event_set(&zone->notify_send_handler, -1, EV_TIMEOUT,
>               xfrd_handle_notify_send, zone);
>       if(event_base_set(xfrd->event_base, &zone->notify_send_handler) != 0)
> Index: xfrd-tcp.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/xfrd-tcp.c,v
> retrieving revision 1.20
> diff -u -p -r1.20 xfrd-tcp.c
> --- xfrd-tcp.c        3 Feb 2018 11:03:51 -0000       1.20
> +++ xfrd-tcp.c        12 Sep 2019 11:25:03 -0000
> @@ -330,6 +330,7 @@ tcp_pipe_reset_timeout(struct xfrd_tcp_p
>       tv.tv_usec = 0;
>       if(tp->handler_added)
>               event_del(&tp->handler);
> +     memset(&tp->handler, 0, sizeof(tp->handler));
>       event_set(&tp->handler, fd, EV_PERSIST|EV_TIMEOUT|EV_READ|
>               (tp->tcp_send_first?EV_WRITE:0), xfrd_handle_tcp_pipe, tp);
>       if(event_base_set(xfrd->event_base, &tp->handler) != 0)
> @@ -575,6 +576,7 @@ xfrd_tcp_open(struct xfrd_tcp_set* set, 
>       /* set the tcp pipe event */
>       if(tp->handler_added)
>               event_del(&tp->handler);
> +     memset(&tp->handler, 0, sizeof(tp->handler));
>       event_set(&tp->handler, fd, EV_PERSIST|EV_TIMEOUT|EV_READ|EV_WRITE,
>               xfrd_handle_tcp_pipe, tp);
>       if(event_base_set(xfrd->event_base, &tp->handler) != 0)
> Index: xfrd.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/xfrd.c,v
> retrieving revision 1.20
> diff -u -p -r1.20 xfrd.c
> --- xfrd.c    10 Dec 2018 16:09:11 -0000      1.20
> +++ xfrd.c    12 Sep 2019 11:25:03 -0000
> @@ -170,6 +170,7 @@ xfrd_init(int socket, struct nsd* nsd, i
>       xfrd->child_timer_added = 0;
>  
>       xfrd->ipc_send_blocked = 0;
> +     memset(&xfrd->ipc_handler, 0, sizeof(xfrd->ipc_handler));
>       event_set(&xfrd->ipc_handler, socket, EV_PERSIST|EV_READ,
>               xfrd_handle_ipc, xfrd);
>       if(event_base_set(xfrd->event_base, &xfrd->ipc_handler) != 0)
> @@ -294,6 +295,7 @@ xfrd_sig_process(void)
>               struct timeval tv;
>               tv.tv_sec = XFRD_CHILD_REAP_TIMEOUT;
>               tv.tv_usec = 0;
> +             memset(&xfrd->child_timer, 0, sizeof(xfrd->child_timer));
>               event_set(&xfrd->child_timer, -1, EV_TIMEOUT,
>                       xfrd_handle_child_timer, xfrd);
>               if(event_base_set(xfrd->event_base, &xfrd->child_timer) != 0)
> @@ -400,6 +402,8 @@ xfrd_shutdown()
>       xfrd_del_tempdir(xfrd->nsd);
>  #ifdef HAVE_SSL
>       daemon_remote_delete(xfrd->nsd->rc); /* ssl-delete secret keys */
> +     if (xfrd->nsd->tls_ctx)
> +             SSL_CTX_free(xfrd->nsd->tls_ctx);
>  #endif
>  #ifdef USE_DNSTAP
>       dt_collector_close(nsd.dt_collector, &nsd);
> @@ -1038,6 +1042,8 @@ xfrd_udp_obtain(xfrd_zone_type* zone)
>               else {
>                       if(zone->event_added)
>                               event_del(&zone->zone_handler);
> +                     memset(&zone->zone_handler, 0,
> +                             sizeof(zone->zone_handler));
>                       event_set(&zone->zone_handler, fd,
>                               EV_PERSIST|EV_READ|EV_TIMEOUT,
>                               xfrd_handle_zone, zone);
> @@ -1174,6 +1180,7 @@ xfrd_set_timer(xfrd_zone_type* zone, tim
>       else    fd = -1;
>       zone->timeout.tv_sec = t;
>       zone->timeout.tv_usec = 0;
> +     memset(&zone->zone_handler, 0, sizeof(zone->zone_handler));
>       event_set(&zone->zone_handler, fd, fl, xfrd_handle_zone, zone);
>       if(event_base_set(xfrd->event_base, &zone->zone_handler) != 0)
>               log_msg(LOG_ERR, "xfrd timer: event_base_set failed");
> @@ -1200,7 +1207,7 @@ xfrd_handle_incoming_soa(xfrd_zone_type*
>       if(zone->soa_disk_acquired && soa->serial == zone->soa_disk.serial)
>       {
>               /* soa in disk has been loaded in memory */
> -             log_msg(LOG_INFO, "zone %s serial %u is updated to %u.",
> +             log_msg(LOG_INFO, "zone %s serial %u is updated to %u",
>                       zone->apex_str, (unsigned)ntohl(zone->soa_nsd.serial),
>                       (unsigned)ntohl(soa->serial));
>               zone->soa_nsd = zone->soa_disk;
> @@ -1324,6 +1331,8 @@ xfrd_udp_release(xfrd_zone_type* zone)
>                               if(fd != -1) {
>                                       if(wz->event_added)
>                                               event_del(&wz->zone_handler);
> +                                     memset(&wz->zone_handler, 0,
> +                                             sizeof(wz->zone_handler));
>                                       event_set(&wz->zone_handler, fd,
>                                               EV_READ|EV_TIMEOUT|EV_PERSIST,
>                                               xfrd_handle_zone, wz);
> @@ -2216,6 +2225,7 @@ xfrd_set_reload_timeout()
>               tv.tv_usec = 0;
>               if(tv.tv_sec > xfrd->nsd->options->xfrd_reload_timeout)
>                       tv.tv_sec = xfrd->nsd->options->xfrd_reload_timeout;
> +             memset(&xfrd->reload_handler, 0, sizeof(xfrd->reload_handler));
>               event_set(&xfrd->reload_handler, -1, EV_TIMEOUT,
>                       xfrd_handle_reload, xfrd);
>               if(event_base_set(xfrd->event_base, &xfrd->reload_handler) != 0)
> @@ -2567,6 +2577,7 @@ static void xfrd_write_timer_set()
>               return;
>       tv.tv_sec = xfrd->nsd->options->zonefiles_write;
>       tv.tv_usec = 0;
> +     memset(&xfrd->write_timer, 0, sizeof(xfrd->write_timer));
>       event_set(&xfrd->write_timer, -1, EV_TIMEOUT,
>               xfrd_handle_write_timer, xfrd);
>       if(event_base_set(xfrd->event_base, &xfrd->write_timer) != 0)
> Index: zlexer.lex
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/zlexer.lex,v
> retrieving revision 1.5
> diff -u -p -r1.5 zlexer.lex
> --- zlexer.lex        3 Feb 2018 11:03:51 -0000       1.5
> +++ zlexer.lex        12 Sep 2019 11:25:03 -0000
> @@ -58,6 +58,10 @@ push_parser_state(FILE *input)
>  static void
>  pop_parser_state(void)
>  {
> +     if (parser->filename)
> +             region_recycle(parser->region, (void *)parser->filename,
> +                     strlen(parser->filename)+1);
> +
>       --include_stack_ptr;
>       parser->filename = zparser_stack[include_stack_ptr].filename;
>       parser->line = zparser_stack[include_stack_ptr].line;
> Index: zonec.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/zonec.c,v
> retrieving revision 1.25
> diff -u -p -r1.25 zonec.c
> --- zonec.c   17 May 2018 18:58:40 -0000      1.25
> +++ zonec.c   12 Sep 2019 11:25:03 -0000
> @@ -1409,8 +1409,10 @@ process_rr(void)
>       assert(zone);
>       if (rr->type == TYPE_SOA) {
>               if (rr->owner != zone->apex) {
> +                     char s[MAXDOMAINLEN*5];
> +                     snprintf(s, sizeof(s), "%s", 
> domain_to_string(zone->apex));
>                       zc_error_prev_line(
> -                             "SOA record with invalid domain name");
> +                             "SOA record with invalid domain name, '%s' is 
> not '%s'", domain_to_string(rr->owner), s);
>                       return 0;
>               }
>               if(has_soa(rr->owner)) {
> @@ -1425,10 +1427,12 @@ process_rr(void)
>  
>       if (!domain_is_subdomain(rr->owner, zone->apex))
>       {
> +             char s[MAXDOMAINLEN*5];
> +             snprintf(s, sizeof(s), "%s", domain_to_string(zone->apex));
>               if(zone_is_slave(zone->opts))
> -                     zc_warning_prev_line("out of zone data");
> +                     zc_warning_prev_line("out of zone data: %s is outside 
> the zone for fqdn %s", domain_to_string(rr->owner), s);
>               else
> -                     zc_error_prev_line("out of zone data");
> +                     zc_error_prev_line("out of zone data: %s is outside the 
> zone for fqdn %s", domain_to_string(rr->owner), s);
>               return 0;
>       }
>  
> @@ -1464,6 +1468,16 @@ process_rr(void)
>  
>               /* Discard the duplicates... */
>               if (i < rrset->rr_count) {
> +                     /* add rdatas to recycle bin. */
> +                     size_t i;
> +                     for (i = 0; i < rr->rdata_count; i++) {
> +                             if(!rdata_atom_is_domain(rr->type, i))
> +                                     region_recycle(parser->region, 
> rr->rdatas[i].data,
> +                                             rdata_atom_size(rr->rdatas[i])
> +                                             + sizeof(uint16_t));
> +                     }
> +                     region_recycle(parser->region, rr->rdatas,
> +                             sizeof(rdata_atom_type)*rr->rdata_count);
>                       return 0;
>               }
>               if(rrset->rr_count == 65535) {
> @@ -1731,4 +1745,33 @@ zonec_parse_string(region_type* region, 
>       zonec_desetup_string_parser();
>       parser_flush();
>       return errors;
> +}
> +
> +/** check SSHFP type for failures and emit warnings */
> +void check_sshfp(void)
> +{
> +     uint8_t hash;
> +     uint16_t size;
> +     if(parser->current_rr.rdata_count < 3)
> +             return; /* cannot check it, too few rdata elements */
> +     if(!parser->current_rr.rdatas[0].data ||
> +             !parser->current_rr.rdatas[1].data ||
> +             !parser->current_rr.rdatas[2].data ||
> +             !parser->current_rr.owner)
> +             return; /* cannot check, NULLs (due to earlier errors) */
> +     if(rdata_atom_size(parser->current_rr.rdatas[1]) != 1)
> +             return; /* wrong size of the hash type rdata element */
> +     hash = rdata_atom_data(parser->current_rr.rdatas[1])[0];
> +     size = rdata_atom_size(parser->current_rr.rdatas[2]);
> +     if(hash == 1 && size != 20) {
> +             zc_warning_prev_line("SSHFP %s of type SHA1 has hash of "
> +                     "wrong length, %d bytes, should be 20",
> +                     domain_to_string(parser->current_rr.owner),
> +                     (int)size);
> +     } else if(hash == 2 && size != 32) {
> +             zc_warning_prev_line("SSHFP %s of type SHA256 has hash of "
> +                     "wrong length, %d bytes, should be 32",
> +                     domain_to_string(parser->current_rr.owner),
> +                     (int)size);
> +     }
>  }
> Index: zonec.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/zonec.h,v
> retrieving revision 1.8
> diff -u -p -r1.8 zonec.h
> --- zonec.h   3 Feb 2018 11:03:51 -0000       1.8
> +++ zonec.h   12 Sep 2019 11:25:03 -0000
> @@ -47,7 +47,6 @@ struct zparser {
>       zone_type *current_zone;
>       domain_type *origin;
>       domain_type *prev_dname;
> -     domain_type *default_apex;
>  
>       int error_occurred;
>       unsigned int errors;
> @@ -143,5 +142,7 @@ unsigned int zonec_read(const char *name
>   * The string must end with a newline after the RR. */
>  int zonec_parse_string(region_type* region, domain_table_type* domains,
>       zone_type* zone, char* str, domain_type** parsed, int* num_rrs);
> +/** check SSHFP type for failures and emit warnings */
> +void check_sshfp(void);
>  
>  #endif /* _ZONEC_H_ */
> Index: zparser.y
> ===================================================================
> RCS file: /cvs/src/usr.sbin/nsd/zparser.y,v
> retrieving revision 1.20
> diff -u -p -r1.20 zparser.y
> --- zparser.y 10 Dec 2018 16:09:11 -0000      1.20
> +++ zparser.y 12 Sep 2019 11:25:03 -0000
> @@ -633,7 +633,7 @@ type_and_rdata:
>      |        T_DLV sp rdata_dlv { if (dlv_warn) { dlv_warn = 0; 
> zc_warning_prev_line("DLV is experimental"); } }
>      |        T_DLV sp rdata_unknown { if (dlv_warn) { dlv_warn = 0; 
> zc_warning_prev_line("DLV is experimental"); } $$ = $1; 
> parse_unknown_rdata($1, $3); }
>      |        T_SSHFP sp rdata_sshfp
> -    |        T_SSHFP sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, 
> $3); }
> +    |        T_SSHFP sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, 
> $3); check_sshfp(); }
>      |        T_RRSIG sp rdata_rrsig
>      |        T_RRSIG sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, 
> $3); }
>      |        T_NSEC sp rdata_nsec
> @@ -906,6 +906,7 @@ rdata_sshfp:      STR sp STR sp str_sp_seq tr
>           zadd_rdata_wireformat(zparser_conv_byte(parser->region, $1.str)); 
> /* alg */
>           zadd_rdata_wireformat(zparser_conv_byte(parser->region, $3.str)); 
> /* fp type */
>           zadd_rdata_wireformat(zparser_conv_hex(parser->region, $5.str, 
> $5.len)); /* hash */
> +         check_sshfp();
>      }
>      ;
>  
> @@ -1020,6 +1021,10 @@ rdata_ipsec_base: STR sp STR sp STR sp d
>                               if(parser->origin == error_domain) {
>                                       zc_error("cannot concatenate origin to 
> domain name, because origin failed to parse");
>                                       break;
> +                             } else if(name->name_size + 
> domain_dname(parser->origin)->name_size - 1 > MAXDOMAINLEN) {
> +                                     zc_error("ipsec gateway name exceeds %d 
> character limit",
> +                                             MAXDOMAINLEN);
> +                                     break;
>                               }
>                               name = dname_concatenate(parser->rr_region, 
> name, 
>                                       domain_dname(parser->origin));
> @@ -1157,7 +1162,6 @@ zparser_create(region_type *region, regi
>       result->current_zone = NULL;
>       result->origin = NULL;
>       result->prev_dname = NULL;
> -     result->default_apex = NULL;
>  
>       result->temporary_rdatas = (rdata_atom_type *) region_alloc_array(
>               result->region, MAXRDATALEN, sizeof(rdata_atom_type));
> @@ -1181,7 +1185,6 @@ zparser_init(const char *filename, uint3
>       parser->current_zone = NULL;
>       parser->origin = domain_table_insert(parser->db->domains, origin);
>       parser->prev_dname = parser->origin;
> -     parser->default_apex = parser->origin;
>       parser->error_occurred = 0;
>       parser->errors = 0;
>       parser->line = 1;
> 


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

  • NSD 4.2.2 Stuart Henderson
    • Re: NSD 4.2.2 Florian Obser

Reply via email to