Testing by millert@, sthen@ and me.
came up with the same diff & OK sthen@
xfrd-notify.o: $(srcdir)/xfrd-notify.c config.h $(srcdir)/xfrd-notify.h $(srcdir)/tsig.h $(srcdir)/buffer.h \
$(srcdir)/region-allocator.h $(srcdir)/util.h $(srcdir)/dname.h $(srcdir)/rbtree.h $(srcdir)/xfrd.h $(srcdir)/namedb.h $(srcdir)/dns.h \
$(srcdir)/radtree.h $(srcdir)/options.h $(srcdir)/xfrd-tcp.h $(srcdir)/packet.h
-xfrd-tcp.o: $(srcdir)/xfrd-tcp.c config.h $(srcdir)/xfrd-tcp.h $(srcdir)/xfrd.h $(srcdir)/rbtree.h \
- $(srcdir)/region-allocator.h $(srcdir)/namedb.h $(srcdir)/dname.h $(srcdir)/buffer.h $(srcdir)/util.h $(srcdir)/dns.h $(srcdir)/radtree.h \
- $(srcdir)/options.h $(srcdir)/tsig.h $(srcdir)/packet.h $(srcdir)/xfrd-disk.h
+xfrd-tcp.o: $(srcdir)/xfrd-tcp.c config.h $(srcdir)/nsd.h $(srcdir)/dns.h $(srcdir)/edns.h $(srcdir)/buffer.h \
+ $(srcdir)/region-allocator.h $(srcdir)/util.h $(srcdir)/xfrd-tcp.h $(srcdir)/xfrd.h $(srcdir)/rbtree.h $(srcdir)/namedb.h $(srcdir)/dname.h \
+ $(srcdir)/radtree.h $(srcdir)/options.h $(srcdir)/tsig.h $(srcdir)/packet.h $(srcdir)/xfrd-disk.h
zlexer.o: zlexer.c config.h $(srcdir)/zonec.h $(srcdir)/namedb.h $(srcdir)/dname.h $(srcdir)/buffer.h \
$(srcdir)/region-allocator.h $(srcdir)/util.h $(srcdir)/dns.h $(srcdir)/radtree.h $(srcdir)/rbtree.h zparser.h
zonec.o: $(srcdir)/zonec.c config.h $(srcdir)/zonec.h $(srcdir)/namedb.h $(srcdir)/dname.h $(srcdir)/buffer.h \
# Copyright 2009, Wouter Wijngaards, NLnet Labs.
# BSD licensed.
#
-# Version 30
+# Version 34
+# 2016-03-21 Check -ldl -pthread for libcrypto for ldns and openssl 1.1.0.
+# 2016-03-21 Use HMAC_Update instead of HMAC_CTX_Init (for openssl-1.1.0).
+# 2016-01-04 -D_DEFAULT_SOURCE defined with -D_BSD_SOURCE for Linux glibc 2.20
+# 2015-12-11 FLTO check for new OSX, clang.
# 2015-11-18 spelling check fix.
# 2015-11-05 ACX_SSL_CHECKS no longer adds -ldl needlessly.
# 2015-08-28 ACX_CHECK_PIE and ACX_CHECK_RELRO_NOW added.
AC_CHECK_HEADERS([getopt.h time.h],,, [AC_INCLUDES_DEFAULT])
-ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE,
+ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE,
[
#include "confdefs.h"
#include <stdlib.h>
a = 0;
return a;
}
-], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE"])
+], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE"])
-ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE,
+ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE,
[
#include "confdefs.h"
#include <stdlib.h>
a = 0;
return a;
}
-], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE"])
+], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE"])
ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG,
[
}
], [CFLAGS="$CFLAGS $C99FLAG"])
-ACX_CHECK_COMPILER_FLAG_NEEDED(-D_BSD_SOURCE,
+ACX_CHECK_COMPILER_FLAG_NEEDED(-D_BSD_SOURCE -D_DEFAULT_SOURCE,
[
#include <ctype.h>
a = isascii(32);
return a;
}
-], [CFLAGS="$CFLAGS -D_BSD_SOURCE"])
+], [CFLAGS="$CFLAGS -D_BSD_SOURCE -D_DEFAULT_SOURCE"])
ACX_CHECK_COMPILER_FLAG_NEEDED(-D_GNU_SOURCE,
[
BAKCFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -flto"
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], [
- if $CC $CFLAGS -o conftest conftest.c 2>&1 | grep "warning: no debug symbols in executable" >/dev/null; then
+ if $CC $CFLAGS -o conftest conftest.c 2>&1 | $GREP -e "warning: no debug symbols in executable" -e "warning: object" >/dev/null; then
CFLAGS="$BAKCFLAGS"
AC_MSG_RESULT(no)
else
ACX_RUNTIME_PATH_ADD([$ssldir/lib])
fi
- AC_MSG_CHECKING([for HMAC_CTX_init in -lcrypto])
+ AC_MSG_CHECKING([for HMAC_Update in -lcrypto])
LIBS="$LIBS -lcrypto"
LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto"
AC_TRY_LINK(, [
- int HMAC_CTX_init(void);
- (void)HMAC_CTX_init();
+ int HMAC_Update(void);
+ (void)HMAC_Update();
], [
AC_MSG_RESULT(yes)
- AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
- [If you have HMAC_CTX_init])
+ AC_DEFINE([HAVE_HMAC_UPDATE], 1,
+ [If you have HMAC_Update])
], [
AC_MSG_RESULT(no)
# check if -lwsock32 or -lgdi32 are needed.
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32"
AC_MSG_CHECKING([if -lcrypto needs -lgdi32])
AC_TRY_LINK([], [
- int HMAC_CTX_init(void);
- (void)HMAC_CTX_init();
+ int HMAC_Update(void);
+ (void)HMAC_Update();
],[
- AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
- [If you have HMAC_CTX_init])
+ AC_DEFINE([HAVE_HMAC_UPDATE], 1,
+ [If you have HMAC_Update])
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
AC_MSG_CHECKING([if -lcrypto needs -ldl])
AC_TRY_LINK([], [
- int HMAC_CTX_init(void);
- (void)HMAC_CTX_init();
+ int HMAC_Update(void);
+ (void)HMAC_Update();
],[
- AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
- [If you have HMAC_CTX_init])
+ AC_DEFINE([HAVE_HMAC_UPDATE], 1,
+ [If you have HMAC_Update])
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
- AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
+ LIBS="$BAKLIBS"
+ LIBSSL_LIBS="$BAKSSLLIBS"
+ LIBS="$LIBS -ldl -pthread"
+ LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
+ AC_MSG_CHECKING([if -lcrypto needs -ldl -pthread])
+ AC_TRY_LINK([], [
+ int HMAC_Update(void);
+ (void)HMAC_Update();
+ ],[
+ AC_DEFINE([HAVE_HMAC_UPDATE], 1,
+ [If you have HMAC_Update])
+ AC_MSG_RESULT(yes)
+ ],[
+ AC_MSG_RESULT(no)
+ AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
+ ])
])
])
])
AC_MSG_NOTICE([Stripping extension flags...])
ACX_CFLAGS_STRIP(-D_GNU_SOURCE)
ACX_CFLAGS_STRIP(-D_BSD_SOURCE)
+ ACX_CFLAGS_STRIP(-D_DEFAULT_SOURCE)
ACX_CFLAGS_STRIP(-D__EXTENSIONS__)
ACX_CFLAGS_STRIP(-D_POSIX_C_SOURCE=200112)
ACX_CFLAGS_STRIP(-D_XOPEN_SOURCE=600)
AC_DEFUN([AHX_CONFIG_EXT_FLAGS],
[AHX_CONFIG_FLAG_EXT(-D_GNU_SOURCE)
AHX_CONFIG_FLAG_EXT(-D_BSD_SOURCE)
+AHX_CONFIG_FLAG_EXT(-D_DEFAULT_SOURCE)
AHX_CONFIG_FLAG_EXT(-D__EXTENSIONS__)
AHX_CONFIG_FLAG_EXT(-D_POSIX_C_SOURCE=200112)
AHX_CONFIG_FLAG_EXT(-D_XOPEN_SOURCE=600)
* sections.
*/
if (done) {
+ /* delegations should have a usable address in it */
+ if(section == ADDITIONAL_A_SECTION &&
+ counts[ADDITIONAL_A_SECTION] == 0 &&
+ q->delegation_domain)
+ TC_SET(q->packet);
break;
}
#endif
}
/* Add zone RRs until answer is full. */
- assert(query->axfr_current_domain);
-
- do {
+ while (query->axfr_current_domain != NULL &&
+ domain_is_subdomain(query->axfr_current_domain,
+ query->axfr_zone->apex))
+ {
if (!query->axfr_current_rrset) {
query->axfr_current_rrset = domain_find_any_rrset(
query->axfr_current_domain,
query->axfr_current_domain
= domain_next(query->axfr_current_domain);
}
- while (query->axfr_current_domain != NULL &&
- domain_is_subdomain(query->axfr_current_domain,
- query->axfr_zone->apex));
/* Add terminating SOA RR. */
assert(query->axfr_zone->soa_rrset->rr_count == 1);
ip-address{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_IP_ADDRESS;}
interface{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_IP_ADDRESS;}
ip-transparent{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_IP_TRANSPARENT;}
+ip-freebind{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_IP_FREEBIND;}
debug-mode{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DEBUG_MODE;}
hide-version{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_HIDE_VERSION;}
ip4-only{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_IP4_ONLY;}
tcp-count{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TCP_COUNT;}
tcp-query-count{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TCP_QUERY_COUNT;}
tcp-timeout{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TCP_TIMEOUT;}
+tcp-mss{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TCP_MSS;}
+outgoing-tcp-mss{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_OUTGOING_TCP_MSS;}
ipv4-edns-size{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_IPV4_EDNS_SIZE;}
ipv6-edns-size{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_IPV6_EDNS_SIZE;}
pidfile{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_PIDFILE;}
%token VAR_CHROOT VAR_USERNAME VAR_ZONESDIR VAR_XFRDFILE VAR_DIFFFILE
%token VAR_XFRD_RELOAD_TIMEOUT VAR_TCP_QUERY_COUNT VAR_TCP_TIMEOUT
%token VAR_IPV4_EDNS_SIZE VAR_IPV6_EDNS_SIZE VAR_DO_IP4 VAR_DO_IP6
+%token VAR_TCP_MSS VAR_OUTGOING_TCP_MSS VAR_IP_FREEBIND
%token VAR_ZONEFILE
%token VAR_ZONE
%token VAR_ALLOW_NOTIFY VAR_REQUEST_XFR VAR_NOTIFY VAR_PROVIDE_XFR
server_tcp_query_count | server_tcp_timeout | server_ipv4_edns_size |
server_ipv6_edns_size | server_verbosity | server_hide_version |
server_zonelistfile | server_xfrdir |
+ server_tcp_mss | server_outgoing_tcp_mss |
server_rrl_size | server_rrl_ratelimit | server_rrl_slip |
server_rrl_ipv4_prefix_length | server_rrl_ipv6_prefix_length | server_rrl_whitelist_ratelimit |
server_zonefiles_check | server_do_ip4 | server_do_ip6 |
server_zonefiles_write | server_log_time_ascii | server_round_robin |
- server_reuseport | server_version;
+ server_reuseport | server_version | server_ip_freebind;
server_ip_address: VAR_IP_ADDRESS STRING
{
OUTYY(("P(server_ip_address:%s)\n", $2));
else cfg_parser->opt->ip_transparent = (strcmp($2, "yes")==0);
}
;
+server_ip_freebind: VAR_IP_FREEBIND STRING
+ {
+ OUTYY(("P(server_ip_freebind:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->opt->ip_freebind = (strcmp($2, "yes")==0);
+ }
+ ;
server_debug_mode: VAR_DEBUG_MODE STRING
{
OUTYY(("P(server_debug_mode:%s)\n", $2));
cfg_parser->opt->tcp_timeout = atoi($2);
}
;
+server_tcp_mss: VAR_TCP_MSS STRING
+ {
+ OUTYY(("P(server_tcp_mss:%s)\n", $2));
+ if(atoi($2) == 0 && strcmp($2, "0") != 0)
+ yyerror("number expected");
+ cfg_parser->opt->tcp_mss = atoi($2);
+ }
+ ;
+server_outgoing_tcp_mss: VAR_OUTGOING_TCP_MSS STRING
+ {
+ OUTYY(("P(server_outgoing_tcp_mss:%s)\n", $2));
+ if(atoi($2) == 0 && strcmp($2, "0") != 0)
+ yyerror("number expected");
+ cfg_parser->opt->outgoing_tcp_mss = atoi($2);
+ }
+ ;
server_ipv4_edns_size: VAR_IPV4_EDNS_SIZE STRING
{
OUTYY(("P(server_ipv4_edns_size:%s)\n", $2));
sinclude(acx_nlnetlabs.m4)
-AC_INIT(NSD,4.1.7,nsd-bugs@nlnetlabs.nl)
+AC_INIT(NSD,4.1.10,nsd-bugs@nlnetlabs.nl)
AC_CONFIG_HEADER([config.h])
CFLAGS="$CFLAGS"
# Checks for header files.
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
-AC_CHECK_HEADERS([time.h arpa/inet.h signal.h string.h strings.h fcntl.h limits.h netinet/in.h stddef.h sys/param.h sys/socket.h syslog.h unistd.h sys/select.h stdarg.h stdint.h netdb.h sys/bitypes.h tcpd.h glob.h grp.h endian.h])
+AC_CHECK_HEADERS([time.h arpa/inet.h signal.h string.h strings.h fcntl.h limits.h netinet/in.h netinet/tcp.h stddef.h sys/param.h sys/socket.h syslog.h unistd.h sys/select.h stdarg.h stdint.h netdb.h sys/bitypes.h tcpd.h glob.h grp.h endian.h])
AC_DEFUN([CHECK_VALIST_DEF],
[
# include <netinet/in.h>
#endif])
ACX_CHECK_SS_FAMILY
+AC_CHECK_MEMBERS([struct stat.st_mtimensec, struct stat.st_mtim.tv_nsec])
# Checks for library functions.
AC_FUNC_CHOWN
AC_CHECK_SIZEOF(void*)
AC_CHECK_SIZEOF(off_t)
AC_CHECK_FUNCS([arc4random arc4random_uniform])
-AC_CHECK_FUNCS([tzset alarm chroot dup2 endpwent gethostname memset memcpy pwrite socket strcasecmp strchr strdup strerror strncasecmp strtol writev getaddrinfo getnameinfo freeaddrinfo gai_strerror sigaction sigprocmask strptime strftime localtime_r setusercontext glob initgroups setresuid setreuid setresgid setregid getpwnam mmap ppoll])
+AC_CHECK_FUNCS([tzset alarm chroot dup2 endpwent gethostname memset memcpy pwrite socket strcasecmp strchr strdup strerror strncasecmp strtol writev getaddrinfo getnameinfo freeaddrinfo gai_strerror sigaction sigprocmask strptime strftime localtime_r setusercontext glob initgroups setresuid setreuid setresgid setregid getpwnam mmap ppoll clock_gettime])
-AC_ARG_ENABLE(recvmmsg, AC_HELP_STRING([--enable-recvmmsg], [Enable recvmmsg and sendmmsg compilation, faster but some kernel versions may have implementation problems]))
+AC_ARG_ENABLE(recvmmsg, AC_HELP_STRING([--enable-recvmmsg], [Enable recvmmsg and sendmmsg compilation, faster but some kernel versions may have implementation problems for IPv6]))
case "$enable_recvmmsg" in
yes)
AC_CHECK_FUNC([recvmmsg], [
CHECK_SSL
if test x$HAVE_SSL = x"yes"; then
ACX_LIB_SSL
+
+ # Check for -pthread
+ BAKLIBS="$LIBS"
+ LIBS="-lcrypto $LIBS"
+ AC_TRY_LINK([], [
+ int HMAC_Update(void);
+ (void)HMAC_Update();
+ ], [],[
+ dnl so link fails for HMAC_Update, try with -pthread.
+ BAKCFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -pthread"
+ AC_MSG_CHECKING([if libcrypto needs -pthread])
+ AC_TRY_LINK_FUNC([HMAC_Update], [
+ AC_MSG_RESULT([yes])
+ ] , [
+ AC_MSG_RESULT([no])
+ dnl restore the nonpthread value
+ CFLAGS="$BAKCFLAGS"
+ ])
+ ])
+ LIBS="$BAKLIBS"
+
if test -n "$ssldir"; then
- AC_CHECK_LIB(crypto, HMAC_CTX_init,, [
+ AC_CHECK_LIB(crypto, HMAC_Update,, [
AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
])
fi
AC_CHECK_HEADERS([openssl/ssl.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([openssl/err.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([openssl/rand.h],,, [AC_INCLUDES_DEFAULT])
+ AC_CHECK_FUNCS([HMAC_CTX_reset HMAC_CTX_new])
else
AC_MSG_WARN([No SSL, therefore remote-control is disabled])
fi
# ifndef _BSD_SOURCE
# define _BSD_SOURCE 1
# endif
+# ifndef _DEFAULT_SOURCE
+# define _DEFAULT_SOURCE 1
+# endif
# ifndef __EXTENSIONS__
# define __EXTENSIONS__ 1
# endif
#include <netinet/in.h>
#endif
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
zone->opts = zo;
zone->filename = NULL;
zone->logstr = NULL;
- zone->mtime = 0;
+ zone->mtime.tv_sec = 0;
+ zone->mtime.tv_nsec = 0;
zone->zonestatid = 0;
zone->is_secure = 0;
zone->is_changed = 0;
}
/** the the file mtime stat (or nonexist or error) */
-static int
-file_get_mtime(const char* file, time_t* mtime, int* nonexist)
+int
+file_get_mtime(const char* file, struct timespec* mtime, int* nonexist)
{
struct stat s;
if(stat(file, &s) != 0) {
- *mtime = 0;
+ mtime->tv_sec = 0;
+ mtime->tv_nsec = 0;
*nonexist = (errno == ENOENT);
return 0;
}
*nonexist = 0;
- *mtime = s.st_mtime;
+ mtime->tv_sec = s.st_mtime;
+#ifdef HAVE_STRUCT_STAT_ST_MTIMENSEC
+ mtime->tv_nsec = s.st_mtimensec;
+#elif defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
+ mtime->tv_nsec = s.st_mtim.tv_nsec;
+#else
+ mtime->tv_nsec = 0;
+#endif
return 1;
}
namedb_read_zonefile(struct nsd* nsd, struct zone* zone, udb_base* taskudb,
udb_ptr* last_task)
{
- time_t mtime = 0;
+ struct timespec mtime;
int nonexist = 0;
unsigned int errors;
const char* fname;
if(!nsd->db || !zone || !zone->opts || !zone->opts->pattern->zonefile)
return;
+ mtime.tv_sec = 0;
+ mtime.tv_nsec = 0;
fname = config_make_zonefile(zone->opts, nsd);
if(!file_get_mtime(fname, &mtime, &nonexist)) {
if(nonexist) {
return;
} else {
const char* zone_fname = zone->filename;
- time_t zone_mtime = zone->mtime;
+ struct timespec zone_mtime = zone->mtime;
if(nsd->db->udb) {
zone_fname = udb_zone_get_file_str(nsd->db->udb,
dname_name(domain_dname(zone->apex)),
domain_dname(zone->apex)->name_size);
- zone_mtime = (time_t)udb_zone_get_mtime(nsd->db->udb,
+ udb_zone_get_mtime(nsd->db->udb,
dname_name(domain_dname(zone->apex)),
- domain_dname(zone->apex)->name_size);
+ domain_dname(zone->apex)->name_size,
+ &zone_mtime);
}
/* if no zone_fname, then it was acquired in zone transfer,
* see if the file is newer than the zone transfer
* (regardless if this is a different file), because the
* zone transfer is a different content source too */
- if(!zone_fname && zone_mtime >= mtime) {
+ if(!zone_fname && timespec_compare(&zone_mtime, &mtime) >= 0) {
VERBOSITY(3, (LOG_INFO, "zonefile %s is older than "
"zone transfer in memory", fname));
return;
/* if zone_fname, then the file was acquired from reading it,
* and see if filename changed or mtime newer to read it */
} else if(zone_fname && fname &&
- strcmp(zone_fname, fname) == 0 && zone_mtime >= mtime) {
+ strcmp(zone_fname, fname) == 0 &&
+ timespec_compare(&zone_mtime, &mtime) == 0) {
VERBOSITY(3, (LOG_INFO, "zonefile %s is not modified",
fname));
return;
zone->is_changed = 0;
/* store zone into udb */
if(nsd->db->udb) {
- if(!write_zone_to_udb(nsd->db->udb, zone, mtime, fname)) {
+ if(!write_zone_to_udb(nsd->db->udb, zone, &mtime,
+ fname)) {
log_msg(LOG_ERR, "failed to store zone in db");
} else {
VERBOSITY(2, (LOG_INFO, "zone %s written to db",
/** create and write a zone */
int
-write_zone_to_udb(udb_base* udb, zone_type* zone, time_t mtime,
+write_zone_to_udb(udb_base* udb, zone_type* zone, struct timespec* mtime,
const char* file_str)
{
udb_ptr z;
}
}
/* set mtime */
- ZONE(&z)->mtime = (uint64_t)mtime;
+ ZONE(&z)->mtime = (uint64_t)mtime->tv_sec;
+ ZONE(&z)->mtime_nsec = (uint64_t)mtime->tv_nsec;
ZONE(&z)->is_changed = 0;
udb_zone_set_log_str(udb, &z, NULL);
udb_zone_set_file_str(udb, &z, file_str);
if(notexist || zone->is_changed) {
char logs[4096];
char bakfile[4096];
+ struct timespec mtime;
udb_ptr zudb;
if(nsd->db->udb) {
if(!udb_zone_search(nsd->db->udb, &zudb,
return;
}
zone->is_changed = 0;
+ /* fetch the mtime of the just created zonefile so we
+ * do not waste effort reading it back in */
+ if(!file_get_mtime(zfile, &mtime, ¬exist)) {
+ get_time(&mtime);
+ }
if(nsd->db->udb) {
- ZONE(&zudb)->mtime = (uint64_t)time(0);
+ ZONE(&zudb)->mtime = (uint64_t)mtime.tv_sec;
+ ZONE(&zudb)->mtime_nsec = (uint64_t)mtime.tv_nsec;
ZONE(&zudb)->is_changed = 0;
udb_zone_set_log_str(nsd->db->udb, &zudb, NULL);
udb_ptr_unlink(&zudb, nsd->db->udb);
} else {
- zone->mtime = time(0);
+ zone->mtime = mtime;
if(zone->filename)
region_recycle(nsd->db->region, zone->filename,
strlen(zone->filename)+1);
if(nsd->db->udb) {
ZONE(&z)->is_changed = 1;
ZONE(&z)->mtime = time_end_0;
+ ZONE(&z)->mtime_nsec = time_end_1*1000;
udb_zone_set_log_str(nsd->db->udb, &z, log_buf);
udb_zone_set_file_str(nsd->db->udb, &z, NULL);
udb_ptr_unlink(&z, nsd->db->udb);
} else {
- zonedb->mtime = time_end_0;
+ zonedb->mtime.tv_sec = time_end_0;
+ zonedb->mtime.tv_nsec = time_end_1*1000;
if(zonedb->logstr)
region_recycle(nsd->db->region, zonedb->logstr,
strlen(zonedb->logstr)+1);
/* 61 */
{ 61, NULL, T_UTYPE, 1, 1, { RDATA_WF_BINARY }, { RDATA_ZF_UNKNOWN } },
/* 62 */
- { 62, NULL, T_UTYPE, 1, 1, { RDATA_WF_BINARY }, { RDATA_ZF_UNKNOWN } },
+ { TYPE_CSYNC, "CSYNC", T_CSYNC, 3, 3, { RDATA_WF_LONG, RDATA_WF_SHORT,
+ RDATA_WF_BINARY }, { RDATA_ZF_LONG, RDATA_ZF_SHORT, RDATA_ZF_NSEC } },
/* 63 */
{ 63, NULL, T_UTYPE, 1, 1, { RDATA_WF_BINARY }, { RDATA_ZF_UNKNOWN } },
/* 64 */
#define TYPE_TLSA 52 /* RFC 6698 */
#define TYPE_CDS 59 /* RFC 7344 */
#define TYPE_CDNSKEY 60 /* RFC 7344 */
+#define TYPE_CSYNC 62 /* RFC 7477 */
#define TYPE_SPF 99 /* RFC 4408 */
return NULL;
}
+domain_type *
+find_dname_above(domain_type* domain, zone_type* zone)
+{
+ domain_type* d = domain->parent;
+ while(d && d != zone->apex) {
+ if(domain_find_rrset(d, zone, TYPE_DNAME))
+ return d;
+ d = d->parent;
+ }
+ return NULL;
+}
+
int
domain_is_glue(domain_type* domain, zone_type* zone)
{
struct zone_options* opts;
char* filename; /* set if read from file, which file */
char* logstr; /* set for zone xfer, the log string */
- time_t mtime; /* time of last modification */
+ struct timespec mtime; /* time of last modification */
unsigned zonestatid; /* array index for zone stats */
unsigned is_secure : 1; /* zone uses DNSSEC */
unsigned is_ok : 1; /* zone has not expired. */
zone_type* domain_find_parent_zone(zone_type* zone);
domain_type* domain_find_ns_rrsets(domain_type* domain, zone_type* zone, rrset_type **ns);
+/* find DNAME rrset in domain->parent or higher and return that domain */
+domain_type * find_dname_above(domain_type* domain, zone_type* zone);
int domain_is_glue(domain_type* domain, zone_type* zone);
/** dbcreate.c */
int udb_write_rr(struct udb_base* udb, struct udb_ptr* z, rr_type* rr);
void udb_del_rr(struct udb_base* udb, struct udb_ptr* z, rr_type* rr);
-int write_zone_to_udb(struct udb_base* udb, zone_type* zone, time_t mtime,
- const char* file_str);
+int write_zone_to_udb(struct udb_base* udb, zone_type* zone,
+ struct timespec* mtime, const char* file_str);
/** marshal rdata into buffer, must be MAX_RDLENGTH in size */
size_t rr_marshal_rdata(rr_type* rr, uint8_t* rdata, size_t sz);
/* dbaccess.c */
void namedb_write_zonefile(struct nsd* nsd, struct zone_options* zopt);
void namedb_write_zonefiles(struct nsd* nsd, struct nsd_options* options);
int create_dirs(const char* path);
+int file_get_mtime(const char* file, struct timespec* mtime, int* nonexist);
void allocate_domain_nsec3(domain_table_type *table, domain_type *result);
static inline int
-.TH "nsd\-checkconf" "8" "Dec 10, 2015" "NLnet Labs" "nsd 4.1.7"
+.TH "nsd\-checkconf" "8" "Jun 14, 2016" "NLnet Labs" "nsd 4.1.10"
.\" Copyright (c) 2001\-2008, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
SERV_GET_IP(ip_address, ip_addresses, o);
/* bin */
SERV_GET_BIN(ip_transparent, o);
+ SERV_GET_BIN(ip_freebind, o);
SERV_GET_BIN(debug_mode, o);
SERV_GET_BIN(do_ip4, o);
SERV_GET_BIN(do_ip6, o);
SERV_GET_INT(tcp_count, o);
SERV_GET_INT(tcp_query_count, o);
SERV_GET_INT(tcp_timeout, o);
+ SERV_GET_INT(tcp_mss, o);
+ SERV_GET_INT(outgoing_tcp_mss, o);
SERV_GET_INT(ipv4_edns_size, o);
SERV_GET_INT(ipv6_edns_size, o);
SERV_GET_INT(statistics, o);
printf("server:\n");
printf("\tdebug-mode: %s\n", opt->debug_mode?"yes":"no");
printf("\tip-transparent: %s\n", opt->ip_transparent?"yes":"no");
+ printf("\tip-freebind: %s\n", opt->ip_freebind?"yes":"no");
printf("\treuseport: %s\n", opt->reuseport?"yes":"no");
printf("\tdo-ip4: %s\n", opt->do_ip4?"yes":"no");
printf("\tdo-ip6: %s\n", opt->do_ip6?"yes":"no");
print_string_var("version:", opt->version);
print_string_var("nsid:", opt->nsid);
print_string_var("logfile:", opt->logfile);
- printf("\tserver_count: %d\n", opt->server_count);
- printf("\ttcp_count: %d\n", opt->tcp_count);
- printf("\ttcp_query_count: %d\n", opt->tcp_query_count);
- printf("\ttcp_timeout: %d\n", opt->tcp_timeout);
+ printf("\tserver-count: %d\n", opt->server_count);
+ printf("\ttcp-count: %d\n", opt->tcp_count);
+ printf("\ttcp-query-count: %d\n", opt->tcp_query_count);
+ printf("\ttcp-timeout: %d\n", opt->tcp_timeout);
+ printf("\ttcp-mss: %d\n", opt->tcp_mss);
+ printf("\toutgoing-tcp-mss: %d\n", opt->outgoing_tcp_mss);
printf("\tipv4-edns-size: %d\n", (int) opt->ipv4_edns_size);
printf("\tipv6-edns-size: %d\n", (int) opt->ipv6_edns_size);
print_string_var("pidfile:", opt->pidfile);
print_string_var("xfrdfile:", opt->xfrdfile);
print_string_var("zonelistfile:", opt->zonelistfile);
print_string_var("xfrdir:", opt->xfrdir);
- printf("\txfrd_reload_timeout: %d\n", opt->xfrd_reload_timeout);
+ printf("\txfrd-reload-timeout: %d\n", opt->xfrd_reload_timeout);
printf("\tlog-time-ascii: %s\n", opt->log_time_ascii?"yes":"no");
printf("\tround-robin: %s\n", opt->round_robin?"yes":"no");
printf("\tverbosity: %d\n", opt->verbosity);
-.TH "nsd\-checkzone" "8" "Dec 10, 2015" "NLnet Labs" "nsd 4.1.7"
+.TH "nsd\-checkzone" "8" "Jun 14, 2016" "NLnet Labs" "nsd 4.1.10"
.\" Copyright (c) 2014, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
-.TH "nsd\-control" "8" "Dec 10, 2015" "NLnet Labs" "nsd 4.1.7"
+.TH "nsd\-control" "8" "Jun 14, 2016" "NLnet Labs" "nsd 4.1.10"
.\" Copyright (c) 2011, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
-.TH "NSD" "8" "Dec 10, 2015" "NLnet Labs" "NSD 4.1.7"
+.TH "NSD" "8" "Jun 14, 2016" "NLnet Labs" "NSD 4.1.10"
.\" Copyright (c) 2001\-2008, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
.B nsd
-\- Name Server Daemon (NSD) version 4.1.7.
+\- Name Server Daemon (NSD) version 4.1.10.
.SH "SYNOPSIS"
.B nsd
.RB [ \-4 ]
Use the specified
.I database
instead of the default of
-.IR @dbfile@ .
+.IR '@dbfile@' .
If a
.B zonesdir:
is specified in the config file this path can be relative to that
Dump BIND8\-style statistics into the log. Ignored otherwise.
.SH "FILES"
.TP
-@dbfile@
+"@dbfile@"
default
.B NSD
database
}
nsd.tcp_timeout = nsd.options->tcp_timeout;
nsd.tcp_query_count = nsd.options->tcp_query_count;
+ nsd.tcp_mss = nsd.options->tcp_mss;
+ nsd.outgoing_tcp_mss = nsd.options->outgoing_tcp_mss;
nsd.ipv4_edns_size = nsd.options->ipv4_edns_size;
nsd.ipv6_edns_size = nsd.options->ipv6_edns_size;
VERBOSITY(2, (LOG_WARNING, "chown %s failed: %s",
nsd.log_filename, strerror(errno)));
}
+ log_msg(LOG_NOTICE, "%s starting (%s)", argv0, PACKAGE_STRING);
/* Do we have a running nsd? */
if ((oldpid = readpid(nsd.pidfile)) == -1) {
-.TH "nsd.conf" "5" "Dec 10, 2015" "NLnet Labs" "nsd 4.1.7"
+.TH "nsd.conf" "5" "Jun 14, 2016" "NLnet Labs" "nsd 4.1.10"
.\" Copyright (c) 2001\-2008, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
listen to IP addresses that are not (yet) added to the network interface, so
that it can answer immediately when the address is added. Default is no.
.TP
+.B ip\-freebind:\fR <yes or no>
+Set the IP_FREEBIND option to bind to nonlocal addresses and interfaces
+that are down. Similar to ip\-transparent. Default is no.
+.TP
.B reuseport:\fR <yes or no>
Use the SO_REUSEPORT socket option, and create file descriptors for every
server in the server\-count. This improves performance of the network
.TP
.B database:\fR <filename>
By default
-.I @dbfile@
+.I '@dbfile@'
is used. The specified file is used to store the compiled
zone information. Same as commandline option
.BR \-f.
.B tcp\-timeout:\fR <number>
Overrides the default TCP timeout. This also affects zone transfers over TCP.
.TP
+.B tcp-mss:\fR <number>
+Maximum segment size (MSS) of TCP socket on which the server responds
+to queries. Value lower than common MSS on Ethernet
+(1220 for example) will address path MTU problem.
+Note that not all platform supports socket option to set MSS (TCP_MAXSEG).
+Default is system default MSS determined by interface MTU and
+negotiation between server and client.
+.TP
+.B outgoing\-tcp\-mss:\fR <number>
+Maximum segment size (MSS) of TCP socket for outgoing XFR request
+to other namesevers. Value lower than
+common MSS on Ethernet (1220 for example) will
+address path MTU problem.
+Note that not all platform supports socket option to set MSS (TCP_MAXSEG).
+Default is system default MSS determined by interface MTU and
+negotiation between NSD and other servers.
+.TP
.B ipv4\-edns\-size:\fR <number>
Preferred EDNS buffer size for IPv4. Default 4096.
.TP
BIND9 has for the resolver or caching thus have no equivalents for NSD.
.SH "FILES"
.TP
-@dbfile@
+"@dbfile@"
default
.B NSD
database
# Allow binding to non local addresses. Default no.
# ip-transparent: no
+ # Allow binding to addresses that are down. Default no.
+ # ip-freebind: no
+
# use the reuseport socket option for performance. Default no.
# reuseport: no
# Override the default (120 seconds) TCP timeout.
# tcp-timeout: 120
+ # Maximum segment size (MSS) of TCP socket on which the server
+ # responds to queries. Default is 0, system default MSS.
+ # tcp-mss: 0
+
+ # Maximum segment size (MSS) of TCP socket for outgoing AXFR request.
+ # Default is 0, system default MSS.
+ # outgoing-tcp-mss: 0
+
# Preferred EDNS buffer size for IPv4.
# ipv4-edns-size: 4096
int current_tcp_count;
int tcp_query_count;
int tcp_timeout;
+ int tcp_mss;
+ int outgoing_tcp_mss;
size_t ipv4_edns_size;
size_t ipv6_edns_size;
original->nsec3->nsec3_cover);
}
else { /* add nsec3 to prove rrset does not exist */
- if(original->nsec3 && original->nsec3->nsec3_is_exact) {
+ if(original->nsec3) {
+ if(!original->nsec3->nsec3_is_exact) {
+ /* go up to an existing parent */
+ while(original->parent && original->parent->nsec3 && !original->parent->nsec3->nsec3_is_exact)
+ original = original->parent;
+ }
nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
original->nsec3->nsec3_cover);
+ if(!original->nsec3->nsec3_is_exact) {
+ if(original->parent && original->parent->nsec3 && original->parent->nsec3->nsec3_is_exact)
+ nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
+ original->parent->nsec3->nsec3_cover);
+
+ }
}
}
}
#if 0
query->qtype != TYPE_NSEC3 &&
#endif
- domain_has_only_NSEC3(*match, query->zone))
+ (domain_has_only_NSEC3(*match, query->zone) ||
+ !domain_find_any_rrset(*match, query->zone)))
{
/* this looks like a NSEC3 domain, but is actually an empty non-terminal. */
nsec3_answer_nodata(query, answer, *match);
opt->keys = rbtree_create(region, rbtree_strcmp);
opt->ip_addresses = NULL;
opt->ip_transparent = 0;
+ opt->ip_freebind = 0;
opt->debug_mode = 0;
opt->verbosity = 0;
opt->hide_version = 0;
opt->tcp_count = 100;
opt->tcp_query_count = 0;
opt->tcp_timeout = TCP_TIMEOUT;
+ opt->tcp_mss = 0;
+ opt->outgoing_tcp_mss = 0;
opt->ipv4_edns_size = EDNS_MAX_MESSAGE_LEN;
opt->ipv6_edns_size = EDNS_MAX_MESSAGE_LEN;
opt->pidfile = PIDFILE;
ip_address_option_t* ip_addresses;
int ip_transparent;
+ int ip_freebind;
int debug_mode;
int verbosity;
int hide_version;
int tcp_count;
int tcp_query_count;
int tcp_timeout;
+ int tcp_mss;
+ int outgoing_tcp_mss;
size_t ipv4_edns_size;
size_t ipv6_edns_size;
const char* pidfile;
{ 0, (rr_section_type) 0 }
};
+struct additional_rr_types swap_aaaa_additional_rr_types[] = {
+ { TYPE_AAAA, ADDITIONAL_A_SECTION },
+ { TYPE_A, ADDITIONAL_AAAA_SECTION },
+ { 0, (rr_section_type) 0 }
+};
+
struct additional_rr_types rt_additional_rr_types[] = {
{ TYPE_A, ADDITIONAL_A_SECTION },
{ TYPE_AAAA, ADDITIONAL_AAAA_SECTION },
result = answer_add_rrset(answer, section, owner, rrset);
switch (rrset_rrtype(rrset)) {
case TYPE_NS:
+ /* if query over IPv6, swap A and AAAA; put AAAA first */
add_additional_rrsets(query, answer, rrset, 0, 1,
- default_additional_rr_types);
+ (query->addr.ss_family == AF_INET6)?
+ swap_aaaa_additional_rr_types:
+ default_additional_rr_types);
break;
case TYPE_MB:
add_additional_rrsets(query, answer, rrset, 0, 0,
zone_type* origzone = q->zone;
++q->cname_count;
- while (!closest_encloser->is_existing)
- closest_encloser = closest_encloser->parent;
-
answer_lookup_zone(nsd, q, answer, closest_match->number,
closest_match == closest_encloser,
closest_match, closest_encloser,
{
domain_type *match;
domain_type *original = closest_match;
+ domain_type *dname_ce;
rrset_type *rrset;
#ifdef NSEC3
closest_encloser = closest_encloser->parent;
}
#endif /* NSEC3 */
+ if((dname_ce = find_dname_above(closest_encloser, q->zone)) != NULL) {
+ /* occlude the found data, the DNAME is closest_encloser */
+ closest_encloser = dname_ce;
+ exact = 0;
+ }
if (exact) {
match = closest_match;
return;
}
- while (closest_encloser && !closest_encloser->is_existing)
- closest_encloser = closest_encloser->parent;
answer_lookup_zone(nsd, q, answer, newnum,
closest_match == closest_encloser,
closest_match, closest_encloser, newname);
RCODE_SET(q->packet, RCODE_SERVFAIL);
return;
}
+ /* now move up the closest encloser until it exists, previous
+ * (possibly empty) closest encloser was useful to finding the zone
+ * (for empty zones too), but now we want actual data nodes */
+ if (closest_encloser && !closest_encloser->is_existing) {
+ exact = 0;
+ while (closest_encloser != NULL && !closest_encloser->is_existing)
+ closest_encloser = closest_encloser->parent;
+ }
/*
* See RFC 4035 (DNSSEC protocol) section 3.1.4.1 Responding
} else {
q->delegation_domain = domain_find_ns_rrsets(
closest_encloser, q->zone, &q->delegation_rrset);
+ if(q->delegation_domain && find_dname_above(q->delegation_domain, q->zone)) {
+ q->delegation_domain = NULL; /* use higher DNAME */
+ }
if (!q->delegation_domain
|| (exact && q->qtype == TYPE_DS && closest_encloser == q->delegation_domain))
answer_init(&answer);
exact = namedb_lookup(nsd->db, q->qname, &closest_match, &closest_encloser);
- if (!closest_encloser->is_existing) {
- exact = 0;
- while (closest_encloser != NULL && !closest_encloser->is_existing)
- closest_encloser = closest_encloser->parent;
- }
- if(!closest_encloser) {
- RCODE_SET(q->packet, RCODE_SERVFAIL);
- return;
- }
answer_lookup_zone(nsd, q, &answer, 0, exact, closest_match,
closest_encloser, q->qname);
query_state_type rrl_slip(query_type* query)
{
/* discard number the packets, randomly */
-#ifdef HAVE_ARC4RANDOM
+#ifdef HAVE_ARC4RANDOM_UNIFORM
+ if((rrl_slip_ratio > 0) && ((rrl_slip_ratio == 1) || ((arc4random_uniform(rrl_slip_ratio)) == 0))) {
+#elif HAVE_ARC4RANDOM
if((rrl_slip_ratio > 0) && ((rrl_slip_ratio == 1) || ((arc4random() % rrl_slip_ratio) == 0))) {
#else
if((rrl_slip_ratio > 0) && ((rrl_slip_ratio == 1) || ((random() % rrl_slip_ratio) == 0))) {
{
struct addrinfo* addr;
size_t i;
-#if defined(SO_REUSEPORT) || defined(SO_REUSEADDR) || (defined(INET6) && (defined(IPV6_V6ONLY) || defined(IPV6_USE_MIN_MTU) || defined(IPV6_MTU) || defined(IP_TRANSPARENT)))
+#if defined(SO_REUSEPORT) || defined(SO_REUSEADDR) || (defined(INET6) && (defined(IPV6_V6ONLY) || defined(IPV6_USE_MIN_MTU) || defined(IPV6_MTU) || defined(IP_TRANSPARENT)) || defined(IP_FREEBIND))
int on = 1;
#endif
}
/* Bind it... */
+ if (nsd->options->ip_freebind) {
+#ifdef IP_FREEBIND
+ if (setsockopt(nsd->udp[i].s, IPPROTO_IP, IP_FREEBIND, &on, sizeof(on)) < 0) {
+ log_msg(LOG_ERR, "setsockopt(...,IP_FREEBIND, ...) failed for udp: %s",
+ strerror(errno));
+ }
+#endif /* IP_FREEBIND */
+ }
+
if (nsd->options->ip_transparent) {
#ifdef IP_TRANSPARENT
if (setsockopt(nsd->udp[i].s, IPPROTO_IP, IP_TRANSPARENT, &on, sizeof(on)) < 0) {
# endif
}
#endif
+ /* set maximum segment size to tcp socket */
+ if(nsd->tcp_mss > 0) {
+#if defined(IPPROTO_TCP) && defined(TCP_MAXSEG)
+ if(setsockopt(nsd->tcp[i].s, IPPROTO_TCP, TCP_MAXSEG,
+ (void*)&nsd->tcp_mss,
+ sizeof(nsd->tcp_mss)) < 0) {
+ log_msg(LOG_ERR,
+ "setsockopt(...,TCP_MAXSEG,...)"
+ " failed for tcp: %s", strerror(errno));
+ }
+#else
+ log_msg(LOG_ERR, "setsockopt(TCP_MAXSEG) unsupported");
+#endif /* defined(IPPROTO_TCP) && defined(TCP_MAXSEG) */
+ }
+
/* set it nonblocking */
/* (StevensUNP p463), if tcp listening socket is blocking, then
it may block in accept, even if select() says readable. */
}
/* Bind it... */
+ if (nsd->options->ip_freebind) {
+#ifdef IP_FREEBIND
+ if (setsockopt(nsd->tcp[i].s, IPPROTO_IP, IP_FREEBIND, &on, sizeof(on)) < 0) {
+ log_msg(LOG_ERR, "setsockopt(...,IP_FREEBIND, ...) failed for tcp: %s",
+ strerror(errno));
+ }
+#endif /* IP_FREEBIND */
+ }
+
if (nsd->options->ip_transparent) {
#ifdef IP_TRANSPARENT
if (setsockopt(nsd->tcp[i].s, IPPROTO_IP, IP_TRANSPARENT, &on, sizeof(on)) < 0) {
*/
if (slowaccept || data->nsd->current_tcp_count == data->nsd->maximum_tcp_count) {
configure_handler_event_types(EV_READ|EV_PERSIST);
- slowaccept = 0;
+ if(slowaccept) {
+ event_del(&slowaccept_event);
+ slowaccept = 0;
+ }
}
--data->nsd->current_tcp_count;
assert(data->nsd->current_tcp_count >= 0);
cleanup_context(void *data)
{
HMAC_CTX *context = (HMAC_CTX *) data;
+#ifdef HAVE_HMAC_CTX_NEW
+ HMAC_CTX_free(context);
+#else
HMAC_CTX_cleanup(context);
+ free(context);
+#endif
}
static void *
create_context(region_type *region)
{
- HMAC_CTX *context
- = (HMAC_CTX *) region_alloc(region, sizeof(HMAC_CTX));
+#ifdef HAVE_HMAC_CTX_NEW
+ HMAC_CTX *context = HMAC_CTX_new();
+#else
+ HMAC_CTX *context = (HMAC_CTX *) malloc(sizeof(HMAC_CTX));
+#endif
region_add_cleanup(region, cleanup_context, context);
+#ifdef HAVE_HMAC_CTX_RESET
+ HMAC_CTX_reset(context);
+#else
HMAC_CTX_init(context);
+#endif
return context;
}
/** magic string that starts an UDB file, uint64_t, note first byte=0, to mark
* header start as a chunk. */
#define UDB_MAGIC (((uint64_t)'u'<<48)|((uint64_t)'d'<<40)|((uint64_t)'b' \
- <<32)|((uint64_t)'v'<<24)|((uint64_t)'0'<<16)|((uint64_t)'a'<<8))
+ <<32)|((uint64_t)'v'<<24)|((uint64_t)'0'<<16)|((uint64_t)'b'<<8))
/* UDB BASE */
/**
ZONE(&z)->rr_count = 0;
ZONE(&z)->expired = 0;
ZONE(&z)->mtime = 0;
+ ZONE(&z)->mtime_nsec = 0;
ZONE(&z)->namelen = dlen;
memmove(ZONE(&z)->name, dname, dlen);
if(!udb_radix_tree_create(udb, &dtree)) {
ZONE(zone)->rr_count = 0;
ZONE(zone)->expired = 0;
ZONE(zone)->mtime = 0;
+ ZONE(zone)->mtime_nsec = 0;
udb_ptr_unlink(&dtree, udb);
}
return 0;
}
-uint64_t udb_zone_get_mtime(udb_base* udb, const uint8_t* dname, size_t dlen)
+void udb_zone_get_mtime(udb_base* udb, const uint8_t* dname, size_t dlen,
+ struct timespec* mtime)
{
udb_ptr z;
if(udb_zone_search(udb, &z, dname, dlen)) {
- uint64_t t = ZONE(&z)->mtime;
+ mtime->tv_sec = ZONE(&z)->mtime;
+ mtime->tv_nsec = ZONE(&z)->mtime_nsec;
udb_ptr_unlink(&z, udb);
- return t;
+ return;
}
- return 0;
+ mtime->tv_sec = 0;
+ mtime->tv_nsec = 0;
}
void udb_zone_set_log_str(udb_base* udb, udb_ptr* zone, const char* str)
udb_rel_ptr file_str;
/** modification time, time when the zone data was changed */
uint64_t mtime;
+ /** modification time, nsecs */
+ uint64_t mtime_nsec;
/** number of RRsets in the zone */
uint64_t rrset_count;
/** number of RRs in the zone */
int udb_zone_search(udb_base* udb, udb_ptr* result, const uint8_t* dname,
size_t dlen);
/** get modification time for zone or 0 */
-uint64_t udb_zone_get_mtime(udb_base* udb, const uint8_t* dname, size_t dlen);
+void udb_zone_get_mtime(udb_base* udb, const uint8_t* dname, size_t dlen,
+ struct timespec* mtime);
/** set log str in udb, or remove it */
void udb_zone_set_log_str(udb_base* udb, udb_ptr* zone, const char* str);
/** set file str in udb, or remove it */
return 1;
}
+void get_time(struct timespec* t)
+{
+ struct timeval tv;
+#ifdef HAVE_CLOCK_GETTIME
+ /* first try nanosecond precision */
+ if(clock_gettime(CLOCK_REALTIME, t)>=0) {
+ return; /* success */
+ }
+ log_msg(LOG_ERR, "clock_gettime: %s", strerror(errno));
+#endif
+ /* try millisecond precision */
+ if(gettimeofday(&tv, NULL)>=0) {
+ t->tv_sec = tv.tv_sec;
+ t->tv_nsec = tv.tv_usec*1000;
+ return; /* success */
+ }
+ log_msg(LOG_ERR, "gettimeofday: %s", strerror(errno));
+ /* whole seconds precision */
+ t->tv_sec = time(0);
+ t->tv_nsec = 0;
+}
+
int
timespec_compare(const struct timespec *left,
const struct timespec *right)
left->tv_nsec = 1000 * right->tv_usec;
}
+/* get the time */
+void get_time(struct timespec* t);
/*
* Converts a string representation of a period of time into
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
+#include "nsd.h"
#include "xfrd-tcp.h"
#include "buffer.h"
#include "packet.h"
return 0;
}
+ if(xfrd->nsd->outgoing_tcp_mss > 0) {
+#if defined(IPPROTO_TCP) && defined(TCP_MAXSEG)
+ if(setsockopt(fd, IPPROTO_TCP, TCP_MAXSEG,
+ (void*)&xfrd->nsd->outgoing_tcp_mss,
+ sizeof(xfrd->nsd->outgoing_tcp_mss)) < 0) {
+ log_msg(LOG_ERR, "xfrd: setsockopt(TCP_MAXSEG)"
+ "failed: %s", strerror(errno));
+ }
+#else
+ log_msg(LOG_ERR, "setsockopt(TCP_MAXSEG) unsupported");
+#endif
+ }
+
tp->ip_len = xfrd_acl_sockaddr_to(zone->master, &tp->ip);
/* bind it */
/* if no information, use reasonable timeout */
if(zone->fresh_xfr_timeout == 0)
zone->fresh_xfr_timeout = XFRD_TRANSFER_TIMEOUT_START;
-#ifdef HAVE_ARC4RANDOM
+#ifdef HAVE_ARC4RANDOM_UNIFORM
xfrd_set_timer(zone, zone->fresh_xfr_timeout
- + arc4random()%zone->fresh_xfr_timeout);
+ + arc4random_uniform(zone->fresh_xfr_timeout));
+#elif HAVE_ARC4RANDOM
+ xfrd_set_timer(zone, zone->fresh_xfr_timeout
+ + arc4random() % zone->fresh_xfr_timeout);
#else
xfrd_set_timer(zone, zone->fresh_xfr_timeout
+ random()%zone->fresh_xfr_timeout);
/* only for times far in the future */
if(t > 10) {
time_t base = t*9/10;
-#ifdef HAVE_ARC4RANDOM
- t = base + arc4random()%(t-base);
+#ifdef HAVE_ARC4RANDOM_UNIFORM
+ t = base + arc4random_uniform(t-base);
+#elif HAVE_ARC4RANDOM
+ t = base + arc4random() % (t-base);
#else
t = base + random()%(t-base);
#endif
%token <type> T_AXFR T_MAILB T_MAILA T_DS T_DLV T_SSHFP T_RRSIG T_NSEC T_DNSKEY
%token <type> T_SPF T_NSEC3 T_IPSECKEY T_DHCID T_NSEC3PARAM T_TLSA T_URI
%token <type> T_NID T_L32 T_L64 T_LP T_EUI48 T_EUI64 T_CAA T_CDS T_CDNSKEY
+%token <type> T_CSYNC
/* other tokens */
%token DOLLAR_TTL DOLLAR_ORIGIN NL SP
| T_CDS sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
| T_CDNSKEY sp rdata_dnskey
| T_CDNSKEY sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
+ | T_CSYNC sp rdata_csync
+ | T_CSYNC sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
| T_URI sp rdata_uri
| T_URI sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
| T_UTYPE sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
}
;
+/* RFC7477 */
+rdata_csync: STR sp STR nsec_seq
+ {
+ zadd_rdata_wireformat(zparser_conv_serial(parser->region, $1.str));
+ zadd_rdata_wireformat(zparser_conv_short(parser->region, $3.str));
+ zadd_rdata_wireformat(zparser_conv_nsec(parser->region, nsecbits)); /* nsec bitlist */
+ memset(nsecbits, 0, sizeof(nsecbits));
+ nsec_highest_rcode = 0;
+ }
+ ;
+
rdata_unknown: URR sp STR sp str_sp_seq trail
{
/* $2 is the number of octets, currently ignored */