mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
Compare commits
230
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20a77f115f | ||
|
|
07470115e5 | ||
|
|
061e2dd431 | ||
|
|
76f273aed5 | ||
|
|
fa94a9753d | ||
|
|
f82edc1b64 | ||
|
|
3c55073799 | ||
|
|
85c915f116 | ||
|
|
d16524d39a | ||
|
|
b212b302e6 | ||
|
|
0f1aa80123 | ||
|
|
68e7d81863 | ||
|
|
03c4ee417a | ||
|
|
482fbf3872 | ||
|
|
d6aba21ac4 | ||
|
|
d4f49a7a40 | ||
|
|
6cab3a1dda | ||
|
|
f37bd4f2ce | ||
|
|
64b28585e0 | ||
|
|
6b1222dcb6 | ||
|
|
44e894b6c2 | ||
|
|
4943101c09 | ||
|
|
c7872942ac | ||
|
|
1467c5de52 | ||
|
|
097c70be91 | ||
|
|
87ded67cb6 | ||
|
|
98b6f90637 | ||
|
|
b9ed797a22 | ||
|
|
25096aa3ab | ||
|
|
42e23da129 | ||
|
|
cd8e4a0bc5 | ||
|
|
d051dfaf19 | ||
|
|
f2da5c6867 | ||
|
|
97456b8f4c | ||
|
|
6ba973a8bd | ||
|
|
7090975243 | ||
|
|
62f3b7bb93 | ||
|
|
ccf4099366 | ||
|
|
15c805677c | ||
|
|
15aacbe89b | ||
|
|
452b7fce3a | ||
|
|
598beb1b06 | ||
|
|
06a3f735d7 | ||
|
|
eb03758c79 | ||
|
|
c42a74b77c | ||
|
|
8903dd175a | ||
|
|
5c73dbdbc0 | ||
|
|
277b1a1c2d | ||
|
|
da1bd6fd3f | ||
|
|
fe56d9e504 | ||
|
|
85016da2cb | ||
|
|
159d5a18b6 | ||
|
|
b375ba3455 | ||
|
|
65cc9f1dd1 | ||
|
|
43ab18d6ed | ||
|
|
aafed76b0f | ||
|
|
0a1195f690 | ||
|
|
ea158af48d | ||
|
|
6dd1dbd09f | ||
|
|
3d4f037f53 | ||
|
|
3930e23b8c | ||
|
|
6819016a83 | ||
|
|
2d2c04c271 | ||
|
|
13a839d624 | ||
|
|
2bf79c2e65 | ||
|
|
53a448ffae | ||
|
|
d71a1ba0c2 | ||
|
|
e1a817338e | ||
|
|
cf147df593 | ||
|
|
279f409636 | ||
|
|
a0db316445 | ||
|
|
8e472aa8c4 | ||
|
|
ec452bed83 | ||
|
|
d9a2a36049 | ||
|
|
1b08416dbe | ||
|
|
1c0f5a8aba | ||
|
|
bafc5741ba | ||
|
|
eb926f15da | ||
|
|
b441875206 | ||
|
|
8e20d58fa8 | ||
|
|
fa3337d42a | ||
|
|
0d5441bd8a | ||
|
|
d17f39416b | ||
|
|
4e92719611 | ||
|
|
fc52ee5aca | ||
|
|
ac103fc5bd | ||
|
|
af71677114 | ||
|
|
6e46110ae8 | ||
|
|
82ebbe32d1 | ||
|
|
1736d8078a | ||
|
|
57199f80c9 | ||
|
|
d7172c55ed | ||
|
|
9429092966 | ||
|
|
7f6827cc97 | ||
|
|
773d8e3b84 | ||
|
|
682ff957ed | ||
|
|
c90d6d2538 | ||
|
|
8e1cb52458 | ||
|
|
987c707a4d | ||
|
|
eac4a9604c | ||
|
|
9bbc6f4b56 | ||
|
|
718dcce317 | ||
|
|
08835e01ee | ||
|
|
d64b14cff9 | ||
|
|
943f8f43b9 | ||
|
|
7a58fdcebc | ||
|
|
db6cd0a635 | ||
|
|
03a7425ead | ||
|
|
d25268b7ee | ||
|
|
e789dac9a1 | ||
|
|
850525139b | ||
|
|
db33e4dbf6 | ||
|
|
05aaa8a138 | ||
|
|
09b9ea04a3 | ||
|
|
358fd2ad07 | ||
|
|
14059dca14 | ||
|
|
388d0639bc | ||
|
|
e8050a5587 | ||
|
|
c352ee2e85 | ||
|
|
9117191d44 | ||
|
|
924789d877 | ||
|
|
8c2f658cd1 | ||
|
|
8cafd0e379 | ||
|
|
ad2fa5c810 | ||
|
|
bec8d15cd0 | ||
|
|
dff630c788 | ||
|
|
30038d8fa6 | ||
|
|
71e85ee6fb | ||
|
|
b54efa5c69 | ||
|
|
c480290a30 | ||
|
|
c1d79638c4 | ||
|
|
6f6ccee95b | ||
|
|
c44ef11de5 | ||
|
|
9c8ac75026 | ||
|
|
31f071db25 | ||
|
|
b5337c1e05 | ||
|
|
2e26ec2d01 | ||
|
|
cf8ee796c9 | ||
|
|
8b078cc509 | ||
|
|
589924e36c | ||
|
|
fd9aa53370 | ||
|
|
6dd2c0467e | ||
|
|
a7ec2af62a | ||
|
|
bbfb2f2202 | ||
|
|
1238b7979f | ||
|
|
1f29a98366 | ||
|
|
0916e1d0ea | ||
|
|
65ad15da56 | ||
|
|
5ae8bec719 | ||
|
|
e0fd0ef80c | ||
|
|
8e62925ffb | ||
|
|
e7282a291b | ||
|
|
fa909b6cc7 | ||
|
|
5fa08a0be9 | ||
|
|
1cf44b0b5c | ||
|
|
111ef6f862 | ||
|
|
33e6deb675 | ||
|
|
1aa1c1404c | ||
|
|
694f02f1df | ||
|
|
9761d0c6de | ||
|
|
3b35e412f5 | ||
|
|
35172e89f4 | ||
|
|
eb29370697 | ||
|
|
01f3e90871 | ||
|
|
7bdae2d545 | ||
|
|
ae666ea203 | ||
|
|
557aad4b72 | ||
|
|
bbb583e754 | ||
|
|
2824d0ad52 | ||
|
|
6dfa0d643b | ||
|
|
3395637700 | ||
|
|
29ce27f300 | ||
|
|
e3e6246860 | ||
|
|
c8696005a7 | ||
|
|
fc7f057d0b | ||
|
|
1befacc444 | ||
|
|
a1c76554a2 | ||
|
|
cf1d2135e1 | ||
|
|
1cee11cba8 | ||
|
|
ae5d794c47 | ||
|
|
a08cf3c4e5 | ||
|
|
8f5596f643 | ||
|
|
a798dcb5bd | ||
|
|
939c103a73 | ||
|
|
ef4d9a1ecb | ||
|
|
9a0b040403 | ||
|
|
b8b2ce58d0 | ||
|
|
6a918b841f | ||
|
|
115c36a94e | ||
|
|
03c34b695f | ||
|
|
aa0536dcb5 | ||
|
|
28131d5845 | ||
|
|
69aafe3a1c | ||
|
|
2479955f9f | ||
|
|
9b47af529e | ||
|
|
11f5e16932 | ||
|
|
3d5cef932e | ||
|
|
0f825eb283 | ||
|
|
7ea69fe9c2 | ||
|
|
83367411ef | ||
|
|
51810c1408 | ||
|
|
ddddbf284f | ||
|
|
28c9738062 | ||
|
|
cefc027dbc | ||
|
|
d66ff13f9c | ||
|
|
01027a8322 | ||
|
|
086e31e88d | ||
|
|
ce63172a67 | ||
|
|
684429e6c8 | ||
|
|
80424bc16e | ||
|
|
a16c24b4f0 | ||
|
|
52f4247c48 | ||
|
|
dfd769b60c | ||
|
|
680b0d1cce | ||
|
|
bcdd32e7e1 | ||
|
|
b6d88c0b41 | ||
|
|
7cf757596c | ||
|
|
0f57f21ca2 | ||
|
|
68d82e9ce4 | ||
|
|
881f0ad30f | ||
|
|
d9ceec4005 | ||
|
|
f82a0847eb | ||
|
|
c3f5b5f773 | ||
|
|
b72d40f3dd | ||
|
|
c4cac78f10 | ||
|
|
164f86e377 | ||
|
|
c30e90b435 | ||
|
|
365f87a4a4 | ||
|
|
1af30c02fc | ||
|
|
83938e1d3b |
+992
-299
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,5 @@
|
||||
Unbound README
|
||||
* ./configure && make && make install
|
||||
* on BSDs and Solaris use gmake (GNU make).
|
||||
* You can use libevent if you want. libevent is useful when using
|
||||
many (10000) outgoing ports. By default max 256 ports are opened at
|
||||
the same time and the builtin alternative is equally capable and a
|
||||
|
||||
Vendored
+739
-345
File diff suppressed because it is too large
Load Diff
+51
-10
@@ -2,7 +2,14 @@
|
||||
# Copyright 2009, Wouter Wijngaards, NLnet Labs.
|
||||
# BSD licensed.
|
||||
#
|
||||
# Version 14
|
||||
# Version 21
|
||||
# 2012-02-09 Fix AHX_MEMCMP_BROKEN with undef in compat/memcmp.h.
|
||||
# 2012-01-20 Fix COMPILER_FLAGS_UNBOUND for gcc 4.6.2 assigned-not-used-warns.
|
||||
# 2011-12-05 Fix getaddrinfowithincludes on windows with fedora16 mingw32-gcc.
|
||||
# Fix ACX_MALLOC for redefined malloc error.
|
||||
# Fix GETADDRINFO_WITH_INCLUDES to add -lws2_32
|
||||
# 2011-11-10 Fix FLTO test to not drop a.out in current directory.
|
||||
# 2011-11-01 Fix FLTO test for llvm on Lion.
|
||||
# 2011-08-01 Fix nonblock test (broken at v13).
|
||||
# 2011-08-01 Fix autoconf 2.68 warnings
|
||||
# 2011-06-23 Add ACX_CHECK_FLTO to check -flto.
|
||||
@@ -254,6 +261,8 @@ int test() {
|
||||
a = getopt(2, opts, "a");
|
||||
a = isascii(32);
|
||||
str = gai_strerror(0);
|
||||
if(str && t && tv.tv_usec && msg.msg_control)
|
||||
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"])
|
||||
@@ -289,6 +298,8 @@ int test() {
|
||||
a = getopt(2, opts, "a");
|
||||
a = isascii(32);
|
||||
str = gai_strerror(0);
|
||||
if(str && t && tv.tv_usec && msg.msg_control)
|
||||
a = 0;
|
||||
return a;
|
||||
}
|
||||
], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE"])
|
||||
@@ -355,6 +366,8 @@ int test() {
|
||||
const char* str = NULL;
|
||||
t = ctime_r(&time, buf);
|
||||
str = gai_strerror(0);
|
||||
if(t && str)
|
||||
a = 0;
|
||||
return a;
|
||||
}
|
||||
], [CFLAGS="$CFLAGS -D_POSIX_C_SOURCE=200112"])
|
||||
@@ -381,6 +394,8 @@ int test() {
|
||||
srandom(32);
|
||||
a = getopt(2, opts, "a");
|
||||
a = isascii(32);
|
||||
if(tv.tv_usec)
|
||||
a = 0;
|
||||
return a;
|
||||
}
|
||||
], [CFLAGS="$CFLAGS -D__EXTENSIONS__"])
|
||||
@@ -394,7 +409,15 @@ AC_DEFUN([ACX_CHECK_FLTO],
|
||||
[AC_MSG_CHECKING([if $CC supports -flto])
|
||||
BAKCFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -flto"
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], [AC_MSG_RESULT(yes)], [CFLAGS="$BAKCFLAGS" ; AC_MSG_RESULT(no)])
|
||||
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
|
||||
CFLAGS="$BAKCFLAGS"
|
||||
AC_MSG_RESULT(no)
|
||||
else
|
||||
AC_MSG_RESULT(yes)
|
||||
fi
|
||||
rm -f conftest conftest.c conftest.o
|
||||
], [CFLAGS="$BAKCFLAGS" ; AC_MSG_RESULT(no)])
|
||||
])
|
||||
|
||||
dnl Check the printf-format attribute (if any)
|
||||
@@ -784,7 +807,14 @@ int main() {
|
||||
}
|
||||
]])],
|
||||
dnl this case on linux, solaris, bsd
|
||||
[ac_cv_func_getaddrinfo="yes"],
|
||||
[ac_cv_func_getaddrinfo="yes"
|
||||
dnl see if on windows
|
||||
if test "$ac_cv_header_windows_h" = "yes"; then
|
||||
AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
|
||||
USE_WINSOCK="1"
|
||||
LIBS="$LIBS -lws2_32"
|
||||
fi
|
||||
],
|
||||
dnl no quick getaddrinfo, try mingw32 and winsock2 library.
|
||||
ORIGLIBS="$LIBS"
|
||||
LIBS="$LIBS -lws2_32"
|
||||
@@ -1040,10 +1070,23 @@ dnl detect malloc and provide malloc compat prototype.
|
||||
dnl $1: unique name for compat code
|
||||
AC_DEFUN([ACX_FUNC_MALLOC],
|
||||
[
|
||||
AC_FUNC_MALLOC
|
||||
if test "$ac_cv_func_malloc_0_nonnull" = no; then
|
||||
AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])
|
||||
fi
|
||||
AC_MSG_CHECKING([for GNU libc compatible malloc])
|
||||
AC_RUN_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#if defined STDC_HEADERS || defined HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
char *malloc ();
|
||||
#endif
|
||||
]], [ if(malloc(0) != 0) return 1;])
|
||||
],
|
||||
[AC_MSG_RESULT([no])
|
||||
AC_LIBOBJ(malloc)
|
||||
AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])] ,
|
||||
[AC_MSG_RESULT([yes])
|
||||
AC_DEFINE([HAVE_MALLOC], 1, [If have GNU libc compatible malloc])],
|
||||
[AC_MSG_RESULT([no (crosscompile)])
|
||||
AC_LIBOBJ(malloc)
|
||||
AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])] )
|
||||
])
|
||||
|
||||
dnl Define fallback for fseeko and ftello if needed.
|
||||
@@ -1284,9 +1327,7 @@ int main(void)
|
||||
dnl define memcmp to its replacement, pass unique id for program as arg
|
||||
AC_DEFUN([AHX_MEMCMP_BROKEN], [
|
||||
#ifdef MEMCMP_IS_BROKEN
|
||||
# ifdef memcmp
|
||||
# undef memcmp
|
||||
# endif
|
||||
#include "compat/memcmp.h"
|
||||
#define memcmp memcmp_$1
|
||||
int memcmp(const void *x, const void *y, size_t n);
|
||||
#endif
|
||||
|
||||
+5
-2
@@ -164,8 +164,11 @@ $ac_distutils_result])
|
||||
AC_MSG_CHECKING([consistency of all components of python development environment])
|
||||
AC_LANG_PUSH([C])
|
||||
# save current global flags
|
||||
LIBS="$ac_save_LIBS $PYTHON_LDFLAGS"
|
||||
CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS"
|
||||
ac_save_LIBS="$LIBS"
|
||||
ac_save_CPPFLAGS="$CPPFLAGS"
|
||||
|
||||
LIBS="$LIBS $PYTHON_LDFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS"
|
||||
AC_TRY_LINK([
|
||||
#include <Python.h>
|
||||
],[
|
||||
|
||||
@@ -135,7 +135,9 @@ inet_ntop6(const u_char *src, char *dst, size_t size)
|
||||
for (i = 0; i < IN6ADDRSZ; i++)
|
||||
words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
|
||||
best.base = -1;
|
||||
best.len = 0;
|
||||
cur.base = -1;
|
||||
cur.len = 0;
|
||||
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
|
||||
if (words[i] == 0) {
|
||||
if (cur.base == -1)
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* memcmp.h: undef memcmp for compat.
|
||||
*
|
||||
* Copyright (c) 2012, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* See LICENSE for the license.
|
||||
*/
|
||||
#ifndef COMPAT_MEMCMP_H
|
||||
#define COMPAT_MEMCMP_H
|
||||
|
||||
#ifdef memcmp
|
||||
/* undef here otherwise autoheader messes it up in config.h */
|
||||
# undef memcmp
|
||||
#endif
|
||||
|
||||
#endif /* COMPAT_MEMCMP_H */
|
||||
+1
-3
@@ -106,12 +106,10 @@ str2int(const char **buf, int max)
|
||||
char *
|
||||
unbound_strptime(const char *s, const char *format, struct tm *tm)
|
||||
{
|
||||
int c, alt_format, ret;
|
||||
int c, ret;
|
||||
int split_year = 0;
|
||||
|
||||
while ((c = *format) != '\0') {
|
||||
alt_format = 0;
|
||||
|
||||
/* whitespace, literal or format */
|
||||
if (isspace(c)) { /* whitespace */
|
||||
/** whitespace matches zero or more whitespace characters in the
|
||||
|
||||
+30
-5
@@ -25,6 +25,11 @@
|
||||
/* Define if you want to use debug lock checking (slow). */
|
||||
#undef ENABLE_LOCK_CHECKS
|
||||
|
||||
/* Define this if you enabled-allsymbols from libunbound to link binaries to
|
||||
it for smaller install size, but the libunbound export table is polluted by
|
||||
internal symbols */
|
||||
#undef EXPORT_ALL_SYMBOLS
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#undef HAVE_ARPA_INET_H
|
||||
|
||||
@@ -46,6 +51,14 @@
|
||||
/* Define to 1 if you have the `daemon' function. */
|
||||
#undef HAVE_DAEMON
|
||||
|
||||
/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_NID_SECP384R1
|
||||
|
||||
/* Define to 1 if you have the declaration of `NID_X9_62_prime256v1', and to 0
|
||||
if you don't. */
|
||||
#undef HAVE_DECL_NID_X9_62_PRIME256V1
|
||||
|
||||
/* Define to 1 if you have the declaration of `sk_SSL_COMP_pop_free', and to 0
|
||||
if you don't. */
|
||||
#undef HAVE_DECL_SK_SSL_COMP_POP_FREE
|
||||
@@ -93,6 +106,9 @@
|
||||
/* Define to 1 if you have the `fcntl' function. */
|
||||
#undef HAVE_FCNTL
|
||||
|
||||
/* Define to 1 if you have the `FIPS_mode' function. */
|
||||
#undef HAVE_FIPS_MODE
|
||||
|
||||
/* Define to 1 if you have the `fork' function. */
|
||||
#undef HAVE_FORK
|
||||
|
||||
@@ -165,8 +181,7 @@
|
||||
/* Define to 1 if you have the <login_cap.h> header file. */
|
||||
#undef HAVE_LOGIN_CAP_H
|
||||
|
||||
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
|
||||
to 0 otherwise. */
|
||||
/* If have GNU libc compatible malloc */
|
||||
#undef HAVE_MALLOC
|
||||
|
||||
/* Define to 1 if you have the `memmove' function. */
|
||||
@@ -181,6 +196,9 @@
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#undef HAVE_NETINET_IN_H
|
||||
|
||||
/* Use libnss for crypto */
|
||||
#undef HAVE_NSS
|
||||
|
||||
/* Define to 1 if you have the `OPENSSL_config' function. */
|
||||
#undef HAVE_OPENSSL_CONFIG
|
||||
|
||||
@@ -295,6 +313,9 @@
|
||||
/* Define to 1 if you have the `strptime' function. */
|
||||
#undef HAVE_STRPTIME
|
||||
|
||||
/* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */
|
||||
#undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST
|
||||
|
||||
/* Define if you have Swig libraries and header files. */
|
||||
#undef HAVE_SWIG
|
||||
|
||||
@@ -475,6 +496,12 @@
|
||||
/* define this to enable debug checks. */
|
||||
#undef UNBOUND_DEBUG
|
||||
|
||||
/* Define this to enable ECDSA support. */
|
||||
#undef USE_ECDSA
|
||||
|
||||
/* Define this to enable an EVP workaround for older openssl */
|
||||
#undef USE_ECDSA_EVP_WORKAROUND
|
||||
|
||||
/* Define this to enable GOST support. */
|
||||
#undef USE_GOST
|
||||
|
||||
@@ -807,9 +834,7 @@ struct tm *gmtime_r(const time_t *timep, struct tm *result);
|
||||
|
||||
|
||||
#ifdef MEMCMP_IS_BROKEN
|
||||
# ifdef memcmp
|
||||
# undef memcmp
|
||||
# endif
|
||||
#include "compat/memcmp.h"
|
||||
#define memcmp memcmp_unbound
|
||||
int memcmp(const void *x, const void *y, size_t n);
|
||||
#endif
|
||||
|
||||
+390
-67
@@ -6,11 +6,11 @@ sinclude(acx_pthread.m4)
|
||||
sinclude(acx_python.m4)
|
||||
sinclude(ac_pkg_swig.m4)
|
||||
|
||||
AC_INIT(unbound, 1.4.13, unbound-bugs@nlnetlabs.nl, unbound)
|
||||
AC_INIT(unbound, 1.4.18, unbound-bugs@nlnetlabs.nl, unbound)
|
||||
|
||||
LIBUNBOUND_CURRENT=2
|
||||
LIBUNBOUND_REVISION=13
|
||||
LIBUNBOUND_AGE=0
|
||||
LIBUNBOUND_CURRENT=3
|
||||
LIBUNBOUND_REVISION=3
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
# 1.0.2 had 0:14:0
|
||||
@@ -38,6 +38,12 @@ LIBUNBOUND_AGE=0
|
||||
# 1.4.11 had 2:11:0
|
||||
# 1.4.12 had 2:12:0
|
||||
# 1.4.13 had 2:13:0
|
||||
# and 1.4.13p1 and 1.4.13.p2
|
||||
# 1.4.14 had 2:14:0
|
||||
# 1.4.15 had 3:0:1 # adds ub_version()
|
||||
# 1.4.16 had 3:1:1
|
||||
# 1.4.17 had 3:2:1
|
||||
# 1.4.18 had 3:3:1
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -135,7 +141,7 @@ else
|
||||
fi
|
||||
)
|
||||
AC_SUBST(UNBOUND_CHROOT_DIR)
|
||||
ACX_ESCAPE_BACKSLASH($UNBOUND_CHOOT_DIR, hdr_chroot)
|
||||
ACX_ESCAPE_BACKSLASH($UNBOUND_CHROOT_DIR, hdr_chroot)
|
||||
AC_DEFINE_UNQUOTED(CHROOT_DIR, ["$hdr_chroot"], [Directory to chroot to])
|
||||
|
||||
AC_ARG_WITH(share-dir,
|
||||
@@ -203,8 +209,11 @@ AC_DEFINE_UNQUOTED(RSRC_PACKAGE_VERSION, [$wnvs], [version number for resource f
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
AC_LANG_C
|
||||
# allow user to override the -g -O2 flags.
|
||||
if test "x$CFLAGS" = "x" ; then
|
||||
ACX_CHECK_COMPILER_FLAG(g, [CFLAGS="$CFLAGS -g"])
|
||||
ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"])
|
||||
fi
|
||||
AC_PROG_CC
|
||||
ACX_DEPFLAG
|
||||
ACX_DETERMINE_EXT_FLAGS_UNBOUND
|
||||
@@ -285,6 +294,31 @@ AC_SUBST(RUNTIME_PATH)
|
||||
AC_SEARCH_LIBS([inet_pton], [nsl])
|
||||
AC_SEARCH_LIBS([socket], [socket])
|
||||
|
||||
# check wether strptime also works
|
||||
AC_DEFUN([AC_CHECK_STRPTIME_WORKS],
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
AC_MSG_CHECKING(whether strptime works)
|
||||
if test c${cross_compiling} = cno; then
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#define _XOPEN_SOURCE
|
||||
#include <time.h>
|
||||
int main(void) { struct tm tm; char *res;
|
||||
res = strptime("2010-07-15T00:00:00+00:00", "%t%Y%t-%t%m%t-%t%d%tT%t%H%t:%t%M%t:%t%S%t", &tm);
|
||||
if (!res) return 2;
|
||||
res = strptime("20070207111842", "%Y%m%d%H%M%S", &tm);
|
||||
if (!res) return 1; return 0; }
|
||||
]])] , [eval "ac_cv_c_strptime_works=yes"], [eval "ac_cv_c_strptime_works=no"])
|
||||
else
|
||||
eval "ac_cv_c_strptime_works=maybe"
|
||||
fi
|
||||
AC_MSG_RESULT($ac_cv_c_strptime_works)
|
||||
if test $ac_cv_c_strptime_works = no; then
|
||||
AC_LIBOBJ(strptime)
|
||||
else
|
||||
AC_DEFINE_UNQUOTED([STRPTIME_WORKS], 1, [use default strptime.])
|
||||
fi
|
||||
])dnl
|
||||
|
||||
# check some functions of the OS before linking libs (while still runnable).
|
||||
AC_FUNC_CHOWN
|
||||
AC_FUNC_FORK
|
||||
@@ -293,6 +327,30 @@ AC_FUNC_FSEEKO
|
||||
ACX_SYS_LARGEFILE
|
||||
ACX_CHECK_NONBLOCKING_BROKEN
|
||||
ACX_MKDIR_ONE_ARG
|
||||
AC_CHECK_FUNCS([strptime],[AC_CHECK_STRPTIME_WORKS],[AC_LIBOBJ([strptime])])
|
||||
|
||||
# set memory allocation checking if requested
|
||||
AC_ARG_ENABLE(alloc-checks, AC_HELP_STRING([--enable-alloc-checks],
|
||||
[ enable to memory allocation statistics, for debug purposes ]),
|
||||
, )
|
||||
AC_ARG_ENABLE(alloc-lite, AC_HELP_STRING([--enable-alloc-lite],
|
||||
[ enable for lightweight alloc assertions, for debug purposes ]),
|
||||
, )
|
||||
AC_ARG_ENABLE(alloc-nonregional, AC_HELP_STRING([--enable-alloc-nonregional],
|
||||
[ enable nonregional allocs, slow but exposes regional allocations to other memory purifiers, for debug purposes ]),
|
||||
, )
|
||||
if test x_$enable_alloc_nonregional = x_yes; then
|
||||
AC_DEFINE(UNBOUND_ALLOC_NONREGIONAL, 1, [use malloc not regions, for debug use])
|
||||
fi
|
||||
if test x_$enable_alloc_checks = x_yes; then
|
||||
AC_DEFINE(UNBOUND_ALLOC_STATS, 1, [use statistics for allocs and frees, for debug use])
|
||||
else
|
||||
if test x_$enable_alloc_lite = x_yes; then
|
||||
AC_DEFINE(UNBOUND_ALLOC_LITE, 1, [use to enable lightweight alloc assertions, for debug use])
|
||||
else
|
||||
ACX_FUNC_MALLOC([unbound])
|
||||
fi
|
||||
fi
|
||||
|
||||
# check windows threads (we use them, not pthreads, on windows).
|
||||
if test "$on_mingw" = "yes"; then
|
||||
@@ -417,6 +475,14 @@ if test x_$ub_test_python != x_no; then
|
||||
AC_DEFINE(WITH_PYTHONMODULE, 1, [Define if you want Python module.])
|
||||
WITH_PYTHONMODULE=yes
|
||||
AC_SUBST(WITH_PYTHONMODULE)
|
||||
PYTHONMOD_OBJ="pythonmod.lo pythonmod_utils.lo"
|
||||
AC_SUBST(PYTHONMOD_OBJ)
|
||||
PYTHONMOD_HEADER='$(srcdir)/pythonmod/pythonmod.h'
|
||||
AC_SUBST(PYTHONMOD_HEADER)
|
||||
PYTHONMOD_INSTALL=pythonmod-install
|
||||
AC_SUBST(PYTHONMOD_INSTALL)
|
||||
PYTHONMOD_UNINSTALL=pythonmod-uninstall
|
||||
AC_SUBST(PYTHONMOD_UNINSTALL)
|
||||
fi
|
||||
|
||||
# Declare PyUnbound
|
||||
@@ -424,6 +490,14 @@ if test x_$ub_test_python != x_no; then
|
||||
AC_DEFINE(WITH_PYUNBOUND, 1, [Define if you want PyUnbound.])
|
||||
WITH_PYUNBOUND=yes
|
||||
AC_SUBST(WITH_PYUNBOUND)
|
||||
PYUNBOUND_OBJ="libunbound_wrap.lo"
|
||||
AC_SUBST(PYUNBOUND_OBJ)
|
||||
PYUNBOUND_TARGET="_unbound.la"
|
||||
AC_SUBST(PYUNBOUND_TARGET)
|
||||
PYUNBOUND_INSTALL=pyunbound-install
|
||||
AC_SUBST(PYUNBOUND_INSTALL)
|
||||
PYUNBOUND_UNINSTALL=pyunbound-uninstall
|
||||
AC_SUBST(PYUNBOUND_UNINSTALL)
|
||||
fi
|
||||
fi
|
||||
else
|
||||
@@ -433,12 +507,41 @@ if test x_$ub_test_python != x_no; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "`uname`" = "NetBSD"; then
|
||||
NETBSD_LINTFLAGS='"-D__RENAME(x)=" -D_NETINET_IN_H_'
|
||||
AC_SUBST(NETBSD_LINTFLAGS)
|
||||
fi
|
||||
CONFIG_DATE=`date +%Y%m%d`
|
||||
AC_SUBST(CONFIG_DATE)
|
||||
|
||||
# Checks for libraries.
|
||||
|
||||
# libnss
|
||||
USE_NSS="no"
|
||||
AC_ARG_WITH([nss], AC_HELP_STRING([--with-nss=path],
|
||||
[use libnss instead of openssl, installed at path.]),
|
||||
[
|
||||
USE_NSS="yes"
|
||||
AC_DEFINE(HAVE_NSS, 1, [Use libnss for crypto])
|
||||
if test "$withval" != "/usr" -a "$withval" != "" -a "$withval" != "yes"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$withval/include"
|
||||
LDFLAGS="$LDFLAGS -L$withval/lib"
|
||||
ACX_RUNTIME_PATH_ADD([$withval/lib])
|
||||
CPPFLAGS="-I$withval/include/nspr4 $CPPFLAGS"
|
||||
else
|
||||
CPPFLAGS="-I/usr/include/nspr4 $CPPFLAGS"
|
||||
fi
|
||||
LIBS="$LIBS -lnss3 -lnspr4"
|
||||
]
|
||||
)
|
||||
|
||||
# openssl
|
||||
if test $USE_NSS = "no"; then
|
||||
ACX_WITH_SSL
|
||||
ACX_LIB_SSL
|
||||
AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode])
|
||||
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free], [], [], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
@@ -459,6 +562,8 @@ AC_INCLUDES_DEFAULT
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/evp.h>
|
||||
])
|
||||
fi
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sha2, AC_HELP_STRING([--disable-sha2], [Disable SHA256 and SHA512 RRSIG support]))
|
||||
case "$enable_sha2" in
|
||||
@@ -469,18 +574,148 @@ case "$enable_sha2" in
|
||||
;;
|
||||
esac
|
||||
|
||||
# check wether gost also works
|
||||
AC_DEFUN([AC_CHECK_GOST_WORKS],
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
AC_MSG_CHECKING([if GOST works])
|
||||
if test c${cross_compiling} = cno; then
|
||||
BAKCFLAGS="$CFLAGS"
|
||||
if test -n "$ssldir"; then
|
||||
CFLAGS="$CFLAGS -Wl,-rpath,$ssldir/lib"
|
||||
fi
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <string.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/conf.h>
|
||||
/* routine to load gost from ldns */
|
||||
int load_gost_id(void)
|
||||
{
|
||||
static int gost_id = 0;
|
||||
const EVP_PKEY_ASN1_METHOD* meth;
|
||||
ENGINE* e;
|
||||
|
||||
if(gost_id) return gost_id;
|
||||
|
||||
/* see if configuration loaded gost implementation from other engine*/
|
||||
meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
|
||||
if(meth) {
|
||||
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
|
||||
return gost_id;
|
||||
}
|
||||
|
||||
/* see if engine can be loaded already */
|
||||
e = ENGINE_by_id("gost");
|
||||
if(!e) {
|
||||
/* load it ourself, in case statically linked */
|
||||
ENGINE_load_builtin_engines();
|
||||
ENGINE_load_dynamic();
|
||||
e = ENGINE_by_id("gost");
|
||||
}
|
||||
if(!e) {
|
||||
/* no gost engine in openssl */
|
||||
return 0;
|
||||
}
|
||||
if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
|
||||
ENGINE_finish(e);
|
||||
ENGINE_free(e);
|
||||
return 0;
|
||||
}
|
||||
|
||||
meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
|
||||
if(!meth) {
|
||||
/* algo not found */
|
||||
ENGINE_finish(e);
|
||||
ENGINE_free(e);
|
||||
return 0;
|
||||
}
|
||||
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
|
||||
return gost_id;
|
||||
}
|
||||
int main(void) {
|
||||
EVP_MD_CTX* ctx;
|
||||
const EVP_MD* md;
|
||||
unsigned char digest[64]; /* its a 256-bit digest, so uses 32 bytes */
|
||||
const char* str = "Hello world";
|
||||
const unsigned char check[] = {
|
||||
0x40 , 0xed , 0xf8 , 0x56 , 0x5a , 0xc5 , 0x36 , 0xe1 ,
|
||||
0x33 , 0x7c , 0x7e , 0x87 , 0x62 , 0x1c , 0x42 , 0xe0 ,
|
||||
0x17 , 0x1b , 0x5e , 0xce , 0xa8 , 0x46 , 0x65 , 0x4d ,
|
||||
0x8d , 0x3e , 0x22 , 0x9b , 0xe1 , 0x30 , 0x19 , 0x9d
|
||||
};
|
||||
OPENSSL_config(NULL);
|
||||
(void)load_gost_id();
|
||||
md = EVP_get_digestbyname("md_gost94");
|
||||
if(!md) return 1;
|
||||
memset(digest, 0, sizeof(digest));
|
||||
ctx = EVP_MD_CTX_create();
|
||||
if(!ctx) return 2;
|
||||
if(!EVP_DigestInit_ex(ctx, md, NULL)) return 3;
|
||||
if(!EVP_DigestUpdate(ctx, str, 10)) return 4;
|
||||
if(!EVP_DigestFinal_ex(ctx, digest, NULL)) return 5;
|
||||
/* uncomment to see the hash calculated.
|
||||
{int i;
|
||||
for(i=0; i<32; i++)
|
||||
printf(" %2.2x", (int)digest[i]);
|
||||
printf("\n");}
|
||||
*/
|
||||
if(memcmp(digest, check, sizeof(check)) != 0)
|
||||
return 6;
|
||||
return 0;
|
||||
}
|
||||
]])] , [eval "ac_cv_c_gost_works=yes"], [eval "ac_cv_c_gost_works=no"])
|
||||
CFLAGS="$BAKCFLAGS"
|
||||
else
|
||||
eval "ac_cv_c_gost_works=maybe"
|
||||
fi
|
||||
AC_MSG_RESULT($ac_cv_c_gost_works)
|
||||
])dnl
|
||||
|
||||
AC_ARG_ENABLE(gost, AC_HELP_STRING([--disable-gost], [Disable GOST support]))
|
||||
use_gost="no"
|
||||
if test $USE_NSS = "no"; then
|
||||
case "$enable_gost" in
|
||||
no)
|
||||
;;
|
||||
*)
|
||||
AC_CHECK_FUNC(EVP_PKEY_set_type_str, [:],[AC_MSG_ERROR([OpenSSL 1.0.0 is needed for GOST support])])
|
||||
AC_CHECK_FUNC(EC_KEY_new, [], [AC_MSG_ERROR([OpenSSL does not support ECC, needed for GOST support])])
|
||||
use_gost="yes"
|
||||
AC_DEFINE([USE_GOST], [1], [Define this to enable GOST support.])
|
||||
AC_CHECK_FUNC(EC_KEY_new, [], [AC_MSG_ERROR([OpenSSL does not support ECC, needed for GOST support])])
|
||||
AC_CHECK_GOST_WORKS
|
||||
if test "$ac_cv_c_gost_works" != no; then
|
||||
use_gost="yes"
|
||||
AC_DEFINE([USE_GOST], [1], [Define this to enable GOST support.])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi dnl !USE_NSS
|
||||
|
||||
AC_ARG_ENABLE(ecdsa, AC_HELP_STRING([--disable-ecdsa], [Disable ECDSA support]))
|
||||
use_ecdsa="no"
|
||||
case "$enable_ecdsa" in
|
||||
no)
|
||||
;;
|
||||
*)
|
||||
if test $USE_NSS = "no"; then
|
||||
AC_CHECK_FUNC(ECDSA_sign, [], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])])
|
||||
AC_CHECK_FUNC(SHA384_Init, [], [AC_MSG_ERROR([OpenSSL does not support SHA384: please upgrade or rerun with --disable-ecdsa])])
|
||||
AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [], [AC_MSG_ERROR([OpenSSL does not support the ECDSA curves: please upgrade or rerun with --disable-ecdsa])], [AC_INCLUDES_DEFAULT
|
||||
#include <openssl/evp.h>
|
||||
])
|
||||
# see if OPENSSL 1.0.0 or later (has EVP MD and Verify independency)
|
||||
AC_MSG_CHECKING([if openssl supports SHA2 and ECDSA with EVP])
|
||||
if grep OPENSSL_VERSION_NUMBER $ssldir/include/openssl/opensslv.h | grep 0x0 >/dev/null; then
|
||||
AC_MSG_RESULT([no])
|
||||
AC_DEFINE_UNQUOTED([USE_ECDSA_EVP_WORKAROUND], [1], [Define this to enable an EVP workaround for older openssl])
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
fi
|
||||
# we now know we have ECDSA and the required curves.
|
||||
AC_DEFINE_UNQUOTED([USE_ECDSA], [1], [Define this to enable ECDSA support.])
|
||||
use_ecdsa="yes"
|
||||
;;
|
||||
esac
|
||||
|
||||
# check for libevent
|
||||
AC_ARG_WITH(libevent, AC_HELP_STRING([--with-libevent=pathname],
|
||||
@@ -606,43 +841,34 @@ AC_ARG_ENABLE(lock_checks, AC_HELP_STRING([--enable-lock-checks],
|
||||
, )
|
||||
if test x_$enable_lock_checks = x_yes; then
|
||||
AC_DEFINE(ENABLE_LOCK_CHECKS, 1, [Define if you want to use debug lock checking (slow).])
|
||||
CHECKLOCK_SRC="testcode/checklocks.c"
|
||||
AC_SUBST(CHECKLOCK_SRC)
|
||||
fi
|
||||
|
||||
# set memory allocation checking if requested
|
||||
AC_ARG_ENABLE(alloc-checks, AC_HELP_STRING([--enable-alloc-checks],
|
||||
[ enable to memory allocation statistics, for debug purposes ]),
|
||||
, )
|
||||
AC_ARG_ENABLE(alloc-lite, AC_HELP_STRING([--enable-alloc-lite],
|
||||
[ enable for lightweight alloc assertions, for debug purposes ]),
|
||||
, )
|
||||
AC_ARG_ENABLE(alloc-nonregional, AC_HELP_STRING([--enable-alloc-nonregional],
|
||||
[ enable nonregional allocs, slow but exposes regional allocations to other memory purifiers, for debug purposes ]),
|
||||
, )
|
||||
if test x_$enable_alloc_nonregional = x_yes; then
|
||||
AC_DEFINE(UNBOUND_ALLOC_NONREGIONAL, 1, [use malloc not regions, for debug use])
|
||||
fi
|
||||
if test x_$enable_alloc_checks = x_yes; then
|
||||
AC_DEFINE(UNBOUND_ALLOC_STATS, 1, [use statistics for allocs and frees, for debug use])
|
||||
else
|
||||
if test x_$enable_alloc_lite = x_yes; then
|
||||
AC_DEFINE(UNBOUND_ALLOC_LITE, 1, [use to enable lightweight alloc assertions, for debug use])
|
||||
else
|
||||
ACX_FUNC_MALLOC([unbound])
|
||||
fi
|
||||
CHECKLOCK_OBJ="checklocks.lo"
|
||||
AC_SUBST(CHECKLOCK_OBJ)
|
||||
fi
|
||||
|
||||
ACX_CHECK_GETADDRINFO_WITH_INCLUDES
|
||||
if test "$USE_WINSOCK" = 1; then
|
||||
AC_DEFINE(UB_ON_WINDOWS, 1, [Use win32 resources and API])
|
||||
UB_ON_WINDOWS=yes
|
||||
AC_SUBST(UB_ON_WINDOWS)
|
||||
AC_CHECK_HEADERS([iphlpapi.h],,, [AC_INCLUDES_DEFAULT
|
||||
#include <windows.h>
|
||||
])
|
||||
AC_CHECK_TOOL(WINDRES, windres)
|
||||
LIBS="$LIBS -liphlpapi"
|
||||
WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe"
|
||||
AC_SUBST(WINAPPS)
|
||||
WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c"
|
||||
AC_SUBST(WIN_DAEMON_SRC)
|
||||
WIN_DAEMON_OBJ="win_svc.lo w_inst.lo"
|
||||
AC_SUBST(WIN_DAEMON_OBJ)
|
||||
WIN_DAEMON_OBJ_LINK="rsrc_unbound.o"
|
||||
AC_SUBST(WIN_DAEMON_OBJ_LINK)
|
||||
WIN_HOST_OBJ_LINK="rsrc_unbound_host.o"
|
||||
AC_SUBST(WIN_HOST_OBJ_LINK)
|
||||
WIN_UBANCHOR_OBJ_LINK="rsrc_unbound_anchor.o log.lo locks.lo"
|
||||
AC_SUBST(WIN_UBANCHOR_OBJ_LINK)
|
||||
WIN_CONTROL_OBJ_LINK="rsrc_unbound_control.o"
|
||||
AC_SUBST(WIN_CONTROL_OBJ_LINK)
|
||||
WIN_CHECKCONF_OBJ_LINK="rsrc_unbound_checkconf.o"
|
||||
AC_SUBST(WIN_CHECKCONF_OBJ_LINK)
|
||||
fi
|
||||
if test $ac_cv_func_getaddrinfo = no; then
|
||||
AC_LIBOBJ([fake-rfc2553])
|
||||
@@ -658,29 +884,36 @@ if test $ac_cv_func_daemon = yes; then
|
||||
])
|
||||
fi
|
||||
|
||||
# check wether strptime also works
|
||||
AC_DEFUN([AC_CHECK_STRPTIME_WORKS],
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
AC_MSG_CHECKING(whether strptime works)
|
||||
if test c${cross_compiling} = cno; then
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#define _XOPEN_SOURCE
|
||||
#include <time.h>
|
||||
int main(void) { struct tm tm; char *res;
|
||||
res = strptime("20070207111842", "%Y%m%d%H%M%S", &tm);
|
||||
if (!res) return 1; return 0; }
|
||||
]])] , [eval "ac_cv_c_strptime_works=yes"], [eval "ac_cv_c_strptime_works=no"])
|
||||
else
|
||||
eval "ac_cv_c_strptime_works=maybe"
|
||||
fi
|
||||
AC_MSG_RESULT($ac_cv_c_strptime_works)
|
||||
if test $ac_cv_c_strptime_works = no; then
|
||||
AC_LIBOBJ(strptime)
|
||||
else
|
||||
AC_DEFINE_UNQUOTED([STRPTIME_WORKS], 1, [use default strptime.])
|
||||
fi
|
||||
])dnl
|
||||
AC_CHECK_FUNCS([strptime],[AC_CHECK_STRPTIME_WORKS],[AC_LIBOBJ([strptime])])
|
||||
AC_CHECK_MEMBERS([struct in_pktinfo.ipi_spec_dst],,,[
|
||||
AC_INCLUDES_DEFAULT
|
||||
#if HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_UIO_H
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
])
|
||||
AC_SEARCH_LIBS([setusercontext], [util])
|
||||
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam getrlimit setrlimit setsid sbrk chroot kill sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex])
|
||||
AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])])
|
||||
@@ -697,18 +930,87 @@ AC_REPLACE_FUNCS(snprintf)
|
||||
AC_REPLACE_FUNCS(strlcpy)
|
||||
AC_REPLACE_FUNCS(memmove)
|
||||
AC_REPLACE_FUNCS(gmtime_r)
|
||||
LIBOBJ_WITHOUT_CTIME="$LIBOBJS"
|
||||
AC_SUBST(LIBOBJ_WITHOUT_CTIME)
|
||||
AC_REPLACE_FUNCS(ctime_r)
|
||||
|
||||
AC_ARG_ENABLE(allsymbols, AC_HELP_STRING([--enable-allsymbols], [export all symbols from libunbound and link binaries to it, smaller install size but libunbound export table is polluted by internal symbols]))
|
||||
case "$enable_allsymbols" in
|
||||
no)
|
||||
EXPORT_ALL_SYMBOLS=no
|
||||
;;
|
||||
yes)
|
||||
EXPORT_ALL_SYMBOLS=yes
|
||||
COMMON_OBJ_ALL_SYMBOLS=""
|
||||
UBSYMS=""
|
||||
EXTRALINK="-L. -L.libs -lunbound"
|
||||
AC_DEFINE(EXPORT_ALL_SYMBOLS, 1, [Define this if you enabled-allsymbols from libunbound to link binaries to it for smaller install size, but the libunbound export table is polluted by internal symbols])
|
||||
;;
|
||||
no|*)
|
||||
COMMON_OBJ_ALL_SYMBOLS='$(COMMON_OBJ)'
|
||||
UBSYMS='-export-symbols $(srcdir)/libunbound/ubsyms.def'
|
||||
EXTRALINK=""
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(EXPORT_ALL_SYMBOLS)
|
||||
AC_SUBST(COMMON_OBJ_ALL_SYMBOLS)
|
||||
AC_SUBST(EXTRALINK)
|
||||
AC_SUBST(UBSYMS)
|
||||
if test x_$enable_lock_checks = x_yes; then
|
||||
UBSYMS="-export-symbols clubsyms.def"
|
||||
cp ${srcdir}/libunbound/ubsyms.def clubsyms.def
|
||||
echo lock_protect >> clubsyms.def
|
||||
echo lock_unprotect >> clubsyms.def
|
||||
echo lock_get_mem >> clubsyms.def
|
||||
echo checklock_start >> clubsyms.def
|
||||
echo checklock_stop >> clubsyms.def
|
||||
echo checklock_lock >> clubsyms.def
|
||||
echo checklock_unlock >> clubsyms.def
|
||||
echo checklock_init >> clubsyms.def
|
||||
echo checklock_thrcreate >> clubsyms.def
|
||||
echo checklock_thrjoin >> clubsyms.def
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([if ${MAKE:-make} supports $< with implicit rule in scope])
|
||||
# on openBSD, the implicit rule make $< work.
|
||||
# on Solaris, it does not work ($? is changed sources, $^ lists dependencies).
|
||||
# gmake works.
|
||||
cat >conftest.make <<EOF
|
||||
all: conftest.lo
|
||||
|
||||
conftest.lo foo.lo bla.lo:
|
||||
if test -f "\$<"; then touch \$@; fi
|
||||
|
||||
.SUFFIXES: .lo
|
||||
.c.lo:
|
||||
if test -f "\$<"; then touch \$@; fi
|
||||
|
||||
conftest.lo: conftest.dir/conftest.c
|
||||
EOF
|
||||
mkdir conftest.dir
|
||||
touch conftest.dir/conftest.c
|
||||
rm -f conftest.lo conftest.c
|
||||
${MAKE:-make} -f conftest.make >/dev/null
|
||||
rm -f conftest.make conftest.c conftest.dir/conftest.c
|
||||
rm -rf conftest.dir
|
||||
if test ! -f conftest.lo; then
|
||||
AC_MSG_RESULT(no)
|
||||
SOURCEDETERMINE='echo "$^" | awk "-F " "{print \$$1;}" > .source'
|
||||
SOURCEFILE='`cat .source`'
|
||||
else
|
||||
AC_MSG_RESULT(yes)
|
||||
SOURCEDETERMINE=':'
|
||||
SOURCEFILE='$<'
|
||||
fi
|
||||
rm -f conftest.lo
|
||||
AC_SUBST(SOURCEDETERMINE)
|
||||
AC_SUBST(SOURCEFILE)
|
||||
|
||||
# see if we want to build the library or everything
|
||||
ALLTARGET="alltargets"
|
||||
AC_ARG_WITH(libunbound-only, AC_HELP_STRING([--with-libunbound-only],
|
||||
[do not build daemon and tool programs]),
|
||||
[
|
||||
if test "$withval" = "yes"; then
|
||||
ALLTARGET="lib"
|
||||
fi
|
||||
])
|
||||
AC_SUBST(ALLTARGET)
|
||||
|
||||
# check this after all other compilation checks, since the linking of the lib
|
||||
# may break checks after this.
|
||||
@@ -731,15 +1033,35 @@ AC_CHECK_LIB(ldns, ldns_rr_new,,[
|
||||
AC_MSG_ERROR([No ldns library found, install the ldns library into system lib dir or use --with-ldns=path to other location. The --with-ldns can point to the make-dir of ldns. Install the package ldns or download source http://www.nlnetlabs.nl/projects/ldns])
|
||||
])
|
||||
AC_CHECK_FUNC(ldns_buffer_copy)
|
||||
AC_CHECK_FUNC(ldns_key_buf2rsa_raw)
|
||||
if test $USE_NSS = "no"; then
|
||||
AC_CHECK_FUNC(ldns_key_buf2rsa_raw)
|
||||
else
|
||||
dnl ignore test
|
||||
ac_cv_func_ldns_key_buf2rsa_raw="yes"
|
||||
fi
|
||||
AC_CHECK_FUNC(ldns_get_random)
|
||||
AC_CHECK_FUNC(ldns_b32_ntop_extended_hex)
|
||||
if test x$use_gost = xyes; then
|
||||
if test x$use_gost = xyes -a x$USE_NSS = xno; then
|
||||
AC_CHECK_FUNC(ldns_key_EVP_load_gost_id)
|
||||
AC_CHECK_FUNCS([ldns_key_EVP_unload_gost])
|
||||
else
|
||||
dnl ignore test
|
||||
ac_cv_func_ldns_key_EVP_load_gost_id="yes"
|
||||
fi
|
||||
if test x$use_ecdsa = xyes; then
|
||||
AC_CHECK_DECL([LDNS_ECDSAP384SHA384], [], [], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
# include <ws2tcpip.h>
|
||||
#endif
|
||||
#include <ldns/ldns.h>
|
||||
])
|
||||
else
|
||||
ac_cv_have_decl_LDNS_ECDSAP384SHA384="yes"
|
||||
fi
|
||||
AC_CHECK_HEADERS([ldns/ldns.h],,[
|
||||
AC_MSG_ERROR([No ldns include file found, install the ldns library development files. Install package ldns-dev or ldns-devel or download source http://www.nlnetlabs.nl/projects/ldns])
|
||||
], [AC_INCLUDES_DEFAULT
|
||||
@@ -768,7 +1090,8 @@ if test $ac_cv_func_ldns_buffer_copy = yes \
|
||||
-a $ac_cv_func_ldns_get_random = yes \
|
||||
-a $ac_cv_header_ldns_ldns_h = yes \
|
||||
-a $ac_cv_func_ldns_b32_ntop_extended_hex = yes \
|
||||
-a $ac_cv_func_ldns_key_EVP_load_gost_id = yes; then
|
||||
-a $ac_cv_func_ldns_key_EVP_load_gost_id = yes \
|
||||
-a $ac_cv_have_decl_LDNS_ECDSAP384SHA384 = yes; then
|
||||
dnl ldns was found
|
||||
:
|
||||
else
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# plugin for munin to monitor usage of unbound servers.
|
||||
# To install copy this to /usr/local/share/munin/plugins/unbound_munin_
|
||||
# and use munin-node-configure (--suggest, --shell).
|
||||
#
|
||||
# (C) 2008 W.C.A. Wijngaards. BSD Licensed.
|
||||
#
|
||||
@@ -45,9 +47,9 @@
|
||||
# unbound_munin_histogram - histogram of query resolving times
|
||||
#
|
||||
# Magic markers - optional - used by installation scripts and
|
||||
# munin-config:
|
||||
# munin-config: (originally contrib family but munin-node-configure ignores it)
|
||||
#
|
||||
#%# family=contrib
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf suggest
|
||||
|
||||
# POD documentation
|
||||
@@ -175,7 +177,7 @@ if test "$1" = "autoconf" ; then
|
||||
exit 1
|
||||
fi
|
||||
if test ! -d `dirname $state`; then
|
||||
echo no "($state directory does not exist)"
|
||||
echo no "(`dirname $state` directory does not exist)"
|
||||
exit 1
|
||||
fi
|
||||
echo yes
|
||||
@@ -228,9 +230,8 @@ if test "$1" = "config" ; then
|
||||
echo "graph_args --base 1000 -l 0"
|
||||
echo "graph_vlabel queries / second"
|
||||
echo "graph_category DNS"
|
||||
for x in thread0.num.queries thread1.num.queries \
|
||||
thread2.num.queries thread3.num.queries thread4.num.queries \
|
||||
thread5.num.queries thread6.num.queries thread7.num.queries; do
|
||||
for x in `grep "^thread[0-9][0-9]*\.num\.queries=" $state |
|
||||
sed -e 's/=.*//'`; do
|
||||
exist_config $x "queries handled by `basename $x .num.queries`"
|
||||
done
|
||||
p_config "total.num.queries" "total queries from clients"
|
||||
@@ -421,9 +422,8 @@ print_value ( ) {
|
||||
|
||||
case $id in
|
||||
hits)
|
||||
for x in thread0.num.queries thread1.num.queries thread2.num.queries \
|
||||
thread3.num.queries thread4.num.queries thread5.num.queries \
|
||||
thread6.num.queries thread7.num.queries total.num.queries \
|
||||
for x in `grep "^thread[0-9][0-9]*\.num\.queries=" $state |
|
||||
sed -e 's/=.*//'` total.num.queries \
|
||||
total.num.cachehits total.num.prefetch num.query.tcp \
|
||||
num.query.ipv6 unwanted.queries unwanted.replies; do
|
||||
if grep "^"$x"=" $state >/dev/null 2>&1; then
|
||||
|
||||
@@ -27,7 +27,7 @@ notify_cmd="nc localhost 1234"
|
||||
# first the daemon itself, then the controller for the daemon.
|
||||
reporter_daemon() {
|
||||
trap "rm -f \"$pidfile\"" EXIT
|
||||
tail -f $logfile | grep "unbound.*info: validation failure" | \
|
||||
tail -F $logfile | grep --line-buffered "unbound.*info: validation failure" | \
|
||||
while read x; do
|
||||
echo "$x" | $notify_cmd
|
||||
done
|
||||
|
||||
+17
-18
@@ -40,15 +40,13 @@
|
||||
* to text format.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ldns/ldns.h"
|
||||
#include <ldns/ldns.h>
|
||||
#include "daemon/cachedump.h"
|
||||
#include "daemon/remote.h"
|
||||
#include "daemon/worker.h"
|
||||
#include "daemon/daemon.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/modstack.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/net_help.h"
|
||||
@@ -765,7 +763,7 @@ load_msg(SSL* ssl, ldns_buffer* buf, struct worker* worker)
|
||||
if(!go_on)
|
||||
return 1; /* skip this one, not all references satisfied */
|
||||
|
||||
if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0)) {
|
||||
if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL)) {
|
||||
log_warn("error out of memory");
|
||||
return 0;
|
||||
}
|
||||
@@ -802,7 +800,8 @@ print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp)
|
||||
{
|
||||
char buf[257];
|
||||
struct delegpt_addr* a;
|
||||
int lame, dlame, rlame, rto, edns_vs, to, delay, entry_ttl;
|
||||
int lame, dlame, rlame, rto, edns_vs, to, delay, entry_ttl,
|
||||
tA = 0, tAAAA = 0, tother = 0;
|
||||
struct rtt_info ri;
|
||||
uint8_t edns_lame_known;
|
||||
for(a = dp->target_list; a; a = a->next_target) {
|
||||
@@ -814,10 +813,14 @@ print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp)
|
||||
return;
|
||||
}
|
||||
/* lookup in infra cache */
|
||||
delay=0;
|
||||
entry_ttl = infra_get_host_rto(worker->env.infra_cache,
|
||||
&a->addr, a->addrlen, &ri, &delay, *worker->env.now);
|
||||
&a->addr, a->addrlen, dp->name, dp->namelen,
|
||||
&ri, &delay, *worker->env.now, &tA, &tAAAA, &tother);
|
||||
if(entry_ttl == -2 && ri.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
if(!ssl_printf(ssl, "expired, rto %d msec.\n", ri.rto))
|
||||
if(!ssl_printf(ssl, "expired, rto %d msec, tA %d "
|
||||
"tAAAA %d tother %d.\n", ri.rto, tA, tAAAA,
|
||||
tother))
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
@@ -838,17 +841,19 @@ print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp)
|
||||
continue; /* skip stuff not in infra cache */
|
||||
}
|
||||
if(!ssl_printf(ssl, "%s%s%s%srto %d msec, ttl %d, ping %d "
|
||||
"var %d rtt %d",
|
||||
"var %d rtt %d, tA %d, tAAAA %d, tother %d",
|
||||
lame?"LAME ":"", dlame?"NoDNSSEC ":"",
|
||||
a->lame?"AddrWasParentSide ":"",
|
||||
rlame?"NoAuthButRecursive ":"", rto, entry_ttl,
|
||||
ri.srtt, ri.rttvar, rtt_notimeout(&ri)))
|
||||
ri.srtt, ri.rttvar, rtt_notimeout(&ri),
|
||||
tA, tAAAA, tother))
|
||||
return;
|
||||
if(delay)
|
||||
if(!ssl_printf(ssl, ", probedelay %d", delay))
|
||||
return;
|
||||
if(infra_host(worker->env.infra_cache, &a->addr, a->addrlen,
|
||||
*worker->env.now, &edns_vs, &edns_lame_known, &to)) {
|
||||
dp->name, dp->namelen, *worker->env.now, &edns_vs,
|
||||
&edns_lame_known, &to)) {
|
||||
if(edns_vs == -1) {
|
||||
if(!ssl_printf(ssl, ", noEDNS%s.",
|
||||
edns_lame_known?" probed":" assumed"))
|
||||
@@ -904,19 +909,12 @@ int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
|
||||
char b[260];
|
||||
struct query_info qinfo;
|
||||
struct iter_hints_stub* stub;
|
||||
struct iter_env* ie;
|
||||
regional_free_all(region);
|
||||
qinfo.qname = nm;
|
||||
qinfo.qname_len = nmlen;
|
||||
qinfo.qtype = LDNS_RR_TYPE_A;
|
||||
qinfo.qclass = LDNS_RR_CLASS_IN;
|
||||
|
||||
if(modstack_find(&worker->daemon->mods, "iterator") == -1) {
|
||||
return ssl_printf(ssl, "error: no iterator module\n");
|
||||
}
|
||||
ie = (struct iter_env*)worker->env.modinfo[modstack_find(&worker->
|
||||
daemon->mods, "iterator")];
|
||||
|
||||
dname_str(nm, b);
|
||||
if(!ssl_printf(ssl, "The following name servers are used for lookup "
|
||||
"of %s\n", b))
|
||||
@@ -961,7 +959,8 @@ int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
stub = hints_lookup_stub(ie->hints, nm, qinfo.qclass, dp);
|
||||
stub = hints_lookup_stub(worker->env.hints, nm, qinfo.qclass,
|
||||
dp);
|
||||
if(stub) {
|
||||
if(stub->noprime) {
|
||||
if(!ssl_printf(ssl, "The noprime stub servers "
|
||||
|
||||
+35
-15
@@ -55,7 +55,12 @@
|
||||
#ifdef HAVE_OPENSSL_ENGINE_H
|
||||
#include <openssl/engine.h>
|
||||
#endif
|
||||
#include "ldns/ldns.h"
|
||||
|
||||
#ifdef HAVE_NSS
|
||||
#include <nss3/nss.h>
|
||||
#endif
|
||||
|
||||
#include <ldns/ldns.h>
|
||||
#include "daemon/daemon.h"
|
||||
#include "daemon/worker.h"
|
||||
#include "daemon/remote.h"
|
||||
@@ -63,6 +68,7 @@
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/storage/lookup3.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "services/cache/rrset.h"
|
||||
@@ -188,20 +194,25 @@ daemon_init(void)
|
||||
#endif /* USE_WINSOCK */
|
||||
signal_handling_record();
|
||||
checklock_start();
|
||||
#ifdef HAVE_SSL
|
||||
ERR_load_crypto_strings();
|
||||
ERR_load_SSL_strings();
|
||||
#ifdef HAVE_OPENSSL_CONFIG
|
||||
# ifdef HAVE_OPENSSL_CONFIG
|
||||
OPENSSL_config("unbound");
|
||||
#endif
|
||||
#ifdef USE_GOST
|
||||
# endif
|
||||
# ifdef USE_GOST
|
||||
(void)ldns_key_EVP_load_gost_id();
|
||||
#endif
|
||||
# endif
|
||||
OpenSSL_add_all_algorithms();
|
||||
#if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS
|
||||
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS
|
||||
/* grab the COMP method ptr because openssl leaks it */
|
||||
comp_meth = (void*)SSL_COMP_get_compression_methods();
|
||||
#endif
|
||||
# endif
|
||||
(void)SSL_library_init();
|
||||
#elif defined(HAVE_NSS)
|
||||
if(NSS_NoDB_Init(NULL) != SECSuccess)
|
||||
fatal_exit("could not init NSS");
|
||||
#endif /* HAVE_SSL or HAVE_NSS */
|
||||
#ifdef HAVE_TZSET
|
||||
/* init timezone info while we are not chrooted yet */
|
||||
tzset();
|
||||
@@ -320,6 +331,7 @@ daemon_create_workers(struct daemon* daemon)
|
||||
if(!daemon->rand)
|
||||
fatal_exit("could not init random generator");
|
||||
}
|
||||
hash_set_raninit((uint32_t)ub_random(daemon->rand));
|
||||
shufport = (int*)calloc(65536, sizeof(int));
|
||||
if(!shufport)
|
||||
fatal_exit("out of memory during daemon init");
|
||||
@@ -528,29 +540,37 @@ daemon_delete(struct daemon* daemon)
|
||||
free(daemon->chroot);
|
||||
free(daemon->pidfile);
|
||||
free(daemon->env);
|
||||
#ifdef HAVE_SSL
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_sslctx);
|
||||
SSL_CTX_free((SSL_CTX*)daemon->connect_sslctx);
|
||||
#endif
|
||||
free(daemon);
|
||||
#ifdef LEX_HAS_YYLEX_DESTROY
|
||||
/* lex cleanup */
|
||||
ub_c_lex_destroy();
|
||||
#endif
|
||||
/* libcrypto cleanup */
|
||||
#if defined(USE_GOST) && defined(HAVE_LDNS_KEY_EVP_UNLOAD_GOST)
|
||||
#ifdef HAVE_SSL
|
||||
# if defined(USE_GOST) && defined(HAVE_LDNS_KEY_EVP_UNLOAD_GOST)
|
||||
ldns_key_EVP_unload_gost();
|
||||
#endif
|
||||
#if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS && HAVE_DECL_SK_SSL_COMP_POP_FREE
|
||||
#ifndef S_SPLINT_S
|
||||
# endif
|
||||
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS && HAVE_DECL_SK_SSL_COMP_POP_FREE
|
||||
# ifndef S_SPLINT_S
|
||||
sk_SSL_COMP_pop_free(comp_meth, (void(*)())CRYPTO_free);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_CONFIG
|
||||
# endif
|
||||
# endif
|
||||
# ifdef HAVE_OPENSSL_CONFIG
|
||||
EVP_cleanup();
|
||||
ENGINE_cleanup();
|
||||
CONF_modules_free();
|
||||
#endif
|
||||
# endif
|
||||
CRYPTO_cleanup_all_ex_data(); /* safe, no more threads right now */
|
||||
ERR_remove_state(0);
|
||||
ERR_free_strings();
|
||||
RAND_cleanup();
|
||||
#elif defined(HAVE_NSS)
|
||||
NSS_Shutdown();
|
||||
#endif /* HAVE_SSL or HAVE_NSS */
|
||||
checklock_stop();
|
||||
#ifdef USE_WINSOCK
|
||||
if(WSACleanup() != 0) {
|
||||
|
||||
@@ -80,6 +80,8 @@ struct daemon {
|
||||
struct listen_port* rc_ports;
|
||||
/** remote control connections management (for first worker) */
|
||||
struct daemon_remote* rc;
|
||||
/** ssl context for listening to dnstcp over ssl, and connecting ssl */
|
||||
void* listen_sslctx, *connect_sslctx;
|
||||
/** num threads allocated */
|
||||
int num;
|
||||
/** the worker entries */
|
||||
|
||||
+373
-112
@@ -47,7 +47,7 @@
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include "ldns/ldns.h"
|
||||
#include <ldns/ldns.h>
|
||||
#include "daemon/remote.h"
|
||||
#include "daemon/worker.h"
|
||||
#include "daemon/daemon.h"
|
||||
@@ -68,6 +68,7 @@
|
||||
#include "validator/validator.h"
|
||||
#include "validator/val_kcache.h"
|
||||
#include "validator/val_kentry.h"
|
||||
#include "validator/val_anchor.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
@@ -92,21 +93,6 @@
|
||||
/** if true, inhibits a lot of =0 lines from the stats output */
|
||||
static const int inhibit_zero = 1;
|
||||
|
||||
/** log ssl crypto err */
|
||||
static void
|
||||
log_crypto_err(const char* str)
|
||||
{
|
||||
/* error:[error code]:[library name]:[function name]:[reason string] */
|
||||
char buf[128];
|
||||
unsigned long e;
|
||||
ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
|
||||
log_err("%s crypto %s", str, buf);
|
||||
while( (e=ERR_get_error()) ) {
|
||||
ERR_error_string_n(e, buf, sizeof(buf));
|
||||
log_err("and additionally crypto %s", buf);
|
||||
}
|
||||
}
|
||||
|
||||
/** subtract timers and the values do not overflow or become negative */
|
||||
static void
|
||||
timeval_subtract(struct timeval* d, const struct timeval* end,
|
||||
@@ -376,6 +362,22 @@ int daemon_remote_open_accept(struct daemon_remote* rc,
|
||||
return 1;
|
||||
}
|
||||
|
||||
void daemon_remote_stop_accept(struct daemon_remote* rc)
|
||||
{
|
||||
struct listen_list* p;
|
||||
for(p=rc->accept_list; p; p=p->next) {
|
||||
comm_point_stop_listening(p->com);
|
||||
}
|
||||
}
|
||||
|
||||
void daemon_remote_start_accept(struct daemon_remote* rc)
|
||||
{
|
||||
struct listen_list* p;
|
||||
for(p=rc->accept_list; p; p=p->next) {
|
||||
comm_point_start_listening(p->com, -1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
int remote_accept_callback(struct comm_point* c, void* arg, int err,
|
||||
struct comm_reply* ATTR_UNUSED(rep))
|
||||
{
|
||||
@@ -1103,33 +1105,6 @@ do_flush_stats(SSL* ssl, struct worker* worker)
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** flush infra cache */
|
||||
static void
|
||||
do_flush_infra(SSL* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t len;
|
||||
if(strcmp(arg, "all") == 0) {
|
||||
slabhash_clear(worker->env.infra_cache->hosts);
|
||||
send_ok(ssl);
|
||||
return;
|
||||
}
|
||||
if(!ipstrtoaddr(arg, UNBOUND_DNS_PORT, &addr, &len)) {
|
||||
(void)ssl_printf(ssl, "error parsing ip addr: '%s'\n", arg);
|
||||
return;
|
||||
}
|
||||
infra_remove_host(worker->env.infra_cache, &addr, len);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** flush requestlist */
|
||||
static void
|
||||
do_flush_requestlist(SSL* ssl, struct worker* worker)
|
||||
{
|
||||
mesh_delete_all(worker->env.mesh);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Local info for deletion functions
|
||||
*/
|
||||
@@ -1152,8 +1127,76 @@ struct del_info {
|
||||
size_t num_msgs;
|
||||
/** number of key entries removed */
|
||||
size_t num_keys;
|
||||
/** length of addr */
|
||||
socklen_t addrlen;
|
||||
/** socket address for host deletion */
|
||||
struct sockaddr_storage addr;
|
||||
};
|
||||
|
||||
/** callback to delete hosts in infra cache */
|
||||
static void
|
||||
infra_del_host(struct lruhash_entry* e, void* arg)
|
||||
{
|
||||
/* entry is locked */
|
||||
struct del_info* inf = (struct del_info*)arg;
|
||||
struct infra_key* k = (struct infra_key*)e->key;
|
||||
if(sockaddr_cmp(&inf->addr, inf->addrlen, &k->addr, k->addrlen) == 0) {
|
||||
struct infra_data* d = (struct infra_data*)e->data;
|
||||
d->probedelay = 0;
|
||||
d->timeout_A = 0;
|
||||
d->timeout_AAAA = 0;
|
||||
d->timeout_other = 0;
|
||||
rtt_init(&d->rtt);
|
||||
if(d->ttl >= inf->now) {
|
||||
d->ttl = inf->expired;
|
||||
inf->num_keys++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** flush infra cache */
|
||||
static void
|
||||
do_flush_infra(SSL* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t len;
|
||||
struct del_info inf;
|
||||
if(strcmp(arg, "all") == 0) {
|
||||
slabhash_clear(worker->env.infra_cache->hosts);
|
||||
send_ok(ssl);
|
||||
return;
|
||||
}
|
||||
if(!ipstrtoaddr(arg, UNBOUND_DNS_PORT, &addr, &len)) {
|
||||
(void)ssl_printf(ssl, "error parsing ip addr: '%s'\n", arg);
|
||||
return;
|
||||
}
|
||||
/* delete all entries from cache */
|
||||
/* what we do is to set them all expired */
|
||||
inf.worker = worker;
|
||||
inf.name = 0;
|
||||
inf.len = 0;
|
||||
inf.labs = 0;
|
||||
inf.now = *worker->env.now;
|
||||
inf.expired = *worker->env.now;
|
||||
inf.expired -= 3; /* handle 3 seconds skew between threads */
|
||||
inf.num_rrsets = 0;
|
||||
inf.num_msgs = 0;
|
||||
inf.num_keys = 0;
|
||||
inf.addrlen = len;
|
||||
memmove(&inf.addr, &addr, len);
|
||||
slabhash_traverse(worker->env.infra_cache->hosts, 1, &infra_del_host,
|
||||
&inf);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** flush requestlist */
|
||||
static void
|
||||
do_flush_requestlist(SSL* ssl, struct worker* worker)
|
||||
{
|
||||
mesh_delete_all(worker->env.mesh);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** callback to delete rrsets in a zone */
|
||||
static void
|
||||
zone_del_rrset(struct lruhash_entry* e, void* arg)
|
||||
@@ -1243,6 +1286,74 @@ do_flush_zone(SSL* ssl, struct worker* worker, char* arg)
|
||||
(unsigned)inf.num_msgs, (unsigned)inf.num_keys);
|
||||
}
|
||||
|
||||
/** callback to delete bogus rrsets */
|
||||
static void
|
||||
bogus_del_rrset(struct lruhash_entry* e, void* arg)
|
||||
{
|
||||
/* entry is locked */
|
||||
struct del_info* inf = (struct del_info*)arg;
|
||||
struct packed_rrset_data* d = (struct packed_rrset_data*)e->data;
|
||||
if(d->security == sec_status_bogus) {
|
||||
d->ttl = inf->expired;
|
||||
inf->num_rrsets++;
|
||||
}
|
||||
}
|
||||
|
||||
/** callback to delete bogus messages */
|
||||
static void
|
||||
bogus_del_msg(struct lruhash_entry* e, void* arg)
|
||||
{
|
||||
/* entry is locked */
|
||||
struct del_info* inf = (struct del_info*)arg;
|
||||
struct reply_info* d = (struct reply_info*)e->data;
|
||||
if(d->security == sec_status_bogus) {
|
||||
d->ttl = inf->expired;
|
||||
inf->num_msgs++;
|
||||
}
|
||||
}
|
||||
|
||||
/** callback to delete bogus keys */
|
||||
static void
|
||||
bogus_del_kcache(struct lruhash_entry* e, void* arg)
|
||||
{
|
||||
/* entry is locked */
|
||||
struct del_info* inf = (struct del_info*)arg;
|
||||
struct key_entry_data* d = (struct key_entry_data*)e->data;
|
||||
if(d->isbad) {
|
||||
d->ttl = inf->expired;
|
||||
inf->num_keys++;
|
||||
}
|
||||
}
|
||||
|
||||
/** remove all rrsets and keys from zone from cache */
|
||||
static void
|
||||
do_flush_bogus(SSL* ssl, struct worker* worker)
|
||||
{
|
||||
struct del_info inf;
|
||||
/* what we do is to set them all expired */
|
||||
inf.worker = worker;
|
||||
inf.now = *worker->env.now;
|
||||
inf.expired = *worker->env.now;
|
||||
inf.expired -= 3; /* handle 3 seconds skew between threads */
|
||||
inf.num_rrsets = 0;
|
||||
inf.num_msgs = 0;
|
||||
inf.num_keys = 0;
|
||||
slabhash_traverse(&worker->env.rrset_cache->table, 1,
|
||||
&bogus_del_rrset, &inf);
|
||||
|
||||
slabhash_traverse(worker->env.msg_cache, 1, &bogus_del_msg, &inf);
|
||||
|
||||
/* and validator cache */
|
||||
if(worker->env.key_cache) {
|
||||
slabhash_traverse(worker->env.key_cache->slab, 1,
|
||||
&bogus_del_kcache, &inf);
|
||||
}
|
||||
|
||||
(void)ssl_printf(ssl, "ok removed %u rrsets, %u messages "
|
||||
"and %u key entries\n", (unsigned)inf.num_rrsets,
|
||||
(unsigned)inf.num_msgs, (unsigned)inf.num_keys);
|
||||
}
|
||||
|
||||
/** remove name rrset from cache */
|
||||
static void
|
||||
do_flush_name(SSL* ssl, struct worker* w, char* arg)
|
||||
@@ -1316,15 +1427,15 @@ print_root_fwds(SSL* ssl, struct iter_forwards* fwds, uint8_t* root)
|
||||
|
||||
/** parse args into delegpt */
|
||||
static struct delegpt*
|
||||
parse_delegpt(SSL* ssl, struct regional* region, char* args, uint8_t* root)
|
||||
parse_delegpt(SSL* ssl, char* args, uint8_t* nm, int allow_names)
|
||||
{
|
||||
/* parse args and add in */
|
||||
char* p = args;
|
||||
char* todo;
|
||||
struct delegpt* dp = delegpt_create(region);
|
||||
struct delegpt* dp = delegpt_create_mlc(nm);
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen;
|
||||
if(!dp || !delegpt_set_name(dp, region, root)) {
|
||||
if(!dp) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
@@ -1337,14 +1448,38 @@ parse_delegpt(SSL* ssl, struct regional* region, char* args, uint8_t* root)
|
||||
}
|
||||
/* parse address */
|
||||
if(!extstrtoaddr(todo, &addr, &addrlen)) {
|
||||
(void)ssl_printf(ssl, "error cannot parse"
|
||||
" IP address '%s'\n", todo);
|
||||
return NULL;
|
||||
}
|
||||
/* add address */
|
||||
if(!delegpt_add_addr(dp, region, &addr, addrlen, 0, 0)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
return NULL;
|
||||
if(allow_names) {
|
||||
uint8_t* n = NULL;
|
||||
size_t ln;
|
||||
int lb;
|
||||
if(!parse_arg_name(ssl, todo, &n, &ln, &lb)) {
|
||||
(void)ssl_printf(ssl, "error cannot "
|
||||
"parse IP address or name "
|
||||
"'%s'\n", todo);
|
||||
delegpt_free_mlc(dp);
|
||||
return NULL;
|
||||
}
|
||||
if(!delegpt_add_ns_mlc(dp, n, 0)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
free(n);
|
||||
delegpt_free_mlc(dp);
|
||||
return NULL;
|
||||
}
|
||||
free(n);
|
||||
|
||||
} else {
|
||||
(void)ssl_printf(ssl, "error cannot parse"
|
||||
" IP address '%s'\n", todo);
|
||||
delegpt_free_mlc(dp);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
/* add address */
|
||||
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
delegpt_free_mlc(dp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp;
|
||||
@@ -1368,14 +1503,11 @@ do_forward(SSL* ssl, struct worker* worker, char* args)
|
||||
* the actual mesh is not running, so we can freely edit it. */
|
||||
/* delete all the existing queries first */
|
||||
mesh_delete_all(worker->env.mesh);
|
||||
/* reset the fwd structure ; the cfg is unchanged (shared by threads)*/
|
||||
/* this reset frees up memory */
|
||||
forwards_apply_cfg(fwd, worker->env.cfg);
|
||||
if(strcmp(args, "off") == 0) {
|
||||
forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, root);
|
||||
} else {
|
||||
struct delegpt* dp;
|
||||
if(!(dp = parse_delegpt(ssl, fwd->region, args, root)))
|
||||
if(!(dp = parse_delegpt(ssl, args, root, 0)))
|
||||
return;
|
||||
if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
@@ -1385,6 +1517,152 @@ do_forward(SSL* ssl, struct worker* worker, char* args)
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
static int
|
||||
parse_fs_args(SSL* ssl, char* args, uint8_t** nm, struct delegpt** dp,
|
||||
int* insecure, int* prime)
|
||||
{
|
||||
char* zonename;
|
||||
char* rest;
|
||||
size_t nmlen;
|
||||
int nmlabs;
|
||||
/* parse all -x args */
|
||||
while(args[0] == '+') {
|
||||
if(!find_arg2(ssl, args, &rest))
|
||||
return 0;
|
||||
while(*(++args) != 0) {
|
||||
if(*args == 'i' && insecure)
|
||||
*insecure = 1;
|
||||
else if(*args == 'p' && prime)
|
||||
*prime = 1;
|
||||
else {
|
||||
(void)ssl_printf(ssl, "error: unknown option %s\n", args);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
args = rest;
|
||||
}
|
||||
/* parse name */
|
||||
if(dp) {
|
||||
if(!find_arg2(ssl, args, &rest))
|
||||
return 0;
|
||||
zonename = args;
|
||||
args = rest;
|
||||
} else zonename = args;
|
||||
if(!parse_arg_name(ssl, zonename, nm, &nmlen, &nmlabs))
|
||||
return 0;
|
||||
|
||||
/* parse dp */
|
||||
if(dp) {
|
||||
if(!(*dp = parse_delegpt(ssl, args, *nm, 1))) {
|
||||
free(*nm);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** do the forward_add command */
|
||||
static void
|
||||
do_forward_add(SSL* ssl, struct worker* worker, char* args)
|
||||
{
|
||||
struct iter_forwards* fwd = worker->env.fwds;
|
||||
int insecure = 0;
|
||||
uint8_t* nm = NULL;
|
||||
struct delegpt* dp = NULL;
|
||||
if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, NULL))
|
||||
return;
|
||||
if(insecure) {
|
||||
if(!anchors_add_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
|
||||
nm)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
delegpt_free_mlc(dp);
|
||||
free(nm);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
free(nm);
|
||||
return;
|
||||
}
|
||||
free(nm);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** do the forward_remove command */
|
||||
static void
|
||||
do_forward_remove(SSL* ssl, struct worker* worker, char* args)
|
||||
{
|
||||
struct iter_forwards* fwd = worker->env.fwds;
|
||||
int insecure = 0;
|
||||
uint8_t* nm = NULL;
|
||||
if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL))
|
||||
return;
|
||||
if(insecure)
|
||||
anchors_delete_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
|
||||
nm);
|
||||
forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, nm);
|
||||
free(nm);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** do the stub_add command */
|
||||
static void
|
||||
do_stub_add(SSL* ssl, struct worker* worker, char* args)
|
||||
{
|
||||
struct iter_forwards* fwd = worker->env.fwds;
|
||||
int insecure = 0, prime = 0;
|
||||
uint8_t* nm = NULL;
|
||||
struct delegpt* dp = NULL;
|
||||
if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, &prime))
|
||||
return;
|
||||
if(insecure) {
|
||||
if(!anchors_add_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
|
||||
nm)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
delegpt_free_mlc(dp);
|
||||
free(nm);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(!forwards_add_stub_hole(fwd, LDNS_RR_CLASS_IN, nm)) {
|
||||
if(insecure) anchors_delete_insecure(worker->env.anchors,
|
||||
LDNS_RR_CLASS_IN, nm);
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
delegpt_free_mlc(dp);
|
||||
free(nm);
|
||||
return;
|
||||
}
|
||||
if(!hints_add_stub(worker->env.hints, LDNS_RR_CLASS_IN, dp, !prime)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
forwards_delete_stub_hole(fwd, LDNS_RR_CLASS_IN, nm);
|
||||
if(insecure) anchors_delete_insecure(worker->env.anchors,
|
||||
LDNS_RR_CLASS_IN, nm);
|
||||
free(nm);
|
||||
return;
|
||||
}
|
||||
free(nm);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** do the stub_remove command */
|
||||
static void
|
||||
do_stub_remove(SSL* ssl, struct worker* worker, char* args)
|
||||
{
|
||||
struct iter_forwards* fwd = worker->env.fwds;
|
||||
int insecure = 0;
|
||||
uint8_t* nm = NULL;
|
||||
if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL))
|
||||
return;
|
||||
if(insecure)
|
||||
anchors_delete_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
|
||||
nm);
|
||||
forwards_delete_stub_hole(fwd, LDNS_RR_CLASS_IN, nm);
|
||||
hints_delete_stub(worker->env.hints, LDNS_RR_CLASS_IN, nm);
|
||||
free(nm);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** do the status command */
|
||||
static void
|
||||
do_status(SSL* ssl, struct worker* worker)
|
||||
@@ -1527,68 +1805,38 @@ struct infra_arg {
|
||||
SSL* ssl;
|
||||
/** the time now */
|
||||
uint32_t now;
|
||||
/** ipstr */
|
||||
char* ipstr;
|
||||
};
|
||||
|
||||
/** callback for every lame element in the infra cache */
|
||||
static void
|
||||
dump_infra_lame(struct lruhash_entry* e, void* arg)
|
||||
{
|
||||
struct infra_arg* a = (struct infra_arg*)arg;
|
||||
struct infra_lame_key* k = (struct infra_lame_key*)e->key;
|
||||
struct infra_lame_data* d = (struct infra_lame_data*)e->data;
|
||||
ldns_rdf* rdf;
|
||||
size_t pos = 0;
|
||||
char* nm;
|
||||
/* skip expired */
|
||||
if(d->ttl < a->now) {
|
||||
return;
|
||||
}
|
||||
/* use ldns print for domain name */
|
||||
if(ldns_wire2dname(&rdf, k->zonename, k->namelen, &pos)
|
||||
!= LDNS_STATUS_OK)
|
||||
return;
|
||||
nm = ldns_rdf2str(rdf);
|
||||
ldns_rdf_deep_free(rdf);
|
||||
if(!ssl_printf(a->ssl, "%s lame %s ttl %d dnssec %d rec %d "
|
||||
"A %d other %d\n", a->ipstr, nm, (int)(d->ttl - a->now),
|
||||
d->isdnsseclame, d->rec_lame, d->lame_type_A, d->lame_other)) {
|
||||
free(nm);
|
||||
return;
|
||||
}
|
||||
free(nm);
|
||||
}
|
||||
|
||||
/** callback for every host element in the infra cache */
|
||||
static void
|
||||
dump_infra_host(struct lruhash_entry* e, void* arg)
|
||||
{
|
||||
struct infra_arg* a = (struct infra_arg*)arg;
|
||||
struct infra_host_key* k = (struct infra_host_key*)e->key;
|
||||
struct infra_host_data* d = (struct infra_host_data*)e->data;
|
||||
struct infra_key* k = (struct infra_key*)e->key;
|
||||
struct infra_data* d = (struct infra_data*)e->data;
|
||||
char ip_str[1024];
|
||||
char name[257];
|
||||
addr_to_str(&k->addr, k->addrlen, ip_str, sizeof(ip_str));
|
||||
a->ipstr = ip_str;
|
||||
dname_str(k->zonename, name);
|
||||
/* skip expired stuff (only backed off) */
|
||||
if(d->ttl < a->now) {
|
||||
if(d->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
if(!ssl_printf(a->ssl, "%s expired rto %d\n", ip_str,
|
||||
d->rtt.rto)) return;
|
||||
if(!ssl_printf(a->ssl, "%s %s expired rto %d\n", ip_str,
|
||||
name, d->rtt.rto)) return;
|
||||
}
|
||||
if(d->lameness)
|
||||
lruhash_traverse(d->lameness, 0, &dump_infra_lame, arg);
|
||||
return;
|
||||
}
|
||||
if(!ssl_printf(a->ssl, "%s ttl %d ping %d var %d rtt %d rto %d "
|
||||
"ednsknown %d edns %d delay %d\n",
|
||||
ip_str, (int)(d->ttl - a->now),
|
||||
if(!ssl_printf(a->ssl, "%s %s ttl %d ping %d var %d rtt %d rto %d "
|
||||
"tA %d tAAAA %d tother %d "
|
||||
"ednsknown %d edns %d delay %d lame dnssec %d rec %d A %d "
|
||||
"other %d\n", ip_str, name, (int)(d->ttl - a->now),
|
||||
d->rtt.srtt, d->rtt.rttvar, rtt_notimeout(&d->rtt), d->rtt.rto,
|
||||
d->timeout_A, d->timeout_AAAA, d->timeout_other,
|
||||
(int)d->edns_lame_known, (int)d->edns_version,
|
||||
(int)(a->now<d->probedelay?d->probedelay-a->now:0)))
|
||||
(int)(a->now<d->probedelay?d->probedelay-a->now:0),
|
||||
(int)d->isdnsseclame, (int)d->rec_lame, (int)d->lame_type_A,
|
||||
(int)d->lame_other))
|
||||
return;
|
||||
if(d->lameness)
|
||||
lruhash_traverse(d->lameness, 0, &dump_infra_lame, arg);
|
||||
}
|
||||
|
||||
/** do the dump_infra command */
|
||||
@@ -1663,17 +1911,8 @@ do_list_forwards(SSL* ssl, struct worker* worker)
|
||||
static void
|
||||
do_list_stubs(SSL* ssl, struct worker* worker)
|
||||
{
|
||||
/* readonly structure */
|
||||
int m;
|
||||
struct iter_hints_stub* z;
|
||||
struct iter_env* ie;
|
||||
m = modstack_find(&worker->env.mesh->mods, "iterator");
|
||||
if(m == -1) {
|
||||
(void)ssl_printf(ssl, "error no iterator module\n");
|
||||
return;
|
||||
}
|
||||
ie = (struct iter_env*)worker->env.modinfo[m];
|
||||
RBTREE_FOR(z, struct iter_hints_stub*, &ie->hints->tree) {
|
||||
RBTREE_FOR(z, struct iter_hints_stub*, &worker->env.hints->tree) {
|
||||
if(!ssl_print_name_dp(ssl,
|
||||
z->noprime?"stub noprime":"stub prime", z->node.name,
|
||||
z->node.dclass, z->dp))
|
||||
@@ -1791,6 +2030,26 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd,
|
||||
} else if(cmdcmp(p, "list_local_data", 15)) {
|
||||
do_list_local_data(ssl, worker);
|
||||
return;
|
||||
} else if(cmdcmp(p, "stub_add", 8)) {
|
||||
/* must always distribute this cmd */
|
||||
if(rc) distribute_cmd(rc, ssl, cmd);
|
||||
do_stub_add(ssl, worker, skipwhite(p+8));
|
||||
return;
|
||||
} else if(cmdcmp(p, "stub_remove", 11)) {
|
||||
/* must always distribute this cmd */
|
||||
if(rc) distribute_cmd(rc, ssl, cmd);
|
||||
do_stub_remove(ssl, worker, skipwhite(p+11));
|
||||
return;
|
||||
} else if(cmdcmp(p, "forward_add", 11)) {
|
||||
/* must always distribute this cmd */
|
||||
if(rc) distribute_cmd(rc, ssl, cmd);
|
||||
do_forward_add(ssl, worker, skipwhite(p+11));
|
||||
return;
|
||||
} else if(cmdcmp(p, "forward_remove", 14)) {
|
||||
/* must always distribute this cmd */
|
||||
if(rc) distribute_cmd(rc, ssl, cmd);
|
||||
do_forward_remove(ssl, worker, skipwhite(p+14));
|
||||
return;
|
||||
} else if(cmdcmp(p, "forward", 7)) {
|
||||
/* must always distribute this cmd */
|
||||
if(rc) distribute_cmd(rc, ssl, cmd);
|
||||
@@ -1847,6 +2106,8 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd,
|
||||
do_set_option(ssl, worker, skipwhite(p+10));
|
||||
} else if(cmdcmp(p, "get_option", 10)) {
|
||||
do_get_option(ssl, worker, skipwhite(p+10));
|
||||
} else if(cmdcmp(p, "flush_bogus", 11)) {
|
||||
do_flush_bogus(ssl, worker);
|
||||
} else {
|
||||
(void)ssl_printf(ssl, "error unknown command '%s'\n", p);
|
||||
}
|
||||
|
||||
@@ -69,8 +69,10 @@ struct rc_state {
|
||||
struct comm_point* c;
|
||||
/** in the handshake part */
|
||||
enum { rc_none, rc_hs_read, rc_hs_write } shake_state;
|
||||
#ifdef HAVE_SSL
|
||||
/** the ssl state */
|
||||
SSL* ssl;
|
||||
#endif
|
||||
/** the rc this is part of */
|
||||
struct daemon_remote* rc;
|
||||
};
|
||||
@@ -93,8 +95,10 @@ struct daemon_remote {
|
||||
int max_active;
|
||||
/** current commpoints busy; should be a short list, malloced */
|
||||
struct rc_state* busy_list;
|
||||
#ifdef HAVE_SSL
|
||||
/** the SSL context for creating new SSL streams */
|
||||
SSL_CTX* ctx;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -135,6 +139,18 @@ struct listen_port* daemon_remote_open_ports(struct config_file* cfg);
|
||||
int daemon_remote_open_accept(struct daemon_remote* rc,
|
||||
struct listen_port* ports, struct worker* worker);
|
||||
|
||||
/**
|
||||
* Stop accept handlers for TCP (until enabled again)
|
||||
* @param rc: state
|
||||
*/
|
||||
void daemon_remote_stop_accept(struct daemon_remote* rc);
|
||||
|
||||
/**
|
||||
* Stop accept handlers for TCP (until enabled again)
|
||||
* @param rc: state
|
||||
*/
|
||||
void daemon_remote_start_accept(struct daemon_remote* rc);
|
||||
|
||||
/**
|
||||
* Handle nonthreaded remote cmd execution.
|
||||
* @param worker: this worker (the remote worker).
|
||||
@@ -147,6 +163,7 @@ int remote_accept_callback(struct comm_point*, void*, int, struct comm_reply*);
|
||||
/** handle remote control data callbacks */
|
||||
int remote_control_callback(struct comm_point*, void*, int, struct comm_reply*);
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
/**
|
||||
* Print fixed line of text over ssl connection in blocking mode
|
||||
* @param ssl: print to
|
||||
@@ -173,6 +190,7 @@ int ssl_printf(SSL* ssl, const char* format, ...)
|
||||
* @return false on connection failure.
|
||||
*/
|
||||
int ssl_read_line(SSL* ssl, char* buf, size_t max);
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
/** routine to printout option values over SSL */
|
||||
void remote_get_opt_ssl(char* line, void* arg);
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@
|
||||
* numbers. These 'statistics' may be of interest to the operator.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ldns/wire2host.h"
|
||||
#include <ldns/wire2host.h>
|
||||
#include "daemon/stats.h"
|
||||
#include "daemon/worker.h"
|
||||
#include "daemon/daemon.h"
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@
|
||||
#ifndef DAEMON_STATS_H
|
||||
#define DAEMON_STATS_H
|
||||
#include "util/timehist.h"
|
||||
#include "ldns/buffer.h"
|
||||
#include <ldns/buffer.h>
|
||||
struct worker;
|
||||
struct config_file;
|
||||
struct comm_point;
|
||||
|
||||
+35
-10
@@ -55,6 +55,7 @@
|
||||
#include "services/cache/infra.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/module.h"
|
||||
#include "util/net_help.h"
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <openssl/crypto.h>
|
||||
@@ -86,6 +87,10 @@
|
||||
# include "winrc/win_svc.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NSS
|
||||
# include <nss3/nss.h>
|
||||
#endif
|
||||
|
||||
/** global debug value to keep track of heap memory allocation */
|
||||
void* unbound_start_brk = 0;
|
||||
|
||||
@@ -158,7 +163,12 @@ static void usage()
|
||||
get_event_sys(&evnm, &evsys, &evmethod);
|
||||
printf("linked libs: %s %s (it uses %s), ldns %s, %s\n",
|
||||
evnm, evsys, evmethod, ldns_version(),
|
||||
SSLeay_version(SSLEAY_VERSION));
|
||||
#ifdef HAVE_SSL
|
||||
SSLeay_version(SSLEAY_VERSION)
|
||||
#elif defined(HAVE_NSS)
|
||||
NSS_GetVersion()
|
||||
#endif
|
||||
);
|
||||
printf("linked modules:");
|
||||
for(m = module_list_avail(); *m; m++)
|
||||
printf(" %s", *m);
|
||||
@@ -444,8 +454,17 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
* given to unbound on the commandline. */
|
||||
|
||||
/* read ssl keys while superuser and outside chroot */
|
||||
#ifdef HAVE_SSL
|
||||
if(!(daemon->rc = daemon_remote_create(cfg)))
|
||||
fatal_exit("could not set up remote-control");
|
||||
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
|
||||
if(!(daemon->listen_sslctx = listen_sslctx_create(
|
||||
cfg->ssl_service_key, cfg->ssl_service_pem, NULL)))
|
||||
fatal_exit("could not set up listen SSL_CTX");
|
||||
}
|
||||
if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL, NULL)))
|
||||
fatal_exit("could not set up connect SSL_CTX");
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_KILL
|
||||
/* check old pid file before forking */
|
||||
@@ -494,6 +513,21 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
(void)daemon;
|
||||
#endif
|
||||
|
||||
/* Set user context */
|
||||
#ifdef HAVE_GETPWNAM
|
||||
if(cfg->username && cfg->username[0]) {
|
||||
#ifdef HAVE_SETUSERCONTEXT
|
||||
/* setusercontext does initgroups, setuid, setgid, and
|
||||
* also resource limits from login config, but we
|
||||
* still call setresuid, setresgid to be sure to set all uid*/
|
||||
if(setusercontext(NULL, pwd, uid,
|
||||
LOGIN_SETALL & ~LOGIN_SETUSER & ~LOGIN_SETGROUP) != 0)
|
||||
log_warn("unable to setusercontext %s: %s",
|
||||
cfg->username, strerror(errno));
|
||||
#endif /* HAVE_SETUSERCONTEXT */
|
||||
}
|
||||
#endif /* HAVE_GETPWNAM */
|
||||
|
||||
/* box into the chroot */
|
||||
#ifdef HAVE_CHROOT
|
||||
if(cfg->chrootdir && cfg->chrootdir[0]) {
|
||||
@@ -546,20 +580,11 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
/* drop permissions after chroot, getpwnam, pidfile, syslog done*/
|
||||
#ifdef HAVE_GETPWNAM
|
||||
if(cfg->username && cfg->username[0]) {
|
||||
#ifdef HAVE_SETUSERCONTEXT
|
||||
/* setusercontext does initgroups, setuid, setgid, and
|
||||
* also resource limits from login config, but we
|
||||
* still call setresuid, setresgid to be sure to set all uid*/
|
||||
if(setusercontext(NULL, pwd, uid, LOGIN_SETALL) != 0)
|
||||
log_warn("unable to setusercontext %s: %s",
|
||||
cfg->username, strerror(errno));
|
||||
#else /* !HAVE_SETUSERCONTEXT */
|
||||
# ifdef HAVE_INITGROUPS
|
||||
if(initgroups(cfg->username, gid) != 0)
|
||||
log_warn("unable to initgroups %s: %s",
|
||||
cfg->username, strerror(errno));
|
||||
# endif /* HAVE_INITGROUPS */
|
||||
#endif /* HAVE_SETUSERCONTEXT */
|
||||
endpwent();
|
||||
|
||||
#ifdef HAVE_SETRESGID
|
||||
|
||||
+42
-13
@@ -40,7 +40,7 @@
|
||||
* pending requests.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ldns/wire2host.h"
|
||||
#include <ldns/wire2host.h>
|
||||
#include "util/log.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/random.h"
|
||||
@@ -67,7 +67,9 @@
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "util/tube.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
#include "validator/autotrust.h"
|
||||
#include "validator/val_anchor.h"
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
@@ -148,7 +150,7 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
|
||||
#ifdef UNBOUND_ALLOC_STATS
|
||||
/* debug func in validator module */
|
||||
size_t total, front, back, mesh, msg, rrset, infra, ac, superac;
|
||||
size_t me, iter, val;
|
||||
size_t me, iter, val, anch;
|
||||
int i;
|
||||
if(verbosity < VERB_ALGO)
|
||||
return;
|
||||
@@ -160,6 +162,7 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
|
||||
mesh = mesh_get_mem(worker->env.mesh);
|
||||
ac = alloc_get_mem(&worker->alloc);
|
||||
superac = alloc_get_mem(&worker->daemon->superalloc);
|
||||
anch = anchors_get_mem(worker->env.anchors);
|
||||
iter = 0;
|
||||
val = 0;
|
||||
for(i=0; i<worker->env.mesh->mods.num; i++) {
|
||||
@@ -177,7 +180,8 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
|
||||
+ regional_get_mem(worker->scratchpad)
|
||||
+ sizeof(*worker->env.scratch_buffer)
|
||||
+ ldns_buffer_capacity(worker->env.scratch_buffer)
|
||||
+ forwards_get_mem(worker->env.fwds);
|
||||
+ forwards_get_mem(worker->env.fwds)
|
||||
+ hints_get_mem(worker->env.hints);
|
||||
if(worker->thread_num == 0)
|
||||
me += acl_list_get_mem(worker->daemon->acl);
|
||||
if(cur_serv) {
|
||||
@@ -185,12 +189,12 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
|
||||
}
|
||||
total = front+back+mesh+msg+rrset+infra+iter+val+ac+superac+me;
|
||||
log_info("Memory conditions: %u front=%u back=%u mesh=%u msg=%u "
|
||||
"rrset=%u infra=%u iter=%u val=%u "
|
||||
"rrset=%u infra=%u iter=%u val=%u anchors=%u "
|
||||
"alloccache=%u globalalloccache=%u me=%u",
|
||||
(unsigned)total, (unsigned)front, (unsigned)back,
|
||||
(unsigned)mesh, (unsigned)msg, (unsigned)rrset,
|
||||
(unsigned)infra, (unsigned)iter, (unsigned)val, (unsigned)ac,
|
||||
(unsigned)superac, (unsigned)me);
|
||||
(unsigned)infra, (unsigned)iter, (unsigned)val, (unsigned)anch,
|
||||
(unsigned)ac, (unsigned)superac, (unsigned)me);
|
||||
debug_total_mem(total);
|
||||
#else /* no UNBOUND_ALLOC_STATS */
|
||||
size_t val = 0;
|
||||
@@ -1053,6 +1057,8 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
comm_base_set_slow_accept_handlers(worker->base, &worker_stop_accept,
|
||||
&worker_start_accept, worker);
|
||||
if(do_sigs) {
|
||||
#ifdef SIGHUP
|
||||
ub_thread_sig_unblock(SIGHUP);
|
||||
@@ -1092,7 +1098,7 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
}
|
||||
worker->front = listen_create(worker->base, ports,
|
||||
cfg->msg_buffer_size, (int)cfg->incoming_num_tcp,
|
||||
worker_handle_request, worker);
|
||||
worker->daemon->listen_sslctx, worker_handle_request, worker);
|
||||
if(!worker->front) {
|
||||
log_err("could not create listening sockets");
|
||||
worker_delete(worker);
|
||||
@@ -1105,7 +1111,7 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
worker->daemon->env->infra_cache, worker->rndstate,
|
||||
cfg->use_caps_bits_for_id, worker->ports, worker->numports,
|
||||
cfg->unwanted_threshold, &worker_alloc_cleanup, worker,
|
||||
cfg->do_udp);
|
||||
cfg->do_udp, worker->daemon->connect_sslctx);
|
||||
if(!worker->back) {
|
||||
log_err("could not create outgoing sockets");
|
||||
worker_delete(worker);
|
||||
@@ -1158,6 +1164,12 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
if(!(worker->env.hints = hints_create()) ||
|
||||
!hints_apply_cfg(worker->env.hints, cfg)) {
|
||||
log_err("Could not set root or stub hints");
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
/* one probe timer per process -- if we have 5011 anchors */
|
||||
if(autr_get_num_anchors(worker->env.anchors) > 0
|
||||
#ifndef THREADS_DISABLED
|
||||
@@ -1210,6 +1222,7 @@ worker_delete(struct worker* worker)
|
||||
mesh_delete(worker->env.mesh);
|
||||
ldns_buffer_free(worker->env.scratch_buffer);
|
||||
forwards_delete(worker->env.fwds);
|
||||
hints_delete(worker->env.hints);
|
||||
listen_delete(worker->front);
|
||||
outside_network_delete(worker->back);
|
||||
comm_signal_delete(worker->comsig);
|
||||
@@ -1244,8 +1257,8 @@ outbound_entry_compare(void* a, void* b)
|
||||
struct outbound_entry*
|
||||
worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
|
||||
uint16_t qclass, uint16_t flags, int dnssec, int want_dnssec,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct module_qstate* q)
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, struct module_qstate* q)
|
||||
{
|
||||
struct worker* worker = q->env->worker;
|
||||
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
|
||||
@@ -1255,9 +1268,9 @@ worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
|
||||
e->qstate = q;
|
||||
e->qsent = outnet_serviced_query(worker->back, qname,
|
||||
qnamelen, qtype, qclass, flags, dnssec, want_dnssec,
|
||||
q->env->cfg->tcp_upstream, addr, addrlen,
|
||||
worker_handle_service_reply, e, worker->back->udp_buff,
|
||||
&outbound_entry_compare);
|
||||
q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr,
|
||||
addrlen, zone, zonelen, worker_handle_service_reply, e,
|
||||
worker->back->udp_buff, &outbound_entry_compare);
|
||||
if(!e->qsent) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -1279,6 +1292,22 @@ void worker_stats_clear(struct worker* worker)
|
||||
worker->back->unwanted_replies = 0;
|
||||
}
|
||||
|
||||
void worker_start_accept(void* arg)
|
||||
{
|
||||
struct worker* worker = (struct worker*)arg;
|
||||
listen_start_accept(worker->front);
|
||||
if(worker->thread_num == 0)
|
||||
daemon_remote_start_accept(worker->daemon->rc);
|
||||
}
|
||||
|
||||
void worker_stop_accept(void* arg)
|
||||
{
|
||||
struct worker* worker = (struct worker*)arg;
|
||||
listen_stop_accept(worker->front);
|
||||
if(worker->thread_num == 0)
|
||||
daemon_remote_stop_accept(worker->daemon->rc);
|
||||
}
|
||||
|
||||
/* --- fake callbacks for fptr_wlist to work --- */
|
||||
struct outbound_entry* libworker_send_query(uint8_t* ATTR_UNUSED(qname),
|
||||
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
|
||||
|
||||
+9
-1
@@ -175,6 +175,8 @@ void worker_sighandler(int sig, void* arg);
|
||||
* @param want_dnssec: signatures needed.
|
||||
* @param addr: where to.
|
||||
* @param addrlen: length of addr.
|
||||
* @param zone: wireformat dname of the zone.
|
||||
* @param zonelen: length of zone name.
|
||||
* @param q: wich query state to reactivate upon return.
|
||||
* @return: false on failure (memory or socket related). no query was
|
||||
* sent.
|
||||
@@ -182,7 +184,7 @@ void worker_sighandler(int sig, void* arg);
|
||||
struct outbound_entry* worker_send_query(uint8_t* qname, size_t qnamelen,
|
||||
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
|
||||
int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct module_qstate* q);
|
||||
uint8_t* zone, size_t zonelen, struct module_qstate* q);
|
||||
|
||||
/**
|
||||
* process control messages from the main thread. Frees the control
|
||||
@@ -223,4 +225,10 @@ void worker_stat_timer_cb(void* arg);
|
||||
/** probe timer callback handler */
|
||||
void worker_probe_timer_cb(void* arg);
|
||||
|
||||
/** start accept callback handler */
|
||||
void worker_start_accept(void* arg);
|
||||
|
||||
/** stop accept callback handler */
|
||||
void worker_stop_accept(void* arg);
|
||||
|
||||
#endif /* DAEMON_WORKER_H */
|
||||
|
||||
@@ -18,3 +18,4 @@ cz.nic - sponsoring 'summer of code' development by Zdenek and Marek.
|
||||
Brett Carr - windows beta testing.
|
||||
Luca Bruno - patch for windows support in libunbound hosts and resolvconf().
|
||||
Tom Hendrikx - contributed split-itar.sh a useful script to 5011-track ITAR.
|
||||
Daisuke HIGASHI - patch for rrset-roundrobin and minimal-responses.
|
||||
|
||||
+433
@@ -1,3 +1,436 @@
|
||||
30 July 2012: Wouter
|
||||
- tag 1.4.18rc2.
|
||||
|
||||
27 July 2012: Wouter
|
||||
- unbound-host works with libNSS
|
||||
- fix bogus nodata cname chain not reported as bogus by validator,
|
||||
(Thanks Peter van Dijk).
|
||||
|
||||
26 July 2012: Wouter
|
||||
- iana portlist updated.
|
||||
- tag 1.4.18rc1.
|
||||
|
||||
25 July 2012: Wouter
|
||||
- review fix for libnss, check hash prefix allocation size.
|
||||
|
||||
23 July 2012: Wouter
|
||||
- fix missing break for GOST DS hash function.
|
||||
- implemented forward_first for the root.
|
||||
|
||||
20 July 2012: Wouter
|
||||
- Fix bug#452 and another assertion failure in mesh.c, makes
|
||||
assertions in mesh.c resist duplicates. Fixes DS NS search to
|
||||
not generate duplicate sub queries.
|
||||
|
||||
19 July 2012: Willem
|
||||
- Fix bug#454: Remove ACX_CHECK_COMPILER_FLAG from configure.ac,
|
||||
if CFLAGS is specified at configure time then '-g -O2' is not
|
||||
appended to CFLAGS, so that the user can override them.
|
||||
|
||||
18 July 2012: Willem
|
||||
- Fix libunbound report of errors when in background mode.
|
||||
|
||||
11 July 2012: Willem
|
||||
- updated iana ports list.
|
||||
|
||||
9 July 2012: Willem
|
||||
- Add flush_bogus option for unbound-control
|
||||
|
||||
6 July 2012: Wouter
|
||||
- Fix validation of qtype DS queries that result in no data for
|
||||
non-optout NSEC3 zones.
|
||||
|
||||
4 July 2012: Wouter
|
||||
- compile libunbound with libnss on Suse, passes regression tests.
|
||||
|
||||
3 July 2012: Wouter
|
||||
- FIPS_mode openssl does not use arc4random but RAND_pseudo_bytes.
|
||||
|
||||
2 July 2012: Wouter
|
||||
- updated iana ports list.
|
||||
|
||||
29 June 2012: Wouter
|
||||
- patch for unbound_munin_ script to handle arbitrary thread count by
|
||||
Sven Ulland.
|
||||
|
||||
28 June 2012: Wouter
|
||||
- detect if openssl has FIPS_mode.
|
||||
- code review: return value of cache_store can be ignored for better
|
||||
performance in out of memory conditions.
|
||||
- fix edns-buffer-size and msg-buffer-size manpage documentation.
|
||||
- updated iana ports list.
|
||||
|
||||
25 June 2012: Wouter
|
||||
- disable RSAMD5 if in FIPS mode (for openssl and for libnss).
|
||||
|
||||
22 June 2012: Wouter
|
||||
- implement DS records, NSEC3 and ECDSA for compile with libnss.
|
||||
|
||||
21 June 2012: Wouter
|
||||
- fix error handling of alloc failure during rrsig verification.
|
||||
- nss check for verification failure.
|
||||
- nss crypto works for RSA and DSA.
|
||||
|
||||
20 June 2012: Wouter
|
||||
- work on --with-nss build option (for now, --with-libunbound-only).
|
||||
|
||||
19 June 2012: Wouter
|
||||
- --with-libunbound-only build option, only builds the library and
|
||||
not the daemon and other tools.
|
||||
|
||||
18 June 2012: Wouter
|
||||
- code review.
|
||||
|
||||
15 June 2012: Wouter
|
||||
- implement log-time-ascii on windows.
|
||||
- The key-cache bad key ttl is now 60 seconds.
|
||||
- updated iana ports list.
|
||||
- code review.
|
||||
|
||||
11 June 2012: Wouter
|
||||
- bug #452: fix crash on assert in mesh_state_attachment.
|
||||
|
||||
30 May 2012: Wouter
|
||||
- silence warning from swig-generated code (md set but not used in
|
||||
swig initmodule, due to ifdefs in swig-generated code).
|
||||
|
||||
27 May 2012: Wouter
|
||||
- Fix debian-bugs-658021: Please enable hardened build flags.
|
||||
|
||||
25 May 2012: Wouter
|
||||
- updated iana ports list.
|
||||
|
||||
24 May 2012: Wouter
|
||||
- tag for 1.4.17 release.
|
||||
- trunk is 1.4.18 in development.
|
||||
|
||||
18 May 2012: Wouter
|
||||
- Review comments, removed duplicate memset to zero in delegpt.
|
||||
|
||||
16 May 2012: Wouter
|
||||
- Updated doc/FEATURES with RFCs that are implemented but not listed.
|
||||
- Protect if statements in val_anchor for compile without locks.
|
||||
- tag for 1.4.17rc1.
|
||||
|
||||
15 May 2012: Wouter
|
||||
- fix configure ECDSA support in ldns detection for windows compile.
|
||||
- fix possible uninitialised variable in windows pipe implementation.
|
||||
|
||||
9 May 2012: Wouter
|
||||
- Fix alignment problem in util/random on sparc64/freebsd.
|
||||
|
||||
8 May 2012: Wouter
|
||||
- Fix for accept spinning reported by OpenBSD.
|
||||
- iana portlist updated.
|
||||
|
||||
2 May 2012: Wouter
|
||||
- Fix validation of nodata for DS query in NSEC zones, reported by
|
||||
Ondrej Mikle.
|
||||
|
||||
13 April 2012: Wouter
|
||||
- ECDSA support (RFC 6605) by default. Use --disable-ecdsa for older
|
||||
openssl.
|
||||
|
||||
10 April 2012: Wouter
|
||||
- Applied patch from Daisuke HIGASHI for rrset-roundrobin and
|
||||
minimal-responses features.
|
||||
- iana portlist updated.
|
||||
|
||||
5 April 2012: Wouter
|
||||
- fix bug #443: --with-chroot-dir not honoured by configure.
|
||||
- fix bug #444: setusercontext was called too late (thanks Bjorn
|
||||
Ketelaars).
|
||||
|
||||
27 March 2012: Wouter
|
||||
- fix bug #442: Fix that Makefile depends on pythonmod headers
|
||||
even using --without-pythonmodule.
|
||||
|
||||
22 March 2012: Wouter
|
||||
- contrib/validation-reporter follows rotated log file (patch from
|
||||
Augie Schwer).
|
||||
|
||||
21 March 2012: Wouter
|
||||
- new approach to NS fetches for DS lookup that works with
|
||||
cornercases, and is more robust and considers forwarders.
|
||||
|
||||
19 March 2012: Wouter
|
||||
- iana portlist updated.
|
||||
- fix to locate nameservers for DS lookup with NS fetches.
|
||||
|
||||
16 March 2012: Wouter
|
||||
- Patch for access to full DNS packet data in unbound python module
|
||||
from Ondrej Mikle.
|
||||
|
||||
9 March 2012: Wouter
|
||||
- Applied line-buffer patch from Augie Schwer to validation.reporter.sh.
|
||||
|
||||
2 March 2012: Wouter
|
||||
- flush_infra cleans timeouted servers from the cache too.
|
||||
- removed warning from --enable-ecdsa.
|
||||
|
||||
1 March 2012: Wouter
|
||||
- forward-first option. Tries without forward if a query fails.
|
||||
Also stub-first option that is similar.
|
||||
|
||||
28 February 2012: Wouter
|
||||
- Fix from code review, if EINPROGRESS not defined chain if statement
|
||||
differently.
|
||||
|
||||
27 February 2012: Wouter
|
||||
- Fix bug#434: on windows check registry for config file location
|
||||
for unbound-control.exe, and unbound-checkconf.exe.
|
||||
|
||||
23 February 2012: Wouter
|
||||
- Fix to squelch 'network unreachable' errors from tcp connect in
|
||||
logs, high verbosity will show them.
|
||||
|
||||
16 February 2012: Wouter
|
||||
- iter_hints is now thread-owned in module env, and thus threadsafe.
|
||||
- Fix prefetch and sticky NS, now the prefetch works. It picks
|
||||
nameservers that 'would be valid in the future', and if this makes
|
||||
the NS timeout, it updates that NS by asking delegation from the
|
||||
parent again. If child NS has longer TTL, that TTL does not get
|
||||
refreshed from the lookup to the child nameserver.
|
||||
|
||||
15 February 2012: Wouter
|
||||
- Fix forward-zone memory, uses malloc and frees original root dp.
|
||||
- iter hints (stubs) uses malloc inside for more dynamicity.
|
||||
- unbound-control forward_add, forward_remove, stub_add, stub_remove
|
||||
can modify stubs and forwards for running unbound (on mobile computer)
|
||||
they can also add and remove domain-insecure for the zone.
|
||||
|
||||
14 February 2012: Wouter
|
||||
- Fix sticky NS (ghost domain problem) if prefetch is yes.
|
||||
- iter forwards uses malloc inside for more dynamicity.
|
||||
|
||||
13 February 2012: Wouter
|
||||
- RT#2955. Fix for cygwin compilation.
|
||||
- iana portlist updated.
|
||||
|
||||
10 February 2012: Wouter
|
||||
- Slightly smaller critical region in one case in infra cache.
|
||||
- Fix timeouts to keep track of query type, A, AAAA and other, if
|
||||
another has caused timeout blacklist, different type can still probe.
|
||||
- unit test fix for nomem_cnametopos.rpl race condition.
|
||||
|
||||
9 February 2012: Wouter
|
||||
- Fix AHX_BROKEN_MEMCMP for autoheader mess up of #undef in config.h.
|
||||
|
||||
8 February 2012: Wouter
|
||||
- implement draft-ietf-dnsext-ecdsa-04; which is in IETF LC; This
|
||||
implementation is experimental at this time and not recommended
|
||||
for use on the public internet (the protocol numbers have not
|
||||
been assigned). Needs recent ldns with --enable-ecdsa.
|
||||
- fix memory leak in errorcase for DSA signatures.
|
||||
- iana portlist updated.
|
||||
- workaround for openssl 0.9.8 ecdsa sha2 and evp problem.
|
||||
|
||||
3 February 2012: Wouter
|
||||
- fix for windows, rename() is not posix compliant on windows.
|
||||
|
||||
2 February 2012: Wouter
|
||||
- 1.4.16 release tag.
|
||||
- svn trunk is 1.4.17 in development.
|
||||
- iana portlist updated.
|
||||
|
||||
1 February 2012: Wouter
|
||||
- Fix validation failures (like: validation failure xx: no NSEC3
|
||||
closest encloser from yy for DS zz. while building chain of trust,
|
||||
because of a bug in the TTL-fix in 1.4.15, it picked the wrong rdata
|
||||
for an NSEC3. Now it does not change rdata, and fixes TTL.
|
||||
|
||||
30 January 2012: Wouter
|
||||
- Fix version-number in libtool to be version-info so it produces
|
||||
libunbound.so.2 like it should.
|
||||
|
||||
26 January 2012: Wouter
|
||||
- Tag 1.4.15 (same as 1.4.15rc1), for 1.4.15 release.
|
||||
- trunk 1.4.16; includes changes memset testcode, #424 openindiana,
|
||||
and keyfile write fixup.
|
||||
- applied patch to support outgoing-interface with ub_ctx_set_option.
|
||||
|
||||
23 January 2012: Wouter
|
||||
- Fix memset in test code.
|
||||
|
||||
20 January 2012: Wouter
|
||||
- Fix bug #424: compile on OpenIndiana OS with gcc 4.6.2.
|
||||
|
||||
19 January 2012: Wouter
|
||||
- Fix to write key files completely to a temporary file, and if that
|
||||
succeeds, replace the real key file. So failures leave a useful file.
|
||||
|
||||
18 January 2012: Wouter
|
||||
- tag 1.4.15rc1 created
|
||||
- updated libunbound/ubsyms.def and remade tag 1.4.15rc1.
|
||||
|
||||
17 January 2012: Wouter
|
||||
- Fix bug where canonical_compare of RRSIG did not downcase the
|
||||
signer-name. This is mostly harmless because RRSIGs do not have
|
||||
to be sorted in canonical order, usually.
|
||||
|
||||
12 January 2012: Wouter
|
||||
- bug#428: add ub_version() call to libunbound. API version increase,
|
||||
with (binary) backwards compatibility for the previous version.
|
||||
|
||||
10 January 2012: Wouter
|
||||
- Fix bug #425: unbound reports wrong TTL in reply, it reports a TTL
|
||||
that would be permissible by the RFCs but it is not the TTL in the
|
||||
cache.
|
||||
- iana portlist updated.
|
||||
- uninitialised variable in reprobe for rtt blocked domains fixed.
|
||||
- lintfix and new flex output.
|
||||
|
||||
2 January 2012: Wouter
|
||||
- Fix to randomize hash function, based on 28c3 congress, reported
|
||||
by Peter van Dijk.
|
||||
|
||||
24 December 2011: Wouter
|
||||
- Fix for memory leak (about 20 bytes when a tcp or udp send operation
|
||||
towards authority servers failed, takes about 50.000 such failures to
|
||||
leak one Mb, such failures are also usually logged), reported by
|
||||
Robert Fleischmann.
|
||||
- iana portlist updated.
|
||||
|
||||
19 December 2011: Wouter
|
||||
- Fix for VU#209659 CVE-2011-4528: Unbound denial of service
|
||||
vulnerabilities from nonstandard redirection and denial of existence
|
||||
http://www.unbound.net/downloads/CVE-2011-4528.txt
|
||||
- robust checks for next-closer NSEC3s.
|
||||
- tag 1.4.14 created.
|
||||
- trunk has 1.4.15 in development.
|
||||
|
||||
15 December 2011: Wouter
|
||||
- remove uninit warning from cachedump code.
|
||||
- Fix parse error on negative SOA RRSIGs if badly ordered in the packet.
|
||||
|
||||
13 December 2011: Wouter
|
||||
- iana portlist updated.
|
||||
- svn tag 1.4.14rc1
|
||||
- fix infra cache comparison.
|
||||
- Fix to constrain signer_name to be a parent of the lookupname.
|
||||
|
||||
5 December 2011: Wouter
|
||||
- Fix getaddrinfowithincludes on windows with fedora16 mingw32-gcc.
|
||||
- Fix warnings with gcc 4.6 in compat/inet_ntop.c.
|
||||
- Fix warning unused in compat/strptime.c.
|
||||
- Fix malloc detection and double defintion.
|
||||
|
||||
2 December 2011: Wouter
|
||||
- configure generated with autoconf 2.68.
|
||||
|
||||
30 November 2011: Wouter
|
||||
- Fix for tcp-upstream and ssl-upstream for if a laptop sleeps, causes
|
||||
SERVFAILs. Also fixed for UDP (but less likely).
|
||||
|
||||
28 November 2011: Wouter
|
||||
- Fix quartile time estimate, it was too low, (thanks Jan Komissar).
|
||||
- iana ports updated.
|
||||
|
||||
11 November 2011: Wouter
|
||||
- Makefile compat with SunOS make, BSD make and GNU make.
|
||||
- iana ports updated.
|
||||
|
||||
10 November 2011: Wouter
|
||||
- Makefile changed for BSD make compatibility.
|
||||
|
||||
9 November 2011: Wouter
|
||||
- added unit test for SSL service and SSL-upstream.
|
||||
|
||||
8 November 2011: Wouter
|
||||
- can configure ssl service to one port number, and not on others.
|
||||
- fixup windows compile with ssl support.
|
||||
- Fix double free in unbound-host, reported by Steve Grubb.
|
||||
- iana portlist updated.
|
||||
|
||||
1 November 2011: Wouter
|
||||
- dns over ssl support as a client, ssl-upstream yes turns it on.
|
||||
It performs an SSL transaction for every DNS query (250 msec).
|
||||
- documentation for new options: ssl-upstream, ssl-service-key and
|
||||
ssl-service.pem.
|
||||
- iana portlist updated.
|
||||
- fix -flto detection on Lion for llvm-gcc.
|
||||
|
||||
31 October 2011: Wouter
|
||||
- dns over ssl support, ssl-service-pem and ssl-service-key files
|
||||
can be given and then TCP queries are serviced wrapped in SSL.
|
||||
|
||||
27 October 2011: Wouter
|
||||
- lame-ttl and lame-size options no longer exist, it is integrated
|
||||
with the host info. They are ignored (with verbose warning) if
|
||||
encountered to keep the config file backwards compatible.
|
||||
- fix iana-update for changing gzip compression of results.
|
||||
- fix export-all-symbols on OSX.
|
||||
|
||||
26 October 2011: Wouter
|
||||
- iana portlist updated.
|
||||
- Infra cache stores information about ping and lameness per IP, zone.
|
||||
This fixes bug #416.
|
||||
- fix iana_update target for gzipped file on iana site.
|
||||
|
||||
24 October 2011: Wouter
|
||||
- Fix resolve of partners.extranet.microsoft.com with a fix for the
|
||||
server selection for choosing out of a (particular) list of bad
|
||||
choices. (bug#415)
|
||||
- Fix make_new_space function so that the incoming query is not
|
||||
overwritten if a jostled out query causes a waiting query to be
|
||||
resumed that then fails and sends an error message. (Thanks to
|
||||
Matthew Lee).
|
||||
|
||||
21 October 2011: Wouter
|
||||
- fix --enable-allsymbols, fptr wlist is disabled on windows with this
|
||||
option enabled because of memory layout exe vs dll.
|
||||
|
||||
19 October 2011: Wouter
|
||||
- fix unbound-anchor for broken strptime on OSX lion, detected
|
||||
in configure.
|
||||
- Detect if GOST really works, openssl1.0 on OSX fails.
|
||||
- Implement ipv6%interface notation for scope_id usage.
|
||||
|
||||
17 October 2011: Wouter
|
||||
- better documentation for inform_super (Thanks Yang Zhe).
|
||||
|
||||
14 October 2011: Wouter
|
||||
- Fix for out-of-memory condition in libunbound (thanks
|
||||
Robert Fleischman).
|
||||
|
||||
13 October 2011: Wouter
|
||||
- Fix --enable-allsymbols, it depended on link specifics of the
|
||||
target platform, or fptr_wlist assertion failures could occur.
|
||||
|
||||
12 October 2011: Wouter
|
||||
- updated contrib/unbound_munin_ to family=auto so that it works with
|
||||
munin-node-configure automatically (if installed as
|
||||
/usr/local/share/munin/plugins/unbound_munin_ ).
|
||||
|
||||
27 September 2011: Wouter
|
||||
- unbound.exe -w windows option for start and stop service.
|
||||
|
||||
23 September 2011: Wouter
|
||||
- TCP-upstream calculates tcp-ping so server selection works if there
|
||||
are alternatives.
|
||||
|
||||
20 September 2011: Wouter
|
||||
- Fix classification of NS set in answer section, where there is a
|
||||
parent-child server, and the answer has the AA flag for dir.slb.com.
|
||||
Thanks to Amanda Constant from Secure64.
|
||||
|
||||
16 September 2011: Wouter
|
||||
- fix bug #408: accept patch from Steve Snyder that comments out
|
||||
unused functions in lookup3.c.
|
||||
- iana portlist updated.
|
||||
- fix EDNS1480 change memleak and TCP fallback.
|
||||
- fix various compiler warnings (reported by Paul Wouters).
|
||||
- max sent count. EDNS1480 only for rtt < 5000. No promiscuous
|
||||
fetch if sentcount > 3, stop query if sentcount > 16. Count is
|
||||
reset when referral or CNAME happens. This makes unbound better
|
||||
at managing large NS sets, they are explored when there is continued
|
||||
interest (in the form of queries).
|
||||
|
||||
15 September 2011: Wouter
|
||||
- release 1.4.13.
|
||||
- trunk contains 1.4.14 in development.
|
||||
- Unbound probes at EDNS1480 if there an EDNS0 timeout.
|
||||
|
||||
12 September 2011: Wouter
|
||||
- Reverted dns EDNS backoff fix, it did not help and needs
|
||||
fragmentation fixes instead.
|
||||
|
||||
+32
-23
@@ -12,31 +12,44 @@ Big Features
|
||||
Recursive service.
|
||||
Caching service.
|
||||
Forwarding and stub zones.
|
||||
No authoritative service.
|
||||
Very limited authoritative service.
|
||||
DNSSEC Validation options.
|
||||
EDNS0, NSEC3, Unknown-RR-types.
|
||||
|
||||
EDNS0, NSEC3, IPv6, DNAME, Unknown-RR-types.
|
||||
RSASHA256, GOST, ECDSA, SHA384 DNSSEC algorithms.
|
||||
|
||||
Details
|
||||
-------
|
||||
Processing support
|
||||
RFC 1034-1035: as a recursive, caching server. Not authoritative.
|
||||
including CNAMEs, referrals, wildcards, classes, ...
|
||||
AAAA type, and IP6 dual stack support.
|
||||
type ANY queries are supported, class ANY queries are supported.
|
||||
RFC 4033-4035: as a validating caching server (unbound daemon).
|
||||
as a validating stub (libunbound).
|
||||
RFC 1918.
|
||||
RFC 2181: completely, including the trust model, keeping rrsets together.
|
||||
RFC 2672: DNAME support.
|
||||
RFC 3597: Unknown RR type support.
|
||||
RFC 2671: EDNS0 support, default advertisement 4Kb size.
|
||||
RFC 5155: NSEC3, NSEC3PARAM types
|
||||
AAAA type. and IP6 dual stack support.
|
||||
type ANY queries are supported.
|
||||
RFC 2308: TTL directive, and the rest of the RFC too.
|
||||
RFC 4592: wildcards.
|
||||
|
||||
RFC 1995, 1996, 2136: not authoritative, so no AXFR, IXFR, NOTIFY or
|
||||
dynamic update services are appropriate.
|
||||
RFC 2181: completely, including the trust model, keeping rrsets together.
|
||||
RFC 2308: TTL directive, and the rest of the RFC too.
|
||||
RFC 2671: EDNS0 support, default advertisement 4Kb size.
|
||||
RFC 2672: DNAME support.
|
||||
RFC 3597: Unknown RR type support.
|
||||
RFC 4343: case insensitive handling of domain names.
|
||||
RFC 4509: SHA256 DS hash.
|
||||
RFC 4592: wildcards.
|
||||
RFC 4697: No DNS Resolution Misbehavior.
|
||||
RFC 5011: update of trust anchors with timers.
|
||||
RFC 5155: NSEC3, NSEC3PARAM types
|
||||
RFC 5358: reflectors-are-evil: access control list for recursive
|
||||
service. In fact for all DNS service so cache snooping is halted.
|
||||
RFC 5452: forgery resilience. all recommendations followed.
|
||||
RFC 5702: RSASHA256 signature algorithm.
|
||||
RFC 5933: GOST signature algorithm.
|
||||
RFC 6303: default local zones.
|
||||
It is possible to block zones or return an address for localhost.
|
||||
This is a very limited authoritative service. Defaults as in draft.
|
||||
RFC 6604: xNAME RCODE and status bits.
|
||||
RFC 6605: ECDSA signature algorithm, SHA384 DS hash.
|
||||
|
||||
chroot and drop-root-privileges support, default enabled in config file.
|
||||
|
||||
@@ -44,27 +57,23 @@ AD bit in query can be used to request AD bit in response (w/o using DO bit).
|
||||
CD bit in query can be used to request bogus data.
|
||||
UDP and TCP service is provided downstream.
|
||||
UDP and TCP are used to request from upstream servers.
|
||||
SSL wrapped TCP service can be used upstream and provided downstream.
|
||||
Multiple queries can be made over a TCP stream.
|
||||
|
||||
No TSIG support at this time.
|
||||
No SIG0 support at this time.
|
||||
No dTLS support at this time.
|
||||
This is not a DNS statistics package, but some operationally useful
|
||||
values are provided.
|
||||
TXT RRs from the Chaos class (id.server, hostname.bind, ...) supported.
|
||||
values are provided via unbound-control stats.
|
||||
TXT RRs from the Chaos class (id.server, hostname.bind, ...) are supported.
|
||||
|
||||
draft-forgery-resilience: all recommendations followed.
|
||||
draft-0x20: experimental implementation (incomplete).
|
||||
implements bitwise echo of the query to support downstream 0x20.
|
||||
draft-ietf-dnsop-default-local-zones is fully supported (-04).
|
||||
It is possible to block zones or return an address for localhost.
|
||||
This is a very limited authoritative service. Defaults as in draft.
|
||||
draft-0x20: implemented, use caps-for-id option to enable use.
|
||||
Also implements bitwise echo of the query to support downstream 0x20.
|
||||
draft-ietf-dnsop-resolver-priming(-00): can prime and can fallback to
|
||||
a safety belt list.
|
||||
draft-ietf-dnsop-dnssec-trust-anchor(-01): DS records can be configured
|
||||
as trust anchors. Also DNSKEYs are allowed, by the way.
|
||||
draft-ietf-dnsop-reflectors-are-evil: access control list for recursive
|
||||
service. In fact for all DNS service so cache snooping is halted.
|
||||
draft-ietf-dnsext-dnssec-bis-updates: supported.
|
||||
|
||||
Record type syntax support, extensive, from lib ldns.
|
||||
For these types only syntax and parsing support is needed.
|
||||
|
||||
@@ -16,7 +16,6 @@ This software is under BSD license, see LICENSE for details.
|
||||
(optional) can use builtin alternative instead.
|
||||
|
||||
* Make and install: ./configure; make; make install
|
||||
* Use GNU make; default on linux, often called 'gmake' on BSD and Solaris.
|
||||
* --with-ldns=/path/to/ldns
|
||||
It will dynamically link against it.
|
||||
* --with-libevent=/path/to/libevent
|
||||
|
||||
+24
-8
@@ -123,24 +123,18 @@ server:
|
||||
# cache. Items are not cached for longer. In seconds.
|
||||
# cache-max-ttl: 86400
|
||||
|
||||
# the time to live (TTL) value for cached roundtrip times and
|
||||
# the time to live (TTL) value for cached roundtrip times, lameness and
|
||||
# EDNS version information for hosts. In seconds.
|
||||
# infra-host-ttl: 900
|
||||
|
||||
# the time to live (TTL) value for cached lame delegations. In sec.
|
||||
# infra-lame-ttl: 900
|
||||
|
||||
# the number of slabs to use for the Infrastructure cache.
|
||||
# the number of slabs must be a power of 2.
|
||||
# more slabs reduce lock contention, but fragment memory usage.
|
||||
# infra-cache-slabs: 4
|
||||
|
||||
# the maximum number of hosts that are cached (roundtrip times, EDNS).
|
||||
# the maximum number of hosts that are cached (roundtrip, EDNS, lame).
|
||||
# infra-cache-numhosts: 10000
|
||||
|
||||
# the maximum size of the lame zones cached per host. in bytes.
|
||||
# infra-cache-lame-size: 10k
|
||||
|
||||
# Enable IPv4, "yes" or "no".
|
||||
# do-ip4: yes
|
||||
|
||||
@@ -315,6 +309,13 @@ server:
|
||||
# if yes, perform key lookups adjacent to normal lookups.
|
||||
# prefetch-key: no
|
||||
|
||||
# if yes, Unbound rotates RRSet order in response.
|
||||
# rrset-roundrobin: no
|
||||
|
||||
# if yes, Unbound doesn't insert authority/additional sections
|
||||
# into response messages when those sections are not required.
|
||||
# minimal-responses: no
|
||||
|
||||
# module configuration of the server. A string with identifiers
|
||||
# separated by spaces. "iterator" or "validator iterator"
|
||||
# module-config: "validator iterator"
|
||||
@@ -459,6 +460,17 @@ server:
|
||||
# you need to do the reverse notation yourself.
|
||||
# local-data-ptr: "192.0.2.3 www.example.com"
|
||||
|
||||
# service clients over SSL (on the TCP sockets), with plain DNS inside
|
||||
# the SSL stream. Give the certificate to use and private key.
|
||||
# default is "" (disabled). requires restart to take effect.
|
||||
# ssl-service-key: "path/to/privatekeyfile.key"
|
||||
# ssl-service-pem: "path/to/publiccertfile.pem"
|
||||
# ssl-port: 443
|
||||
|
||||
# request upstream over SSL (with plain DNS inside the SSL stream).
|
||||
# Default is no. Can be turned on and off with unbound-control.
|
||||
# ssl-upstream: no
|
||||
|
||||
# Python config section. To enable:
|
||||
# o use --with-pythonmodule to configure before compiling.
|
||||
# o list python in the module-config string (above) to enable.
|
||||
@@ -498,10 +510,12 @@ remote-control:
|
||||
# 'example.org' go to the given list of nameservers. list zero or more
|
||||
# nameservers by hostname or by ipaddress. If you set stub-prime to yes,
|
||||
# the list is treated as priming hints (default is no).
|
||||
# With stub-first yes, it attempts without the stub if it fails.
|
||||
# stub-zone:
|
||||
# name: "example.com"
|
||||
# stub-addr: 192.0.2.68
|
||||
# stub-prime: no
|
||||
# stub-first: no
|
||||
# stub-zone:
|
||||
# name: "example.org"
|
||||
# stub-host: ns.example.com.
|
||||
@@ -511,10 +525,12 @@ remote-control:
|
||||
# 'example.org' go to the given list of servers. These servers have to handle
|
||||
# recursion to other nameservers. List zero or more nameservers by hostname
|
||||
# or by ipaddress. Use an entry with name "." to forward all queries.
|
||||
# If you enable forward-first, it attempts without the forward if it fails.
|
||||
# forward-zone:
|
||||
# name: "example.com"
|
||||
# forward-addr: 192.0.2.68
|
||||
# forward-addr: 192.0.2.73@5355 # forward to port 5355.
|
||||
# forward-first: no
|
||||
# forward-zone:
|
||||
# name: "example.org"
|
||||
# forward-host: fwd.example.com
|
||||
|
||||
@@ -127,6 +127,9 @@ Remove all information at or below the name from the cache.
|
||||
The rrsets and key entries are removed so that new lookups will be performed.
|
||||
This needs to walk and inspect the entire cache, and is a slow operation.
|
||||
.TP
|
||||
.B flush_bogus
|
||||
Remove all bogus data from the cache.
|
||||
.TP
|
||||
.B flush_stats
|
||||
Reset statistics to zero.
|
||||
.TP
|
||||
@@ -164,7 +167,7 @@ harden\-glue, harden\-dnssec\-stripped, harden\-below\-nxdomain,
|
||||
harden\-referral\-path, prefetch, prefetch\-key, log\-queries,
|
||||
hide\-identity, hide\-version, identity, version, val\-log\-level,
|
||||
val\-log\-squelch, ignore\-cd\-flag, add\-holddown, del\-holddown,
|
||||
keep\-missing, tcp\-upstream.
|
||||
keep\-missing, tcp\-upstream, ssl\-upstream.
|
||||
.TP
|
||||
.B get_option \fIopt
|
||||
Get the value of the option. Give the option name without a trailing ':'.
|
||||
@@ -190,6 +193,27 @@ List the local zones in use. These are printed one per line with zone type.
|
||||
.B list_local_data
|
||||
List the local data RRs in use. The resource records are printed.
|
||||
.TP
|
||||
.B forward_add \fR[\fI+i\fR] \fIzone addr ...
|
||||
Add a new forward zone to running unbound. With +i option also adds a
|
||||
\fIdomain\-insecure\fR for the zone (so it can resolve insecurely if you have
|
||||
a DNSSEC root trust anchor configured for other names).
|
||||
The addr can be IP4, IP6 or nameserver names, like \fIforward-zone\fR config
|
||||
in unbound.conf.
|
||||
.TP
|
||||
.B forward_remove \fR[\fI+i\fR] \fIzone
|
||||
Remove a forward zone from running unbound. The +i also removes a
|
||||
\fIdomain\-insecure\fR for the zone.
|
||||
.TP
|
||||
.B stub_add \fR[\fI+ip\fR] \fIzone addr ...
|
||||
Add a new stub zone to running unbound. With +i option also adds a
|
||||
\fIdomain\-insecure\fR for the zone. With +p the stub zone is set to prime,
|
||||
without it it is set to notprime. The addr can be IP4, IP6 or nameserver
|
||||
names, like the \fIstub-zone\fR config in unbound.conf.
|
||||
.TP
|
||||
.B stub_remove \fR[\fI+i\fR] \fIzone
|
||||
Remove a stub zone from running unbound. The +i also removes a
|
||||
\fIdomain\-insecure\fR for the zone.
|
||||
.TP
|
||||
.B forward \fR[\fIoff\fR | \fIaddr ...\fR ]
|
||||
Setup forwarding mode. Configures if the server should ask other upstream
|
||||
nameservers, should go to the internet root nameservers itself, or show
|
||||
|
||||
+45
-11
@@ -176,7 +176,7 @@ to 0, or if do_tcp is "no", no TCP queries from clients are accepted.
|
||||
Number of bytes size to advertise as the EDNS reassembly buffer size.
|
||||
This is the value put into datagrams over UDP towards peers. The actual
|
||||
buffer size is determined by msg\-buffer\-size (both for TCP and UDP). Do
|
||||
not set lower than that value. Default is 4096 which is RFC recommended.
|
||||
not set higher than that value. Default is 4096 which is RFC recommended.
|
||||
If you have fragmentation reassembly problems, usually seen as timeouts,
|
||||
then a value of 1480 can fix it. Setting to 512 bypasses even the most
|
||||
stringent path MTU problems, but is seen as extreme, since the amount
|
||||
@@ -269,10 +269,7 @@ the data in the cache does not match up with the actual data any more.
|
||||
.TP
|
||||
.B infra\-host\-ttl: \fI<seconds>
|
||||
Time to live for entries in the host cache. The host cache contains
|
||||
roundtrip timing and EDNS support information. Default is 900.
|
||||
.TP
|
||||
.B infra\-lame\-ttl: \fI<seconds>
|
||||
The time to live when a delegation is discovered to be lame. Default is 900.
|
||||
roundtrip timing, lameness and EDNS support information. Default is 900.
|
||||
.TP
|
||||
.B infra\-cache\-slabs: \fI<number>
|
||||
Number of slabs in the infrastructure cache. Slabs reduce lock contention
|
||||
@@ -281,11 +278,6 @@ by threads. Must be set to a power of 2.
|
||||
.B infra\-cache\-numhosts: \fI<number>
|
||||
Number of hosts for which information is cached. Default is 10000.
|
||||
.TP
|
||||
.B infra\-cache\-lame\-size: \fI<number>
|
||||
Number of bytes that the lameness cache per host is allowed to use. Default
|
||||
is 10 kb, which gives maximum storage for a couple score zones, depending on
|
||||
the lame zone name lengths.
|
||||
.TP
|
||||
.B do\-ip4: \fI<yes or no>
|
||||
Enable or disable whether ip4 queries are answered or issued. Default is yes.
|
||||
.TP
|
||||
@@ -304,6 +296,29 @@ Enable or disable whether TCP queries are answered or issued. Default is yes.
|
||||
Enable or disable whether the upstream queries use TCP only for transport.
|
||||
Default is no. Useful in tunneling scenarios.
|
||||
.TP
|
||||
.B ssl\-upstream: \fI<yes or no>
|
||||
Enabled or disable whether the upstream queries use SSL only for transport.
|
||||
Default is no. Useful in tunneling scenarios. The SSL contains plain DNS in
|
||||
TCP wireformat. The other server must support this (see \fBssl\-service\-key\fR).
|
||||
.TP
|
||||
.B ssl\-service-key: \fI<file>
|
||||
If enabled, the server provider SSL service on its TCP sockets. The clients
|
||||
have to use ssl\-upstream: yes. The file is the private key for the TLS
|
||||
session. The public certificate is in the ssl\-service\-pem file. Default
|
||||
is "", turned off. Requires a restart (a reload is not enough) if changed,
|
||||
because the private key is read while root permissions are held and before
|
||||
chroot (if any). Normal DNS TCP service is not provided and gives errors,
|
||||
this service is best run with a different \fBport:\fR config or \fI@port\fR
|
||||
suffixes in the \fBinterface\fR config.
|
||||
.TP
|
||||
.B ssl\-service\-pem: \fI<file>
|
||||
The public key certificate pem file for the ssl service. Default is "",
|
||||
turned off.
|
||||
.TP
|
||||
.B ssl\-port: \fI<number>
|
||||
The port number on which to provide TCP SSL service, default 443, only
|
||||
interfaces configured with that port number as @number get the SSL service.
|
||||
.TP
|
||||
.B do\-daemonize: \fI<yes or no>
|
||||
Enable or disable whether the unbound server forks into the background as
|
||||
a daemon. Default is yes.
|
||||
@@ -555,6 +570,18 @@ If yes, fetch the DNSKEYs earlier in the validation process, when a DS
|
||||
record is encountered. This lowers the latency of requests. It does use
|
||||
a little more CPU. Also if the cache is set to 0, it is no use. Default is no.
|
||||
.TP
|
||||
.B rrset-roundrobin: \fI<yes or no>
|
||||
If yes, Unbound rotates RRSet order in response (the random number is taken
|
||||
from the query ID, for speed and thread safety). Default is no.
|
||||
.TP
|
||||
.B minimal-responses: \fI<yes or no>
|
||||
If yes, Unbound doesn't insert authority/additional sections into response
|
||||
messages when those sections are not required. This reduces response
|
||||
size significantly, and may avoid TCP fallback for some responses.
|
||||
This may cause a slight speedup. The default is no, because the DNS
|
||||
protocol RFCs mandate these sections, and the additional content could
|
||||
be of use and save roundtrips for clients.
|
||||
.TP
|
||||
.B module\-config: \fI<"module names">
|
||||
Module configuration, a list of module names separated by spaces, surround
|
||||
the string with quotes (""). The modules can be validator, iterator.
|
||||
@@ -964,6 +991,10 @@ This option is by default off. If enabled it performs NS set priming,
|
||||
which is similar to root hints, where it starts using the list of nameservers
|
||||
currently published by the zone. Thus, if the hint list is slightly outdated,
|
||||
the resolver picks up a correct list online.
|
||||
.TP
|
||||
.B stub\-first: \fI<yes or no>
|
||||
If enabled, a query is attempted without the stub clause if it fails.
|
||||
The default is no.
|
||||
.SS "Forward Zone Options"
|
||||
.LP
|
||||
There may be multiple
|
||||
@@ -988,6 +1019,10 @@ Name of server to forward to. Is itself resolved before it is used.
|
||||
.B forward\-addr: \fI<IP address>
|
||||
IP address of server to forward to. Can be IP 4 or IP 6.
|
||||
To use a nondefault port for DNS communication append '@' with the port number.
|
||||
.TP
|
||||
.B forward\-first: \fI<yes or no>
|
||||
If enabled, a query is attempted without the forward clause if it fails.
|
||||
The default is no.
|
||||
.SS "Python Module Options"
|
||||
.LP
|
||||
The
|
||||
@@ -1023,7 +1058,6 @@ server:
|
||||
rrset\-cache\-slabs: 1
|
||||
infra\-cache\-numhosts: 200
|
||||
infra\-cache\-slabs: 1
|
||||
infra\-cache\-lame\-size: 1k
|
||||
key\-cache\-size: 100k
|
||||
key\-cache\-slabs: 1
|
||||
neg\-cache\-size: 10k
|
||||
|
||||
+147
-1
@@ -90,6 +90,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
|
||||
int
|
||||
delegpt_set_name(struct delegpt* dp, struct regional* region, uint8_t* name)
|
||||
{
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
dp->namelabs = dname_count_size_labels(name, &dp->namelen);
|
||||
dp->name = regional_alloc_init(region, name, dp->namelen);
|
||||
return dp->name != 0;
|
||||
@@ -102,6 +103,7 @@ delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name,
|
||||
struct delegpt_ns* ns;
|
||||
size_t len;
|
||||
(void)dname_count_size_labels(name, &len);
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
/* slow check for duplicates to avoid counting failures when
|
||||
* adding the same server as a dependency twice */
|
||||
if(delegpt_find_ns(dp, name, len))
|
||||
@@ -120,7 +122,7 @@ delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name,
|
||||
ns->lame = (uint8_t)lame;
|
||||
ns->done_pside4 = 0;
|
||||
ns->done_pside6 = 0;
|
||||
return 1;
|
||||
return ns->name != 0;
|
||||
}
|
||||
|
||||
struct delegpt_ns*
|
||||
@@ -157,6 +159,7 @@ delegpt_add_target(struct delegpt* dp, struct regional* region,
|
||||
socklen_t addrlen, int bogus, int lame)
|
||||
{
|
||||
struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen);
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
if(!ns) {
|
||||
/* ignore it */
|
||||
return 1;
|
||||
@@ -177,6 +180,7 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region,
|
||||
int lame)
|
||||
{
|
||||
struct delegpt_addr* a;
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
/* check for duplicates */
|
||||
if((a = delegpt_find_addr(dp, addr, addrlen))) {
|
||||
if(bogus)
|
||||
@@ -377,6 +381,7 @@ delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region,
|
||||
struct packed_rrset_data* nsdata = (struct packed_rrset_data*)
|
||||
ns_rrset->entry.data;
|
||||
size_t i;
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
if(nsdata->security == sec_status_bogus)
|
||||
dp->bogus = 1;
|
||||
for(i=0; i<nsdata->count; i++) {
|
||||
@@ -399,6 +404,7 @@ delegpt_add_rrset_A(struct delegpt* dp, struct regional* region,
|
||||
size_t i;
|
||||
struct sockaddr_in sa;
|
||||
socklen_t len = (socklen_t)sizeof(sa);
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
memset(&sa, 0, len);
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
|
||||
@@ -422,6 +428,7 @@ delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region,
|
||||
size_t i;
|
||||
struct sockaddr_in6 sa;
|
||||
socklen_t len = (socklen_t)sizeof(sa);
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
memset(&sa, 0, len);
|
||||
sa.sin6_family = AF_INET6;
|
||||
sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
|
||||
@@ -492,3 +499,142 @@ void delegpt_no_ipv4(struct delegpt* dp)
|
||||
ns->resolved = 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct delegpt* delegpt_create_mlc(uint8_t* name)
|
||||
{
|
||||
struct delegpt* dp=(struct delegpt*)calloc(1, sizeof(*dp));
|
||||
if(!dp)
|
||||
return NULL;
|
||||
dp->dp_type_mlc = 1;
|
||||
if(name) {
|
||||
dp->namelabs = dname_count_size_labels(name, &dp->namelen);
|
||||
dp->name = memdup(name, dp->namelen);
|
||||
if(!dp->name) {
|
||||
free(dp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
void delegpt_free_mlc(struct delegpt* dp)
|
||||
{
|
||||
struct delegpt_ns* n, *nn;
|
||||
struct delegpt_addr* a, *na;
|
||||
if(!dp) return;
|
||||
log_assert(dp->dp_type_mlc);
|
||||
n = dp->nslist;
|
||||
while(n) {
|
||||
nn = n->next;
|
||||
free(n->name);
|
||||
free(n);
|
||||
n = nn;
|
||||
}
|
||||
a = dp->target_list;
|
||||
while(a) {
|
||||
na = a->next_target;
|
||||
free(a);
|
||||
a = na;
|
||||
}
|
||||
free(dp->name);
|
||||
free(dp);
|
||||
}
|
||||
|
||||
int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name)
|
||||
{
|
||||
log_assert(dp->dp_type_mlc);
|
||||
dp->namelabs = dname_count_size_labels(name, &dp->namelen);
|
||||
dp->name = memdup(name, dp->namelen);
|
||||
return (dp->name != NULL);
|
||||
}
|
||||
|
||||
int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, int lame)
|
||||
{
|
||||
struct delegpt_ns* ns;
|
||||
size_t len;
|
||||
(void)dname_count_size_labels(name, &len);
|
||||
log_assert(dp->dp_type_mlc);
|
||||
/* slow check for duplicates to avoid counting failures when
|
||||
* adding the same server as a dependency twice */
|
||||
if(delegpt_find_ns(dp, name, len))
|
||||
return 1;
|
||||
ns = (struct delegpt_ns*)malloc(sizeof(struct delegpt_ns));
|
||||
if(!ns)
|
||||
return 0;
|
||||
ns->namelen = len;
|
||||
ns->name = memdup(name, ns->namelen);
|
||||
if(!ns->name) {
|
||||
free(ns);
|
||||
return 0;
|
||||
}
|
||||
ns->next = dp->nslist;
|
||||
dp->nslist = ns;
|
||||
ns->resolved = 0;
|
||||
ns->got4 = 0;
|
||||
ns->got6 = 0;
|
||||
ns->lame = (uint8_t)lame;
|
||||
ns->done_pside4 = 0;
|
||||
ns->done_pside6 = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int bogus, int lame)
|
||||
{
|
||||
struct delegpt_addr* a;
|
||||
log_assert(dp->dp_type_mlc);
|
||||
/* check for duplicates */
|
||||
if((a = delegpt_find_addr(dp, addr, addrlen))) {
|
||||
if(bogus)
|
||||
a->bogus = bogus;
|
||||
if(!lame)
|
||||
a->lame = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
a = (struct delegpt_addr*)malloc(sizeof(struct delegpt_addr));
|
||||
if(!a)
|
||||
return 0;
|
||||
a->next_target = dp->target_list;
|
||||
dp->target_list = a;
|
||||
a->next_result = 0;
|
||||
a->next_usable = dp->usable_list;
|
||||
dp->usable_list = a;
|
||||
memcpy(&a->addr, addr, addrlen);
|
||||
a->addrlen = addrlen;
|
||||
a->attempts = 0;
|
||||
a->bogus = bogus;
|
||||
a->lame = lame;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int lame)
|
||||
{
|
||||
struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen);
|
||||
log_assert(dp->dp_type_mlc);
|
||||
if(!ns) {
|
||||
/* ignore it */
|
||||
return 1;
|
||||
}
|
||||
if(!lame) {
|
||||
if(addr_is_ip6(addr, addrlen))
|
||||
ns->got6 = 1;
|
||||
else ns->got4 = 1;
|
||||
if(ns->got4 && ns->got6)
|
||||
ns->resolved = 1;
|
||||
}
|
||||
return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame);
|
||||
}
|
||||
|
||||
size_t delegpt_get_mem(struct delegpt* dp)
|
||||
{
|
||||
struct delegpt_ns* ns;
|
||||
size_t s;
|
||||
if(!dp) return 0;
|
||||
s = sizeof(*dp) + dp->namelen +
|
||||
delegpt_count_targets(dp)*sizeof(struct delegpt_addr);
|
||||
for(ns=dp->nslist; ns; ns=ns->next)
|
||||
s += sizeof(*ns)+ns->namelen;
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -79,6 +79,8 @@ struct delegpt {
|
||||
* Also true if the delegationpoint was created from a delegation
|
||||
* message and thus contains the parent-side-info already. */
|
||||
uint8_t has_parent_side_NS;
|
||||
/** for assertions on type of delegpt */
|
||||
uint8_t dp_type_mlc;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -346,4 +348,64 @@ void delegpt_no_ipv6(struct delegpt* dp);
|
||||
*/
|
||||
void delegpt_no_ipv4(struct delegpt* dp);
|
||||
|
||||
/**
|
||||
* create malloced delegation point, with the given name
|
||||
* @param name: uncompressed wireformat of degegpt name.
|
||||
* @return NULL on alloc failure
|
||||
*/
|
||||
struct delegpt* delegpt_create_mlc(uint8_t* name);
|
||||
|
||||
/**
|
||||
* free malloced delegation point.
|
||||
* @param dp: must have been created with delegpt_create_mlc, free'd.
|
||||
*/
|
||||
void delegpt_free_mlc(struct delegpt* dp);
|
||||
|
||||
/**
|
||||
* Set name of delegation point.
|
||||
* @param dp: delegation point. malloced.
|
||||
* @param name: name to use.
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name);
|
||||
|
||||
/**
|
||||
* add a name to malloced delegation point.
|
||||
* @param dp: must have been created with delegpt_create_mlc.
|
||||
* @param name: the name to add.
|
||||
* @param lame: the name is lame, disprefer.
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, int lame);
|
||||
|
||||
/**
|
||||
* add an address to a malloced delegation point.
|
||||
* @param dp: must have been created with delegpt_create_mlc.
|
||||
* @param addr: the address.
|
||||
* @param addrlen: the length of addr.
|
||||
* @param bogus: if address is bogus.
|
||||
* @param lame: if address is lame.
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int bogus, int lame);
|
||||
|
||||
/**
|
||||
* Add target address to the delegation point.
|
||||
* @param dp: must have been created with delegpt_create_mlc.
|
||||
* @param name: name for which target was found (must be in nslist).
|
||||
* This name is marked resolved.
|
||||
* @param namelen: length of name.
|
||||
* @param addr: the address.
|
||||
* @param addrlen: the length of addr.
|
||||
* @param bogus: security status for the address, pass true if bogus.
|
||||
* @param lame: address is lame.
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int lame);
|
||||
|
||||
/** get memory in use by dp */
|
||||
size_t delegpt_get_mem(struct delegpt* dp);
|
||||
|
||||
#endif /* ITERATOR_ITER_DELEGPT_H */
|
||||
|
||||
+129
-61
@@ -40,12 +40,11 @@
|
||||
* Keep track of forward zones and config settings.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ldns/rdata.h"
|
||||
#include "ldns/dname.h"
|
||||
#include "ldns/rr.h"
|
||||
#include <ldns/rdata.h>
|
||||
#include <ldns/dname.h>
|
||||
#include <ldns/rr.h>
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_delegpt.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
@@ -73,21 +72,36 @@ forwards_create(void)
|
||||
sizeof(struct iter_forwards));
|
||||
if(!fwd)
|
||||
return NULL;
|
||||
fwd->region = regional_create();
|
||||
if(!fwd->region) {
|
||||
forwards_delete(fwd);
|
||||
return NULL;
|
||||
}
|
||||
return fwd;
|
||||
}
|
||||
|
||||
static void fwd_zone_free(struct iter_forward_zone* n)
|
||||
{
|
||||
if(!n) return;
|
||||
delegpt_free_mlc(n->dp);
|
||||
free(n->name);
|
||||
free(n);
|
||||
}
|
||||
|
||||
static void delfwdnode(rbnode_t* n, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct iter_forward_zone* node = (struct iter_forward_zone*)n;
|
||||
fwd_zone_free(node);
|
||||
}
|
||||
|
||||
static void fwd_del_tree(struct iter_forwards* fwd)
|
||||
{
|
||||
if(fwd->tree)
|
||||
traverse_postorder(fwd->tree, &delfwdnode, NULL);
|
||||
free(fwd->tree);
|
||||
}
|
||||
|
||||
void
|
||||
forwards_delete(struct iter_forwards* fwd)
|
||||
{
|
||||
if(!fwd)
|
||||
return;
|
||||
regional_destroy(fwd->region);
|
||||
free(fwd->tree);
|
||||
fwd_del_tree(fwd);
|
||||
free(fwd);
|
||||
}
|
||||
|
||||
@@ -96,20 +110,28 @@ static int
|
||||
forwards_insert_data(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
|
||||
size_t nmlen, int nmlabs, struct delegpt* dp)
|
||||
{
|
||||
struct iter_forward_zone* node = regional_alloc(fwd->region,
|
||||
struct iter_forward_zone* node = (struct iter_forward_zone*)malloc(
|
||||
sizeof(struct iter_forward_zone));
|
||||
if(!node)
|
||||
if(!node) {
|
||||
delegpt_free_mlc(dp);
|
||||
return 0;
|
||||
}
|
||||
node->node.key = node;
|
||||
node->dclass = c;
|
||||
node->name = regional_alloc_init(fwd->region, nm, nmlen);
|
||||
if(!node->name)
|
||||
node->name = memdup(nm, nmlen);
|
||||
if(!node->name) {
|
||||
delegpt_free_mlc(dp);
|
||||
free(node);
|
||||
return 0;
|
||||
}
|
||||
node->namelen = nmlen;
|
||||
node->namelabs = nmlabs;
|
||||
node->dp = dp;
|
||||
if(!rbtree_insert(fwd->tree, &node->node)) {
|
||||
log_err("duplicate forward zone ignored.");
|
||||
delegpt_free_mlc(dp);
|
||||
free(node->name);
|
||||
free(node);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -152,33 +174,32 @@ fwd_init_parents(struct iter_forwards* fwd)
|
||||
}
|
||||
|
||||
/** set zone name */
|
||||
static int
|
||||
read_fwds_name(struct iter_forwards* fwd, struct config_stub* s,
|
||||
struct delegpt* dp)
|
||||
static struct delegpt*
|
||||
read_fwds_name(struct config_stub* s)
|
||||
{
|
||||
struct delegpt* dp;
|
||||
ldns_rdf* rdf;
|
||||
if(!s->name) {
|
||||
log_err("forward zone without a name (use name \".\" to forward everything)");
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
rdf = ldns_dname_new_frm_str(s->name);
|
||||
if(!rdf) {
|
||||
log_err("cannot parse forward zone name %s", s->name);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
if(!delegpt_set_name(dp, fwd->region, ldns_rdf_data(rdf))) {
|
||||
if(!(dp=delegpt_create_mlc(ldns_rdf_data(rdf)))) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
ldns_rdf_deep_free(rdf);
|
||||
return 1;
|
||||
return dp;
|
||||
}
|
||||
|
||||
/** set fwd host names */
|
||||
static int
|
||||
read_fwds_host(struct iter_forwards* fwd, struct config_stub* s,
|
||||
struct delegpt* dp)
|
||||
read_fwds_host(struct config_stub* s, struct delegpt* dp)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
ldns_rdf* rdf;
|
||||
@@ -190,7 +211,7 @@ read_fwds_host(struct iter_forwards* fwd, struct config_stub* s,
|
||||
s->name, p->str);
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_add_ns(dp, fwd->region, ldns_rdf_data(rdf), 0)) {
|
||||
if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(rdf), 0)) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
@@ -202,8 +223,7 @@ read_fwds_host(struct iter_forwards* fwd, struct config_stub* s,
|
||||
|
||||
/** set fwd server addresses */
|
||||
static int
|
||||
read_fwds_addr(struct iter_forwards* fwd, struct config_stub* s,
|
||||
struct delegpt* dp)
|
||||
read_fwds_addr(struct config_stub* s, struct delegpt* dp)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
struct sockaddr_storage addr;
|
||||
@@ -215,7 +235,7 @@ read_fwds_addr(struct iter_forwards* fwd, struct config_stub* s,
|
||||
s->name, p->str);
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_add_addr(dp, fwd->region, &addr, addrlen, 0, 0)) {
|
||||
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
@@ -229,22 +249,23 @@ read_forwards(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
{
|
||||
struct config_stub* s;
|
||||
for(s = cfg->forwards; s; s = s->next) {
|
||||
struct delegpt* dp = delegpt_create(fwd->region);
|
||||
if(!dp) {
|
||||
log_err("out of memory");
|
||||
struct delegpt* dp;
|
||||
if(!(dp=read_fwds_name(s)))
|
||||
return 0;
|
||||
if(!read_fwds_host(s, dp) || !read_fwds_addr(s, dp)) {
|
||||
delegpt_free_mlc(dp);
|
||||
return 0;
|
||||
}
|
||||
/* set flag that parent side NS information is included.
|
||||
* Asking a (higher up) server on the internet is not useful */
|
||||
dp->has_parent_side_NS = 1;
|
||||
if(!read_fwds_name(fwd, s, dp) ||
|
||||
!read_fwds_host(fwd, s, dp) ||
|
||||
!read_fwds_addr(fwd, s, dp))
|
||||
return 0;
|
||||
if(!forwards_insert(fwd, LDNS_RR_CLASS_IN, dp))
|
||||
return 0;
|
||||
/* the flag is turned off for 'forward-first' so that the
|
||||
* last resort will ask for parent-side NS record and thus
|
||||
* fallback to the internet name servers on a failure */
|
||||
dp->has_parent_side_NS = (uint8_t)!s->isfirst;
|
||||
verbose(VERB_QUERY, "Forward zone server list:");
|
||||
delegpt_log(VERB_QUERY, dp);
|
||||
if(!forwards_insert(fwd, LDNS_RR_CLASS_IN, dp))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -268,28 +289,35 @@ need_hole_insert(rbtree_t* tree, struct iter_forward_zone* zone)
|
||||
return 0; /* no forwards above, no holes needed */
|
||||
}
|
||||
|
||||
/** insert a stub hole (if necessary) for stub name */
|
||||
static int
|
||||
fwd_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||
{
|
||||
struct iter_forward_zone key;
|
||||
key.node.key = &key;
|
||||
key.dclass = c;
|
||||
key.name = nm;
|
||||
key.namelabs = dname_count_size_labels(key.name, &key.namelen);
|
||||
if(need_hole_insert(fwd->tree, &key)) {
|
||||
return forwards_insert_data(fwd, key.dclass, key.name,
|
||||
key.namelen, key.namelabs, NULL);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** make NULL entries for stubs */
|
||||
static int
|
||||
make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
{
|
||||
struct config_stub* s;
|
||||
struct iter_forward_zone key;
|
||||
key.node.key = &key;
|
||||
key.dclass = LDNS_RR_CLASS_IN;
|
||||
for(s = cfg->stubs; s; s = s->next) {
|
||||
ldns_rdf* rdf = ldns_dname_new_frm_str(s->name);
|
||||
if(!rdf) {
|
||||
log_err("cannot parse stub name '%s'", s->name);
|
||||
return 0;
|
||||
}
|
||||
key.name = ldns_rdf_data(rdf);
|
||||
key.namelabs = dname_count_size_labels(key.name, &key.namelen);
|
||||
if(!need_hole_insert(fwd->tree, &key)) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
continue;
|
||||
}
|
||||
if(!forwards_insert_data(fwd, key.dclass, key.name,
|
||||
key.namelen, key.namelabs, NULL)) {
|
||||
if(!fwd_add_stub_hole(fwd, LDNS_RR_CLASS_IN,
|
||||
ldns_rdf_data(rdf))) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
@@ -302,8 +330,7 @@ make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
int
|
||||
forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
{
|
||||
free(fwd->tree);
|
||||
regional_free_all(fwd->region);
|
||||
fwd_del_tree(fwd);
|
||||
fwd->tree = rbtree_create(fwd_cmp);
|
||||
if(!fwd->tree)
|
||||
return 0;
|
||||
@@ -411,15 +438,36 @@ forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass)
|
||||
size_t
|
||||
forwards_get_mem(struct iter_forwards* fwd)
|
||||
{
|
||||
struct iter_forward_zone* p;
|
||||
size_t s;
|
||||
if(!fwd)
|
||||
return 0;
|
||||
return sizeof(*fwd) + sizeof(*fwd->tree) +
|
||||
regional_get_mem(fwd->region);
|
||||
s = sizeof(*fwd) + sizeof(*fwd->tree);
|
||||
RBTREE_FOR(p, struct iter_forward_zone*, fwd->tree) {
|
||||
s += sizeof(*p) + p->namelen + delegpt_get_mem(p->dp);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static struct iter_forward_zone*
|
||||
fwd_zone_find(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||
{
|
||||
struct iter_forward_zone key;
|
||||
key.node.key = &key;
|
||||
key.dclass = c;
|
||||
key.name = nm;
|
||||
key.namelabs = dname_count_size_labels(nm, &key.namelen);
|
||||
return (struct iter_forward_zone*)rbtree_search(fwd->tree, &key);
|
||||
}
|
||||
|
||||
int
|
||||
forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
|
||||
{
|
||||
struct iter_forward_zone *z;
|
||||
if((z=fwd_zone_find(fwd, c, dp->name)) != NULL) {
|
||||
(void)rbtree_delete(fwd->tree, &z->node);
|
||||
fwd_zone_free(z);
|
||||
}
|
||||
if(!forwards_insert(fwd, c, dp))
|
||||
return 0;
|
||||
fwd_init_parents(fwd);
|
||||
@@ -429,14 +477,34 @@ forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
|
||||
void
|
||||
forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||
{
|
||||
struct iter_forward_zone key;
|
||||
key.node.key = &key;
|
||||
key.dclass = c;
|
||||
key.name = nm;
|
||||
key.namelabs = dname_count_size_labels(nm, &key.namelen);
|
||||
if(!rbtree_search(fwd->tree, &key))
|
||||
struct iter_forward_zone *z;
|
||||
if(!(z=fwd_zone_find(fwd, c, nm)))
|
||||
return; /* nothing to do */
|
||||
(void)rbtree_delete(fwd->tree, &key);
|
||||
(void)rbtree_delete(fwd->tree, &z->node);
|
||||
fwd_zone_free(z);
|
||||
fwd_init_parents(fwd);
|
||||
}
|
||||
|
||||
int
|
||||
forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||
{
|
||||
if(!fwd_add_stub_hole(fwd, c, nm)) {
|
||||
return 0;
|
||||
}
|
||||
fwd_init_parents(fwd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||
{
|
||||
struct iter_forward_zone *z;
|
||||
if(!(z=fwd_zone_find(fwd, c, nm)))
|
||||
return; /* nothing to do */
|
||||
if(z->dp != NULL)
|
||||
return; /* not a stub hole */
|
||||
(void)rbtree_delete(fwd->tree, &z->node);
|
||||
fwd_zone_free(z);
|
||||
fwd_init_parents(fwd);
|
||||
}
|
||||
|
||||
|
||||
+25
-9
@@ -45,14 +45,11 @@
|
||||
#include "util/rbtree.h"
|
||||
struct config_file;
|
||||
struct delegpt;
|
||||
struct regional;
|
||||
|
||||
/**
|
||||
* Iterator forward zones structure
|
||||
*/
|
||||
struct iter_forwards {
|
||||
/** regional where forward zone server addresses are allocated */
|
||||
struct regional* region;
|
||||
/**
|
||||
* Zones are stored in this tree. Sort order is specially chosen.
|
||||
* first sorted on qclass. Then on dname in nsec-like order, so that
|
||||
@@ -77,7 +74,9 @@ struct iter_forward_zone {
|
||||
int namelabs;
|
||||
/** delegation point with forward server information for this zone.
|
||||
* If NULL then this forward entry is used to indicate that a
|
||||
* stub-zone with the same name exists, and should be used. */
|
||||
* stub-zone with the same name exists, and should be used.
|
||||
* This delegation point is malloced.
|
||||
*/
|
||||
struct delegpt* dp;
|
||||
/** pointer to parent in tree (or NULL if none) */
|
||||
struct iter_forward_zone* parent;
|
||||
@@ -152,9 +151,7 @@ int fwd_cmp(const void* k1, const void* k2);
|
||||
* @param fwd: the forward data structure
|
||||
* @param c: class of zone
|
||||
* @param dp: delegation point with name and target nameservers for new
|
||||
* forward zone. This delegation point and all its data must be
|
||||
* malloced in the fwd->region. (then it is freed when the fwd is
|
||||
* deleted).
|
||||
* forward zone. malloced.
|
||||
* @return false on failure (out of memory);
|
||||
*/
|
||||
int forwards_add_zone(struct iter_forwards* fwd, uint16_t c,
|
||||
@@ -162,12 +159,31 @@ int forwards_add_zone(struct iter_forwards* fwd, uint16_t c,
|
||||
|
||||
/**
|
||||
* Remove zone from forward structure. For external use since it
|
||||
* recalcs the tree parents. Does not actually release any memory, the region
|
||||
* is unchanged.
|
||||
* recalcs the tree parents.
|
||||
* @param fwd: the forward data structure
|
||||
* @param c: class of zone
|
||||
* @param nm: name of zone (in uncompressed wireformat).
|
||||
*/
|
||||
void forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm);
|
||||
|
||||
/**
|
||||
* Add stub hole (empty entry in forward table, that makes resolution skip
|
||||
* a forward-zone because the stub zone should override the forward zone).
|
||||
* Does not add one if not necessary.
|
||||
* @param fwd: the forward data structure
|
||||
* @param c: class of zone
|
||||
* @param nm: name of zone (in uncompressed wireformat).
|
||||
* @return false on failure (out of memory);
|
||||
*/
|
||||
int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm);
|
||||
|
||||
/**
|
||||
* Remove stub hole, if one exists.
|
||||
* @param fwd: the forward data structure
|
||||
* @param c: class of zone
|
||||
* @param nm: name of zone (in uncompressed wireformat).
|
||||
*/
|
||||
void forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
|
||||
uint8_t* nm);
|
||||
|
||||
#endif /* ITERATOR_ITER_FWD_H */
|
||||
|
||||
+128
-77
@@ -40,11 +40,10 @@
|
||||
* Keep track of stub and root hints, and read those from config.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ldns/dname.h"
|
||||
#include "ldns/rr.h"
|
||||
#include <ldns/dname.h>
|
||||
#include <ldns/rr.h>
|
||||
#include "iterator/iter_hints.h"
|
||||
#include "iterator/iter_delegpt.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
@@ -57,26 +56,39 @@ hints_create(void)
|
||||
sizeof(struct iter_hints));
|
||||
if(!hints)
|
||||
return NULL;
|
||||
hints->region = regional_create();
|
||||
if(!hints->region) {
|
||||
hints_delete(hints);
|
||||
return NULL;
|
||||
}
|
||||
return hints;
|
||||
}
|
||||
|
||||
static void hints_stub_free(struct iter_hints_stub* s)
|
||||
{
|
||||
if(!s) return;
|
||||
delegpt_free_mlc(s->dp);
|
||||
free(s);
|
||||
}
|
||||
|
||||
static void delhintnode(rbnode_t* n, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct iter_hints_stub* node = (struct iter_hints_stub*)n;
|
||||
hints_stub_free(node);
|
||||
}
|
||||
|
||||
static void hints_del_tree(struct iter_hints* hints)
|
||||
{
|
||||
traverse_postorder(&hints->tree, &delhintnode, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
hints_delete(struct iter_hints* hints)
|
||||
{
|
||||
if(!hints)
|
||||
return;
|
||||
regional_destroy(hints->region);
|
||||
hints_del_tree(hints);
|
||||
free(hints);
|
||||
}
|
||||
|
||||
/** add hint to delegation hints */
|
||||
static int
|
||||
ah(struct delegpt* dp, struct regional* r, const char* sv, const char* ip)
|
||||
ah(struct delegpt* dp, const char* sv, const char* ip)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen;
|
||||
@@ -85,9 +97,9 @@ ah(struct delegpt* dp, struct regional* r, const char* sv, const char* ip)
|
||||
log_err("could not parse %s", sv);
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_add_ns(dp, r, ldns_rdf_data(rdf), 0) ||
|
||||
if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(rdf), 0) ||
|
||||
!extstrtoaddr(ip, &addr, &addrlen) ||
|
||||
!delegpt_add_target(dp, r, ldns_rdf_data(rdf), ldns_rdf_size(rdf),
|
||||
!delegpt_add_target_mlc(dp, ldns_rdf_data(rdf), ldns_rdf_size(rdf),
|
||||
&addr, addrlen, 0, 0)) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
return 0;
|
||||
@@ -98,7 +110,7 @@ ah(struct delegpt* dp, struct regional* r, const char* sv, const char* ip)
|
||||
|
||||
/** obtain compiletime provided root hints */
|
||||
static struct delegpt*
|
||||
compile_time_root_prime(struct regional* r, int do_ip4, int do_ip6)
|
||||
compile_time_root_prime(int do_ip4, int do_ip6)
|
||||
{
|
||||
/* from:
|
||||
; This file is made available by InterNIC
|
||||
@@ -109,39 +121,40 @@ compile_time_root_prime(struct regional* r, int do_ip4, int do_ip6)
|
||||
;
|
||||
; related version of root zone: 2010061700
|
||||
*/
|
||||
struct delegpt* dp = delegpt_create(r);
|
||||
struct delegpt* dp = delegpt_create_mlc((uint8_t*)"\000");
|
||||
if(!dp)
|
||||
return NULL;
|
||||
dp->has_parent_side_NS = 1;
|
||||
if(!delegpt_set_name(dp, r, (uint8_t*)"\000"))
|
||||
return NULL;
|
||||
if(do_ip4) {
|
||||
if(!ah(dp, r, "A.ROOT-SERVERS.NET.", "198.41.0.4")) return 0;
|
||||
if(!ah(dp, r, "B.ROOT-SERVERS.NET.", "192.228.79.201")) return 0;
|
||||
if(!ah(dp, r, "C.ROOT-SERVERS.NET.", "192.33.4.12")) return 0;
|
||||
if(!ah(dp, r, "D.ROOT-SERVERS.NET.", "128.8.10.90")) return 0;
|
||||
if(!ah(dp, r, "E.ROOT-SERVERS.NET.", "192.203.230.10")) return 0;
|
||||
if(!ah(dp, r, "F.ROOT-SERVERS.NET.", "192.5.5.241")) return 0;
|
||||
if(!ah(dp, r, "G.ROOT-SERVERS.NET.", "192.112.36.4")) return 0;
|
||||
if(!ah(dp, r, "H.ROOT-SERVERS.NET.", "128.63.2.53")) return 0;
|
||||
if(!ah(dp, r, "I.ROOT-SERVERS.NET.", "192.36.148.17")) return 0;
|
||||
if(!ah(dp, r, "J.ROOT-SERVERS.NET.", "192.58.128.30")) return 0;
|
||||
if(!ah(dp, r, "K.ROOT-SERVERS.NET.", "193.0.14.129")) return 0;
|
||||
if(!ah(dp, r, "L.ROOT-SERVERS.NET.", "199.7.83.42")) return 0;
|
||||
if(!ah(dp, r, "M.ROOT-SERVERS.NET.", "202.12.27.33")) return 0;
|
||||
if(!ah(dp, "A.ROOT-SERVERS.NET.", "198.41.0.4")) goto failed;
|
||||
if(!ah(dp, "B.ROOT-SERVERS.NET.", "192.228.79.201")) goto failed;
|
||||
if(!ah(dp, "C.ROOT-SERVERS.NET.", "192.33.4.12")) goto failed;
|
||||
if(!ah(dp, "D.ROOT-SERVERS.NET.", "128.8.10.90")) goto failed;
|
||||
if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) goto failed;
|
||||
if(!ah(dp, "F.ROOT-SERVERS.NET.", "192.5.5.241")) goto failed;
|
||||
if(!ah(dp, "G.ROOT-SERVERS.NET.", "192.112.36.4")) goto failed;
|
||||
if(!ah(dp, "H.ROOT-SERVERS.NET.", "128.63.2.53")) goto failed;
|
||||
if(!ah(dp, "I.ROOT-SERVERS.NET.", "192.36.148.17")) goto failed;
|
||||
if(!ah(dp, "J.ROOT-SERVERS.NET.", "192.58.128.30")) goto failed;
|
||||
if(!ah(dp, "K.ROOT-SERVERS.NET.", "193.0.14.129")) goto failed;
|
||||
if(!ah(dp, "L.ROOT-SERVERS.NET.", "199.7.83.42")) goto failed;
|
||||
if(!ah(dp, "M.ROOT-SERVERS.NET.", "202.12.27.33")) goto failed;
|
||||
}
|
||||
if(do_ip6) {
|
||||
if(!ah(dp, r, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) return 0;
|
||||
if(!ah(dp, r, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) return 0;
|
||||
if(!ah(dp, r, "F.ROOT-SERVERS.NET.", "2001:500:2f::f")) return 0;
|
||||
if(!ah(dp, r, "H.ROOT-SERVERS.NET.", "2001:500:1::803f:235")) return 0;
|
||||
if(!ah(dp, r, "I.ROOT-SERVERS.NET.", "2001:7fe::53")) return 0;
|
||||
if(!ah(dp, r, "J.ROOT-SERVERS.NET.", "2001:503:c27::2:30")) return 0;
|
||||
if(!ah(dp, r, "K.ROOT-SERVERS.NET.", "2001:7fd::1")) return 0;
|
||||
if(!ah(dp, r, "L.ROOT-SERVERS.NET.", "2001:500:3::42")) return 0;
|
||||
if(!ah(dp, r, "M.ROOT-SERVERS.NET.", "2001:dc3::35")) return 0;
|
||||
if(!ah(dp, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) goto failed;
|
||||
if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) goto failed;
|
||||
if(!ah(dp, "F.ROOT-SERVERS.NET.", "2001:500:2f::f")) goto failed;
|
||||
if(!ah(dp, "H.ROOT-SERVERS.NET.", "2001:500:1::803f:235")) goto failed;
|
||||
if(!ah(dp, "I.ROOT-SERVERS.NET.", "2001:7fe::53")) goto failed;
|
||||
if(!ah(dp, "J.ROOT-SERVERS.NET.", "2001:503:c27::2:30")) goto failed;
|
||||
if(!ah(dp, "K.ROOT-SERVERS.NET.", "2001:7fd::1")) goto failed;
|
||||
if(!ah(dp, "L.ROOT-SERVERS.NET.", "2001:500:3::42")) goto failed;
|
||||
if(!ah(dp, "M.ROOT-SERVERS.NET.", "2001:dc3::35")) goto failed;
|
||||
}
|
||||
return dp;
|
||||
failed:
|
||||
delegpt_free_mlc(dp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** insert new hint info into hint structure */
|
||||
@@ -149,51 +162,50 @@ static int
|
||||
hints_insert(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
||||
int noprime)
|
||||
{
|
||||
struct iter_hints_stub* node = regional_alloc(hints->region,
|
||||
struct iter_hints_stub* node = (struct iter_hints_stub*)malloc(
|
||||
sizeof(struct iter_hints_stub));
|
||||
uint8_t* nm;
|
||||
if(!node)
|
||||
return 0;
|
||||
nm = regional_alloc_init(hints->region, dp->name, dp->namelen);
|
||||
if(!nm)
|
||||
if(!node) {
|
||||
delegpt_free_mlc(dp);
|
||||
return 0;
|
||||
}
|
||||
node->dp = dp;
|
||||
node->noprime = (uint8_t)noprime;
|
||||
if(!name_tree_insert(&hints->tree, &node->node, nm, dp->namelen,
|
||||
if(!name_tree_insert(&hints->tree, &node->node, dp->name, dp->namelen,
|
||||
dp->namelabs, c)) {
|
||||
log_err("second hints ignored.");
|
||||
delegpt_free_mlc(dp);
|
||||
free(node);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** set stub name */
|
||||
static int
|
||||
read_stubs_name(struct iter_hints* hints, struct config_stub* s,
|
||||
struct delegpt* dp)
|
||||
static struct delegpt*
|
||||
read_stubs_name(struct config_stub* s)
|
||||
{
|
||||
struct delegpt* dp;
|
||||
ldns_rdf* rdf;
|
||||
if(!s->name) {
|
||||
log_err("stub zone without a name");
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
rdf = ldns_dname_new_frm_str(s->name);
|
||||
if(!rdf) {
|
||||
log_err("cannot parse stub zone name %s", s->name);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
if(!delegpt_set_name(dp, hints->region, ldns_rdf_data(rdf))) {
|
||||
if(!(dp=delegpt_create_mlc(ldns_rdf_data(rdf)))) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
ldns_rdf_deep_free(rdf);
|
||||
return 1;
|
||||
return dp;
|
||||
}
|
||||
|
||||
/** set stub host names */
|
||||
static int
|
||||
read_stubs_host(struct iter_hints* hints, struct config_stub* s,
|
||||
struct delegpt* dp)
|
||||
read_stubs_host(struct config_stub* s, struct delegpt* dp)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
ldns_rdf* rdf;
|
||||
@@ -205,7 +217,7 @@ read_stubs_host(struct iter_hints* hints, struct config_stub* s,
|
||||
s->name, p->str);
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_add_ns(dp, hints->region, ldns_rdf_data(rdf), 0)) {
|
||||
if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(rdf), 0)) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
@@ -217,8 +229,7 @@ read_stubs_host(struct iter_hints* hints, struct config_stub* s,
|
||||
|
||||
/** set stub server addresses */
|
||||
static int
|
||||
read_stubs_addr(struct iter_hints* hints, struct config_stub* s,
|
||||
struct delegpt* dp)
|
||||
read_stubs_addr(struct config_stub* s, struct delegpt* dp)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
struct sockaddr_storage addr;
|
||||
@@ -230,7 +241,7 @@ read_stubs_addr(struct iter_hints* hints, struct config_stub* s,
|
||||
s->name, p->str);
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_add_addr(dp, hints->region, &addr, addrlen, 0, 0)) {
|
||||
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
@@ -243,20 +254,21 @@ static int
|
||||
read_stubs(struct iter_hints* hints, struct config_file* cfg)
|
||||
{
|
||||
struct config_stub* s;
|
||||
struct delegpt* dp;
|
||||
for(s = cfg->stubs; s; s = s->next) {
|
||||
struct delegpt* dp = delegpt_create(hints->region);
|
||||
if(!dp) {
|
||||
log_err("out of memory");
|
||||
if(!(dp=read_stubs_name(s)))
|
||||
return 0;
|
||||
if(!read_stubs_host(s, dp) || !read_stubs_addr(s, dp)) {
|
||||
delegpt_free_mlc(dp);
|
||||
return 0;
|
||||
}
|
||||
dp->has_parent_side_NS = 1;
|
||||
if(!read_stubs_name(hints, s, dp) ||
|
||||
!read_stubs_host(hints, s, dp) ||
|
||||
!read_stubs_addr(hints, s, dp))
|
||||
return 0;
|
||||
/* the flag is turned off for 'stub-first' so that the
|
||||
* last resort will ask for parent-side NS record and thus
|
||||
* fallback to the internet name servers on a failure */
|
||||
dp->has_parent_side_NS = (uint8_t)!s->isfirst;
|
||||
delegpt_log(VERB_QUERY, dp);
|
||||
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, !s->isprime))
|
||||
return 0;
|
||||
delegpt_log(VERB_QUERY, dp);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -279,7 +291,7 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
fname, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
dp = delegpt_create(hints->region);
|
||||
dp = delegpt_create_mlc(NULL);
|
||||
if(!dp) {
|
||||
log_err("out of memory reading root hints");
|
||||
fclose(f);
|
||||
@@ -300,14 +312,14 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
goto stop_read;
|
||||
}
|
||||
if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_NS) {
|
||||
if(!delegpt_add_ns(dp, hints->region,
|
||||
if(!delegpt_add_ns_mlc(dp,
|
||||
ldns_rdf_data(ldns_rr_rdf(rr, 0)), 0)) {
|
||||
log_err("out of memory reading root hints");
|
||||
goto stop_read;
|
||||
}
|
||||
c = ldns_rr_get_class(rr);
|
||||
if(!dp->name) {
|
||||
if(!delegpt_set_name(dp, hints->region,
|
||||
if(!delegpt_set_name_mlc(dp,
|
||||
ldns_rdf_data(ldns_rr_owner(rr)))){
|
||||
log_err("out of memory.");
|
||||
goto stop_read;
|
||||
@@ -321,7 +333,7 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
|
||||
memmove(&sa.sin_addr,
|
||||
ldns_rdf_data(ldns_rr_rdf(rr, 0)), INET_SIZE);
|
||||
if(!delegpt_add_target(dp, hints->region,
|
||||
if(!delegpt_add_target_mlc(dp,
|
||||
ldns_rdf_data(ldns_rr_owner(rr)),
|
||||
ldns_rdf_size(ldns_rr_owner(rr)),
|
||||
(struct sockaddr_storage*)&sa, len,
|
||||
@@ -337,7 +349,7 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
|
||||
memmove(&sa.sin6_addr,
|
||||
ldns_rdf_data(ldns_rr_rdf(rr, 0)), INET6_SIZE);
|
||||
if(!delegpt_add_target(dp, hints->region,
|
||||
if(!delegpt_add_target_mlc(dp,
|
||||
ldns_rdf_data(ldns_rr_owner(rr)),
|
||||
ldns_rdf_size(ldns_rr_owner(rr)),
|
||||
(struct sockaddr_storage*)&sa, len,
|
||||
@@ -360,6 +372,7 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
fclose(f);
|
||||
if(!dp->name) {
|
||||
log_warn("root hints %s: no NS content", fname);
|
||||
delegpt_free_mlc(dp);
|
||||
return 1;
|
||||
}
|
||||
if(!hints_insert(hints, c, dp, 0)) {
|
||||
@@ -373,6 +386,7 @@ stop_read:
|
||||
ldns_rdf_deep_free(origin);
|
||||
if (prev_rr)
|
||||
ldns_rdf_deep_free(prev_rr);
|
||||
delegpt_free_mlc(dp);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
@@ -400,7 +414,7 @@ read_root_hints_list(struct iter_hints* hints, struct config_file* cfg)
|
||||
int
|
||||
hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
|
||||
{
|
||||
regional_free_all(hints->region);
|
||||
hints_del_tree(hints);
|
||||
name_tree_init(&hints->tree);
|
||||
|
||||
/* read root hints */
|
||||
@@ -413,8 +427,8 @@ hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
|
||||
|
||||
/* use fallback compiletime root hints */
|
||||
if(!hints_lookup_root(hints, LDNS_RR_CLASS_IN)) {
|
||||
struct delegpt* dp = compile_time_root_prime(hints->region,
|
||||
cfg->do_ip4, cfg->do_ip6);
|
||||
struct delegpt* dp = compile_time_root_prime(cfg->do_ip4,
|
||||
cfg->do_ip6);
|
||||
verbose(VERB_ALGO, "no config, using builtin root hints.");
|
||||
if(!dp)
|
||||
return 0;
|
||||
@@ -483,6 +497,43 @@ int hints_next_root(struct iter_hints* hints, uint16_t* qclass)
|
||||
size_t
|
||||
hints_get_mem(struct iter_hints* hints)
|
||||
{
|
||||
size_t s;
|
||||
struct iter_hints_stub* p;
|
||||
if(!hints) return 0;
|
||||
return sizeof(*hints) + regional_get_mem(hints->region);
|
||||
s = sizeof(*hints);
|
||||
RBTREE_FOR(p, struct iter_hints_stub*, &hints->tree) {
|
||||
s += sizeof(*p) + delegpt_get_mem(p->dp);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
||||
int noprime)
|
||||
{
|
||||
struct iter_hints_stub *z;
|
||||
if((z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
|
||||
dp->name, dp->namelen, dp->namelabs, c)) != NULL) {
|
||||
(void)rbtree_delete(&hints->tree, &z->node);
|
||||
hints_stub_free(z);
|
||||
}
|
||||
if(!hints_insert(hints, c, dp, noprime))
|
||||
return 0;
|
||||
name_tree_init_parents(&hints->tree);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm)
|
||||
{
|
||||
struct iter_hints_stub *z;
|
||||
size_t len;
|
||||
int labs = dname_count_size_labels(nm, &len);
|
||||
if(!(z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
|
||||
nm, len, labs, c)))
|
||||
return; /* nothing to do */
|
||||
(void)rbtree_delete(&hints->tree, &z->node);
|
||||
hints_stub_free(z);
|
||||
name_tree_init_parents(&hints->tree);
|
||||
}
|
||||
|
||||
|
||||
+23
-4
@@ -46,14 +46,11 @@
|
||||
struct iter_env;
|
||||
struct config_file;
|
||||
struct delegpt;
|
||||
struct regional;
|
||||
|
||||
/**
|
||||
* Iterator hints structure
|
||||
*/
|
||||
struct iter_hints {
|
||||
/** regional where hints are allocated */
|
||||
struct regional* region;
|
||||
/**
|
||||
* Hints are stored in this tree. Sort order is specially chosen.
|
||||
* first sorted on qclass. Then on dname in nsec-like order, so that
|
||||
@@ -71,7 +68,7 @@ struct iter_hints {
|
||||
struct iter_hints_stub {
|
||||
/** tree sorted by name, class */
|
||||
struct name_tree_node node;
|
||||
/** delegation point with hint information for this stub. */
|
||||
/** delegation point with hint information for this stub. malloced. */
|
||||
struct delegpt* dp;
|
||||
/** does the stub need to forego priming (like on other ports) */
|
||||
uint8_t noprime;
|
||||
@@ -139,4 +136,26 @@ struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
|
||||
*/
|
||||
size_t hints_get_mem(struct iter_hints* hints);
|
||||
|
||||
/**
|
||||
* Add stub to hints structure. For external use since it recalcs
|
||||
* the tree parents.
|
||||
* @param hints: the hints data structure
|
||||
* @param c: class of zone
|
||||
* @param dp: delegation point with name and target nameservers for new
|
||||
* hints stub. malloced.
|
||||
* @param noprime: set noprime option to true or false on new hint stub.
|
||||
* @return false on failure (out of memory);
|
||||
*/
|
||||
int hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
||||
int noprime);
|
||||
|
||||
/**
|
||||
* Remove stub from hints structure. For external use since it
|
||||
* recalcs the tree parents.
|
||||
* @param hints: the hints data structure
|
||||
* @param c: class of stub zone
|
||||
* @param nm: name of stub zone (in uncompressed wireformat).
|
||||
*/
|
||||
void hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm);
|
||||
|
||||
#endif /* ITERATOR_ITER_HINTS_H */
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "ldns/dname.h"
|
||||
#include <ldns/dname.h>
|
||||
#include "iterator/iter_priv.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/log.h"
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
#ifndef ITERATOR_ITER_PRIV_H
|
||||
#define ITERATOR_ITER_PRIV_H
|
||||
#include "util/rbtree.h"
|
||||
#include "ldns/buffer.h"
|
||||
#include <ldns/buffer.h>
|
||||
struct iter_env;
|
||||
struct config_file;
|
||||
struct regional;
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
* one of the response types.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ldns/packet.h"
|
||||
#include <ldns/packet.h>
|
||||
#include "iterator/iter_resptype.h"
|
||||
#include "iterator/iter_delegpt.h"
|
||||
#include "services/cache/dns.h"
|
||||
@@ -163,6 +163,8 @@ response_type_from_server(int rdset,
|
||||
ntohs(s->rk.rrset_class) == request->qclass &&
|
||||
dname_strict_subdomain_c(s->rk.dname,
|
||||
origzone)) {
|
||||
if((msg->rep->flags&BIT_AA))
|
||||
return RESPONSE_TYPE_ANSWER;
|
||||
return RESPONSE_TYPE_REFERRAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -187,11 +187,14 @@ parse_get_cname_target(struct rrset_parse* rrset, uint8_t** sname,
|
||||
size_t* snamelen)
|
||||
{
|
||||
if(rrset->rr_count != 1) {
|
||||
struct rr_parse* sig;
|
||||
verbose(VERB_ALGO, "Found CNAME rrset with "
|
||||
"size > 1: %u", (unsigned)rrset->rr_count);
|
||||
/* use the first CNAME! */
|
||||
rrset->rr_count = 1;
|
||||
rrset->size = rrset->rr_first->size;
|
||||
for(sig=rrset->rrsig_first; sig; sig=sig->next)
|
||||
rrset->size += sig->size;
|
||||
rrset->rr_last = rrset->rr_first;
|
||||
rrset->rr_first->next = NULL;
|
||||
}
|
||||
@@ -532,8 +535,7 @@ store_rrset(ldns_buffer* pkt, struct msg_parse* msg, struct module_env* env,
|
||||
ref.key = k;
|
||||
ref.id = k->id;
|
||||
/*ignore ret: it was in the cache, ref updated */
|
||||
(void)rrset_cache_update(env->rrset_cache, &ref,
|
||||
env->alloc, now);
|
||||
(void)rrset_cache_update(env->rrset_cache, &ref, env->alloc, now);
|
||||
}
|
||||
|
||||
/** Check if there are SOA records in the authority section (negative) */
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
#ifndef ITERATOR_ITER_SCRUB_H
|
||||
#define ITERATOR_ITER_SCRUB_H
|
||||
#include "ldns/buffer.h"
|
||||
#include <ldns/buffer.h>
|
||||
struct msg_parse;
|
||||
struct query_info;
|
||||
struct regional;
|
||||
|
||||
+77
-11
@@ -62,6 +62,7 @@
|
||||
#include "validator/val_anchor.h"
|
||||
#include "validator/val_kcache.h"
|
||||
#include "validator/val_kentry.h"
|
||||
#include "validator/val_utils.h"
|
||||
|
||||
/** time when nameserver glue is said to be 'recent' */
|
||||
#define SUSPICION_RECENT_EXPIRY 86400
|
||||
@@ -113,12 +114,6 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
verbose(VERB_QUERY, "target fetch policy for level %d is %d",
|
||||
i, iter_env->target_fetch_policy[i]);
|
||||
|
||||
if(!iter_env->hints)
|
||||
iter_env->hints = hints_create();
|
||||
if(!iter_env->hints || !hints_apply_cfg(iter_env->hints, cfg)) {
|
||||
log_err("Could not set root or stub hints");
|
||||
return 0;
|
||||
}
|
||||
if(!iter_env->donotq)
|
||||
iter_env->donotq = donotq_create();
|
||||
if(!iter_env->donotq || !donotq_apply_cfg(iter_env->donotq, cfg)) {
|
||||
@@ -212,8 +207,13 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
|
||||
if(lame)
|
||||
return -1; /* server is lame */
|
||||
else if(rtt >= USEFUL_SERVER_TOP_TIMEOUT)
|
||||
/* server is unresponsive */
|
||||
return USEFUL_SERVER_TOP_TIMEOUT;
|
||||
/* server is unresponsive,
|
||||
* we used to return TOP_TIMOUT, but fairly useless,
|
||||
* because if == TOP_TIMEOUT is dropped because
|
||||
* blacklisted later, instead, remove it here, so
|
||||
* other choices (that are not blacklisted) can be
|
||||
* tried */
|
||||
return -1;
|
||||
/* select remainder from worst to best */
|
||||
else if(reclame)
|
||||
return rtt+USEFUL_SERVER_TOP_TIMEOUT*3; /* nonpref */
|
||||
@@ -418,11 +418,14 @@ dns_copy_msg(struct dns_msg* from, struct regional* region)
|
||||
return m;
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
iter_dns_store(struct module_env* env, struct query_info* msgqinf,
|
||||
struct reply_info* msgrep, int is_referral, uint32_t leeway)
|
||||
struct reply_info* msgrep, int is_referral, uint32_t leeway, int pside,
|
||||
struct regional* region)
|
||||
{
|
||||
return dns_cache_store(env, msgqinf, msgrep, is_referral, leeway);
|
||||
if(!dns_cache_store(env, msgqinf, msgrep, is_referral, leeway,
|
||||
pside, region))
|
||||
log_err("out of memory: cannot store data in cache");
|
||||
}
|
||||
|
||||
int
|
||||
@@ -967,3 +970,66 @@ void iter_merge_retry_counts(struct delegpt* dp, struct delegpt* old)
|
||||
a = a->next_usable;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
iter_ds_toolow(struct dns_msg* msg, struct delegpt* dp)
|
||||
{
|
||||
/* if for query example.com, there is example.com SOA or a subdomain
|
||||
* of example.com, then we are too low and need to fetch NS. */
|
||||
size_t i;
|
||||
/* if we have a DNAME or CNAME we are probably wrong */
|
||||
/* if we have a qtype DS in the answer section, its fine */
|
||||
for(i=0; i < msg->rep->an_numrrsets; i++) {
|
||||
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_DNAME ||
|
||||
ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME) {
|
||||
/* not the right answer, maybe too low, check the
|
||||
* RRSIG signer name (if there is any) for a hint
|
||||
* that it is from the dp zone anyway */
|
||||
uint8_t* sname;
|
||||
size_t slen;
|
||||
val_find_rrset_signer(s, &sname, &slen);
|
||||
if(sname && query_dname_compare(dp->name, sname)==0)
|
||||
return 0; /* it is fine, from the right dp */
|
||||
return 1;
|
||||
}
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_DS)
|
||||
return 0; /* fine, we have a DS record */
|
||||
}
|
||||
for(i=msg->rep->an_numrrsets;
|
||||
i < msg->rep->an_numrrsets + msg->rep->ns_numrrsets; i++) {
|
||||
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_SOA) {
|
||||
if(dname_subdomain_c(s->rk.dname, msg->qinfo.qname))
|
||||
return 1; /* point is too low */
|
||||
if(query_dname_compare(s->rk.dname, dp->name)==0)
|
||||
return 0; /* right dp */
|
||||
}
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC ||
|
||||
ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) {
|
||||
uint8_t* sname;
|
||||
size_t slen;
|
||||
val_find_rrset_signer(s, &sname, &slen);
|
||||
if(sname && query_dname_compare(dp->name, sname)==0)
|
||||
return 0; /* it is fine, from the right dp */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* we do not know */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp)
|
||||
{
|
||||
/* no delegation point, do not see how we can go down,
|
||||
* robust check, it should really exist */
|
||||
if(!dp) return 0;
|
||||
|
||||
/* see if dp equals the qname, then we cannot go down further */
|
||||
if(query_dname_compare(qinfo->qname, dp->name) == 0)
|
||||
return 0;
|
||||
/* if dp is one label above the name we also cannot go down further */
|
||||
if(dname_count_labels(qinfo->qname) == dp->namelabs+1)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
+32
-4
@@ -43,7 +43,7 @@
|
||||
#ifndef ITERATOR_ITER_UTILS_H
|
||||
#define ITERATOR_ITER_UTILS_H
|
||||
#include "iterator/iter_resptype.h"
|
||||
#include "ldns/buffer.h"
|
||||
#include <ldns/buffer.h>
|
||||
struct iter_env;
|
||||
struct iter_hints;
|
||||
struct iter_forwards;
|
||||
@@ -121,10 +121,18 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);
|
||||
* @param is_referral: If true, then the given message to be stored is a
|
||||
* referral. The cache implementation may use this as a hint.
|
||||
* @param leeway: prefetch TTL leeway to expire old rrsets quicker.
|
||||
* @return 0 on alloc error (out of memory).
|
||||
* @param pside: true if dp is parentside, thus message is 'fresh' and NS
|
||||
* can be prefetch-updates.
|
||||
* @param region: to copy modified (cache is better) rrs back to.
|
||||
* @return void, because we are not interested in alloc errors,
|
||||
* the iterator and validator can operate on the results in their
|
||||
* scratch space (the qstate.region) and are not dependent on the cache.
|
||||
* It is useful to log the alloc failure (for the server operator),
|
||||
* but the query resolution can continue without cache storage.
|
||||
*/
|
||||
int iter_dns_store(struct module_env* env, struct query_info* qinf,
|
||||
struct reply_info* rep, int is_referral, uint32_t leeway);
|
||||
void iter_dns_store(struct module_env* env, struct query_info* qinf,
|
||||
struct reply_info* rep, int is_referral, uint32_t leeway, int pside,
|
||||
struct regional* region);
|
||||
|
||||
/**
|
||||
* Select randomly with n/m probability.
|
||||
@@ -307,4 +315,24 @@ void iter_dec_attempts(struct delegpt* dp, int d);
|
||||
*/
|
||||
void iter_merge_retry_counts(struct delegpt* dp, struct delegpt* old);
|
||||
|
||||
/**
|
||||
* See if a DS response (type ANSWER) is too low: a nodata answer with
|
||||
* a SOA record in the authority section at-or-below the qchase.qname.
|
||||
* Also returns true if we are not sure (i.e. empty message, CNAME nosig).
|
||||
* @param msg: the response.
|
||||
* @param dp: the dp name is used to check if the RRSIG gives a clue that
|
||||
* it was originated from the correct nameserver.
|
||||
* @return true if too low.
|
||||
*/
|
||||
int iter_ds_toolow(struct dns_msg* msg, struct delegpt* dp);
|
||||
|
||||
/**
|
||||
* See if delegpt can go down a step to the qname or not
|
||||
* @param qinfo: the query name looked up.
|
||||
* @param dp: checked if the name can go lower to the qname
|
||||
* @return true if can go down, false if that would not be possible.
|
||||
* the current response seems to be the one and only, best possible, response.
|
||||
*/
|
||||
int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp);
|
||||
|
||||
#endif /* ITERATOR_ITER_UTILS_H */
|
||||
|
||||
+229
-59
@@ -41,7 +41,7 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "ldns/ldns.h"
|
||||
#include <ldns/ldns.h>
|
||||
#include "iterator/iterator.h"
|
||||
#include "iterator/iter_utils.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
@@ -89,7 +89,6 @@ iter_deinit(struct module_env* env, int id)
|
||||
iter_env = (struct iter_env*)env->modinfo[id];
|
||||
free(iter_env->target_fetch_policy);
|
||||
priv_delete(iter_env->priv);
|
||||
hints_delete(iter_env->hints);
|
||||
donotq_delete(iter_env->donotq);
|
||||
free(iter_env);
|
||||
env->modinfo[id] = NULL;
|
||||
@@ -117,6 +116,7 @@ iter_new(struct module_qstate* qstate, int id)
|
||||
iq->num_current_queries = 0;
|
||||
iq->query_restart_count = 0;
|
||||
iq->referral_count = 0;
|
||||
iq->sent_count = 0;
|
||||
iq->wait_priming_stub = 0;
|
||||
iq->refetch_glue = 0;
|
||||
iq->dnssec_expected = 0;
|
||||
@@ -259,9 +259,7 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)
|
||||
/* do not waste time trying to validate this servfail */
|
||||
err.security = sec_status_indeterminate;
|
||||
verbose(VERB_ALGO, "store error response in message cache");
|
||||
if(!iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0)) {
|
||||
log_err("error_response_cache: could not store error (nomem)");
|
||||
}
|
||||
iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL);
|
||||
return error_response(qstate, id, rcode);
|
||||
}
|
||||
|
||||
@@ -531,21 +529,20 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
|
||||
* Generate and send a root priming request.
|
||||
* @param qstate: the qtstate that triggered the need to prime.
|
||||
* @param iq: iterator query state.
|
||||
* @param ie: iterator global state.
|
||||
* @param id: module id.
|
||||
* @param qclass: the class to prime.
|
||||
* @return 0 on failure
|
||||
*/
|
||||
static int
|
||||
prime_root(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
struct iter_env* ie, int id, uint16_t qclass)
|
||||
prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
||||
uint16_t qclass)
|
||||
{
|
||||
struct delegpt* dp;
|
||||
struct module_qstate* subq;
|
||||
verbose(VERB_DETAIL, "priming . %s NS",
|
||||
ldns_lookup_by_id(ldns_rr_classes, (int)qclass)?
|
||||
ldns_lookup_by_id(ldns_rr_classes, (int)qclass)->name:"??");
|
||||
dp = hints_lookup_root(ie->hints, qclass);
|
||||
dp = hints_lookup_root(qstate->env->hints, qclass);
|
||||
if(!dp) {
|
||||
verbose(VERB_ALGO, "Cannot prime due to lack of hints");
|
||||
return 0;
|
||||
@@ -589,31 +586,26 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
*
|
||||
* @param qstate: the qtstate that triggered the need to prime.
|
||||
* @param iq: iterator query state.
|
||||
* @param ie: iterator global state.
|
||||
* @param id: module id.
|
||||
* @param q: request name.
|
||||
* @param qname: request name.
|
||||
* @param qclass: request class.
|
||||
* @return true if a priming subrequest was made, false if not. The will only
|
||||
* issue a priming request if it detects an unprimed stub.
|
||||
* Uses value of 2 to signal during stub-prime in root-prime situation
|
||||
* that a noprime-stub is available and resolution can continue.
|
||||
*/
|
||||
static int
|
||||
prime_stub(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
struct iter_env* ie, int id, struct query_info* q)
|
||||
prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
||||
uint8_t* qname, uint16_t qclass)
|
||||
{
|
||||
/* Lookup the stub hint. This will return null if the stub doesn't
|
||||
* need to be re-primed. */
|
||||
struct iter_hints_stub* stub;
|
||||
struct delegpt* stub_dp;
|
||||
struct module_qstate* subq;
|
||||
uint8_t* delname = q->qname;
|
||||
size_t delnamelen = q->qname_len;
|
||||
|
||||
if(q->qtype == LDNS_RR_TYPE_DS && !dname_is_root(q->qname))
|
||||
/* remove first label, but not for root */
|
||||
dname_remove_label(&delname, &delnamelen);
|
||||
|
||||
stub = hints_lookup_stub(ie->hints, delname, q->qclass, iq->dp);
|
||||
if(!qname) return 0;
|
||||
stub = hints_lookup_stub(qstate->env->hints, qname, qclass, iq->dp);
|
||||
/* The stub (if there is one) does not need priming. */
|
||||
if(!stub)
|
||||
return 0;
|
||||
@@ -632,18 +624,18 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 1; /* return 1 to make module stop, with error */
|
||||
}
|
||||
log_nametypeclass(VERB_DETAIL, "use stub", stub_dp->name,
|
||||
LDNS_RR_TYPE_NS, q->qclass);
|
||||
LDNS_RR_TYPE_NS, qclass);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Otherwise, we need to (re)prime the stub. */
|
||||
log_nametypeclass(VERB_DETAIL, "priming stub", stub_dp->name,
|
||||
LDNS_RR_TYPE_NS, q->qclass);
|
||||
LDNS_RR_TYPE_NS, qclass);
|
||||
|
||||
/* Stub priming events start at the QUERYTARGETS state to avoid the
|
||||
* redundant INIT state processing. */
|
||||
if(!generate_sub_request(stub_dp->name, stub_dp->namelen,
|
||||
LDNS_RR_TYPE_NS, q->qclass, qstate, id, iq,
|
||||
LDNS_RR_TYPE_NS, qclass, qstate, id, iq,
|
||||
QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0)) {
|
||||
verbose(VERB_ALGO, "could not prime stub");
|
||||
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
@@ -849,8 +841,12 @@ forward_request(struct module_qstate* qstate, struct iter_qstate* iq)
|
||||
struct delegpt* dp;
|
||||
uint8_t* delname = iq->qchase.qname;
|
||||
size_t delnamelen = iq->qchase.qname_len;
|
||||
if(iq->refetch_glue) {
|
||||
delname = iq->dp->name;
|
||||
delnamelen = iq->dp->namelen;
|
||||
}
|
||||
/* strip one label off of DS query to lookup higher for it */
|
||||
if(iq->qchase.qtype == LDNS_RR_TYPE_DS
|
||||
if( (iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue)
|
||||
&& !dname_is_root(iq->qchase.qname))
|
||||
dname_remove_label(&delname, &delnamelen);
|
||||
dp = forwards_lookup(qstate->env->fwds, delname, iq->qchase.qclass);
|
||||
@@ -974,6 +970,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->dp = NULL;
|
||||
iq->refetch_glue = 0;
|
||||
iq->query_restart_count++;
|
||||
iq->sent_count = 0;
|
||||
sock_list_insert(&qstate->reply_origin, NULL, 0, qstate->region);
|
||||
return next_state(iq, INIT_REQUEST_STATE);
|
||||
}
|
||||
@@ -1030,7 +1027,6 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
qstate->prefetch_leeway)))
|
||||
delname = NULL; /* go to root priming */
|
||||
else dname_remove_label(&delname, &delnamelen);
|
||||
iq->refetch_glue = 0; /* if CNAME causes restart, no refetch */
|
||||
}
|
||||
/* delname is the name to lookup a delegation for. If NULL rootprime */
|
||||
while(1) {
|
||||
@@ -1040,14 +1036,16 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if(delname)
|
||||
iq->dp = dns_cache_find_delegation(qstate->env, delname,
|
||||
delnamelen, iq->qchase.qtype, iq->qchase.qclass,
|
||||
qstate->region, &iq->deleg_msg, *qstate->env->now);
|
||||
qstate->region, &iq->deleg_msg,
|
||||
*qstate->env->now+qstate->prefetch_leeway);
|
||||
else iq->dp = NULL;
|
||||
|
||||
/* If the cache has returned nothing, then we have a
|
||||
* root priming situation. */
|
||||
if(iq->dp == NULL) {
|
||||
/* if there is a stub, then no root prime needed */
|
||||
int r = prime_stub(qstate, iq, ie, id, &iq->qchase);
|
||||
int r = prime_stub(qstate, iq, id, delname,
|
||||
iq->qchase.qclass);
|
||||
if(r == 2)
|
||||
break; /* got noprime-stub-zone, continue */
|
||||
else if(r)
|
||||
@@ -1056,7 +1054,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->qchase.qclass)) {
|
||||
/* forward zone root, no root prime needed */
|
||||
/* fill in some dp - safety belt */
|
||||
iq->dp = hints_lookup_root(ie->hints,
|
||||
iq->dp = hints_lookup_root(qstate->env->hints,
|
||||
iq->qchase.qclass);
|
||||
if(!iq->dp) {
|
||||
log_err("internal error: no hints dp");
|
||||
@@ -1073,7 +1071,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
/* Note that the result of this will set a new
|
||||
* DelegationPoint based on the result of priming. */
|
||||
if(!prime_root(qstate, iq, ie, id, iq->qchase.qclass))
|
||||
if(!prime_root(qstate, iq, id, iq->qchase.qclass))
|
||||
return error_response(qstate, id,
|
||||
LDNS_RCODE_REFUSED);
|
||||
|
||||
@@ -1102,7 +1100,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* use safety belt */
|
||||
verbose(VERB_QUERY, "Cache has root NS but "
|
||||
"no addresses. Fallback to the safety belt.");
|
||||
iq->dp = hints_lookup_root(ie->hints,
|
||||
iq->dp = hints_lookup_root(qstate->env->hints,
|
||||
iq->qchase.qclass);
|
||||
/* note deleg_msg is from previous lookup,
|
||||
* but RD is on, so it is not used */
|
||||
@@ -1149,20 +1147,37 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
*
|
||||
* @param qstate: query state.
|
||||
* @param iq: iterator query state.
|
||||
* @param ie: iterator shared global environment.
|
||||
* @param id: module id.
|
||||
* @return true if the event needs more request processing immediately,
|
||||
* false if not.
|
||||
*/
|
||||
static int
|
||||
processInitRequest2(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
struct iter_env* ie, int id)
|
||||
int id)
|
||||
{
|
||||
uint8_t* delname;
|
||||
size_t delnamelen;
|
||||
log_query_info(VERB_QUERY, "resolving (init part 2): ",
|
||||
&qstate->qinfo);
|
||||
|
||||
if(iq->refetch_glue) {
|
||||
if(!iq->dp) {
|
||||
log_err("internal or malloc fail: no dp for refetch");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
delname = iq->dp->name;
|
||||
delnamelen = iq->dp->namelen;
|
||||
} else {
|
||||
delname = iq->qchase.qname;
|
||||
delnamelen = iq->qchase.qname_len;
|
||||
}
|
||||
if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue) {
|
||||
if(!dname_is_root(delname))
|
||||
dname_remove_label(&delname, &delnamelen);
|
||||
iq->refetch_glue = 0; /* if CNAME causes restart, no refetch */
|
||||
}
|
||||
/* Check to see if we need to prime a stub zone. */
|
||||
if(prime_stub(qstate, iq, ie, id, &iq->qchase)) {
|
||||
if(prime_stub(qstate, iq, id, delname, iq->qchase.qclass)) {
|
||||
/* A priming sub request was made */
|
||||
return 0;
|
||||
}
|
||||
@@ -1259,7 +1274,8 @@ generate_parentside_target_query(struct module_qstate* qstate,
|
||||
} else {
|
||||
subiq->dp = dns_cache_find_delegation(qstate->env,
|
||||
name, namelen, qtype, qclass, subq->region,
|
||||
&subiq->deleg_msg, *qstate->env->now);
|
||||
&subiq->deleg_msg,
|
||||
*qstate->env->now+subq->prefetch_leeway);
|
||||
/* if no dp, then it's from root, refetch unneeded */
|
||||
if(subiq->dp) {
|
||||
subiq->dnssec_expected = iter_indicates_dnssec(
|
||||
@@ -1414,7 +1430,24 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
verbose(VERB_ALGO, "No more query targets, attempting last resort");
|
||||
log_assert(iq->dp);
|
||||
|
||||
if(!iq->dp->has_parent_side_NS) {
|
||||
if(!iq->dp->has_parent_side_NS && dname_is_root(iq->dp->name)) {
|
||||
struct delegpt* p = hints_lookup_root(qstate->env->hints,
|
||||
iq->qchase.qclass);
|
||||
if(p) {
|
||||
struct delegpt_ns* ns;
|
||||
struct delegpt_addr* a;
|
||||
for(ns = p->nslist; ns; ns=ns->next) {
|
||||
(void)delegpt_add_ns(iq->dp, qstate->region,
|
||||
ns->name, (int)ns->lame);
|
||||
}
|
||||
for(a = p->target_list; a; a=a->next_target) {
|
||||
(void)delegpt_add_addr(iq->dp, qstate->region,
|
||||
&a->addr, a->addrlen, a->bogus,
|
||||
a->lame);
|
||||
}
|
||||
}
|
||||
iq->dp->has_parent_side_NS = 1;
|
||||
} else if(!iq->dp->has_parent_side_NS) {
|
||||
if(!iter_lookup_parent_NS_from_cache(qstate->env, iq->dp,
|
||||
qstate->region, &qstate->qinfo)
|
||||
|| !iq->dp->has_parent_side_NS) {
|
||||
@@ -1425,6 +1458,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->deleg_msg = NULL;
|
||||
iq->refetch_glue = 1;
|
||||
iq->query_restart_count++;
|
||||
iq->sent_count = 0;
|
||||
return next_state(iq, INIT_REQUEST_STATE);
|
||||
}
|
||||
}
|
||||
@@ -1507,6 +1541,59 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find the NS record set that will resolve a qtype DS query. Due
|
||||
* to grandparent/grandchild reasons we did not get a proper lookup right
|
||||
* away. We need to create type NS queries until we get the right parent
|
||||
* for this lookup. We remove labels from the query to find the right point.
|
||||
* If we end up at the old dp name, then there is no solution.
|
||||
*
|
||||
* @param qstate: query state.
|
||||
* @param iq: iterator query state.
|
||||
* @param id: module id.
|
||||
* @return true if the event requires more immediate processing, false if
|
||||
* not. This is generally only true when forwarding the request to
|
||||
* the final state (i.e., on answer).
|
||||
*/
|
||||
static int
|
||||
processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id)
|
||||
{
|
||||
struct module_qstate* subq = NULL;
|
||||
verbose(VERB_ALGO, "processDSNSFind");
|
||||
|
||||
if(!iq->dsns_point) {
|
||||
/* initialize */
|
||||
iq->dsns_point = iq->qchase.qname;
|
||||
iq->dsns_point_len = iq->qchase.qname_len;
|
||||
}
|
||||
/* robustcheck for internal error: we are not underneath the dp */
|
||||
if(!dname_subdomain_c(iq->dsns_point, iq->dp->name)) {
|
||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
/* go up one (more) step, until we hit the dp, if so, end */
|
||||
dname_remove_label(&iq->dsns_point, &iq->dsns_point_len);
|
||||
if(query_dname_compare(iq->dsns_point, iq->dp->name) == 0) {
|
||||
/* there was no inbetween nameserver, use the old delegation
|
||||
* point again. And this time, because dsns_point is nonNULL
|
||||
* we are going to accept the (bad) result */
|
||||
iq->state = QUERYTARGETS_STATE;
|
||||
return 1;
|
||||
}
|
||||
iq->state = DSNS_FIND_STATE;
|
||||
|
||||
/* spawn NS lookup (validation not needed, this is for DS lookup) */
|
||||
log_nametypeclass(VERB_ALGO, "fetch nameservers",
|
||||
iq->dsns_point, LDNS_RR_TYPE_NS, iq->qchase.qclass);
|
||||
if(!generate_sub_request(iq->dsns_point, iq->dsns_point_len,
|
||||
LDNS_RR_TYPE_NS, iq->qchase.qclass, qstate, id, iq,
|
||||
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0)) {
|
||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the request event state where the request will be sent to one of
|
||||
* its current query targets. This state also handles issuing target lookup
|
||||
@@ -1537,8 +1624,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
|
||||
log_query_info(VERB_QUERY, "processQueryTargets:", &qstate->qinfo);
|
||||
verbose(VERB_ALGO, "processQueryTargets: targetqueries %d, "
|
||||
"currentqueries %d", iq->num_target_queries,
|
||||
iq->num_current_queries);
|
||||
"currentqueries %d sentcount %d", iq->num_target_queries,
|
||||
iq->num_current_queries, iq->sent_count);
|
||||
|
||||
/* Make sure that we haven't run away */
|
||||
/* FIXME: is this check even necessary? */
|
||||
@@ -1547,6 +1634,11 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
"number of referrrals with %d", iq->referral_count);
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(iq->sent_count > MAX_SENT_COUNT) {
|
||||
verbose(VERB_QUERY, "request has exceeded the maximum "
|
||||
"number of sends with %d", iq->sent_count);
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
/* Make sure we have a delegation point, otherwise priming failed
|
||||
* or another failure occurred */
|
||||
@@ -1573,7 +1665,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* < not <=, because although the array is large enough for <=, the
|
||||
* generated query will immediately be discarded due to depth and
|
||||
* that servfail is cached, which is not good as opportunism goes. */
|
||||
if(iq->depth < ie->max_dependency_depth) {
|
||||
if(iq->depth < ie->max_dependency_depth
|
||||
&& iq->sent_count < TARGET_FETCH_STOP) {
|
||||
tf_policy = ie->target_fetch_policy[iq->depth];
|
||||
}
|
||||
|
||||
@@ -1596,7 +1689,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* the current caps_server is the number of fallbacks sent.
|
||||
* the original query is one that matched too, so we have
|
||||
* caps_server+1 number of matching queries now */
|
||||
if(iq->caps_server+1 >= naddr*3) {
|
||||
if(iq->caps_server+1 >= naddr*3 ||
|
||||
iq->caps_server+1 >= MAX_SENT_COUNT) {
|
||||
/* we're done, process the response */
|
||||
verbose(VERB_ALGO, "0x20 fallback had %d responses "
|
||||
"match for %d wanted, done.",
|
||||
@@ -1605,6 +1699,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iter_dec_attempts(iq->dp, 3); /* space for fallback */
|
||||
iq->num_current_queries++; /* RespState decrements it*/
|
||||
iq->referral_count++; /* make sure we don't loop */
|
||||
iq->sent_count = 0;
|
||||
iq->state = QUERY_RESP_STATE;
|
||||
return 1;
|
||||
}
|
||||
@@ -1712,7 +1807,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->qchase.qname, iq->qchase.qname_len,
|
||||
iq->qchase.qtype, iq->qchase.qclass,
|
||||
iq->chase_flags | (iq->chase_to_rd?BIT_RD:0), EDNS_DO|BIT_CD,
|
||||
iq->dnssec_expected, &target->addr, target->addrlen, qstate);
|
||||
iq->dnssec_expected, &target->addr, target->addrlen,
|
||||
iq->dp->name, iq->dp->namelen, qstate);
|
||||
if(!outq) {
|
||||
log_addr(VERB_DETAIL, "error sending query to auth server",
|
||||
&target->addr, target->addrlen);
|
||||
@@ -1720,6 +1816,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
outbound_list_insert(&iq->outlist, outq);
|
||||
iq->num_current_queries++;
|
||||
iq->sent_count++;
|
||||
qstate->ext_state[id] = module_wait_reply;
|
||||
|
||||
return 0;
|
||||
@@ -1818,9 +1915,25 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
(iq->response->rep->an_numrrsets?"ANSWER":
|
||||
"nodata ANSWER"));
|
||||
}
|
||||
if(!iter_dns_store(qstate->env, &iq->response->qinfo,
|
||||
iq->response->rep, 0, qstate->prefetch_leeway))
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
/* if qtype is DS, check we have the right level of answer,
|
||||
* like grandchild answer but we need the middle, reject it */
|
||||
if(iq->qchase.qtype == LDNS_RR_TYPE_DS && !iq->dsns_point
|
||||
&& !(iq->chase_flags&BIT_RD)
|
||||
&& iter_ds_toolow(iq->response, iq->dp)
|
||||
&& iter_dp_cangodown(&iq->qchase, iq->dp)) {
|
||||
/* close down outstanding requests to be discarded */
|
||||
outbound_list_clear(&iq->outlist);
|
||||
iq->num_current_queries = 0;
|
||||
fptr_ok(fptr_whitelist_modenv_detach_subs(
|
||||
qstate->env->detach_subs));
|
||||
(*qstate->env->detach_subs)(qstate);
|
||||
iq->num_target_queries = 0;
|
||||
return processDSNSFind(qstate, iq, id);
|
||||
}
|
||||
iter_dns_store(qstate->env, &iq->response->qinfo,
|
||||
iq->response->rep, 0, qstate->prefetch_leeway,
|
||||
iq->dp&&iq->dp->has_parent_side_NS,
|
||||
qstate->region);
|
||||
/* close down outstanding requests to be discarded */
|
||||
outbound_list_clear(&iq->outlist);
|
||||
iq->num_current_queries = 0;
|
||||
@@ -1857,10 +1970,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
)) {
|
||||
/* Store the referral under the current query */
|
||||
/* no prefetch-leeway, since its not the answer */
|
||||
if(!iter_dns_store(qstate->env, &iq->response->qinfo,
|
||||
iq->response->rep, 1, 0))
|
||||
return error_response(qstate, id,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
iter_dns_store(qstate->env, &iq->response->qinfo,
|
||||
iq->response->rep, 1, 0, 0, NULL);
|
||||
if(iq->store_parent_NS)
|
||||
iter_store_parentside_NS(qstate->env,
|
||||
iq->response->rep);
|
||||
@@ -1896,6 +2007,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
delegpt_log(VERB_ALGO, iq->dp);
|
||||
/* Count this as a referral. */
|
||||
iq->referral_count++;
|
||||
iq->sent_count = 0;
|
||||
/* see if the next dp is a trust anchor, or a DS was sent
|
||||
* along, indicating dnssec is expected for next zone */
|
||||
iq->dnssec_expected = iter_indicates_dnssec(qstate->env,
|
||||
@@ -1934,6 +2046,20 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if(verbosity >= VERB_ALGO)
|
||||
log_dns_msg("cname msg", &iq->response->qinfo,
|
||||
iq->response->rep);
|
||||
/* if qtype is DS, check we have the right level of answer,
|
||||
* like grandchild answer but we need the middle, reject it */
|
||||
if(iq->qchase.qtype == LDNS_RR_TYPE_DS && !iq->dsns_point
|
||||
&& !(iq->chase_flags&BIT_RD)
|
||||
&& iter_ds_toolow(iq->response, iq->dp)
|
||||
&& iter_dp_cangodown(&iq->qchase, iq->dp)) {
|
||||
outbound_list_clear(&iq->outlist);
|
||||
iq->num_current_queries = 0;
|
||||
fptr_ok(fptr_whitelist_modenv_detach_subs(
|
||||
qstate->env->detach_subs));
|
||||
(*qstate->env->detach_subs)(qstate);
|
||||
iq->num_target_queries = 0;
|
||||
return processDSNSFind(qstate, iq, id);
|
||||
}
|
||||
/* Process the CNAME response. */
|
||||
if(!handle_cname_response(qstate, iq, iq->response,
|
||||
&sname, &snamelen))
|
||||
@@ -1942,17 +2068,19 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* NOTE : set referral=1, so that rrsets get stored but not
|
||||
* the partial query answer (CNAME only). */
|
||||
/* prefetchleeway applied because this updates answer parts */
|
||||
if(!iter_dns_store(qstate->env, &iq->response->qinfo,
|
||||
iq->response->rep, 1, qstate->prefetch_leeway))
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
iter_dns_store(qstate->env, &iq->response->qinfo,
|
||||
iq->response->rep, 1, qstate->prefetch_leeway,
|
||||
iq->dp&&iq->dp->has_parent_side_NS, NULL);
|
||||
/* set the current request's qname to the new value. */
|
||||
iq->qchase.qname = sname;
|
||||
iq->qchase.qname_len = snamelen;
|
||||
/* Clear the query state, since this is a query restart. */
|
||||
iq->deleg_msg = NULL;
|
||||
iq->dp = NULL;
|
||||
iq->dsns_point = NULL;
|
||||
/* Note the query restart. */
|
||||
iq->query_restart_count++;
|
||||
iq->sent_count = 0;
|
||||
|
||||
/* stop current outstanding queries.
|
||||
* FIXME: should the outstanding queries be waited for and
|
||||
@@ -2211,6 +2339,41 @@ processTargetResponse(struct module_qstate* qstate, int id,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process response for DS NS Find queries, that attempt to find the delegation
|
||||
* point where we ask the DS query from.
|
||||
*
|
||||
* @param qstate: query state.
|
||||
* @param id: module id.
|
||||
* @param forq: super query state.
|
||||
*/
|
||||
static void
|
||||
processDSNSResponse(struct module_qstate* qstate, int id,
|
||||
struct module_qstate* forq)
|
||||
{
|
||||
struct iter_qstate* foriq = (struct iter_qstate*)forq->minfo[id];
|
||||
|
||||
/* if the finished (iq->response) query has no NS set: continue
|
||||
* up to look for the right dp; nothing to change, do DPNSstate */
|
||||
if(qstate->return_rcode != LDNS_RCODE_NOERROR)
|
||||
return; /* seek further */
|
||||
/* find the NS RRset (without allowing CNAMEs) */
|
||||
if(!reply_find_rrset(qstate->return_msg->rep, qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len, LDNS_RR_TYPE_NS,
|
||||
qstate->qinfo.qclass)){
|
||||
return; /* seek further */
|
||||
}
|
||||
|
||||
/* else, store as DP and continue at querytargets */
|
||||
foriq->state = QUERYTARGETS_STATE;
|
||||
foriq->dp = delegpt_from_message(qstate->return_msg, forq->region);
|
||||
if(!foriq->dp) {
|
||||
log_err("out of memory in dsns dp alloc");
|
||||
return; /* dp==NULL in QUERYTARGETS makes SERVFAIL */
|
||||
}
|
||||
/* success, go query the querytargets in the new dp (and go down) */
|
||||
}
|
||||
|
||||
/**
|
||||
* Process response for qclass=ANY queries for a particular class.
|
||||
* Append to result or error-exit.
|
||||
@@ -2320,7 +2483,6 @@ static int
|
||||
processCollectClass(struct module_qstate* qstate, int id)
|
||||
{
|
||||
struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id];
|
||||
struct iter_env* ie = (struct iter_env*)qstate->env->modinfo[id];
|
||||
struct module_qstate* subq;
|
||||
/* If qchase.qclass == 0 then send out queries for all classes.
|
||||
* Otherwise, do nothing (wait for all answers to arrive and the
|
||||
@@ -2329,7 +2491,8 @@ processCollectClass(struct module_qstate* qstate, int id)
|
||||
if(iq->qchase.qclass == 0) {
|
||||
uint16_t c = 0;
|
||||
iq->qchase.qclass = LDNS_RR_CLASS_ANY;
|
||||
while(iter_get_next_root(ie->hints, qstate->env->fwds, &c)) {
|
||||
while(iter_get_next_root(qstate->env->hints,
|
||||
qstate->env->fwds, &c)) {
|
||||
/* generate query for this class */
|
||||
log_nametypeclass(VERB_ALGO, "spawn collect query",
|
||||
qstate->qinfo.qname, qstate->qinfo.qtype, c);
|
||||
@@ -2417,10 +2580,10 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* but only if we did recursion. The nonrecursion referral
|
||||
* from cache does not need to be stored in the msg cache. */
|
||||
if(qstate->query_flags&BIT_RD) {
|
||||
if(!iter_dns_store(qstate->env, &qstate->qinfo,
|
||||
iq->response->rep, 0, qstate->prefetch_leeway))
|
||||
return error_response(qstate, id,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
iter_dns_store(qstate->env, &qstate->qinfo,
|
||||
iq->response->rep, 0, qstate->prefetch_leeway,
|
||||
iq->dp&&iq->dp->has_parent_side_NS,
|
||||
qstate->region);
|
||||
}
|
||||
}
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
@@ -2444,6 +2607,9 @@ iter_inform_super(struct module_qstate* qstate, int id,
|
||||
{
|
||||
if(!qstate->is_priming && super->qinfo.qclass == LDNS_RR_CLASS_ANY)
|
||||
processClassResponse(qstate, id, super);
|
||||
else if(super->qinfo.qtype == LDNS_RR_TYPE_DS && ((struct iter_qstate*)
|
||||
super->minfo[id])->state == DSNS_FIND_STATE)
|
||||
processDSNSResponse(qstate, id, super);
|
||||
else if(qstate->return_rcode != LDNS_RCODE_NOERROR)
|
||||
error_supers(qstate, id, super);
|
||||
else if(qstate->is_priming)
|
||||
@@ -2476,7 +2642,7 @@ iter_handle(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
cont = processInitRequest(qstate, iq, ie, id);
|
||||
break;
|
||||
case INIT_REQUEST_2_STATE:
|
||||
cont = processInitRequest2(qstate, iq, ie, id);
|
||||
cont = processInitRequest2(qstate, iq, id);
|
||||
break;
|
||||
case INIT_REQUEST_3_STATE:
|
||||
cont = processInitRequest3(qstate, iq, id);
|
||||
@@ -2493,6 +2659,9 @@ iter_handle(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
case COLLECT_CLASS_STATE:
|
||||
cont = processCollectClass(qstate, id);
|
||||
break;
|
||||
case DSNS_FIND_STATE:
|
||||
cont = processDSNSFind(qstate, iq, id);
|
||||
break;
|
||||
case FINISHED_STATE:
|
||||
cont = processFinished(qstate, iq, id);
|
||||
break;
|
||||
@@ -2688,8 +2857,7 @@ iter_get_mem(struct module_env* env, int id)
|
||||
if(!ie)
|
||||
return 0;
|
||||
return sizeof(*ie) + sizeof(int)*((size_t)ie->max_dependency_depth+1)
|
||||
+ hints_get_mem(ie->hints) + donotq_get_mem(ie->donotq)
|
||||
+ priv_get_mem(ie->priv);
|
||||
+ donotq_get_mem(ie->donotq) + priv_get_mem(ie->priv);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2724,6 +2892,8 @@ iter_state_to_string(enum iter_state state)
|
||||
return "PRIME RESPONSE STATE";
|
||||
case COLLECT_CLASS_STATE :
|
||||
return "COLLECT CLASS STATE";
|
||||
case DSNS_FIND_STATE :
|
||||
return "DSNS FIND STATE";
|
||||
case QUERY_RESP_STATE :
|
||||
return "QUERY RESPONSE STATE";
|
||||
case FINISHED_STATE :
|
||||
|
||||
+16
-8
@@ -56,6 +56,10 @@ struct iter_priv;
|
||||
#define MAX_RESTART_COUNT 8
|
||||
/** max number of referrals. Makes sure resolver does not run away */
|
||||
#define MAX_REFERRAL_COUNT 130
|
||||
/** max number of queries-sent-out. Make sure large NS set does not loop */
|
||||
#define MAX_SENT_COUNT 16
|
||||
/** at what query-sent-count to stop target fetch policy */
|
||||
#define TARGET_FETCH_STOP 3
|
||||
/** how nice is a server without further information, in msec
|
||||
* Equals rtt initial timeout value.
|
||||
*/
|
||||
@@ -82,14 +86,6 @@ struct iter_priv;
|
||||
* Global state for the iterator.
|
||||
*/
|
||||
struct iter_env {
|
||||
/**
|
||||
* The hints -- these aren't stored in the cache because they don't
|
||||
* expire. The hints are always used to "prime" the cache. Note
|
||||
* that both root hints and stub zone "hints" are stored in this
|
||||
* data structure.
|
||||
*/
|
||||
struct iter_hints* hints;
|
||||
|
||||
/** A flag to indicate whether or not we have an IPv6 route */
|
||||
int supports_ipv6;
|
||||
|
||||
@@ -159,6 +155,10 @@ enum iter_state {
|
||||
* it spawns off queries for every class, it returns here. */
|
||||
COLLECT_CLASS_STATE,
|
||||
|
||||
/** Find NS record to resolve DS record from, walking to the right
|
||||
* NS spot until we find it */
|
||||
DSNS_FIND_STATE,
|
||||
|
||||
/** Responses that are to be returned upstream end at this state.
|
||||
* As well as responses to target queries. */
|
||||
FINISHED_STATE
|
||||
@@ -252,6 +252,9 @@ struct iter_qstate {
|
||||
/** the number of times this query as followed a referral. */
|
||||
int referral_count;
|
||||
|
||||
/** number of queries fired off */
|
||||
int sent_count;
|
||||
|
||||
/**
|
||||
* The query must store NS records from referrals as parentside RRs
|
||||
* Enabled once it hits resolution problems, to throttle retries.
|
||||
@@ -272,6 +275,11 @@ struct iter_qstate {
|
||||
/** the parent-side-glue element (NULL if none, its first match) */
|
||||
struct ub_packed_rrset_key* pside_glue;
|
||||
|
||||
/** If nonNULL we are walking upwards from DS query to find NS */
|
||||
uint8_t* dsns_point;
|
||||
/** length of the dname in dsns_point */
|
||||
size_t dsns_point_len;
|
||||
|
||||
/**
|
||||
* expected dnssec information for this iteration step.
|
||||
* If dnssec rrsigs are expected and not given, the server is marked
|
||||
|
||||
@@ -1117,3 +1117,8 @@ int ub_ctx_data_remove(struct ub_ctx* ctx, char *data)
|
||||
free(nm);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
|
||||
const char* ub_version(void)
|
||||
{
|
||||
return PACKAGE_VERSION;
|
||||
}
|
||||
|
||||
+57
-12
@@ -44,6 +44,7 @@
|
||||
#include "config.h"
|
||||
#include <ldns/dname.h>
|
||||
#include <ldns/wire2host.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include "libunbound/libworker.h"
|
||||
#include "libunbound/context.h"
|
||||
#include "libunbound/unbound.h"
|
||||
@@ -57,6 +58,7 @@
|
||||
#include "util/random.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/netevent.h"
|
||||
#include "util/storage/lookup3.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/data/dname.h"
|
||||
@@ -64,6 +66,7 @@
|
||||
#include "util/data/msgencode.h"
|
||||
#include "util/tube.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
|
||||
/** handle new query command for bg worker */
|
||||
static void handle_newq(struct libworker* w, uint8_t* buf, uint32_t len);
|
||||
@@ -81,9 +84,11 @@ libworker_delete(struct libworker* w)
|
||||
ldns_buffer_free(w->env->scratch_buffer);
|
||||
regional_destroy(w->env->scratch);
|
||||
forwards_delete(w->env->fwds);
|
||||
hints_delete(w->env->hints);
|
||||
ub_randfree(w->env->rnd);
|
||||
free(w->env);
|
||||
}
|
||||
SSL_CTX_free(w->sslctx);
|
||||
outside_network_delete(w->back);
|
||||
comm_base_delete(w->base);
|
||||
free(w);
|
||||
@@ -124,10 +129,24 @@ libworker_setup(struct ub_ctx* ctx, int is_bg)
|
||||
forwards_delete(w->env->fwds);
|
||||
w->env->fwds = NULL;
|
||||
}
|
||||
w->env->hints = hints_create();
|
||||
if(w->env->hints && !hints_apply_cfg(w->env->hints, cfg)) {
|
||||
hints_delete(w->env->hints);
|
||||
w->env->hints = NULL;
|
||||
}
|
||||
if(cfg->ssl_upstream) {
|
||||
w->sslctx = connect_sslctx_create(NULL, NULL, NULL);
|
||||
if(!w->sslctx) {
|
||||
/* to make the setup fail after unlock */
|
||||
hints_delete(w->env->hints);
|
||||
w->env->hints = NULL;
|
||||
}
|
||||
}
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
}
|
||||
if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds) {
|
||||
if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds ||
|
||||
!w->env->hints) {
|
||||
libworker_delete(w);
|
||||
return NULL;
|
||||
}
|
||||
@@ -150,6 +169,19 @@ libworker_setup(struct ub_ctx* ctx, int is_bg)
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
}
|
||||
if(1) {
|
||||
/* primitive lockout for threading: if it overwrites another
|
||||
* thread it is like wiping the cache (which is likely empty
|
||||
* at the start) */
|
||||
/* note we are holding the ctx lock in normal threaded
|
||||
* cases so that is solved properly, it is only for many ctx
|
||||
* in different threads that this may clash */
|
||||
static int done_raninit = 0;
|
||||
if(!done_raninit) {
|
||||
done_raninit = 1;
|
||||
hash_set_raninit((uint32_t)ub_random(w->env->rnd));
|
||||
}
|
||||
}
|
||||
seed = 0;
|
||||
|
||||
w->base = comm_base_create(0);
|
||||
@@ -171,7 +203,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg)
|
||||
cfg->do_tcp?cfg->outgoing_num_tcp:0,
|
||||
w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id,
|
||||
ports, numports, cfg->unwanted_threshold,
|
||||
&libworker_alloc_cleanup, w, cfg->do_udp);
|
||||
&libworker_alloc_cleanup, w, cfg->do_udp, w->sslctx);
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
}
|
||||
@@ -261,7 +293,12 @@ libworker_dobg(void* arg)
|
||||
/* setup */
|
||||
uint32_t m;
|
||||
struct libworker* w = (struct libworker*)arg;
|
||||
struct ub_ctx* ctx = w->ctx;
|
||||
struct ub_ctx* ctx;
|
||||
if(!w) {
|
||||
log_err("libunbound bg worker init failed, nomem");
|
||||
return NULL;
|
||||
}
|
||||
ctx = w->ctx;
|
||||
log_thread_set(&w->thread_num);
|
||||
#ifdef THREADS_DISABLED
|
||||
/* we are forked */
|
||||
@@ -270,10 +307,6 @@ libworker_dobg(void* arg)
|
||||
tube_close_write(ctx->qq_pipe);
|
||||
tube_close_read(ctx->rr_pipe);
|
||||
#endif
|
||||
if(!w) {
|
||||
log_err("libunbound bg worker init failed, nomem");
|
||||
return NULL;
|
||||
}
|
||||
if(!tube_setup_bg_listen(ctx->qq_pipe, w->base,
|
||||
libworker_handle_control_cmd, w)) {
|
||||
log_err("libunbound bg worker init failed, no bglisten");
|
||||
@@ -310,11 +343,11 @@ int libworker_bg(struct ub_ctx* ctx)
|
||||
if(ctx->dothread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
w = libworker_setup(ctx, 1);
|
||||
if(!w) return UB_NOMEM;
|
||||
w->is_bg_thread = 1;
|
||||
#ifdef ENABLE_LOCK_CHECKS
|
||||
w->thread_num = 1; /* for nicer DEBUG checklocks */
|
||||
#endif
|
||||
if(!w) return UB_NOMEM;
|
||||
ub_thread_create(&ctx->bg_tid, libworker_dobg, w);
|
||||
} else {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
@@ -610,6 +643,8 @@ libworker_bg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s,
|
||||
return;
|
||||
}
|
||||
q->msg_security = s;
|
||||
if(!buf)
|
||||
buf = q->w->env->scratch_buffer;
|
||||
if(rcode != 0) {
|
||||
error_encode(buf, rcode, NULL, 0, BIT_RD, NULL);
|
||||
}
|
||||
@@ -684,7 +719,7 @@ outbound_entry_compare(void* a, void* b)
|
||||
struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
|
||||
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
|
||||
int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct module_qstate* q)
|
||||
uint8_t* zone, size_t zonelen, struct module_qstate* q)
|
||||
{
|
||||
struct libworker* w = (struct libworker*)q->env->worker;
|
||||
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
|
||||
@@ -694,9 +729,9 @@ struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
|
||||
e->qstate = q;
|
||||
e->qsent = outnet_serviced_query(w->back, qname,
|
||||
qnamelen, qtype, qclass, flags, dnssec, want_dnssec,
|
||||
q->env->cfg->tcp_upstream, addr, addrlen,
|
||||
libworker_handle_service_reply, e, w->back->udp_buff,
|
||||
&outbound_entry_compare);
|
||||
q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr,
|
||||
addrlen, zone, zonelen, libworker_handle_service_reply, e,
|
||||
w->back->udp_buff, &outbound_entry_compare);
|
||||
if(!e->qsent) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -838,6 +873,16 @@ void worker_probe_timer_cb(void* ATTR_UNUSED(arg))
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void worker_start_accept(void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void worker_stop_accept(void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
int order_lock_cmp(const void* ATTR_UNUSED(e1), const void* ATTR_UNUSED(e2))
|
||||
{
|
||||
log_assert(0);
|
||||
|
||||
@@ -81,6 +81,8 @@ struct libworker {
|
||||
struct outside_network* back;
|
||||
/** random() table for this worker. */
|
||||
struct ub_randstate* rndstate;
|
||||
/** sslcontext for SSL wrapped DNS over TCP queries */
|
||||
void* sslctx;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -118,6 +120,8 @@ void libworker_alloc_cleanup(void* arg);
|
||||
* @param want_dnssec: signatures needed.
|
||||
* @param addr: where to.
|
||||
* @param addrlen: length of addr.
|
||||
* @param zone: delegation point name.
|
||||
* @param zonelen: length of zone name wireformat dname.
|
||||
* @param q: wich query state to reactivate upon return.
|
||||
* @return: false on failure (memory or socket related). no query was
|
||||
* sent.
|
||||
@@ -125,7 +129,7 @@ void libworker_alloc_cleanup(void* arg);
|
||||
struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
|
||||
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
|
||||
int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct module_qstate* q);
|
||||
uint8_t* zone, size_t zonelen, struct module_qstate* q);
|
||||
|
||||
/** process incoming replies from the network */
|
||||
int libworker_handle_reply(struct comm_point* c, void* arg, int error,
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python
|
||||
from unbound import ub_ctx, RR_TYPE_A, RR_TYPE_RRSIG, RR_TYPE_NSEC, RR_TYPE_NSEC3
|
||||
import ldns
|
||||
|
||||
def dnssecParse(domain, rrType=RR_TYPE_A):
|
||||
print "Resolving domain", domain
|
||||
s, r = resolver.resolve(domain)
|
||||
print "status: %s, secure: %s, rcode: %s, havedata: %s, answer_len; %s" % (s, r.secure, r.rcode_str, r.havedata, r.answer_len)
|
||||
|
||||
s, pkt = ldns.ldns_wire2pkt(r.packet)
|
||||
if s != 0:
|
||||
raise RuntimeError("Error parsing DNS packet")
|
||||
|
||||
rrsigs = pkt.rr_list_by_type(RR_TYPE_RRSIG, ldns.LDNS_SECTION_ANSWER)
|
||||
print "RRSIGs from answer:", rrsigs
|
||||
|
||||
rrsigs = pkt.rr_list_by_type(RR_TYPE_RRSIG, ldns.LDNS_SECTION_AUTHORITY)
|
||||
print "RRSIGs from authority:", rrsigs
|
||||
|
||||
nsecs = pkt.rr_list_by_type(RR_TYPE_NSEC, ldns.LDNS_SECTION_AUTHORITY)
|
||||
print "NSECs:", nsecs
|
||||
|
||||
nsec3s = pkt.rr_list_by_type(RR_TYPE_NSEC3, ldns.LDNS_SECTION_AUTHORITY)
|
||||
print "NSEC3s:", nsec3s
|
||||
|
||||
print "---"
|
||||
|
||||
|
||||
resolver = ub_ctx()
|
||||
resolver.add_ta(". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5")
|
||||
|
||||
dnssecParse("nic.cz")
|
||||
dnssecParse("nonexistent-domain-blablabla.cz")
|
||||
dnssecParse("nonexistent-domain-blablabla.root.cz")
|
||||
|
||||
@@ -768,6 +768,10 @@ Result: ['74.125.43.147', '74.125.43.99', '74.125.43.103', '74.125.43.104']
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
PyObject* _packet() {
|
||||
return PyString_FromStringAndSize($self->answer_packet, $self->answer_len);
|
||||
}
|
||||
|
||||
%pythoncode %{
|
||||
def __init__(self):
|
||||
@@ -805,6 +809,7 @@ Result: ['74.125.43.147', '74.125.43.99', '74.125.43.103', '74.125.43.104']
|
||||
return ub_data(self._ub_result_data(self))
|
||||
|
||||
__swig_getmethods__["data"] = _get_data
|
||||
__swig_getmethods__["packet"] = _packet
|
||||
data = property(_get_data, doc="Returns :class:`ub_data` instance containing various decoding functions or None")
|
||||
|
||||
%}
|
||||
|
||||
@@ -26,3 +26,4 @@ ub_ctx_zone_add
|
||||
ub_ctx_zone_remove
|
||||
ub_ctx_data_add
|
||||
ub_ctx_data_remove
|
||||
ub_version
|
||||
|
||||
@@ -543,6 +543,12 @@ int ub_ctx_data_add(struct ub_ctx* ctx, char *data);
|
||||
*/
|
||||
int ub_ctx_data_remove(struct ub_ctx* ctx, char *data);
|
||||
|
||||
/**
|
||||
* Get a version string from the libunbound implementation.
|
||||
* @return a static constant string with the version number.
|
||||
*/
|
||||
const char* ub_version(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -606,10 +606,8 @@ struct config_file {
|
||||
size_t rrset_cache_size;
|
||||
size_t rrset_cache_slabs;
|
||||
int host_ttl;
|
||||
int lame_ttl;
|
||||
size_t infra_cache_slabs;
|
||||
size_t infra_cache_numhosts;
|
||||
size_t infra_cache_lame_size;
|
||||
char* target_fetch_policy;
|
||||
int if_automatic;
|
||||
int num_ifs;
|
||||
|
||||
@@ -41,10 +41,11 @@
|
||||
/* ignore the varargs unused warning from SWIGs internal vararg support */
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include "ldns/ldns.h"
|
||||
#include <ldns/ldns.h>
|
||||
|
||||
#undef _POSIX_C_SOURCE
|
||||
#undef _XOPEN_SOURCE
|
||||
|
||||
@@ -66,7 +66,7 @@ int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, st
|
||||
}
|
||||
|
||||
return dns_cache_store(qstate->env, qinfo, msgrep, is_referral,
|
||||
qstate->prefetch_leeway);
|
||||
qstate->prefetch_leeway, 0, NULL);
|
||||
}
|
||||
|
||||
/* Invalidate the message associated with query_info stored in message cache */
|
||||
|
||||
Vendored
+50
-9
@@ -55,24 +55,58 @@
|
||||
* @param env: module environment with caches.
|
||||
* @param rep: contains list of rrsets to store.
|
||||
* @param now: current time.
|
||||
* @param leeway: during prefetch how much leeway to update TTLs.
|
||||
* This makes rrsets (other than type NS) timeout sooner so they get
|
||||
* updated with a new full TTL.
|
||||
* Type NS does not get this, because it must not be refreshed from the
|
||||
* child domain, but keep counting down properly.
|
||||
* @param pside: if from parentside discovered NS, so that its NS is okay
|
||||
* in a prefetch situation to be updated (without becoming sticky).
|
||||
* @param qrep: update rrsets here if cache is better
|
||||
* @param region: for qrep allocs.
|
||||
*/
|
||||
static void
|
||||
store_rrsets(struct module_env* env, struct reply_info* rep, uint32_t now)
|
||||
store_rrsets(struct module_env* env, struct reply_info* rep, uint32_t now,
|
||||
uint32_t leeway, int pside, struct reply_info* qrep,
|
||||
struct regional* region)
|
||||
{
|
||||
size_t i;
|
||||
/* see if rrset already exists in cache, if not insert it. */
|
||||
for(i=0; i<rep->rrset_count; i++) {
|
||||
rep->ref[i].key = rep->rrsets[i];
|
||||
rep->ref[i].id = rep->rrsets[i]->id;
|
||||
if(rrset_cache_update(env->rrset_cache, &rep->ref[i],
|
||||
env->alloc, now)) /* it was in the cache */
|
||||
/* update ref if it was in the cache */
|
||||
switch(rrset_cache_update(env->rrset_cache, &rep->ref[i],
|
||||
env->alloc, now + ((ntohs(rep->ref[i].key->rk.type)==
|
||||
LDNS_RR_TYPE_NS && !pside)?0:leeway))) {
|
||||
case 0: /* ref unchanged, item inserted */
|
||||
break;
|
||||
case 2: /* ref updated, cache is superior */
|
||||
if(region) {
|
||||
struct ub_packed_rrset_key* ck;
|
||||
lock_rw_rdlock(&rep->ref[i].key->entry.lock);
|
||||
/* if deleted rrset, do not copy it */
|
||||
if(rep->ref[i].key->id == 0)
|
||||
ck = NULL;
|
||||
else ck = packed_rrset_copy_region(
|
||||
rep->ref[i].key, region, now);
|
||||
lock_rw_unlock(&rep->ref[i].key->entry.lock);
|
||||
if(ck) {
|
||||
/* use cached copy if memory allows */
|
||||
qrep->rrsets[i] = ck;
|
||||
}
|
||||
}
|
||||
/* no break: also copy key item */
|
||||
case 1: /* ref updated, item inserted */
|
||||
rep->rrsets[i] = rep->ref[i].key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
hashvalue_t hash, struct reply_info* rep, uint32_t leeway)
|
||||
hashvalue_t hash, struct reply_info* rep, uint32_t leeway, int pside,
|
||||
struct reply_info* qrep, struct regional* region)
|
||||
{
|
||||
struct msgreply_entry* e;
|
||||
uint32_t ttl = rep->ttl;
|
||||
@@ -83,9 +117,11 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
rep->ref[i].key = rep->rrsets[i];
|
||||
rep->ref[i].id = rep->rrsets[i]->id;
|
||||
}
|
||||
reply_info_sortref(rep);
|
||||
|
||||
/* there was a reply_info_sortref(rep) here but it seems to be
|
||||
* unnecessary, because the cache gets locked per rrset. */
|
||||
reply_info_set_ttls(rep, *env->now);
|
||||
store_rrsets(env, rep, *env->now+leeway);
|
||||
store_rrsets(env, rep, *env->now, leeway, pside, qrep, region);
|
||||
if(ttl == 0) {
|
||||
/* we do not store the message, but we did store the RRs,
|
||||
* which could be useful for delegation information */
|
||||
@@ -703,7 +739,8 @@ dns_cache_lookup(struct module_env* env,
|
||||
|
||||
int
|
||||
dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
struct reply_info* msgrep, int is_referral, uint32_t leeway)
|
||||
struct reply_info* msgrep, int is_referral, uint32_t leeway, int pside,
|
||||
struct regional* region)
|
||||
{
|
||||
struct reply_info* rep = NULL;
|
||||
/* alloc, malloc properly (not in region, like msg is) */
|
||||
@@ -724,8 +761,11 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
ref.key = rep->rrsets[i];
|
||||
ref.id = rep->rrsets[i]->id;
|
||||
/*ignore ret: it was in the cache, ref updated */
|
||||
/* no leeway for typeNS */
|
||||
(void)rrset_cache_update(env->rrset_cache, &ref,
|
||||
env->alloc, *env->now + leeway);
|
||||
env->alloc, *env->now +
|
||||
((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS
|
||||
&& !pside) ? 0:leeway));
|
||||
}
|
||||
free(rep);
|
||||
return 1;
|
||||
@@ -746,7 +786,8 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
rep->flags |= (BIT_RA | BIT_QR);
|
||||
rep->flags &= ~(BIT_AA | BIT_CD);
|
||||
h = query_info_hash(&qinf);
|
||||
dns_cache_store_msg(env, &qinf, h, rep, leeway);
|
||||
dns_cache_store_msg(env, &qinf, h, rep, leeway, pside, msgrep,
|
||||
region);
|
||||
/* qname is used inside query_info_entrysetup, and set to
|
||||
* NULL. If it has not been used, free it. free(0) is safe. */
|
||||
free(qinf.qname);
|
||||
|
||||
Vendored
+14
-2
@@ -74,10 +74,16 @@ struct dns_msg {
|
||||
* It will store only the RRsets, not the message.
|
||||
* @param leeway: TTL value, if not 0, other rrsets are considered expired
|
||||
* that many seconds before actual TTL expiry.
|
||||
* @param pside: if true, information came from a server which was fetched
|
||||
* from the parentside of the zonecut. This means that the type NS
|
||||
* can be updated to full TTL even in prefetch situations.
|
||||
* @param region: region to allocate better entries from cache into.
|
||||
* (used when is_referral is false).
|
||||
* @return 0 on alloc error (out of memory).
|
||||
*/
|
||||
int dns_cache_store(struct module_env* env, struct query_info* qinf,
|
||||
struct reply_info* rep, int is_referral, uint32_t leeway);
|
||||
struct reply_info* rep, int is_referral, uint32_t leeway, int pside,
|
||||
struct regional* region);
|
||||
|
||||
/**
|
||||
* Store message in the cache. Stores in message cache and rrset cache.
|
||||
@@ -92,9 +98,15 @@ int dns_cache_store(struct module_env* env, struct query_info* qinf,
|
||||
* Adjusts the reply info TTLs to absolute time.
|
||||
* @param leeway: TTL value, if not 0, other rrsets are considered expired
|
||||
* that many seconds before actual TTL expiry.
|
||||
* @param pside: if true, information came from a server which was fetched
|
||||
* from the parentside of the zonecut. This means that the type NS
|
||||
* can be updated to full TTL even in prefetch situations.
|
||||
* @param qrep: message that can be altered with better rrs from cache.
|
||||
* @param region: to allocate into for qmsg.
|
||||
*/
|
||||
void dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
hashvalue_t hash, struct reply_info* rep, uint32_t leeway);
|
||||
hashvalue_t hash, struct reply_info* rep, uint32_t leeway, int pside,
|
||||
struct reply_info* qrep, struct regional* region);
|
||||
|
||||
/**
|
||||
* Find a delegation from the cache.
|
||||
|
||||
Vendored
+221
-351
@@ -39,7 +39,7 @@
|
||||
* This file contains the infrastructure cache.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ldns/rr.h"
|
||||
#include <ldns/rr.h>
|
||||
#include "services/cache/infra.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/storage/lookup3.h"
|
||||
@@ -52,37 +52,50 @@
|
||||
/** Timeout when only a single probe query per IP is allowed. */
|
||||
#define PROBE_MAXRTO 12000 /* in msec */
|
||||
|
||||
/** number of timeouts for a type when the domain can be blocked ;
|
||||
* even if another type has completely rtt maxed it, the different type
|
||||
* can do this number of packets (until those all timeout too) */
|
||||
#define TIMEOUT_COUNT_MAX 3
|
||||
|
||||
size_t
|
||||
infra_host_sizefunc(void* k, void* ATTR_UNUSED(d))
|
||||
infra_sizefunc(void* k, void* ATTR_UNUSED(d))
|
||||
{
|
||||
struct infra_host_key* key = (struct infra_host_key*)k;
|
||||
return sizeof(*key) + sizeof(struct infra_host_data)
|
||||
struct infra_key* key = (struct infra_key*)k;
|
||||
return sizeof(*key) + sizeof(struct infra_data) + key->namelen
|
||||
+ lock_get_mem(&key->entry.lock);
|
||||
}
|
||||
|
||||
int
|
||||
infra_host_compfunc(void* key1, void* key2)
|
||||
infra_compfunc(void* key1, void* key2)
|
||||
{
|
||||
struct infra_host_key* k1 = (struct infra_host_key*)key1;
|
||||
struct infra_host_key* k2 = (struct infra_host_key*)key2;
|
||||
return sockaddr_cmp(&k1->addr, k1->addrlen, &k2->addr, k2->addrlen);
|
||||
struct infra_key* k1 = (struct infra_key*)key1;
|
||||
struct infra_key* k2 = (struct infra_key*)key2;
|
||||
int r = sockaddr_cmp(&k1->addr, k1->addrlen, &k2->addr, k2->addrlen);
|
||||
if(r != 0)
|
||||
return r;
|
||||
if(k1->namelen != k2->namelen) {
|
||||
if(k1->namelen < k2->namelen)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
return query_dname_compare(k1->zonename, k2->zonename);
|
||||
}
|
||||
|
||||
void
|
||||
infra_host_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
|
||||
infra_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct infra_host_key* key = (struct infra_host_key*)k;
|
||||
struct infra_key* key = (struct infra_key*)k;
|
||||
if(!key)
|
||||
return;
|
||||
lock_rw_destroy(&key->entry.lock);
|
||||
free(key->zonename);
|
||||
free(key);
|
||||
}
|
||||
|
||||
void
|
||||
infra_host_deldatafunc(void* d, void* ATTR_UNUSED(arg))
|
||||
infra_deldatafunc(void* d, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct infra_host_data* data = (struct infra_host_data*)d;
|
||||
lruhash_delete(data->lameness);
|
||||
struct infra_data* data = (struct infra_data*)d;
|
||||
free(data);
|
||||
}
|
||||
|
||||
@@ -91,21 +104,16 @@ infra_create(struct config_file* cfg)
|
||||
{
|
||||
struct infra_cache* infra = (struct infra_cache*)calloc(1,
|
||||
sizeof(struct infra_cache));
|
||||
/* the size of the lameness tables are not counted */
|
||||
size_t maxmem = cfg->infra_cache_numhosts *
|
||||
(sizeof(struct infra_host_key)+sizeof(struct infra_host_data));
|
||||
size_t maxmem = cfg->infra_cache_numhosts * (sizeof(struct infra_key)+
|
||||
sizeof(struct infra_data)+INFRA_BYTES_NAME);
|
||||
infra->hosts = slabhash_create(cfg->infra_cache_slabs,
|
||||
INFRA_HOST_STARTSIZE, maxmem, &infra_host_sizefunc,
|
||||
&infra_host_compfunc, &infra_host_delkeyfunc,
|
||||
&infra_host_deldatafunc, NULL);
|
||||
INFRA_HOST_STARTSIZE, maxmem, &infra_sizefunc, &infra_compfunc,
|
||||
&infra_delkeyfunc, &infra_deldatafunc, NULL);
|
||||
if(!infra->hosts) {
|
||||
free(infra);
|
||||
return NULL;
|
||||
}
|
||||
infra->host_ttl = cfg->host_ttl;
|
||||
infra->lame_ttl = cfg->lame_ttl;
|
||||
infra->max_lame_size = cfg->infra_cache_lame_size;
|
||||
infra->jostle = cfg->jostle_time;
|
||||
return infra;
|
||||
}
|
||||
|
||||
@@ -125,11 +133,8 @@ infra_adjust(struct infra_cache* infra, struct config_file* cfg)
|
||||
if(!infra)
|
||||
return infra_create(cfg);
|
||||
infra->host_ttl = cfg->host_ttl;
|
||||
infra->lame_ttl = cfg->lame_ttl;
|
||||
infra->max_lame_size = cfg->infra_cache_lame_size;
|
||||
infra->jostle = cfg->jostle_time;
|
||||
maxmem = cfg->infra_cache_numhosts *
|
||||
(sizeof(struct infra_host_key)+sizeof(struct infra_host_data));
|
||||
maxmem = cfg->infra_cache_numhosts * (sizeof(struct infra_key)+
|
||||
sizeof(struct infra_data)+INFRA_BYTES_NAME);
|
||||
if(maxmem != slabhash_get_size(infra->hosts) ||
|
||||
cfg->infra_cache_slabs != infra->hosts->size) {
|
||||
infra_delete(infra);
|
||||
@@ -158,65 +163,47 @@ hash_addr(struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
return h;
|
||||
}
|
||||
|
||||
void
|
||||
infra_remove_host(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
/** calculate infra hash for a key */
|
||||
static hashvalue_t
|
||||
hash_infra(struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name)
|
||||
{
|
||||
struct infra_host_key k;
|
||||
k.addrlen = addrlen;
|
||||
memcpy(&k.addr, addr, addrlen);
|
||||
k.entry.hash = hash_addr(addr, addrlen);
|
||||
k.entry.key = (void*)&k;
|
||||
k.entry.data = NULL;
|
||||
slabhash_remove(infra->hosts, k.entry.hash, &k);
|
||||
return dname_query_hash(name, hash_addr(addr, addrlen));
|
||||
}
|
||||
|
||||
/** lookup version that does not check host ttl (you check it) */
|
||||
static struct lruhash_entry*
|
||||
infra_lookup_host_nottl(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int wr)
|
||||
struct lruhash_entry*
|
||||
infra_lookup_nottl(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* name, size_t namelen, int wr)
|
||||
{
|
||||
struct infra_host_key k;
|
||||
struct infra_key k;
|
||||
k.addrlen = addrlen;
|
||||
memcpy(&k.addr, addr, addrlen);
|
||||
k.entry.hash = hash_addr(addr, addrlen);
|
||||
k.namelen = namelen;
|
||||
k.zonename = name;
|
||||
k.entry.hash = hash_infra(addr, addrlen, name);
|
||||
k.entry.key = (void*)&k;
|
||||
k.entry.data = NULL;
|
||||
return slabhash_lookup(infra->hosts, k.entry.hash, &k, wr);
|
||||
}
|
||||
|
||||
struct infra_host_data*
|
||||
infra_lookup_host(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int wr,
|
||||
uint32_t timenow, struct infra_host_key** key)
|
||||
{
|
||||
struct infra_host_data* data;
|
||||
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
||||
addrlen, wr);
|
||||
*key = NULL;
|
||||
if(!e)
|
||||
return NULL;
|
||||
/* check TTL */
|
||||
data = (struct infra_host_data*)e->data;
|
||||
if(data->ttl < timenow) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
return NULL;
|
||||
}
|
||||
*key = (struct infra_host_key*)e->key;
|
||||
return data;
|
||||
}
|
||||
|
||||
/** init the host elements (not lame elems) */
|
||||
/** init the data elements */
|
||||
static void
|
||||
host_entry_init(struct infra_cache* infra, struct lruhash_entry* e,
|
||||
data_entry_init(struct infra_cache* infra, struct lruhash_entry* e,
|
||||
uint32_t timenow)
|
||||
{
|
||||
struct infra_host_data* data = (struct infra_host_data*)e->data;
|
||||
struct infra_data* data = (struct infra_data*)e->data;
|
||||
data->ttl = timenow + infra->host_ttl;
|
||||
rtt_init(&data->rtt);
|
||||
data->edns_version = 0;
|
||||
data->edns_lame_known = 0;
|
||||
data->probedelay = 0;
|
||||
data->isdnsseclame = 0;
|
||||
data->rec_lame = 0;
|
||||
data->lame_type_A = 0;
|
||||
data->lame_other = 0;
|
||||
data->timeout_A = 0;
|
||||
data->timeout_AAAA = 0;
|
||||
data->timeout_other = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,87 +211,100 @@ host_entry_init(struct infra_cache* infra, struct lruhash_entry* e,
|
||||
* @param infra: infra structure with config parameters.
|
||||
* @param addr: host address.
|
||||
* @param addrlen: length of addr.
|
||||
* @param name: name of zone
|
||||
* @param namelen: length of name.
|
||||
* @param tm: time now.
|
||||
* @return: the new entry or NULL on malloc failure.
|
||||
*/
|
||||
static struct lruhash_entry*
|
||||
new_host_entry(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint32_t tm)
|
||||
new_entry(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* name, size_t namelen, uint32_t tm)
|
||||
{
|
||||
struct infra_host_data* data;
|
||||
struct infra_host_key* key = (struct infra_host_key*)malloc(
|
||||
sizeof(struct infra_host_key));
|
||||
struct infra_data* data;
|
||||
struct infra_key* key = (struct infra_key*)malloc(sizeof(*key));
|
||||
if(!key)
|
||||
return NULL;
|
||||
data = (struct infra_host_data*)malloc(
|
||||
sizeof(struct infra_host_data));
|
||||
data = (struct infra_data*)malloc(sizeof(struct infra_data));
|
||||
if(!data) {
|
||||
free(key);
|
||||
return NULL;
|
||||
}
|
||||
key->zonename = memdup(name, namelen);
|
||||
if(!key->zonename) {
|
||||
free(key);
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
key->namelen = namelen;
|
||||
lock_rw_init(&key->entry.lock);
|
||||
key->entry.hash = hash_addr(addr, addrlen);
|
||||
key->entry.hash = hash_infra(addr, addrlen, name);
|
||||
key->entry.key = (void*)key;
|
||||
key->entry.data = (void*)data;
|
||||
key->addrlen = addrlen;
|
||||
memcpy(&key->addr, addr, addrlen);
|
||||
data->lameness = NULL;
|
||||
host_entry_init(infra, &key->entry, tm);
|
||||
data_entry_init(infra, &key->entry, tm);
|
||||
return &key->entry;
|
||||
}
|
||||
|
||||
int
|
||||
infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint32_t timenow, int* edns_vs,
|
||||
uint8_t* edns_lame_known, int* to)
|
||||
socklen_t addrlen, uint8_t* nm, size_t nmlen, uint32_t timenow,
|
||||
int* edns_vs, uint8_t* edns_lame_known, int* to)
|
||||
{
|
||||
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
||||
addrlen, 0);
|
||||
struct infra_host_data* data;
|
||||
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
|
||||
nm, nmlen, 0);
|
||||
struct infra_data* data;
|
||||
int wr = 0;
|
||||
if(e && ((struct infra_host_data*)e->data)->ttl < timenow) {
|
||||
if(e && ((struct infra_data*)e->data)->ttl < timenow) {
|
||||
/* it expired, try to reuse existing entry */
|
||||
int old = ((struct infra_host_data*)e->data)->rtt.rto;
|
||||
int old = ((struct infra_data*)e->data)->rtt.rto;
|
||||
uint8_t tA = ((struct infra_data*)e->data)->timeout_A;
|
||||
uint8_t tAAAA = ((struct infra_data*)e->data)->timeout_AAAA;
|
||||
uint8_t tother = ((struct infra_data*)e->data)->timeout_other;
|
||||
lock_rw_unlock(&e->lock);
|
||||
e = infra_lookup_host_nottl(infra, addr, addrlen, 1);
|
||||
e = infra_lookup_nottl(infra, addr, addrlen, nm, nmlen, 1);
|
||||
if(e) {
|
||||
/* if its still there we have a writelock, init */
|
||||
/* re-initialise */
|
||||
/* do not touch lameness, it may be valid still */
|
||||
host_entry_init(infra, e, timenow);
|
||||
data_entry_init(infra, e, timenow);
|
||||
wr = 1;
|
||||
/* TOP_TIMEOUT remains on reuse */
|
||||
if(old >= USEFUL_SERVER_TOP_TIMEOUT)
|
||||
((struct infra_host_data*)e->data)->rtt.rto
|
||||
if(old >= USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
((struct infra_data*)e->data)->rtt.rto
|
||||
= USEFUL_SERVER_TOP_TIMEOUT;
|
||||
((struct infra_data*)e->data)->timeout_A = tA;
|
||||
((struct infra_data*)e->data)->timeout_AAAA = tAAAA;
|
||||
((struct infra_data*)e->data)->timeout_other = tother;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!e) {
|
||||
/* insert new entry */
|
||||
if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
|
||||
if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow)))
|
||||
return 0;
|
||||
data = (struct infra_host_data*)e->data;
|
||||
*to = rtt_timeout(&data->rtt);
|
||||
data = (struct infra_data*)e->data;
|
||||
*edns_vs = data->edns_version;
|
||||
*edns_lame_known = data->edns_lame_known;
|
||||
*to = rtt_timeout(&data->rtt);
|
||||
slabhash_insert(infra->hosts, e->hash, e, data, NULL);
|
||||
return 1;
|
||||
}
|
||||
/* use existing entry */
|
||||
data = (struct infra_host_data*)e->data;
|
||||
*to = rtt_timeout(&data->rtt);
|
||||
data = (struct infra_data*)e->data;
|
||||
*edns_vs = data->edns_version;
|
||||
*edns_lame_known = data->edns_lame_known;
|
||||
*to = rtt_timeout(&data->rtt);
|
||||
if(*to >= PROBE_MAXRTO && rtt_notimeout(&data->rtt)*4 <= *to) {
|
||||
/* delay other queries, this is the probe query */
|
||||
if(!wr) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
e = infra_lookup_host_nottl(infra, addr, addrlen, 1);
|
||||
e = infra_lookup_nottl(infra, addr,addrlen,nm,nmlen, 1);
|
||||
if(!e) { /* flushed from cache real fast, no use to
|
||||
allocate just for the probedelay */
|
||||
return 1;
|
||||
}
|
||||
data = (struct infra_host_data*)e->data;
|
||||
data = (struct infra_data*)e->data;
|
||||
}
|
||||
/* add 999 to round up the timeout value from msec to sec,
|
||||
* then add a whole second so it is certain that this probe
|
||||
@@ -315,170 +315,38 @@ infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** hash lameness key */
|
||||
static hashvalue_t
|
||||
hash_lameness(uint8_t* name)
|
||||
{
|
||||
return dname_query_hash(name, 0xab);
|
||||
}
|
||||
|
||||
int
|
||||
infra_lookup_lame(struct infra_host_data* host,
|
||||
uint8_t* name, size_t namelen, uint32_t timenow,
|
||||
int* dlame, int* rlame, int* alame, int* olame)
|
||||
infra_set_lame(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* nm, size_t nmlen, uint32_t timenow,
|
||||
int dnsseclame, int reclame, uint16_t qtype)
|
||||
{
|
||||
struct lruhash_entry* e;
|
||||
struct infra_lame_key k;
|
||||
struct infra_lame_data *d;
|
||||
if(!host->lameness)
|
||||
return 0;
|
||||
k.entry.hash = hash_lameness(name);
|
||||
k.zonename = name;
|
||||
k.namelen = namelen;
|
||||
k.entry.key = (void*)&k;
|
||||
k.entry.data = NULL;
|
||||
e = lruhash_lookup(host->lameness, k.entry.hash, &k, 0);
|
||||
if(!e)
|
||||
return 0;
|
||||
d = (struct infra_lame_data*)e->data;
|
||||
if(d->ttl < timenow) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 0;
|
||||
}
|
||||
*dlame = d->isdnsseclame;
|
||||
*rlame = d->rec_lame;
|
||||
*alame = d->lame_type_A;
|
||||
*olame = d->lame_other;
|
||||
lock_rw_unlock(&e->lock);
|
||||
return *dlame || *rlame || *alame || *olame;
|
||||
}
|
||||
|
||||
size_t
|
||||
infra_lame_sizefunc(void* k, void* ATTR_UNUSED(d))
|
||||
{
|
||||
struct infra_lame_key* key = (struct infra_lame_key*)k;
|
||||
return sizeof(*key) + sizeof(struct infra_lame_data)
|
||||
+ key->namelen + lock_get_mem(&key->entry.lock);
|
||||
}
|
||||
|
||||
int
|
||||
infra_lame_compfunc(void* key1, void* key2)
|
||||
{
|
||||
struct infra_lame_key* k1 = (struct infra_lame_key*)key1;
|
||||
struct infra_lame_key* k2 = (struct infra_lame_key*)key2;
|
||||
if(k1->namelen != k2->namelen) {
|
||||
if(k1->namelen < k2->namelen)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
return query_dname_compare(k1->zonename, k2->zonename);
|
||||
}
|
||||
|
||||
void
|
||||
infra_lame_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct infra_lame_key* key = (struct infra_lame_key*)k;
|
||||
if(!key)
|
||||
return;
|
||||
lock_rw_destroy(&key->entry.lock);
|
||||
free(key->zonename);
|
||||
free(key);
|
||||
}
|
||||
|
||||
void
|
||||
infra_lame_deldatafunc(void* d, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
if(!d)
|
||||
return;
|
||||
free(d);
|
||||
}
|
||||
|
||||
int
|
||||
infra_set_lame(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* name, size_t namelen, uint32_t timenow, int dnsseclame,
|
||||
int reclame, uint16_t qtype)
|
||||
{
|
||||
struct infra_host_data* data;
|
||||
struct infra_data* data;
|
||||
struct lruhash_entry* e;
|
||||
int needtoinsert = 0;
|
||||
struct infra_lame_key* k;
|
||||
struct infra_lame_data* d;
|
||||
/* allocate at start, easier cleanup (no locks held) */
|
||||
k = (struct infra_lame_key*)malloc(sizeof(*k));
|
||||
if(!k) {
|
||||
log_err("set_lame: malloc failure");
|
||||
return 0;
|
||||
}
|
||||
d = (struct infra_lame_data*)malloc(sizeof(*d));
|
||||
if(!d) {
|
||||
free(k);
|
||||
log_err("set_lame: malloc failure");
|
||||
return 0;
|
||||
}
|
||||
k->zonename = memdup(name, namelen);
|
||||
if(!k->zonename) {
|
||||
free(d);
|
||||
free(k);
|
||||
log_err("set_lame: malloc failure");
|
||||
return 0;
|
||||
}
|
||||
lock_rw_init(&k->entry.lock);
|
||||
k->entry.hash = hash_lameness(name);
|
||||
k->entry.key = (void*)k;
|
||||
k->entry.data = (void*)d;
|
||||
d->ttl = timenow + infra->lame_ttl;
|
||||
d->isdnsseclame = dnsseclame;
|
||||
d->rec_lame = reclame;
|
||||
d->lame_type_A = (!dnsseclame && !reclame && qtype == LDNS_RR_TYPE_A);
|
||||
d->lame_other = (!dnsseclame && !reclame && qtype != LDNS_RR_TYPE_A);
|
||||
k->namelen = namelen;
|
||||
e = infra_lookup_host_nottl(infra, addr, addrlen, 1);
|
||||
e = infra_lookup_nottl(infra, addr, addrlen, nm, nmlen, 1);
|
||||
if(!e) {
|
||||
/* insert it */
|
||||
if(!(e = new_host_entry(infra, addr, addrlen, timenow))) {
|
||||
free(k->zonename);
|
||||
free(k);
|
||||
free(d);
|
||||
if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow))) {
|
||||
log_err("set_lame: malloc failure");
|
||||
return 0;
|
||||
}
|
||||
needtoinsert = 1;
|
||||
} else if( ((struct infra_data*)e->data)->ttl < timenow) {
|
||||
/* expired, reuse existing entry */
|
||||
data_entry_init(infra, e, timenow);
|
||||
}
|
||||
/* got an entry, now set the zone lame */
|
||||
data = (struct infra_host_data*)e->data;
|
||||
if(!data->lameness) {
|
||||
/* create hash table if not there already */
|
||||
data->lameness = lruhash_create(INFRA_LAME_STARTSIZE,
|
||||
infra->max_lame_size, infra_lame_sizefunc,
|
||||
infra_lame_compfunc, infra_lame_delkeyfunc,
|
||||
infra_lame_deldatafunc, NULL);
|
||||
if(!data->lameness) {
|
||||
log_err("set_lame: malloc failure");
|
||||
if(needtoinsert) slabhash_insert(infra->hosts,
|
||||
e->hash, e, e->data, NULL);
|
||||
else { lock_rw_unlock(&e->lock); }
|
||||
free(k->zonename);
|
||||
free(k);
|
||||
free(d);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* lookup existing lameness entry (if any) and merge data */
|
||||
int dlame, rlame, alame, olame;
|
||||
if(infra_lookup_lame(data, name, namelen, timenow,
|
||||
&dlame, &rlame, &alame, &olame)) {
|
||||
/* merge data into new structure */
|
||||
if(dlame) d->isdnsseclame = 1;
|
||||
if(rlame) d->rec_lame = 1;
|
||||
if(alame) d->lame_type_A = 1;
|
||||
if(olame) d->lame_other = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* inserts new entry, or updates TTL of older entry */
|
||||
lruhash_insert(data->lameness, k->entry.hash, &k->entry, d, NULL);
|
||||
|
||||
data = (struct infra_data*)e->data;
|
||||
/* merge data (if any) */
|
||||
if(dnsseclame)
|
||||
data->isdnsseclame = 1;
|
||||
if(reclame)
|
||||
data->rec_lame = 1;
|
||||
if(!dnsseclame && !reclame && qtype == LDNS_RR_TYPE_A)
|
||||
data->lame_type_A = 1;
|
||||
if(!dnsseclame && !reclame && qtype != LDNS_RR_TYPE_A)
|
||||
data->lame_other = 1;
|
||||
/* done */
|
||||
if(needtoinsert)
|
||||
slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
|
||||
else { lock_rw_unlock(&e->lock); }
|
||||
@@ -487,14 +355,15 @@ infra_set_lame(struct infra_cache* infra,
|
||||
|
||||
void
|
||||
infra_update_tcp_works(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* nm,
|
||||
size_t nmlen)
|
||||
{
|
||||
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
||||
addrlen, 1);
|
||||
struct infra_host_data* data;
|
||||
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
|
||||
nm, nmlen, 1);
|
||||
struct infra_data* data;
|
||||
if(!e)
|
||||
return; /* doesn't exist */
|
||||
data = (struct infra_host_data*)e->data;
|
||||
data = (struct infra_data*)e->data;
|
||||
if(data->rtt.rto >= RTT_MAX_TIMEOUT)
|
||||
/* do not disqualify this server altogether, it is better
|
||||
* than nothing */
|
||||
@@ -503,29 +372,44 @@ infra_update_tcp_works(struct infra_cache* infra,
|
||||
}
|
||||
|
||||
int
|
||||
infra_rtt_update(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
int roundtrip, int orig_rtt, uint32_t timenow)
|
||||
infra_rtt_update(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* nm, size_t nmlen, int qtype,
|
||||
int roundtrip, int orig_rtt, uint32_t timenow)
|
||||
{
|
||||
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
||||
addrlen, 1);
|
||||
struct infra_host_data* data;
|
||||
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
|
||||
nm, nmlen, 1);
|
||||
struct infra_data* data;
|
||||
int needtoinsert = 0;
|
||||
int rto = 1;
|
||||
if(!e) {
|
||||
if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
|
||||
if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow)))
|
||||
return 0;
|
||||
needtoinsert = 1;
|
||||
} else if(((struct infra_host_data*)e->data)->ttl < timenow) {
|
||||
host_entry_init(infra, e, timenow);
|
||||
}
|
||||
} else if(((struct infra_data*)e->data)->ttl < timenow) {
|
||||
data_entry_init(infra, e, timenow);
|
||||
}
|
||||
/* have an entry, update the rtt */
|
||||
data = (struct infra_host_data*)e->data;
|
||||
data = (struct infra_data*)e->data;
|
||||
if(roundtrip == -1) {
|
||||
rtt_lost(&data->rtt, orig_rtt);
|
||||
if(qtype == LDNS_RR_TYPE_A) {
|
||||
if(data->timeout_A < TIMEOUT_COUNT_MAX)
|
||||
data->timeout_A++;
|
||||
} else if(qtype == LDNS_RR_TYPE_AAAA) {
|
||||
if(data->timeout_AAAA < TIMEOUT_COUNT_MAX)
|
||||
data->timeout_AAAA++;
|
||||
} else {
|
||||
if(data->timeout_other < TIMEOUT_COUNT_MAX)
|
||||
data->timeout_other++;
|
||||
}
|
||||
} else {
|
||||
rtt_update(&data->rtt, roundtrip);
|
||||
data->probedelay = 0;
|
||||
if(qtype == LDNS_RR_TYPE_A)
|
||||
data->timeout_A = 0;
|
||||
else if(qtype == LDNS_RR_TYPE_AAAA)
|
||||
data->timeout_AAAA = 0;
|
||||
else data->timeout_other = 0;
|
||||
}
|
||||
if(data->rtt.rto > 0)
|
||||
rto = data->rtt.rto;
|
||||
@@ -537,15 +421,16 @@ infra_rtt_update(struct infra_cache* infra,
|
||||
}
|
||||
|
||||
int infra_get_host_rto(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct rtt_info* rtt, int* delay, uint32_t timenow)
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* nm,
|
||||
size_t nmlen, struct rtt_info* rtt, int* delay, uint32_t timenow,
|
||||
int* tA, int* tAAAA, int* tother)
|
||||
{
|
||||
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
||||
addrlen, 0);
|
||||
struct infra_host_data* data;
|
||||
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
|
||||
nm, nmlen, 0);
|
||||
struct infra_data* data;
|
||||
int ttl = -2;
|
||||
if(!e) return -1;
|
||||
data = (struct infra_host_data*)e->data;
|
||||
data = (struct infra_data*)e->data;
|
||||
if(data->ttl >= timenow) {
|
||||
ttl = (int)(data->ttl - timenow);
|
||||
memmove(rtt, &data->rtt, sizeof(*rtt));
|
||||
@@ -553,28 +438,31 @@ int infra_get_host_rto(struct infra_cache* infra,
|
||||
*delay = (int)(data->probedelay - timenow);
|
||||
else *delay = 0;
|
||||
}
|
||||
*tA = (int)data->timeout_A;
|
||||
*tAAAA = (int)data->timeout_AAAA;
|
||||
*tother = (int)data->timeout_other;
|
||||
lock_rw_unlock(&e->lock);
|
||||
return ttl;
|
||||
}
|
||||
|
||||
int
|
||||
infra_edns_update(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
int edns_version, uint32_t timenow)
|
||||
infra_edns_update(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* nm, size_t nmlen, int edns_version,
|
||||
uint32_t timenow)
|
||||
{
|
||||
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
||||
addrlen, 1);
|
||||
struct infra_host_data* data;
|
||||
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
|
||||
nm, nmlen, 1);
|
||||
struct infra_data* data;
|
||||
int needtoinsert = 0;
|
||||
if(!e) {
|
||||
if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
|
||||
if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow)))
|
||||
return 0;
|
||||
needtoinsert = 1;
|
||||
} else if(((struct infra_host_data*)e->data)->ttl < timenow) {
|
||||
host_entry_init(infra, e, timenow);
|
||||
}
|
||||
} else if(((struct infra_data*)e->data)->ttl < timenow) {
|
||||
data_entry_init(infra, e, timenow);
|
||||
}
|
||||
/* have an entry, update the rtt, and the ttl */
|
||||
data = (struct infra_host_data*)e->data;
|
||||
data = (struct infra_data*)e->data;
|
||||
/* do not update if noEDNS and stored is yesEDNS */
|
||||
if(!(edns_version == -1 && (data->edns_version != -1 &&
|
||||
data->edns_lame_known))) {
|
||||
@@ -588,107 +476,89 @@ infra_edns_update(struct infra_cache* infra,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
infra_get_lame_rtt(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* name, size_t namelen, uint16_t qtype,
|
||||
int* lame, int* dnsseclame, int* reclame, int* rtt, uint32_t timenow)
|
||||
{
|
||||
struct infra_host_data* host;
|
||||
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
||||
addrlen, 0);
|
||||
int dlm, rlm, alm, olm;
|
||||
struct infra_data* host;
|
||||
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
|
||||
name, namelen, 0);
|
||||
if(!e)
|
||||
return 0;
|
||||
host = (struct infra_host_data*)e->data;
|
||||
host = (struct infra_data*)e->data;
|
||||
*rtt = rtt_unclamped(&host->rtt);
|
||||
if(host->rtt.rto >= PROBE_MAXRTO && timenow < host->probedelay
|
||||
&& rtt_notimeout(&host->rtt)*4 <= host->rtt.rto)
|
||||
&& rtt_notimeout(&host->rtt)*4 <= host->rtt.rto) {
|
||||
/* single probe for this domain, and we are not probing */
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
|
||||
/* check lameness first, if so, ttl on host does not matter anymore */
|
||||
if(infra_lookup_lame(host, name, namelen, timenow,
|
||||
&dlm, &rlm, &alm, &olm)) {
|
||||
if(alm && qtype == LDNS_RR_TYPE_A) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*lame = 1;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 0;
|
||||
return 1;
|
||||
} else if(olm && qtype != LDNS_RR_TYPE_A) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*lame = 1;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 0;
|
||||
return 1;
|
||||
} else if(dlm) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*lame = 0;
|
||||
*dnsseclame = 1;
|
||||
*reclame = 0;
|
||||
return 1;
|
||||
} else if(rlm) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*lame = 0;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 1;
|
||||
return 1;
|
||||
/* unless the query type allows a probe to happen */
|
||||
if(qtype == LDNS_RR_TYPE_A) {
|
||||
if(host->timeout_A >= TIMEOUT_COUNT_MAX)
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
|
||||
else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
||||
} else if(qtype == LDNS_RR_TYPE_AAAA) {
|
||||
if(host->timeout_AAAA >= TIMEOUT_COUNT_MAX)
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
|
||||
else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
||||
} else {
|
||||
if(host->timeout_other >= TIMEOUT_COUNT_MAX)
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
|
||||
else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
||||
}
|
||||
/* no lameness for this type of query */
|
||||
}
|
||||
*lame = 0;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 0;
|
||||
if(timenow > host->ttl) {
|
||||
/* expired entry */
|
||||
/* see if this can be a re-probe of an unresponsive server */
|
||||
/* minus 1000 because that is outside of the RTTBAND, so
|
||||
* blacklisted servers stay blacklisted if this is chosen */
|
||||
if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
||||
lock_rw_unlock(&e->lock);
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
||||
*lame = 0;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 0;
|
||||
return 1;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 0;
|
||||
}
|
||||
/* check lameness first */
|
||||
if(host->lame_type_A && qtype == LDNS_RR_TYPE_A) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*lame = 1;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 0;
|
||||
return 1;
|
||||
} else if(host->lame_other && qtype != LDNS_RR_TYPE_A) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*lame = 1;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 0;
|
||||
return 1;
|
||||
} else if(host->isdnsseclame) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*lame = 0;
|
||||
*dnsseclame = 1;
|
||||
*reclame = 0;
|
||||
return 1;
|
||||
} else if(host->rec_lame) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*lame = 0;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 1;
|
||||
return 1;
|
||||
}
|
||||
/* no lameness for this type of query */
|
||||
lock_rw_unlock(&e->lock);
|
||||
*lame = 0;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** helper memory count for a host lame cache */
|
||||
static size_t
|
||||
count_host_lame(struct lruhash_entry* e)
|
||||
{
|
||||
struct infra_host_data* host_data = (struct infra_host_data*)e->data;
|
||||
if(!host_data->lameness)
|
||||
return 0;
|
||||
return lruhash_get_mem(host_data->lameness);
|
||||
}
|
||||
|
||||
size_t
|
||||
infra_get_mem(struct infra_cache* infra)
|
||||
{
|
||||
size_t i, bin;
|
||||
size_t s = sizeof(*infra) +
|
||||
slabhash_get_mem(infra->hosts);
|
||||
struct lruhash_entry* e;
|
||||
for(i=0; i<infra->hosts->size; i++) {
|
||||
lock_quick_lock(&infra->hosts->array[i]->lock);
|
||||
for(bin=0; bin<infra->hosts->array[i]->size; bin++) {
|
||||
lock_quick_lock(&infra->hosts->array[i]->
|
||||
array[bin].lock);
|
||||
/* count data size in bin items. */
|
||||
for(e = infra->hosts->array[i]->array[bin].
|
||||
overflow_list; e; e = e->overflow_next) {
|
||||
lock_rw_rdlock(&e->lock);
|
||||
s += count_host_lame(e);
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
lock_quick_unlock(&infra->hosts->array[i]->
|
||||
array[bin].lock);
|
||||
}
|
||||
lock_quick_unlock(&infra->hosts->array[i]->lock);
|
||||
}
|
||||
return s;
|
||||
return sizeof(*infra) + slabhash_get_mem(infra->hosts);
|
||||
}
|
||||
|
||||
Vendored
+60
-92
@@ -47,65 +47,57 @@ struct slabhash;
|
||||
struct config_file;
|
||||
|
||||
/**
|
||||
* Host information kept for every server.
|
||||
* Host information kept for every server, per zone.
|
||||
*/
|
||||
struct infra_host_key {
|
||||
struct infra_key {
|
||||
/** the host address. */
|
||||
struct sockaddr_storage addr;
|
||||
/** length of addr. */
|
||||
socklen_t addrlen;
|
||||
/** hash table entry, data of type infra_host_data. */
|
||||
/** zone name in wireformat */
|
||||
uint8_t* zonename;
|
||||
/** length of zonename */
|
||||
size_t namelen;
|
||||
/** hash table entry, data of type infra_data. */
|
||||
struct lruhash_entry entry;
|
||||
};
|
||||
|
||||
/**
|
||||
* Host information encompasses host capabilities and retransmission timeouts.
|
||||
* And lameness information (notAuthoritative, noEDNS, Recursive)
|
||||
*/
|
||||
struct infra_host_data {
|
||||
struct infra_data {
|
||||
/** TTL value for this entry. absolute time. */
|
||||
uint32_t ttl;
|
||||
|
||||
/** time in seconds (absolute) when probing re-commences, 0 disabled */
|
||||
uint32_t probedelay;
|
||||
/** round trip times for timeout calculation */
|
||||
struct rtt_info rtt;
|
||||
/** Names of the zones that are lame. NULL=no lame zones. */
|
||||
struct lruhash* lameness;
|
||||
|
||||
/** edns version that the host supports, -1 means no EDNS */
|
||||
int edns_version;
|
||||
/** if the EDNS lameness is already known or not.
|
||||
* EDNS lame is when EDNS queries or replies are dropped,
|
||||
* and cause a timeout */
|
||||
uint8_t edns_lame_known;
|
||||
};
|
||||
|
||||
/**
|
||||
* Lameness information, per host, per zone.
|
||||
*/
|
||||
struct infra_lame_key {
|
||||
/** key is zone name in wireformat */
|
||||
uint8_t* zonename;
|
||||
/** length of zonename */
|
||||
size_t namelen;
|
||||
/** lruhash entry */
|
||||
struct lruhash_entry entry;
|
||||
};
|
||||
|
||||
/**
|
||||
* Lameness information. Expires.
|
||||
* This host is lame because it is in the cache.
|
||||
*/
|
||||
struct infra_lame_data {
|
||||
/** TTL of this entry. absolute time. */
|
||||
uint32_t ttl;
|
||||
/** is the host lame (does not serve the zone authoritatively),
|
||||
* or is the host dnssec lame (does not serve DNSSEC data) */
|
||||
int isdnsseclame;
|
||||
uint8_t isdnsseclame;
|
||||
/** is the host recursion lame (not AA, but RA) */
|
||||
int rec_lame;
|
||||
uint8_t rec_lame;
|
||||
/** the host is lame (not authoritative) for A records */
|
||||
int lame_type_A;
|
||||
uint8_t lame_type_A;
|
||||
/** the host is lame (not authoritative) for other query types */
|
||||
int lame_other;
|
||||
uint8_t lame_other;
|
||||
|
||||
/** timeouts counter for type A */
|
||||
uint8_t timeout_A;
|
||||
/** timeouts counter for type AAAA */
|
||||
uint8_t timeout_AAAA;
|
||||
/** timeouts counter for others */
|
||||
uint8_t timeout_other;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -116,18 +108,12 @@ struct infra_cache {
|
||||
struct slabhash* hosts;
|
||||
/** TTL value for host information, in seconds */
|
||||
int host_ttl;
|
||||
/** TTL for Lameness information, in seconds */
|
||||
int lame_ttl;
|
||||
/** infra lame cache max memory per host, in bytes */
|
||||
size_t max_lame_size;
|
||||
/** jostle timeout in msec */
|
||||
size_t jostle;
|
||||
};
|
||||
|
||||
/** infra host cache default hash lookup size */
|
||||
#define INFRA_HOST_STARTSIZE 32
|
||||
/** infra lame cache default hash lookup size */
|
||||
#define INFRA_LAME_STARTSIZE 2
|
||||
/** bytes per zonename reserved in the hostcache, dnamelen(zonename.com.) */
|
||||
#define INFRA_BYTES_NAME 14
|
||||
|
||||
/**
|
||||
* Create infra cache.
|
||||
@@ -142,10 +128,6 @@ struct infra_cache* infra_create(struct config_file* cfg);
|
||||
*/
|
||||
void infra_delete(struct infra_cache* infra);
|
||||
|
||||
/** explicitly delete an infra host element */
|
||||
void infra_remove_host(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Adjust infra cache to use updated configuration settings.
|
||||
* This may clean the cache. Operates a bit like realloc.
|
||||
@@ -158,18 +140,18 @@ struct infra_cache* infra_adjust(struct infra_cache* infra,
|
||||
struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Lookup host data
|
||||
* Plain find infra data function (used by the the other functions)
|
||||
* @param infra: infrastructure cache.
|
||||
* @param addr: host address.
|
||||
* @param addrlen: length of addr.
|
||||
* @param wr: set to true to get a writelock on the entry.
|
||||
* @param timenow: what time it is now.
|
||||
* @param key: the key for the host, returned so caller can unlock when done.
|
||||
* @return: host data or NULL if not found or expired.
|
||||
* @param name: domain name of zone.
|
||||
* @param namelen: length of domain name.
|
||||
* @param wr: if true, writelock, else readlock.
|
||||
* @return the entry, could be expired (this is not checked) or NULL.
|
||||
*/
|
||||
struct infra_host_data* infra_lookup_host(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int wr,
|
||||
uint32_t timenow, struct infra_host_key** key);
|
||||
struct lruhash_entry* infra_lookup_nottl(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name,
|
||||
size_t namelen, int wr);
|
||||
|
||||
/**
|
||||
* Find host information to send a packet. Creates new entry if not found.
|
||||
@@ -180,6 +162,8 @@ struct infra_host_data* infra_lookup_host(struct infra_cache* infra,
|
||||
* @param infra: infrastructure cache.
|
||||
* @param addr: host address.
|
||||
* @param addrlen: length of addr.
|
||||
* @param name: domain name of zone.
|
||||
* @param namelen: length of domain name.
|
||||
* @param timenow: what time it is now.
|
||||
* @param edns_vs: edns version it supports, is returned.
|
||||
* @param edns_lame_known: if EDNS lame (EDNS is dropped in transit) has
|
||||
@@ -188,25 +172,8 @@ struct infra_host_data* infra_lookup_host(struct infra_cache* infra,
|
||||
* @return: 0 on error.
|
||||
*/
|
||||
int infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint32_t timenow, int* edns_vs,
|
||||
uint8_t* edns_lame_known, int* to);
|
||||
|
||||
/**
|
||||
* Check for lameness of this server for a particular zone.
|
||||
* You must have a lock on the host structure.
|
||||
* @param host: infrastructure cache data for the host. Caller holds lock.
|
||||
* @param name: domain name of zone apex.
|
||||
* @param namelen: length of domain name.
|
||||
* @param timenow: what time it is now.
|
||||
* @param dlame: if the function returns true, is set true if dnssec lame.
|
||||
* @param rlame: if the function returns true, is set true if recursion lame.
|
||||
* @param alame: if the function returns true, is set true if qtype A lame.
|
||||
* @param olame: if the function returns true, is set true if qtype other lame.
|
||||
* @return: 0 if not lame or unknown or timed out, 1 if lame
|
||||
*/
|
||||
int infra_lookup_lame(struct infra_host_data* host,
|
||||
uint8_t* name, size_t namelen, uint32_t timenow,
|
||||
int* dlame, int* rlame, int* alame, int* olame);
|
||||
socklen_t addrlen, uint8_t* name, size_t namelen,
|
||||
uint32_t timenow, int* edns_vs, uint8_t* edns_lame_known, int* to);
|
||||
|
||||
/**
|
||||
* Set a host to be lame for the given zone.
|
||||
@@ -233,6 +200,9 @@ int infra_set_lame(struct infra_cache* infra,
|
||||
* @param infra: infrastructure cache.
|
||||
* @param addr: host address.
|
||||
* @param addrlen: length of addr.
|
||||
* @param name: zone name
|
||||
* @param namelen: zone name length
|
||||
* @param qtype: query type.
|
||||
* @param roundtrip: estimate of roundtrip time in milliseconds or -1 for
|
||||
* timeout.
|
||||
* @param orig_rtt: original rtt for the query that timed out (roundtrip==-1).
|
||||
@@ -240,8 +210,8 @@ int infra_set_lame(struct infra_cache* infra,
|
||||
* @param timenow: what time it is now.
|
||||
* @return: 0 on error. new rto otherwise.
|
||||
*/
|
||||
int infra_rtt_update(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
int infra_rtt_update(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* name, size_t namelen, int qtype,
|
||||
int roundtrip, int orig_rtt, uint32_t timenow);
|
||||
|
||||
/**
|
||||
@@ -249,15 +219,20 @@ int infra_rtt_update(struct infra_cache* infra,
|
||||
* @param infra: infrastructure cache.
|
||||
* @param addr: host address.
|
||||
* @param addrlen: length of addr.
|
||||
* @param name: name of zone
|
||||
* @param namelen: length of name
|
||||
*/
|
||||
void infra_update_tcp_works(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen);
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* name, size_t namelen);
|
||||
|
||||
/**
|
||||
* Update edns information for the host.
|
||||
* @param infra: infrastructure cache.
|
||||
* @param addr: host address.
|
||||
* @param addrlen: length of addr.
|
||||
* @param name: name of zone
|
||||
* @param namelen: length of name
|
||||
* @param edns_version: the version that it publishes.
|
||||
* If it is known to support EDNS then no-EDNS is not stored over it.
|
||||
* @param timenow: what time it is now.
|
||||
@@ -265,7 +240,7 @@ void infra_update_tcp_works(struct infra_cache* infra,
|
||||
*/
|
||||
int infra_edns_update(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
int edns_version, uint32_t timenow);
|
||||
uint8_t* name, size_t namelen, int edns_version, uint32_t timenow);
|
||||
|
||||
/**
|
||||
* Get Lameness information and average RTT if host is in the cache.
|
||||
@@ -295,15 +270,21 @@ int infra_get_lame_rtt(struct infra_cache* infra,
|
||||
* @param infra: infra cache.
|
||||
* @param addr: host address.
|
||||
* @param addrlen: length of addr.
|
||||
* @param name: zone name
|
||||
* @param namelen: zone name length
|
||||
* @param rtt: the rtt_info is copied into here (caller alloced return struct).
|
||||
* @param delay: probe delay (if any).
|
||||
* @param timenow: what time it is now.
|
||||
* @param tA: timeout counter on type A.
|
||||
* @param tAAAA: timeout counter on type AAAA.
|
||||
* @param tother: timeout counter on type other.
|
||||
* @return TTL the infra host element is valid for. If -1: not found in cache.
|
||||
* TTL -2: found but expired.
|
||||
*/
|
||||
int infra_get_host_rto(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct rtt_info* rtt, int* delay, uint32_t timenow);
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name,
|
||||
size_t namelen, struct rtt_info* rtt, int* delay, uint32_t timenow,
|
||||
int* tA, int* tAAAA, int* tother);
|
||||
|
||||
/**
|
||||
* Get memory used by the infra cache.
|
||||
@@ -314,28 +295,15 @@ size_t infra_get_mem(struct infra_cache* infra);
|
||||
|
||||
/** calculate size for the hashtable, does not count size of lameness,
|
||||
* so the hashtable is a fixed number of items */
|
||||
size_t infra_host_sizefunc(void* k, void* d);
|
||||
size_t infra_sizefunc(void* k, void* d);
|
||||
|
||||
/** compare two addresses, returns -1, 0, or +1 */
|
||||
int infra_host_compfunc(void* key1, void* key2);
|
||||
int infra_compfunc(void* key1, void* key2);
|
||||
|
||||
/** delete key, and destroy the lock */
|
||||
void infra_host_delkeyfunc(void* k, void* arg);
|
||||
void infra_delkeyfunc(void* k, void* arg);
|
||||
|
||||
/** delete data and destroy the lameness hashtable */
|
||||
void infra_host_deldatafunc(void* d, void* arg);
|
||||
|
||||
/** calculate size, which is fixed, zonename does not count so that
|
||||
* a fixed number of items is stored */
|
||||
size_t infra_lame_sizefunc(void* k, void* d);
|
||||
|
||||
/** compare zone names, returns -1, 0, +1 */
|
||||
int infra_lame_compfunc(void* key1, void* key2);
|
||||
|
||||
/** free key, lock and zonename */
|
||||
void infra_lame_delkeyfunc(void* k, void* arg);
|
||||
|
||||
/** free the lameness data */
|
||||
void infra_lame_deldatafunc(void* d, void* arg);
|
||||
void infra_deldatafunc(void* d, void* arg);
|
||||
|
||||
#endif /* SERVICES_CACHE_INFRA_H */
|
||||
|
||||
Vendored
+1
@@ -207,6 +207,7 @@ rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
|
||||
/* cache is superior, return that value */
|
||||
lock_rw_unlock(&e->lock);
|
||||
ub_packed_rrset_parsedelete(k, alloc);
|
||||
if(equal) return 2;
|
||||
return 1;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
|
||||
Vendored
+4
@@ -125,6 +125,10 @@ void rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key,
|
||||
* @param alloc: how to allocate (and deallocate) the special rrset key.
|
||||
* @param timenow: current time (to see if ttl in cache is expired).
|
||||
* @return: true if the passed reference is updated, false if it is unchanged.
|
||||
* 0: reference unchanged, inserted in cache.
|
||||
* 1: reference updated, item is inserted in cache.
|
||||
* 2: reference updated, item in cache is considered superior.
|
||||
* also the rdata is equal (but other parameters in cache are superior).
|
||||
*/
|
||||
int rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
|
||||
struct alloc_cache* alloc, uint32_t timenow);
|
||||
|
||||
+81
-10
@@ -323,6 +323,11 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
log_err("setsockopt(..., IP_MTU_DISCOVER, "
|
||||
"IP_PMTUDISC_DONT...) failed: %s",
|
||||
strerror(errno));
|
||||
# ifndef USE_WINSOCK
|
||||
close(s);
|
||||
# else
|
||||
closesocket(s);
|
||||
# endif
|
||||
return -1;
|
||||
}
|
||||
# elif defined(IP_DONTFRAG)
|
||||
@@ -331,6 +336,11 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
&off, (socklen_t)sizeof(off)) < 0) {
|
||||
log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s",
|
||||
strerror(errno));
|
||||
# ifndef USE_WINSOCK
|
||||
close(s);
|
||||
# else
|
||||
closesocket(s);
|
||||
# endif
|
||||
return -1;
|
||||
}
|
||||
# endif /* IPv4 MTU */
|
||||
@@ -408,9 +418,11 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto)
|
||||
#ifndef USE_WINSOCK
|
||||
log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
|
||||
strerror(errno));
|
||||
close(s);
|
||||
#else
|
||||
log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
closesocket(s);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
@@ -422,9 +434,11 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto)
|
||||
#ifndef USE_WINSOCK
|
||||
log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
|
||||
strerror(errno));
|
||||
close(s);
|
||||
#else
|
||||
log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
closesocket(s);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
@@ -443,23 +457,32 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto)
|
||||
(struct sockaddr_storage*)addr->ai_addr,
|
||||
addr->ai_addrlen);
|
||||
}
|
||||
close(s);
|
||||
#else
|
||||
log_err("can't bind socket: %s",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
log_addr(0, "failed address",
|
||||
(struct sockaddr_storage*)addr->ai_addr,
|
||||
addr->ai_addrlen);
|
||||
closesocket(s);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
if(!fd_set_nonblock(s)) {
|
||||
#ifndef USE_WINSOCK
|
||||
close(s);
|
||||
#else
|
||||
closesocket(s);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
if(listen(s, TCP_BACKLOG) == -1) {
|
||||
#ifndef USE_WINSOCK
|
||||
log_err("can't listen: %s", strerror(errno));
|
||||
close(s);
|
||||
#else
|
||||
log_err("can't listen: %s", wsa_strerror(WSAGetLastError()));
|
||||
closesocket(s);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
@@ -632,12 +655,13 @@ set_recvpktinfo(int s, int family)
|
||||
* @param list: list of open ports, appended to, changed to point to list head.
|
||||
* @param rcv: receive buffer size for UDP
|
||||
* @param snd: send buffer size for UDP
|
||||
* @param ssl_port: ssl service port number
|
||||
* @return: returns false on error.
|
||||
*/
|
||||
static int
|
||||
ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
struct addrinfo *hints, const char* port, struct listen_port** list,
|
||||
size_t rcv, size_t snd)
|
||||
size_t rcv, size_t snd, int ssl_port)
|
||||
{
|
||||
int s, noip6=0;
|
||||
if(!do_udp && !do_tcp)
|
||||
@@ -652,8 +676,14 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
return 0;
|
||||
}
|
||||
/* getting source addr packet info is highly non-portable */
|
||||
if(!set_recvpktinfo(s, hints->ai_family))
|
||||
if(!set_recvpktinfo(s, hints->ai_family)) {
|
||||
#ifndef USE_WINSOCK
|
||||
close(s);
|
||||
#else
|
||||
closesocket(s);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
if(!port_insert(list, s, listen_type_udpancil)) {
|
||||
#ifndef USE_WINSOCK
|
||||
close(s);
|
||||
@@ -682,6 +712,9 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
}
|
||||
}
|
||||
if(do_tcp) {
|
||||
int is_ssl = ((strchr(ifname, '@') &&
|
||||
atoi(strchr(ifname, '@')+1) == ssl_port) ||
|
||||
(!strchr(ifname, '@') && atoi(port) == ssl_port));
|
||||
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
|
||||
&noip6, 0, 0)) == -1) {
|
||||
if(noip6) {
|
||||
@@ -690,7 +723,10 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if(!port_insert(list, s, listen_type_tcp)) {
|
||||
if(is_ssl)
|
||||
verbose(VERB_ALGO, "setup TCP for SSL service");
|
||||
if(!port_insert(list, s, is_ssl?listen_type_ssl:
|
||||
listen_type_tcp)) {
|
||||
#ifndef USE_WINSOCK
|
||||
close(s);
|
||||
#else
|
||||
@@ -723,7 +759,7 @@ listen_cp_insert(struct comm_point* c, struct listen_dnsport* front)
|
||||
|
||||
struct listen_dnsport*
|
||||
listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
size_t bufsize, int tcp_accept_count,
|
||||
size_t bufsize, int tcp_accept_count, void* sslctx,
|
||||
comm_point_callback_t* cb, void *cb_arg)
|
||||
{
|
||||
struct listen_dnsport* front = (struct listen_dnsport*)
|
||||
@@ -736,7 +772,7 @@ listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
free(front);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* create comm points as needed */
|
||||
while(ports) {
|
||||
struct comm_point* cp = NULL;
|
||||
@@ -746,7 +782,11 @@ listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
else if(ports->ftype == listen_type_tcp)
|
||||
cp = comm_point_create_tcp(base, ports->fd,
|
||||
tcp_accept_count, bufsize, cb, cb_arg);
|
||||
else if(ports->ftype == listen_type_udpancil)
|
||||
else if(ports->ftype == listen_type_ssl) {
|
||||
cp = comm_point_create_tcp(base, ports->fd,
|
||||
tcp_accept_count, bufsize, cb, cb_arg);
|
||||
cp->ssl = sslctx;
|
||||
} else if(ports->ftype == listen_type_udpancil)
|
||||
cp = comm_point_create_udp_ancil(base, ports->fd,
|
||||
front->udp_buff, cb, cb_arg);
|
||||
if(!cp) {
|
||||
@@ -830,7 +870,8 @@ listening_ports_open(struct config_file* cfg)
|
||||
if(!ports_create_if(do_auto?"::0":"::1",
|
||||
do_auto, cfg->do_udp, do_tcp,
|
||||
&hints, portbuf, &list,
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf)) {
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -840,7 +881,8 @@ listening_ports_open(struct config_file* cfg)
|
||||
if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1",
|
||||
do_auto, cfg->do_udp, do_tcp,
|
||||
&hints, portbuf, &list,
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf)) {
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -852,7 +894,8 @@ listening_ports_open(struct config_file* cfg)
|
||||
hints.ai_family = AF_INET6;
|
||||
if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
|
||||
do_tcp, &hints, portbuf, &list,
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf)) {
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -862,7 +905,8 @@ listening_ports_open(struct config_file* cfg)
|
||||
hints.ai_family = AF_INET;
|
||||
if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
|
||||
do_tcp, &hints, portbuf, &list,
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf)) {
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -900,3 +944,30 @@ size_t listen_get_mem(struct listen_dnsport* listen)
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void listen_stop_accept(struct listen_dnsport* listen)
|
||||
{
|
||||
/* do not stop the ones that have no tcp_free list
|
||||
* (they have already stopped listening) */
|
||||
struct listen_list* p;
|
||||
for(p=listen->cps; p; p=p->next) {
|
||||
if(p->com->type == comm_tcp_accept &&
|
||||
p->com->tcp_free != NULL) {
|
||||
comm_point_stop_listening(p->com);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void listen_start_accept(struct listen_dnsport* listen)
|
||||
{
|
||||
/* do not start the ones that have no tcp_free list, it is no
|
||||
* use to listen to them because they have no free tcp handlers */
|
||||
struct listen_list* p;
|
||||
for(p=listen->cps; p; p=p->next) {
|
||||
if(p->com->type == comm_tcp_accept &&
|
||||
p->com->tcp_free != NULL) {
|
||||
comm_point_start_listening(p->com, -1, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,9 @@ enum listen_type {
|
||||
/** tcp type */
|
||||
listen_type_tcp,
|
||||
/** udp ipv6 (v4mapped) for use with ancillary data */
|
||||
listen_type_udpancil
|
||||
listen_type_udpancil,
|
||||
/** ssl over tcp type */
|
||||
listen_type_ssl
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -121,6 +123,7 @@ void listening_ports_free(struct listen_port* list);
|
||||
* @param bufsize: size of datagram buffer.
|
||||
* @param tcp_accept_count: max number of simultaneous TCP connections
|
||||
* from clients.
|
||||
* @param sslctx: nonNULL if ssl context.
|
||||
* @param cb: callback function when a request arrives. It is passed
|
||||
* the packet and user argument. Return true to send a reply.
|
||||
* @param cb_arg: user data argument for callback function.
|
||||
@@ -128,7 +131,7 @@ void listening_ports_free(struct listen_port* list);
|
||||
*/
|
||||
struct listen_dnsport* listen_create(struct comm_base* base,
|
||||
struct listen_port* ports, size_t bufsize, int tcp_accept_count,
|
||||
comm_point_callback_t* cb, void* cb_arg);
|
||||
void* sslctx, comm_point_callback_t* cb, void* cb_arg);
|
||||
|
||||
/**
|
||||
* delete the listening structure
|
||||
@@ -150,6 +153,18 @@ void listen_list_delete(struct listen_list* list);
|
||||
*/
|
||||
size_t listen_get_mem(struct listen_dnsport* listen);
|
||||
|
||||
/**
|
||||
* stop accept handlers for TCP (until enabled again)
|
||||
* @param listen: listening structure.
|
||||
*/
|
||||
void listen_stop_accept(struct listen_dnsport* listen);
|
||||
|
||||
/**
|
||||
* start accept handlers for TCP (was stopped before)
|
||||
* @param listen: listening structure.
|
||||
*/
|
||||
void listen_start_accept(struct listen_dnsport* listen);
|
||||
|
||||
/**
|
||||
* Create and bind nonblocking UDP socket
|
||||
* @param family: for socket call.
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
* This file contains functions to enable local zone authority service.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ldns/dname.h"
|
||||
#include "ldns/host2wire.h"
|
||||
#include <ldns/dname.h>
|
||||
#include <ldns/host2wire.h>
|
||||
#include "services/localzone.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/config_file.h"
|
||||
|
||||
+69
-17
@@ -43,7 +43,7 @@
|
||||
* send back to clients.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ldns/wire2host.h"
|
||||
#include <ldns/wire2host.h>
|
||||
#include "services/mesh.h"
|
||||
#include "services/outbound_list.h"
|
||||
#include "services/cache/dns.h"
|
||||
@@ -162,7 +162,8 @@ mesh_create(struct module_stack* stack, struct module_env* env)
|
||||
return NULL;
|
||||
}
|
||||
mesh->histogram = timehist_setup();
|
||||
if(!mesh->histogram) {
|
||||
mesh->qbuf_bak = ldns_buffer_new(env->cfg->msg_buffer_size);
|
||||
if(!mesh->histogram || !mesh->qbuf_bak) {
|
||||
free(mesh);
|
||||
log_err("mesh area alloc: out of memory");
|
||||
return NULL;
|
||||
@@ -209,6 +210,7 @@ mesh_delete(struct mesh_area* mesh)
|
||||
while(mesh->all.count)
|
||||
mesh_delete_helper(mesh->all.root);
|
||||
timehist_delete(mesh->histogram);
|
||||
ldns_buffer_free(mesh->qbuf_bak);
|
||||
free(mesh);
|
||||
}
|
||||
|
||||
@@ -232,7 +234,7 @@ mesh_delete_all(struct mesh_area* mesh)
|
||||
mesh->jostle_last = NULL;
|
||||
}
|
||||
|
||||
int mesh_make_new_space(struct mesh_area* mesh)
|
||||
int mesh_make_new_space(struct mesh_area* mesh, ldns_buffer* qbuf)
|
||||
{
|
||||
struct mesh_state* m = mesh->jostle_first;
|
||||
/* free space is available */
|
||||
@@ -250,6 +252,8 @@ int mesh_make_new_space(struct mesh_area* mesh)
|
||||
"make space for a new one",
|
||||
m->s.qinfo.qname, m->s.qinfo.qtype,
|
||||
m->s.qinfo.qclass);
|
||||
/* backup the query */
|
||||
if(qbuf) ldns_buffer_copy(mesh->qbuf_bak, qbuf);
|
||||
/* notify supers */
|
||||
if(m->super_set.count > 0) {
|
||||
verbose(VERB_ALGO, "notify supers of failure");
|
||||
@@ -259,6 +263,9 @@ int mesh_make_new_space(struct mesh_area* mesh)
|
||||
}
|
||||
mesh->stats_jostled ++;
|
||||
mesh_state_delete(&m->s);
|
||||
/* restore the query - note that the qinfo ptr to
|
||||
* the querybuffer is then correct again. */
|
||||
if(qbuf) ldns_buffer_copy(qbuf, mesh->qbuf_bak);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -280,7 +287,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
int added = 0;
|
||||
/* does this create a new reply state? */
|
||||
if(!s || s->list_select == mesh_no_list) {
|
||||
if(!mesh_make_new_space(mesh)) {
|
||||
if(!mesh_make_new_space(mesh, rep->c->buffer)) {
|
||||
verbose(VERB_ALGO, "Too many queries. dropping "
|
||||
"incoming query.");
|
||||
comm_point_drop_reply(rep);
|
||||
@@ -301,7 +308,9 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
}
|
||||
/* see if it already exists, if not, create one */
|
||||
if(!s) {
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_t* n;
|
||||
#endif
|
||||
s = mesh_state_create(mesh->env, qinfo, qflags&BIT_RD, 0);
|
||||
if(!s) {
|
||||
log_err("mesh_state_create: out of memory; SERVFAIL");
|
||||
@@ -310,7 +319,10 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
comm_point_send_reply(rep);
|
||||
return;
|
||||
}
|
||||
n = rbtree_insert(&mesh->all, &s->node);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#endif
|
||||
rbtree_insert(&mesh->all, &s->node);
|
||||
log_assert(n != NULL);
|
||||
/* set detached (it is now) */
|
||||
mesh->num_detached_states++;
|
||||
@@ -369,12 +381,17 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
|
||||
/* see if it already exists, if not, create one */
|
||||
if(!s) {
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_t* n;
|
||||
#endif
|
||||
s = mesh_state_create(mesh->env, qinfo, qflags&BIT_RD, 0);
|
||||
if(!s) {
|
||||
return 0;
|
||||
}
|
||||
n = rbtree_insert(&mesh->all, &s->node);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#endif
|
||||
rbtree_insert(&mesh->all, &s->node);
|
||||
log_assert(n != NULL);
|
||||
/* set detached (it is now) */
|
||||
mesh->num_detached_states++;
|
||||
@@ -408,7 +425,9 @@ void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, uint32_t leeway)
|
||||
{
|
||||
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&BIT_RD, 0);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_t* n;
|
||||
#endif
|
||||
/* already exists, and for a different purpose perhaps.
|
||||
* if mesh_no_list, keep it that way. */
|
||||
if(s) {
|
||||
@@ -419,7 +438,7 @@ void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
s->s.prefetch_leeway = leeway;
|
||||
return;
|
||||
}
|
||||
if(!mesh_make_new_space(mesh)) {
|
||||
if(!mesh_make_new_space(mesh, NULL)) {
|
||||
verbose(VERB_ALGO, "Too many queries. dropped prefetch.");
|
||||
mesh->stats_dropped ++;
|
||||
return;
|
||||
@@ -429,7 +448,10 @@ void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
log_err("prefetch mesh_state_create: out of memory");
|
||||
return;
|
||||
}
|
||||
n = rbtree_insert(&mesh->all, &s->node);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#endif
|
||||
rbtree_insert(&mesh->all, &s->node);
|
||||
log_assert(n != NULL);
|
||||
/* set detached (it is now) */
|
||||
mesh->num_detached_states++;
|
||||
@@ -627,11 +649,16 @@ void mesh_detach_subs(struct module_qstate* qstate)
|
||||
{
|
||||
struct mesh_area* mesh = qstate->env->mesh;
|
||||
struct mesh_state_ref* ref, lookup;
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_t* n;
|
||||
#endif
|
||||
lookup.node.key = &lookup;
|
||||
lookup.s = qstate->mesh_info;
|
||||
RBTREE_FOR(ref, struct mesh_state_ref*, &qstate->mesh_info->sub_set) {
|
||||
n = rbtree_delete(&ref->s->super_set, &lookup);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#endif
|
||||
rbtree_delete(&ref->s->super_set, &lookup);
|
||||
log_assert(n != NULL); /* must have been present */
|
||||
if(!ref->s->reply_list && !ref->s->cb_list
|
||||
&& ref->s->super_set.count == 0) {
|
||||
@@ -649,31 +676,43 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
/* find it, if not, create it */
|
||||
struct mesh_area* mesh = qstate->env->mesh;
|
||||
struct mesh_state* sub = mesh_area_find(mesh, qinfo, qflags, prime);
|
||||
int was_detached;
|
||||
if(mesh_detect_cycle_found(qstate, sub)) {
|
||||
verbose(VERB_ALGO, "attach failed, cycle detected");
|
||||
return 0;
|
||||
}
|
||||
if(!sub) {
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_t* n;
|
||||
#endif
|
||||
/* create a new one */
|
||||
sub = mesh_state_create(qstate->env, qinfo, qflags, prime);
|
||||
if(!sub) {
|
||||
log_err("mesh_attach_sub: out of memory");
|
||||
return 0;
|
||||
}
|
||||
n = rbtree_insert(&mesh->all, &sub->node);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#endif
|
||||
rbtree_insert(&mesh->all, &sub->node);
|
||||
log_assert(n != NULL);
|
||||
/* set detached (it is now) */
|
||||
mesh->num_detached_states++;
|
||||
/* set new query state to run */
|
||||
n = rbtree_insert(&mesh->run, &sub->run_node);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#endif
|
||||
rbtree_insert(&mesh->run, &sub->run_node);
|
||||
log_assert(n != NULL);
|
||||
*newq = &sub->s;
|
||||
} else
|
||||
*newq = NULL;
|
||||
was_detached = (sub->super_set.count == 0);
|
||||
if(!mesh_state_attachment(qstate->mesh_info, sub))
|
||||
return 0;
|
||||
if(!sub->reply_list && !sub->cb_list && sub->super_set.count == 1) {
|
||||
/* if it was a duplicate attachment, the count was not zero before */
|
||||
if(!sub->reply_list && !sub->cb_list && was_detached &&
|
||||
sub->super_set.count == 1) {
|
||||
/* it used to be detached, before this one got added */
|
||||
log_assert(mesh->num_detached_states > 0);
|
||||
mesh->num_detached_states--;
|
||||
@@ -684,7 +723,9 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
|
||||
int mesh_state_attachment(struct mesh_state* super, struct mesh_state* sub)
|
||||
{
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_t* n;
|
||||
#endif
|
||||
struct mesh_state_ref* subref; /* points to sub, inserted in super */
|
||||
struct mesh_state_ref* superref; /* points to super, inserted in sub */
|
||||
if( !(subref = regional_alloc(super->s.region,
|
||||
@@ -698,10 +739,20 @@ int mesh_state_attachment(struct mesh_state* super, struct mesh_state* sub)
|
||||
superref->s = super;
|
||||
subref->node.key = subref;
|
||||
subref->s = sub;
|
||||
n = rbtree_insert(&sub->super_set, &superref->node);
|
||||
log_assert(n != NULL);
|
||||
n = rbtree_insert(&super->sub_set, &subref->node);
|
||||
log_assert(n != NULL);
|
||||
if(!rbtree_insert(&sub->super_set, &superref->node)) {
|
||||
/* this should not happen, iterator and validator do not
|
||||
* attach subqueries that are identical. */
|
||||
/* already attached, we are done, nothing todo.
|
||||
* since superref and subref already allocated in region,
|
||||
* we cannot free them */
|
||||
return 1;
|
||||
}
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#endif
|
||||
rbtree_insert(&super->sub_set, &subref->node);
|
||||
log_assert(n != NULL); /* we checked above if statement, the reverse
|
||||
administration should not fail now, unless they are out of sync */
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1101,7 +1152,8 @@ mesh_get_mem(struct mesh_area* mesh)
|
||||
{
|
||||
struct mesh_state* m;
|
||||
size_t s = sizeof(*mesh) + sizeof(struct timehist) +
|
||||
sizeof(struct th_buck)*mesh->histogram->num;
|
||||
sizeof(struct th_buck)*mesh->histogram->num +
|
||||
sizeof(ldns_buffer) + ldns_buffer_capacity(mesh->qbuf_bak);
|
||||
RBTREE_FOR(m, struct mesh_state*, &mesh->all) {
|
||||
/* all, including m itself allocated in qstate region */
|
||||
s += regional_get_mem(m->s.region);
|
||||
|
||||
+14
-2
@@ -123,6 +123,10 @@ struct mesh_area {
|
||||
/** (extended stats) rcode nodata in replies */
|
||||
size_t ans_nodata;
|
||||
|
||||
/** backup of query if other operations recurse and need the
|
||||
* network buffers */
|
||||
ldns_buffer* qbuf_bak;
|
||||
|
||||
/** double linked list of the run-to-completion query states.
|
||||
* These are query states with a reply */
|
||||
struct mesh_state* forever_first;
|
||||
@@ -377,7 +381,8 @@ void mesh_query_done(struct mesh_state* mstate);
|
||||
* results from this query state. These can then be changed for error
|
||||
* or results.
|
||||
* Called when a module is module_finished or returns module_error.
|
||||
* The super query states become runnable with event module_event_pass.
|
||||
* The super query states become runnable with event module_event_pass,
|
||||
* it calls the current module for the super with the inform_super event.
|
||||
*
|
||||
* @param mesh: mesh area to add newly runnable modules to.
|
||||
* @param mstate: the state that has results, used to find mesh state.
|
||||
@@ -534,9 +539,16 @@ int mesh_state_ref_compare(const void* ap, const void* bp);
|
||||
/**
|
||||
* Make space for another recursion state for a reply in the mesh
|
||||
* @param mesh: mesh area
|
||||
* @param qbuf: query buffer to save if recursion is invoked to make space.
|
||||
* This buffer is necessary, because the following sequence in calls
|
||||
* can result in an overwrite of the incoming query:
|
||||
* delete_other_mesh_query - iter_clean - serviced_delete - waiting
|
||||
* udp query is sent - on error callback - callback sends SERVFAIL reply
|
||||
* over the same network channel, and shared UDP buffer is overwritten.
|
||||
* You can pass NULL if there is no buffer that must be backed up.
|
||||
* @return false if no space is available.
|
||||
*/
|
||||
int mesh_make_new_space(struct mesh_area* mesh);
|
||||
int mesh_make_new_space(struct mesh_area* mesh, ldns_buffer* qbuf);
|
||||
|
||||
/**
|
||||
* Insert mesh state into a double linked list. Inserted at end.
|
||||
|
||||
+144
-32
@@ -45,7 +45,7 @@
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
#include "ldns/wire2host.h"
|
||||
#include <ldns/wire2host.h>
|
||||
#include "services/outside_network.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "services/cache/infra.h"
|
||||
@@ -58,6 +58,7 @@
|
||||
#include "util/net_help.h"
|
||||
#include "util/random.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
@@ -226,7 +227,10 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
|
||||
#else
|
||||
if(1) {
|
||||
#endif
|
||||
log_err("outgoing tcp: connect: %s", strerror(errno));
|
||||
if(tcp_connect_errno_needs_log(
|
||||
(struct sockaddr*)&w->addr, w->addrlen))
|
||||
log_err("outgoing tcp: connect: %s",
|
||||
strerror(errno));
|
||||
close(s);
|
||||
#else /* USE_WINSOCK */
|
||||
if(WSAGetLastError() != WSAEINPROGRESS &&
|
||||
@@ -237,6 +241,18 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if(w->outnet->sslctx && w->ssl_upstream) {
|
||||
pend->c->ssl = outgoing_ssl_fd(w->outnet->sslctx, s);
|
||||
if(!pend->c->ssl) {
|
||||
pend->c->fd = s;
|
||||
comm_point_close(pend->c);
|
||||
return 0;
|
||||
}
|
||||
#ifdef USE_WINSOCK
|
||||
comm_point_tcp_win_bio_cb(pend->c, pend->c->ssl);
|
||||
#endif
|
||||
pend->c->ssl_shake_state = comm_ssl_shake_write;
|
||||
}
|
||||
w->pkt = NULL;
|
||||
w->next_waiting = (void*)pend;
|
||||
pend->id = LDNS_ID_WIRE(pkt);
|
||||
@@ -280,6 +296,13 @@ static void
|
||||
decomission_pending_tcp(struct outside_network* outnet,
|
||||
struct pending_tcp* pend)
|
||||
{
|
||||
if(pend->c->ssl) {
|
||||
#ifdef HAVE_SSL
|
||||
SSL_shutdown(pend->c->ssl);
|
||||
SSL_free(pend->c->ssl);
|
||||
pend->c->ssl = NULL;
|
||||
#endif
|
||||
}
|
||||
comm_point_close(pend->c);
|
||||
pend->next_free = outnet->tcp_free;
|
||||
outnet->tcp_free = pend;
|
||||
@@ -535,7 +558,8 @@ outside_network_create(struct comm_base *base, size_t bufsize,
|
||||
int do_ip6, size_t num_tcp, struct infra_cache* infra,
|
||||
struct ub_randstate* rnd, int use_caps_for_id, int* availports,
|
||||
int numavailports, size_t unwanted_threshold,
|
||||
void (*unwanted_action)(void*), void* unwanted_param, int do_udp)
|
||||
void (*unwanted_action)(void*), void* unwanted_param, int do_udp,
|
||||
void* sslctx)
|
||||
{
|
||||
struct outside_network* outnet = (struct outside_network*)
|
||||
calloc(1, sizeof(struct outside_network));
|
||||
@@ -549,6 +573,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
|
||||
outnet->num_tcp = num_tcp;
|
||||
outnet->infra = infra;
|
||||
outnet->rnd = rnd;
|
||||
outnet->sslctx = sslctx;
|
||||
outnet->svcd_overhead = 0;
|
||||
outnet->want_to_quit = 0;
|
||||
outnet->unwanted_threshold = unwanted_threshold;
|
||||
@@ -669,6 +694,7 @@ serviced_node_del(rbnode_t* node, void* ATTR_UNUSED(arg))
|
||||
struct serviced_query* sq = (struct serviced_query*)node;
|
||||
struct service_callback* p = sq->cblist, *np;
|
||||
free(sq->qbuf);
|
||||
free(sq->zone);
|
||||
while(p) {
|
||||
np = p->next;
|
||||
free(p);
|
||||
@@ -1054,7 +1080,7 @@ outnet_tcptimer(void* arg)
|
||||
struct waiting_tcp*
|
||||
pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int timeout,
|
||||
comm_point_callback_t* callback, void* callback_arg)
|
||||
comm_point_callback_t* callback, void* callback_arg, int ssl_upstream)
|
||||
{
|
||||
struct pending_tcp* pend = outnet->tcp_free;
|
||||
struct waiting_tcp* w;
|
||||
@@ -1079,6 +1105,7 @@ pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet,
|
||||
w->outnet = outnet;
|
||||
w->cb = callback;
|
||||
w->cb_arg = callback_arg;
|
||||
w->ssl_upstream = ssl_upstream;
|
||||
#ifndef S_SPLINT_S
|
||||
tv.tv_sec = timeout;
|
||||
tv.tv_usec = 0;
|
||||
@@ -1142,10 +1169,14 @@ lookup_serviced(struct outside_network* outnet, ldns_buffer* buff, int dnssec,
|
||||
/** Create new serviced entry */
|
||||
static struct serviced_query*
|
||||
serviced_create(struct outside_network* outnet, ldns_buffer* buff, int dnssec,
|
||||
int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
int want_dnssec, int tcp_upstream, int ssl_upstream,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, int qtype)
|
||||
{
|
||||
struct serviced_query* sq = (struct serviced_query*)malloc(sizeof(*sq));
|
||||
#ifdef UNBOUND_DEBUG
|
||||
rbnode_t* ins;
|
||||
#endif
|
||||
if(!sq)
|
||||
return NULL;
|
||||
sq->node.key = sq;
|
||||
@@ -1155,8 +1186,18 @@ serviced_create(struct outside_network* outnet, ldns_buffer* buff, int dnssec,
|
||||
return NULL;
|
||||
}
|
||||
sq->qbuflen = ldns_buffer_limit(buff);
|
||||
sq->zone = memdup(zone, zonelen);
|
||||
if(!sq->zone) {
|
||||
free(sq->qbuf);
|
||||
free(sq);
|
||||
return NULL;
|
||||
}
|
||||
sq->zonelen = zonelen;
|
||||
sq->qtype = qtype;
|
||||
sq->dnssec = dnssec;
|
||||
sq->want_dnssec = want_dnssec;
|
||||
sq->tcp_upstream = tcp_upstream;
|
||||
sq->ssl_upstream = ssl_upstream;
|
||||
memcpy(&sq->addr, addr, addrlen);
|
||||
sq->addrlen = addrlen;
|
||||
sq->outnet = outnet;
|
||||
@@ -1165,7 +1206,10 @@ serviced_create(struct outside_network* outnet, ldns_buffer* buff, int dnssec,
|
||||
sq->status = serviced_initial;
|
||||
sq->retry = 0;
|
||||
sq->to_be_deleted = 0;
|
||||
ins = rbtree_insert(outnet->serviced, &sq->node);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
ins =
|
||||
#endif
|
||||
rbtree_insert(outnet->serviced, &sq->node);
|
||||
log_assert(ins != NULL); /* must not be already present */
|
||||
return sq;
|
||||
}
|
||||
@@ -1199,6 +1243,7 @@ serviced_delete(struct serviced_query* sq)
|
||||
if(sq->status == serviced_query_UDP_EDNS ||
|
||||
sq->status == serviced_query_UDP ||
|
||||
sq->status == serviced_query_PROBE_EDNS ||
|
||||
sq->status == serviced_query_UDP_EDNS_FRAG ||
|
||||
sq->status == serviced_query_UDP_EDNS_fallback) {
|
||||
struct pending* p = (struct pending*)sq->pending;
|
||||
if(p->pc)
|
||||
@@ -1280,7 +1325,19 @@ serviced_encode(struct serviced_query* sq, ldns_buffer* buff, int with_edns)
|
||||
edns.edns_present = 1;
|
||||
edns.ext_rcode = 0;
|
||||
edns.edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
if(sq->status == serviced_query_UDP_EDNS_FRAG) {
|
||||
if(addr_is_ip6(&sq->addr, sq->addrlen)) {
|
||||
if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE)
|
||||
edns.udp_size = EDNS_FRAG_SIZE_IP6;
|
||||
else edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
} else {
|
||||
if(EDNS_FRAG_SIZE_IP4 < EDNS_ADVERTISED_SIZE)
|
||||
edns.udp_size = EDNS_FRAG_SIZE_IP4;
|
||||
else edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
}
|
||||
} else {
|
||||
edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
}
|
||||
edns.bits = 0;
|
||||
if(sq->dnssec & EDNS_DO)
|
||||
edns.bits = EDNS_DO;
|
||||
@@ -1304,8 +1361,8 @@ serviced_udp_send(struct serviced_query* sq, ldns_buffer* buff)
|
||||
uint8_t edns_lame_known;
|
||||
uint32_t now = *sq->outnet->now_secs;
|
||||
|
||||
if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen, now, &vs,
|
||||
&edns_lame_known, &rtt))
|
||||
if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen, sq->zone,
|
||||
sq->zonelen, now, &vs, &edns_lame_known, &rtt))
|
||||
return 0;
|
||||
sq->last_rtt = rtt;
|
||||
verbose(VERB_ALGO, "EDNS lookup known=%d vs=%d", edns_lame_known, vs);
|
||||
@@ -1324,7 +1381,8 @@ serviced_udp_send(struct serviced_query* sq, ldns_buffer* buff)
|
||||
sq->status = serviced_query_UDP;
|
||||
}
|
||||
}
|
||||
serviced_encode(sq, buff, sq->status == serviced_query_UDP_EDNS);
|
||||
serviced_encode(sq, buff, (sq->status == serviced_query_UDP_EDNS) ||
|
||||
(sq->status == serviced_query_UDP_EDNS_FRAG));
|
||||
sq->last_sent_time = *sq->outnet->now_tv;
|
||||
sq->edns_lame_known = (int)edns_lame_known;
|
||||
verbose(VERB_ALGO, "serviced query UDP timeout=%d msec", rtt);
|
||||
@@ -1387,11 +1445,13 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c,
|
||||
int dobackup = (sq->cblist && sq->cblist->next); /* >1 cb*/
|
||||
uint8_t *backup_p = NULL;
|
||||
size_t backlen = 0;
|
||||
rbnode_t* rem;
|
||||
#ifdef UNBOUND_DEBUG
|
||||
rbnode_t* rem =
|
||||
#endif
|
||||
/* remove from tree, and schedule for deletion, so that callbacks
|
||||
* can safely deregister themselves and even create new serviced
|
||||
* queries that are identical to this one. */
|
||||
rem = rbtree_delete(sq->outnet->serviced, sq);
|
||||
rbtree_delete(sq->outnet->serviced, sq);
|
||||
log_assert(rem); /* should have been present */
|
||||
sq->to_be_deleted = 1;
|
||||
verbose(VERB_ALGO, "svcd callbacks start");
|
||||
@@ -1472,7 +1532,7 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
|
||||
&sq->addr, sq->addrlen);
|
||||
if(error==NETEVENT_NOERROR)
|
||||
infra_update_tcp_works(sq->outnet->infra, &sq->addr,
|
||||
sq->addrlen);
|
||||
sq->addrlen, sq->zone, sq->zonelen);
|
||||
if(error==NETEVENT_NOERROR && sq->status == serviced_query_TCP_EDNS &&
|
||||
(LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) ==
|
||||
LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE(ldns_buffer_begin(
|
||||
@@ -1493,10 +1553,31 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
|
||||
/* only store noEDNS in cache if domain is noDNSSEC */
|
||||
if(!sq->want_dnssec)
|
||||
if(!infra_edns_update(sq->outnet->infra, &sq->addr,
|
||||
sq->addrlen, -1, *sq->outnet->now_secs))
|
||||
sq->addrlen, sq->zone, sq->zonelen, -1,
|
||||
*sq->outnet->now_secs))
|
||||
log_err("Out of memory caching no edns for host");
|
||||
sq->status = serviced_query_TCP;
|
||||
}
|
||||
if(sq->tcp_upstream || sq->ssl_upstream) {
|
||||
struct timeval now = *sq->outnet->now_tv;
|
||||
if(now.tv_sec > sq->last_sent_time.tv_sec ||
|
||||
(now.tv_sec == sq->last_sent_time.tv_sec &&
|
||||
now.tv_usec > sq->last_sent_time.tv_usec)) {
|
||||
/* convert from microseconds to milliseconds */
|
||||
int roundtime = ((int)now.tv_sec - (int)sq->last_sent_time.tv_sec)*1000
|
||||
+ ((int)now.tv_usec - (int)sq->last_sent_time.tv_usec)/1000;
|
||||
verbose(VERB_ALGO, "measured TCP-time at %d msec", roundtime);
|
||||
log_assert(roundtime >= 0);
|
||||
/* only store if less then AUTH_TIMEOUT seconds, it could be
|
||||
* huge due to system-hibernated and we woke up */
|
||||
if(roundtime < TCP_AUTH_QUERY_TIMEOUT*1000) {
|
||||
if(!infra_rtt_update(sq->outnet->infra, &sq->addr,
|
||||
sq->addrlen, sq->zone, sq->zonelen, sq->qtype,
|
||||
roundtime, sq->last_rtt, (uint32_t)now.tv_sec))
|
||||
log_err("out of memory noting rtt.");
|
||||
}
|
||||
}
|
||||
}
|
||||
/* insert address into reply info */
|
||||
if(!rep) {
|
||||
/* create one if there isn't (on errors) */
|
||||
@@ -1516,9 +1597,10 @@ serviced_tcp_initiate(struct outside_network* outnet,
|
||||
verbose(VERB_ALGO, "initiate TCP query %s",
|
||||
sq->status==serviced_query_TCP_EDNS?"EDNS":"");
|
||||
serviced_encode(sq, buff, sq->status == serviced_query_TCP_EDNS);
|
||||
sq->last_sent_time = *sq->outnet->now_tv;
|
||||
sq->pending = pending_tcp_query(outnet, buff, &sq->addr,
|
||||
sq->addrlen, TCP_AUTH_QUERY_TIMEOUT, serviced_tcp_callback,
|
||||
sq);
|
||||
sq, sq->ssl_upstream);
|
||||
if(!sq->pending) {
|
||||
/* delete from tree so that a retry by above layer does not
|
||||
* clash with this entry */
|
||||
@@ -1533,16 +1615,18 @@ serviced_tcp_send(struct serviced_query* sq, ldns_buffer* buff)
|
||||
{
|
||||
int vs, rtt;
|
||||
uint8_t edns_lame_known;
|
||||
if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen,
|
||||
*sq->outnet->now_secs, &vs, &edns_lame_known, &rtt))
|
||||
if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen, sq->zone,
|
||||
sq->zonelen, *sq->outnet->now_secs, &vs, &edns_lame_known,
|
||||
&rtt))
|
||||
return 0;
|
||||
if(vs != -1)
|
||||
sq->status = serviced_query_TCP_EDNS;
|
||||
else sq->status = serviced_query_TCP;
|
||||
serviced_encode(sq, buff, sq->status == serviced_query_TCP_EDNS);
|
||||
sq->last_sent_time = *sq->outnet->now_tv;
|
||||
sq->pending = pending_tcp_query(sq->outnet, buff, &sq->addr,
|
||||
sq->addrlen, TCP_AUTH_QUERY_TIMEOUT, serviced_tcp_callback,
|
||||
sq);
|
||||
sq, sq->ssl_upstream);
|
||||
return sq->pending != NULL;
|
||||
}
|
||||
|
||||
@@ -1564,9 +1648,24 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
* by EDNS. */
|
||||
sq->status = serviced_query_UDP_EDNS;
|
||||
}
|
||||
if(sq->status == serviced_query_UDP_EDNS && sq->last_rtt < 5000) {
|
||||
/* fallback to 1480/1280 */
|
||||
sq->status = serviced_query_UDP_EDNS_FRAG;
|
||||
log_name_addr(VERB_ALGO, "try edns1xx0", sq->qbuf+10,
|
||||
&sq->addr, sq->addrlen);
|
||||
if(!serviced_udp_send(sq, c->buffer)) {
|
||||
serviced_callbacks(sq, NETEVENT_CLOSED, c, rep);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if(sq->status == serviced_query_UDP_EDNS_FRAG) {
|
||||
/* fragmentation size did not fix it */
|
||||
sq->status = serviced_query_UDP_EDNS;
|
||||
}
|
||||
sq->retry++;
|
||||
if(!(rto=infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
-1, sq->last_rtt, (uint32_t)now.tv_sec)))
|
||||
sq->zone, sq->zonelen, sq->qtype, -1, sq->last_rtt,
|
||||
(uint32_t)now.tv_sec)))
|
||||
log_err("out of memory in UDP exponential backoff");
|
||||
if(sq->retry < OUTBOUND_UDP_RETRY) {
|
||||
log_name_addr(VERB_ALGO, "retry query", sq->qbuf+10,
|
||||
@@ -1589,7 +1688,8 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
return 0;
|
||||
}
|
||||
if(!fallback_tcp) {
|
||||
if(sq->status == serviced_query_UDP_EDNS
|
||||
if( (sq->status == serviced_query_UDP_EDNS
|
||||
||sq->status == serviced_query_UDP_EDNS_FRAG)
|
||||
&& (LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer))
|
||||
== LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE(
|
||||
ldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOTIMPL)) {
|
||||
@@ -1609,7 +1709,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
/* only store noEDNS in cache if domain is noDNSSEC */
|
||||
if(!sq->want_dnssec)
|
||||
if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
-1, (uint32_t)now.tv_sec)) {
|
||||
sq->zone, sq->zonelen, -1, (uint32_t)now.tv_sec)) {
|
||||
log_err("Out of memory caching no edns for host");
|
||||
}
|
||||
sq->status = serviced_query_UDP;
|
||||
@@ -1619,7 +1719,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
log_addr(VERB_ALGO, "serviced query: EDNS works for",
|
||||
&sq->addr, sq->addrlen);
|
||||
if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
0, (uint32_t)now.tv_sec)) {
|
||||
sq->zone, sq->zonelen, 0, (uint32_t)now.tv_sec)) {
|
||||
log_err("Out of memory caching edns works");
|
||||
}
|
||||
sq->edns_lame_known = 1;
|
||||
@@ -1636,7 +1736,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
log_addr(VERB_ALGO, "serviced query: EDNS fails for",
|
||||
&sq->addr, sq->addrlen);
|
||||
if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
-1, (uint32_t)now.tv_sec)) {
|
||||
sq->zone, sq->zonelen, -1, (uint32_t)now.tv_sec)) {
|
||||
log_err("Out of memory caching no edns for host");
|
||||
}
|
||||
} else {
|
||||
@@ -1654,9 +1754,14 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
+ ((int)now.tv_usec - (int)sq->last_sent_time.tv_usec)/1000;
|
||||
verbose(VERB_ALGO, "measured roundtrip at %d msec", roundtime);
|
||||
log_assert(roundtime >= 0);
|
||||
if(!infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
roundtime, sq->last_rtt, (uint32_t)now.tv_sec))
|
||||
/* in case the system hibernated, do not enter a huge value,
|
||||
* above this value gives trouble with server selection */
|
||||
if(roundtime < 60000) {
|
||||
if(!infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
sq->zone, sq->zonelen, sq->qtype, roundtime,
|
||||
sq->last_rtt, (uint32_t)now.tv_sec))
|
||||
log_err("out of memory noting rtt.");
|
||||
}
|
||||
}
|
||||
} /* end of if_!fallback_tcp */
|
||||
/* perform TC flag check and TCP fallback after updating our
|
||||
@@ -1665,6 +1770,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
/* fallback to TCP */
|
||||
/* this discards partial UDP contents */
|
||||
if(sq->status == serviced_query_UDP_EDNS ||
|
||||
sq->status == serviced_query_UDP_EDNS_FRAG ||
|
||||
sq->status == serviced_query_UDP_EDNS_fallback)
|
||||
/* if we have unfinished EDNS_fallback, start again */
|
||||
sq->status = serviced_query_TCP_EDNS;
|
||||
@@ -1694,9 +1800,9 @@ struct serviced_query*
|
||||
outnet_serviced_query(struct outside_network* outnet,
|
||||
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int tcp_upstream,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
comm_point_callback_t* callback, void* callback_arg,
|
||||
ldns_buffer* buff, int (*arg_compare)(void*,void*))
|
||||
int ssl_upstream, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, comm_point_callback_t* callback,
|
||||
void* callback_arg, ldns_buffer* buff, int (*arg_compare)(void*,void*))
|
||||
{
|
||||
struct serviced_query* sq;
|
||||
struct service_callback* cb;
|
||||
@@ -1713,16 +1819,18 @@ outnet_serviced_query(struct outside_network* outnet,
|
||||
if(!sq) {
|
||||
/* make new serviced query entry */
|
||||
sq = serviced_create(outnet, buff, dnssec, want_dnssec,
|
||||
addr, addrlen);
|
||||
tcp_upstream, ssl_upstream, addr, addrlen, zone,
|
||||
zonelen, (int)qtype);
|
||||
if(!sq) {
|
||||
free(cb);
|
||||
return NULL;
|
||||
}
|
||||
/* perform first network action */
|
||||
if(outnet->do_udp && !tcp_upstream) {
|
||||
if(outnet->do_udp && !(tcp_upstream || ssl_upstream)) {
|
||||
if(!serviced_udp_send(sq, buff)) {
|
||||
(void)rbtree_delete(outnet->serviced, sq);
|
||||
free(sq->qbuf);
|
||||
free(sq->zone);
|
||||
free(sq);
|
||||
free(cb);
|
||||
return NULL;
|
||||
@@ -1731,6 +1839,7 @@ outnet_serviced_query(struct outside_network* outnet,
|
||||
if(!serviced_tcp_send(sq, buff)) {
|
||||
(void)rbtree_delete(outnet->serviced, sq);
|
||||
free(sq->qbuf);
|
||||
free(sq->zone);
|
||||
free(sq);
|
||||
free(cb);
|
||||
return NULL;
|
||||
@@ -1768,8 +1877,10 @@ void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg)
|
||||
callback_list_remove(sq, cb_arg);
|
||||
/* if callbacks() routine scheduled deletion, let it do that */
|
||||
if(!sq->cblist && !sq->to_be_deleted) {
|
||||
rbnode_t* rem;
|
||||
rem = rbtree_delete(sq->outnet->serviced, sq);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
rbnode_t* rem =
|
||||
#endif
|
||||
rbtree_delete(sq->outnet->serviced, sq);
|
||||
log_assert(rem); /* should be present */
|
||||
serviced_delete(sq);
|
||||
}
|
||||
@@ -1866,6 +1977,7 @@ serviced_get_mem(struct serviced_query* sq)
|
||||
if(sq->status == serviced_query_UDP_EDNS ||
|
||||
sq->status == serviced_query_UDP ||
|
||||
sq->status == serviced_query_PROBE_EDNS ||
|
||||
sq->status == serviced_query_UDP_EDNS_FRAG ||
|
||||
sq->status == serviced_query_UDP_EDNS_fallback) {
|
||||
s += sizeof(struct pending);
|
||||
s += comm_timer_get_mem(NULL);
|
||||
|
||||
@@ -118,6 +118,8 @@ struct outside_network {
|
||||
struct infra_cache* infra;
|
||||
/** where to get random numbers */
|
||||
struct ub_randstate* rnd;
|
||||
/** ssl context to create ssl wrapped TCP with DNS connections */
|
||||
void* sslctx;
|
||||
|
||||
/**
|
||||
* Array of tcp pending used for outgoing TCP connections.
|
||||
@@ -260,6 +262,8 @@ struct waiting_tcp {
|
||||
comm_point_callback_t* cb;
|
||||
/** callback user argument */
|
||||
void* cb_arg;
|
||||
/** if it uses ssl upstream */
|
||||
int ssl_upstream;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -274,6 +278,11 @@ struct service_callback {
|
||||
void* cb_arg;
|
||||
};
|
||||
|
||||
/** fallback size for fragmentation for EDNS in IPv4 */
|
||||
#define EDNS_FRAG_SIZE_IP4 1480
|
||||
/** fallback size for EDNS in IPv6, fits one fragment with ip6-tunnel-ids */
|
||||
#define EDNS_FRAG_SIZE_IP6 1260
|
||||
|
||||
/**
|
||||
* Query service record.
|
||||
* Contains query and destination. UDP, TCP, EDNS are all tried.
|
||||
@@ -293,10 +302,18 @@ struct serviced_query {
|
||||
int dnssec;
|
||||
/** We want signatures, or else the answer is likely useless */
|
||||
int want_dnssec;
|
||||
/** tcp upstream used, use tcp, or ssl_upstream for SSL */
|
||||
int tcp_upstream, ssl_upstream;
|
||||
/** where to send it */
|
||||
struct sockaddr_storage addr;
|
||||
/** length of addr field in use. */
|
||||
socklen_t addrlen;
|
||||
/** zone name, uncompressed domain name in wireformat */
|
||||
uint8_t* zone;
|
||||
/** length of zone name */
|
||||
size_t zonelen;
|
||||
/** qtype */
|
||||
int qtype;
|
||||
/** current status */
|
||||
enum serviced_query_status {
|
||||
/** initial status */
|
||||
@@ -314,7 +331,9 @@ struct serviced_query {
|
||||
/** probe to test noEDNS0 (EDNS gives FORMERRorNOTIMP) */
|
||||
serviced_query_UDP_EDNS_fallback,
|
||||
/** probe to test TCP noEDNS0 (EDNS gives FORMERRorNOTIMP) */
|
||||
serviced_query_TCP_EDNS_fallback
|
||||
serviced_query_TCP_EDNS_fallback,
|
||||
/** send UDP query with EDNS1480 (or 1280) */
|
||||
serviced_query_UDP_EDNS_FRAG
|
||||
}
|
||||
/** variable with current status */
|
||||
status;
|
||||
@@ -356,6 +375,7 @@ struct serviced_query {
|
||||
* @param unwanted_action: the action to take.
|
||||
* @param unwanted_param: user parameter to action.
|
||||
* @param do_udp: if udp is done.
|
||||
* @param sslctx: context to create outgoing connections with (if enabled).
|
||||
* @return: the new structure (with no pending answers) or NULL on error.
|
||||
*/
|
||||
struct outside_network* outside_network_create(struct comm_base* base,
|
||||
@@ -363,7 +383,8 @@ struct outside_network* outside_network_create(struct comm_base* base,
|
||||
int do_ip4, int do_ip6, size_t num_tcp, struct infra_cache* infra,
|
||||
struct ub_randstate* rnd, int use_caps_for_id, int* availports,
|
||||
int numavailports, size_t unwanted_threshold,
|
||||
void (*unwanted_action)(void*), void* unwanted_param, int do_udp);
|
||||
void (*unwanted_action)(void*), void* unwanted_param, int do_udp,
|
||||
void* sslctx);
|
||||
|
||||
/**
|
||||
* Delete outside_network structure.
|
||||
@@ -406,12 +427,13 @@ struct pending* pending_udp_query(struct outside_network* outnet,
|
||||
* without any query been sent to the server yet.
|
||||
* @param callback: function to call on error, timeout or reply.
|
||||
* @param callback_arg: user argument for callback function.
|
||||
* @param ssl_upstream: if the tcp connection must use SSL.
|
||||
* @return: false on error for malloc or socket. Else the pending TCP object.
|
||||
*/
|
||||
struct waiting_tcp* pending_tcp_query(struct outside_network* outnet,
|
||||
ldns_buffer* packet, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int timeout, comm_point_callback_t* callback,
|
||||
void* callback_arg);
|
||||
void* callback_arg, int ssl_upstream);
|
||||
|
||||
/**
|
||||
* Delete pending answer.
|
||||
@@ -436,10 +458,15 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
|
||||
* @param want_dnssec: signatures are needed, without EDNS the answer is
|
||||
* likely to be useless.
|
||||
* @param tcp_upstream: use TCP for upstream queries.
|
||||
* @param ssl_upstream: use SSL for upstream queries.
|
||||
* @param callback: callback function.
|
||||
* @param callback_arg: user argument to callback function.
|
||||
* @param addr: to which server to send the query.
|
||||
* @param addrlen: length of addr.
|
||||
* @param zone: name of the zone of the delegation point. wireformat dname.
|
||||
This is the delegation point name for which the server is deemed
|
||||
authoritative.
|
||||
* @param zonelen: length of zone.
|
||||
* @param buff: scratch buffer to create query contents in. Empty on exit.
|
||||
* @param arg_compare: function to compare callback args, return true if
|
||||
* identical. It is given the callback_arg and args that are listed.
|
||||
@@ -449,9 +476,10 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
|
||||
struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int tcp_upstream,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
comm_point_callback_t* callback, void* callback_arg,
|
||||
ldns_buffer* buff, int (*arg_compare)(void*,void*));
|
||||
int ssl_upstream, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, comm_point_callback_t* callback,
|
||||
void* callback_arg, ldns_buffer* buff,
|
||||
int (*arg_compare)(void*,void*));
|
||||
|
||||
/**
|
||||
* Remove service query callback.
|
||||
|
||||
@@ -1583,7 +1583,9 @@ xml_parse(BIO* xml, time_t now)
|
||||
(void)BIO_seek(data.ds, 0);
|
||||
len = BIO_get_mem_data(data.ds, &pp);
|
||||
printf("got DS bio %d: '", len);
|
||||
(void)fwrite(pp, (size_t)len, 1, stdout);
|
||||
if(!fwrite(pp, (size_t)len, 1, stdout))
|
||||
/* compilers do not allow us to ignore fwrite .. */
|
||||
fprintf(stderr, "error writing to stdout\n");
|
||||
printf("'\n");
|
||||
}
|
||||
BIO_free(data.czone);
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "util/regional.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
#include "validator/validator.h"
|
||||
#include "services/localzone.h"
|
||||
#ifdef HAVE_GETOPT_H
|
||||
@@ -434,6 +435,17 @@ check_fwd(struct config_file* cfg)
|
||||
forwards_delete(fwd);
|
||||
}
|
||||
|
||||
/** check hints */
|
||||
static void
|
||||
check_hints(struct config_file* cfg)
|
||||
{
|
||||
struct iter_hints* hints = hints_create();
|
||||
if(!hints || !hints_apply_cfg(hints, cfg)) {
|
||||
fatal_exit("Could not set root or stub hints");
|
||||
}
|
||||
hints_delete(hints);
|
||||
}
|
||||
|
||||
/** check config file */
|
||||
static void
|
||||
checkconf(const char* cfgfile, const char* opt)
|
||||
@@ -454,6 +466,7 @@ checkconf(const char* cfgfile, const char* opt)
|
||||
check_mod(cfg, pythonmod_get_funcblock());
|
||||
#endif
|
||||
check_fwd(cfg);
|
||||
check_hints(cfg);
|
||||
if(opt) print_option(cfg, opt);
|
||||
else printf("unbound-checkconf: no errors in %s\n", cfgfile);
|
||||
config_delete(cfg);
|
||||
@@ -470,9 +483,15 @@ int main(int argc, char* argv[])
|
||||
int c;
|
||||
const char* f;
|
||||
const char* opt = NULL;
|
||||
const char* cfgfile = CONFIGFILE;
|
||||
log_ident_set("unbound-checkconf");
|
||||
log_init(NULL, 0, NULL);
|
||||
checklock_start();
|
||||
#ifdef USE_WINSOCK
|
||||
/* use registry config file in preference to compiletime location */
|
||||
if(!(cfgfile=w_lookup_reg_str("Software\\Unbound", "ConfigFile")))
|
||||
cfgfile = CONFIGFILE;
|
||||
#endif /* USE_WINSOCK */
|
||||
/* parse the options */
|
||||
while( (c=getopt(argc, argv, "ho:")) != -1) {
|
||||
switch(c) {
|
||||
@@ -491,7 +510,7 @@ int main(int argc, char* argv[])
|
||||
usage();
|
||||
if(argc == 1)
|
||||
f = argv[0];
|
||||
else f = CONFIGFILE;
|
||||
else f = cfgfile;
|
||||
checkconf(f, opt);
|
||||
checklock_stop();
|
||||
return 0;
|
||||
|
||||
@@ -93,6 +93,7 @@ usage()
|
||||
printf(" flush_type <name> <type> flush name, type from cache\n");
|
||||
printf(" flush_zone <name> flush everything at or under name\n");
|
||||
printf(" from rr and dnssec caches\n");
|
||||
printf(" flush_bogus flush all bogus data\n");
|
||||
printf(" flush_stats flush statistics, make zero\n");
|
||||
printf(" flush_requestlist drop queries that are worked on\n");
|
||||
printf(" dump_requestlist show what is worked on\n");
|
||||
@@ -104,6 +105,12 @@ usage()
|
||||
printf(" list_forwards list forward-zones in use\n");
|
||||
printf(" list_local_zones list local-zones in use\n");
|
||||
printf(" list_local_data list local-data RRs in use\n");
|
||||
printf(" forward_add [+i] zone addr.. add forward-zone with servers\n");
|
||||
printf(" forward_remove [+i] zone remove forward zone\n");
|
||||
printf(" stub_add [+ip] zone addr.. add stub-zone with servers\n");
|
||||
printf(" stub_remove [+i] zone remove stub zone\n");
|
||||
printf(" +i also do dnssec insecure point\n");
|
||||
printf(" +p set stub to use priming\n");
|
||||
printf(" forward [off | addr ...] without arg show forward setup\n");
|
||||
printf(" or off to turn off root forwarding\n");
|
||||
printf(" or give list of ip addresses\n");
|
||||
@@ -360,6 +367,9 @@ int main(int argc, char* argv[])
|
||||
#ifdef USE_WINSOCK
|
||||
if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0)
|
||||
fatal_exit("WSAStartup failed: %s", wsa_strerror(r));
|
||||
/* use registry config file in preference to compiletime location */
|
||||
if(!(cfgfile=w_lookup_reg_str("Software\\Unbound", "ConfigFile")))
|
||||
cfgfile = CONFIGFILE;
|
||||
#endif
|
||||
|
||||
ERR_load_crypto_strings();
|
||||
@@ -370,7 +380,8 @@ int main(int argc, char* argv[])
|
||||
if(!RAND_status()) {
|
||||
/* try to seed it */
|
||||
unsigned char buf[256];
|
||||
unsigned int v, seed=(unsigned)time(NULL) ^ (unsigned)getpid();
|
||||
unsigned int seed=(unsigned)time(NULL) ^ (unsigned)getpid();
|
||||
unsigned int v = seed;
|
||||
size_t i;
|
||||
for(i=0; i<256/sizeof(v); i++) {
|
||||
memmove(buf+i*sizeof(v), &v, sizeof(v));
|
||||
|
||||
+11
-1
@@ -61,6 +61,9 @@
|
||||
#endif
|
||||
#include "libunbound/unbound.h"
|
||||
#include <ldns/ldns.h>
|
||||
#ifdef HAVE_NSS
|
||||
#include <nss3/nss.h>
|
||||
#endif
|
||||
|
||||
/** verbosity for unbound-host app */
|
||||
static int verb = 0;
|
||||
@@ -255,9 +258,10 @@ print_rd(int t, char* data, size_t len)
|
||||
ldns_rr_set_owner(rr, NULL);
|
||||
status = ldns_wire2rdf(rr, rd, len+2, &pos);
|
||||
if(status != LDNS_STATUS_OK) {
|
||||
|
||||
free(rd);
|
||||
ldns_rr_free(rr);
|
||||
printf("error_printing_data");
|
||||
return;
|
||||
}
|
||||
for(i=0; i<ldns_rr_rd_count(rr); i++) {
|
||||
printf(" ");
|
||||
@@ -508,6 +512,12 @@ int main(int argc, char* argv[])
|
||||
if(argc != 1)
|
||||
usage();
|
||||
|
||||
#ifdef HAVE_NSS
|
||||
if(NSS_NoDB_Init(".") != SECSuccess) {
|
||||
fprintf(stderr, "could not init NSS\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
lookup(ctx, argv[0], qtype, qclass);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -195,6 +195,16 @@ void worker_probe_timer_cb(void* ATTR_UNUSED(arg))
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void worker_start_accept(void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void worker_stop_accept(void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
/** keep track of lock id in lock-verify application */
|
||||
struct order_id {
|
||||
/** the thread id that created it */
|
||||
|
||||
+80
-10
@@ -51,6 +51,7 @@
|
||||
#include "util/data/msgparse.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/data/msgencode.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/config_file.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "services/outside_network.h"
|
||||
@@ -61,6 +62,7 @@
|
||||
#include "util/fptr_wlist.h"
|
||||
#include <signal.h>
|
||||
struct worker;
|
||||
struct daemon_remote;
|
||||
|
||||
/** Global variable: the scenario. Saved here for when event_init is done. */
|
||||
static struct replay_scenario* saved_scenario = NULL;
|
||||
@@ -146,6 +148,7 @@ delete_fake_pending(struct fake_pending* pend)
|
||||
{
|
||||
if(!pend)
|
||||
return;
|
||||
free(pend->zone);
|
||||
ldns_buffer_free(pend->buffer);
|
||||
ldns_pkt_free(pend->pkt);
|
||||
free(pend);
|
||||
@@ -548,11 +551,35 @@ static void
|
||||
do_infra_rtt(struct replay_runtime* runtime)
|
||||
{
|
||||
struct replay_moment* now = runtime->now;
|
||||
int rto = infra_rtt_update(runtime->infra, &now->addr,
|
||||
now->addrlen, atoi(now->string), -1, runtime->now_secs);
|
||||
int rto;
|
||||
ldns_rdf* dp = ldns_dname_new_frm_str(now->variable);
|
||||
if(!dp) fatal_exit("cannot parse %s", now->variable);
|
||||
rto = infra_rtt_update(runtime->infra, &now->addr,
|
||||
now->addrlen, ldns_rdf_data(dp), ldns_rdf_size(dp),
|
||||
LDNS_RR_TYPE_A, atoi(now->string), -1, runtime->now_secs);
|
||||
log_addr(0, "INFRA_RTT for", &now->addr, now->addrlen);
|
||||
log_info("INFRA_RTT(roundtrip %d): rto of %d", atoi(now->string), rto);
|
||||
log_info("INFRA_RTT(%s roundtrip %d): rto of %d", now->variable,
|
||||
atoi(now->string), rto);
|
||||
if(rto == 0) fatal_exit("infra_rtt_update failed");
|
||||
ldns_rdf_deep_free(dp);
|
||||
}
|
||||
|
||||
/** perform exponential backoff on the timout */
|
||||
static void
|
||||
expon_timeout_backoff(struct replay_runtime* runtime)
|
||||
{
|
||||
struct fake_pending* p = runtime->pending_list;
|
||||
int rtt, vs;
|
||||
uint8_t edns_lame_known;
|
||||
int last_rtt, rto;
|
||||
if(!p) return; /* no pending packet to backoff */
|
||||
if(!infra_host(runtime->infra, &p->addr, p->addrlen, p->zone,
|
||||
p->zonelen, runtime->now_secs, &vs, &edns_lame_known, &rtt))
|
||||
return;
|
||||
last_rtt = rtt;
|
||||
rto = infra_rtt_update(runtime->infra, &p->addr, p->addrlen, p->zone,
|
||||
p->zonelen, p->qtype, -1, last_rtt, runtime->now_secs);
|
||||
log_info("infra_rtt_update returned rto %d", rto);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,6 +628,7 @@ do_moment_and_advance(struct replay_runtime* runtime)
|
||||
case repevt_timeout:
|
||||
mom = runtime->now;
|
||||
advance_moment(runtime);
|
||||
expon_timeout_backoff(runtime);
|
||||
fake_pending_callback(runtime, mom, NETEVENT_TIMEOUT);
|
||||
break;
|
||||
case repevt_back_reply:
|
||||
@@ -701,7 +729,7 @@ run_scenario(struct replay_runtime* runtime)
|
||||
struct listen_dnsport*
|
||||
listen_create(struct comm_base* base, struct listen_port* ATTR_UNUSED(ports),
|
||||
size_t bufsize, int ATTR_UNUSED(tcp_accept_count),
|
||||
comm_point_callback_t* cb, void* cb_arg)
|
||||
void* ATTR_UNUSED(sslctx), comm_point_callback_t* cb, void* cb_arg)
|
||||
{
|
||||
struct replay_runtime* runtime = (struct replay_runtime*)base;
|
||||
struct listen_dnsport* l= calloc(1, sizeof(struct listen_dnsport));
|
||||
@@ -870,7 +898,7 @@ outside_network_create(struct comm_base* base, size_t bufsize,
|
||||
int ATTR_UNUSED(use_caps_for_id), int* ATTR_UNUSED(availports),
|
||||
int ATTR_UNUSED(numavailports), size_t ATTR_UNUSED(unwanted_threshold),
|
||||
void (*unwanted_action)(void*), void* ATTR_UNUSED(unwanted_param),
|
||||
int ATTR_UNUSED(do_udp))
|
||||
int ATTR_UNUSED(do_udp), void* ATTR_UNUSED(sslctx))
|
||||
{
|
||||
struct replay_runtime* runtime = (struct replay_runtime*)base;
|
||||
struct outside_network* outnet = calloc(1,
|
||||
@@ -922,6 +950,7 @@ pending_udp_query(struct outside_network* outnet, ldns_buffer* packet,
|
||||
pend->timeout = timeout/1000;
|
||||
pend->transport = transport_udp;
|
||||
pend->pkt = NULL;
|
||||
pend->zone = NULL;
|
||||
pend->serviced = 0;
|
||||
pend->runtime = runtime;
|
||||
status = ldns_buffer2pkt_wire(&pend->pkt, packet);
|
||||
@@ -955,7 +984,8 @@ pending_udp_query(struct outside_network* outnet, ldns_buffer* packet,
|
||||
struct waiting_tcp*
|
||||
pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int timeout,
|
||||
comm_point_callback_t* callback, void* callback_arg)
|
||||
comm_point_callback_t* callback, void* callback_arg,
|
||||
int ATTR_UNUSED(ssl_upstream))
|
||||
{
|
||||
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
|
||||
struct fake_pending* pend = (struct fake_pending*)calloc(1,
|
||||
@@ -974,6 +1004,7 @@ pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet,
|
||||
pend->timeout = timeout;
|
||||
pend->transport = transport_tcp;
|
||||
pend->pkt = NULL;
|
||||
pend->zone = NULL;
|
||||
pend->runtime = runtime;
|
||||
pend->serviced = 0;
|
||||
status = ldns_buffer2pkt_wire(&pend->pkt, packet);
|
||||
@@ -1007,20 +1038,23 @@ pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet,
|
||||
struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
|
||||
uint16_t flags, int dnssec, int ATTR_UNUSED(want_dnssec),
|
||||
int ATTR_UNUSED(tcp_upstream), struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, comm_point_callback_t* callback, void* callback_arg,
|
||||
int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream),
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, comm_point_callback_t* callback, void* callback_arg,
|
||||
ldns_buffer* ATTR_UNUSED(buff), int (*arg_compare)(void*,void*))
|
||||
{
|
||||
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
|
||||
struct fake_pending* pend = (struct fake_pending*)calloc(1,
|
||||
sizeof(struct fake_pending));
|
||||
char z[256];
|
||||
ldns_status status;
|
||||
(void)arg_compare;
|
||||
log_assert(pend);
|
||||
log_nametypeclass(VERB_OPS, "pending serviced query",
|
||||
qname, qtype, qclass);
|
||||
verbose(VERB_OPS, "pending serviced query flags%s%s%s%s",
|
||||
(flags&BIT_RD)?" RD":"", (flags&BIT_CD)?" CD":"",
|
||||
dname_str(zone, z);
|
||||
verbose(VERB_OPS, "pending serviced query zone %s flags%s%s%s%s",
|
||||
z, (flags&BIT_RD)?" RD":"", (flags&BIT_CD)?" CD":"",
|
||||
(flags&~(BIT_RD|BIT_CD))?" MORE":"", (dnssec)?" DO":"");
|
||||
|
||||
/* create packet with EDNS */
|
||||
@@ -1050,6 +1084,10 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
}
|
||||
memcpy(&pend->addr, addr, addrlen);
|
||||
pend->addrlen = addrlen;
|
||||
pend->zone = memdup(zone, zonelen);
|
||||
pend->zonelen = zonelen;
|
||||
pend->qtype = (int)qtype;
|
||||
log_assert(pend->zone);
|
||||
pend->callback = callback;
|
||||
pend->cb_arg = callback_arg;
|
||||
pend->timeout = UDP_AUTH_QUERY_TIMEOUT;
|
||||
@@ -1100,6 +1138,7 @@ void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg)
|
||||
else runtime->pending_list = p->next;
|
||||
ldns_buffer_free(p->buffer);
|
||||
ldns_pkt_free(p->pkt);
|
||||
free(p->zone);
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
@@ -1248,6 +1287,12 @@ void comm_point_raw_handle_callback(int ATTR_UNUSED(fd),
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void comm_base_handle_slow_accept(int ATTR_UNUSED(fd),
|
||||
short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
int serviced_udp_callback(struct comm_point* ATTR_UNUSED(c),
|
||||
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
|
||||
struct comm_reply* ATTR_UNUSED(reply_info))
|
||||
@@ -1330,6 +1375,15 @@ void comm_timer_delete(struct comm_timer* timer)
|
||||
free(timer);
|
||||
}
|
||||
|
||||
void comm_base_set_slow_accept_handlers(struct comm_base* ATTR_UNUSED(b),
|
||||
void (*stop_acc)(void*), void (*start_acc)(void*),
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
/* ignore this */
|
||||
(void)stop_acc;
|
||||
(void)start_acc;
|
||||
}
|
||||
|
||||
struct event_base* comm_base_internal(struct comm_base* ATTR_UNUSED(b))
|
||||
{
|
||||
/* no pipe comm possible in testbound */
|
||||
@@ -1340,4 +1394,20 @@ void daemon_remote_exec(struct worker* ATTR_UNUSED(worker))
|
||||
{
|
||||
}
|
||||
|
||||
void listen_start_accept(struct listen_dnsport* ATTR_UNUSED(listen))
|
||||
{
|
||||
}
|
||||
|
||||
void listen_stop_accept(struct listen_dnsport* ATTR_UNUSED(listen))
|
||||
{
|
||||
}
|
||||
|
||||
void daemon_remote_start_accept(struct daemon_remote* ATTR_UNUSED(rc))
|
||||
{
|
||||
}
|
||||
|
||||
void daemon_remote_stop_accept(struct daemon_remote* ATTR_UNUSED(rc))
|
||||
{
|
||||
}
|
||||
|
||||
/*********** End of Dummy routines ***********/
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
#include "ldns/ldns.h"
|
||||
#include <ldns/ldns.h>
|
||||
#include <signal.h>
|
||||
#include "libunbound/unbound.h"
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
|
||||
@@ -231,7 +231,7 @@ static void adjustline(char* line, struct entry* e,
|
||||
static struct entry* new_entry()
|
||||
{
|
||||
struct entry* e = LDNS_MALLOC(struct entry);
|
||||
memset(e, 0, sizeof(e));
|
||||
memset(e, 0, sizeof(*e));
|
||||
e->match_opcode = false;
|
||||
e->match_qtype = false;
|
||||
e->match_qname = false;
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
#include "ldns/ldns.h"
|
||||
#include <ldns/ldns.h>
|
||||
#include <signal.h>
|
||||
#include "util/log.h"
|
||||
#include "util/locks.h"
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "ldns/ldns.h"
|
||||
#include <ldns/ldns.h>
|
||||
#include "util/log.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/data/msgparse.h"
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@
|
||||
|
||||
#ifndef TESTCODE_READHEX_H
|
||||
#define TESTCODE_READHEX_H
|
||||
#include "ldns/buffer.h"
|
||||
#include <ldns/buffer.h>
|
||||
|
||||
/**
|
||||
* Helper to convert hex string to packet buffer.
|
||||
|
||||
+13
-5
@@ -331,23 +331,31 @@ replay_moment_read(char* remain, FILE* in, const char* name, int* lineno,
|
||||
mom->evt_type = repevt_assign;
|
||||
read_assign_step(remain, mom);
|
||||
} else if(parse_keyword(&remain, "INFRA_RTT")) {
|
||||
char *s;
|
||||
char *s, *m;
|
||||
mom->evt_type = repevt_infra_rtt;
|
||||
while(isspace((int)*remain))
|
||||
remain++;
|
||||
s = remain;
|
||||
remain = strchr(s, ' ');
|
||||
if(!remain) fatal_exit("expected two args for INFRA_RTT");
|
||||
if(!remain) fatal_exit("expected three args for INFRA_RTT");
|
||||
remain[0] = 0;
|
||||
remain++;
|
||||
while(isspace((int)*remain))
|
||||
remain++;
|
||||
m = strchr(remain, ' ');
|
||||
if(!m) fatal_exit("expected three args for INFRA_RTT");
|
||||
m[0] = 0;
|
||||
m++;
|
||||
while(isspace((int)*m))
|
||||
m++;
|
||||
if(!extstrtoaddr(s, &mom->addr, &mom->addrlen))
|
||||
fatal_exit("bad infra_rtt address %s", s);
|
||||
if(strlen(remain)>0 && remain[strlen(remain)-1]=='\n')
|
||||
remain[strlen(remain)-1] = 0;
|
||||
mom->string = strdup(remain);
|
||||
if(strlen(m)>0 && m[strlen(m)-1]=='\n')
|
||||
m[strlen(m)-1] = 0;
|
||||
mom->variable = strdup(remain);
|
||||
mom->string = strdup(m);
|
||||
if(!mom->string) fatal_exit("out of memory");
|
||||
if(!mom->variable) fatal_exit("out of memory");
|
||||
} else {
|
||||
log_err("%d: unknown event type %s", *lineno, remain);
|
||||
free(mom);
|
||||
|
||||
+7
-1
@@ -75,7 +75,7 @@
|
||||
* the step waits for traffic to stop.
|
||||
* o CHECK_AUTOTRUST [id] - followed by FILE_BEGIN [to match] FILE_END.
|
||||
* The file contents is macro expanded before match.
|
||||
* o INFRA_RTT [ip] [rtt] - update infra cache entry with rtt.
|
||||
* o INFRA_RTT [ip] [dp] [rtt] - update infra cache entry with rtt.
|
||||
* o ERROR
|
||||
* ; following entry starts on the next line, ENTRY_BEGIN.
|
||||
* ; more STEP items
|
||||
@@ -323,6 +323,12 @@ struct fake_pending {
|
||||
struct sockaddr_storage addr;
|
||||
/** len of addr */
|
||||
socklen_t addrlen;
|
||||
/** zone name, uncompressed wire format (as used when sent) */
|
||||
uint8_t* zone;
|
||||
/** length of zone name */
|
||||
size_t zonelen;
|
||||
/** qtype */
|
||||
int qtype;
|
||||
/** The callback function to call when answer arrives (or timeout) */
|
||||
comm_point_callback_t* callback;
|
||||
/** callback user argument */
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@
|
||||
* construct input to test the validator with.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ldns/ldns.h"
|
||||
#include <ldns/ldns.h>
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
|
||||
+125
-33
@@ -43,14 +43,16 @@
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
#include "ldns/ldns.h"
|
||||
#include <ldns/ldns.h>
|
||||
#include <signal.h>
|
||||
#include "util/locks.h"
|
||||
#include "util/log.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/data/msgencode.h"
|
||||
#include "util/data/msgparse.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/data/dname.h"
|
||||
#include <openssl/err.h>
|
||||
|
||||
#ifndef PF_INET6
|
||||
/** define in case streamtcp is compiled on legacy systems */
|
||||
@@ -65,6 +67,7 @@ static void usage(char* argv[])
|
||||
printf("-f server what ipaddr@portnr to send the queries to\n");
|
||||
printf("-u use UDP. No retries are attempted.\n");
|
||||
printf("-n do not wait for an answer.\n");
|
||||
printf("-s use ssl\n");
|
||||
printf("-h this help text\n");
|
||||
exit(1);
|
||||
}
|
||||
@@ -105,7 +108,7 @@ open_svr(const char* svr, int udp)
|
||||
|
||||
/** write a query over the TCP fd */
|
||||
static void
|
||||
write_q(int fd, int udp, ldns_buffer* buf, int id,
|
||||
write_q(int fd, int udp, SSL* ssl, ldns_buffer* buf, uint16_t id,
|
||||
const char* strname, const char* strtype, const char* strclass)
|
||||
{
|
||||
struct query_info qinfo;
|
||||
@@ -128,65 +131,111 @@ write_q(int fd, int udp, ldns_buffer* buf, int id,
|
||||
|
||||
/* make query */
|
||||
qinfo_query_encode(buf, &qinfo);
|
||||
ldns_buffer_write_u16_at(buf, 0, (uint16_t)id);
|
||||
ldns_buffer_write_u16_at(buf, 0, id);
|
||||
ldns_buffer_write_u16_at(buf, 2, BIT_RD);
|
||||
|
||||
if(1) {
|
||||
/* add EDNS DO */
|
||||
struct edns_data edns;
|
||||
memset(&edns, 0, sizeof(edns));
|
||||
edns.edns_present = 1;
|
||||
edns.bits = EDNS_DO;
|
||||
edns.udp_size = 4096;
|
||||
attach_edns_record(buf, &edns);
|
||||
}
|
||||
|
||||
/* send it */
|
||||
if(!udp) {
|
||||
len = (uint16_t)ldns_buffer_limit(buf);
|
||||
len = htons(len);
|
||||
if(send(fd, (void*)&len, sizeof(len), 0)<(ssize_t)sizeof(len)){
|
||||
if(ssl) {
|
||||
if(SSL_write(ssl, (void*)&len, (int)sizeof(len)) <= 0) {
|
||||
log_crypto_err("cannot SSL_write");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
if(send(fd, (void*)&len, sizeof(len), 0) <
|
||||
(ssize_t)sizeof(len)){
|
||||
#ifndef USE_WINSOCK
|
||||
perror("send() len failed");
|
||||
perror("send() len failed");
|
||||
#else
|
||||
printf("send len: %s\n",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
printf("send len: %s\n",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ssl) {
|
||||
if(SSL_write(ssl, (void*)ldns_buffer_begin(buf),
|
||||
(int)ldns_buffer_limit(buf)) <= 0) {
|
||||
log_crypto_err("cannot SSL_write");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
if(send(fd, (void*)ldns_buffer_begin(buf),
|
||||
ldns_buffer_limit(buf), 0) <
|
||||
(ssize_t)ldns_buffer_limit(buf)) {
|
||||
#ifndef USE_WINSOCK
|
||||
perror("send() data failed");
|
||||
#else
|
||||
printf("send data: %s\n", wsa_strerror(WSAGetLastError()));
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if(send(fd, (void*)ldns_buffer_begin(buf), ldns_buffer_limit(buf), 0) <
|
||||
(ssize_t)ldns_buffer_limit(buf)) {
|
||||
#ifndef USE_WINSOCK
|
||||
perror("send() data failed");
|
||||
#else
|
||||
printf("send data: %s\n", wsa_strerror(WSAGetLastError()));
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
free(qinfo.qname);
|
||||
}
|
||||
|
||||
/** receive DNS datagram over TCP and print it */
|
||||
static void
|
||||
recv_one(int fd, int udp, ldns_buffer* buf)
|
||||
recv_one(int fd, int udp, SSL* ssl, ldns_buffer* buf)
|
||||
{
|
||||
uint16_t len;
|
||||
ldns_pkt* pkt;
|
||||
ldns_status status;
|
||||
if(!udp) {
|
||||
if(recv(fd, (void*)&len, sizeof(len), 0)<(ssize_t)sizeof(len)){
|
||||
if(ssl) {
|
||||
if(SSL_read(ssl, (void*)&len, (int)sizeof(len)) <= 0) {
|
||||
log_crypto_err("could not SSL_read");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
if(recv(fd, (void*)&len, sizeof(len), 0) <
|
||||
(ssize_t)sizeof(len)) {
|
||||
#ifndef USE_WINSOCK
|
||||
perror("read() len failed");
|
||||
perror("read() len failed");
|
||||
#else
|
||||
printf("read len: %s\n",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
printf("read len: %s\n",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
#endif
|
||||
exit(1);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
len = ntohs(len);
|
||||
ldns_buffer_clear(buf);
|
||||
ldns_buffer_set_limit(buf, len);
|
||||
if(recv(fd, (void*)ldns_buffer_begin(buf), len, 0) <
|
||||
(ssize_t)len) {
|
||||
if(ssl) {
|
||||
int r = SSL_read(ssl, (void*)ldns_buffer_begin(buf),
|
||||
(int)len);
|
||||
if(r <= 0) {
|
||||
log_crypto_err("could not SSL_read");
|
||||
exit(1);
|
||||
}
|
||||
if(r != (int)len)
|
||||
fatal_exit("ssl_read %d of %d", r, len);
|
||||
} else {
|
||||
if(recv(fd, (void*)ldns_buffer_begin(buf), len, 0) <
|
||||
(ssize_t)len) {
|
||||
#ifndef USE_WINSOCK
|
||||
perror("read() data failed");
|
||||
perror("read() data failed");
|
||||
#else
|
||||
printf("read data: %s\n",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
printf("read data: %s\n",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
#endif
|
||||
exit(1);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ssize_t l;
|
||||
@@ -220,20 +269,54 @@ recv_one(int fd, int udp, ldns_buffer* buf)
|
||||
|
||||
/** send the TCP queries and print answers */
|
||||
static void
|
||||
send_em(const char* svr, int udp, int noanswer, int num, char** qs)
|
||||
send_em(const char* svr, int udp, int usessl, int noanswer, int num, char** qs)
|
||||
{
|
||||
ldns_buffer* buf = ldns_buffer_new(65553);
|
||||
int fd = open_svr(svr, udp);
|
||||
int i;
|
||||
SSL_CTX* ctx = NULL;
|
||||
SSL* ssl = NULL;
|
||||
if(!buf) fatal_exit("out of memory");
|
||||
if(usessl) {
|
||||
ctx = connect_sslctx_create(NULL, NULL, NULL);
|
||||
if(!ctx) fatal_exit("cannot create ssl ctx");
|
||||
ssl = outgoing_ssl_fd(ctx, fd);
|
||||
if(!ssl) fatal_exit("cannot create ssl");
|
||||
while(1) {
|
||||
int r;
|
||||
ERR_clear_error();
|
||||
if( (r=SSL_do_handshake(ssl)) == 1)
|
||||
break;
|
||||
r = SSL_get_error(ssl, r);
|
||||
if(r != SSL_ERROR_WANT_READ &&
|
||||
r != SSL_ERROR_WANT_WRITE) {
|
||||
log_crypto_err("could not ssl_handshake");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if(1) {
|
||||
X509* x = SSL_get_peer_certificate(ssl);
|
||||
if(!x) printf("SSL: no peer certificate\n");
|
||||
else {
|
||||
X509_print_fp(stdout, x);
|
||||
X509_free(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(i=0; i<num; i+=3) {
|
||||
printf("\nNext query is %s %s %s\n", qs[i], qs[i+1], qs[i+2]);
|
||||
write_q(fd, udp, buf, i, qs[i], qs[i+1], qs[i+2]);
|
||||
write_q(fd, udp, ssl, buf, ldns_get_random(), qs[i],
|
||||
qs[i+1], qs[i+2]);
|
||||
/* print at least one result */
|
||||
if(!noanswer)
|
||||
recv_one(fd, udp, buf);
|
||||
recv_one(fd, udp, ssl, buf);
|
||||
}
|
||||
|
||||
if(usessl) {
|
||||
SSL_shutdown(ssl);
|
||||
SSL_free(ssl);
|
||||
SSL_CTX_free(ctx);
|
||||
}
|
||||
#ifndef USE_WINSOCK
|
||||
close(fd);
|
||||
#else
|
||||
@@ -268,6 +351,7 @@ int main(int argc, char** argv)
|
||||
const char* svr = "127.0.0.1";
|
||||
int udp = 0;
|
||||
int noanswer = 0;
|
||||
int usessl = 0;
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
WSADATA wsa_data;
|
||||
@@ -292,7 +376,7 @@ int main(int argc, char** argv)
|
||||
if(argc == 1) {
|
||||
usage(argv);
|
||||
}
|
||||
while( (c=getopt(argc, argv, "f:hnu")) != -1) {
|
||||
while( (c=getopt(argc, argv, "f:hnsu")) != -1) {
|
||||
switch(c) {
|
||||
case 'f':
|
||||
svr = optarg;
|
||||
@@ -303,6 +387,9 @@ int main(int argc, char** argv)
|
||||
case 'u':
|
||||
udp = 1;
|
||||
break;
|
||||
case 's':
|
||||
usessl = 1;
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
@@ -316,7 +403,12 @@ int main(int argc, char** argv)
|
||||
printf("queries must be multiples of name,type,class\n");
|
||||
return 1;
|
||||
}
|
||||
send_em(svr, udp, noanswer, argc, argv);
|
||||
if(usessl) {
|
||||
ERR_load_SSL_strings();
|
||||
OpenSSL_add_all_algorithms();
|
||||
SSL_library_init();
|
||||
}
|
||||
send_em(svr, udp, usessl, noanswer, argc, argv);
|
||||
checklock_stop();
|
||||
#ifdef USE_WINSOCK
|
||||
WSACleanup();
|
||||
|
||||
+12
-2
@@ -70,6 +70,7 @@ testbound_usage()
|
||||
printf("-p file playback text file\n");
|
||||
printf("-2 detect SHA256 support (exit code 0 or 1)\n");
|
||||
printf("-g detect GOST support (exit code 0 or 1)\n");
|
||||
printf("-e detect ECDSA support (exit code 0 or 1)\n");
|
||||
printf("-s testbound self-test - unit test of testbound parts.\n");
|
||||
printf("-o str unbound commandline options separated by spaces.\n");
|
||||
printf("Version %s\n", PACKAGE_VERSION);
|
||||
@@ -272,7 +273,7 @@ main(int argc, char* argv[])
|
||||
pass_argc = 1;
|
||||
pass_argv[0] = "unbound";
|
||||
add_opts("-d", &pass_argc, pass_argv);
|
||||
while( (c=getopt(argc, argv, "2gho:p:s")) != -1) {
|
||||
while( (c=getopt(argc, argv, "2egho:p:s")) != -1) {
|
||||
switch(c) {
|
||||
case 's':
|
||||
free(pass_argv[1]);
|
||||
@@ -280,12 +281,21 @@ main(int argc, char* argv[])
|
||||
printf("selftest successful\n");
|
||||
exit(0);
|
||||
case '2':
|
||||
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
|
||||
#if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS)) && defined(USE_SHA2)
|
||||
printf("SHA256 supported\n");
|
||||
exit(0);
|
||||
#else
|
||||
printf("SHA256 not supported\n");
|
||||
exit(1);
|
||||
#endif
|
||||
break;
|
||||
case 'e':
|
||||
#if defined(USE_ECDSA)
|
||||
printf("ECDSA supported\n");
|
||||
exit(0);
|
||||
#else
|
||||
printf("ECDSA not supported\n");
|
||||
exit(1);
|
||||
#endif
|
||||
break;
|
||||
case 'g':
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "ldns/rr.h"
|
||||
#include <ldns/rr.h>
|
||||
#include "util/log.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "testcode/unitmain.h"
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "ldns/dname.h"
|
||||
#include "ldns/host2wire.h"
|
||||
#include <ldns/dname.h>
|
||||
#include <ldns/host2wire.h>
|
||||
#include "util/log.h"
|
||||
#include "testcode/unitmain.h"
|
||||
#include "util/data/dname.h"
|
||||
|
||||
+65
-38
@@ -55,7 +55,12 @@
|
||||
#ifdef HAVE_OPENSSL_ENGINE_H
|
||||
#include <openssl/engine.h>
|
||||
#endif
|
||||
#include "ldns/ldns.h"
|
||||
|
||||
#ifdef HAVE_NSS
|
||||
#include "nss3/nss.h"
|
||||
#endif
|
||||
|
||||
#include <ldns/ldns.h>
|
||||
#include "util/log.h"
|
||||
#include "testcode/unitmain.h"
|
||||
|
||||
@@ -401,6 +406,25 @@ rtt_test(void)
|
||||
|
||||
#include "services/cache/infra.h"
|
||||
#include "util/config_file.h"
|
||||
|
||||
/* lookup and get key and data structs easily */
|
||||
static struct infra_data* infra_lookup_host(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, int wr, uint32_t now, struct infra_key** k)
|
||||
{
|
||||
struct infra_data* d;
|
||||
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
|
||||
zone, zonelen, wr);
|
||||
if(!e) return NULL;
|
||||
d = (struct infra_data*)e->data;
|
||||
if(d->ttl < now) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
return NULL;
|
||||
}
|
||||
*k = (struct infra_key*)e->key;
|
||||
return d;
|
||||
}
|
||||
|
||||
/** test host cache */
|
||||
static void
|
||||
infra_test(void)
|
||||
@@ -414,70 +438,63 @@ infra_test(void)
|
||||
uint32_t now = 0;
|
||||
uint8_t edns_lame;
|
||||
int vs, to;
|
||||
struct infra_host_key* k;
|
||||
struct infra_host_data* d;
|
||||
struct infra_key* k;
|
||||
struct infra_data* d;
|
||||
int init = 376;
|
||||
int dlame, rlame, alame, olame;
|
||||
|
||||
unit_show_feature("infra cache");
|
||||
unit_assert(ipstrtoaddr("127.0.0.1", 53, &one, &onelen));
|
||||
|
||||
slab = infra_create(cfg);
|
||||
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
|
||||
(socklen_t)sizeof(int), now, &vs, &edns_lame, &to) );
|
||||
unit_assert( infra_host(slab, &one, onelen, zone, zonelen, now,
|
||||
&vs, &edns_lame, &to) );
|
||||
unit_assert( vs == 0 && to == init && edns_lame == 0 );
|
||||
|
||||
unit_assert( infra_rtt_update(slab, &one, onelen, -1, init, now) );
|
||||
unit_assert( infra_host(slab, &one, onelen,
|
||||
unit_assert( infra_rtt_update(slab, &one, onelen, zone, zonelen, LDNS_RR_TYPE_A, -1, init, now) );
|
||||
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
|
||||
now, &vs, &edns_lame, &to) );
|
||||
unit_assert( vs == 0 && to == init*2 && edns_lame == 0 );
|
||||
|
||||
unit_assert( infra_edns_update(slab, &one, onelen, -1, now) );
|
||||
unit_assert( infra_host(slab, &one, onelen,
|
||||
unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, -1, now) );
|
||||
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
|
||||
now, &vs, &edns_lame, &to) );
|
||||
unit_assert( vs == -1 && to == init*2 && edns_lame == 1);
|
||||
|
||||
now += cfg->host_ttl + 10;
|
||||
unit_assert( infra_host(slab, &one, onelen,
|
||||
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
|
||||
now, &vs, &edns_lame, &to) );
|
||||
unit_assert( vs == 0 && to == init && edns_lame == 0 );
|
||||
|
||||
unit_assert( infra_set_lame(slab, &one, onelen,
|
||||
unit_assert( infra_set_lame(slab, &one, onelen,
|
||||
zone, zonelen, now, 0, 0, LDNS_RR_TYPE_A) );
|
||||
unit_assert( (d=infra_lookup_host(slab, &one, onelen, 0, now, &k)) );
|
||||
unit_assert( (d=infra_lookup_host(slab, &one, onelen, zone, zonelen, 0, now, &k)) );
|
||||
unit_assert( d->ttl == now+cfg->host_ttl );
|
||||
unit_assert( d->edns_version == 0 );
|
||||
unit_assert( infra_lookup_lame(d, zone, zonelen, now,
|
||||
&dlame, &rlame, &alame, &olame) );
|
||||
unit_assert(!dlame && !rlame && alame && !olame);
|
||||
unit_assert( !infra_lookup_lame(d, zone, zonelen,
|
||||
now+cfg->lame_ttl+10, &dlame, &rlame, &alame, &olame) );
|
||||
unit_assert( !infra_lookup_lame(d, (uint8_t*)"\000", 1, now,
|
||||
&dlame, &rlame, &alame, &olame) );
|
||||
unit_assert(!d->isdnsseclame && !d->rec_lame && d->lame_type_A &&
|
||||
!d->lame_other);
|
||||
lock_rw_unlock(&k->entry.lock);
|
||||
|
||||
/* test merge of data */
|
||||
unit_assert( infra_set_lame(slab, &one, onelen,
|
||||
unit_assert( infra_set_lame(slab, &one, onelen,
|
||||
zone, zonelen, now, 0, 0, LDNS_RR_TYPE_AAAA) );
|
||||
unit_assert( (d=infra_lookup_host(slab, &one, onelen, 0, now, &k)) );
|
||||
unit_assert( infra_lookup_lame(d, zone, zonelen, now,
|
||||
&dlame, &rlame, &alame, &olame) );
|
||||
unit_assert(!dlame && !rlame && alame && olame);
|
||||
unit_assert( (d=infra_lookup_host(slab, &one, onelen, zone, zonelen, 0, now, &k)) );
|
||||
unit_assert(!d->isdnsseclame && !d->rec_lame && d->lame_type_A &&
|
||||
d->lame_other);
|
||||
lock_rw_unlock(&k->entry.lock);
|
||||
|
||||
/* test that noEDNS cannot overwrite known-yesEDNS */
|
||||
now += cfg->host_ttl + 10;
|
||||
unit_assert( infra_host(slab, &one, onelen,
|
||||
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
|
||||
now, &vs, &edns_lame, &to) );
|
||||
unit_assert( vs == 0 && to == init && edns_lame == 0 );
|
||||
|
||||
unit_assert( infra_edns_update(slab, &one, onelen, 0, now) );
|
||||
unit_assert( infra_host(slab, &one, onelen,
|
||||
unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, 0, now) );
|
||||
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
|
||||
now, &vs, &edns_lame, &to) );
|
||||
unit_assert( vs == 0 && to == init && edns_lame == 1 );
|
||||
|
||||
unit_assert( infra_edns_update(slab, &one, onelen, -1, now) );
|
||||
unit_assert( infra_host(slab, &one, onelen,
|
||||
unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, -1, now) );
|
||||
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
|
||||
now, &vs, &edns_lame, &to) );
|
||||
unit_assert( vs == 0 && to == init && edns_lame == 1 );
|
||||
|
||||
@@ -543,13 +560,18 @@ main(int argc, char* argv[])
|
||||
return 1;
|
||||
}
|
||||
printf("Start of %s unit test.\n", PACKAGE_STRING);
|
||||
#ifdef HAVE_SSL
|
||||
ERR_load_crypto_strings();
|
||||
#ifdef HAVE_OPENSSL_CONFIG
|
||||
# ifdef HAVE_OPENSSL_CONFIG
|
||||
OPENSSL_config("unbound");
|
||||
#endif
|
||||
#ifdef USE_GOST
|
||||
# endif
|
||||
# ifdef USE_GOST
|
||||
(void)ldns_key_EVP_load_gost_id();
|
||||
#endif
|
||||
# endif
|
||||
#elif defined(HAVE_NSS)
|
||||
if(NSS_NoDB_Init(".") != SECSuccess)
|
||||
fatal_exit("could not init NSS");
|
||||
#endif /* HAVE_SSL or HAVE_NSS*/
|
||||
checklock_start();
|
||||
neg_test();
|
||||
rnd_test();
|
||||
@@ -567,18 +589,23 @@ main(int argc, char* argv[])
|
||||
msgparse_test();
|
||||
checklock_stop();
|
||||
printf("%d checks ok.\n", testcount);
|
||||
#if defined(USE_GOST) && defined(HAVE_LDNS_KEY_EVP_UNLOAD_GOST)
|
||||
#ifdef HAVE_SSL
|
||||
# if defined(USE_GOST) && defined(HAVE_LDNS_KEY_EVP_UNLOAD_GOST)
|
||||
ldns_key_EVP_unload_gost();
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_CONFIG
|
||||
# endif
|
||||
# ifdef HAVE_OPENSSL_CONFIG
|
||||
EVP_cleanup();
|
||||
ENGINE_cleanup();
|
||||
CONF_modules_free();
|
||||
#endif
|
||||
# endif
|
||||
CRYPTO_cleanup_all_ex_data();
|
||||
ERR_remove_state(0);
|
||||
ERR_free_strings();
|
||||
RAND_cleanup();
|
||||
#elif defined(HAVE_NSS)
|
||||
if(NSS_Shutdown() != SECSuccess)
|
||||
fatal_exit("could not shutdown NSS");
|
||||
#endif /* HAVE_SSL or HAVE_NSS */
|
||||
#ifdef HAVE_PTHREAD
|
||||
/* dlopen frees its thread specific state */
|
||||
pthread_exit(NULL);
|
||||
|
||||
+11
-2
@@ -39,7 +39,7 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "ldns/ldns.h"
|
||||
#include <ldns/ldns.h>
|
||||
#include "util/log.h"
|
||||
#include "testcode/unitmain.h"
|
||||
#include "util/data/msgparse.h"
|
||||
@@ -59,6 +59,8 @@ static int check_formerr_gone = 0;
|
||||
static int matches_nolocation = 0;
|
||||
/** see if RRSIGs are properly matched to RRsets. */
|
||||
static int check_rrsigs = 0;
|
||||
/** do not check buffer sameness */
|
||||
static int check_nosameness = 0;
|
||||
|
||||
/** match two rr lists */
|
||||
static int
|
||||
@@ -431,7 +433,8 @@ testpkt(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out,
|
||||
if(vbmp) printf("inlen %u outlen %u\n",
|
||||
(unsigned)ldns_buffer_limit(pkt),
|
||||
(unsigned)ldns_buffer_limit(out));
|
||||
test_buffers(pkt, out);
|
||||
if(!check_nosameness)
|
||||
test_buffers(pkt, out);
|
||||
if(check_rrsigs)
|
||||
check_the_rrsigs(&qi, rep);
|
||||
|
||||
@@ -607,6 +610,12 @@ void msgparse_test(void)
|
||||
testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.8");
|
||||
check_formerr_gone = 0;
|
||||
|
||||
check_rrsigs = 1;
|
||||
check_nosameness = 1;
|
||||
testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.9");
|
||||
check_nosameness = 0;
|
||||
check_rrsigs = 0;
|
||||
|
||||
/* cleanup */
|
||||
alloc_clear(&alloc);
|
||||
alloc_clear(&super_a);
|
||||
|
||||
+11
-2
@@ -42,6 +42,7 @@
|
||||
#include "util/log.h"
|
||||
#include "testcode/unitmain.h"
|
||||
#include "validator/val_sigcrypt.h"
|
||||
#include "validator/val_secalgo.h"
|
||||
#include "validator/val_nsec.h"
|
||||
#include "validator/val_nsec3.h"
|
||||
#include "validator/validator.h"
|
||||
@@ -505,12 +506,12 @@ verify_test(void)
|
||||
verifytest_file("testdata/test_signatures.6", "20080416005004");
|
||||
verifytest_file("testdata/test_signatures.7", "20070829144150");
|
||||
verifytest_file("testdata/test_signatures.8", "20070829144150");
|
||||
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
|
||||
#if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS)) && defined(USE_SHA2)
|
||||
verifytest_file("testdata/test_sigs.rsasha256", "20070829144150");
|
||||
verifytest_file("testdata/test_sigs.sha1_and_256", "20070829144150");
|
||||
verifytest_file("testdata/test_sigs.rsasha256_draft", "20090101000000");
|
||||
#endif
|
||||
#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
|
||||
#if (defined(HAVE_EVP_SHA512) || defined(HAVE_NSS)) && defined(USE_SHA2)
|
||||
verifytest_file("testdata/test_sigs.rsasha512_draft", "20070829144150");
|
||||
#endif
|
||||
verifytest_file("testdata/test_sigs.hinfo", "20090107100022");
|
||||
@@ -519,6 +520,14 @@ verify_test(void)
|
||||
if(ldns_key_EVP_load_gost_id())
|
||||
verifytest_file("testdata/test_sigs.gost", "20090807060504");
|
||||
else printf("Warning: skipped GOST, openssl does not provide gost.\n");
|
||||
#endif
|
||||
#ifdef USE_ECDSA
|
||||
/* test for support in case we use libNSS and ECC is removed */
|
||||
if(dnskey_algo_id_is_supported(LDNS_ECDSAP256SHA256)) {
|
||||
verifytest_file("testdata/test_sigs.ecdsa_p256", "20100908100439");
|
||||
verifytest_file("testdata/test_sigs.ecdsa_p384", "20100908100439");
|
||||
}
|
||||
dstest_file("testdata/test_ds.sha384");
|
||||
#endif
|
||||
dstest_file("testdata/test_ds.sha1");
|
||||
nsectest();
|
||||
|
||||
Vendored
BIN
Binary file not shown.
Vendored
+2
-2
@@ -239,9 +239,9 @@ nx1.example.com. IN A
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
example.com. 3600 IN SOA a. b. 1 2 3 4 5
|
||||
example.com. 3600 IN NS ns.example.com.
|
||||
example.com. 1800 IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. 3600 IN A 1.2.3.4
|
||||
ns.example.com. 1800 IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
|
||||
; after another 1900 seconds the domain must have timed out.
|
||||
|
||||
Vendored
+145
@@ -0,0 +1,145 @@
|
||||
; config options
|
||||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test locate of NS records for parent nameservers of DS
|
||||
|
||||
; K.ROOT-SERVERS.NET.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 193.0.14.129
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
. IN NS
|
||||
SECTION ANSWER
|
||||
. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
|
||||
; content of root-servers.net
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
root-servers.net. IN NS
|
||||
SECTION ANSWER
|
||||
root-servers.net. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
k.root-servers.net. IN A
|
||||
SECTION ANSWER
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
SECTION AUTHORITY
|
||||
root-servers.net. IN NS K.ROOT-SERVERS.NET.
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
k.root-servers.net. IN AAAA
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
root-servers.net. IN DS
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
net. IN A
|
||||
SECTION AUTHORITY
|
||||
net. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; a.gtld-servers.net.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 192.5.6.30
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
net. IN NS
|
||||
SECTION ANSWER
|
||||
net. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
root-servers.net. IN DS
|
||||
SECTION AUTHORITY
|
||||
net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
root-servers.net. IN A
|
||||
SECTION AUTHORITY
|
||||
root-servers.net. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
STEP 1 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
root-servers.net. IN DS
|
||||
ENTRY_END
|
||||
|
||||
; recursion happens here.
|
||||
STEP 10 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
root-servers.net. IN DS
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
Vendored
+155
@@ -0,0 +1,155 @@
|
||||
; config options
|
||||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test locate of NS records for DS with CNAME
|
||||
|
||||
; K.ROOT-SERVERS.NET.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 193.0.14.129
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
. IN NS
|
||||
SECTION ANSWER
|
||||
. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
|
||||
; content of root-servers.net
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
root-servers.net. IN NS
|
||||
SECTION ANSWER
|
||||
root-servers.net. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
k.root-servers.net. IN A
|
||||
SECTION ANSWER
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
SECTION AUTHORITY
|
||||
root-servers.net. IN NS K.ROOT-SERVERS.NET.
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
k.root-servers.net. IN AAAA
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
root-servers.net. IN DS
|
||||
SECTION ANSWER
|
||||
root-servers.net. IN CNAME blabla.com.
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
net. IN A
|
||||
SECTION AUTHORITY
|
||||
net. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NXDOMAIN
|
||||
SECTION QUESTION
|
||||
blabla.com. IN DS
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; a.gtld-servers.net.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 192.5.6.30
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
net. IN NS
|
||||
SECTION ANSWER
|
||||
net. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
root-servers.net. IN DS
|
||||
SECTION AUTHORITY
|
||||
net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
root-servers.net. IN A
|
||||
SECTION AUTHORITY
|
||||
root-servers.net. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
STEP 1 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
root-servers.net. IN DS
|
||||
ENTRY_END
|
||||
|
||||
; recursion happens here.
|
||||
STEP 10 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
root-servers.net. IN DS
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
+296
@@ -0,0 +1,296 @@
|
||||
; config options
|
||||
server:
|
||||
target-fetch-policy: "3 2 1 0 0"
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test locate of NS records for DS and with detached queries
|
||||
; the additional targets looked up cause detached queries.
|
||||
; hence the target fetch policy is increased above.
|
||||
|
||||
; K.ROOT-SERVERS.NET.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 193.0.14.129
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
. IN NS
|
||||
SECTION ANSWER
|
||||
. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
k.root-servers.net. IN A
|
||||
SECTION ANSWER
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
SECTION AUTHORITY
|
||||
root-servers.net. IN NS K.ROOT-SERVERS.NET.
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
k.root-servers.net. IN AAAA
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
net. IN DS
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
net. IN A
|
||||
SECTION AUTHORITY
|
||||
net. IN NS a.server.net.
|
||||
net. IN NS b.server.net.
|
||||
net. IN NS c.server.net.
|
||||
SECTION ADDITIONAL
|
||||
a.server.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; a.server.net.
|
||||
; The b.server.net and c.server.net servers are here to cause
|
||||
; extra lookups to be generated (to create detached queries in the
|
||||
; iterator), there is no IP address that answers for them set up.
|
||||
; force DSNSFind, we host a grandchild zone.
|
||||
; also, this range of steps is without responses for b and c, so that
|
||||
; they can be force to happen later (after the DSNS is activated).
|
||||
RANGE_BEGIN 0 20
|
||||
ADDRESS 192.5.6.30
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
net. IN NS
|
||||
SECTION ANSWER
|
||||
net. IN NS a.server.net.
|
||||
net. IN NS b.server.net.
|
||||
net. IN NS c.server.net.
|
||||
SECTION ADDITIONAL
|
||||
a.server.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
a.server.net. IN A
|
||||
SECTION ANSWER
|
||||
a.server.net. IN A 192.5.6.30
|
||||
SECTION AUTHORITY
|
||||
net. IN NS a.server.net.
|
||||
net. IN NS b.server.net.
|
||||
net. IN NS c.server.net.
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
a.sub.example.net. IN DS
|
||||
SECTION AUTHORITY
|
||||
sub.example.net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
sub.example.net. IN NS
|
||||
SECTION ANSWER
|
||||
sub.example.net. IN NS a.server.net.
|
||||
sub.example.net. IN NS b.server.net.
|
||||
sub.example.net. IN NS c.server.net.
|
||||
SECTION ADDITIONAL
|
||||
a.server.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
a.sub.example.net. IN A
|
||||
SECTION AUTHORITY
|
||||
sub.example.net. IN NS a.server.net.
|
||||
SECTION ADDITIONAL
|
||||
a.server.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; a.server.net range with all the answers (to finish the test).
|
||||
RANGE_BEGIN 30 100
|
||||
ADDRESS 192.5.6.30
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
net. IN NS
|
||||
SECTION ANSWER
|
||||
net. IN NS a.server.net.
|
||||
net. IN NS b.server.net.
|
||||
net. IN NS c.server.net.
|
||||
SECTION ADDITIONAL
|
||||
a.server.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
a.server.net. IN A
|
||||
SECTION ANSWER
|
||||
a.server.net. IN A 192.5.6.30
|
||||
SECTION AUTHORITY
|
||||
net. IN NS a.server.net.
|
||||
net. IN NS b.server.net.
|
||||
net. IN NS c.server.net.
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
a.server.net. IN AAAA
|
||||
SECTION AUTHORITY
|
||||
net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
b.server.net. IN A
|
||||
SECTION AUTHORITY
|
||||
net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
b.server.net. IN AAAA
|
||||
SECTION AUTHORITY
|
||||
net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
c.server.net. IN A
|
||||
SECTION AUTHORITY
|
||||
net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
c.server.net. IN AAAA
|
||||
SECTION AUTHORITY
|
||||
net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
a.sub.example.net. IN DS
|
||||
SECTION AUTHORITY
|
||||
sub.example.net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
sub.example.net. IN NS
|
||||
SECTION ANSWER
|
||||
sub.example.net. IN NS a.server.net.
|
||||
sub.example.net. IN NS b.server.net.
|
||||
sub.example.net. IN NS c.server.net.
|
||||
SECTION ADDITIONAL
|
||||
a.server.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
a.sub.example.net. IN A
|
||||
SECTION AUTHORITY
|
||||
sub.example.net. IN NS a.server.net.
|
||||
SECTION ADDITIONAL
|
||||
a.server.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
STEP 1 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
a.sub.example.net. IN DS
|
||||
ENTRY_END
|
||||
|
||||
; make traffic flow at this time
|
||||
STEP 15 TRAFFIC
|
||||
|
||||
STEP 20 TRAFFIC
|
||||
|
||||
STEP 40 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
a.sub.example.net. IN DS
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
sub.example.net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
STEP 50 TRAFFIC
|
||||
|
||||
SCENARIO_END
|
||||
Vendored
+145
@@ -0,0 +1,145 @@
|
||||
; config options
|
||||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test locate of NS records for DS without a SOA record
|
||||
|
||||
; K.ROOT-SERVERS.NET.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 193.0.14.129
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
. IN NS
|
||||
SECTION ANSWER
|
||||
. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
|
||||
; content of root-servers.net
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
root-servers.net. IN NS
|
||||
SECTION ANSWER
|
||||
root-servers.net. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
k.root-servers.net. IN A
|
||||
SECTION ANSWER
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
SECTION AUTHORITY
|
||||
root-servers.net. IN NS K.ROOT-SERVERS.NET.
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
k.root-servers.net. IN AAAA
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
root-servers.net. IN DS
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
;root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
net. IN A
|
||||
SECTION AUTHORITY
|
||||
net. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; a.gtld-servers.net.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 192.5.6.30
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
net. IN NS
|
||||
SECTION ANSWER
|
||||
net. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
root-servers.net. IN DS
|
||||
SECTION AUTHORITY
|
||||
net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
root-servers.net. IN A
|
||||
SECTION AUTHORITY
|
||||
root-servers.net. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
STEP 1 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
root-servers.net. IN DS
|
||||
ENTRY_END
|
||||
|
||||
; recursion happens here.
|
||||
STEP 10 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
root-servers.net. IN DS
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
Vendored
+157
@@ -0,0 +1,157 @@
|
||||
; config options
|
||||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
||||
forward-zone:
|
||||
name: "example.com"
|
||||
forward-addr: 1.2.3.6 # failing resolver
|
||||
forward-first: yes
|
||||
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test forward-first directive
|
||||
|
||||
; K.ROOT-SERVERS.NET.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 193.0.14.129
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
. IN NS
|
||||
SECTION ANSWER
|
||||
. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
com. IN A
|
||||
SECTION AUTHORITY
|
||||
com. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; a.gtld-servers.net.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 192.5.6.30
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
com. IN NS
|
||||
SECTION ANSWER
|
||||
com. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN A
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; ns.example.com.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 1.2.3.4
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN NS
|
||||
SECTION ANSWER
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. IN A 10.20.30.40
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; local resolver (that fails a lot)
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 1.2.3.6
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR RA SERVFAIL
|
||||
SECTION QUESTION
|
||||
example.com. IN NS
|
||||
SECTION ANSWER
|
||||
;example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
;ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR RA SERVFAIL
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
;www.example.com. IN A 10.20.30.50
|
||||
SECTION AUTHORITY
|
||||
;example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
;ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
STEP 1 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
; recursion happens here.
|
||||
STEP 10 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. IN A 10.20.30.40
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
Vendored
+1
-1
@@ -238,7 +238,7 @@ RANGE_END
|
||||
; store bad timing for one server to influence server selection
|
||||
; 1.2.3.44 (ns.example.net) gets 900 msec.
|
||||
; so the 376 ns.example.com is preferred.
|
||||
STEP 1 INFRA_RTT 1.2.3.44 900
|
||||
STEP 1 INFRA_RTT 1.2.3.44 example.net. 900
|
||||
|
||||
STEP 10 QUERY
|
||||
ENTRY_BEGIN
|
||||
|
||||
Vendored
+1
@@ -217,6 +217,7 @@ www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. 3600 IN A 10.20.30.40
|
||||
SECTION AUTHORITY
|
||||
; NS rrset picked up from parent-NS (the child-NS timed out at now+prefetch)
|
||||
example.com. 3600 IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. 3600 IN A 1.2.3.4
|
||||
|
||||
Vendored
+364
@@ -0,0 +1,364 @@
|
||||
; config options
|
||||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
prefetch: "yes"
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test resolver prefetch and a moved domain
|
||||
; for bug #425.
|
||||
|
||||
; K.ROOT-SERVERS.NET.
|
||||
RANGE_BEGIN 0 500
|
||||
ADDRESS 193.0.14.129
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
. IN NS
|
||||
SECTION ANSWER
|
||||
. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
com. IN A
|
||||
SECTION AUTHORITY
|
||||
com. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; a.gtld-servers.net. (before sale of domain)
|
||||
RANGE_BEGIN 0 30
|
||||
ADDRESS 192.5.6.30
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
com. IN NS
|
||||
SECTION ANSWER
|
||||
com. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN A
|
||||
SECTION AUTHORITY
|
||||
example.com. 86400 IN NS old-ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
old-ns.example.com. 86400 IN A 192.168.0.1
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; a.gtld-servers.net. (after sale of domain)
|
||||
RANGE_BEGIN 40 500
|
||||
ADDRESS 192.5.6.30
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
com. IN NS
|
||||
SECTION ANSWER
|
||||
com. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN A
|
||||
SECTION AUTHORITY
|
||||
example.com. 86400 IN NS new-ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
new-ns.example.com. 86400 IN A 172.16.0.1
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; ns.example.com. first owner
|
||||
RANGE_BEGIN 0 500
|
||||
ADDRESS 192.168.0.1
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN NS
|
||||
SECTION ANSWER
|
||||
example.com. 86400 IN NS old-ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
old-ns.example.com. 86400 IN A 192.168.0.1
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. 3600 IN A 10.1.1.1
|
||||
SECTION AUTHORITY
|
||||
example.com. 86400 IN NS old-ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
old-ns.example.com. 86400 IN A 192.168.0.1
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; ns.example.com. new owner
|
||||
RANGE_BEGIN 0 500
|
||||
ADDRESS 172.16.0.1
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN NS
|
||||
SECTION ANSWER
|
||||
example.com. 86400 IN NS new-ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
new-ns.example.com. 86400 IN A 172.16.0.1
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
old-ns.example.com. IN A
|
||||
SECTION ANSWER
|
||||
old-ns.example.com. 86400 IN A 172.16.0.1
|
||||
SECTION AUTHORITY
|
||||
example.com. 86400 IN NS new-ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
new-ns.example.com. 86400 IN A 172.16.0.1
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. 3600 IN A 10.2.2.2
|
||||
SECTION AUTHORITY
|
||||
example.com. 86400 IN NS new-ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
new-ns.example.com. 86400 IN A 172.16.0.1
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
STEP 1 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
ENTRY_END
|
||||
; recursion happens here.
|
||||
STEP 10 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all ttl
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. 3600 IN A 10.1.1.1
|
||||
SECTION AUTHORITY
|
||||
example.com. 86400 IN NS old-ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
old-ns.example.com. 86400 IN A 192.168.0.1
|
||||
ENTRY_END
|
||||
|
||||
; after 1800 secs still the cached answer
|
||||
STEP 20 TIME_PASSES ELAPSE 1800
|
||||
|
||||
STEP 30 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
ENTRY_END
|
||||
; recursion happens here.
|
||||
STEP 40 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all ttl
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. 1800 IN A 10.1.1.1
|
||||
SECTION AUTHORITY
|
||||
example.com. 84600 IN NS old-ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
old-ns.example.com. 84600 IN A 192.168.0.1
|
||||
ENTRY_END
|
||||
|
||||
; after 1440 we are 360 seconds before the expiry
|
||||
; but it still contacts the old-ns
|
||||
STEP 50 TIME_PASSES ELAPSE 1440
|
||||
|
||||
STEP 60 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
ENTRY_END
|
||||
; recursion happens here.
|
||||
STEP 70 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all ttl
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. 360 IN A 10.1.1.1
|
||||
SECTION AUTHORITY
|
||||
example.com. 83160 IN NS old-ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
old-ns.example.com. 83160 IN A 192.168.0.1
|
||||
ENTRY_END
|
||||
|
||||
STEP 80 TRAFFIC
|
||||
; let traffic flow for prefetch to happen
|
||||
|
||||
; we updated from the old-ns.
|
||||
STEP 90 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
ENTRY_END
|
||||
; recursion happens here.
|
||||
STEP 100 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all ttl
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. 3600 IN A 10.1.1.1
|
||||
SECTION AUTHORITY
|
||||
example.com. 83160 IN NS old-ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
old-ns.example.com. 83160 IN A 192.168.0.1
|
||||
ENTRY_END
|
||||
|
||||
; the NS record is now 10% from expiry (8640 TTL left).
|
||||
; and the A record has expired completely, retry.
|
||||
STEP 110 TIME_PASSES ELAPSE 74520
|
||||
|
||||
; the NS record should have timed out.
|
||||
; but you see the full TTL here, this is only for *this query*
|
||||
; in the cache itself its 8640, not 86400.
|
||||
STEP 120 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
ENTRY_END
|
||||
; recursion happens here.
|
||||
STEP 130 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all ttl
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. 3600 IN A 10.1.1.1
|
||||
SECTION AUTHORITY
|
||||
example.com. 8640 IN NS old-ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
old-ns.example.com. 8640 IN A 192.168.0.1
|
||||
ENTRY_END
|
||||
|
||||
; get it from cache
|
||||
STEP 140 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
ENTRY_END
|
||||
; recursion happens here.
|
||||
STEP 150 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all ttl
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. 3600 IN A 10.1.1.1
|
||||
SECTION AUTHORITY
|
||||
example.com. 8640 IN NS old-ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
old-ns.example.com. 8640 IN A 192.168.0.1
|
||||
ENTRY_END
|
||||
|
||||
; the NS record times out after 8640 seconds.
|
||||
STEP 160 TIME_PASSES ELAPSE 8641
|
||||
|
||||
; fetch it
|
||||
STEP 170 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
ENTRY_END
|
||||
; recursion happens here.
|
||||
STEP 180 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all ttl
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. 3600 IN A 10.2.2.2
|
||||
SECTION AUTHORITY
|
||||
example.com. 86400 IN NS new-ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
new-ns.example.com. 86400 IN A 172.16.0.1
|
||||
ENTRY_END
|
||||
|
||||
; a reply from cache
|
||||
STEP 190 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
ENTRY_END
|
||||
; recursion happens here.
|
||||
STEP 200 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all ttl
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. 3600 IN A 10.2.2.2
|
||||
SECTION AUTHORITY
|
||||
example.com. 86400 IN NS new-ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
new-ns.example.com. 86400 IN A 172.16.0.1
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user