summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsthen <sthen@openbsd.org>2015-11-05 21:21:58 +0000
committersthen <sthen@openbsd.org>2015-11-05 21:21:58 +0000
commite3d8a0a5f9ff3b25a81f272af3e295c86fe9495b (patch)
tree0cd5419500a768e3c664148d9ad6c079a759d24f
parentupdate to NSD 4.1.6, ok millert@ florian@ (diff)
downloadwireguard-openbsd-e3d8a0a5f9ff3b25a81f272af3e295c86fe9495b.tar.xz
wireguard-openbsd-e3d8a0a5f9ff3b25a81f272af3e295c86fe9495b.zip
merge
-rw-r--r--usr.sbin/nsd/axfr.c9
-rw-r--r--usr.sbin/nsd/config.h.in6
-rw-r--r--usr.sbin/nsd/configparser.y13
-rw-r--r--usr.sbin/nsd/configure138
-rw-r--r--usr.sbin/nsd/configure.ac19
-rw-r--r--usr.sbin/nsd/dns.c4
-rw-r--r--usr.sbin/nsd/dns.h2
-rw-r--r--usr.sbin/nsd/mkinstalldirs2
-rw-r--r--usr.sbin/nsd/nsd-checkconf.8.in2
-rw-r--r--usr.sbin/nsd/nsd-checkconf.c19
-rw-r--r--usr.sbin/nsd/nsd-control.8.in2
-rw-r--r--usr.sbin/nsd/nsd.8.in20
-rw-r--r--usr.sbin/nsd/nsd.c96
-rw-r--r--usr.sbin/nsd/nsd.conf.5.in27
-rw-r--r--usr.sbin/nsd/options.c40
-rw-r--r--usr.sbin/nsd/query.c12
-rw-r--r--usr.sbin/nsd/remote.c6
-rw-r--r--usr.sbin/nsd/server.c174
-rw-r--r--usr.sbin/nsd/util.c3
-rw-r--r--usr.sbin/nsd/xfrd-tcp.c5
-rw-r--r--usr.sbin/nsd/zonec.c2
-rw-r--r--usr.sbin/nsd/zparser.y13
22 files changed, 440 insertions, 174 deletions
diff --git a/usr.sbin/nsd/axfr.c b/usr.sbin/nsd/axfr.c
index 3990a32ccb5..f7e0caacea2 100644
--- a/usr.sbin/nsd/axfr.c
+++ b/usr.sbin/nsd/axfr.c
@@ -91,7 +91,7 @@ query_axfr(struct nsd *nsd, struct query *query)
query->edns.status = EDNS_NOT_PRESENT;
buffer_set_limit(query->packet, QHEADERSZ);
QDCOUNT_SET(query->packet, 0);
- query_prepare_response(query);
+ query_prepare_response(query, nsd);
}
/* Add zone RRs until answer is full. */
@@ -193,6 +193,13 @@ answer_axfr_ixfr(struct nsd *nsd, struct query *q)
}
DEBUG(DEBUG_XFRD,1, (LOG_INFO, "axfr admitted acl %s %s",
acl->ip_address_spec, acl->key_name?acl->key_name:"NOKEY"));
+ if (verbosity >= 1) {
+ char a[128];
+ addr2str(&q->addr, a, sizeof(a));
+ VERBOSITY(1, (LOG_INFO, "%s for %s from %s",
+ (q->qtype==TYPE_AXFR?"axfr":"ixfr"),
+ dname_to_string(q->qname, NULL), a));
+ }
return query_axfr(nsd, q);
}
/** Fallthrough: AXFR over UDP queries are discarded. */
diff --git a/usr.sbin/nsd/config.h.in b/usr.sbin/nsd/config.h.in
index c8fd3a82a03..b2b1c3884dc 100644
--- a/usr.sbin/nsd/config.h.in
+++ b/usr.sbin/nsd/config.h.in
@@ -359,9 +359,6 @@
/* Define to the maximum message length to pass to syslog. */
#undef MAXSYSLOGMSGLEN
-/* Define to the maximum ip-addresses to serve. */
-#undef MAX_INTERFACES
-
/* Define if memcmp() does not compare unsigned bytes */
#undef MEMCMP_IS_BROKEN
@@ -417,6 +414,9 @@
/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE
+/* enable reuseport option by default. */
+#undef REUSEPORT_BY_DEFAULT
+
/* Define this to configure as a root server. */
#undef ROOT_SERVER
diff --git a/usr.sbin/nsd/configparser.y b/usr.sbin/nsd/configparser.y
index 6c55bac5195..03310ca27ba 100644
--- a/usr.sbin/nsd/configparser.y
+++ b/usr.sbin/nsd/configparser.y
@@ -67,7 +67,7 @@ extern config_parser_state_t* cfg_parser;
%token VAR_RRL_IPV4_PREFIX_LENGTH VAR_RRL_IPV6_PREFIX_LENGTH
%token VAR_RRL_WHITELIST_RATELIMIT VAR_RRL_WHITELIST
%token VAR_ZONEFILES_CHECK VAR_ZONEFILES_WRITE VAR_LOG_TIME_ASCII
-%token VAR_ROUND_ROBIN VAR_ZONESTATS
+%token VAR_ROUND_ROBIN VAR_ZONESTATS VAR_REUSEPORT
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@@ -96,7 +96,8 @@ content_server: server_ip_address | server_ip_transparent | server_debug_mode |
server_rrl_size | server_rrl_ratelimit | server_rrl_slip |
server_rrl_ipv4_prefix_length | server_rrl_ipv6_prefix_length | server_rrl_whitelist_ratelimit |
server_zonefiles_check | server_do_ip4 | server_do_ip6 |
- server_zonefiles_write | server_log_time_ascii | server_round_robin;
+ server_zonefiles_write | server_log_time_ascii | server_round_robin |
+ server_reuseport;
server_ip_address: VAR_IP_ADDRESS STRING
{
OUTYY(("P(server_ip_address:%s)\n", $2));
@@ -191,6 +192,14 @@ server_do_ip6: VAR_DO_IP6 STRING
else cfg_parser->opt->do_ip6 = (strcmp($2, "yes")==0);
}
;
+server_reuseport: VAR_REUSEPORT STRING
+ {
+ OUTYY(("P(server_reuseport:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->opt->reuseport = (strcmp($2, "yes")==0);
+ }
+ ;
server_database: VAR_DATABASE STRING
{
OUTYY(("P(server_database:%s)\n", $2));
diff --git a/usr.sbin/nsd/configure b/usr.sbin/nsd/configure
index 14de3cb4ce2..70dca096b86 100644
--- a/usr.sbin/nsd/configure
+++ b/usr.sbin/nsd/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for NSD 4.1.3.
+# Generated by GNU Autoconf 2.69 for NSD 4.1.6.
#
# Report bugs to <nsd-bugs@nlnetlabs.nl>.
#
@@ -580,8 +580,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='NSD'
PACKAGE_TARNAME='nsd'
-PACKAGE_VERSION='4.1.3'
-PACKAGE_STRING='NSD 4.1.3'
+PACKAGE_VERSION='4.1.6'
+PACKAGE_STRING='NSD 4.1.6'
PACKAGE_BUGREPORT='nsd-bugs@nlnetlabs.nl'
PACKAGE_URL=''
@@ -712,11 +712,12 @@ with_xfrdir
with_chroot
with_user
enable_flto
+enable_pie
+enable_relro_now
with_libevent
enable_largefile
enable_recvmmsg
with_facility
-with_max_ips
with_tcp_timeout
enable_root_server
enable_ipv6
@@ -1280,7 +1281,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.3 to adapt to many kinds of systems.
+\`configure' configures NSD 4.1.6 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1341,7 +1342,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of NSD 4.1.3:";;
+ short | recursive ) echo "Configuration of NSD 4.1.6:";;
esac
cat <<\_ACEOF
@@ -1350,6 +1351,10 @@ Optional Features:
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--disable-flto Disable link-time optimization (gcc specific option)
+ --enable-pie Enable Position-Independent Executable (eg. to fully
+ benefit from ASLR, small performance penalty)
+ --enable-relro-now Enable full relocation binding at load-time (RELRO
+ NOW, to protect GOT and .dtor areas)
--disable-largefile omit support for large files
--enable-recvmmsg Enable recvmmsg and sendmmsg compilation, faster but
some kernel versions may have implementation
@@ -1389,8 +1394,6 @@ Optional Packages:
an explicit path), useful when the zone count is
high.
--with-facility=name Syslog default facility (LOG_DAEMON)
- --with-max-ips=number Limit on the number of ip-addresses that may be
- specified
--with-tcp-timeout=number
Limit the default tcp timeout
--with-ssl=pathname enable SSL (will check /usr/local/ssl /usr/lib/ssl
@@ -1478,7 +1481,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-NSD configure 4.1.3
+NSD configure 4.1.6
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2187,7 +2190,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.3, which was
+It was created by NSD $as_me 4.1.6, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -5075,6 +5078,96 @@ rm -f core conftest.err conftest.$ac_objext \
fi
+
+ # Check whether --enable-pie was given.
+if test "${enable_pie+set}" = set; then :
+ enableval=$enable_pie;
+fi
+
+ if test "x$enable_pie" = "xyes"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports PIE" >&5
+$as_echo_n "checking if $CC supports PIE... " >&6; }
+ BAKLDFLAGS="$LDFLAGS"
+ BAKCFLAGS="$CFLAGS"
+ LDFLAGS="$LDFLAGS -pie"
+ CFLAGS="$CFLAGS -fPIE"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ if $CC $CFLAGS $LDFLAGS -o conftest conftest.c 2>&1 | grep "warning: no debug symbols in executable" >/dev/null; then
+ LDFLAGS="$BAKLDFLAGS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ fi
+ rm -f conftest conftest.c conftest.o
+
+else
+ LDFLAGS="$BAKLDFLAGS" ; CFLAGS="$BAKCFLAGS" ; { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+
+
+ # Check whether --enable-relro_now was given.
+if test "${enable_relro_now+set}" = set; then :
+ enableval=$enable_relro_now;
+fi
+
+ if test "x$enable_relro_now" = "xyes"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Wl,-z,relro,-z,now" >&5
+$as_echo_n "checking if $CC supports -Wl,-z,relro,-z,now... " >&6; }
+ BAKLDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS -Wl,-z,relro,-z,now"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ if $CC $CFLAGS $LDFLAGS -o conftest conftest.c 2>&1 | grep "warning: no debug symbols in executable" >/dev/null; then
+ LDFLAGS="$BAKLDFLAGS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ fi
+ rm -f conftest conftest.c conftest.o
+
+else
+ LDFLAGS="$BAKLDFLAGS" ; { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
$as_echo_n "checking for an ANSI C-conforming const... " >&6; }
@@ -6380,6 +6473,14 @@ fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# see if reuseport is enabled by default (also a config option).
+# freebsd can compile the option, but it does not work, it works on Linux.
+if test "`uname`" = "Linux"; then
+
+$as_echo "#define REUSEPORT_BY_DEFAULT 1" >>confdefs.h
+
+fi
+
# set -I. and -Isrcdir
if test -n "$CPPFLAGS"; then
CPPFLAGS="$CPPFLAGS -I."
@@ -8289,19 +8390,6 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
-max_ips=32
-
-# Check whether --with-max_ips was given.
-if test "${with_max_ips+set}" = set; then :
- withval=$with_max_ips; max_ips=$withval
-fi
-
-
-cat >>confdefs.h <<_ACEOF
-#define MAX_INTERFACES $max_ips
-_ACEOF
-
-
tcp_timeout=120
# Check whether --with-tcp_timeout was given.
@@ -9475,7 +9563,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by NSD $as_me 4.1.3, which was
+This file was extended by NSD $as_me 4.1.6, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -9537,7 +9625,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.3
+NSD config.status 4.1.6
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/usr.sbin/nsd/configure.ac b/usr.sbin/nsd/configure.ac
index 60ea50d2bf2..d559af34d7c 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,4.1.3,nsd-bugs@nlnetlabs.nl)
+AC_INIT(NSD,4.1.6,nsd-bugs@nlnetlabs.nl)
AC_CONFIG_HEADER([config.h])
CFLAGS="$CFLAGS"
@@ -282,6 +282,8 @@ if test "x$CFLAGS" = "x" ; then
# we do not use O3 because it causes miscompilations.
ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"])
ACX_CHECK_FLTO
+ ACX_CHECK_PIE
+ ACX_CHECK_RELRO_NOW
fi
AC_C_CONST
AC_C_INLINE
@@ -502,6 +504,12 @@ AC_CHECK_STRPTIME_WORKS
ACX_CHECK_NONBLOCKING_BROKEN
ACX_MKDIR_ONE_ARG
+# see if reuseport is enabled by default (also a config option).
+# freebsd can compile the option, but it does not work, it works on Linux.
+if test "`uname`" = "Linux"; then
+ AC_DEFINE([REUSEPORT_BY_DEFAULT], 1, [enable reuseport option by default.])
+fi
+
# set -I. and -Isrcdir
if test -n "$CPPFLAGS"; then
CPPFLAGS="$CPPFLAGS -I."
@@ -736,15 +744,6 @@ AC_ARG_WITH([facility],
AC_DEFINE_UNQUOTED([FACILITY], $facility, [Define to the default facility for syslog.])
dnl
-dnl Determine the maximum number of ip-addresses that are allowed
-dnl
-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])
-AC_DEFINE_UNQUOTED([MAX_INTERFACES], $max_ips, [Define to the maximum ip-addresses to serve.])
-
-dnl
dnl Determine the default tcp timeout
dnl
tcp_timeout=120
diff --git a/usr.sbin/nsd/dns.c b/usr.sbin/nsd/dns.c
index b10a53810e5..58e2da034b9 100644
--- a/usr.sbin/nsd/dns.c
+++ b/usr.sbin/nsd/dns.c
@@ -730,7 +730,9 @@ static rrtype_descriptor_type rrtype_descriptors[(RRTYPE_DESCRIPTORS_LENGTH+1)]
/* 255 - * [RFC 1035, RFC 6895] */
{ 255, NULL, T_UTYPE, 1, 1, { RDATA_WF_BINARY }, { RDATA_ZF_UNKNOWN } },
/* 256 - URI */
- { 256, NULL, T_UTYPE, 1, 1, { RDATA_WF_BINARY }, { RDATA_ZF_UNKNOWN } },
+ { TYPE_URI, "URI", T_URI, 3, 3,
+ { RDATA_WF_SHORT, RDATA_WF_SHORT, RDATA_WF_LONG_TEXT },
+ { RDATA_ZF_SHORT, RDATA_ZF_SHORT, RDATA_ZF_LONG_TEXT } },
/* 257 - CAA [RFC 6844] */
{ TYPE_CAA, "CAA", T_CAA, 3, 3,
{ RDATA_WF_BYTE, RDATA_WF_TEXT, RDATA_WF_LONG_TEXT },
diff --git a/usr.sbin/nsd/dns.h b/usr.sbin/nsd/dns.h
index 077f00d2f27..3e9e88c92ca 100644
--- a/usr.sbin/nsd/dns.h
+++ b/usr.sbin/nsd/dns.h
@@ -154,7 +154,7 @@ typedef enum nsd_rc nsd_rc_type;
#define TYPE_MAILB 253 /* A request for mailbox-related records (MB, MG or MR) */
#define TYPE_MAILA 254 /* A request for mail agent RRs (Obsolete - see MX) */
#define TYPE_ANY 255 /* any type (wildcard) */
-
+#define TYPE_URI 256 /* RFC 7553 */
#define TYPE_CAA 257 /* RFC 6844 */
#define TYPE_DLV 32769 /* RFC 4431 */
diff --git a/usr.sbin/nsd/mkinstalldirs b/usr.sbin/nsd/mkinstalldirs
index b61f354cf8e..bfdc5bd222e 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.3 2013/11/26 12:53:58 sthen Exp $
+# $Id: mkinstalldirs,v 1.4 2015/11/05 21:21:59 sthen Exp $
errstatus=0
diff --git a/usr.sbin/nsd/nsd-checkconf.8.in b/usr.sbin/nsd/nsd-checkconf.8.in
index 212d080cb5b..6cb43541ae9 100644
--- a/usr.sbin/nsd/nsd-checkconf.8.in
+++ b/usr.sbin/nsd/nsd-checkconf.8.in
@@ -1,4 +1,4 @@
-.TH "nsd\-checkconf" "8" "Jun 23, 2015" "NLnet Labs" "nsd 4.1.3"
+.TH "nsd\-checkconf" "8" "Oct 22, 2015" "NLnet Labs" "nsd 4.1.6"
.\" Copyright (c) 2001\-2008, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
diff --git a/usr.sbin/nsd/nsd-checkconf.c b/usr.sbin/nsd/nsd-checkconf.c
index 25c23d161d0..96bc89eca89 100644
--- a/usr.sbin/nsd/nsd-checkconf.c
+++ b/usr.sbin/nsd/nsd-checkconf.c
@@ -344,6 +344,7 @@ config_print_zone(nsd_options_t* opt, const char* k, int s, const char *o,
SERV_GET_BIN(debug_mode, o);
SERV_GET_BIN(do_ip4, o);
SERV_GET_BIN(do_ip6, o);
+ SERV_GET_BIN(reuseport, o);
SERV_GET_BIN(hide_version, o);
SERV_GET_BIN(zonefiles_check, o);
SERV_GET_BIN(log_time_ascii, o);
@@ -440,6 +441,7 @@ config_test_print_server(nsd_options_t* opt)
printf("server:\n");
printf("\tdebug-mode: %s\n", opt->debug_mode?"yes":"no");
printf("\tip-transparent: %s\n", opt->ip_transparent?"yes":"no");
+ printf("\treuseport: %s\n", opt->reuseport?"yes":"no");
printf("\tdo-ip4: %s\n", opt->do_ip4?"yes":"no");
printf("\tdo-ip6: %s\n", opt->do_ip6?"yes":"no");
printf("\thide-version: %s\n", opt->hide_version?"yes":"no");
@@ -539,18 +541,8 @@ file_inside_chroot(const char* fname, const char* chr)
static int
additional_checks(nsd_options_t* opt, const char* filename)
{
- ip_address_option_t* ip = opt->ip_addresses;
zone_options_t* zone;
- int num = 0;
int errors = 0;
- while(ip) {
- num++;
- ip = ip->next;
- }
- if(num > MAX_INTERFACES) {
- fprintf(stderr, "%s: too many interfaces (ip-address:) specified.\n", filename);
- errors ++;
- }
RBTREE_FOR(zone, zone_options_t*, opt->zone_options)
{
@@ -565,6 +557,13 @@ additional_checks(nsd_options_t* opt, const char* filename)
"is received?\n", filename, zone->name);
errors ++;
}
+ if(!zone_is_slave(zone) && (!zone->pattern->zonefile ||
+ zone->pattern->zonefile[0] == 0)) {
+ fprintf(stderr, "%s: zone %s is a master zone but has "
+ "no zonefile. Where can the data come from?\n",
+ filename, zone->name);
+ errors ++;
+ }
}
#ifndef BIND8_STATS
diff --git a/usr.sbin/nsd/nsd-control.8.in b/usr.sbin/nsd/nsd-control.8.in
index 82bfbf0241e..b6af80ce551 100644
--- a/usr.sbin/nsd/nsd-control.8.in
+++ b/usr.sbin/nsd/nsd-control.8.in
@@ -1,4 +1,4 @@
-.TH "nsd\-control" "8" "Jun 23, 2015" "NLnet Labs" "nsd 4.1.3"
+.TH "nsd\-control" "8" "Oct 22, 2015" "NLnet Labs" "nsd 4.1.6"
.\" Copyright (c) 2011, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
diff --git a/usr.sbin/nsd/nsd.8.in b/usr.sbin/nsd/nsd.8.in
index 8dfa2c08ec9..eeea5054c94 100644
--- a/usr.sbin/nsd/nsd.8.in
+++ b/usr.sbin/nsd/nsd.8.in
@@ -1,9 +1,9 @@
-.TH "NSD" "8" "Feb 3, 2015" "NLnet Labs" "NSD 4.1.1"
+.TH "NSD" "8" "Oct 22, 2015" "NLnet Labs" "NSD 4.1.6"
.\" Copyright (c) 2001\-2008, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
.B nsd
-\- Name Server Daemon (NSD) version 4.1.1.
+\- Name Server Daemon (NSD) version 4.1.6.
.SH "SYNOPSIS"
.B nsd
.RB [ \-4 ]
@@ -79,8 +79,9 @@ configfile.
.P
Normally
.B NSD
-should be started with the `nsd\-control(8) start` command invoked from
-.IR /etc/rc.d/nsd .
+should be started with the `nsd\-control(8) start` command invoked from a
+.I /etc/rc.d/nsd.sh
+script or similar at the operating system startup.
.TP
.B \-4
Only listen to IPv4 connections.
@@ -102,7 +103,8 @@ listens to the wildcard interface.
.TP
.B \-c\fI configfile
Read specified
-.I configfile instead of the default
+.I configfile
+instead of the default
.IR @nsdconfigfile@ .
For format description see nsd.conf(5).
.TP
@@ -183,7 +185,12 @@ to the daemon periodically.
.B \-t\fI chroot
Specifies a directory to
.I chroot
-to upon startup.
+to upon startup. This option requires you to ensure that appropriate
+syslogd(8) socket (e.g.
+.I chrootdir
+/dev/log) is available, otherwise
+.B NSD
+won't produce any log output.
.TP
.B \-u\fI username
Drop user and group privileges to those of
@@ -230,6 +237,7 @@ default
.B NSD
configuration file
.SH "DIAGNOSTICS"
+.B NSD
will log all the problems via the standard syslog(8)
.I daemon
facility, unless the
diff --git a/usr.sbin/nsd/nsd.c b/usr.sbin/nsd/nsd.c
index b8b39b5e8f7..2420a6512e1 100644
--- a/usr.sbin/nsd/nsd.c
+++ b/usr.sbin/nsd/nsd.c
@@ -167,6 +167,28 @@ get_ip_port_frm_str(const char* arg, const char** hostname,
*hostname = arg;
}
+/* append interface to interface array (names, udp, tcp) */
+void
+add_interface(char*** nodes, struct nsd* nsd, char* ip)
+{
+ /* realloc the arrays */
+ if(nsd->ifs == 0) {
+ *nodes = xalloc_zero(sizeof(*nodes));
+ nsd->udp = xalloc_zero(sizeof(*nsd->udp));
+ nsd->tcp = xalloc_zero(sizeof(*nsd->udp));
+ } else {
+ *nodes = xrealloc(*nodes, (nsd->ifs+1)*sizeof(*nodes));
+ nsd->udp = xrealloc(nsd->udp, (nsd->ifs+1)*sizeof(*nsd->udp));
+ nsd->tcp = xrealloc(nsd->tcp, (nsd->ifs+1)*sizeof(*nsd->udp));
+ (*nodes)[nsd->ifs] = NULL;
+ memset(&nsd->udp[nsd->ifs], 0, sizeof(*nsd->udp));
+ memset(&nsd->tcp[nsd->ifs], 0, sizeof(*nsd->tcp));
+ }
+
+ /* add it */
+ (*nodes)[nsd->ifs] = ip;
+ ++nsd->ifs;
+}
/*
* Fetch the nsd parent process id from the nsd pidfile
@@ -404,10 +426,9 @@ main(int argc, char *argv[])
struct passwd *pwd = NULL;
#endif /* HAVE_GETPWNAM */
- /* For initialising the address info structures */
- /* static so it can get very big without overflowing the stack */
- static struct addrinfo hints[MAX_INTERFACES];
- static const char *nodes[MAX_INTERFACES];
+ struct addrinfo hints[2];
+ int hints_in_use = 1;
+ char** nodes = NULL; /* array of address strings, size nsd.ifs */
const char *udp_port = 0;
const char *tcp_port = 0;
@@ -423,14 +444,11 @@ main(int argc, char *argv[])
nsd.dbfile = 0;
nsd.pidfile = 0;
nsd.server_kind = NSD_SERVER_MAIN;
-
- for (i = 0; i < MAX_INTERFACES; i++) {
- memset(&hints[i], 0, sizeof(hints[i]));
- hints[i].ai_family = DEFAULT_AI_FAMILY;
- hints[i].ai_flags = AI_PASSIVE;
- nodes[i] = NULL;
- }
-
+ memset(&hints, 0, sizeof(*hints)*2);
+ hints[0].ai_family = DEFAULT_AI_FAMILY;
+ hints[0].ai_flags = AI_PASSIVE;
+ hints[1].ai_family = DEFAULT_AI_FAMILY;
+ hints[1].ai_flags = AI_PASSIVE;
nsd.identity = 0;
nsd.version = VERSION;
nsd.username = 0;
@@ -454,7 +472,6 @@ main(int argc, char *argv[])
nsd.identity = IDENTITY;
}
-
/* Parse the command line... */
while ((c = getopt(argc, argv, "46a:c:df:hi:I:l:N:n:P:p:s:u:t:X:V:v"
#ifndef NDEBUG /* <mattthijs> only when configured with --enable-checking */
@@ -463,26 +480,17 @@ main(int argc, char *argv[])
)) != -1) {
switch (c) {
case '4':
- for (i = 0; i < MAX_INTERFACES; ++i) {
- hints[i].ai_family = AF_INET;
- }
+ hints[0].ai_family = AF_INET;
break;
case '6':
#ifdef INET6
- for (i = 0; i < MAX_INTERFACES; ++i) {
- hints[i].ai_family = AF_INET6;
- }
+ hints[0].ai_family = AF_INET6;
#else /* !INET6 */
error("IPv6 support not enabled.");
#endif /* INET6 */
break;
case 'a':
- if (nsd.ifs < MAX_INTERFACES) {
- nodes[nsd.ifs] = optarg;
- ++nsd.ifs;
- } else {
- error("too many interfaces ('-a') specified.");
- }
+ add_interface(&nodes, &nsd, optarg);
break;
case 'c':
configfile = optarg;
@@ -613,29 +621,18 @@ main(int argc, char *argv[])
nsd.options->zonelistfile);
}
if(nsd.options->do_ip4 && !nsd.options->do_ip6) {
- for (i = 0; i < MAX_INTERFACES; ++i) {
- hints[i].ai_family = AF_INET;
- }
+ hints[0].ai_family = AF_INET;
}
#ifdef INET6
if(nsd.options->do_ip6 && !nsd.options->do_ip4) {
- for (i = 0; i < MAX_INTERFACES; ++i) {
- hints[i].ai_family = AF_INET6;
- }
+ hints[0].ai_family = AF_INET6;
}
#endif /* INET6 */
if(nsd.options->ip_addresses)
{
ip_address_option_t* ip = nsd.options->ip_addresses;
while(ip) {
- if (nsd.ifs < MAX_INTERFACES) {
- nodes[nsd.ifs] = ip->address;
- ++nsd.ifs;
- } else {
- error("too many interfaces ('-a' + "
- "'ip-address:') specified.");
- break;
- }
+ add_interface(&nodes, &nsd, ip->address);
ip = ip->next;
}
}
@@ -671,6 +668,11 @@ main(int argc, char *argv[])
if(nsd.child_count == 0) {
nsd.child_count = nsd.options->server_count;
}
+#ifdef SO_REUSEPORT
+ if(nsd.options->reuseport && nsd.child_count > 1) {
+ nsd.reuseport = nsd.child_count;
+ }
+#endif /* SO_REUSEPORT */
if(nsd.maximum_tcp_count == 0) {
nsd.maximum_tcp_count = nsd.options->tcp_count;
}
@@ -761,7 +763,7 @@ main(int argc, char *argv[])
/* We need at least one active interface */
if (nsd.ifs == 0) {
- nsd.ifs = 1;
+ add_interface(&nodes, &nsd, NULL);
/*
* With IPv6 we'd like to open two separate sockets,
@@ -778,9 +780,10 @@ main(int argc, char *argv[])
#ifdef INET6
if (hints[0].ai_family == AF_UNSPEC) {
#ifdef IPV6_V6ONLY
+ add_interface(&nodes, &nsd, NULL);
hints[0].ai_family = AF_INET6;
hints[1].ai_family = AF_INET;
- nsd.ifs = 2;
+ hints_in_use = 2;
nsd.grab_ip6_optional = 1;
#else /* !IPV6_V6ONLY */
hints[0].ai_family = AF_INET6;
@@ -794,14 +797,15 @@ main(int argc, char *argv[])
int r;
const char* node = NULL;
const char* service = NULL;
+ int h = ((hints_in_use == 1)?0:i%hints_in_use);
/* We don't perform name-lookups */
if (nodes[i] != NULL)
- hints[i].ai_flags |= AI_NUMERICHOST;
+ hints[h].ai_flags |= AI_NUMERICHOST;
get_ip_port_frm_str(nodes[i], &node, &service);
- hints[i].ai_socktype = SOCK_DGRAM;
- if ((r=getaddrinfo(node, (service?service:udp_port), &hints[i], &nsd.udp[i].addr)) != 0) {
+ hints[h].ai_socktype = SOCK_DGRAM;
+ if ((r=getaddrinfo(node, (service?service:udp_port), &hints[h], &nsd.udp[i].addr)) != 0) {
#ifdef INET6
if(nsd.grab_ip6_optional && hints[0].ai_family == AF_INET6) {
log_msg(LOG_WARNING, "No IPv6, fallback to IPv4. getaddrinfo: %s",
@@ -815,8 +819,8 @@ main(int argc, char *argv[])
r==EAI_SYSTEM?strerror(errno):"");
}
- hints[i].ai_socktype = SOCK_STREAM;
- if ((r=getaddrinfo(node, (service?service:tcp_port), &hints[i], &nsd.tcp[i].addr)) != 0) {
+ hints[h].ai_socktype = SOCK_STREAM;
+ if ((r=getaddrinfo(node, (service?service:tcp_port), &hints[h], &nsd.tcp[i].addr)) != 0) {
error("cannot parse address '%s': getaddrinfo: %s %s",
nodes[i]?nodes[i]:"(null)",
gai_strerror(r),
diff --git a/usr.sbin/nsd/nsd.conf.5.in b/usr.sbin/nsd/nsd.conf.5.in
index 7d1a83d8e56..45e116fd5ce 100644
--- a/usr.sbin/nsd/nsd.conf.5.in
+++ b/usr.sbin/nsd/nsd.conf.5.in
@@ -1,4 +1,4 @@
-.TH "nsd.conf" "5" "Jun 23, 2015" "NLnet Labs" "nsd 4.1.3"
+.TH "nsd.conf" "5" "Oct 22, 2015" "NLnet Labs" "nsd 4.1.6"
.\" Copyright (c) 2001\-2008, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
@@ -153,6 +153,13 @@ NSD will bind to the listed ip\-address. Can be give multiple times
to bind multiple ip\-addresses. Optionally, a port number can be given.
If none are given NSD listens to the wildcard interface. Same as commandline option
.BR \-a.
+For servers with multiple IP addresses that can be used to send traffic
+to the internet, list them one by one, or the source address of replies
+could be wrong. This is because if the udp socket associates a source
+address of 0.0.0.0 then the kernel picks an ip-address with which to
+send to the internet, and it picks the wrong one. Typically needed for
+anycast instances. Use ip-transparent to be able to list addresses that
+turn on later (typical for certain load-balancing).
.TP
.B interface:\fR <ip4 or ip6>[@port]
Same as ip\-address (for easy of compatibility with unbound.conf).
@@ -162,10 +169,23 @@ Allows NSD to bind to non local addresses. This is useful to have NSD
listen to IP addresses that are not (yet) added to the network interface, so
that it can answer immediately when the address is added. Default is no.
.TP
+.B reuseport:\fR <yes or no>
+Use the SO_REUSEPORT socket option, and create file descriptors for every
+server in the server\-count. This improves performance of the network
+stack. Only really useful if you also configure a server\-count higher
+than 1 (such as, equal to the number of cpus). The default is yes on
+Linux (where it works, and has been (backported) to 2.6 and 3.x kernels).
+On FreeBSD it is known to fail (default is no), but you can enable it
+if you think it is fixed. And a cautious default of no is used for
+other systems.
+.TP
.B debug\-mode:\fR <yes or no>
Turns on debugging mode for nsd, does not fork a daemon process.
-Default is no. Same as commandline option
+Default is no. Same as commandline option
.BR \-d.
+If set to yes it does not fork and stays in the foreground, which can
+be helpful for commandline debugging, but is also used by certain
+server supervisor processes to ascertain that the server is running.
.TP
.B do\-ip4:\fR <yes or no>
If yes, NSD listens to IPv4 connections. Default yes.
@@ -298,7 +318,8 @@ once per the number of seconds. The default is 1 second.
.B verbosity:\fR <level>
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.
+zone transfers. 2 lists soft warnings that are encountered. 3 prints
+more information.
.IP
Verbosity 0 will print warnings and errors, and other events that are
important to keep NSD running.
diff --git a/usr.sbin/nsd/options.c b/usr.sbin/nsd/options.c
index cefb928ede8..f86e99bf420 100644
--- a/usr.sbin/nsd/options.c
+++ b/usr.sbin/nsd/options.c
@@ -24,6 +24,7 @@ int c_parse(void);
int c_lex(void);
int c_wrap(void);
void c_error(const char *message);
+extern char* c_text;
static int
rbtree_strcmp(const void* p1, const void* p2)
@@ -68,6 +69,11 @@ nsd_options_create(region_type* region)
opt->pidfile = PIDFILE;
opt->port = UDP_PORT;
/* deprecated? opt->port = TCP_PORT; */
+#ifdef REUSEPORT_BY_DEFAULT
+ opt->reuseport = 1;
+#else
+ opt->reuseport = 0;
+#endif
opt->statistics = 0;
opt->chroot = 0;
opt->username = USER;
@@ -682,40 +688,60 @@ zone_list_close(nsd_options_t* opt)
opt->zonelist = NULL;
}
-
void
-c_error_va_list(const char* fmt, va_list args)
+c_error_va_list_pos(int showpos, const char* fmt, va_list args)
{
+ char* at = NULL;
cfg_parser->errors++;
+ if(showpos && c_text && c_text[0]!=0) {
+ at = c_text;
+ }
if(cfg_parser->err) {
char m[MAXSYSLOGMSGLEN];
- snprintf(m, sizeof(m), "%s:%d: error: ", cfg_parser->filename,
+ snprintf(m, sizeof(m), "%s:%d: ", cfg_parser->filename,
cfg_parser->line);
(*cfg_parser->err)(cfg_parser->err_arg, m);
+ if(at) {
+ snprintf(m, sizeof(m), "at '%s': ", at);
+ (*cfg_parser->err)(cfg_parser->err_arg, m);
+ }
+ (*cfg_parser->err)(cfg_parser->err_arg, "error: ");
vsnprintf(m, sizeof(m), fmt, args);
(*cfg_parser->err)(cfg_parser->err_arg, m);
(*cfg_parser->err)(cfg_parser->err_arg, "\n");
return;
}
- fprintf(stderr, "%s:%d: error: ", cfg_parser->filename,
- cfg_parser->line);
+ fprintf(stderr, "%s:%d: ", cfg_parser->filename, cfg_parser->line);
+ if(at) fprintf(stderr, "at '%s': ", at);
+ fprintf(stderr, "error: ");
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
}
void
+c_error_msg_pos(int showpos, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ c_error_va_list_pos(showpos, fmt, args);
+ va_end(args);
+}
+
+void
c_error_msg(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
- c_error_va_list(fmt, args);
+ c_error_va_list_pos(0, fmt, args);
va_end(args);
}
void
c_error(const char* str)
{
- c_error_msg("%s", str);
+ if((strcmp(str, "syntax error")==0 || strcmp(str, "parse error")==0))
+ c_error_msg_pos(1, "%s", str);
+ else c_error_msg("%s", str);
}
int
diff --git a/usr.sbin/nsd/query.c b/usr.sbin/nsd/query.c
index d1a2b92c6b1..ee8057bcf91 100644
--- a/usr.sbin/nsd/query.c
+++ b/usr.sbin/nsd/query.c
@@ -135,6 +135,7 @@ query_error (struct query *q, nsd_rc_type rcode)
buffer_clear(q->packet);
QR_SET(q->packet); /* This is an answer. */
+ AD_CLR(q->packet);
RCODE_SET(q->packet, (int) rcode); /* Error code. */
/* Truncate the question as well... */
@@ -1267,7 +1268,7 @@ answer_query(struct nsd *nsd, struct query *q)
}
void
-query_prepare_response(query_type *q)
+query_prepare_response(query_type *q, nsd_type *nsd)
{
uint16_t flags;
@@ -1282,6 +1283,9 @@ query_prepare_response(query_type *q)
*/
q->reserved_space = edns_reserved_space(&q->edns);
q->reserved_space += tsig_reserved_space(&q->tsig);
+ if(q->edns.nsid == 1 && nsd->nsid_len > 0 &&
+ q->edns.status != EDNS_NOT_PRESENT)
+ q->reserved_space += OPT_HDR + nsd->nsid_len;
/* Update the flags. */
flags = FLAGS(q->packet);
@@ -1411,7 +1415,7 @@ query_process(query_type *q, nsd_type *nsd)
return query_error(q, NSD_RC_OK);
}
- query_prepare_response(q);
+ query_prepare_response(q, nsd);
if (q->qclass != CLASS_IN && q->qclass != CLASS_ANY) {
if (q->qclass == CLASS_CH) {
@@ -1450,8 +1454,8 @@ query_add_optional(query_type *q, nsd_type *nsd)
if (q->edns.dnssec_ok) edns->ok[7] = 0x80;
else edns->ok[7] = 0x00;
buffer_write(q->packet, edns->ok, OPT_LEN);
- if (nsd->nsid_len > 0 && q->edns.nsid == 1 &&
- !query_overflow_nsid(q, nsd->nsid_len)) {
+ if (nsd->nsid_len > 0 && q->edns.nsid == 1 && buffer_available(
+ q->packet, OPT_RDATA+OPT_HDR+nsd->nsid_len)) {
/* rdata length */
buffer_write(q->packet, edns->rdata_nsid, OPT_RDATA);
/* nsid opt header */
diff --git a/usr.sbin/nsd/remote.c b/usr.sbin/nsd/remote.c
index e3322c67671..c0319c4bc6f 100644
--- a/usr.sbin/nsd/remote.c
+++ b/usr.sbin/nsd/remote.c
@@ -834,7 +834,7 @@ do_notify(SSL* ssl, xfrd_state_t* xfrd, char* arg)
struct notify_zone_t* n = (struct notify_zone_t*)rbtree_search(
xfrd->notify_zones, (const dname_type*)zo->node.key);
if(n) {
- xfrd_notify_start(n);
+ xfrd_notify_start(n, xfrd);
send_ok(ssl);
} else {
ssl_printf(ssl, "error zone does not have notify\n");
@@ -842,7 +842,7 @@ do_notify(SSL* ssl, xfrd_state_t* xfrd, char* arg)
} else {
struct notify_zone_t* n;
RBTREE_FOR(n, struct notify_zone_t*, xfrd->notify_zones) {
- xfrd_notify_start(n);
+ xfrd_notify_start(n, xfrd);
}
send_ok(ssl);
}
@@ -1495,7 +1495,7 @@ repat_interrupt_notify_start(xfrd_state_t* xfrd)
nz->notify_current = nz->options->pattern->notify;
if(nz->notify_restart == 2) {
if(nz->notify_restart)
- xfrd_notify_start(nz);
+ xfrd_notify_start(nz, xfrd);
}
}
}
diff --git a/usr.sbin/nsd/server.c b/usr.sbin/nsd/server.c
index 07dfc1d41fb..9ac2687885d 100644
--- a/usr.sbin/nsd/server.c
+++ b/usr.sbin/nsd/server.c
@@ -30,6 +30,7 @@
#include <unistd.h>
#include <signal.h>
#include <netdb.h>
+#include <poll.h>
#ifndef SHUT_WR
#define SHUT_WR 1
#endif
@@ -304,6 +305,7 @@ restart_child_servers(struct nsd *nsd, region_type* region, netio_type* netio,
nsd->child_count = 0;
nsd->server_kind = nsd->children[i].kind;
nsd->this_child = &nsd->children[i];
+ nsd->this_child->child_num = i;
/* remove signal flags inherited from parent
the parent will handle them. */
nsd->signal_hint_reload_hup = 0;
@@ -546,29 +548,30 @@ initialize_dname_compression_tables(struct nsd *nsd)
compressed_dname_offsets[0] = QHEADERSZ; /* The original query name */
}
-/*
- * Initialize the server, create and bind the sockets.
- *
- */
-int
-server_init(struct nsd *nsd)
+/* create and bind sockets. */
+static int
+server_init_ifs(struct nsd *nsd, size_t from, size_t to, int* reuseport_works)
{
+ struct addrinfo* addr;
size_t i;
-#if defined(SO_REUSEADDR) || (defined(INET6) && (defined(IPV6_V6ONLY) || defined(IPV6_USE_MIN_MTU) || defined(IPV6_MTU) || defined(IP_TRANSPARENT)))
+#if defined(SO_REUSEPORT) || defined(SO_REUSEADDR) || (defined(INET6) && (defined(IPV6_V6ONLY) || defined(IPV6_USE_MIN_MTU) || defined(IPV6_MTU) || defined(IP_TRANSPARENT)))
int on = 1;
#endif
/* UDP */
/* Make a socket... */
- for (i = 0; i < nsd->ifs; i++) {
- if (!nsd->udp[i].addr) {
+ for (i = from; i < to; i++) {
+ /* for reuseports copy socket specs of first entries */
+ addr = nsd->udp[i%nsd->ifs].addr;
+ if (!addr) {
nsd->udp[i].s = -1;
continue;
}
- if ((nsd->udp[i].s = socket(nsd->udp[i].addr->ai_family, nsd->udp[i].addr->ai_socktype, 0)) == -1) {
+ nsd->udp[i].fam = (int)addr->ai_family;
+ if ((nsd->udp[i].s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) {
#if defined(INET6)
- if (nsd->udp[i].addr->ai_family == AF_INET6 &&
+ if (addr->ai_family == AF_INET6 &&
errno == EAFNOSUPPORT && nsd->grab_ip6_optional) {
log_msg(LOG_WARNING, "fallback to UDP4, no IPv6: not supported");
continue;
@@ -578,6 +581,22 @@ server_init(struct nsd *nsd)
return -1;
}
+#ifdef SO_REUSEPORT
+ if(nsd->reuseport && *reuseport_works &&
+ setsockopt(nsd->udp[i].s, SOL_SOCKET, SO_REUSEPORT,
+ (void*)&on, (socklen_t)sizeof(on)) < 0) {
+ if(verbosity >= 3
+#ifdef ENOPROTOOPT
+ || errno != ENOPROTOOPT
+#endif
+ )
+ log_msg(LOG_ERR, "setsockopt(..., SO_REUSEPORT, "
+ "...) failed: %s", strerror(errno));
+ *reuseport_works = 0;
+ }
+#else
+ (void)reuseport_works;
+#endif /* SO_REUSEPORT */
#if defined(SO_RCVBUF) || defined(SO_SNDBUF)
if(1) {
int rcv = 1*1024*1024;
@@ -633,7 +652,7 @@ server_init(struct nsd *nsd)
#endif /* defined(SO_RCVBUF) || defined(SO_SNDBUF) */
#if defined(INET6)
- if (nsd->udp[i].addr->ai_family == AF_INET6) {
+ if (addr->ai_family == AF_INET6) {
# if defined(IPV6_V6ONLY)
if (setsockopt(nsd->udp[i].s,
IPPROTO_IPV6, IPV6_V6ONLY,
@@ -679,7 +698,7 @@ server_init(struct nsd *nsd)
}
#endif
#if defined(AF_INET)
- if (nsd->udp[i].addr->ai_family == AF_INET) {
+ if (addr->ai_family == AF_INET) {
# if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
int action = IP_PMTUDISC_DONT;
if (setsockopt(nsd->udp[i].s, IPPROTO_IP,
@@ -718,7 +737,7 @@ server_init(struct nsd *nsd)
#endif /* IP_TRANSPARENT */
}
- if (bind(nsd->udp[i].s, (struct sockaddr *) nsd->udp[i].addr->ai_addr, nsd->udp[i].addr->ai_addrlen) != 0) {
+ if (bind(nsd->udp[i].s, (struct sockaddr *) addr->ai_addr, addr->ai_addrlen) != 0) {
log_msg(LOG_ERR, "can't bind udp socket: %s", strerror(errno));
return -1;
}
@@ -727,14 +746,17 @@ server_init(struct nsd *nsd)
/* TCP */
/* Make a socket... */
- for (i = 0; i < nsd->ifs; i++) {
- if (!nsd->tcp[i].addr) {
+ for (i = from; i < to; i++) {
+ /* for reuseports copy socket specs of first entries */
+ addr = nsd->tcp[i%nsd->ifs].addr;
+ if (!addr) {
nsd->tcp[i].s = -1;
continue;
}
- if ((nsd->tcp[i].s = socket(nsd->tcp[i].addr->ai_family, nsd->tcp[i].addr->ai_socktype, 0)) == -1) {
+ nsd->tcp[i].fam = (int)addr->ai_family;
+ if ((nsd->tcp[i].s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) {
#if defined(INET6)
- if (nsd->tcp[i].addr->ai_family == AF_INET6 &&
+ if (addr->ai_family == AF_INET6 &&
errno == EAFNOSUPPORT && nsd->grab_ip6_optional) {
log_msg(LOG_WARNING, "fallback to TCP4, no IPv6: not supported");
continue;
@@ -744,6 +766,20 @@ server_init(struct nsd *nsd)
return -1;
}
+#ifdef SO_REUSEPORT
+ if(nsd->reuseport && *reuseport_works &&
+ setsockopt(nsd->tcp[i].s, SOL_SOCKET, SO_REUSEPORT,
+ (void*)&on, (socklen_t)sizeof(on)) < 0) {
+ if(verbosity >= 3
+#ifdef ENOPROTOOPT
+ || errno != ENOPROTOOPT
+#endif
+ )
+ log_msg(LOG_ERR, "setsockopt(..., SO_REUSEPORT, "
+ "...) failed: %s", strerror(errno));
+ *reuseport_works = 0;
+ }
+#endif /* SO_REUSEPORT */
#ifdef SO_REUSEADDR
if (setsockopt(nsd->tcp[i].s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
log_msg(LOG_ERR, "setsockopt(..., SO_REUSEADDR, ...) failed: %s", strerror(errno));
@@ -751,7 +787,7 @@ server_init(struct nsd *nsd)
#endif /* SO_REUSEADDR */
#if defined(INET6)
- if (nsd->tcp[i].addr->ai_family == AF_INET6) {
+ if (addr->ai_family == AF_INET6) {
# if defined(IPV6_V6ONLY)
if (setsockopt(nsd->tcp[i].s, IPPROTO_IPV6, IPV6_V6ONLY,
&on, sizeof(on)) < 0) {
@@ -802,7 +838,7 @@ server_init(struct nsd *nsd)
#endif /* IP_TRANSPARENT */
}
- if (bind(nsd->tcp[i].s, (struct sockaddr *) nsd->tcp[i].addr->ai_addr, nsd->tcp[i].addr->ai_addrlen) != 0) {
+ if (bind(nsd->tcp[i].s, (struct sockaddr *) addr->ai_addr, addr->ai_addrlen) != 0) {
log_msg(LOG_ERR, "can't bind tcp socket: %s", strerror(errno));
return -1;
}
@@ -818,6 +854,43 @@ server_init(struct nsd *nsd)
}
/*
+ * Initialize the server, reuseport, create and bind the sockets.
+ */
+int
+server_init(struct nsd *nsd)
+{
+ int reuseport_successful = 1; /* see if reuseport works in OS */
+ if(nsd->reuseport) {
+ /* increase the size of the udp and tcp interface arrays,
+ * there are going to be separate interface file descriptors
+ * for every server instance */
+ nsd->udp = xrealloc(nsd->udp, (nsd->ifs*nsd->reuseport)*
+ sizeof(*nsd->udp));
+ nsd->tcp = xrealloc(nsd->tcp, (nsd->ifs*nsd->reuseport)*
+ sizeof(*nsd->tcp));
+ memset(&nsd->udp[nsd->ifs], 0, sizeof(*nsd->udp)*
+ (nsd->ifs*(nsd->reuseport-1)));
+ memset(&nsd->tcp[nsd->ifs], 0, sizeof(*nsd->tcp)*
+ (nsd->ifs*(nsd->reuseport-1)));
+ }
+
+ /* open the server interface ports */
+ if(server_init_ifs(nsd, 0, nsd->ifs, &reuseport_successful) == -1)
+ return -1;
+
+ /* continue to open the remaining reuseport ports */
+ if(nsd->reuseport && reuseport_successful) {
+ if(server_init_ifs(nsd, nsd->ifs, nsd->ifs*nsd->reuseport,
+ &reuseport_successful) == -1)
+ return -1;
+ nsd->ifs *= nsd->reuseport;
+ } else {
+ nsd->reuseport = 0;
+ }
+ return 0;
+}
+
+/*
* Prepare the server for take off.
*
*/
@@ -902,7 +975,8 @@ server_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);
- freeaddrinfo(sockets[i].addr);
+ if(sockets[i].addr)
+ freeaddrinfo(sockets[i].addr);
sockets[i].s = -1;
}
}
@@ -1168,16 +1242,14 @@ block_read(struct nsd* nsd, int s, void* p, ssize_t sz, int timeout)
{
uint8_t* buf = (uint8_t*) p;
ssize_t total = 0;
- fd_set rfds;
- struct timeval tv;
- FD_ZERO(&rfds);
-
+ struct pollfd fd;
+ memset(&fd, 0, sizeof(fd));
+ fd.fd = s;
+ fd.events = POLLIN;
+
while( total < sz) {
ssize_t ret;
- FD_SET(s, &rfds);
- tv.tv_sec = timeout;
- tv.tv_usec = 0;
- ret = select(s+1, &rfds, NULL, NULL, timeout==-1?NULL:&tv);
+ ret = poll(&fd, 1, (timeout==-1)?-1:timeout*1000);
if(ret == -1) {
if(errno == EAGAIN)
/* blocking read */
@@ -1850,7 +1922,7 @@ nsd_child_event_base(void)
void
server_child(struct nsd *nsd)
{
- size_t i;
+ size_t i, from, numifs;
region_type *server_region = region_create(xalloc, free);
struct event_base* event_base = nsd_child_event_base();
query_type *udp_query;
@@ -1862,7 +1934,7 @@ server_child(struct nsd *nsd)
}
#ifdef RATELIMIT
- rrl_init((nsd->this_child - nsd->children)/sizeof(nsd->children[0]));
+ rrl_init(nsd->this_child->child_num);
#endif
assert(nsd->server_kind != NSD_SERVER_MAIN);
@@ -1893,6 +1965,18 @@ server_child(struct nsd *nsd)
log_msg(LOG_ERR, "nsd ipcchild: event_add failed");
}
+ if(nsd->reuseport) {
+ numifs = nsd->ifs / nsd->reuseport;
+ from = numifs * nsd->this_child->child_num;
+ if(from+numifs > nsd->ifs) { /* should not happen */
+ from = 0;
+ numifs = nsd->ifs;
+ }
+ } else {
+ from = 0;
+ numifs = nsd->ifs;
+ }
+
if (nsd->server_kind & NSD_SERVER_UDP) {
#if (defined(NONBLOCKING_IS_BROKEN) || !defined(HAVE_RECVMMSG))
udp_query = query_create(server_region,
@@ -1912,7 +1996,7 @@ server_child(struct nsd *nsd)
msgs[i].msg_hdr.msg_namelen = queries[i]->addrlen;
}
#endif
- for (i = 0; i < nsd->ifs; ++i) {
+ for (i = from; i < from+numifs; ++i) {
struct udp_handler_data *data;
struct event *handler;
@@ -1939,15 +2023,15 @@ server_child(struct nsd *nsd)
* and disable them based on the current number of active TCP
* connections.
*/
- tcp_accept_handler_count = nsd->ifs;
+ tcp_accept_handler_count = numifs;
tcp_accept_handlers = (struct tcp_accept_handler_data*)
region_alloc_array(server_region,
- nsd->ifs, sizeof(*tcp_accept_handlers));
+ numifs, 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;
+ for (i = from; i < numifs; ++i) {
+ struct event *handler = &tcp_accept_handlers[i-from].event;
struct tcp_accept_handler_data* data =
- &tcp_accept_handlers[i];
+ &tcp_accept_handlers[i-from];
data->nsd = nsd;
data->socket = &nsd->tcp[i];
event_set(handler, nsd->tcp[i].s, EV_PERSIST|EV_READ,
@@ -2060,9 +2144,9 @@ handle_udp(int fd, short event, void* arg)
/* Account... */
#ifdef BIND8_STATS
- if (data->socket->addr->ai_family == AF_INET) {
+ if (data->socket->fam == AF_INET) {
STATUP(data->nsd, qudp);
- } else if (data->socket->addr->ai_family == AF_INET6) {
+ } else if (data->socket->fam == AF_INET6) {
STATUP(data->nsd, qudp6);
}
#endif
@@ -2078,9 +2162,9 @@ handle_udp(int fd, short event, void* arg)
}
#ifdef USE_ZONE_STATS
- if (data->socket->addr->ai_family == AF_INET) {
+ if (data->socket->fam == AF_INET) {
ZTATUP(data->nsd, q->zone, qudp);
- } else if (data->socket->addr->ai_family == AF_INET6) {
+ } else if (data->socket->fam == AF_INET6) {
ZTATUP(data->nsd, q->zone, qudp6);
}
#endif
@@ -2218,9 +2302,9 @@ handle_udp(int fd, short event, void* arg)
#endif /* NONBLOCKING_IS_BROKEN || !HAVE_RECVMMSG */
/* Account... */
- if (data->socket->addr->ai_family == AF_INET) {
+ if (data->socket->fam == AF_INET) {
STATUP(data->nsd, qudp);
- } else if (data->socket->addr->ai_family == AF_INET6) {
+ } else if (data->socket->fam == AF_INET6) {
STATUP(data->nsd, qudp6);
}
@@ -2235,9 +2319,9 @@ handle_udp(int fd, short event, void* arg)
}
#ifdef USE_ZONE_STATS
- if (data->socket->addr->ai_family == AF_INET) {
+ if (data->socket->fam == AF_INET) {
ZTATUP(data->nsd, q->zone, qudp);
- } else if (data->socket->addr->ai_family == AF_INET6) {
+ } else if (data->socket->fam == AF_INET6) {
ZTATUP(data->nsd, q->zone, qudp6);
}
#endif
diff --git a/usr.sbin/nsd/util.c b/usr.sbin/nsd/util.c
index 507bfee4f69..ff54eda72b2 100644
--- a/usr.sbin/nsd/util.c
+++ b/usr.sbin/nsd/util.c
@@ -1014,7 +1014,7 @@ rcode2str(int rc)
case RCODE_FORMAT:
return "FORMAT ERROR";
case RCODE_SERVFAIL:
- return "SERV FAIL";
+ return "SERVFAIL";
case RCODE_NXDOMAIN:
return "NAME ERROR";
case RCODE_IMPL:
@@ -1030,6 +1030,7 @@ rcode2str(int rc)
case RCODE_NOTAUTH:
return "SERVER NOT AUTHORITATIVE FOR ZONE";
case RCODE_NOTZONE:
+ /* Name not contained in zone */
return "NOTZONE";
default:
return "UNKNOWN ERROR";
diff --git a/usr.sbin/nsd/xfrd-tcp.c b/usr.sbin/nsd/xfrd-tcp.c
index e251df7d6ca..2dde66cf39d 100644
--- a/usr.sbin/nsd/xfrd-tcp.c
+++ b/usr.sbin/nsd/xfrd-tcp.c
@@ -568,7 +568,10 @@ xfrd_tcp_setup_write_packet(struct xfrd_tcp_pipeline* tp, xfrd_zone_t* zone)
assert(zone->tcp_waiting == 0);
/* start AXFR or IXFR for the zone */
if(zone->soa_disk_acquired == 0 || zone->master->use_axfr_only ||
- zone->master->ixfr_disabled) {
+ zone->master->ixfr_disabled ||
+ /* if zone expired, after the first round, do not ask for
+ * IXFR any more, but full AXFR (of any serial number) */
+ (zone->state == xfrd_zone_expired && zone->round_num != 0)) {
DEBUG(DEBUG_XFRD,1, (LOG_INFO, "request full zone transfer "
"(AXFR) for %s to %s",
zone->apex_str, zone->master->ip_address_spec));
diff --git a/usr.sbin/nsd/zonec.c b/usr.sbin/nsd/zonec.c
index 0ff7f9cb705..0505a8b7547 100644
--- a/usr.sbin/nsd/zonec.c
+++ b/usr.sbin/nsd/zonec.c
@@ -1449,7 +1449,7 @@ process_rr(void)
return 0;
}
if(rrset->rr_count == 65535) {
- zc_error_prev_line("too may RRs for domain RRset");
+ zc_error_prev_line("too many RRs for domain RRset");
return 0;
}
diff --git a/usr.sbin/nsd/zparser.y b/usr.sbin/nsd/zparser.y
index e8a8563fef9..8a90ddb3b0d 100644
--- a/usr.sbin/nsd/zparser.y
+++ b/usr.sbin/nsd/zparser.y
@@ -66,7 +66,7 @@ nsec3_add_params(const char* hash_algo_str, const char* flag_str,
%token <type> T_GPOS T_EID T_NIMLOC T_ATMA T_NAPTR T_KX T_A6 T_DNAME T_SINK
%token <type> T_OPT T_APL T_UINFO T_UID T_GID T_UNSPEC T_TKEY T_TSIG T_IXFR
%token <type> T_AXFR T_MAILB T_MAILA T_DS T_DLV T_SSHFP T_RRSIG T_NSEC T_DNSKEY
-%token <type> T_SPF T_NSEC3 T_IPSECKEY T_DHCID T_NSEC3PARAM T_TLSA
+%token <type> T_SPF T_NSEC3 T_IPSECKEY T_DHCID T_NSEC3PARAM T_TLSA T_URI
%token <type> T_NID T_L32 T_L64 T_LP T_EUI48 T_EUI64 T_CAA T_CDS T_CDNSKEY
/* other tokens */
@@ -632,6 +632,8 @@ type_and_rdata:
| T_CDS sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
| T_CDNSKEY sp rdata_dnskey
| T_CDNSKEY sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
+ | T_URI sp rdata_uri
+ | T_URI sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
| T_UTYPE sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
| STR error NL
{
@@ -1030,6 +1032,15 @@ rdata_eui64: STR trail
}
;
+/* RFC7553 */
+rdata_uri: STR sp STR sp STR trail
+ {
+ zadd_rdata_wireformat(zparser_conv_short(parser->region, $1.str)); /* priority */
+ zadd_rdata_wireformat(zparser_conv_short(parser->region, $3.str)); /* weight */
+ zadd_rdata_wireformat(zparser_conv_long_text(parser->region, $5.str, $5.len)); /* target */
+ }
+ ;
+
/* RFC 6844 */
rdata_caa: STR sp STR sp STR trail
{