Highlights: reallocarray, various fixes for zone file parsing. I haven't
added the compat file for reallocarray as we don't need it (we can remove
most other compat files but that's not part of this diff).

Comments, OK?


NSD 4.1.3:

Features

    nsd-control addzones and delzones read list of zones from stdin.
    hmac sha224, sha384 and sha512 support, patch from David Gwynne.
    max-interfaces raised to 32.

Bugfixes

    Fix #665: when removing subdomain, nsd does not reparse parent zone.
    Fix task and zonestat files to be stored in a subdirectory in tmp to stop 
privilege elevation.
    Fix crash in zone parser for relative dname after error in origin.
    Fix that formerrors are ratelimited.

NSD 4.1.2:

Features

    Incoming notifies have serial number logged (at verbosity 1).

Bugfixes

    Remove some duplicate header includes (from Brad Smith).
    Fix tcp waiting list for zone transfers where the bind and connect calls 
fail.
    Fix segfault in zone reader on invalid input. (thanks John Van de 
Meulebrouck Brendgard)
    Fix segfault on double origin in zone reader (thanks John Van de 
Meulebrouck Brendgard).
    Fix b64pton out of bounds error on invalid zonefile input. (thanks John Van 
de Meulebrouck Brendgard)
    Fix origin directive from unused old value and subdomain parser failure, 
reported by John Van de Meulebrouck Brendgard.
    Fix use after free after zonefile syntax error followed by ttl or origin 
directive, reported by John Van de Meulebrouck Brendgard.
    Fix syntax error followed by too many TXT elements parse crash reported by 
John Van de Meulebrouck Brendgard.
    Fix buffer overflow in config parse of domain name, reported by John Van de 
Meulebrouck Brendgard.
    Use reallocarray for integer overflow protection, patch submitted by 
Loganaden Velvindron.
    Fix allocation integer overflow checks.
    Fix #654: Fix contradiction in notify logging verbosity level.
    Fix #655: Fix contradiction in verbosity for zone transfers.
    Made log message more consistent, changed 'axfr refused' log message to be 
more consistent with other messages. Also notify refused.
    verbosity 2 logs axfr refused and notify refused. verbosity 1 contains less 
log messages.


Index: Makefile.in
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/Makefile.in,v
retrieving revision 1.16
diff -u -p -r1.16 Makefile.in
--- Makefile.in 16 Sep 2014 17:01:38 -0000      1.16
+++ Makefile.in 16 Jul 2015 16:34:43 -0000
@@ -228,6 +228,9 @@ malloc.o:   $(srcdir)/compat/malloc.c
 pselect.o:     $(srcdir)/compat/pselect.c
        $(COMPILE) -c $(srcdir)/compat/pselect.c
 
+reallocarray.o:        $(srcdir)/compat/reallocarray.c
+       $(COMPILE) -c $(srcdir)/compat/reallocarray.c
+
 fake-rfc2553.o:        $(srcdir)/compat/fake-rfc2553.c
        $(COMPILE) -c $(srcdir)/compat/fake-rfc2553.c
 
@@ -373,7 +376,7 @@ namedb.o: $(srcdir)/namedb.c config.h $(
  $(srcdir)/util.h $(srcdir)/dns.h $(srcdir)/radtree.h $(srcdir)/rbtree.h 
$(srcdir)/nsec3.h
 netio.o: $(srcdir)/netio.c config.h $(srcdir)/netio.h 
$(srcdir)/region-allocator.h $(srcdir)/util.h
 nsd.o: $(srcdir)/nsd.c config.h $(srcdir)/nsd.h $(srcdir)/dns.h 
$(srcdir)/edns.h $(srcdir)/buffer.h $(srcdir)/region-allocator.h \
- $(srcdir)/util.h $(srcdir)/options.h $(srcdir)/rbtree.h $(srcdir)/tsig.h 
$(srcdir)/dname.h $(srcdir)/remote.h
+ $(srcdir)/util.h $(srcdir)/options.h $(srcdir)/rbtree.h $(srcdir)/tsig.h 
$(srcdir)/dname.h $(srcdir)/remote.h $(srcdir)/xfrd-disk.h
 nsd-checkconf.o: $(srcdir)/nsd-checkconf.c config.h $(srcdir)/tsig.h 
$(srcdir)/buffer.h \
  $(srcdir)/region-allocator.h $(srcdir)/util.h $(srcdir)/dname.h 
$(srcdir)/options.h $(srcdir)/rbtree.h $(srcdir)/rrl.h $(srcdir)/query.h \
  $(srcdir)/namedb.h $(srcdir)/dns.h $(srcdir)/radtree.h $(srcdir)/nsd.h 
$(srcdir)/edns.h $(srcdir)/packet.h
@@ -456,6 +459,7 @@ malloc.o: $(srcdir)/compat/malloc.c
 memcmp.o: $(srcdir)/compat/memcmp.c config.h
 memmove.o: $(srcdir)/compat/memmove.c config.h
 pselect.o: $(srcdir)/compat/pselect.c config.h
+reallocarray.o: $(srcdir)/compat/reallocarray.c config.h
 snprintf.o: $(srcdir)/compat/snprintf.c config.h
 strlcat.o: $(srcdir)/compat/strlcat.c config.h
 strlcpy.o: $(srcdir)/compat/strlcpy.c config.h
Index: acx_nlnetlabs.m4
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/acx_nlnetlabs.m4,v
retrieving revision 1.1.1.8
diff -u -p -r1.1.1.8 acx_nlnetlabs.m4
--- acx_nlnetlabs.m4    26 Nov 2013 12:50:23 -0000      1.1.1.8
+++ acx_nlnetlabs.m4    16 Jul 2015 16:34:43 -0000
@@ -2,7 +2,8 @@
 # Copyright 2009, Wouter Wijngaards, NLnet Labs.   
 # BSD licensed.
 #
-# Version 26
+# Version 27
+# 2015-03-17 AHX_CONFIG_REALLOCARRAY added
 # 2013-09-19 FLTO help text improved.
 # 2013-07-18 Enable ACX_CHECK_COMPILER_FLAG to test for -Wstrict-prototypes
 # 2013-06-25 FLTO has --disable-flto option.
@@ -1210,6 +1211,16 @@ AC_DEFUN([AHX_CONFIG_GMTIME_R],
 #ifndef HAVE_GMTIME_R
 #define gmtime_r gmtime_r_$1
 struct tm *gmtime_r(const time_t *timep, struct tm *result);
+#endif
+])
+
+dnl provide reallocarray compat prototype.
+dnl $1: unique name for compat code
+AC_DEFUN([AHX_CONFIG_REALLOCARRAY],
+[
+#ifndef HAVE_REALLOCARRAY
+#define reallocarray reallocarray$1
+void* reallocarray(void *ptr, size_t nmemb, size_t size);
 #endif
 ])
 
Index: axfr.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/axfr.c,v
retrieving revision 1.12
diff -u -p -r1.12 axfr.c
--- axfr.c      3 Feb 2015 10:40:01 -0000       1.12
+++ axfr.c      16 Jul 2015 16:34:43 -0000
@@ -176,10 +176,10 @@ answer_axfr_ixfr(struct nsd *nsd, struct
                        if(!zone_opt ||
                           acl_check_incoming(zone_opt->pattern->provide_xfr, 
q, &acl)==-1)
                        {
-                               if (verbosity > 0) {
+                               if (verbosity >= 2) {
                                        char a[128];
                                        addr2str(&q->addr, a, sizeof(a));
-                                       VERBOSITY(1, (LOG_INFO, "axfr for zone 
%s from client %s refused, %s",
+                                       VERBOSITY(2, (LOG_INFO, "axfr for %s 
from %s refused, %s",
                                                dname_to_string(q->qname, 
NULL), a, acl?"blocked":"no acl matches"));
                                }
                                DEBUG(DEBUG_XFRD,1, (LOG_INFO, "axfr refused, 
%s",
Index: config.h.in
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/config.h.in,v
retrieving revision 1.17
diff -u -p -r1.17 config.h.in
--- config.h.in 3 Feb 2015 10:40:01 -0000       1.17
+++ config.h.in 16 Jul 2015 16:34:43 -0000
@@ -85,12 +85,6 @@
 /* Define to 1 if you have the <event.h> header file. */
 #undef HAVE_EVENT_H
 
-/* Define to 1 if you have the `EVP_sha1' function. */
-#undef HAVE_EVP_SHA1
-
-/* Define to 1 if you have the `EVP_sha256' function. */
-#undef HAVE_EVP_SHA256
-
 /* Define to 1 if you have the `ev_default_loop' function. */
 #undef HAVE_EV_DEFAULT_LOOP
 
@@ -203,6 +197,9 @@
 /* Define to 1 if you have the `pwrite' function. */
 #undef HAVE_PWRITE
 
+/* Define to 1 if you have the `reallocarray' function. */
+#undef HAVE_REALLOCARRAY
+
 /* Define if recvmmsg is implemented */
 #undef HAVE_RECVMMSG
 
@@ -356,6 +353,9 @@
 /* Define this to enable IPv6 support. */
 #undef INET6
 
+/* If flex defines yy_current_buffer as a macro */
+#undef LEX_DEFINES_YY_CURRENT_BUFFER
+
 /* Define to the maximum message length to pass to syslog. */
 #undef MAXSYSLOGMSGLEN
 
@@ -741,6 +741,9 @@ size_t strlcat(char *dst, const char *sr
 #endif
 #ifndef HAVE_STRLCPY
 size_t strlcpy(char *dst, const char *src, size_t siz);
+#endif
+#ifndef HAVE_REALLOCARRAY
+void* reallocarray(void *ptr, size_t nmemb, size_t size);
 #endif
 #ifndef HAVE_GETADDRINFO
 #include "compat/fake-rfc2553.h"
Index: configparser.y
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/configparser.y,v
retrieving revision 1.10
diff -u -p -r1.10 configparser.y
--- configparser.y      3 Feb 2015 10:40:01 -0000       1.10
+++ configparser.y      16 Jul 2015 16:34:43 -0000
@@ -209,24 +209,30 @@ server_identity: VAR_IDENTITY STRING
 server_nsid: VAR_NSID STRING
        { 
                unsigned char* nsid = 0;
-               uint16_t nsid_len = 0;
+               size_t nsid_len = 0;
 
                OUTYY(("P(server_nsid:%s)\n", $2));
 
                if (strncasecmp($2, "ascii_", 6) == 0) {
                        nsid_len = strlen($2+6);
-                       cfg_parser->opt->nsid = 
region_alloc(cfg_parser->opt->region, nsid_len*2+1);
-                       hex_ntop((uint8_t*)$2+6, nsid_len, 
(char*)cfg_parser->opt->nsid, nsid_len*2+1);
+                       if(nsid_len < 65535) {
+                               cfg_parser->opt->nsid = 
region_alloc(cfg_parser->opt->region, nsid_len*2+1);
+                               hex_ntop((uint8_t*)$2+6, nsid_len, 
(char*)cfg_parser->opt->nsid, nsid_len*2+1);
+                       } else
+                               yyerror("NSID too long");
                } else if (strlen($2) % 2 != 0) {
                        yyerror("the NSID must be a hex string of an even 
length.");
                } else {
                        nsid_len = strlen($2) / 2;
-                       nsid = xalloc(nsid_len);
-                       if (hex_pton($2, nsid, nsid_len) == -1)
-                               yyerror("hex string cannot be parsed in NSID.");
-                       else
-                               cfg_parser->opt->nsid = 
region_strdup(cfg_parser->opt->region, $2);
-                       free(nsid);
+                       if(nsid_len < 65535) {
+                               nsid = xalloc(nsid_len);
+                               if (hex_pton($2, nsid, nsid_len) == -1)
+                                       yyerror("hex string cannot be parsed in 
NSID.");
+                               else
+                                       cfg_parser->opt->nsid = 
region_strdup(cfg_parser->opt->region, $2);
+                               free(nsid);
+                       } else
+                               yyerror("NSID too long");
                }
        }
        ;
Index: configure
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/configure,v
retrieving revision 1.21
diff -u -p -r1.21 configure
--- configure   3 Feb 2015 10:40:02 -0000       1.21
+++ configure   16 Jul 2015 16:34:43 -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.1.
+# Generated by GNU Autoconf 2.69 for NSD 4.1.3.
 #
 # Report bugs to <[email protected]>.
 #
@@ -580,8 +580,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='NSD'
 PACKAGE_TARNAME='nsd'
-PACKAGE_VERSION='4.1.1'
-PACKAGE_STRING='NSD 4.1.1'
+PACKAGE_VERSION='4.1.3'
+PACKAGE_STRING='NSD 4.1.3'
 PACKAGE_BUGREPORT='[email protected]'
 PACKAGE_URL=''
 
@@ -1280,7 +1280,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.1 to adapt to many kinds of systems.
+\`configure' configures NSD 4.1.3 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1341,7 +1341,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of NSD 4.1.1:";;
+     short | recursive ) echo "Configuration of NSD 4.1.3:";;
    esac
   cat <<\_ACEOF
 
@@ -1478,7 +1478,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-NSD configure 4.1.1
+NSD configure 4.1.3
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2187,7 +2187,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.1, which was
+It was created by NSD $as_me 4.1.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -4936,6 +4936,30 @@ done
 test -n "$YACC" || YACC="yacc"
 
 
+if test "$LEX" != ":" -a "$LEX" != ""; then
+  # Check if lex defines yy_current_buffer, because 2.4.6 and older use it,
+  # but later could define it as a macro and then we should not redefine it.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if lex defines 
yy_current_buffer" >&5
+$as_echo_n "checking if lex defines yy_current_buffer... " >&6; }
+  cat <<EOF >conftest.lex
+%%
+EOF
+  $LEX -i -t conftest.lex >> conftest.c
+  if grep "^#define yy_current_buffer" conftest.c >/dev/null; then
+
+cat >>confdefs.h <<_ACEOF
+#define LEX_DEFINES_YY_CURRENT_BUFFER 1
+_ACEOF
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  else
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  fi
+  rm -f conftest.lex conftest.c
+fi
+
 
 
 
@@ -8072,6 +8096,20 @@ 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
+
+else
+  case " $LIBOBJS " in
+  *" reallocarray.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS reallocarray.$ac_objext"
+ ;;
+esac
+
+fi
+
+
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pselect prototype in 
sys/select.h" >&5
 $as_echo_n "checking for pselect prototype in sys/select.h... " >&6; }
@@ -8199,7 +8237,7 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-max_ips=16
+max_ips=32
 
 # Check whether --with-max_ips was given.
 if test "${with_max_ips+set}" = set; then :
@@ -8553,18 +8591,6 @@ else
 
 fi
 
-               for ac_func in EVP_sha1 EVP_sha256
-do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
         fi
 
     fi
@@ -9396,7 +9422,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.1, which was
+This file was extended by NSD $as_me 4.1.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -9458,7 +9484,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.1
+NSD config.status 4.1.3
 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.20
diff -u -p -r1.20 configure.ac
--- configure.ac        3 Feb 2015 10:40:02 -0000       1.20
+++ configure.ac        16 Jul 2015 16:34:43 -0000
@@ -4,7 +4,7 @@ dnl
 
 sinclude(acx_nlnetlabs.m4)
 
-AC_INIT(NSD,4.1.1,[email protected])
+AC_INIT(NSD,4.1.3,[email protected])
 AC_CONFIG_HEADER([config.h])
 
 CFLAGS="$CFLAGS"
@@ -168,6 +168,23 @@ AC_PROG_INSTALL
 AC_PROG_LEX
 AC_PROG_YACC
 
+if test "$LEX" != ":" -a "$LEX" != ""; then
+  # Check if lex defines yy_current_buffer, because 2.4.6 and older use it,
+  # but later could define it as a macro and then we should not redefine it.
+  AC_MSG_CHECKING(if lex defines yy_current_buffer)
+  cat <<EOF >conftest.lex
+%%
+EOF
+  $LEX -i -t conftest.lex >> conftest.c
+  if grep "^#define yy_current_buffer" conftest.c >/dev/null; then
+         AC_DEFINE_UNQUOTED(LEX_DEFINES_YY_CURRENT_BUFFER, 1, [If flex defines 
yy_current_buffer as a macro])
+       AC_MSG_RESULT(yes)
+  else
+       AC_MSG_RESULT(no)
+  fi
+  rm -f conftest.lex conftest.c
+fi
+
 AC_DEFUN([AC_CHECK_FORMAT_ATTRIBUTE],
 [AC_REQUIRE([AC_PROG_CC])
 AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "format" 
attribute)
@@ -320,7 +337,6 @@ AC_DEFUN([CHECK_SSL], [
             AC_CHECK_LIB(crypto, HMAC_CTX_init,, [
                     AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 
or higher is required])
                 ])
-               AC_CHECK_FUNCS([EVP_sha1 EVP_sha256])
         fi
         AC_SUBST(HAVE_SSL)
     fi
@@ -642,6 +658,7 @@ AC_REPLACE_FUNCS(b64_pton)
 AC_REPLACE_FUNCS(b64_ntop)
 AC_REPLACE_FUNCS(pselect)
 AC_REPLACE_FUNCS(memmove)
+AC_REPLACE_FUNCS(reallocarray)
 
 AC_MSG_CHECKING(for pselect prototype in sys/select.h)
 AC_EGREP_HEADER([[^a-zA-Z_]*pselect[^a-zA-Z_]], sys/select.h, 
AC_DEFINE(HAVE_PSELECT_PROTO, 1, 
@@ -688,7 +705,7 @@ AC_DEFINE_UNQUOTED([FACILITY], $facility
 dnl
 dnl Determine the maximum number of ip-addresses that are allowed
 dnl
-max_ips=16
+max_ips=32
 AC_ARG_WITH([max_ips],
        AC_HELP_STRING([--with-max-ips=number], [Limit on the number of 
ip-addresses that may be specified]),
        [max_ips=$withval])
@@ -957,6 +974,9 @@ size_t strlcat(char *dst, const char *sr
 #endif
 #ifndef HAVE_STRLCPY
 size_t strlcpy(char *dst, const char *src, size_t siz);
+#endif
+#ifndef HAVE_REALLOCARRAY
+void* reallocarray(void *ptr, size_t nmemb, size_t size);
 #endif
 #ifndef HAVE_GETADDRINFO
 #include "compat/fake-rfc2553.h"
Index: configyyrename.h
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/configyyrename.h,v
retrieving revision 1.1.1.4
diff -u -p -r1.1.1.4 configyyrename.h
--- configyyrename.h    26 Nov 2013 12:50:18 -0000      1.1.1.4
+++ configyyrename.h    16 Jul 2015 16:34:43 -0000
@@ -104,7 +104,9 @@
 #define yy_accept c__accept
 #define yy_c_buf_p c__c_buf_p
 #define yy_chk c__chk
-#define yy_current_buffer c__current_buffer
+#ifndef LEX_DEFINES_YY_CURRENT_BUFFER
+#  define yy_current_buffer c__current_buffer
+#endif
 #define yy_def c__def
 #define yy_did_buffer_switch_on_eof c__did_buffer_switch_on_eof
 #define yy_ec c__ec
Index: dbaccess.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/dbaccess.c,v
retrieving revision 1.1.1.12
diff -u -p -r1.1.1.12 dbaccess.c
--- dbaccess.c  3 Feb 2015 10:24:32 -0000       1.1.1.12
+++ dbaccess.c  16 Jul 2015 16:34:43 -0000
@@ -156,8 +156,8 @@ read_rrset(udb_base* udb, namedb_type* d
        rrset = (rrset_type *) region_alloc(db->region, sizeof(rrset_type));
        rrset->zone = zone;
        rrset->rr_count = calculate_rr_count(udb, urrset);
-       rrset->rrs = (rr_type *) region_alloc(
-               db->region, rrset->rr_count * sizeof(rr_type));
+       rrset->rrs = (rr_type *) region_alloc_array(
+               db->region, rrset->rr_count, sizeof(rr_type));
        /* add the RRs */
        udb_ptr_new(&urr, udb, &RRSET(urrset)->rrs);
        for(i=0; i<rrset->rr_count; i++) {
@@ -288,6 +288,7 @@ namedb_zone_delete(namedb_type* db, zone
        /* see if apex can be deleted */
        if(zone->apex) {
                zone->apex->usage --;
+               zone->apex->is_apex = 0;
                if(zone->apex->usage == 0) {
                        /* delete the apex, possibly */
                        domain_table_deldomain(db, zone->apex);
@@ -607,7 +608,7 @@ namedb_read_zonefile(struct nsd* nsd, st
                        zone->logstr = NULL;
                }
        } else {
-               VERBOSITY(1, (LOG_INFO, "zone %s read with no errors",
+               VERBOSITY(1, (LOG_INFO, "zone %s read with success",
                        zone->opts->name));
                zone->is_ok = 1;
                zone->is_changed = 0;
Index: difffile.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/difffile.c,v
retrieving revision 1.3
diff -u -p -r1.3 difffile.c
--- difffile.c  3 Feb 2015 10:40:02 -0000       1.3
+++ difffile.c  16 Jul 2015 16:34:43 -0000
@@ -702,8 +702,8 @@ delete_RR(namedb_type* db, const dname_t
                                rrset->rrs[rrnum] = 
rrset->rrs[rrset->rr_count-1];
                        memset(&rrset->rrs[rrset->rr_count-1], 0, 
sizeof(rr_type));
                        /* realloc the rrs array one smaller */
-                       rrset->rrs = region_alloc_init(db->region, rrs_orig,
-                               sizeof(rr_type) * (rrset->rr_count-1));
+                       rrset->rrs = region_alloc_array_init(db->region, 
rrs_orig,
+                               (rrset->rr_count-1), sizeof(rr_type));
                        if(!rrset->rrs) {
                                log_msg(LOG_ERR, "out of memory, %s:%d", 
__FILE__, __LINE__);
                                exit(1);
@@ -791,11 +791,16 @@ add_RR(namedb_type* db, const dname_type
                *softfail = 1;
                return 1;
        }
+       if(rrset->rr_count == 65535) {
+               log_msg(LOG_ERR, "diff: too many RRs at %s",
+                       dname_to_string(dname,0));
+               return 0;
+       }
 
        /* re-alloc the rrs and add the new */
        rrs_old = rrset->rrs;
-       rrset->rrs = region_alloc(db->region,
-               (rrset->rr_count+1) * sizeof(rr_type));
+       rrset->rrs = region_alloc_array(db->region,
+               (rrset->rr_count+1), sizeof(rr_type));
        if(!rrset->rrs) {
                log_msg(LOG_ERR, "out of memory, %s:%d", __FILE__, __LINE__);
                exit(1);
@@ -1403,7 +1408,7 @@ apply_ixfr_for_zone(nsd_type* nsd, zone_
                        double elapsed = (double)(time_end_0 - time_start_0)+
                                (double)((double)time_end_1
                                -(double)time_start_1) / 1000000.0;
-                       VERBOSITY(2, (LOG_INFO, "zone %s %s of %d bytes in %g 
seconds",
+                       VERBOSITY(1, (LOG_INFO, "zone %s %s of %d bytes in %g 
seconds",
                                zone_buf, log_buf, num_bytes, elapsed));
                }
        }
Index: dname.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/dname.c,v
retrieving revision 1.10
diff -u -p -r1.10 dname.c
--- dname.c     3 Feb 2015 10:40:02 -0000       1.10
+++ dname.c     16 Jul 2015 16:34:43 -0000
@@ -63,7 +63,7 @@ dname_make(region_type *region, const ui
        result = (dname_type *) region_alloc(
                region,
                (sizeof(dname_type)
-                + (label_count + name_size) * sizeof(uint8_t)));
+                + (((size_t)label_count) + ((size_t)name_size)) * 
sizeof(uint8_t)));
        result->name_size = name_size;
        result->label_count = label_count;
        memcpy((uint8_t *) dname_label_offsets(result),
@@ -244,6 +244,9 @@ int dname_parse_wire(uint8_t* dname, con
        }
 
        /* Add root label.  */
+       if (h - dname >= MAXDOMAINLEN) {
+               return 0;
+       }
        *h = 0;
 
        return p-dname;
@@ -482,7 +485,7 @@ dname_replace(region_type* region,
                return NULL;
 
        res = (dname_type*)region_alloc(region, sizeof(dname_type) +
-               (x_labels+dest->label_count + x_len+dest->name_size)
+               (x_labels+((int)dest->label_count) + 
x_len+((int)dest->name_size))
                *sizeof(uint8_t));
        res->name_size = x_len+dest->name_size;
        res->label_count = x_labels+dest->label_count;
Index: dname.h
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/dname.h,v
retrieving revision 1.1.1.4
diff -u -p -r1.1.1.4 dname.h
--- dname.h     26 Nov 2013 12:50:19 -0000      1.1.1.4
+++ dname.h     16 Jul 2015 16:34:44 -0000
@@ -217,7 +217,7 @@ static inline size_t
 dname_total_size(const dname_type *dname)
 {
        return (sizeof(dname_type)
-               + ((dname->label_count + dname->name_size)
+               + ((((size_t)dname->label_count) + ((size_t)dname->name_size))
                   * sizeof(uint8_t)));
 }
 
Index: namedb.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/namedb.c,v
retrieving revision 1.2
diff -u -p -r1.2 namedb.c
--- namedb.c    18 Dec 2014 23:26:13 -0000      1.2
+++ namedb.c    16 Jul 2015 16:34:44 -0000
@@ -443,19 +443,6 @@ domain_table_insert(domain_table_type* t
        return result;
 }
 
-int
-domain_table_iterate(domain_table_type* table,
-                   domain_table_iterator_type iterator,
-                   void* user_data)
-{
-       int error = 0;
-       struct radnode* n;
-       for(n = radix_first(table->nametree); n; n = radix_next(n)) {
-               error += iterator((domain_type*)n->elem, user_data);
-       }
-       return error;
-}
-
 domain_type *domain_previous_existing_child(domain_type* domain)
 {
        domain_type* parent = domain->parent;
Index: namedb.h
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/namedb.h,v
retrieving revision 1.3
diff -u -p -r1.3 namedb.h
--- namedb.h    3 Feb 2015 10:40:02 -0000       1.3
+++ namedb.h    16 Jul 2015 16:34:44 -0000
@@ -223,16 +223,6 @@ void prehash_del(domain_table_type* tabl
 int domain_is_prehash(domain_table_type* table, domain_type* domain);
 
 /*
- * Iterate over all the domain names in the domain tree.
- */
-typedef int (*domain_table_iterator_type)(domain_type *node,
-                                          void *user_data);
-
-int domain_table_iterate(domain_table_type* table,
-                         domain_table_iterator_type iterator,
-                         void* user_data);
-
-/*
  * Add an RRset to the specified domain.  Updates the is_existing flag
  * as required.
  */
Index: nsd-checkconf.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/nsd-checkconf.8.in,v
retrieving revision 1.15
diff -u -p -r1.15 nsd-checkconf.8.in
--- nsd-checkconf.8.in  3 Feb 2015 10:40:02 -0000       1.15
+++ nsd-checkconf.8.in  16 Jul 2015 16:34:44 -0000
@@ -1,4 +1,4 @@
-.TH "nsd\-checkconf" "8" "Feb  3, 2015" "NLnet Labs" "nsd 4.1.1"
+.TH "nsd\-checkconf" "8" "Jun 23, 2015" "NLnet Labs" "nsd 4.1.3"
 .\" 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.11
diff -u -p -r1.11 nsd-checkconf.c
--- nsd-checkconf.c     3 Feb 2015 10:40:02 -0000       1.11
+++ nsd-checkconf.c     16 Jul 2015 16:34:44 -0000
@@ -520,7 +520,7 @@ static void
 append_trailing_slash(const char** dirname, region_type* region)
 {
        int l = strlen(*dirname);
-       if (l>0 && (*dirname)[l-1] != '/') {
+       if (l>0 && (*dirname)[l-1] != '/' && l < 0xffffff) {
                char *dirname_slash = region_alloc(region, l+2);
                memcpy(dirname_slash, *dirname, l+1);
                strlcat(dirname_slash, "/", l+2);
Index: nsd-checkzone.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/nsd-checkzone.8.in,v
retrieving revision 1.1.1.2
diff -u -p -r1.1.1.2 nsd-checkzone.8.in
--- nsd-checkzone.8.in  3 Feb 2015 10:24:35 -0000       1.1.1.2
+++ nsd-checkzone.8.in  16 Jul 2015 16:34:44 -0000
@@ -1,4 +1,4 @@
-.TH "nsd\-checkzone" "8" "Feb  3, 2015" "NLnet Labs" "nsd 4.1.1"
+.TH "nsd\-checkzone" "8" "Jun 23, 2015" "NLnet Labs" "nsd 4.1.3"
 .\" Copyright (c) 2014, NLnet Labs. All rights reserved.
 .\" See LICENSE for the license.
 .SH "NAME"
Index: nsd-control-setup.sh.in
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/nsd-control-setup.sh.in,v
retrieving revision 1.1.1.2
diff -u -p -r1.1.1.2 nsd-control-setup.sh.in
--- nsd-control-setup.sh.in     13 Mar 2014 02:00:29 -0000      1.1.1.2
+++ nsd-control-setup.sh.in     16 Jul 2015 16:34:44 -0000
@@ -46,7 +46,7 @@ CLIENTNAME=nsd-control
 DAYS=7200
 
 # size of keys in bits
-BITS=1536
+BITS=3072
 
 # hash algorithm
 HASH=sha256
Index: nsd-control.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/nsd-control.8.in,v
retrieving revision 1.3
diff -u -p -r1.3 nsd-control.8.in
--- nsd-control.8.in    3 Feb 2015 10:40:02 -0000       1.3
+++ nsd-control.8.in    16 Jul 2015 16:34:44 -0000
@@ -1,4 +1,4 @@
-.TH "nsd\-control" "8" "Feb  3, 2015" "NLnet Labs" "nsd 4.1.1"
+.TH "nsd\-control" "8" "Jun 23, 2015" "NLnet Labs" "nsd 4.1.3"
 .\" Copyright (c) 2011, NLnet Labs. All rights reserved.
 .\" See LICENSE for the license.
 .SH "NAME"
@@ -87,6 +87,14 @@ had a zonefile, this remains (but may be
 inside nsd.conf itself cannot be removed this way because the daemon
 does not write to the nsd.conf file, you need to add such zones to the
 zonelist file to be able to delete them with the delzone command.
+.TP
+.B addzones
+Add zones read from stdin of nsd\-control.  Input is read per line,
+with name space patternname on a line.  For bulk additions.
+.TP
+.B delzones
+Remove zones read from stdin of nsd\-control.  Input is one name per line.
+For bulk removals.
 .TP
 .B write [<zone>]
 Write zonefiles to disk, or the given zonefile to disk.  Zones that have
Index: nsd-control.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/nsd-control.c,v
retrieving revision 1.1.1.3
diff -u -p -r1.1.1.3 nsd-control.c
--- nsd-control.c       3 Feb 2015 10:24:29 -0000       1.1.1.3
+++ nsd-control.c       16 Jul 2015 16:34:44 -0000
@@ -84,6 +84,8 @@ usage()
        printf("  stats_noreset                 peek at statistics\n");
        printf("  addzone <name> <pattern>      add a new zone\n");
        printf("  delzone <name>                remove a zone\n");
+       printf("  addzones                      add zone list on stdin {name 
space pattern newline}\n");
+       printf("  delzones                      remove zone list on stdin {name 
newline}\n");
        printf("  write [<zone>]                write changed zonefiles to 
disk\n");
        printf("  notify [<zone>]               send NOTIFY messages to slave 
servers\n");
        printf("  transfer [<zone>]             try to update slave zones to 
newer serial\n");
@@ -253,10 +255,14 @@ setup_ssl(SSL_CTX* ctx, int fd)
 static void
 send_file(SSL* ssl, FILE* in, char* buf, size_t sz)
 {
+       char e[] = {0x04, 0x0a};
        while(fgets(buf, (int)sz, in)) {
                if(SSL_write(ssl, buf, (int)strlen(buf)) <= 0)
                        ssl_err("could not SSL_write contents");
        }
+       /* send end-of-file marker */
+       if(SSL_write(ssl, e, (int)sizeof(e)) <= 0)
+               ssl_err("could not SSL_write end-of-file marker");
 }
 
 /** send command and display result */
@@ -281,8 +287,9 @@ go_cmd(SSL* ssl, int argc, char* argv[])
        if(SSL_write(ssl, newline, (int)strlen(newline)) <= 0)
                ssl_err("could not SSL_write");
 
-       /* TODO remove or use file upload */
-       if(argc == 1 && strcmp(argv[0], "load_cache") == 0) {
+       /* send contents to server */
+       if(argc == 1 && (strcmp(argv[0], "addzones") == 0 ||
+               strcmp(argv[0], "delzones") == 0)) {
                send_file(ssl, stdin, buf, sizeof(buf));
        }
 
Index: nsd.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/nsd.c,v
retrieving revision 1.21
diff -u -p -r1.21 nsd.c
--- nsd.c       3 Feb 2015 10:40:02 -0000       1.21
+++ nsd.c       16 Jul 2015 16:34:44 -0000
@@ -44,6 +44,7 @@
 #include "options.h"
 #include "tsig.h"
 #include "remote.h"
+#include "xfrd-disk.h"
 
 /* The server handler... */
 struct nsd nsd;
@@ -132,7 +133,7 @@ static void
 append_trailing_slash(const char** dirname, region_type* region)
 {
        int l = strlen(*dirname);
-       if (l>0 && (*dirname)[l-1] != '/') {
+       if (l>0 && (*dirname)[l-1] != '/' && l < 0xffffff) {
                char *dirname_slash = region_alloc(region, l+2);
                memcpy(dirname_slash, *dirname, l+1);
                strlcat(dirname_slash, "/", l+2);
@@ -742,8 +743,8 @@ main(int argc, char *argv[])
 #endif /* defined(INET6) */
 
        /* Number of child servers to fork.  */
-       nsd.children = (struct nsd_child *) region_alloc(
-               nsd.region, nsd.child_count * sizeof(struct nsd_child));
+       nsd.children = (struct nsd_child *) region_alloc_array(
+               nsd.region, nsd.child_count, sizeof(struct nsd_child));
        for (i = 0; i < nsd.child_count; ++i) {
                nsd.children[i].kind = NSD_SERVER_BOTH;
                nsd.children[i].pid = -1;
@@ -1106,6 +1107,7 @@ main(int argc, char *argv[])
                        nsd.username));
        }
 #endif /* HAVE_GETPWNAM */
+       xfrd_make_tempdir(&nsd);
 #ifdef USE_ZONE_STATS
        options_zonestatnames_create(nsd.options);
        server_zonestat_alloc(&nsd);
Index: nsd.conf.5.in
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/nsd.conf.5.in,v
retrieving revision 1.15
diff -u -p -r1.15 nsd.conf.5.in
--- nsd.conf.5.in       3 Feb 2015 10:40:02 -0000       1.15
+++ nsd.conf.5.in       16 Jul 2015 16:34:44 -0000
@@ -1,4 +1,4 @@
-.TH "nsd.conf" "5" "Feb  3, 2015" "NLnet Labs" "nsd 4.1.1"
+.TH "nsd.conf" "5" "Jun 23, 2015" "NLnet Labs" "nsd 4.1.3"
 .\" Copyright (c) 2001\-2008, NLnet Labs. All rights reserved.
 .\" See LICENSE for the license.
 .SH "NAME"
@@ -299,6 +299,16 @@ once per the number of seconds. The defa
 This value specifies the verbosity level for (non\-debug) logging. 
 Default is 0. 1 gives more information about incoming notifies and
 zone transfers. 2 lists soft warnings that are encountered.
+.IP
+Verbosity 0 will print warnings and errors, and other events that are
+important to keep NSD running.
+.IP
+Verbosity 1 prints additionally messages of interest.  Successful notifies,
+successful incoming zone transfer (the zone is updated), failed incoming
+zone transfers or the inability to process zone updates.
+.IP
+Verbosity 2 prints additionally soft errors, like connection resets over TCP.
+And notify refusal, and axfr request refusals.
 .TP
 .B hide\-version:\fR <yes or no>
 Prevent NSD from replying with the version string on CHAOS class 
Index: nsd.h
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/nsd.h,v
retrieving revision 1.1.1.9
diff -u -p -r1.1.1.9 nsd.h
--- nsd.h       3 Feb 2015 10:24:28 -0000       1.1.1.9
+++ nsd.h       16 Jul 2015 16:34:44 -0000
@@ -248,6 +248,10 @@ struct     nsd
        /* current zonestat array to use */
        struct nsdst* zonestatnow;
 #endif /* BIND8_STATS */
+       /* ratelimit for errors, time value */
+       time_t err_limit_time;
+       /* ratelimit for errors, packet count */
+       unsigned int err_limit_count;
 
        struct nsd_options* options;
 };
@@ -272,6 +276,8 @@ struct event_base* nsd_child_event_base(
 /* extra domain numbers for temporary domains */
 #define EXTRA_DOMAIN_NUMBERS 1024
 #define SLOW_ACCEPT_TIMEOUT 2 /* in seconds */
+/* ratelimit for error responses */
+#define ERROR_RATELIMIT 100 /* qps */
 /* allocate zonestat structures */
 void server_zonestat_alloc(struct nsd* nsd);
 /* remap the mmaps for zonestat isx, to bytesize sz.  Caller has to set
Index: packet.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/packet.c,v
retrieving revision 1.1.1.7
diff -u -p -r1.1.1.7 packet.c
--- packet.c    16 Sep 2014 16:54:02 -0000      1.1.1.7
+++ packet.c    16 Jul 2015 16:34:44 -0000
@@ -342,3 +342,57 @@ int packet_read_query_section(buffer_typ
        *qclass = buffer_read_u16(packet);
        return 1;
 }
+
+int packet_find_notify_serial(buffer_type *packet, uint32_t* serial)
+{
+       size_t saved_position = buffer_position(packet);
+       /* count of further RRs after question section */
+       size_t rrcount = ANCOUNT(packet) + NSCOUNT(packet) + ARCOUNT(packet);
+       size_t i;
+       buffer_set_position(packet, QHEADERSZ);
+
+       /* skip all question RRs */
+       for (i = 0; i < QDCOUNT(packet); ++i) {
+               if (!packet_skip_rr(packet, 1)) {
+                       buffer_set_position(packet, saved_position);
+                       return 0;
+               }
+       }
+
+       /* Find the SOA RR */
+       for(i = 0; i < rrcount; i++) {
+               uint16_t rdata_size;
+               if (!packet_skip_dname(packet))
+                       break;
+               /* check length available for type,class,ttl,rdatalen */
+               if (!buffer_available(packet, 10))
+                       break;
+               /* check type, class */
+               if(buffer_read_u16(packet) == TYPE_SOA) {
+                       if(buffer_read_u16(packet) != CLASS_IN)
+                               break;
+                       buffer_skip(packet, 4); /* skip ttl */
+                       rdata_size = buffer_read_u16(packet);
+                       if (!buffer_available(packet, rdata_size))
+                               break;
+                       /* skip two dnames, then serial */
+                       if (!packet_skip_dname(packet) ||
+                               !packet_skip_dname(packet))
+                               break;
+                       if (!buffer_available(packet, 4))
+                               break;
+                       *serial = buffer_read_u32(packet);
+                       buffer_set_position(packet, saved_position);
+                       return 1;
+               }
+               /* continue to next RR */
+               buffer_skip(packet, 6);
+               rdata_size = buffer_read_u16(packet);
+               if (!buffer_available(packet, rdata_size))
+                       break;
+               buffer_skip(packet, rdata_size);
+       }
+       /* failed to find SOA */
+       buffer_set_position(packet, saved_position);
+       return 0;
+}
Index: packet.h
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/packet.h,v
retrieving revision 1.1.1.6
diff -u -p -r1.1.1.6 packet.h
--- packet.h    16 Sep 2014 16:53:59 -0000      1.1.1.6
+++ packet.h    16 Jul 2015 16:34:44 -0000
@@ -196,4 +196,8 @@ int packet_read_query_section(buffer_typ
                        uint16_t* qtype,
                        uint16_t* qclass);
 
+/* read notify SOA serial from packet. buffer position is unmodified on return.
+ * returns false on no-serial found or parse failure. */
+int packet_find_notify_serial(buffer_type *packet, uint32_t* serial);
+
 #endif /* _PACKET_H_ */
Index: query.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/query.c,v
retrieving revision 1.16
diff -u -p -r1.16 query.c
--- query.c     3 Feb 2015 10:40:02 -0000       1.16
+++ query.c     16 Jul 2015 16:34:44 -0000
@@ -146,10 +146,28 @@ query_error (struct query *q, nsd_rc_typ
        return QUERY_PROCESSED;
 }
 
+static int
+query_ratelimit_err(nsd_type* nsd)
+{
+       time_t now = time(NULL);
+       if(nsd->err_limit_time == now) {
+               /* see if limit is exceeded for this second */
+               if(nsd->err_limit_count++ > ERROR_RATELIMIT)
+                       return 1;
+       } else {
+               /* new second, new limits */
+               nsd->err_limit_time = now;
+               nsd->err_limit_count = 1;
+       }
+       return 0;
+}
+
 static query_state_type
-query_formerr (struct query *query)
+query_formerr (struct query *query, nsd_type* nsd)
 {
        int opcode = OPCODE(query->packet);
+       if(query_ratelimit_err(nsd))
+               return QUERY_DISCARDED;
        FLAGS_SET(query->packet, FLAGS(query->packet) & 0x0100U);
                        /* Preserve the RD flag. Clear the rest. */
        OPCODE_SET(query->packet, opcode);
@@ -454,6 +472,18 @@ answer_notify(struct nsd* nsd, struct qu
                                strerror(errno));
                        return query_error(query, NSD_RC_SERVFAIL);
                }
+               if(verbosity >= 1) {
+                       uint32_t serial = 0;
+                       char address[128];
+                       addr2str(&query->addr, address, sizeof(address));
+                       if(packet_find_notify_serial(query->packet, &serial))
+                         VERBOSITY(1, (LOG_INFO, "notify for %s from %s serial 
%u",
+                               dname_to_string(query->qname, NULL), address,
+                               (unsigned)serial));
+                       else
+                         VERBOSITY(1, (LOG_INFO, "notify for %s from %s",
+                               dname_to_string(query->qname, NULL), address));
+               }
 
                /* create notify reply - keep same query contents */
                QR_SET(query->packet);         /* This is an answer.  */
@@ -466,20 +496,14 @@ answer_notify(struct nsd* nsd, struct qu
                pos = buffer_position(query->packet);
                buffer_clear(query->packet);
                buffer_set_position(query->packet, pos);
-               if(verbosity >= 1) {
-                       char address[128];
-                       addr2str(&query->addr, address, sizeof(address));
-                       VERBOSITY(2, (LOG_INFO, "notify for %s from %s",
-                               dname_to_string(query->qname, NULL), address));
-               }
                /* tsig is added in add_additional later (if needed) */
                return QUERY_PROCESSED;
        }
 
-       if (verbosity >= 1) {
+       if (verbosity >= 2) {
                char address[128];
                addr2str(&query->addr, address, sizeof(address));
-               VERBOSITY(1, (LOG_INFO, "notify for zone %s from client %s 
refused, %s%s",
+               VERBOSITY(2, (LOG_INFO, "notify for %s from %s refused, %s%s",
                        dname_to_string(query->qname, NULL),
                        address,
                        why?why->key_name:"no acl matches",
@@ -1291,7 +1315,7 @@ query_process(query_type *q, nsd_type *n
        }
 
        if (RCODE(q->packet) != RCODE_OK || !process_query_section(q)) {
-               return query_formerr(q);
+               return query_formerr(q, nsd);
        }
 
        /* Update statistics.  */
@@ -1303,6 +1327,8 @@ query_process(query_type *q, nsd_type *n
                if (q->opcode == OPCODE_NOTIFY) {
                        return answer_notify(nsd, q);
                } else {
+                       if(query_ratelimit_err(nsd))
+                               return QUERY_DISCARDED;
                        return query_error(q, NSD_RC_IMPL);
                }
        }
@@ -1310,7 +1336,7 @@ query_process(query_type *q, nsd_type *n
        /* Dont bother to answer more than one question at once... */
        if (QDCOUNT(q->packet) != 1) {
                FLAGS_SET(q->packet, 0);
-               return query_formerr(q);
+               return query_formerr(q, nsd);
        }
        /* Ignore settings of flags */
 
@@ -1318,13 +1344,13 @@ query_process(query_type *q, nsd_type *n
           except for IXFR queries. */
        if (ANCOUNT(q->packet) != 0 ||
                (q->qtype!=TYPE_IXFR && NSCOUNT(q->packet) != 0)) {
-               return query_formerr(q);
+               return query_formerr(q, nsd);
        }
        if(q->qtype==TYPE_IXFR && NSCOUNT(q->packet) > 0) {
                int i; /* skip ixfr soa information data here */
                for(i=0; i< NSCOUNT(q->packet); i++)
                        if(!packet_skip_rr(q->packet, 0))
-                               return query_formerr(q);
+                               return query_formerr(q, nsd);
        }
 
        arcount = ARCOUNT(q->packet);
@@ -1340,7 +1366,7 @@ query_process(query_type *q, nsd_type *n
 
                /* see if tsig is before edns record */
                if (!tsig_parse_rr(&q->tsig, q->packet))
-                       return query_formerr(q);
+                       return query_formerr(q, nsd);
                if(q->tsig.status != TSIG_NOT_PRESENT)
                        --arcount;
        }
@@ -1353,20 +1379,20 @@ query_process(query_type *q, nsd_type *n
        if (arcount > 0 && q->tsig.status == TSIG_NOT_PRESENT) {
                /* see if tsig is after the edns record */
                if (!tsig_parse_rr(&q->tsig, q->packet))
-                       return query_formerr(q);
+                       return query_formerr(q, nsd);
                if(q->tsig.status != TSIG_NOT_PRESENT)
                        --arcount;
        }
        /* If more RRs left in Add. Section, FORMERR. */
        if (arcount > 0) {
-               return query_formerr(q);
+               return query_formerr(q, nsd);
        }
 
        /* Do we have any trailing garbage? */
 #ifdef STRICT_MESSAGE_PARSE
        if (buffer_remaining(q->packet) > 0) {
                /* If we're strict.... */
-               return query_formerr(q);
+               return query_formerr(q, nsd);
        }
 #endif
        /* Remove trailing garbage.  */
Index: radtree.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/radtree.c,v
retrieving revision 1.1.1.2
diff -u -p -r1.1.1.2 radtree.c
--- radtree.c   13 Mar 2014 02:00:28 -0000      1.1.1.2
+++ radtree.c   16 Jul 2015 16:34:44 -0000
@@ -189,7 +189,7 @@ radnode_array_grow(struct region* region
        if(ns > 256) ns = 256;
        /* we do not use realloc, because we want to keep the old array
         * in case alloc fails, so that the tree is still usable */
-       a = (struct radsel*)region_alloc(region, ns*sizeof(struct radsel));
+       a = (struct radsel*)region_alloc_array(region, ns, sizeof(struct 
radsel));
        if(!a) return 0;
        assert(n->len <= n->capacity);
        assert(n->capacity < ns);
@@ -670,8 +670,8 @@ static void
 radnode_array_reduce_if_needed(struct region* region, struct radnode* n)
 {
        if(n->len <= n->capacity/2 && n->len != n->capacity) {
-               struct radsel* a = (struct radsel*)region_alloc(region,
-                       sizeof(*a)*n->len);
+               struct radsel* a = (struct radsel*)region_alloc_array(region,
+                       sizeof(*a), n->len);
                if(!a) return;
                memcpy(a, n->array, sizeof(*a)*n->len);
                region_recycle(region, n->array, n->capacity*sizeof(*a));
@@ -953,6 +953,7 @@ struct radnode* radix_last(struct radtre
 
 struct radnode* radix_next(struct radnode* n)
 {
+       if(!n) return NULL;
        if(n->len) {
                /* go down */
                struct radnode* s = radnode_first_in_subtree(n);
@@ -982,6 +983,7 @@ struct radnode* radix_next(struct radnod
 
 struct radnode* radix_prev(struct radnode* n)
 {
+       if(!n) return NULL;
        /* must go up, since all array nodes are after this node */
        while(n->parent) {
                uint8_t idx = n->pidx;
Index: rdata.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/rdata.c,v
retrieving revision 1.10
diff -u -p -r1.10 rdata.c
--- rdata.c     12 Jan 2015 14:36:48 -0000      1.10
+++ rdata.c     16 Jul 2015 16:34:44 -0000
@@ -809,7 +809,7 @@ rdata_wireformat_to_rdata_atoms(region_t
                        }
                        if(is_wirestore) {
                                temp_rdatas[i].data = (uint16_t *) region_alloc(
-                                       region, sizeof(uint16_t) + 
dname->name_size);
+                                       region, sizeof(uint16_t) + 
((size_t)dname->name_size));
                                temp_rdatas[i].data[0] = dname->name_size;
                                memcpy(temp_rdatas[i].data+1, dname_name(dname),
                                        dname->name_size);
@@ -845,8 +845,8 @@ rdata_wireformat_to_rdata_atoms(region_t
                return -1;
        }
 
-       *rdatas = (rdata_atom_type *) region_alloc_init(
-               region, temp_rdatas, i * sizeof(rdata_atom_type));
+       *rdatas = (rdata_atom_type *) region_alloc_array_init(
+               region, temp_rdatas, i, sizeof(rdata_atom_type));
        region_destroy(temp_region);
        return (ssize_t)i;
 }
Index: region-allocator.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/region-allocator.c,v
retrieving revision 1.8
diff -u -p -r1.8 region-allocator.c
--- region-allocator.c  26 Nov 2013 12:53:58 -0000      1.8
+++ region-allocator.c  16 Jul 2015 16:34:44 -0000
@@ -14,11 +14,15 @@
 #include <string.h>
 
 #include "region-allocator.h"
+#include "util.h"
+
+/** This value is enough so that x*y does not overflow if both < than this */
+#define REGION_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
 
 #ifdef ALIGNMENT
 #undef ALIGNMENT
 #endif
-#define ALIGN_UP(x, s)     (((x) + s - 1) & (~(s - 1)))
+#define REGION_ALIGN_UP(x, s)     (((x) + s - 1) & (~(s - 1)))
 #if SIZEOF_OFF_T > SIZEOF_VOIDP
 #define ALIGNMENT      (sizeof(off_t))
 #else
@@ -247,7 +251,7 @@ region_alloc(region_type *region, size_t
        if (size == 0) {
                size = 1;
        }
-       aligned_size = ALIGN_UP(size, ALIGNMENT);
+       aligned_size = REGION_ALIGN_UP(size, ALIGNMENT);
 
        if (aligned_size >= region->large_object_size) {
                result = region->allocator(size + sizeof(struct large_elem));
@@ -329,6 +333,40 @@ region_alloc_zero(region_type *region, s
        return result;
 }
 
+void *
+region_alloc_array_init(region_type *region, const void *init, size_t num,
+       size_t size)
+{
+       if((num >= REGION_NO_OVERFLOW || size >= REGION_NO_OVERFLOW) &&
+               num > 0 && SIZE_MAX / num < size) {
+               log_msg(LOG_ERR, "region_alloc_array_init failed because of 
integer overflow");
+               exit(1);
+       }
+       return region_alloc_init(region, init, num*size);
+}
+
+void *
+region_alloc_array_zero(region_type *region, size_t num, size_t size)
+{
+       if((num >= REGION_NO_OVERFLOW || size >= REGION_NO_OVERFLOW) &&
+               num > 0 && SIZE_MAX / num < size) {
+               log_msg(LOG_ERR, "region_alloc_array_zero failed because of 
integer overflow");
+               exit(1);
+       }
+       return region_alloc_zero(region, num*size);
+}
+
+void *
+region_alloc_array(region_type *region, size_t num, size_t size)
+{
+       if((num >= REGION_NO_OVERFLOW || size >= REGION_NO_OVERFLOW) &&
+               num > 0 && SIZE_MAX / num < size) {
+               log_msg(LOG_ERR, "region_alloc_array failed because of integer 
overflow");
+               exit(1);
+       }
+       return region_alloc(region, num*size);
+}
+
 void
 region_free_all(region_type *region)
 {
@@ -389,7 +427,7 @@ region_recycle(region_type *region, void
        if (size == 0) {
                size = 1;
        }
-       aligned_size = ALIGN_UP(size, ALIGNMENT);
+       aligned_size = REGION_ALIGN_UP(size, ALIGNMENT);
 
        if(aligned_size < region->large_object_size) {
                struct recycle_elem* elem = (struct recycle_elem*)block;
@@ -472,9 +510,7 @@ size_t region_get_mem_unused(region_type
        return region->unused_space;
 }
 
-/* debug routine, includes here to keep base region-allocator independent */
-#undef ALIGN_UP
-#include "util.h"
+/* debug routine */
 void
 region_log_stats(region_type *region)
 {
Index: region-allocator.h
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/region-allocator.h,v
retrieving revision 1.1.1.4
diff -u -p -r1.1.1.4 region-allocator.h
--- region-allocator.h  26 Nov 2013 12:50:14 -0000      1.1.1.4
+++ region-allocator.h  16 Jul 2015 16:34:44 -0000
@@ -88,6 +88,8 @@ void region_remove_cleanup(region_type *
  */
 void *region_alloc(region_type *region, size_t size);
 
+/** Allocate array with integer overflow checks, in region */
+void *region_alloc_array(region_type *region, size_t num, size_t size);
 
 /*
  * Allocate SIZE bytes of memory inside REGION and copy INIT into it.
@@ -96,6 +98,12 @@ void *region_alloc(region_type *region, 
  */
 void *region_alloc_init(region_type *region, const void *init, size_t size);
 
+/** 
+ * Allocate array (with integer overflow check on sizes), and init with
+ * the given array copied into it.  Allocated in the region
+ */
+void *region_alloc_array_init(region_type *region, const void *init,
+       size_t num, size_t size);
 
 /*
  * Allocate SIZE bytes of memory inside REGION that are initialized to
@@ -104,6 +112,11 @@ void *region_alloc_init(region_type *reg
  */
 void *region_alloc_zero(region_type *region, size_t size);
 
+/** 
+ * Allocate array (with integer overflow check on sizes), and zero it.
+ * Allocated in the region.
+ */
+void *region_alloc_array_zero(region_type *region, size_t num, size_t size);
 
 /*
  * Run the cleanup actions and free all memory associated with REGION.
Index: remote.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/remote.c,v
retrieving revision 1.5
diff -u -p -r1.5 remote.c
--- remote.c    3 Feb 2015 10:40:02 -0000       1.5
+++ remote.c    16 Jul 2015 16:34:44 -0000
@@ -77,7 +77,6 @@
 #include "nsd.h"
 #include "options.h"
 #include "difffile.h"
-#include "xfrd.h"
 #include "ipc.h"
 
 #ifdef HAVE_SYS_TYPES_H
@@ -1106,15 +1105,15 @@ zonestat_inc_ifneeded(xfrd_state_t* xfrd
 #endif /* USE_ZONE_STATS */
 }
 
-/** do the addzone command */
-static void
-do_addzone(SSL* ssl, xfrd_state_t* xfrd, char* arg)
+/** perform the addzone command for one zone */
+static int
+perform_addzone(SSL* ssl, xfrd_state_t* xfrd, char* arg)
 {
        const dname_type* dname;
        zone_options_t* zopt;
        char* arg2 = NULL;
        if(!find_arg2(ssl, arg, &arg2))
-               return;
+               return 0;
 
        /* if we add it to the xfrd now, then xfrd could download AXFR and
         * store it and the NSD-reload would see it in the difffile before
@@ -1128,13 +1127,13 @@ do_addzone(SSL* ssl, xfrd_state_t* xfrd,
        if(!rbtree_search(xfrd->nsd->options->patterns, arg2)) {
                (void)ssl_printf(ssl, "error pattern %s does not exist\n",
                        arg2);
-               return;
+               return 0;
        }
 
        dname = dname_parse(xfrd->region, arg);
        if(!dname) {
                (void)ssl_printf(ssl, "error cannot parse zone name\n");
-               return;
+               return 0;
        }
 
        /* see if zone is a duplicate */
@@ -1142,8 +1141,7 @@ do_addzone(SSL* ssl, xfrd_state_t* xfrd,
                region_recycle(xfrd->region, (void*)dname,
                        dname_total_size(dname));
                (void)ssl_printf(ssl, "zone %s already exists\n", arg);
-               send_ok(ssl); /* a nop operation */
-               return;
+               return 1;
        }
        region_recycle(xfrd->region, (void*)dname, dname_total_size(dname));
        dname = NULL;
@@ -1153,7 +1151,7 @@ do_addzone(SSL* ssl, xfrd_state_t* xfrd,
        if(!zopt) {
                /* also dname parse error here */
                (void)ssl_printf(ssl, "error could not add zonelist entry\n");
-               return;
+               return 0;
        }
        /* make addzone task and schedule reload */
        task_new_add_zone(xfrd->nsd->task[xfrd->nsd->mytask],
@@ -1167,13 +1165,12 @@ do_addzone(SSL* ssl, xfrd_state_t* xfrd,
        if(zone_is_slave(zopt)) {
                xfrd_init_slave_zone(xfrd, zopt);
        }
-
-       send_ok(ssl);
+       return 1;
 }
 
-/** do the delzone command */
-static void
-do_delzone(SSL* ssl, xfrd_state_t* xfrd, char* arg)
+/** perform the delzone command for one zone */
+static int
+perform_delzone(SSL* ssl, xfrd_state_t* xfrd, char* arg)
 {
        const dname_type* dname;
        zone_options_t* zopt;
@@ -1181,7 +1178,7 @@ do_delzone(SSL* ssl, xfrd_state_t* xfrd,
        dname = dname_parse(xfrd->region, arg);
        if(!dname) {
                (void)ssl_printf(ssl, "error cannot parse zone name\n");
-               return;
+               return 0;
        }
 
        /* see if we have the zone in question */
@@ -1191,9 +1188,8 @@ do_delzone(SSL* ssl, xfrd_state_t* xfrd,
                        dname_total_size(dname));
                /* nothing to do */
                if(!ssl_printf(ssl, "warning zone %s not present\n", arg))
-                       return;
-               send_ok(ssl);
-               return;
+                       return 0;
+               return 1;
        }
 
        /* see if it can be deleted */
@@ -1203,7 +1199,7 @@ do_delzone(SSL* ssl, xfrd_state_t* xfrd,
                (void)ssl_printf(ssl, "error zone defined in nsd.conf, "
                        "cannot delete it in this manner: remove it from "
                        "nsd.conf yourself and repattern\n");
-               return;
+               return 0;
        }
 
        /* create deletion task */
@@ -1219,9 +1215,72 @@ do_delzone(SSL* ssl, xfrd_state_t* xfrd,
        zone_list_del(xfrd->nsd->options, zopt);
 
        region_recycle(xfrd->region, (void*)dname, dname_total_size(dname));
+       return 1;
+}
+
+/** do the addzone command */
+static void
+do_addzone(SSL* ssl, xfrd_state_t* xfrd, char* arg)
+{
+       if(!perform_addzone(ssl, xfrd, arg))
+               return;
+       send_ok(ssl);
+}
+
+/** do the delzone command */
+static void
+do_delzone(SSL* ssl, xfrd_state_t* xfrd, char* arg)
+{
+       if(!perform_delzone(ssl, xfrd, arg))
+               return;
        send_ok(ssl);
 }
 
+/** do the addzones command */
+static void
+do_addzones(SSL* ssl, xfrd_state_t* xfrd)
+{
+       char buf[2048];
+       int num = 0;
+       while(ssl_read_line(ssl, buf, sizeof(buf))) {
+               if(buf[0] == 0x04 && buf[1] == 0)
+                       break; /* end of transmission */
+               if(!perform_addzone(ssl, xfrd, buf)) {
+                       if(!ssl_printf(ssl, "error for input line '%s'\n", 
+                               buf))
+                               return;
+               } else {
+                       if(!ssl_printf(ssl, "added: %s\n", buf))
+                               return;
+                       num++;
+               }
+       }
+       (void)ssl_printf(ssl, "added %d zones\n", num);
+}
+
+/** do the delzones command */
+static void
+do_delzones(SSL* ssl, xfrd_state_t* xfrd)
+{
+       char buf[2048];
+       int num = 0;
+       while(ssl_read_line(ssl, buf, sizeof(buf))) {
+               if(buf[0] == 0x04 && buf[1] == 0)
+                       break; /* end of transmission */
+               if(!perform_delzone(ssl, xfrd, buf)) {
+                       if(!ssl_printf(ssl, "error for input line '%s'\n", 
+                               buf))
+                               return;
+               } else {
+                       if(!ssl_printf(ssl, "removed: %s\n", buf))
+                               return;
+                       num++;
+               }
+       }
+       (void)ssl_printf(ssl, "deleted %d zones\n", num);
+}
+
+
 /** remove TSIG key from config and add task so that reload does too */
 static void remove_key(xfrd_state_t* xfrd, const char* kname)
 {
@@ -1662,6 +1721,10 @@ execute_cmd(struct daemon_remote* rc, SS
                do_addzone(ssl, rc->xfrd, skipwhite(p+7));
        } else if(cmdcmp(p, "delzone", 7)) {
                do_delzone(ssl, rc->xfrd, skipwhite(p+7));
+       } else if(cmdcmp(p, "addzones", 8)) {
+               do_addzones(ssl, rc->xfrd);
+       } else if(cmdcmp(p, "delzones", 8)) {
+               do_delzones(ssl, rc->xfrd);
        } else if(cmdcmp(p, "notify", 6)) {
                do_notify(ssl, rc->xfrd, skipwhite(p+6));
        } else if(cmdcmp(p, "transfer", 8)) {
@@ -1938,7 +2001,7 @@ print_stat_block(SSL* ssl, char* n, char
 static void
 resize_zonestat(xfrd_state_t* xfrd, size_t num)
 {
-       struct nsdst** a = xalloc_zero(num * sizeof(struct nsdst*));
+       struct nsdst** a = xalloc_array_zero(num, sizeof(struct nsdst*));
        if(xfrd->zonestat_clear_num != 0)
                memcpy(a, xfrd->zonestat_clear, xfrd->zonestat_clear_num
                        * sizeof(struct nsdst*));
Index: rrl.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/rrl.c,v
retrieving revision 1.4
diff -u -p -r1.4 rrl.c
--- rrl.c       16 Sep 2014 17:01:38 -0000      1.4
+++ rrl.c       16 Jul 2015 16:34:44 -0000
@@ -80,7 +80,7 @@ void rrl_mmap_init(int numch, size_t num
        /* allocate the ratelimit hashtable in a memory map so it is
         * preserved across reforks (every child its own table) */
        rrl_maps_num = (size_t)numch;
-       rrl_maps = (void**)xalloc(sizeof(void*)*rrl_maps_num);
+       rrl_maps = (void**)xmallocarray(rrl_maps_num, sizeof(void*));
        for(i=0; i<rrl_maps_num; i++) {
                rrl_maps[i] = mmap(NULL,
                        sizeof(struct rrl_bucket)*rrl_array_size,
@@ -110,7 +110,8 @@ void rrl_set_limit(size_t lm, size_t wlm
 void rrl_init(size_t ch)
 {
        if(!rrl_maps || ch >= rrl_maps_num)
-           rrl_array = xalloc_zero(sizeof(struct rrl_bucket)*rrl_array_size);
+           rrl_array = xalloc_array_zero(sizeof(struct rrl_bucket),
+               rrl_array_size);
 #ifdef HAVE_MMAP
        else rrl_array = (struct rrl_bucket*)rrl_maps[ch];
 #endif
Index: server.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/server.c,v
retrieving revision 1.19
diff -u -p -r1.19 server.c
--- server.c    3 Feb 2015 10:40:02 -0000       1.19
+++ server.c    16 Jul 2015 16:34:44 -0000
@@ -29,7 +29,6 @@
 #include <time.h>
 #include <unistd.h>
 #include <signal.h>
-#include <fcntl.h>
 #include <netdb.h>
 #ifndef SHUT_WR
 #define SHUT_WR 1
@@ -366,11 +365,11 @@ server_zonestat_alloc(struct nsd* nsd)
        /* file names */
        nsd->zonestatfname[0] = 0;
        nsd->zonestatfname[1] = 0;
-       snprintf(tmpfile, sizeof(tmpfile), "%snsd.%u.zstat.0",
-               nsd->options->xfrdir, (unsigned)getpid());
+       snprintf(tmpfile, sizeof(tmpfile), "%snsd-xfr-%d/nsd.%u.zstat.0",
+               nsd->options->xfrdir, (int)getpid(), (unsigned)getpid());
        nsd->zonestatfname[0] = region_strdup(nsd->region, tmpfile);
-       snprintf(tmpfile, sizeof(tmpfile), "%snsd.%u.zstat.1",
-               nsd->options->xfrdir, (unsigned)getpid());
+       snprintf(tmpfile, sizeof(tmpfile), "%snsd-xfr-%d/nsd.%u.zstat.1",
+               nsd->options->xfrdir, (int)getpid(), (unsigned)getpid());
        nsd->zonestatfname[1] = region_strdup(nsd->region, tmpfile);
 
        /* file descriptors */
@@ -536,8 +535,8 @@ initialize_dname_compression_tables(stru
                                compressed_dname_offsets);
                        free(compressed_dname_offsets);
                }
-               compressed_dname_offsets = (uint16_t *) xalloc(
-                       needed * sizeof(uint16_t));
+               compressed_dname_offsets = (uint16_t *) xmallocarray(
+                       needed, sizeof(uint16_t));
                region_add_cleanup(nsd->db->region, 
cleanup_dname_compression_tables,
                        compressed_dname_offsets);
                compression_table_capacity = needed;
@@ -957,16 +956,27 @@ server_prepare_xfrd(struct nsd* nsd)
        char tmpfile[256];
        /* create task mmaps */
        nsd->mytask = 0;
-       snprintf(tmpfile, sizeof(tmpfile), "%snsd.%u.task.0",
-               nsd->options->xfrdir, (unsigned)getpid());
+       snprintf(tmpfile, sizeof(tmpfile), "%snsd-xfr-%d/nsd.%u.task.0",
+               nsd->options->xfrdir, (int)getpid(), (unsigned)getpid());
        nsd->task[0] = task_file_create(tmpfile);
-       if(!nsd->task[0])
+       if(!nsd->task[0]) {
+#ifdef USE_ZONE_STATS
+               unlink(nsd->zonestatfname[0]);
+               unlink(nsd->zonestatfname[1]);
+#endif
+               xfrd_del_tempdir(nsd);
                exit(1);
-       snprintf(tmpfile, sizeof(tmpfile), "%snsd.%u.task.1",
-               nsd->options->xfrdir, (unsigned)getpid());
+       }
+       snprintf(tmpfile, sizeof(tmpfile), "%snsd-xfr-%d/nsd.%u.task.1",
+               nsd->options->xfrdir, (int)getpid(), (unsigned)getpid());
        nsd->task[1] = task_file_create(tmpfile);
        if(!nsd->task[1]) {
                unlink(nsd->task[0]->fname);
+#ifdef USE_ZONE_STATS
+               unlink(nsd->zonestatfname[0]);
+               unlink(nsd->zonestatfname[1]);
+#endif
+               xfrd_del_tempdir(nsd);
                exit(1);
        }
        assert(udb_base_get_userdata(nsd->task[0])->data == 0);
@@ -1930,8 +1940,9 @@ server_child(struct nsd *nsd)
         * connections.
         */
        tcp_accept_handler_count = nsd->ifs;
-       tcp_accept_handlers = (struct tcp_accept_handler_data*) region_alloc(
-               server_region, nsd->ifs * sizeof(*tcp_accept_handlers));
+       tcp_accept_handlers = (struct tcp_accept_handler_data*)
+               region_alloc_array(server_region,
+               nsd->ifs, sizeof(*tcp_accept_handlers));
        if (nsd->server_kind & NSD_SERVER_TCP) {
                for (i = 0; i < nsd->ifs; ++i) {
                        struct event *handler = &tcp_accept_handlers[i].event;
Index: tsig-openssl.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/tsig-openssl.c,v
retrieving revision 1.1.1.6
diff -u -p -r1.1.1.6 tsig-openssl.c
--- tsig-openssl.c      26 Nov 2013 12:50:14 -0000      1.1.1.6
+++ tsig-openssl.c      16 Jul 2015 16:34:44 -0000
@@ -61,14 +61,19 @@ tsig_openssl_init(region_type *region)
        int count = 0;
        OpenSSL_add_all_digests();
 
-       count += tsig_openssl_init_algorithm(region, "md5", 
"hmac-md5","hmac-md5.sig-alg.reg.int.");
-#ifdef HAVE_EVP_SHA1
-       count += tsig_openssl_init_algorithm(region, "sha1", "hmac-sha1", 
"hmac-sha1.");
-#endif /* HAVE_EVP_SHA1 */
+       count += tsig_openssl_init_algorithm(region,
+           "md5", "hmac-md5","hmac-md5.sig-alg.reg.int.");
+       count += tsig_openssl_init_algorithm(region,
+           "sha1", "hmac-sha1", "hmac-sha1.");
+       count += tsig_openssl_init_algorithm(region,
+           "sha224", "hmac-sha224", "hmac-sha224.");
+       count += tsig_openssl_init_algorithm(region,
+           "sha256", "hmac-sha256", "hmac-sha256.");
+       count += tsig_openssl_init_algorithm(region,
+           "sha384", "hmac-sha384", "hmac-sha384.");
+       count += tsig_openssl_init_algorithm(region,
+           "sha512", "hmac-sha512", "hmac-sha512.");
 
-#ifdef HAVE_EVP_SHA256
-       count += tsig_openssl_init_algorithm(region, "sha256", "hmac-sha256", 
"hmac-sha256.");
-#endif /* HAVE_EVP_SHA256 */
        return count;
 }
 
Index: tsig.h
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/tsig.h,v
retrieving revision 1.1.1.4
diff -u -p -r1.1.1.4 tsig.h
--- tsig.h      26 Nov 2013 12:50:14 -0000      1.1.1.4
+++ tsig.h      16 Jul 2015 16:34:44 -0000
@@ -22,10 +22,6 @@
 #define TSIG_ERROR_BADKEY   17
 #define TSIG_ERROR_BADTIME  18
 
-#define TSIG_HMAC_MD5       157
-#define TSIG_HMAC_SHA1      158
-#define TSIG_HMAC_SHA256    159
-
 typedef struct tsig_algorithm tsig_algorithm_type;
 typedef struct tsig_key tsig_key_type;
 typedef struct tsig_record tsig_record_type;
Index: udb.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/udb.c,v
retrieving revision 1.2
diff -u -p -r1.2 udb.c
--- udb.c       16 Jan 2015 01:10:10 -0000      1.2
+++ udb.c       16 Jul 2015 16:34:44 -0000
@@ -91,7 +91,8 @@ udb_base_create_fd(const char* fname, in
        udb->fd = fd;
        udb->ram_size = 1024;
        udb->ram_mask = (int)udb->ram_size - 1;
-       udb->ram_hash = (udb_ptr**)xalloc_zero(sizeof(udb_ptr*)*udb->ram_size);
+       udb->ram_hash = (udb_ptr**)xalloc_array_zero(sizeof(udb_ptr*),
+               udb->ram_size);
        if(!udb->ram_hash) {
                free(udb->fname);
                free(udb);
@@ -432,10 +433,10 @@ void udb_base_link_ptr(udb_base* udb, ud
        assert(udb_valid_dataptr(udb, ptr->data)); /* must be to whole chunk*/
 #endif
        udb->ram_num++;
-       if(udb->ram_num == udb->ram_size && udb->ram_size<(size_t)0xefffffff) {
+       if(udb->ram_num == udb->ram_size && udb->ram_size<(size_t)0x7fffffff) {
                /* grow the array, if allocation succeeds */
-               udb_ptr** newram = (udb_ptr**)xalloc_zero(sizeof(udb_ptr*)*
-                       udb->ram_size*2);
+               udb_ptr** newram = (udb_ptr**)xalloc_array_zero(
+                       sizeof(udb_ptr*), udb->ram_size*2);
                if(newram) {
                        grow_ram_hash(udb, newram);
                }
Index: util.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/util.c,v
retrieving revision 1.16
diff -u -p -r1.16 util.c
--- util.c      3 Feb 2015 10:40:02 -0000       1.16
+++ util.c      16 Jul 2015 16:34:44 -0000
@@ -259,9 +259,32 @@ xalloc(size_t size)
 }
 
 void *
+xmallocarray(size_t num, size_t size)
+{  
+        void *result = reallocarray(NULL, num, size);
+   
+        if (!result) {
+                log_msg(LOG_ERR, "reallocarray failed: %s", strerror(errno));
+                exit(1);
+        }
+        return result;
+}
+
+void *
 xalloc_zero(size_t size)
 {
        void *result = calloc(1, size);
+       if (!result) {
+               log_msg(LOG_ERR, "calloc failed: %s", strerror(errno));
+               exit(1);
+       }
+       return result;
+}
+
+void *
+xalloc_array_zero(size_t num, size_t size)
+{
+       void *result = calloc(num, size);
        if (!result) {
                log_msg(LOG_ERR, "calloc failed: %s", strerror(errno));
                exit(1);
Index: util.h
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/util.h,v
retrieving revision 1.7
diff -u -p -r1.7 util.h
--- util.h      16 Sep 2014 17:01:38 -0000      1.7
+++ util.h      16 Jul 2015 16:34:44 -0000
@@ -135,7 +135,9 @@ lookup_table_type *lookup_by_id(lookup_t
  * return NULL.
  */
 void *xalloc(size_t size);
+void *xmallocarray(size_t num, size_t size);
 void *xalloc_zero(size_t size);
+void *xalloc_array_zero(size_t num, size_t size);
 void *xrealloc(void *ptr, size_t size);
 
 /*
Index: zonec.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/zonec.c,v
retrieving revision 1.14
diff -u -p -r1.14 zonec.c
--- zonec.c     3 Feb 2015 10:40:02 -0000       1.14
+++ zonec.c     16 Jul 2015 16:34:44 -0000
@@ -1150,6 +1150,10 @@ void
 zadd_rdata_txt_wireformat(uint16_t *data, int first)
 {
        rdata_atom_type *rd;
+       if (parser->current_rr.rdata_count >= MAXRDATALEN) {
+               zc_error_prev_line("too many rdata txt elements");
+               return;
+       }
        
        /* First STR in str_seq, allocate 65K in first unused rdata
         * else find last used rdata */
@@ -1183,8 +1187,10 @@ zadd_rdata_txt_clean_wireformat()
 {
        uint16_t *tmp_data;
        rdata_atom_type *rd = 
&parser->current_rr.rdatas[parser->current_rr.rdata_count-1];
+       if(!rd || !rd->data)
+               return; /* previous syntax failure */
        if ((tmp_data = (uint16_t *) region_alloc(parser->region, 
-               rd->data[0] + 2)) != NULL) {
+               ((size_t)rd->data[0]) + ((size_t)2))) != NULL) {
                memcpy(tmp_data, rd->data, rd->data[0] + 2);
                /* rd->data of u16+65535 freed when rr_region is freed */
                rd->data = tmp_data;
@@ -1442,11 +1448,15 @@ process_rr(void)
                if (i < rrset->rr_count) {
                        return 0;
                }
+               if(rrset->rr_count == 65535) {
+                       zc_error_prev_line("too may RRs for domain RRset");
+                       return 0;
+               }
 
                /* Add it... */
                o = rrset->rrs;
-               rrset->rrs = (rr_type *) region_alloc(parser->region,
-                       (rrset->rr_count + 1) * sizeof(rr_type));
+               rrset->rrs = (rr_type *) region_alloc_array(parser->region,
+                       (rrset->rr_count + 1), sizeof(rr_type));
                memcpy(rrset->rrs, o, (rrset->rr_count) * sizeof(rr_type));
                region_recycle(parser->region, o,
                        (rrset->rr_count) * sizeof(rr_type));
@@ -1585,7 +1595,8 @@ zonec_read(const char* name, const char*
        yyparse();
 
        /* remove origin if it was unused */
-       domain_table_deldomain(parser->db, parser->origin);
+       if(parser->origin != error_domain)
+               domain_table_deldomain(parser->db, parser->origin);
        /* rr_region has been emptied by now */
        dname = dname_parse(parser->rr_region, name);
 
@@ -1691,7 +1702,8 @@ zonec_parse_string(region_type* region, 
                *parsed = NULL;
        else    *parsed = parser->prev_dname;
        /* remove origin if it was not used during the parse */
-       domain_table_deldomain(parser->db, parser->origin);
+       if(parser->origin != error_domain)
+               domain_table_deldomain(parser->db, parser->origin);
        zonec_desetup_string_parser();
        return errors;
 }
Index: zparser.y
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/zparser.y,v
retrieving revision 1.10
diff -u -p -r1.10 zparser.y
--- zparser.y   18 Dec 2014 23:26:13 -0000      1.10
+++ zparser.y   16 Jul 2015 16:34:44 -0000
@@ -97,21 +97,29 @@ line:       NL
     |  PREV NL         {}    /* Lines containing only whitespace.  */
     |  ttl_directive
        {
+           region_free_all(parser->rr_region);
+           parser->current_rr.type = 0;
+           parser->current_rr.rdata_count = 0;
+           parser->current_rr.rdatas = parser->temporary_rdatas;
            parser->error_occurred = 0;
     }
     |  origin_directive
        {
+           region_free_all(parser->rr_region);
+           parser->current_rr.type = 0;
+           parser->current_rr.rdata_count = 0;
+           parser->current_rr.rdatas = parser->temporary_rdatas;
            parser->error_occurred = 0;
     }
     |  rr
     {  /* rr should be fully parsed */
            if (!parser->error_occurred) {
                            parser->current_rr.rdatas
-                                   = (rdata_atom_type *) region_alloc_init(
+                                   =(rdata_atom_type *)region_alloc_array_init(
                                            parser->region,
                                            parser->current_rr.rdatas,
-                                           (parser->current_rr.rdata_count
-                                            * sizeof(rdata_atom_type)));
+                                           parser->current_rr.rdata_count,
+                                           sizeof(rdata_atom_type));
 
                            process_rr();
            }
@@ -148,7 +156,12 @@ ttl_directive:     DOLLAR_TTL sp STR trail
 origin_directive:      DOLLAR_ORIGIN sp abs_dname trail
     {
            /* if previous origin is unused, remove it, do not leak it */
-           domain_table_deldomain(parser->db, parser->origin);
+           if(parser->origin != error_domain && parser->origin != $3) {
+               /* protect $3 from deletion, because deldomain walks up */
+               $3->usage ++;
+               domain_table_deldomain(parser->db, parser->origin);
+               $3->usage --;
+           }
            parser->origin = $3;
     }
     |  DOLLAR_ORIGIN sp rel_dname trail
@@ -207,6 +220,9 @@ dname:      abs_dname
     {
            if ($1 == error_dname) {
                    $$ = error_domain;
+           } else if(parser->origin == error_domain) {
+                   zc_error("cannot concatenate origin to domain name, because 
origin failed to parse");
+                   $$ = error_domain;
            } else if ($1->name_size + domain_dname(parser->origin)->name_size 
- 1 > MAXDOMAINLEN) {
                    zc_error("domain name exceeds %d character limit", 
MAXDOMAINLEN);
                    $$ = error_domain;
@@ -949,9 +965,14 @@ rdata_ipsec_base: STR sp STR sp STR sp d
                                zc_error_prev_line("IPSECKEY must specify 
gateway name");
                        if(!(name = dname_parse(parser->region, $7.str)))
                                zc_error_prev_line("IPSECKEY bad gateway dname 
%s", $7.str);
-                       if($7.str[strlen($7.str)-1] != '.')
+                       if($7.str[strlen($7.str)-1] != '.') {
+                               if(parser->origin == error_domain) {
+                                       zc_error("cannot concatenate origin to 
domain name, because origin failed to parse");
+                                       break;
+                               }
                                name = dname_concatenate(parser->rr_region, 
name, 
                                        domain_dname(parser->origin));
+                       }
                        zadd_rdata_wireformat(alloc_rdata_init(parser->region,
                                dname_name(name), name->name_size));
                        break;
@@ -1060,8 +1081,8 @@ zparser_create(region_type *region, regi
        result->prev_dname = NULL;
        result->default_apex = NULL;
 
-       result->temporary_rdatas = (rdata_atom_type *) region_alloc(
-               result->region, MAXRDATALEN * sizeof(rdata_atom_type));
+       result->temporary_rdatas = (rdata_atom_type *) region_alloc_array(
+               result->region, MAXRDATALEN, sizeof(rdata_atom_type));
 
        return result;
 }
Index: compat/b64_pton.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/compat/b64_pton.c,v
retrieving revision 1.3
diff -u -p -r1.3 b64_pton.c
--- compat/b64_pton.c   3 Feb 2015 10:40:02 -0000       1.3
+++ compat/b64_pton.c   16 Jul 2015 16:34:44 -0000
@@ -168,7 +168,7 @@ b64_initialize_rmap ()
 }
 
 static int
-b64_pton_do(char const *src, uint8_t *target, size_t targsize)
+b64_pton_do(unsigned char const *src, uint8_t *target, size_t targsize)
 {
        int tarindex, state, ch;
        uint8_t ofs;
@@ -285,7 +285,7 @@ b64_pton_do(char const *src, uint8_t *ta
 
 
 static int
-b64_pton_len(char const *src)
+b64_pton_len(unsigned char const *src)
 {
        int tarindex, state, ch;
        uint8_t ofs;
@@ -384,7 +384,7 @@ b64_pton(char const *src, uint8_t *targe
                b64_initialize_rmap ();
 
        if (target)
-               return b64_pton_do (src, target, targsize);
+               return b64_pton_do ((unsigned char*)src, target, targsize);
        else
-               return b64_pton_len (src);
+               return b64_pton_len ((unsigned char*)src);
 }

Reply via email to