summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/nsd/config.h.in102
-rw-r--r--usr.sbin/nsd/configparser.y27
-rw-r--r--usr.sbin/nsd/configure.ac13
-rw-r--r--usr.sbin/nsd/dns.c36
-rw-r--r--usr.sbin/nsd/dns.h8
-rw-r--r--usr.sbin/nsd/mkinstalldirs2
-rw-r--r--usr.sbin/nsd/nsd-checkconf.c29
-rw-r--r--usr.sbin/nsd/nsd-notify.c2
-rw-r--r--usr.sbin/nsd/nsd-patch.c4
-rw-r--r--usr.sbin/nsd/nsdc.sh.in48
-rw-r--r--usr.sbin/nsd/nsec3.c10
-rw-r--r--usr.sbin/nsd/query.c37
-rw-r--r--usr.sbin/nsd/rdata.c52
-rw-r--r--usr.sbin/nsd/server.c38
-rw-r--r--usr.sbin/nsd/util.c8
-rw-r--r--usr.sbin/nsd/zonec.c68
-rw-r--r--usr.sbin/nsd/zonec.h2
-rw-r--r--usr.sbin/nsd/zparser.y7
18 files changed, 284 insertions, 209 deletions
diff --git a/usr.sbin/nsd/config.h.in b/usr.sbin/nsd/config.h.in
index b6a98363972..f26fae53a71 100644
--- a/usr.sbin/nsd/config.h.in
+++ b/usr.sbin/nsd/config.h.in
@@ -3,9 +3,6 @@
/* Define this to enable BIND8 like NSTATS & XSTATS. */
#undef BIND8_STATS
-/* NSD default chroot directory */
-#undef CHROOTDIR
-
/* Pathname to the NSD configuration file */
#undef CONFIGFILE
@@ -19,6 +16,9 @@
/* Pathname to the NSD diff transfer journal file. */
#undef DIFFFILE
+/* Define this to enable DNSSEC (RFCs 4033, 4034, and 4035) support. */
+#undef DNSSEC
+
/* Define to the default maximum message length with EDNS. */
#undef EDNS_MAX_MESSAGE_LEN
@@ -134,12 +134,6 @@
/* Define to 1 if you have the `memset' function. */
#undef HAVE_MEMSET
-/* Define to 1 if you have the `mmap' function. */
-#undef HAVE_MMAP
-
-/* Define to 1 if you have the `munmap' function. */
-#undef HAVE_MUNMAP
-
/* Define to 1 if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H
@@ -215,9 +209,6 @@
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
-/* Define to 1 if you have the `strlcat' function. */
-#undef HAVE_STRLCAT
-
/* Define to 1 if you have the `strlcpy' function. */
#undef HAVE_STRLCPY
@@ -239,9 +230,6 @@
/* Define to 1 if you have the <sys/bitypes.h> header file. */
#undef HAVE_SYS_BITYPES_H
-/* Define to 1 if you have the <sys/mman.h> header file. */
-#undef HAVE_SYS_MMAN_H
-
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
@@ -293,18 +281,18 @@
/* Define to the maximum message length to pass to syslog. */
#undef MAXSYSLOGMSGLEN
-/* Define to the maximum ip-addresses to serve. */
+/* Define to the maximum interfaces to serve. */
#undef MAX_INTERFACES
-/* Define if memcmp() does not compare unsigned bytes */
-#undef MEMCMP_IS_BROKEN
-
/* Undefine this to enable internal runtime checks. */
#undef NDEBUG
/* Define this to enable NSEC3 support. */
#undef NSEC3
+/* Define this to enable NSID support. */
+#undef NSID
+
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
@@ -350,6 +338,9 @@
/* Define to the default tcp timeout. */
#undef TCP_TIMEOUT
+/* Define this to enable TSIG support. */
+#undef TSIG
+
/* Define to the default maximum udp message length. */
#undef UDP_MAX_MESSAGE_LEN
@@ -359,31 +350,6 @@
/* the user name to drop privileges to */
#undef USER
-/* Define this to enable mmap instead of malloc. Experimental. */
-#undef USE_MMAP_ALLOC
-
-/* Enable extensions on AIX 3, Interix. */
-#ifndef _ALL_SOURCE
-# undef _ALL_SOURCE
-#endif
-/* Enable GNU extensions on systems that have them. */
-#ifndef _GNU_SOURCE
-# undef _GNU_SOURCE
-#endif
-/* Enable threading extensions on Solaris. */
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# undef _POSIX_PTHREAD_SEMANTICS
-#endif
-/* Enable extensions on HP NonStop. */
-#ifndef _TANDEM_SOURCE
-# undef _TANDEM_SOURCE
-#endif
-/* Enable general extensions on Solaris. */
-#ifndef __EXTENSIONS__
-# undef __EXTENSIONS__
-#endif
-
-
/* Define to the NSD version to answer version.server query. */
#undef VERSION
@@ -416,6 +382,28 @@
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE
+/* Enable extensions on AIX 3, Interix. */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable GNU extensions on systems that have them. */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable threading extensions on Solaris. */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop. */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
@@ -461,15 +449,9 @@
/* Define "socklen_t" to "int" if "socklen_t" is missing */
#undef socklen_t
-/* Fallback member name for socket family in struct sockaddr_storage */
-#undef ss_family
-
/* Define "ssize_t" to "int" if "ssize_t" is missing */
#undef ssize_t
-/* Define "suseconds_t" to "time_t" if "suseconds_t" is missing */
-#undef suseconds_t
-
/* Define to `int' if <sys/types.h> doesn't define. */
#undef uid_t
@@ -485,9 +467,6 @@
/* Define "uint8_t" to "unsigned char" if "uint8_t" is missing */
#undef uint8_t
-/* Define "uintptr_t" to "void*" if "uintptr_t" is missing */
-#undef uintptr_t
-
/* Define as `fork' if `vfork' does not work. */
#undef vfork
@@ -619,9 +598,6 @@ int inet_aton(const char *cp, struct in_addr *addr);
#ifndef HAVE_MEMMOVE
void *memmove(void *dest, const void *src, size_t n);
#endif
-#ifndef HAVE_STRLCAT
-size_t strlcat(char *dst, const char *src, size_t siz);
-#endif
#ifndef HAVE_STRLCPY
size_t strlcpy(char *dst, const char *src, size_t siz);
#endif
@@ -637,20 +613,6 @@ char *strptime(const char *s, const char *format, struct tm *tm);
#define strptime(a,b,c) nsd_strptime((a),(b),(c))
#endif
-
-
-#ifdef MEMCMP_IS_BROKEN
-# ifdef memcmp
-# undef memcmp
-# endif
-#define memcmp memcmp_nsd
-int memcmp(const void *x, const void *y, size_t n);
-#endif
-
-
-
-
-
/* provide timespec def if not available */
#ifndef CONFIG_DEFINES
#define CONFIG_DEFINES
diff --git a/usr.sbin/nsd/configparser.y b/usr.sbin/nsd/configparser.y
index 96969a238df..ef8eb2dcd86 100644
--- a/usr.sbin/nsd/configparser.y
+++ b/usr.sbin/nsd/configparser.y
@@ -17,6 +17,7 @@
#include <assert.h>
#include "options.h"
+#include "util.h"
#include "configyyrename.h"
int c_lex(void);
void c_error(const char *message);
@@ -43,7 +44,7 @@ static int server_settings_seen = 0;
%token SPACE LETTER NEWLINE COMMENT COLON ANY ZONESTR
%token <str> STRING
%token VAR_SERVER VAR_NAME VAR_IP_ADDRESS VAR_DEBUG_MODE
-%token VAR_IP4_ONLY VAR_IP6_ONLY VAR_DATABASE VAR_IDENTITY VAR_LOGFILE
+%token VAR_IP4_ONLY VAR_IP6_ONLY VAR_DATABASE VAR_IDENTITY VAR_NSID VAR_LOGFILE
%token VAR_SERVER_COUNT VAR_TCP_COUNT VAR_PIDFILE VAR_PORT VAR_STATISTICS
%token VAR_CHROOT VAR_USERNAME VAR_ZONESDIR VAR_XFRDFILE VAR_DIFFFILE
%token VAR_XFRD_RELOAD_TIMEOUT VAR_TCP_QUERY_COUNT VAR_TCP_TIMEOUT
@@ -73,7 +74,7 @@ serverstart: VAR_SERVER
;
contents_server: contents_server content_server | ;
content_server: server_ip_address | server_debug_mode | server_ip4_only |
- server_ip6_only | server_database | server_identity | server_logfile |
+ server_ip6_only | server_database | server_identity | server_nsid | server_logfile |
server_server_count | server_tcp_count | server_pidfile | server_port |
server_statistics | server_chroot | server_username | server_zonesdir |
server_difffile | server_xfrdfile | server_xfrd_reload_timeout |
@@ -153,6 +154,26 @@ server_identity: VAR_IDENTITY STRING
cfg_parser->opt->identity = region_strdup(cfg_parser->opt->region, $2);
}
;
+server_nsid: VAR_NSID STRING
+ {
+ unsigned char* nsid = 0;
+ uint16_t nsid_len = 0;
+
+ OUTYY(("P(server_nsid:%s)\n", $2));
+
+ 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);
+ }
+ }
+ ;
server_logfile: VAR_LOGFILE STRING
{
OUTYY(("P(server_logfile:%s)\n", $2));
@@ -401,7 +422,7 @@ zone_outgoing_interface: VAR_OUTGOING_INTERFACE STRING
{
acl_options_t* acl = parse_acl_info(cfg_parser->opt->region, $2, "NOKEY");
OUTYY(("P(zone_outgoing_interface:%s)\n", $2));
-
+ if(acl->rangetype!=acl_range_single) c_error("address range used for outgoing interface");
if(cfg_parser->current_outgoing_interface)
cfg_parser->current_outgoing_interface->next = acl;
else
diff --git a/usr.sbin/nsd/configure.ac b/usr.sbin/nsd/configure.ac
index b80ba667d07..ee2061684fe 100644
--- a/usr.sbin/nsd/configure.ac
+++ b/usr.sbin/nsd/configure.ac
@@ -4,7 +4,7 @@ dnl
sinclude(acx_nlnetlabs.m4)
-AC_INIT(NSD,3.2.6,nsd-bugs@nlnetlabs.nl)
+AC_INIT(NSD,3.2.7,nsd-bugs@nlnetlabs.nl)
AC_CONFIG_HEADER([config.h])
AC_AIX
@@ -275,7 +275,9 @@ AC_DEFUN([CHECK_SSL], [
if test -f "$dir/include/openssl/ssl.h"; then
found_ssl="yes";
AC_DEFINE_UNQUOTED([HAVE_SSL], [], [Define if you have the SSL libraries installed.])
- CPPFLAGS="$CPPFLAGS -I$ssldir/include";
+ if test x_$ssldir != x_/usr; then
+ CPPFLAGS="$CPPFLAGS -I$ssldir/include";
+ fi
break;
fi
done
@@ -284,7 +286,9 @@ AC_DEFUN([CHECK_SSL], [
else
AC_MSG_RESULT(found in $ssldir)
HAVE_SSL=yes
- LDFLAGS="$LDFLAGS -L$ssldir/lib";
+ if test x_$ssldir != x_/usr; then
+ LDFLAGS="$LDFLAGS -L$ssldir/lib";
+ fi
if test x_$ssldir = x_/usr/sfw; then
LDFLAGS="$LDFLAGS -R$ssldir/lib";
fi
@@ -463,6 +467,7 @@ AC_FUNC_MALLOC
AC_TYPE_SIGNAL
AC_FUNC_FSEEKO
AC_SYS_LARGEFILE
+AC_CHECK_FUNCS([arc4random arc4random_uniform])
AC_CHECK_FUNCS([alarm chroot dup2 endpwent gethostname memset memcpy socket strcasecmp strchr strdup strerror strncasecmp strtol getaddrinfo getnameinfo freeaddrinfo gai_strerror sigaction sigprocmask strptime setusercontext initgroups setresuid setreuid setresgid setregid getpwnam])
# check if setreuid en setregid fail, on MacOSX10.4(darwin8).
@@ -527,7 +532,7 @@ AC_ARG_WITH([facility],
AC_DEFINE_UNQUOTED([FACILITY], $facility, [Define to the default facility for syslog.])
dnl
-dnl Determine the maximum number of interfaces that are allowed
+dnl Determine the maximum number of ip-addresses that are allowed
dnl
max_ips=8
AC_ARG_WITH([max_ips],
diff --git a/usr.sbin/nsd/dns.c b/usr.sbin/nsd/dns.c
index ec227f9f5d9..c54e120a012 100644
--- a/usr.sbin/nsd/dns.c
+++ b/usr.sbin/nsd/dns.c
@@ -88,39 +88,9 @@ static rrtype_descriptor_type rrtype_descriptors[(RRTYPE_DESCRIPTORS_LENGTH+1)]
{ RDATA_WF_SHORT, RDATA_WF_COMPRESSED_DNAME },
{ RDATA_ZF_SHORT, RDATA_ZF_DNAME } },
/* 16 */
- { TYPE_TXT, "TXT", T_TXT, 1, MAXRDATALEN,
- { RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT,
- RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT,
- RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT,
- RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT,
- RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT,
- RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT,
- RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT,
- RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT,
- RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT,
- RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT,
- RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT,
- RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT,
- RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT,
- RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT,
- RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT,
- RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT, RDATA_WF_TEXT },
- { RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT,
- RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT,
- RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT,
- RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT,
- RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT,
- RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT,
- RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT,
- RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT,
- RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT,
- RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT,
- RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT,
- RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT,
- RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT,
- RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT,
- RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT,
- RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT, RDATA_ZF_TEXT } },
+ { TYPE_TXT, "TXT", T_TXT, 1, 1,
+ { RDATA_WF_TEXTS },
+ { RDATA_ZF_TEXTS } },
/* 17 */
{ TYPE_RP, "RP", T_RP, 2, 2,
{ RDATA_WF_COMPRESSED_DNAME, RDATA_WF_COMPRESSED_DNAME },
diff --git a/usr.sbin/nsd/dns.h b/usr.sbin/nsd/dns.h
index 650d6fa8883..5e53ec13bea 100644
--- a/usr.sbin/nsd/dns.h
+++ b/usr.sbin/nsd/dns.h
@@ -146,7 +146,7 @@ typedef enum nsd_rc nsd_rc_type;
#define MAXLABELLEN 63
#define MAXDOMAINLEN 255
-#define MAXRDATALEN 64 /* This is more than enough, think multiple TXT. */
+#define MAXRDATALEN 64 /* This is more than enough, think multiple TXT. */
#define MAX_RDLENGTH 65535
/* Maximum size of a single RR. */
@@ -168,6 +168,7 @@ enum rdata_wireformat
RDATA_WF_SHORT, /* 16-bit integer. */
RDATA_WF_LONG, /* 32-bit integer. */
RDATA_WF_TEXT, /* Text string. */
+ RDATA_WF_TEXTS, /* Text string sequence. */
RDATA_WF_A, /* 32-bit IPv4 address. */
RDATA_WF_AAAA, /* 128-bit IPv6 address. */
RDATA_WF_BINARY, /* Binary data (unknown length). */
@@ -185,6 +186,7 @@ enum rdata_zoneformat
RDATA_ZF_DNAME, /* Domain name. */
RDATA_ZF_LITERAL_DNAME, /* DNS name (not lowercased domain name). */
RDATA_ZF_TEXT, /* Text string. */
+ RDATA_ZF_TEXTS, /* Text string sequence. */
RDATA_ZF_BYTE, /* 8-bit integer. */
RDATA_ZF_SHORT, /* 16-bit integer. */
RDATA_ZF_LONG, /* 32-bit integer. */
@@ -215,8 +217,8 @@ struct rrtype_descriptor
uint16_t type; /* RR type */
const char *name; /* Textual name. */
int token; /* Parser token. */
- uint8_t minimum; /* Minimum number of RDATAs. */
- uint8_t maximum; /* Maximum number of RDATAs. */
+ uint32_t minimum; /* Minimum number of RDATAs. */
+ uint32_t maximum; /* Maximum number of RDATAs. */
uint8_t wireformat[MAXRDATALEN]; /* rdata_wireformat_type */
uint8_t zoneformat[MAXRDATALEN]; /* rdata_zoneformat_type */
};
diff --git a/usr.sbin/nsd/mkinstalldirs b/usr.sbin/nsd/mkinstalldirs
index 2c8850ef89b..a246f542699 100644
--- a/usr.sbin/nsd/mkinstalldirs
+++ b/usr.sbin/nsd/mkinstalldirs
@@ -4,7 +4,7 @@
# Created: 1993-05-16
# Public domain
-# $Id: mkinstalldirs,v 1.1 2010/01/15 19:24:49 jakob Exp $
+# $Id: mkinstalldirs,v 1.2 2011/01/27 12:29:14 jakob Exp $
errstatus=0
diff --git a/usr.sbin/nsd/nsd-checkconf.c b/usr.sbin/nsd/nsd-checkconf.c
index 8210bc65f91..e19cbd4c4b6 100644
--- a/usr.sbin/nsd/nsd-checkconf.c
+++ b/usr.sbin/nsd/nsd-checkconf.c
@@ -99,6 +99,7 @@ usage(void)
fprintf(stderr, "-h Print this help information.\n");
fprintf(stderr, "-o option Print value of the option specified to stdout.\n");
fprintf(stderr, "-z zonename Print option value for the zone given.\n");
+ fprintf(stderr, "-a keyname Print algorithm name for the TSIG key.\n");
fprintf(stderr, "-s keyname Print base64 secret blob for the TSIG key.\n");
exit(1);
}
@@ -184,7 +185,7 @@ print_acl(const char* varname, acl_options_t* acl)
void
-config_print_zone(nsd_options_t* opt, const char* k, const char *o, const char *z)
+config_print_zone(nsd_options_t* opt, const char* k, int s, const char *o, const char *z)
{
zone_options_t* zone;
ip_address_option_t* ip;
@@ -194,7 +195,11 @@ config_print_zone(nsd_options_t* opt, const char* k, const char *o, const char *
key_options_t* key = opt->keys;
for( ; key ; key=key->next) {
if(strcmp(key->name, k) == 0) {
- quote(key->secret);
+ if (s) {
+ quote(key->secret);
+ } else {
+ quote(key->algorithm);
+ }
return;
}
}
@@ -456,14 +461,18 @@ main(int argc, char* argv[])
{
int c;
int verbose = 0;
+ int key_sec = 0;
const char * conf_opt = NULL; /* what option do you want? Can be NULL -> print all */
const char * conf_zone = NULL; /* what zone are we talking about */
const char * conf_key = NULL; /* what key is needed */
const char* configfile;
nsd_options_t *options;
+ log_init("nsd-checkconf");
+
+
/* Parse the command line... */
- while ((c = getopt(argc, argv, "vo:s:z:")) != -1) {
+ while ((c = getopt(argc, argv, "vo:a:s:z:")) != -1) {
switch (c) {
case 'v':
verbose = 1;
@@ -471,8 +480,20 @@ main(int argc, char* argv[])
case 'o':
conf_opt = optarg;
break;
+ case 'a':
+ if (conf_key) {
+ fprintf(stderr, "Error: cannot combine -a with -s or other -a.\n");
+ exit(1);
+ }
+ conf_key = optarg;
+ break;
case 's':
+ if (conf_key) {
+ fprintf(stderr, "Error: cannot combine -s with -a or other -s.\n");
+ exit(1);
+ }
conf_key = optarg;
+ key_sec = 1;
break;
case 'z':
conf_zone = optarg;
@@ -495,7 +516,7 @@ main(int argc, char* argv[])
exit(2);
}
if (conf_opt || conf_key) {
- config_print_zone(options, conf_key, underscore(conf_opt), conf_zone);
+ config_print_zone(options, conf_key, key_sec, underscore(conf_opt), conf_zone);
} else {
if (verbose) {
printf("# Read file %s: %d zones, %d keys.\n",
diff --git a/usr.sbin/nsd/nsd-notify.c b/usr.sbin/nsd/nsd-notify.c
index 5029cacc4b3..9929a3917a0 100644
--- a/usr.sbin/nsd/nsd-notify.c
+++ b/usr.sbin/nsd/nsd-notify.c
@@ -213,7 +213,7 @@ add_key(region_type* region, const char* opt, tsig_algorithm_type** algo)
*algo = tsig_get_algorithm_by_name("hmac-md5");
else {
char* by_name = (char*) malloc(sizeof(char)*(5+strlen(delim2)));
- snprintf(by_name, 5+strlen(delim2), "hmac-%s", delim2+1);
+ snprintf(by_name, 5+strlen(delim2), "%s", delim2+1);
*algo = tsig_get_algorithm_by_name(by_name);
free(by_name);
*delim2 = '\0';
diff --git a/usr.sbin/nsd/nsd-patch.c b/usr.sbin/nsd/nsd-patch.c
index 46d4afeebc6..ca429f5a578 100644
--- a/usr.sbin/nsd/nsd-patch.c
+++ b/usr.sbin/nsd/nsd-patch.c
@@ -57,7 +57,7 @@ list_xfr(FILE *in)
return;
}
skiplen = len - (sizeof(uint32_t)*3 + sizeof(uint16_t) + strlen(zone_name));
- fprintf(stdout, "zone %s transfer id %x serial %d timestamp %u.%u: "
+ fprintf(stdout, "zone %s transfer id %x serial %u timestamp %u.%u: "
"seq_nr %d of %d bytes\n", zone_name, id, new_serial,
timestamp[0], timestamp[1], seq_nr, skiplen);
@@ -243,7 +243,7 @@ write_to_zonefile(struct zone* zone, struct diff_log* commit_log)
time_t now = time(0);
FILE *out;
- fprintf(stderr, "writing zone %s to file %s\n", zone->opts->name,
+ fprintf(stdout, "writing zone %s to file %s\n", zone->opts->name,
filename);
if(!zone->apex) {
diff --git a/usr.sbin/nsd/nsdc.sh.in b/usr.sbin/nsd/nsdc.sh.in
index c3dab0087f0..dd01812f643 100644
--- a/usr.sbin/nsd/nsdc.sh.in
+++ b/usr.sbin/nsd/nsdc.sh.in
@@ -230,20 +230,10 @@ do_reload() {
signal "HUP"
}
-# send_updates zone_name ifc_spec {ip_spec key_spec}
+# send_updates zone_name {ip_spec key_spec}
send_updates() {
local zonename=$1
- # set local interface
- ifc_spec=""
- if test I$2 = INOKEY; then
- return
- fi
- if test I$2 != INOKEY -a I$2 != INOIFC; then
- ifc_spec="-a $2"
- fi
-
- shift 2
-
+ shift 1
# extract port number (if any)
port=`${nsd_checkconf} -o port ${configfile}`
if test -n "${port}"; then
@@ -261,12 +251,12 @@ send_updates() {
secret=""
if test K${key_spec} != KNOKEY -a K${key_spec} != KBLOCKED; then
secret=`${nsd_checkconf} -s ${key_spec} ${configfile}`
- secret="-y ${key_spec}:${secret}"
+ algo=`${nsd_checkconf} -a ${key_spec} ${configfile}`
+ secret="-y ${key_spec}:${secret}:${algo}"
fi
if test K${key_spec} != KBLOCKED; then
- #echo "${sbindir}/nsd-notify ${ifc_spec} ${port} -z ${zonename} ${ip_spec} # with ${key_spec}"
- ${sbindir}/nsd-notify ${ifc_spec} ${port} ${secret} \
- -z ${zonename} ${ip_spec} && update_sent="yes"
+ #echo "${sbindir}/nsd-notify -a ${ip_spec} ${port} ${secret} -z ${zonename} ${ip_spec}"
+ ${sbindir}/nsd-notify -a ${ip_spec} ${port} ${secret} -z ${zonename} ${ip_spec} && update_sent="yes"
fi
fi
done
@@ -279,16 +269,12 @@ send_updates() {
fi
}
-# send_notify zone_name {ifc_spec} {ip_spec key_spec}
+# send_notify zone_name ifc_spec {ip_spec key_spec}
send_notify() {
local zonename=$1
# set local interface
ifc_spec=""
- if test I$2 = INOKEY; then
- return
- fi
-
- if test I$2 != INOKEY -a I$2 != INOIFC; then
+ if test I$2 != INOIFC; then
ifc_spec="-a $2"
fi
shift 2
@@ -301,7 +287,8 @@ send_notify() {
if test K${key_spec} != KNOKEY -a K${key_spec} != KBLOCKED; then
secret=`${nsd_checkconf} -s ${key_spec} ${configfile}`
- secret="-y ${key_spec}:${secret}"
+ algo=`${nsd_checkconf} -a ${key_spec} ${configfile}`
+ secret="-y ${key_spec}:${secret}:${algo}"
fi
if test K${key_spec} != KBLOCKED; then
port=""
@@ -310,9 +297,8 @@ send_notify() {
port="-p "`echo ${ip_spec} | sed -e 's/[^@]*@\([0-9]*\)/\1/'`
ipaddr=`echo ${ip_spec} | sed -e 's/\([^@]*\)@[0-9]*/\1/'`
fi
- #echo "${sbindir}/nsd-notify ${ifc_spec} ${port} -z ${zonename} ${ip_spec} # with ${key_spec}"
- ${sbindir}/nsd-notify ${ifc_spec} ${port} ${secret} \
- -z ${zonename} ${ipaddr}
+ #echo "${sbindir}/nsd-notify ${ifc_spec} ${port} ${secret} -z ${zonename} ${ipaddr}"
+ ${sbindir}/nsd-notify ${ifc_spec} ${port} ${secret} -z ${zonename} ${ipaddr}
fi
done
}
@@ -381,7 +367,7 @@ patch)
mv ${difffile}.$$ ${difffile}
fi
echo "`basename $0`: patch failed."
- return 1
+ exit 1
fi
else
echo "`basename $0`: no patch necessary."
@@ -397,14 +383,8 @@ update)
zoneslist=`${nsd_checkconf} -o zones ${configfile}`
for zonename in ${zoneslist}; do
notify_allow=`${nsd_checkconf} -z "${zonename}" -o allow-notify ${configfile}`
- local_ifc=`${nsd_checkconf} -z "${zonename}" -o outgoing-interface ${configfile}`
- if test "" = "${local_ifc}"; then
- local_ifc="NOIFC"
- fi
if test "" != "${notify_allow}"; then
- for ifc in ${local_ifc}; do
- send_updates ${zonename} ${ifc} ${notify_allow}
- done
+ send_updates ${zonename} ${notify_allow}
fi
done
else
diff --git a/usr.sbin/nsd/nsec3.c b/usr.sbin/nsd/nsec3.c
index b285e9a28be..8197d47c28b 100644
--- a/usr.sbin/nsd/nsec3.c
+++ b/usr.sbin/nsd/nsec3.c
@@ -475,7 +475,7 @@ nsec3_answer_wildcard(struct query *query, struct answer *answer,
static void
nsec3_add_ds_proof(struct query *query, struct answer *answer,
- struct domain *domain)
+ struct domain *domain, int delegpt)
{
/* assert we are above the zone cut */
assert(domain != query->zone->apex);
@@ -483,10 +483,14 @@ nsec3_add_ds_proof(struct query *query, struct answer *answer,
/* use NSEC3 record from above the zone cut. */
nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
domain->nsec3_ds_parent_cover);
+ } else if (!delegpt && domain->nsec3_is_exact) {
+ nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
+ domain->nsec3_cover);
} else {
/* prove closest provable encloser */
domain_type* par = domain->parent;
domain_type* prev_par = 0;
+
while(par && !par->nsec3_is_exact)
{
prev_par = par;
@@ -528,7 +532,7 @@ nsec3_answer_nodata(struct query *query, struct answer *answer,
return;
}
/* query->zone must be the parent zone */
- nsec3_add_ds_proof(query, answer, original);
+ nsec3_add_ds_proof(query, answer, original, 0);
}
/* the nodata is result from a wildcard match */
else if (original==original->wildcard_child_closest_match
@@ -554,7 +558,7 @@ nsec3_answer_delegation(struct query *query, struct answer *answer)
{
if(!query->zone->nsec3_soa_rr)
return;
- nsec3_add_ds_proof(query, answer, query->delegation_domain);
+ nsec3_add_ds_proof(query, answer, query->delegation_domain, 1);
}
int
diff --git a/usr.sbin/nsd/query.c b/usr.sbin/nsd/query.c
index 758d6e0877e..6e36fe036e3 100644
--- a/usr.sbin/nsd/query.c
+++ b/usr.sbin/nsd/query.c
@@ -39,9 +39,10 @@
#include "tsig.h"
/* [Bug #253] Adding unnecessary NS RRset may lead to undesired truncation.
- * This function determines if the final response packet needs the NS RRset included.
- * Currently, it will only return negative if QTYPE == DNSKEY. This way, resolvers
- * won't fallback to TCP unnecessarily when priming DNSKEYs.
+ * This function determines if the final response packet needs the NS RRset
+ * included. Currently, it will only return negative if QTYPE == DNSKEY|DS.
+ * This way, resolvers won't fallback to TCP unnecessarily when priming
+ * trust anchors.
*/
static int answer_needs_ns(struct query *query);
@@ -176,12 +177,10 @@ query_create(region_type *region, uint16_t *compressed_dname_offsets,
query->packet = buffer_create(region, QIOBUFSZ);
region_add_cleanup(region, query_cleanup, query);
query->compressed_dname_offsets_size = compressed_dname_size;
-#ifdef TSIG
tsig_create_record(&query->tsig, region);
query->tsig_prepare_it = 1;
query->tsig_update_it = 1;
query->tsig_sign_it = 1;
-#endif /* TSIG */
return query;
}
@@ -205,12 +204,10 @@ query_reset(query_type *q, size_t maxlen, int is_tcp)
q->reserved_space = 0;
buffer_clear(q->packet);
edns_init_record(&q->edns);
-#ifdef TSIG
tsig_init_record(&q->tsig, NULL, NULL);
q->tsig_prepare_it = 1;
q->tsig_update_it = 1;
q->tsig_sign_it = 1;
-#endif /* TSIG */
q->tcp = is_tcp;
q->qname = NULL;
q->qtype = 0;
@@ -355,7 +352,6 @@ process_edns(nsd_type* nsd, struct query *q)
* Processes TSIG.
* Sets error when tsig does not verify on the query.
*/
-#ifdef TSIG
static nsd_rc_type
process_tsig(struct query* q)
{
@@ -380,7 +376,6 @@ process_tsig(struct query* q)
}
return NSD_RC_OK;
}
-#endif /* TSIG */
/*
* Check notify acl and forward to xfrd (or return an error).
@@ -403,7 +398,6 @@ answer_notify(struct nsd* nsd, struct query *query)
if(!nsd->this_child) /* we are in debug mode or something */
return query_error(query, NSD_RC_SERVFAIL);
-#ifdef TSIG
if(!tsig_find_rr(&query->tsig, query->packet)) {
DEBUG(DEBUG_XFRD,2, (LOG_ERR, "bad tsig RR format"));
return query_error(query, NSD_RC_FORMAT);
@@ -411,7 +405,6 @@ answer_notify(struct nsd* nsd, struct query *query)
rc = process_tsig(query);
if(rc != NSD_RC_OK)
return query_error(query, rc);
-#endif /* TSIG */
/* check if it passes acl */
if((acl_num = acl_check_incoming(zone_opt->allow_notify, query,
@@ -625,8 +618,9 @@ static int
answer_needs_ns(struct query* query)
{
assert(query);
- /* Currently, only troublesome for DNSKEYs, cuz their RRSETs are quite large. */
- return (query->qtype != TYPE_DNSKEY);
+ /* Currently, only troublesome for DNSKEY and DS,
+ * cuz their RRSETs are quite large. */
+ return (query->qtype != TYPE_DNSKEY && query->qtype != TYPE_DS);
}
static int
@@ -1220,9 +1214,7 @@ query_prepare_response(query_type *q)
* Reserve space for the EDNS records if required.
*/
q->reserved_space = edns_reserved_space(&q->edns);
-#ifdef TSIG
q->reserved_space += tsig_reserved_space(&q->tsig);
-#endif /* TSIG */
/* Update the flags. */
flags = FLAGS(q->packet);
@@ -1292,7 +1284,6 @@ query_process(query_type *q, nsd_type *nsd)
}
arcount = ARCOUNT(q->packet);
-#ifdef TSIG
if (arcount > 0) {
/* see if tsig is before edns record */
if (!tsig_parse_rr(&q->tsig, q->packet))
@@ -1300,12 +1291,10 @@ query_process(query_type *q, nsd_type *nsd)
if(q->tsig.status != TSIG_NOT_PRESENT)
--arcount;
}
-#endif /* TSIG */
if (arcount > 0) {
if (edns_parse_record(&q->edns, q->packet))
--arcount;
}
-#ifdef TSIG
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))
@@ -1313,7 +1302,6 @@ query_process(query_type *q, nsd_type *nsd)
if(q->tsig.status != TSIG_NOT_PRESENT)
--arcount;
}
-#endif /* TSIG */
if (arcount > 0) {
return query_formerr(q);
}
@@ -1328,12 +1316,10 @@ query_process(query_type *q, nsd_type *nsd)
/* Remove trailing garbage. */
buffer_set_limit(q->packet, buffer_position(q->packet));
-#ifdef TSIG
rc = process_tsig(q);
if (rc != NSD_RC_OK) {
return query_error(q, rc);
}
-#endif /* TSIG */
rc = process_edns(nsd, q);
if (rc != NSD_RC_OK) {
/* We should not return FORMERR, but BADVERS (=16).
@@ -1377,8 +1363,6 @@ query_add_optional(query_type *q, nsd_type *nsd)
break;
case EDNS_OK:
buffer_write(q->packet, edns->ok, OPT_LEN);
- /* check if nsid data should be written */
-#ifdef NSID
if (nsd->nsid_len > 0 && q->edns.nsid == 1 &&
!query_overflow_nsid(q, nsd->nsid_len)) {
/* rdata length */
@@ -1391,12 +1375,7 @@ query_add_optional(query_type *q, nsd_type *nsd)
/* fill with NULLs */
buffer_write(q->packet, edns->rdata_none, OPT_RDATA);
}
-#else
- buffer_write(q->packet, edns->rdata_none, OPT_RDATA);
-#endif /* NSID */
-
ARCOUNT_SET(q->packet, ARCOUNT(q->packet) + 1);
-
STATUP(nsd, edns);
break;
case EDNS_ERROR:
@@ -1407,7 +1386,6 @@ query_add_optional(query_type *q, nsd_type *nsd)
break;
}
-#ifdef TSIG
if (q->tsig.status != TSIG_NOT_PRESENT) {
if (q->tsig.status == TSIG_ERROR ||
q->tsig.error_code != TSIG_ERROR_NOERROR) {
@@ -1428,5 +1406,4 @@ query_add_optional(query_type *q, nsd_type *nsd)
}
}
}
-#endif /* TSIG */
}
diff --git a/usr.sbin/nsd/rdata.c b/usr.sbin/nsd/rdata.c
index 26f4b703b8c..796eda55a94 100644
--- a/usr.sbin/nsd/rdata.c
+++ b/usr.sbin/nsd/rdata.c
@@ -87,11 +87,17 @@ rdata_dns_name_to_string(buffer_type *output, rdata_atom_type rdata,
buffer_printf(output, ".");
for (i = 1; i <= length; ++i) {
- char ch = (char) data[i+offset];
- if (isprint((int)ch))
- buffer_printf(output, "%c", ch);
- else
- buffer_printf(output, "\\%03u", (unsigned) ch);
+ uint8_t ch = data[i+offset];
+
+ if (ch=='.' || ch==';' || ch=='(' || ch==')' || ch=='\\') {
+ buffer_printf(output, "\\%c", (char) ch);
+ } else if (!isgraph((int) ch)) {
+ buffer_printf(output, "\\%03u", (unsigned int) ch);
+ } else if (isprint((int) ch)) {
+ buffer_printf(output, "%c", (char) ch);
+ } else {
+ buffer_printf(output, "\\%03u", (unsigned int) ch);
+ }
}
/* next label */
offset = offset+length+1;
@@ -128,6 +134,34 @@ rdata_text_to_string(buffer_type *output, rdata_atom_type rdata,
}
static int
+rdata_texts_to_string(buffer_type *output, rdata_atom_type rdata,
+ rr_type* ATTR_UNUSED(rr))
+{
+ uint16_t pos = 0;
+ const uint8_t *data = rdata_atom_data(rdata);
+ uint16_t length = rdata_atom_size(rdata);
+ size_t i;
+
+ while (pos < length && pos + data[pos] < length) {
+ buffer_printf(output, "\"");
+ for (i = 1; i <= data[pos]; ++i) {
+ char ch = (char) data[pos + i];
+ if (isprint((int)ch)) {
+ if (ch == '"' || ch == '\\') {
+ buffer_printf(output, "\\");
+ }
+ buffer_printf(output, "%c", ch);
+ } else {
+ buffer_printf(output, "\\%03u", (unsigned) ch);
+ }
+ }
+ pos += data[pos]+1;
+ buffer_printf(output, pos < length?"\" ":"\"");
+ }
+ return 1;
+}
+
+static int
rdata_byte_to_string(buffer_type *output, rdata_atom_type rdata,
rr_type* ATTR_UNUSED(rr))
{
@@ -509,6 +543,7 @@ static rdata_to_string_type rdata_to_string_table[RDATA_ZF_UNKNOWN + 1] = {
rdata_dname_to_string,
rdata_dns_name_to_string,
rdata_text_to_string,
+ rdata_texts_to_string,
rdata_byte_to_string,
rdata_short_to_string,
rdata_long_to_string,
@@ -549,7 +584,7 @@ rdata_wireformat_to_rdata_atoms(region_type *region,
rdata_atom_type **rdatas)
{
size_t end = buffer_position(packet) + data_size;
- ssize_t i;
+ size_t i;
rdata_atom_type temp_rdatas[MAXRDATALEN];
rrtype_descriptor_type *descriptor = rrtype_descriptor_by_type(rrtype);
region_type *temp_region;
@@ -588,6 +623,9 @@ rdata_wireformat_to_rdata_atoms(region_type *region,
case RDATA_WF_LONG:
length = sizeof(uint32_t);
break;
+ case RDATA_WF_TEXTS:
+ length = data_size;
+ break;
case RDATA_WF_TEXT:
case RDATA_WF_BINARYWITHLENGTH:
/* Length is stored in the first byte. */
@@ -687,7 +725,7 @@ rdata_wireformat_to_rdata_atoms(region_type *region,
*rdatas = (rdata_atom_type *) region_alloc_init(
region, temp_rdatas, i * sizeof(rdata_atom_type));
region_destroy(temp_region);
- return i;
+ return (ssize_t)i;
}
size_t
diff --git a/usr.sbin/nsd/server.c b/usr.sbin/nsd/server.c
index c0a84dafe0b..6640a653aa8 100644
--- a/usr.sbin/nsd/server.c
+++ b/usr.sbin/nsd/server.c
@@ -29,6 +29,9 @@
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
+#ifndef SHUT_WR
+#define SHUT_WR 1
+#endif
#include "axfr.h"
#include "namedb.h"
@@ -567,7 +570,7 @@ close_all_sockets(struct nsd_socket sockets[], size_t n)
for (i = 0; i < n; ++i) {
if (sockets[i].s != -1) {
close(sockets[i].s);
- free(sockets[i].addr);
+ freeaddrinfo(sockets[i].addr);
sockets[i].s = -1;
}
}
@@ -771,6 +774,16 @@ server_reload(struct nsd *nsd, region_type* server_region, netio_type* netio,
exit(1);
}
+ /* if the parent has quit, we must quit too, poll the fd for cmds */
+ if(block_read(nsd, cmdsocket, &cmd, sizeof(cmd), 0) == sizeof(cmd)) {
+ DEBUG(DEBUG_IPC,1, (LOG_INFO, "reload: ipc command from main %d", cmd));
+ if(cmd == NSD_QUIT) {
+ DEBUG(DEBUG_IPC,1, (LOG_INFO, "reload: quit to follow nsd"));
+ send_children_quit(nsd);
+ exit(0);
+ }
+ }
+
/* Overwrite pid before closing old parent, to avoid race condition:
* - parent process already closed
* - pidfile still contains old_pid
@@ -802,6 +815,12 @@ server_reload(struct nsd *nsd, region_type* server_region, netio_type* netio,
strerror(errno));
}
DEBUG(DEBUG_IPC,1, (LOG_INFO, "reload: ipc reply main %d %d", ret, cmd));
+ if(cmd == NSD_QUIT) {
+ /* small race condition possible here, parent got quit cmd. */
+ send_children_quit(nsd);
+ unlinkpid(nsd->pidfile);
+ exit(1);
+ }
assert(ret==-1 || ret == 0 || cmd == NSD_RELOAD);
/* inform xfrd of new SOAs */
@@ -1114,8 +1133,8 @@ server_main(struct nsd *nsd)
/* only quit children after xfrd has acked */
send_children_quit(nsd);
+ namedb_fd_close(nsd->db);
region_destroy(server_region);
- namedb_close(nsd->db);
server_shutdown(nsd);
/* ENOTREACH */
@@ -1150,8 +1169,17 @@ server_main(struct nsd *nsd)
/* Unlink it if possible... */
unlinkpid(nsd->pidfile);
- if(reload_listener.fd > 0)
+ if(reload_listener.fd > 0) {
+ sig_atomic_t cmd = NSD_QUIT;
+ DEBUG(DEBUG_IPC,1, (LOG_INFO,
+ "main: ipc send quit to reload-process"));
+ if(!write_socket(reload_listener.fd, &cmd, sizeof(cmd))) {
+ log_msg(LOG_ERR, "server_main: could not send quit to reload: %s",
+ strerror(errno));
+ }
+ fsync(reload_listener.fd);
close(reload_listener.fd);
+ }
if(xfrd_listener.fd > 0) {
/* complete quit, stop xfrd */
sig_atomic_t cmd = NSD_QUIT;
@@ -1165,7 +1193,7 @@ server_main(struct nsd *nsd)
close(xfrd_listener.fd);
}
- namedb_close(nsd->db);
+ namedb_fd_close(nsd->db);
region_destroy(server_region);
server_shutdown(nsd);
}
@@ -1324,7 +1352,7 @@ server_child(struct nsd *nsd)
bind8_stats(nsd);
#endif /* BIND8_STATS */
- namedb_close(nsd->db);
+ namedb_fd_close(nsd->db);
region_destroy(server_region);
server_shutdown(nsd);
}
diff --git a/usr.sbin/nsd/util.c b/usr.sbin/nsd/util.c
index c9f41aedde3..ab374c2b3e0 100644
--- a/usr.sbin/nsd/util.c
+++ b/usr.sbin/nsd/util.c
@@ -834,7 +834,13 @@ compare_serial(uint32_t a, uint32_t b)
uint16_t
qid_generate(void)
{
- return (uint16_t) arc4random();
+#ifdef HAVE_ARC4RANDOM_UNIFORM
+ return (uint16_t) arc4random_uniform(65536);
+#elif HAVE_ARC4RANDOM
+ return (uint16_t) arc4random();
+#else
+ return (uint16_t) random();
+#endif
}
void
diff --git a/usr.sbin/nsd/zonec.c b/usr.sbin/nsd/zonec.c
index 34a58569def..f7a63c26658 100644
--- a/usr.sbin/nsd/zonec.c
+++ b/usr.sbin/nsd/zonec.c
@@ -935,7 +935,7 @@ zparser_ttl2int(const char *ttlstr, int* error)
void
zadd_rdata_wireformat(uint16_t *data)
{
- if (parser->current_rr.rdata_count > MAXRDATALEN) {
+ if (parser->current_rr.rdata_count >= MAXRDATALEN) {
zc_error_prev_line("too many rdata elements");
} else {
parser->current_rr.rdatas[parser->current_rr.rdata_count].data
@@ -944,10 +944,62 @@ zadd_rdata_wireformat(uint16_t *data)
}
}
+/**
+ * Used for TXT RR's to grow with undefined number of strings.
+ */
+void
+zadd_rdata_txt_wireformat(uint16_t *data, int first)
+{
+ rdata_atom_type *rd;
+
+ /* First STR in str_seq, allocate 65K in first unused rdata
+ * else find last used rdata */
+ if (first) {
+ rd = &parser->current_rr.rdatas[parser->current_rr.rdata_count];
+ if ((rd->data = (uint16_t *) region_alloc(parser->rr_region,
+ sizeof(uint16_t) + 65535 * sizeof(uint8_t))) == NULL) {
+ zc_error_prev_line("Could not allocate memory for TXT RR");
+ return;
+ }
+ parser->current_rr.rdata_count++;
+ rd->data[0] = 0;
+ }
+ else
+ rd = &parser->current_rr.rdatas[parser->current_rr.rdata_count-1];
+
+ if ((size_t)rd->data[0] + (size_t)data[0] > 65535) {
+ zc_error_prev_line("too large rdata element");
+ return;
+ }
+
+ memcpy((uint8_t *)rd->data + 2 + rd->data[0], data + 1, data[0]);
+ rd->data[0] += data[0];
+}
+
+/**
+ * Clean up after last call of zadd_rdata_txt_wireformat
+ */
+void
+zadd_rdata_txt_clean_wireformat()
+{
+ uint16_t *tmp_data;
+ rdata_atom_type *rd = &parser->current_rr.rdatas[parser->current_rr.rdata_count-1];
+ if ((tmp_data = (uint16_t *) region_alloc(parser->region,
+ rd->data[0] + 2)) != NULL) {
+ memcpy(tmp_data, rd->data, rd->data[0] + 2);
+ rd->data = tmp_data;
+ }
+ else {
+ /* We could not get memory in non-volatile region */
+ zc_error_prev_line("could not allocate memory for rdata");
+ return;
+ }
+}
+
void
zadd_rdata_domain(domain_type *domain)
{
- if (parser->current_rr.rdata_count > MAXRDATALEN) {
+ if (parser->current_rr.rdata_count >= MAXRDATALEN) {
zc_error_prev_line("too many rdata elements");
} else {
parser->current_rr.rdatas[parser->current_rr.rdata_count].domain
@@ -1260,10 +1312,10 @@ domain_find_rrset_any(domain_type *domain, uint16_t type)
while (result) {
if (rrset_rrtype(result) == type) {
return result;
- }
+ }
result = result->next;
- }
- return NULL;
+ }
+ return NULL;
}
/*
@@ -1556,8 +1608,12 @@ main (int argc, char **argv)
/* Print the total number of errors */
if (vflag > 0 || totalerrors > 0) {
- fprintf(stderr, "\nnsd-zonec: done with %ld errors.\n",
+ if (totalerrors > 0) {
+ fprintf(stderr, "\nnsd-zonec: done with %ld errors.\n",
totalerrors);
+ } else {
+ fprintf(stdout, "\nnsd-zonec: done with no errors.\n");
+ }
}
/* Disable this to save some time. */
diff --git a/usr.sbin/nsd/zonec.h b/usr.sbin/nsd/zonec.h
index f732377740d..9bf7a4b6642 100644
--- a/usr.sbin/nsd/zonec.h
+++ b/usr.sbin/nsd/zonec.h
@@ -108,6 +108,8 @@ void parse_unknown_rdata(uint16_t type, uint16_t *wireformat);
uint32_t zparser_ttl2int(const char *ttlstr, int* error);
void zadd_rdata_wireformat(uint16_t *data);
+void zadd_rdata_txt_wireformat(uint16_t *data, int first);
+void zadd_rdata_txt_clean_wireformat();
void zadd_rdata_domain(domain_type *domain);
void set_bitnsec(uint8_t bits[NSEC_WINDOW_COUNT][NSEC_WINDOW_BITS_SIZE],
diff --git a/usr.sbin/nsd/zparser.y b/usr.sbin/nsd/zparser.y
index 0b50b172ede..a5e896553dd 100644
--- a/usr.sbin/nsd/zparser.y
+++ b/usr.sbin/nsd/zparser.y
@@ -334,11 +334,11 @@ wire_rel_dname: wire_label
str_seq: STR
{
- zadd_rdata_wireformat(zparser_conv_text(parser->region, $1.str, $1.len));
+ zadd_rdata_txt_wireformat(zparser_conv_text(parser->region, $1.str, $1.len), 1);
}
| str_seq sp STR
{
- zadd_rdata_wireformat(zparser_conv_text(parser->region, $3.str, $3.len));
+ zadd_rdata_txt_wireformat(zparser_conv_text(parser->region, $3.str, $3.len), 0);
}
;
@@ -661,6 +661,9 @@ rdata_mx: STR sp dname trail
;
rdata_txt: str_seq trail
+ {
+ zadd_rdata_txt_clean_wireformat();
+ }
;
/* RFC 1183 */