mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
Compare commits
317
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d29c1f06af | ||
|
|
f1be0186ae | ||
|
|
2195bf506a | ||
|
|
63dcbe3d75 | ||
|
|
fb342b73d3 | ||
|
|
cccb5094a4 | ||
|
|
3330d5296c | ||
|
|
f95f98b12a | ||
|
|
7bb6358540 | ||
|
|
ca33c52086 | ||
|
|
aba3ba738f | ||
|
|
60da4369a4 | ||
|
|
b04e84ab9e | ||
|
|
d96de4c222 | ||
|
|
0ff5c52657 | ||
|
|
f532367412 | ||
|
|
94996b8a29 | ||
|
|
59e6f149a7 | ||
|
|
470806b097 | ||
|
|
8fcc82171a | ||
|
|
4d5b32ee59 | ||
|
|
816aa50dfc | ||
|
|
068c52d8f5 | ||
|
|
692caffe2c | ||
|
|
c97bb52d77 | ||
|
|
438634b718 | ||
|
|
d21cb609a8 | ||
|
|
668c0627c0 | ||
|
|
de0b6da9f4 | ||
|
|
5853f90076 | ||
|
|
022d5131b3 | ||
|
|
7458729d28 | ||
|
|
7acf6a4a66 | ||
|
|
04d73b9192 | ||
|
|
f7e99131b9 | ||
|
|
069b0b8c90 | ||
|
|
1ff7a89433 | ||
|
|
640d1cf929 | ||
|
|
c9955f9fdf | ||
|
|
9a877e0e9a | ||
|
|
6b49224c85 | ||
|
|
fd5e4e6019 | ||
|
|
8e2a100460 | ||
|
|
359dcc3c5c | ||
|
|
6021341118 | ||
|
|
d5922830d0 | ||
|
|
23505d30a5 | ||
|
|
0f83653e76 | ||
|
|
20f0e8ad55 | ||
|
|
140a165ab2 | ||
|
|
5fec1c8b1f | ||
|
|
6bd4060ae0 | ||
|
|
84a8415357 | ||
|
|
6429b5c298 | ||
|
|
6b5e7d78e3 | ||
|
|
a8b2c64cbf | ||
|
|
9268f0db50 | ||
|
|
02bd3e2ff1 | ||
|
|
2d28fba3bf | ||
|
|
19aed2dcb1 | ||
|
|
eed1e0789a | ||
|
|
837565c505 | ||
|
|
fece182cf5 | ||
|
|
945452bff4 | ||
|
|
1c08a2ba55 | ||
|
|
d967ceb98b | ||
|
|
a3c3e13b2f | ||
|
|
83a186f6cc | ||
|
|
2598f9bb18 | ||
|
|
ba28c48efc | ||
|
|
98234d1017 | ||
|
|
99a92b3483 | ||
|
|
c85ff492d0 | ||
|
|
b09cfb8fb1 | ||
|
|
966a958ca5 | ||
|
|
885069e1f6 | ||
|
|
077b38e2c5 | ||
|
|
9be04e6fac | ||
|
|
377d5b426a | ||
|
|
f82a128909 | ||
|
|
216759e955 | ||
|
|
9b6caf5a5b | ||
|
|
5c25bbd93f | ||
|
|
d8937492cb | ||
|
|
e91d85edb5 | ||
|
|
5089db7331 | ||
|
|
8e20d628e8 | ||
|
|
d275505df6 | ||
|
|
f7516e6b2b | ||
|
|
898d4c8dd9 | ||
|
|
2e9d09b961 | ||
|
|
8dd6efe5ed | ||
|
|
635df9c806 | ||
|
|
75b8b8c875 | ||
|
|
90f0530234 | ||
|
|
d744827f93 | ||
|
|
fe8b22caa1 | ||
|
|
9a82526b91 | ||
|
|
225a6d9c6e | ||
|
|
87c8dd5434 | ||
|
|
a09c4bbdc2 | ||
|
|
d01651c305 | ||
|
|
00982fc3db | ||
|
|
d8f890a43a | ||
|
|
a58681a718 | ||
|
|
c9d33fb9f7 | ||
|
|
254df71810 | ||
|
|
194dc32059 | ||
|
|
987c1c97e5 | ||
|
|
25c8497ba6 | ||
|
|
5577e55400 | ||
|
|
27472f1270 | ||
|
|
30a14c2716 | ||
|
|
d4a69e4d2a | ||
|
|
000e75581b | ||
|
|
2e5e31e8ac | ||
|
|
ae2653fcc5 | ||
|
|
f7118f29b9 | ||
|
|
57a5e75840 | ||
|
|
8d14e7c0a4 | ||
|
|
e0745813f4 | ||
|
|
0171d06aa2 | ||
|
|
4daf8f5bdb | ||
|
|
8893735a2d | ||
|
|
00ba747be7 | ||
|
|
504ef71975 | ||
|
|
9926fcac4b | ||
|
|
01d8dc2240 | ||
|
|
4fe427ded2 | ||
|
|
b0ca964984 | ||
|
|
e8c4f20f66 | ||
|
|
b0daf867c2 | ||
|
|
8385c462ed | ||
|
|
afd4063f20 | ||
|
|
ed24498f2e | ||
|
|
f2b12c0761 | ||
|
|
df85836b15 | ||
|
|
3f2b6828e5 | ||
|
|
1958d9fbd5 | ||
|
|
0c04b5eaf5 | ||
|
|
8e5a32f4dc | ||
|
|
efe5c8e6be | ||
|
|
1e61604aab | ||
|
|
488eaf09ce | ||
|
|
8b1012613e | ||
|
|
256ab3d935 | ||
|
|
a07337fd6d | ||
|
|
be79ffa371 | ||
|
|
c580e0e33c | ||
|
|
d2f7999b4e | ||
|
|
611e37aa2d | ||
|
|
3f2d186694 | ||
|
|
73f01304f0 | ||
|
|
77bd7d228b | ||
|
|
b97b04a9db | ||
|
|
6e4583a528 | ||
|
|
586b811b87 | ||
|
|
070019c9be | ||
|
|
ce04bcb463 | ||
|
|
cf1bfbba5d | ||
|
|
a4fd088875 | ||
|
|
27023b3f21 | ||
|
|
b2a7933045 | ||
|
|
749d1b9ebc | ||
|
|
87bdb489f9 | ||
|
|
37e9f5591a | ||
|
|
d546e7766d | ||
|
|
62f69f9b40 | ||
|
|
168bc963d3 | ||
|
|
1f148e632f | ||
|
|
c887ae1022 | ||
|
|
375d3e7520 | ||
|
|
3b171545b6 | ||
|
|
aa5efa172d | ||
|
|
a2961e50fb | ||
|
|
adc498d29d | ||
|
|
1ff3e51ee1 | ||
|
|
f9c0f359a7 | ||
|
|
cc538f4f9f | ||
|
|
900cd200a2 | ||
|
|
45e73bcc8e | ||
|
|
26eaf2d1ee | ||
|
|
2f32ef7646 | ||
|
|
b7abbd1d72 | ||
|
|
f364edafd3 | ||
|
|
e3f08cb2a2 | ||
|
|
a92b00ef3c | ||
|
|
3dbdde7fed | ||
|
|
6da37e5ecd | ||
|
|
007123ee2c | ||
|
|
10c085f81d | ||
|
|
1d315e11cf | ||
|
|
c91b657a40 | ||
|
|
60f59271d6 | ||
|
|
40abe08ac8 | ||
|
|
ae1790b8e8 | ||
|
|
aa5fb8b10b | ||
|
|
6de329359c | ||
|
|
2e34a8f643 | ||
|
|
bded93f69b | ||
|
|
38e77d50f2 | ||
|
|
f8e585f308 | ||
|
|
5bda4f9822 | ||
|
|
d2d7b987fa | ||
|
|
7579216922 | ||
|
|
330c6e1cb0 | ||
|
|
41e5a66b73 | ||
|
|
cc5ab744c5 | ||
|
|
0ae750e552 | ||
|
|
cabc120f22 | ||
|
|
c96c2d8a45 | ||
|
|
8aa53f027d | ||
|
|
4bf9d12419 | ||
|
|
f93746b1af | ||
|
|
23dc22b78d | ||
|
|
5e3c30beac | ||
|
|
86f16bef93 | ||
|
|
f2e90b0872 | ||
|
|
1249e0db3f | ||
|
|
15c4dd79f4 | ||
|
|
e324a7819a | ||
|
|
81e9f82a8d | ||
|
|
5d298ed474 | ||
|
|
82e1e3959f | ||
|
|
7181c0fa6a | ||
|
|
49f27c06af | ||
|
|
7247718e12 | ||
|
|
61acc76244 | ||
|
|
2faa4f9ee2 | ||
|
|
2beae211ee | ||
|
|
d3ff7a9333 | ||
|
|
23df700f15 | ||
|
|
755233c720 | ||
|
|
bca54a8b25 | ||
|
|
b5aab36d41 | ||
|
|
d7cfe91cb3 | ||
|
|
a31d45b13e | ||
|
|
23f475bccc | ||
|
|
025fdd0049 | ||
|
|
5bb6dbe21c | ||
|
|
c225ced1a9 | ||
|
|
3a58ad15e8 | ||
|
|
5106ad7a2c | ||
|
|
8c044a616b | ||
|
|
9ccf611954 | ||
|
|
5dfcf122d1 | ||
|
|
7b092127cb | ||
|
|
b26257248d | ||
|
|
3c7d270958 | ||
|
|
c15eae814f | ||
|
|
0e72e06886 | ||
|
|
abff4d1237 | ||
|
|
386f23334b | ||
|
|
a523683d4c | ||
|
|
b25332e1f4 | ||
|
|
a6ec2c6fc7 | ||
|
|
9cb404ba5f | ||
|
|
12251022ec | ||
|
|
00a0cabf7f | ||
|
|
d6ed0e868f | ||
|
|
700ad78f10 | ||
|
|
d65accbb23 | ||
|
|
78767f2014 | ||
|
|
21af42a281 | ||
|
|
0b0ece9db0 | ||
|
|
23edc18cac | ||
|
|
7153c94bd7 | ||
|
|
4df697b4b7 | ||
|
|
7fd32916e8 | ||
|
|
3f837bc440 | ||
|
|
f0769bed93 | ||
|
|
a1bfc07105 | ||
|
|
beba72d6db | ||
|
|
a4a5bfaa2f | ||
|
|
62ea384d19 | ||
|
|
53b1e11eba | ||
|
|
7fae96eb1e | ||
|
|
d386641820 | ||
|
|
7c5e38294a | ||
|
|
1cadc5d677 | ||
|
|
7509bf208e | ||
|
|
ec34bc9af1 | ||
|
|
8d1af17449 | ||
|
|
0db1573d34 | ||
|
|
b3c45a8edb | ||
|
|
1a0bd1a150 | ||
|
|
5a726fb61f | ||
|
|
6792d2d036 | ||
|
|
d32fb26adb | ||
|
|
d4ba7731ad | ||
|
|
b9607297e9 | ||
|
|
9ed59fdf34 | ||
|
|
8bcb44a019 | ||
|
|
6b28c8ace2 | ||
|
|
55088951c0 | ||
|
|
55a0d89f0d | ||
|
|
d532c9913c | ||
|
|
261bf354b7 | ||
|
|
50b6dc4b81 | ||
|
|
ba29a4a078 | ||
|
|
676644d8e8 | ||
|
|
f64a897cbc | ||
|
|
8b209f8f68 | ||
|
|
16b6619dfa | ||
|
|
a8c8fa6bc6 | ||
|
|
6d7e5df98f | ||
|
|
1d5d95c8cb | ||
|
|
8f886fc6dd | ||
|
|
581f975b38 | ||
|
|
d2c8bcf318 | ||
|
|
ef1ed6365c | ||
|
|
82418e2bf7 | ||
|
|
6fefbb4115 | ||
|
|
85bf0bd994 | ||
|
|
913d4537f4 | ||
|
|
4e2bafafef | ||
|
|
bffb7c52d5 |
@@ -36,4 +36,7 @@
|
||||
/streamtcp
|
||||
/testbound
|
||||
/unittest
|
||||
/contrib/libunbound.pc
|
||||
/contrib/unbound.service
|
||||
/contrib/unbound.socket
|
||||
|
||||
|
||||
+467
-537
File diff suppressed because it is too large
Load Diff
@@ -446,6 +446,7 @@ adjust_msg_ttl(struct dns_msg* msg, time_t adjust)
|
||||
msg->rep->ttl -= adjust;
|
||||
else msg->rep->ttl = 0;
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
|
||||
|
||||
for(i=0; i<msg->rep->rrset_count; i++) {
|
||||
packed_rrset_ttl_subtract((struct packed_rrset_data*)msg->
|
||||
|
||||
+71
-2
@@ -71,6 +71,72 @@ static struct {
|
||||
|
||||
static inline void _rs_rekey(u_char *dat, size_t datlen);
|
||||
|
||||
/*
|
||||
* Basic sanity checking; wish we could do better.
|
||||
*/
|
||||
static int
|
||||
fallback_gotdata(char *buf, size_t len)
|
||||
{
|
||||
char any_set = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
any_set |= buf[i];
|
||||
if (any_set == 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fallback for getentropy in case libc returns failure */
|
||||
static int
|
||||
fallback_getentropy_urandom(void *buf, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
int fd, flags;
|
||||
int save_errno = errno;
|
||||
|
||||
start:
|
||||
|
||||
flags = O_RDONLY;
|
||||
#ifdef O_NOFOLLOW
|
||||
flags |= O_NOFOLLOW;
|
||||
#endif
|
||||
#ifdef O_CLOEXEC
|
||||
flags |= O_CLOEXEC;
|
||||
#endif
|
||||
fd = open("/dev/urandom", flags, 0);
|
||||
if (fd == -1) {
|
||||
if (errno == EINTR)
|
||||
goto start;
|
||||
goto nodevrandom;
|
||||
}
|
||||
#ifndef O_CLOEXEC
|
||||
# ifdef HAVE_FCNTL
|
||||
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
|
||||
# endif
|
||||
#endif
|
||||
for (i = 0; i < len; ) {
|
||||
size_t wanted = len - i;
|
||||
ssize_t ret = read(fd, (char*)buf + i, wanted);
|
||||
|
||||
if (ret == -1) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
close(fd);
|
||||
goto nodevrandom;
|
||||
}
|
||||
i += ret;
|
||||
}
|
||||
close(fd);
|
||||
if (fallback_gotdata(buf, len) == 0) {
|
||||
errno = save_errno;
|
||||
return 0; /* satisfied */
|
||||
}
|
||||
nodevrandom:
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_rs_init(u_char *buf, size_t n)
|
||||
{
|
||||
@@ -114,11 +180,14 @@ _rs_stir(void)
|
||||
u_char rnd[KEYSZ + IVSZ];
|
||||
|
||||
if (getentropy(rnd, sizeof rnd) == -1) {
|
||||
if(errno != ENOSYS ||
|
||||
fallback_getentropy_urandom(rnd, sizeof rnd) == -1) {
|
||||
#ifdef SIGKILL
|
||||
raise(SIGKILL);
|
||||
raise(SIGKILL);
|
||||
#else
|
||||
exit(9); /* windows */
|
||||
exit(9); /* windows */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (!rs)
|
||||
|
||||
+23
-1
@@ -1,5 +1,11 @@
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* apply the noreturn attribute to a function that exits the program */
|
||||
#undef ATTR_NORETURN
|
||||
|
||||
/* apply the weak attribute to a symbol */
|
||||
#undef ATTR_WEAK
|
||||
|
||||
/* Directory to chroot to */
|
||||
#undef CHROOT_DIR
|
||||
|
||||
@@ -30,6 +36,9 @@
|
||||
internal symbols */
|
||||
#undef EXPORT_ALL_SYMBOLS
|
||||
|
||||
/* Define to 1 if you have the `accept4' function. */
|
||||
#undef HAVE_ACCEPT4
|
||||
|
||||
/* Define to 1 if you have the `arc4random' function. */
|
||||
#undef HAVE_ARC4RANDOM
|
||||
|
||||
@@ -42,6 +51,9 @@
|
||||
/* Whether the C compiler accepts the "format" attribute */
|
||||
#undef HAVE_ATTR_FORMAT
|
||||
|
||||
/* Whether the C compiler accepts the "noreturn" attribute */
|
||||
#undef HAVE_ATTR_NORETURN
|
||||
|
||||
/* Whether the C compiler accepts the "unused" attribute */
|
||||
#undef HAVE_ATTR_UNUSED
|
||||
|
||||
@@ -196,6 +208,9 @@
|
||||
/* Define to 1 if you have the <expat.h> header file. */
|
||||
#undef HAVE_EXPAT_H
|
||||
|
||||
/* Define to 1 if you have the `explicit_bzero' function. */
|
||||
#undef HAVE_EXPLICIT_BZERO
|
||||
|
||||
/* Define to 1 if you have the `fcntl' function. */
|
||||
#undef HAVE_FCNTL
|
||||
|
||||
@@ -648,6 +663,9 @@
|
||||
/* Define as the return type of signal handlers (`int' or `void'). */
|
||||
#undef RETSIGTYPE
|
||||
|
||||
/* if REUSEPORT is enabled by default */
|
||||
#undef REUSEPORT_DEFAULT
|
||||
|
||||
/* default rootkey location */
|
||||
#undef ROOT_ANCHOR_FILE
|
||||
|
||||
@@ -1141,6 +1159,11 @@ char *strsep(char **stringp, const char *delim);
|
||||
int isblank(int c);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_EXPLICIT_BZERO
|
||||
#define explicit_bzero unbound_explicit_bzero
|
||||
void explicit_bzero(void* buf, size_t len);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INET_NTOP) && !HAVE_DECL_INET_NTOP
|
||||
const char *inet_ntop(int af, const void *src, char *dst, size_t size);
|
||||
#endif
|
||||
@@ -1173,7 +1196,6 @@ void *reallocarray(void *ptr, size_t nmemb, size_t size);
|
||||
# endif
|
||||
#endif /* HAVE_LIBRESSL */
|
||||
#ifndef HAVE_ARC4RANDOM
|
||||
void explicit_bzero(void* buf, size_t len);
|
||||
int getentropy(void* buf, size_t len);
|
||||
uint32_t arc4random(void);
|
||||
void arc4random_buf(void* buf, size_t n);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for unbound 1.7.1.
|
||||
# Generated by GNU Autoconf 2.69 for unbound 1.8.2.
|
||||
#
|
||||
# Report bugs to <unbound-bugs@nlnetlabs.nl>.
|
||||
#
|
||||
@@ -590,8 +590,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='unbound'
|
||||
PACKAGE_TARNAME='unbound'
|
||||
PACKAGE_VERSION='1.7.1'
|
||||
PACKAGE_STRING='unbound 1.7.1'
|
||||
PACKAGE_VERSION='1.8.2'
|
||||
PACKAGE_STRING='unbound 1.8.2'
|
||||
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl'
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -670,9 +670,6 @@ SYSTEMD_DAEMON_LIBS
|
||||
SYSTEMD_DAEMON_CFLAGS
|
||||
SYSTEMD_LIBS
|
||||
SYSTEMD_CFLAGS
|
||||
PKG_CONFIG_LIBDIR
|
||||
PKG_CONFIG_PATH
|
||||
PKG_CONFIG
|
||||
staticexe
|
||||
PC_LIBEVENT_DEPENDENCY
|
||||
UNBOUND_EVENT_UNINSTALL
|
||||
@@ -697,6 +694,9 @@ swig
|
||||
SWIG_LIB
|
||||
SWIG
|
||||
PC_PY_DEPENDENCY
|
||||
PKG_CONFIG_LIBDIR
|
||||
PKG_CONFIG_PATH
|
||||
PKG_CONFIG
|
||||
PY_MAJOR_VERSION
|
||||
PYTHON_SITE_PKG
|
||||
PYTHON_LDFLAGS
|
||||
@@ -1440,7 +1440,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures unbound 1.7.1 to adapt to many kinds of systems.
|
||||
\`configure' configures unbound 1.8.2 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1505,7 +1505,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of unbound 1.7.1:";;
|
||||
short | recursive ) echo "Configuration of unbound 1.8.2:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1722,7 +1722,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
unbound configure 1.7.1
|
||||
unbound configure 1.8.2
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2431,7 +2431,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by unbound $as_me 1.7.1, which was
|
||||
It was created by unbound $as_me 1.8.2, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -2781,14 +2781,14 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
UNBOUND_VERSION_MAJOR=1
|
||||
|
||||
UNBOUND_VERSION_MINOR=7
|
||||
UNBOUND_VERSION_MINOR=8
|
||||
|
||||
UNBOUND_VERSION_MICRO=1
|
||||
UNBOUND_VERSION_MICRO=2
|
||||
|
||||
|
||||
LIBUNBOUND_CURRENT=7
|
||||
LIBUNBOUND_REVISION=9
|
||||
LIBUNBOUND_AGE=5
|
||||
LIBUNBOUND_CURRENT=8
|
||||
LIBUNBOUND_REVISION=2
|
||||
LIBUNBOUND_AGE=0
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
# 1.0.2 had 0:14:0
|
||||
@@ -2848,6 +2848,11 @@ LIBUNBOUND_AGE=5
|
||||
# 1.6.8 had 7:7:5
|
||||
# 1.7.0 had 7:8:5
|
||||
# 1.7.1 had 7:9:5
|
||||
# 1.7.2 had 7:10:5
|
||||
# 1.7.3 had 7:11:5
|
||||
# 1.8.0 had 8:0:0 # changes the event callback function signature
|
||||
# 1.8.1 had 8:1:0
|
||||
# 1.8.2 had 8:2:0
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -6262,6 +6267,54 @@ if test $ac_cv_c_weak_attribute = yes; then
|
||||
|
||||
$as_echo "#define HAVE_ATTR_WEAK 1" >>confdefs.h
|
||||
|
||||
|
||||
$as_echo "#define ATTR_WEAK __attribute__((weak))" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler (${CC-cc}) accepts the \"noreturn\" attribute" >&5
|
||||
$as_echo_n "checking whether the C compiler (${CC-cc}) accepts the \"noreturn\" attribute... " >&6; }
|
||||
if ${ac_cv_c_noreturn_attribute+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_cv_c_noreturn_attribute=no
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <stdio.h>
|
||||
__attribute__((noreturn)) void f(int x) { printf("%d", x); }
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
f(1);
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
ac_cv_c_noreturn_attribute="yes"
|
||||
else
|
||||
ac_cv_c_noreturn_attribute="no"
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
|
||||
fi
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_noreturn_attribute" >&5
|
||||
$as_echo "$ac_cv_c_noreturn_attribute" >&6; }
|
||||
if test $ac_cv_c_noreturn_attribute = yes; then
|
||||
|
||||
$as_echo "#define HAVE_ATTR_NORETURN 1" >>confdefs.h
|
||||
|
||||
|
||||
$as_echo "#define ATTR_NORETURN __attribute__((__noreturn__))" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
|
||||
@@ -6271,6 +6324,8 @@ fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for ac_prog in flex lex
|
||||
do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
@@ -6430,6 +6485,7 @@ fi
|
||||
rm -f conftest.l $LEX_OUTPUT_ROOT.c
|
||||
|
||||
fi
|
||||
if test "$LEX" != "" -a "$LEX" != ":"; then
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for yylex_destroy" >&5
|
||||
$as_echo_n "checking for yylex_destroy... " >&6; }
|
||||
@@ -6440,8 +6496,27 @@ $as_echo "#define LEX_HAS_YYLEX_DESTROY 1" >>confdefs.h
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }; fi
|
||||
$as_echo "no" >&6; };
|
||||
LEX=":"
|
||||
fi
|
||||
|
||||
fi
|
||||
if test "$LEX" != "" -a "$LEX" != ":"; then
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for lex %option" >&5
|
||||
$as_echo_n "checking for lex %option... " >&6; }
|
||||
if cat <<EOF | $LEX -t 2>&1 | grep yy_delete_buffer >/dev/null 2>&1; then
|
||||
%option nounput
|
||||
%%
|
||||
EOF
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; };
|
||||
LEX=":"
|
||||
fi
|
||||
|
||||
fi
|
||||
for ac_prog in 'bison -y' byacc
|
||||
do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
@@ -15892,6 +15967,17 @@ fi
|
||||
done
|
||||
|
||||
|
||||
# check if we can use SO_REUSEPORT
|
||||
if echo "$host" | grep -i -e linux -e dragonfly >/dev/null; then
|
||||
|
||||
$as_echo "#define REUSEPORT_DEFAULT 1" >>confdefs.h
|
||||
|
||||
else
|
||||
|
||||
$as_echo "#define REUSEPORT_DEFAULT 0" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
# set memory allocation checking if requested
|
||||
# Check whether --enable-alloc-checks was given.
|
||||
if test "${enable_alloc_checks+set}" = set; then :
|
||||
@@ -16927,7 +17013,136 @@ $as_echo "#define HAVE_PYTHON 1" >>confdefs.h
|
||||
CPPFLAGS="$PYTHON_CPPFLAGS"
|
||||
fi
|
||||
ub_have_python=yes
|
||||
PC_PY_DEPENDENCY="python"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
|
||||
if test -n "$ac_tool_prefix"; then
|
||||
# Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
|
||||
set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_path_PKG_CONFIG+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
case $PKG_CONFIG in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
|
||||
;;
|
||||
*)
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
PKG_CONFIG=$ac_cv_path_PKG_CONFIG
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
|
||||
$as_echo "$PKG_CONFIG" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
fi
|
||||
if test -z "$ac_cv_path_PKG_CONFIG"; then
|
||||
ac_pt_PKG_CONFIG=$PKG_CONFIG
|
||||
# Extract the first word of "pkg-config", so it can be a program name with args.
|
||||
set dummy pkg-config; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
case $ac_pt_PKG_CONFIG in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
|
||||
;;
|
||||
*)
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
|
||||
if test -n "$ac_pt_PKG_CONFIG"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
|
||||
$as_echo "$ac_pt_PKG_CONFIG" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
if test "x$ac_pt_PKG_CONFIG" = x; then
|
||||
PKG_CONFIG=""
|
||||
else
|
||||
case $cross_compiling:$ac_tool_warned in
|
||||
yes:)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
|
||||
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
|
||||
ac_tool_warned=yes ;;
|
||||
esac
|
||||
PKG_CONFIG=$ac_pt_PKG_CONFIG
|
||||
fi
|
||||
else
|
||||
PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
|
||||
fi
|
||||
|
||||
fi
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
_pkg_min_version=0.9.0
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
|
||||
$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
PKG_CONFIG=""
|
||||
fi
|
||||
fi
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\"python\${PY_MAJOR_VERSION}\"\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors ""python${PY_MAJOR_VERSION}"") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
PC_PY_DEPENDENCY="python${PY_MAJOR_VERSION}"
|
||||
else
|
||||
PC_PY_DEPENDENCY="python"
|
||||
fi
|
||||
|
||||
|
||||
# Check for SWIG
|
||||
@@ -18868,10 +19083,10 @@ else
|
||||
withval="no"
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libhiredis" >&5
|
||||
$as_echo_n "checking for libhiredis... " >&6; }
|
||||
found_libhiredis="no"
|
||||
if test x_$withval = x_yes -o x_$withval != x_no; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libhiredis" >&5
|
||||
$as_echo_n "checking for libhiredis... " >&6; }
|
||||
if test x_$withval = x_ -o x_$withval = x_yes; then
|
||||
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
|
||||
fi
|
||||
@@ -18957,126 +19172,6 @@ else
|
||||
fi
|
||||
|
||||
have_systemd=no
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
|
||||
if test -n "$ac_tool_prefix"; then
|
||||
# Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
|
||||
set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_path_PKG_CONFIG+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
case $PKG_CONFIG in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
|
||||
;;
|
||||
*)
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
PKG_CONFIG=$ac_cv_path_PKG_CONFIG
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
|
||||
$as_echo "$PKG_CONFIG" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
fi
|
||||
if test -z "$ac_cv_path_PKG_CONFIG"; then
|
||||
ac_pt_PKG_CONFIG=$PKG_CONFIG
|
||||
# Extract the first word of "pkg-config", so it can be a program name with args.
|
||||
set dummy pkg-config; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
case $ac_pt_PKG_CONFIG in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
|
||||
;;
|
||||
*)
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
|
||||
if test -n "$ac_pt_PKG_CONFIG"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
|
||||
$as_echo "$ac_pt_PKG_CONFIG" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
if test "x$ac_pt_PKG_CONFIG" = x; then
|
||||
PKG_CONFIG=""
|
||||
else
|
||||
case $cross_compiling:$ac_tool_warned in
|
||||
yes:)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
|
||||
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
|
||||
ac_tool_warned=yes ;;
|
||||
esac
|
||||
PKG_CONFIG=$ac_pt_PKG_CONFIG
|
||||
fi
|
||||
else
|
||||
PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
|
||||
fi
|
||||
|
||||
fi
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
_pkg_min_version=0.9.0
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
|
||||
$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
PKG_CONFIG=""
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_systemd" != xno; then :
|
||||
|
||||
|
||||
@@ -19467,7 +19562,7 @@ else
|
||||
WINDRES="$ac_cv_prog_WINDRES"
|
||||
fi
|
||||
|
||||
LIBS="$LIBS -liphlpapi"
|
||||
LIBS="$LIBS -liphlpapi -lcrypt32"
|
||||
WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe"
|
||||
|
||||
WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c"
|
||||
@@ -19701,7 +19796,7 @@ if test "$ac_res" != no; then :
|
||||
|
||||
fi
|
||||
|
||||
for ac_func in tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget
|
||||
for ac_func in tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4
|
||||
do :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
@@ -19761,7 +19856,7 @@ done
|
||||
|
||||
|
||||
# check if setreuid en setregid fail, on MacOSX10.4(darwin8).
|
||||
if echo $build_os | grep darwin8 > /dev/null; then
|
||||
if echo $target_os | grep darwin8 > /dev/null; then
|
||||
|
||||
$as_echo "#define DARWIN_BROKEN_SETREUID 1" >>confdefs.h
|
||||
|
||||
@@ -19999,6 +20094,20 @@ esac
|
||||
fi
|
||||
|
||||
|
||||
ac_fn_c_check_func "$LINENO" "explicit_bzero" "ac_cv_func_explicit_bzero"
|
||||
if test "x$ac_cv_func_explicit_bzero" = xyes; then :
|
||||
$as_echo "#define HAVE_EXPLICIT_BZERO 1" >>confdefs.h
|
||||
|
||||
else
|
||||
case " $LIBOBJS " in
|
||||
*" explicit_bzero.$ac_objext "* ) ;;
|
||||
*) LIBOBJS="$LIBOBJS explicit_bzero.$ac_objext"
|
||||
;;
|
||||
esac
|
||||
|
||||
fi
|
||||
|
||||
|
||||
LIBOBJ_WITHOUT_CTIMEARC4="$LIBOBJS"
|
||||
|
||||
ac_fn_c_check_func "$LINENO" "reallocarray" "ac_cv_func_reallocarray"
|
||||
@@ -20045,12 +20154,6 @@ fi
|
||||
|
||||
|
||||
if test "$ac_cv_func_arc4random" = "no"; then
|
||||
case " $LIBOBJS " in
|
||||
*" explicit_bzero.$ac_objext "* ) ;;
|
||||
*) LIBOBJS="$LIBOBJS explicit_bzero.$ac_objext"
|
||||
;;
|
||||
esac
|
||||
|
||||
case " $LIBOBJS " in
|
||||
*" arc4_lock.$ac_objext "* ) ;;
|
||||
*) LIBOBJS="$LIBOBJS arc4_lock.$ac_objext"
|
||||
@@ -20854,6 +20957,8 @@ if test "${enable_cachedb+set}" = set; then :
|
||||
enableval=$enable_cachedb;
|
||||
fi
|
||||
|
||||
# turn on cachedb when hiredis support is enabled.
|
||||
if test "$found_libhiredis" = "yes"; then enable_cachedb="yes"; fi
|
||||
case "$enable_cachedb" in
|
||||
yes)
|
||||
|
||||
@@ -21041,7 +21146,7 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
version=1.7.1
|
||||
version=1.8.2
|
||||
|
||||
date=`date +'%b %e, %Y'`
|
||||
|
||||
@@ -21560,7 +21665,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by unbound $as_me 1.7.1, which was
|
||||
This file was extended by unbound $as_me 1.8.2, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -21626,7 +21731,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
unbound config.status 1.7.1
|
||||
unbound config.status 1.8.2
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
+78
-13
@@ -10,16 +10,16 @@ sinclude(dnscrypt/dnscrypt.m4)
|
||||
|
||||
# must be numbers. ac_defun because of later processing
|
||||
m4_define([VERSION_MAJOR],[1])
|
||||
m4_define([VERSION_MINOR],[7])
|
||||
m4_define([VERSION_MICRO],[1])
|
||||
m4_define([VERSION_MINOR],[8])
|
||||
m4_define([VERSION_MICRO],[2])
|
||||
AC_INIT(unbound, m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]), unbound-bugs@nlnetlabs.nl, unbound)
|
||||
AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
|
||||
AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
|
||||
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
|
||||
|
||||
LIBUNBOUND_CURRENT=7
|
||||
LIBUNBOUND_REVISION=9
|
||||
LIBUNBOUND_AGE=5
|
||||
LIBUNBOUND_CURRENT=8
|
||||
LIBUNBOUND_REVISION=2
|
||||
LIBUNBOUND_AGE=0
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
# 1.0.2 had 0:14:0
|
||||
@@ -79,6 +79,11 @@ LIBUNBOUND_AGE=5
|
||||
# 1.6.8 had 7:7:5
|
||||
# 1.7.0 had 7:8:5
|
||||
# 1.7.1 had 7:9:5
|
||||
# 1.7.2 had 7:10:5
|
||||
# 1.7.3 had 7:11:5
|
||||
# 1.8.0 had 8:0:0 # changes the event callback function signature
|
||||
# 1.8.1 had 8:1:0
|
||||
# 1.8.2 had 8:2:0
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -307,11 +312,36 @@ __attribute__((weak)) void f(int x) { printf("%d", x); }
|
||||
AC_MSG_RESULT($ac_cv_c_weak_attribute)
|
||||
if test $ac_cv_c_weak_attribute = yes; then
|
||||
AC_DEFINE(HAVE_ATTR_WEAK, 1, [Whether the C compiler accepts the "weak" attribute])
|
||||
AC_DEFINE(ATTR_WEAK, [__attribute__((weak))], [apply the weak attribute to a symbol])
|
||||
fi
|
||||
])dnl End of CHECK_WEAK_ATTRIBUTE
|
||||
|
||||
CHECK_WEAK_ATTRIBUTE
|
||||
|
||||
AC_DEFUN([CHECK_NORETURN_ATTRIBUTE],
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "noreturn" attribute)
|
||||
AC_CACHE_VAL(ac_cv_c_noreturn_attribute,
|
||||
[ac_cv_c_noreturn_attribute=no
|
||||
AC_TRY_COMPILE(
|
||||
[ #include <stdio.h>
|
||||
__attribute__((noreturn)) void f(int x) { printf("%d", x); }
|
||||
], [
|
||||
f(1);
|
||||
],
|
||||
[ac_cv_c_noreturn_attribute="yes"],
|
||||
[ac_cv_c_noreturn_attribute="no"])
|
||||
])
|
||||
|
||||
AC_MSG_RESULT($ac_cv_c_noreturn_attribute)
|
||||
if test $ac_cv_c_noreturn_attribute = yes; then
|
||||
AC_DEFINE(HAVE_ATTR_NORETURN, 1, [Whether the C compiler accepts the "noreturn" attribute])
|
||||
AC_DEFINE(ATTR_NORETURN, [__attribute__((__noreturn__))], [apply the noreturn attribute to a function that exits the program])
|
||||
fi
|
||||
])dnl End of CHECK_NORETURN_ATTRIBUTE
|
||||
|
||||
CHECK_NORETURN_ATTRIBUTE
|
||||
|
||||
if test "$srcdir" != "."; then
|
||||
CPPFLAGS="$CPPFLAGS -I$srcdir"
|
||||
fi
|
||||
@@ -321,11 +351,30 @@ AC_DEFUN([ACX_YYLEX_DESTROY], [
|
||||
if echo %% | $LEX -t 2>&1 | grep yylex_destroy >/dev/null 2>&1; then
|
||||
AC_DEFINE(LEX_HAS_YYLEX_DESTROY, 1, [if lex has yylex_destroy])
|
||||
AC_MSG_RESULT(yes)
|
||||
else AC_MSG_RESULT(no); fi
|
||||
else AC_MSG_RESULT(no);
|
||||
LEX=":"
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN([ACX_YYLEX_OPTION], [
|
||||
AC_MSG_CHECKING([for lex %option])
|
||||
if cat <<EOF | $LEX -t 2>&1 | grep yy_delete_buffer >/dev/null 2>&1; then
|
||||
%option nounput
|
||||
%%
|
||||
EOF
|
||||
AC_MSG_RESULT(yes)
|
||||
else AC_MSG_RESULT(no);
|
||||
LEX=":"
|
||||
fi
|
||||
])
|
||||
|
||||
AC_PROG_LEX
|
||||
if test "$LEX" != "" -a "$LEX" != ":"; then
|
||||
ACX_YYLEX_DESTROY
|
||||
fi
|
||||
if test "$LEX" != "" -a "$LEX" != ":"; then
|
||||
ACX_YYLEX_OPTION
|
||||
fi
|
||||
AC_PROG_YACC
|
||||
AC_CHECK_PROG(doxygen, doxygen, doxygen)
|
||||
AC_CHECK_TOOL(STRIP, strip)
|
||||
@@ -413,6 +462,13 @@ ACX_CHECK_NONBLOCKING_BROKEN
|
||||
ACX_MKDIR_ONE_ARG
|
||||
AC_CHECK_FUNCS([strptime],[AC_CHECK_STRPTIME_WORKS],[AC_LIBOBJ([strptime])])
|
||||
|
||||
# check if we can use SO_REUSEPORT
|
||||
if echo "$host" | grep -i -e linux -e dragonfly >/dev/null; then
|
||||
AC_DEFINE(REUSEPORT_DEFAULT, 1, [if REUSEPORT is enabled by default])
|
||||
else
|
||||
AC_DEFINE(REUSEPORT_DEFAULT, 0, [if REUSEPORT is enabled by default])
|
||||
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 ]),
|
||||
@@ -583,7 +639,10 @@ if test x_$ub_test_python != x_no; then
|
||||
CPPFLAGS="$PYTHON_CPPFLAGS"
|
||||
fi
|
||||
ub_have_python=yes
|
||||
PC_PY_DEPENDENCY="python"
|
||||
PKG_PROG_PKG_CONFIG
|
||||
PKG_CHECK_EXISTS(["python${PY_MAJOR_VERSION}"],
|
||||
[PC_PY_DEPENDENCY="python${PY_MAJOR_VERSION}"],
|
||||
[PC_PY_DEPENDENCY="python"])
|
||||
AC_SUBST(PC_PY_DEPENDENCY)
|
||||
|
||||
# Check for SWIG
|
||||
@@ -1175,9 +1234,9 @@ AC_CHECK_DECLS([XML_StopParser], [], [], [AC_INCLUDES_DEFAULT
|
||||
AC_ARG_WITH(libhiredis, AC_HELP_STRING([--with-libhiredis=path],
|
||||
[specify explicit path for libhiredis.]),
|
||||
[ ],[ withval="no" ])
|
||||
AC_MSG_CHECKING(for libhiredis)
|
||||
found_libhiredis="no"
|
||||
if test x_$withval = x_yes -o x_$withval != x_no; then
|
||||
AC_MSG_CHECKING(for libhiredis)
|
||||
if test x_$withval = x_ -o x_$withval = x_yes; then
|
||||
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
|
||||
fi
|
||||
@@ -1245,7 +1304,7 @@ if test "$USE_WINSOCK" = 1; then
|
||||
#include <windows.h>
|
||||
])
|
||||
AC_CHECK_TOOL(WINDRES, windres)
|
||||
LIBS="$LIBS -liphlpapi"
|
||||
LIBS="$LIBS -liphlpapi -lcrypt32"
|
||||
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"
|
||||
@@ -1318,12 +1377,12 @@ AC_INCLUDES_DEFAULT
|
||||
#endif
|
||||
])
|
||||
AC_SEARCH_LIBS([setusercontext], [util])
|
||||
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget])
|
||||
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4])
|
||||
AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])])
|
||||
AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
|
||||
|
||||
# check if setreuid en setregid fail, on MacOSX10.4(darwin8).
|
||||
if echo $build_os | grep darwin8 > /dev/null; then
|
||||
if echo $target_os | grep darwin8 > /dev/null; then
|
||||
AC_DEFINE(DARWIN_BROKEN_SETREUID, 1, [Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work])
|
||||
fi
|
||||
AC_CHECK_DECLS([inet_pton,inet_ntop], [], [], [
|
||||
@@ -1371,6 +1430,7 @@ AC_REPLACE_FUNCS(strlcpy)
|
||||
AC_REPLACE_FUNCS(memmove)
|
||||
AC_REPLACE_FUNCS(gmtime_r)
|
||||
AC_REPLACE_FUNCS(isblank)
|
||||
AC_REPLACE_FUNCS(explicit_bzero)
|
||||
dnl without CTIME, ARC4-functions and without reallocarray.
|
||||
LIBOBJ_WITHOUT_CTIMEARC4="$LIBOBJS"
|
||||
AC_SUBST(LIBOBJ_WITHOUT_CTIMEARC4)
|
||||
@@ -1379,7 +1439,6 @@ if test "$USE_NSS" = "no"; then
|
||||
AC_REPLACE_FUNCS(arc4random)
|
||||
AC_REPLACE_FUNCS(arc4random_uniform)
|
||||
if test "$ac_cv_func_arc4random" = "no"; then
|
||||
AC_LIBOBJ(explicit_bzero)
|
||||
AC_LIBOBJ(arc4_lock)
|
||||
AC_CHECK_FUNCS([getentropy],,[
|
||||
if test "$USE_WINSOCK" = 1; then
|
||||
@@ -1488,6 +1547,8 @@ dnsc_DNSCRYPT([
|
||||
|
||||
# check for cachedb if requested
|
||||
AC_ARG_ENABLE(cachedb, AC_HELP_STRING([--enable-cachedb], [enable cachedb module that can use external cache storage]))
|
||||
# turn on cachedb when hiredis support is enabled.
|
||||
if test "$found_libhiredis" = "yes"; then enable_cachedb="yes"; fi
|
||||
case "$enable_cachedb" in
|
||||
yes)
|
||||
AC_DEFINE([USE_CACHEDB], [1], [Define to 1 to use cachedb support])
|
||||
@@ -1702,6 +1763,11 @@ char *strsep(char **stringp, const char *delim);
|
||||
int isblank(int c);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_EXPLICIT_BZERO
|
||||
#define explicit_bzero unbound_explicit_bzero
|
||||
void explicit_bzero(void* buf, size_t len);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INET_NTOP) && !HAVE_DECL_INET_NTOP
|
||||
const char *inet_ntop(int af, const void *src, char *dst, size_t size);
|
||||
#endif
|
||||
@@ -1734,7 +1800,6 @@ void *reallocarray(void *ptr, size_t nmemb, size_t size);
|
||||
# endif
|
||||
#endif /* HAVE_LIBRESSL */
|
||||
#ifndef HAVE_ARC4RANDOM
|
||||
void explicit_bzero(void* buf, size_t len);
|
||||
int getentropy(void* buf, size_t len);
|
||||
uint32_t arc4random(void);
|
||||
void arc4random_buf(void* buf, size_t n);
|
||||
|
||||
+143
-152
@@ -1,15 +1,11 @@
|
||||
Description: based on the included patch contrib/fastrpz.patch
|
||||
Author: fastrpz@farsightsecurity.com
|
||||
---
|
||||
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
|
||||
Index: unboundfastrpz/Makefile.in
|
||||
===================================================================
|
||||
RCS file: ./RCS/Makefile.in,v
|
||||
retrieving revision 1.1
|
||||
Index: unbound-1.7.0~rc1/Makefile.in
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/Makefile.in
|
||||
+++ unbound-1.7.0~rc1/Makefile.in
|
||||
@@ -23,6 +23,8 @@ CHECKLOCK_SRC=testcode/checklocks.c
|
||||
--- unboundfastrpz/Makefile.in (revision 4987)
|
||||
+++ unboundfastrpz/Makefile.in (working copy)
|
||||
@@ -23,6 +23,8 @@
|
||||
CHECKLOCK_OBJ=@CHECKLOCK_OBJ@
|
||||
DNSTAP_SRC=@DNSTAP_SRC@
|
||||
DNSTAP_OBJ=@DNSTAP_OBJ@
|
||||
@@ -18,7 +14,7 @@ Index: unbound-1.7.0~rc1/Makefile.in
|
||||
DNSCRYPT_SRC=@DNSCRYPT_SRC@
|
||||
DNSCRYPT_OBJ=@DNSCRYPT_OBJ@
|
||||
WITH_PYTHONMODULE=@WITH_PYTHONMODULE@
|
||||
@@ -125,7 +127,7 @@ validator/val_sigcrypt.c validator/val_u
|
||||
@@ -126,7 +128,7 @@
|
||||
edns-subnet/edns-subnet.c edns-subnet/subnetmod.c \
|
||||
edns-subnet/addrtree.c edns-subnet/subnet-whitelist.c \
|
||||
cachedb/cachedb.c cachedb/redis.c respip/respip.c $(CHECKLOCK_SRC) \
|
||||
@@ -27,16 +23,16 @@ Index: unbound-1.7.0~rc1/Makefile.in
|
||||
COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \
|
||||
as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
|
||||
iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \
|
||||
@@ -137,7 +139,7 @@ slabhash.lo timehist.lo tube.lo winsock_
|
||||
@@ -139,7 +141,7 @@
|
||||
validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
|
||||
val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo cachedb.lo authzone.lo\
|
||||
val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo cachedb.lo redis.lo authzone.lo \
|
||||
$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
|
||||
-$(IPSECMOD_OBJ) respip.lo
|
||||
+$(FASTRPZ_OBJ) $(IPSECMOD_OBJ) respip.lo
|
||||
COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
|
||||
outside_network.lo
|
||||
COMMON_OBJ=$(COMMON_OBJ_WITHOUT_UB_EVENT) ub_event.lo
|
||||
@@ -400,6 +402,11 @@ dnscrypt.lo dnscrypt.o: $(srcdir)/dnscry
|
||||
@@ -405,6 +407,11 @@
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/netevent.h
|
||||
|
||||
@@ -48,11 +44,11 @@ Index: unbound-1.7.0~rc1/Makefile.in
|
||||
# Python Module
|
||||
pythonmod.lo pythonmod.o: $(srcdir)/pythonmod/pythonmod.c config.h \
|
||||
pythonmod/interface.h \
|
||||
Index: unbound-1.7.0~rc1/config.h.in
|
||||
Index: unboundfastrpz/config.h.in
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/config.h.in
|
||||
+++ unbound-1.7.0~rc1/config.h.in
|
||||
@@ -1228,4 +1228,11 @@ void *unbound_stat_realloc_log(void *ptr
|
||||
--- unboundfastrpz/config.h.in (revision 4987)
|
||||
+++ unboundfastrpz/config.h.in (working copy)
|
||||
@@ -1275,4 +1275,11 @@
|
||||
/** the version of unbound-control that this software implements */
|
||||
#define UNBOUND_CONTROL_VERSION 1
|
||||
|
||||
@@ -65,11 +61,11 @@ Index: unbound-1.7.0~rc1/config.h.in
|
||||
+#undef FASTRPZ_LIB_OPEN
|
||||
+/** turn on fastrpz response policy zones */
|
||||
+#undef ENABLE_FASTRPZ
|
||||
Index: unbound-1.7.0~rc1/configure.ac
|
||||
Index: unboundfastrpz/configure.ac
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/configure.ac
|
||||
+++ unbound-1.7.0~rc1/configure.ac
|
||||
@@ -6,6 +6,7 @@ sinclude(ax_pthread.m4)
|
||||
--- unboundfastrpz/configure.ac (revision 4987)
|
||||
+++ unboundfastrpz/configure.ac (working copy)
|
||||
@@ -6,6 +6,7 @@
|
||||
sinclude(acx_python.m4)
|
||||
sinclude(ac_pkg_swig.m4)
|
||||
sinclude(dnstap/dnstap.m4)
|
||||
@@ -77,7 +73,7 @@ Index: unbound-1.7.0~rc1/configure.ac
|
||||
sinclude(dnscrypt/dnscrypt.m4)
|
||||
|
||||
# must be numbers. ac_defun because of later processing
|
||||
@@ -1453,6 +1454,9 @@ case "$enable_ipsecmod" in
|
||||
@@ -1573,6 +1574,9 @@
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -87,11 +83,11 @@ Index: unbound-1.7.0~rc1/configure.ac
|
||||
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).
|
||||
Index: unbound-1.7.0~rc1/daemon/daemon.c
|
||||
Index: unboundfastrpz/daemon/daemon.c
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/daemon/daemon.c
|
||||
+++ unbound-1.7.0~rc1/daemon/daemon.c
|
||||
@@ -90,6 +90,9 @@
|
||||
--- unboundfastrpz/daemon/daemon.c (revision 4987)
|
||||
+++ unboundfastrpz/daemon/daemon.c (working copy)
|
||||
@@ -91,6 +91,9 @@
|
||||
#include "sldns/keyraw.h"
|
||||
#include "respip/respip.h"
|
||||
#include <signal.h>
|
||||
@@ -101,7 +97,7 @@ Index: unbound-1.7.0~rc1/daemon/daemon.c
|
||||
|
||||
#ifdef HAVE_SYSTEMD
|
||||
#include <systemd/sd-daemon.h>
|
||||
@@ -461,6 +464,14 @@ daemon_create_workers(struct daemon* dae
|
||||
@@ -462,6 +465,14 @@
|
||||
fatal_exit("dnstap enabled in config but not built with dnstap support");
|
||||
#endif
|
||||
}
|
||||
@@ -116,9 +112,9 @@ Index: unbound-1.7.0~rc1/daemon/daemon.c
|
||||
for(i=0; i<daemon->num; i++) {
|
||||
if(!(daemon->workers[i] = worker_create(daemon, i,
|
||||
shufport+numport*i/daemon->num,
|
||||
@@ -710,6 +721,9 @@ daemon_cleanup(struct daemon* daemon)
|
||||
#ifdef USE_DNSCRYPT
|
||||
@@ -719,6 +730,9 @@
|
||||
dnsc_delete(daemon->dnscenv);
|
||||
daemon->dnscenv = NULL;
|
||||
#endif
|
||||
+#ifdef ENABLE_FASTRPZ
|
||||
+ rpz_delete(&daemon->rpz_clist, &daemon->rpz_client);
|
||||
@@ -126,11 +122,11 @@ Index: unbound-1.7.0~rc1/daemon/daemon.c
|
||||
daemon->cfg = NULL;
|
||||
}
|
||||
|
||||
Index: unbound-1.7.0~rc1/daemon/daemon.h
|
||||
Index: unboundfastrpz/daemon/daemon.h
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/daemon/daemon.h
|
||||
+++ unbound-1.7.0~rc1/daemon/daemon.h
|
||||
@@ -134,6 +134,11 @@ struct daemon {
|
||||
--- unboundfastrpz/daemon/daemon.h (revision 4987)
|
||||
+++ unboundfastrpz/daemon/daemon.h (working copy)
|
||||
@@ -136,6 +136,11 @@
|
||||
/** the dnscrypt environment */
|
||||
struct dnsc_env* dnscenv;
|
||||
#endif
|
||||
@@ -142,11 +138,11 @@ Index: unbound-1.7.0~rc1/daemon/daemon.h
|
||||
};
|
||||
|
||||
/**
|
||||
Index: unbound-1.7.0~rc1/daemon/worker.c
|
||||
Index: unboundfastrpz/daemon/worker.c
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/daemon/worker.c
|
||||
+++ unbound-1.7.0~rc1/daemon/worker.c
|
||||
@@ -74,6 +74,9 @@
|
||||
--- unboundfastrpz/daemon/worker.c (revision 4987)
|
||||
+++ unboundfastrpz/daemon/worker.c (working copy)
|
||||
@@ -75,6 +75,9 @@
|
||||
#include "libunbound/context.h"
|
||||
#include "libunbound/libworker.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
@@ -156,7 +152,7 @@ Index: unbound-1.7.0~rc1/daemon/worker.c
|
||||
#include "sldns/wire2str.h"
|
||||
#include "util/shm_side/shm_main.h"
|
||||
#include "dnscrypt/dnscrypt.h"
|
||||
@@ -527,8 +530,27 @@ answer_norec_from_cache(struct worker* w
|
||||
@@ -533,8 +536,27 @@
|
||||
/* not secure */
|
||||
secure = 0;
|
||||
break;
|
||||
@@ -182,9 +178,9 @@ Index: unbound-1.7.0~rc1/daemon/worker.c
|
||||
+ }
|
||||
+#endif
|
||||
/* return this delegation from the cache */
|
||||
edns_bak = *edns;
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
@@ -689,6 +711,23 @@ answer_from_cache(struct worker* worker,
|
||||
@@ -702,6 +724,23 @@
|
||||
secure = 0;
|
||||
}
|
||||
} else secure = 0;
|
||||
@@ -206,9 +202,9 @@ Index: unbound-1.7.0~rc1/daemon/worker.c
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
edns_bak = *edns;
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
@@ -1291,6 +1330,15 @@ worker_handle_request(struct comm_point*
|
||||
@@ -1407,6 +1446,15 @@
|
||||
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
|
||||
&repinfo->addr, repinfo->addrlen);
|
||||
goto send_reply;
|
||||
@@ -224,7 +220,7 @@ Index: unbound-1.7.0~rc1/daemon/worker.c
|
||||
}
|
||||
|
||||
/* If we've found a local alias, replace the qname with the alias
|
||||
@@ -1339,12 +1387,21 @@ lookup_cache:
|
||||
@@ -1455,12 +1503,21 @@
|
||||
h = query_info_hash(lookup_qinfo, sldns_buffer_read_u16_at(c->buffer, 2));
|
||||
if((e=slabhash_lookup(worker->env.msg_cache, h, lookup_qinfo, 0))) {
|
||||
/* answer from cache - we have acquired a readlock on it */
|
||||
@@ -248,7 +244,7 @@ Index: unbound-1.7.0~rc1/daemon/worker.c
|
||||
/* prefetch it if the prefetch TTL expired.
|
||||
* Note that if there is more than one pass
|
||||
* its qname must be that used for cache
|
||||
@@ -1398,11 +1455,19 @@ lookup_cache:
|
||||
@@ -1514,11 +1571,19 @@
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
if(!LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) {
|
||||
@@ -270,14 +266,14 @@ Index: unbound-1.7.0~rc1/daemon/worker.c
|
||||
goto send_reply;
|
||||
}
|
||||
verbose(VERB_ALGO, "answer norec from cache -- "
|
||||
Index: unbound-1.7.0~rc1/doc/unbound.conf.5.in
|
||||
Index: unboundfastrpz/doc/unbound.conf.5.in
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/doc/unbound.conf.5.in
|
||||
+++ unbound-1.7.0~rc1/doc/unbound.conf.5.in
|
||||
@@ -1581,6 +1581,81 @@ It must be /96 or shorter. The default
|
||||
.B dns64\-synthall: \fI<yes or no>\fR
|
||||
Debug option, default no. If enabled, synthesize all AAAA records
|
||||
despite the presence of actual AAAA records.
|
||||
--- unboundfastrpz/doc/unbound.conf.5.in (revision 4987)
|
||||
+++ unboundfastrpz/doc/unbound.conf.5.in (working copy)
|
||||
@@ -1745,6 +1745,81 @@
|
||||
used by dns64 processing instead. Can be entered multiple times, list a
|
||||
new domain for which it applies, one per line. Applies also to names
|
||||
underneath the name given.
|
||||
+.SS "Response Policy Zone Rewriting"
|
||||
+.LP
|
||||
+Response policy zone rewriting is controlled with the
|
||||
@@ -356,10 +352,10 @@ Index: unbound-1.7.0~rc1/doc/unbound.conf.5.in
|
||||
.SS "DNSCrypt Options"
|
||||
.LP
|
||||
The
|
||||
Index: unbound-1.7.0~rc1/fastrpz/librpz.h
|
||||
Index: unboundfastrpz/fastrpz/librpz.h
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ unbound-1.7.0~rc1/fastrpz/librpz.h
|
||||
--- unboundfastrpz/fastrpz/librpz.h (nonexistent)
|
||||
+++ unboundfastrpz/fastrpz/librpz.h (working copy)
|
||||
@@ -0,0 +1,957 @@
|
||||
+/*
|
||||
+ * Define the interface from a DNS resolver to the Response Policy Zone
|
||||
@@ -1318,11 +1314,11 @@ Index: unbound-1.7.0~rc1/fastrpz/librpz.h
|
||||
+#endif /* LIBRPZ_LIB_OPEN */
|
||||
+
|
||||
+#endif /* LIBRPZ_H */
|
||||
Index: unbound-1.7.0~rc1/fastrpz/rpz.c
|
||||
Index: unboundfastrpz/fastrpz/rpz.c
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ unbound-1.7.0~rc1/fastrpz/rpz.c
|
||||
@@ -0,0 +1,1357 @@
|
||||
--- unboundfastrpz/fastrpz/rpz.c (nonexistent)
|
||||
+++ unboundfastrpz/fastrpz/rpz.c (working copy)
|
||||
@@ -0,0 +1,1352 @@
|
||||
+/*
|
||||
+ * fastrpz/rpz.c - interface to the fastrpz response policy zone library
|
||||
+ *
|
||||
@@ -1438,8 +1434,6 @@ Index: unbound-1.7.0~rc1/fastrpz/rpz.c
|
||||
+static void
|
||||
+log_fnc(librpz_log_level_t level, void* ATTR_UNUSED(ctx), const char* buf)
|
||||
+{
|
||||
+ char label_buf[sizeof("rpz ")+8];
|
||||
+
|
||||
+ /* Setting librpz_log_level overrides the unbound "verbose" level. */
|
||||
+ if(level > LIBRPZ_LOG_TRACE1 &&
|
||||
+ level <= librpz->log_level_val(LIBRPZ_LOG_INVALID))
|
||||
@@ -1949,12 +1943,9 @@ Index: unbound-1.7.0~rc1/fastrpz/rpz.c
|
||||
+ case st_ck_ns:
|
||||
+ /* An NSDNAME or NSIP check failed for lack of cached data. */
|
||||
+ return false;
|
||||
+#pragma clang diagnostic push
|
||||
+#pragma clang diagnostic ignored "-Wunreachable-code"
|
||||
+ default:
|
||||
+ fatal_exit("impossible RPZ state %d in rpz_worker_cache()",
|
||||
+ rpz->st);
|
||||
+#pragma clang diagnostic pop
|
||||
+ }
|
||||
+
|
||||
+ /* Wait for a trigger. */
|
||||
@@ -2680,10 +2671,10 @@ Index: unbound-1.7.0~rc1/fastrpz/rpz.c
|
||||
+}
|
||||
+
|
||||
+#endif /* ENABLE_FASTRPZ */
|
||||
Index: unbound-1.7.0~rc1/fastrpz/rpz.h
|
||||
Index: unboundfastrpz/fastrpz/rpz.h
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ unbound-1.7.0~rc1/fastrpz/rpz.h
|
||||
--- unboundfastrpz/fastrpz/rpz.h (nonexistent)
|
||||
+++ unboundfastrpz/fastrpz/rpz.h (working copy)
|
||||
@@ -0,0 +1,138 @@
|
||||
+/*
|
||||
+ * fastrpz/rpz.h - interface to the fastrpz response policy zone library
|
||||
@@ -2823,10 +2814,10 @@ Index: unbound-1.7.0~rc1/fastrpz/rpz.h
|
||||
+
|
||||
+#endif /* ENABLE_FASTRPZ */
|
||||
+#endif /* UNBOUND_FASTRPZ_RPZ_H */
|
||||
Index: unbound-1.7.0~rc1/fastrpz/rpz.m4
|
||||
Index: unboundfastrpz/fastrpz/rpz.m4
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ unbound-1.7.0~rc1/fastrpz/rpz.m4
|
||||
--- unboundfastrpz/fastrpz/rpz.m4 (nonexistent)
|
||||
+++ unboundfastrpz/fastrpz/rpz.m4 (working copy)
|
||||
@@ -0,0 +1,64 @@
|
||||
+# fastrpz/rpz.m4
|
||||
+
|
||||
@@ -2892,10 +2883,10 @@ Index: unbound-1.7.0~rc1/fastrpz/rpz.m4
|
||||
+ AC_MSG_WARN([[dlopen and librpz.so needed for fastrpz]])
|
||||
+ fi
|
||||
+])
|
||||
Index: unbound-1.7.0~rc1/iterator/iterator.c
|
||||
Index: unboundfastrpz/iterator/iterator.c
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/iterator/iterator.c
|
||||
+++ unbound-1.7.0~rc1/iterator/iterator.c
|
||||
--- unboundfastrpz/iterator/iterator.c (revision 4987)
|
||||
+++ unboundfastrpz/iterator/iterator.c (working copy)
|
||||
@@ -68,6 +68,9 @@
|
||||
#include "sldns/str2wire.h"
|
||||
#include "sldns/parseutil.h"
|
||||
@@ -2904,9 +2895,9 @@ Index: unbound-1.7.0~rc1/iterator/iterator.c
|
||||
+#include "fastrpz/rpz.h"
|
||||
+#endif
|
||||
|
||||
int
|
||||
iter_init(struct module_env* env, int id)
|
||||
@@ -511,6 +514,23 @@ handle_cname_response(struct module_qsta
|
||||
/* in msec */
|
||||
int UNKNOWN_SERVER_NICENESS = 376;
|
||||
@@ -551,6 +554,23 @@
|
||||
if(ntohs(r->rk.type) == LDNS_RR_TYPE_CNAME &&
|
||||
query_dname_compare(*mname, r->rk.dname) == 0 &&
|
||||
!iter_find_rrset_in_prepend_answer(iq, r)) {
|
||||
@@ -2930,7 +2921,7 @@ Index: unbound-1.7.0~rc1/iterator/iterator.c
|
||||
/* Add this relevant CNAME rrset to the prepend list.*/
|
||||
if(!iter_add_prepend_answer(qstate, iq, r))
|
||||
return 0;
|
||||
@@ -519,6 +539,9 @@ handle_cname_response(struct module_qsta
|
||||
@@ -559,6 +579,9 @@
|
||||
|
||||
/* Other rrsets in the section are ignored. */
|
||||
}
|
||||
@@ -2940,7 +2931,7 @@ Index: unbound-1.7.0~rc1/iterator/iterator.c
|
||||
/* add authority rrsets to authority prepend, for wildcarded CNAMEs */
|
||||
for(i=msg->rep->an_numrrsets; i<msg->rep->an_numrrsets +
|
||||
msg->rep->ns_numrrsets; i++) {
|
||||
@@ -1148,6 +1171,7 @@ processInitRequest(struct module_qstate*
|
||||
@@ -1195,6 +1218,7 @@
|
||||
uint8_t* delname;
|
||||
size_t delnamelen;
|
||||
struct dns_msg* msg = NULL;
|
||||
@@ -2948,7 +2939,7 @@ Index: unbound-1.7.0~rc1/iterator/iterator.c
|
||||
|
||||
log_query_info(VERB_DETAIL, "resolving", &qstate->qinfo);
|
||||
/* check effort */
|
||||
@@ -1223,8 +1247,7 @@ processInitRequest(struct module_qstate*
|
||||
@@ -1281,8 +1305,7 @@
|
||||
}
|
||||
if(msg) {
|
||||
/* handle positive cache response */
|
||||
@@ -2958,7 +2949,7 @@ Index: unbound-1.7.0~rc1/iterator/iterator.c
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
log_dns_msg("msg from cache lookup", &msg->qinfo,
|
||||
msg->rep);
|
||||
@@ -1232,7 +1255,22 @@ processInitRequest(struct module_qstate*
|
||||
@@ -1290,7 +1313,22 @@
|
||||
(int)msg->rep->ttl,
|
||||
(int)msg->rep->prefetch_ttl);
|
||||
}
|
||||
@@ -2981,7 +2972,7 @@ Index: unbound-1.7.0~rc1/iterator/iterator.c
|
||||
if(type == RESPONSE_TYPE_CNAME) {
|
||||
uint8_t* sname = 0;
|
||||
size_t slen = 0;
|
||||
@@ -2552,6 +2590,62 @@ processQueryResponse(struct module_qstat
|
||||
@@ -2695,6 +2733,62 @@
|
||||
sock_list_insert(&qstate->reply_origin,
|
||||
&qstate->reply->addr, qstate->reply->addrlen,
|
||||
qstate->region);
|
||||
@@ -3041,10 +3032,10 @@ Index: unbound-1.7.0~rc1/iterator/iterator.c
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
if(iq->minimisation_state != DONOT_MINIMISE_STATE) {
|
||||
if(iq->minimisation_state != DONOT_MINIMISE_STATE
|
||||
&& !(iq->chase_flags & BIT_RD)) {
|
||||
if(FLAGS_GET_RCODE(iq->response->rep->flags) !=
|
||||
LDNS_RCODE_NOERROR) {
|
||||
@@ -3273,12 +3367,44 @@ processFinished(struct module_qstate* qs
|
||||
@@ -3441,6 +3535,10 @@
|
||||
* but only if we did recursion. The nonrecursion referral
|
||||
* from cache does not need to be stored in the msg cache. */
|
||||
if(!qstate->no_cache_store && qstate->query_flags&BIT_RD) {
|
||||
@@ -3055,6 +3046,7 @@ Index: unbound-1.7.0~rc1/iterator/iterator.c
|
||||
iter_dns_store(qstate->env, &qstate->qinfo,
|
||||
iq->response->rep, 0, qstate->prefetch_leeway,
|
||||
iq->dp&&iq->dp->has_parent_side_NS,
|
||||
@@ -3447,6 +3545,34 @@
|
||||
qstate->region, qstate->query_flags);
|
||||
}
|
||||
}
|
||||
@@ -3089,11 +3081,11 @@ Index: unbound-1.7.0~rc1/iterator/iterator.c
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
qstate->return_msg = iq->response;
|
||||
return 0;
|
||||
Index: unbound-1.7.0~rc1/iterator/iterator.h
|
||||
Index: unboundfastrpz/iterator/iterator.h
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/iterator/iterator.h
|
||||
+++ unbound-1.7.0~rc1/iterator/iterator.h
|
||||
@@ -383,6 +383,16 @@ struct iter_qstate {
|
||||
--- unboundfastrpz/iterator/iterator.h (revision 4987)
|
||||
+++ unboundfastrpz/iterator/iterator.h (working copy)
|
||||
@@ -386,6 +386,16 @@
|
||||
*/
|
||||
int minimise_count;
|
||||
|
||||
@@ -3110,11 +3102,11 @@ Index: unbound-1.7.0~rc1/iterator/iterator.h
|
||||
/**
|
||||
* Count number of time-outs. Used to prevent resolving failures when
|
||||
* the QNAME minimisation QTYPE is blocked. */
|
||||
Index: unbound-1.7.0~rc1/services/cache/dns.c
|
||||
Index: unboundfastrpz/services/cache/dns.c
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/services/cache/dns.c
|
||||
+++ unbound-1.7.0~rc1/services/cache/dns.c
|
||||
@@ -876,6 +876,14 @@ dns_cache_store(struct module_env* env,
|
||||
--- unboundfastrpz/services/cache/dns.c (revision 4987)
|
||||
+++ unboundfastrpz/services/cache/dns.c (working copy)
|
||||
@@ -939,6 +939,14 @@
|
||||
struct regional* region, uint32_t flags)
|
||||
{
|
||||
struct reply_info* rep = NULL;
|
||||
@@ -3129,11 +3121,11 @@ Index: unbound-1.7.0~rc1/services/cache/dns.c
|
||||
/* alloc, malloc properly (not in region, like msg is) */
|
||||
rep = reply_info_copy(msgrep, env->alloc, NULL);
|
||||
if(!rep)
|
||||
Index: unbound-1.7.0~rc1/services/mesh.c
|
||||
Index: unboundfastrpz/services/mesh.c
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/services/mesh.c
|
||||
+++ unbound-1.7.0~rc1/services/mesh.c
|
||||
@@ -59,6 +59,9 @@
|
||||
--- unboundfastrpz/services/mesh.c (revision 4987)
|
||||
+++ unboundfastrpz/services/mesh.c (working copy)
|
||||
@@ -60,6 +60,9 @@
|
||||
#include "sldns/wire2str.h"
|
||||
#include "services/localzone.h"
|
||||
#include "util/data/dname.h"
|
||||
@@ -3143,7 +3135,7 @@ Index: unbound-1.7.0~rc1/services/mesh.c
|
||||
#include "respip/respip.h"
|
||||
|
||||
/** subtract timers and the values do not overflow or become negative */
|
||||
@@ -1050,6 +1053,13 @@ mesh_send_reply(struct mesh_state* m, in
|
||||
@@ -1057,6 +1060,13 @@
|
||||
else secure = 0;
|
||||
if(!rep && rcode == LDNS_RCODE_NOERROR)
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
@@ -3157,7 +3149,7 @@ Index: unbound-1.7.0~rc1/services/mesh.c
|
||||
/* send the reply */
|
||||
/* We don't reuse the encoded answer if either the previous or current
|
||||
* response has a local alias. We could compare the alias records
|
||||
@@ -1199,6 +1209,7 @@ struct mesh_state* mesh_area_find(struct
|
||||
@@ -1230,6 +1240,7 @@
|
||||
key.s.is_valrec = valrec;
|
||||
key.s.qinfo = *qinfo;
|
||||
key.s.query_flags = qflags;
|
||||
@@ -3165,7 +3157,7 @@ Index: unbound-1.7.0~rc1/services/mesh.c
|
||||
/* We are searching for a similar mesh state when we DO want to
|
||||
* aggregate the state. Thus unique is set to NULL. (default when we
|
||||
* desire aggregation).*/
|
||||
@@ -1245,6 +1256,10 @@ int mesh_state_add_reply(struct mesh_sta
|
||||
@@ -1276,6 +1287,10 @@
|
||||
if(!r)
|
||||
return 0;
|
||||
r->query_reply = *rep;
|
||||
@@ -3176,11 +3168,11 @@ Index: unbound-1.7.0~rc1/services/mesh.c
|
||||
r->edns = *edns;
|
||||
if(edns->opt_list) {
|
||||
r->edns.opt_list = edns_opt_copy_region(edns->opt_list,
|
||||
Index: unbound-1.7.0~rc1/util/config_file.c
|
||||
Index: unboundfastrpz/util/config_file.c
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/util/config_file.c
|
||||
+++ unbound-1.7.0~rc1/util/config_file.c
|
||||
@@ -1323,6 +1323,8 @@ config_delete(struct config_file* cfg)
|
||||
--- unboundfastrpz/util/config_file.c (revision 4987)
|
||||
+++ unboundfastrpz/util/config_file.c (working copy)
|
||||
@@ -1401,6 +1401,8 @@
|
||||
free(cfg->dnstap_socket_path);
|
||||
free(cfg->dnstap_identity);
|
||||
free(cfg->dnstap_version);
|
||||
@@ -3189,11 +3181,11 @@ Index: unbound-1.7.0~rc1/util/config_file.c
|
||||
config_deldblstrlist(cfg->ratelimit_for_domain);
|
||||
config_deldblstrlist(cfg->ratelimit_below_domain);
|
||||
#ifdef USE_IPSECMOD
|
||||
Index: unbound-1.7.0~rc1/util/config_file.h
|
||||
Index: unboundfastrpz/util/config_file.h
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/util/config_file.h
|
||||
+++ unbound-1.7.0~rc1/util/config_file.h
|
||||
@@ -431,6 +431,11 @@ struct config_file {
|
||||
--- unboundfastrpz/util/config_file.h (revision 4987)
|
||||
+++ unboundfastrpz/util/config_file.h (working copy)
|
||||
@@ -480,6 +480,11 @@
|
||||
/** true to disable DNSSEC lameness check in iterator */
|
||||
int disable_dnssec_lame_check;
|
||||
|
||||
@@ -3205,11 +3197,11 @@ Index: unbound-1.7.0~rc1/util/config_file.h
|
||||
/** ratelimit for ip addresses. 0 is off, otherwise qps (unless overridden) */
|
||||
int ip_ratelimit;
|
||||
/** number of slabs for ip_ratelimit cache */
|
||||
Index: unbound-1.7.0~rc1/util/configlexer.lex
|
||||
Index: unboundfastrpz/util/configlexer.lex
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/util/configlexer.lex
|
||||
+++ unbound-1.7.0~rc1/util/configlexer.lex
|
||||
@@ -412,6 +412,10 @@ dnstap-log-forwarder-query-messages{COLO
|
||||
--- unboundfastrpz/util/configlexer.lex (revision 4987)
|
||||
+++ unboundfastrpz/util/configlexer.lex (working copy)
|
||||
@@ -434,6 +434,10 @@
|
||||
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES) }
|
||||
dnstap-log-forwarder-response-messages{COLON} {
|
||||
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES) }
|
||||
@@ -3220,11 +3212,11 @@ Index: unbound-1.7.0~rc1/util/configlexer.lex
|
||||
disable-dnssec-lame-check{COLON} { YDVAR(1, VAR_DISABLE_DNSSEC_LAME_CHECK) }
|
||||
ip-ratelimit{COLON} { YDVAR(1, VAR_IP_RATELIMIT) }
|
||||
ratelimit{COLON} { YDVAR(1, VAR_RATELIMIT) }
|
||||
Index: unbound-1.7.0~rc1/util/configparser.y
|
||||
Index: unboundfastrpz/util/configparser.y
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/util/configparser.y
|
||||
+++ unbound-1.7.0~rc1/util/configparser.y
|
||||
@@ -124,6 +124,7 @@ extern struct config_parser_state* cfg_p
|
||||
--- unboundfastrpz/util/configparser.y (revision 4987)
|
||||
+++ unboundfastrpz/util/configparser.y (working copy)
|
||||
@@ -125,6 +125,7 @@
|
||||
%token VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES
|
||||
%token VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES
|
||||
%token VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES
|
||||
@@ -3232,7 +3224,7 @@ Index: unbound-1.7.0~rc1/util/configparser.y
|
||||
%token VAR_RESPONSE_IP_TAG VAR_RESPONSE_IP VAR_RESPONSE_IP_DATA
|
||||
%token VAR_HARDEN_ALGO_DOWNGRADE VAR_IP_TRANSPARENT
|
||||
%token VAR_DISABLE_DNSSEC_LAME_CHECK
|
||||
@@ -158,7 +159,7 @@ extern struct config_parser_state* cfg_p
|
||||
@@ -168,7 +169,7 @@
|
||||
|
||||
%%
|
||||
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
|
||||
@@ -3241,7 +3233,7 @@ Index: unbound-1.7.0~rc1/util/configparser.y
|
||||
forwardstart contents_forward | pythonstart contents_py |
|
||||
rcstart contents_rc | dtstart contents_dt | viewstart contents_view |
|
||||
dnscstart contents_dnsc | cachedbstart contents_cachedb |
|
||||
@@ -2384,6 +2385,50 @@ dt_dnstap_log_forwarder_response_message
|
||||
@@ -2639,6 +2640,50 @@
|
||||
(strcmp($2, "yes")==0);
|
||||
}
|
||||
;
|
||||
@@ -3269,7 +3261,7 @@ Index: unbound-1.7.0~rc1/util/configparser.y
|
||||
+
|
||||
+ OUTYY(("P(rpz_zone:%s)\n", $2));
|
||||
+ old_cstr = cfg_parser->cfg->rpz_cstr;
|
||||
+ asprintf(&new_cstr, "%s\nzone %s", old_cstr?old_cstr:"", $2);
|
||||
+ (void)asprintf(&new_cstr, "%s\nzone %s", old_cstr?old_cstr:"", $2);
|
||||
+ if(!new_cstr)
|
||||
+ yyerror("out of memory");
|
||||
+ free(old_cstr);
|
||||
@@ -3282,7 +3274,7 @@ Index: unbound-1.7.0~rc1/util/configparser.y
|
||||
+
|
||||
+ OUTYY(("P(rpz_option:%s)\n", $2));
|
||||
+ old_cstr = cfg_parser->cfg->rpz_cstr;
|
||||
+ asprintf(&new_cstr, "%s\n%s", old_cstr ? old_cstr : "", $2);
|
||||
+ (void)asprintf(&new_cstr, "%s\n%s", old_cstr ? old_cstr : "", $2);
|
||||
+ if(!new_cstr)
|
||||
+ yyerror("out of memory");
|
||||
+ free(old_cstr);
|
||||
@@ -3292,11 +3284,11 @@ Index: unbound-1.7.0~rc1/util/configparser.y
|
||||
pythonstart: VAR_PYTHON
|
||||
{
|
||||
OUTYY(("\nP(python:)\n"));
|
||||
Index: unbound-1.7.0~rc1/util/data/msgencode.c
|
||||
Index: unboundfastrpz/util/data/msgencode.c
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/util/data/msgencode.c
|
||||
+++ unbound-1.7.0~rc1/util/data/msgencode.c
|
||||
@@ -585,6 +585,35 @@ insert_section(struct reply_info* rep, s
|
||||
--- unboundfastrpz/util/data/msgencode.c (revision 4987)
|
||||
+++ unboundfastrpz/util/data/msgencode.c (working copy)
|
||||
@@ -590,6 +590,35 @@
|
||||
return RETVAL_OK;
|
||||
}
|
||||
|
||||
@@ -3332,7 +3324,7 @@ Index: unbound-1.7.0~rc1/util/data/msgencode.c
|
||||
/** store query section in wireformat buffer, return RETVAL */
|
||||
static int
|
||||
insert_query(struct query_info* qinfo, struct compress_tree_node** tree,
|
||||
@@ -750,6 +779,19 @@ reply_info_encode(struct query_info* qin
|
||||
@@ -753,6 +782,19 @@
|
||||
return 0;
|
||||
}
|
||||
sldns_buffer_write_u16_at(buffer, 10, arcount);
|
||||
@@ -3352,13 +3344,13 @@ Index: unbound-1.7.0~rc1/util/data/msgencode.c
|
||||
}
|
||||
sldns_buffer_flip(buffer);
|
||||
return 1;
|
||||
Index: unbound-1.7.0~rc1/util/data/packed_rrset.c
|
||||
Index: unboundfastrpz/util/data/packed_rrset.c
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/util/data/packed_rrset.c
|
||||
+++ unbound-1.7.0~rc1/util/data/packed_rrset.c
|
||||
@@ -254,6 +254,10 @@ sec_status_to_string(enum sec_status s)
|
||||
case sec_status_indeterminate: return "sec_status_indeterminate";
|
||||
--- unboundfastrpz/util/data/packed_rrset.c (revision 4987)
|
||||
+++ unboundfastrpz/util/data/packed_rrset.c (working copy)
|
||||
@@ -255,6 +255,10 @@
|
||||
case sec_status_insecure: return "sec_status_insecure";
|
||||
case sec_status_secure_sentinel_fail: return "sec_status_secure_sentinel_fail";
|
||||
case sec_status_secure: return "sec_status_secure";
|
||||
+#ifdef ENABLE_FASTRPZ
|
||||
+ case sec_status_rpz_rewritten: return "sec_status_rpz_rewritten";
|
||||
@@ -3367,12 +3359,12 @@ Index: unbound-1.7.0~rc1/util/data/packed_rrset.c
|
||||
}
|
||||
return "unknown_sec_status_value";
|
||||
}
|
||||
Index: unbound-1.7.0~rc1/util/data/packed_rrset.h
|
||||
Index: unboundfastrpz/util/data/packed_rrset.h
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/util/data/packed_rrset.h
|
||||
+++ unbound-1.7.0~rc1/util/data/packed_rrset.h
|
||||
@@ -189,7 +189,15 @@ enum sec_status {
|
||||
sec_status_insecure,
|
||||
--- unboundfastrpz/util/data/packed_rrset.h (revision 4987)
|
||||
+++ unboundfastrpz/util/data/packed_rrset.h (working copy)
|
||||
@@ -193,7 +193,15 @@
|
||||
sec_status_secure_sentinel_fail,
|
||||
/** SECURE means that the object (RRset or message) validated
|
||||
* according to local policy. */
|
||||
- sec_status_secure
|
||||
@@ -3388,11 +3380,11 @@ Index: unbound-1.7.0~rc1/util/data/packed_rrset.h
|
||||
};
|
||||
|
||||
/**
|
||||
Index: unbound-1.7.0~rc1/util/netevent.c
|
||||
Index: unboundfastrpz/util/netevent.c
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/util/netevent.c
|
||||
+++ unbound-1.7.0~rc1/util/netevent.c
|
||||
@@ -54,6 +54,9 @@
|
||||
--- unboundfastrpz/util/netevent.c (revision 4987)
|
||||
+++ unboundfastrpz/util/netevent.c (working copy)
|
||||
@@ -56,6 +56,9 @@
|
||||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
@@ -3402,7 +3394,7 @@ Index: unbound-1.7.0~rc1/util/netevent.c
|
||||
|
||||
/* -------- Start of local definitions -------- */
|
||||
/** if CMSG_ALIGN is not defined on this platform, a workaround */
|
||||
@@ -585,6 +588,9 @@ comm_point_udp_ancil_callback(int fd, sh
|
||||
@@ -588,6 +591,9 @@
|
||||
struct cmsghdr* cmsg;
|
||||
#endif /* S_SPLINT_S */
|
||||
|
||||
@@ -3412,7 +3404,7 @@ Index: unbound-1.7.0~rc1/util/netevent.c
|
||||
rep.c = (struct comm_point*)arg;
|
||||
log_assert(rep.c->type == comm_udp);
|
||||
|
||||
@@ -674,6 +680,9 @@ comm_point_udp_callback(int fd, short ev
|
||||
@@ -677,6 +683,9 @@
|
||||
int i;
|
||||
struct sldns_buffer *buffer;
|
||||
|
||||
@@ -3422,7 +3414,7 @@ Index: unbound-1.7.0~rc1/util/netevent.c
|
||||
rep.c = (struct comm_point*)arg;
|
||||
log_assert(rep.c->type == comm_udp);
|
||||
|
||||
@@ -717,6 +726,9 @@ comm_point_udp_callback(int fd, short ev
|
||||
@@ -720,6 +729,9 @@
|
||||
(void)comm_point_send_udp_msg(rep.c, buffer,
|
||||
(struct sockaddr*)&rep.addr, rep.addrlen);
|
||||
}
|
||||
@@ -3432,7 +3424,7 @@ Index: unbound-1.7.0~rc1/util/netevent.c
|
||||
if(!rep.c || rep.c->fd != fd) /* commpoint closed to -1 or reused for
|
||||
another UDP port. Note rep.c cannot be reused with TCP fd. */
|
||||
break;
|
||||
@@ -2956,6 +2968,9 @@ comm_point_send_reply(struct comm_reply
|
||||
@@ -3035,6 +3047,9 @@
|
||||
comm_point_start_listening(repinfo->c, -1,
|
||||
repinfo->c->tcp_timeout_msec);
|
||||
}
|
||||
@@ -3442,7 +3434,7 @@ Index: unbound-1.7.0~rc1/util/netevent.c
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2965,6 +2980,9 @@ comm_point_drop_reply(struct comm_reply*
|
||||
@@ -3044,6 +3059,9 @@
|
||||
return;
|
||||
log_assert(repinfo && repinfo->c);
|
||||
log_assert(repinfo->c->type != comm_tcp_accept);
|
||||
@@ -3452,7 +3444,7 @@ Index: unbound-1.7.0~rc1/util/netevent.c
|
||||
if(repinfo->c->type == comm_udp)
|
||||
return;
|
||||
reclaim_tcp_handler(repinfo->c);
|
||||
@@ -2984,6 +3002,9 @@ comm_point_start_listening(struct comm_p
|
||||
@@ -3063,6 +3081,9 @@
|
||||
{
|
||||
verbose(VERB_ALGO, "comm point start listening %d",
|
||||
c->fd==-1?newfd:c->fd);
|
||||
@@ -3462,11 +3454,11 @@ Index: unbound-1.7.0~rc1/util/netevent.c
|
||||
if(c->type == comm_tcp_accept && !c->tcp_free) {
|
||||
/* no use to start listening no free slots. */
|
||||
return;
|
||||
Index: unbound-1.7.0~rc1/util/netevent.h
|
||||
Index: unboundfastrpz/util/netevent.h
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/util/netevent.h
|
||||
+++ unbound-1.7.0~rc1/util/netevent.h
|
||||
@@ -119,6 +119,10 @@ struct comm_reply {
|
||||
--- unboundfastrpz/util/netevent.h (revision 4987)
|
||||
+++ unboundfastrpz/util/netevent.h (working copy)
|
||||
@@ -120,6 +120,10 @@
|
||||
/** return type 0 (none), 4(IP4), 6(IP6) */
|
||||
int srctype;
|
||||
/* DnsCrypt context */
|
||||
@@ -3477,11 +3469,11 @@ Index: unbound-1.7.0~rc1/util/netevent.h
|
||||
#ifdef USE_DNSCRYPT
|
||||
uint8_t client_nonce[crypto_box_HALF_NONCEBYTES];
|
||||
uint8_t nmkey[crypto_box_BEFORENMBYTES];
|
||||
Index: unbound-1.7.0~rc1/validator/validator.c
|
||||
Index: unboundfastrpz/validator/validator.c
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/validator/validator.c
|
||||
+++ unbound-1.7.0~rc1/validator/validator.c
|
||||
@@ -2688,6 +2688,12 @@ ds_response_to_ke(struct module_qstate*
|
||||
--- unboundfastrpz/validator/validator.c (revision 4987)
|
||||
+++ unboundfastrpz/validator/validator.c (working copy)
|
||||
@@ -2755,6 +2755,12 @@
|
||||
default:
|
||||
/* NSEC proof did not work, try next */
|
||||
break;
|
||||
@@ -3494,7 +3486,7 @@ Index: unbound-1.7.0~rc1/validator/validator.c
|
||||
}
|
||||
|
||||
sec = nsec3_prove_nods(qstate->env, ve,
|
||||
@@ -2721,6 +2727,12 @@ ds_response_to_ke(struct module_qstate*
|
||||
@@ -2788,6 +2794,12 @@
|
||||
default:
|
||||
/* NSEC3 proof did not work */
|
||||
break;
|
||||
@@ -3507,4 +3499,3 @@ Index: unbound-1.7.0~rc1/validator/validator.c
|
||||
}
|
||||
|
||||
/* Apparently, no available NSEC/NSEC3 proved NODATA, so
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@ Name: unbound
|
||||
Description: Library with validating, recursive, and caching DNS resolver
|
||||
URL: http://www.unbound.net
|
||||
Version: @PACKAGE_VERSION@
|
||||
Requires: libcrypto libssl @PC_LIBEVENT_DEPENDENCY@ @PC_PY_DEPENDENCY@
|
||||
Libs: -L${libdir} -lunbound
|
||||
Requires: libcrypto libssl @PC_LIBEVENT_DEPENDENCY@
|
||||
Requires.private: @PC_PY_DEPENDENCY@
|
||||
Libs: -L${libdir} -lunbound -lssl -lcrypto
|
||||
Libs.private: @SSLLIB@ @LIBS@
|
||||
Cflags: -I${includedir}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
[Unit]
|
||||
Description=Validating, recursive, and caching DNS resolver
|
||||
Documentation=man:unbound(8)
|
||||
After=network.target
|
||||
Before=network-online.target nss-lookup.target
|
||||
Wants=nss-lookup.target
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -10,7 +13,7 @@ ExecReload=/bin/kill -HUP $MAINPID
|
||||
ExecStart=@UNBOUND_SBIN_DIR@/unbound
|
||||
NotifyAccess=main
|
||||
Type=notify
|
||||
CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT
|
||||
CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE
|
||||
MemoryDenyWriteExecute=true
|
||||
NoNewPrivileges=true
|
||||
PrivateDevices=true
|
||||
@@ -21,7 +24,7 @@ ProtectKernelModules=true
|
||||
ProtectKernelTunables=true
|
||||
ProtectSystem=strict
|
||||
ReadWritePaths=@UNBOUND_SYSCONF_DIR@ @UNBOUND_LOCALSTATE_DIR@ /run @UNBOUND_RUN_DIR@
|
||||
RestrictAddressFamilies=AF_INET AF_UNIX
|
||||
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
|
||||
RestrictRealtime=true
|
||||
SystemCallArchitectures=native
|
||||
SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module mount @obsolete @resources
|
||||
|
||||
@@ -111,6 +111,8 @@ acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
|
||||
control = acl_refuse_non_local;
|
||||
else if(strcmp(s2, "allow_snoop") == 0)
|
||||
control = acl_allow_snoop;
|
||||
else if(strcmp(s2, "allow_setrd") == 0)
|
||||
control = acl_allow_setrd;
|
||||
else {
|
||||
log_err("access control type %s unknown", str);
|
||||
return 0;
|
||||
|
||||
+3
-1
@@ -63,7 +63,9 @@ enum acl_access {
|
||||
/** allow full access for recursion (+RD) queries */
|
||||
acl_allow,
|
||||
/** allow full access for all queries, recursion and cache snooping */
|
||||
acl_allow_snoop
|
||||
acl_allow_snoop,
|
||||
/** allow full access for recursion queries and set RD flag regardless of request */
|
||||
acl_allow_setrd
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+22
-21
@@ -62,7 +62,7 @@
|
||||
|
||||
/** dump one rrset zonefile line */
|
||||
static int
|
||||
dump_rrset_line(SSL* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i)
|
||||
dump_rrset_line(RES* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i)
|
||||
{
|
||||
char s[65535];
|
||||
if(!packed_rr_to_string(k, i, now, s, sizeof(s))) {
|
||||
@@ -73,7 +73,7 @@ dump_rrset_line(SSL* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i)
|
||||
|
||||
/** dump rrset key and data info */
|
||||
static int
|
||||
dump_rrset(SSL* ssl, struct ub_packed_rrset_key* k,
|
||||
dump_rrset(RES* ssl, struct ub_packed_rrset_key* k,
|
||||
struct packed_rrset_data* d, time_t now)
|
||||
{
|
||||
size_t i;
|
||||
@@ -99,7 +99,7 @@ dump_rrset(SSL* ssl, struct ub_packed_rrset_key* k,
|
||||
|
||||
/** dump lruhash rrset cache */
|
||||
static int
|
||||
dump_rrset_lruhash(SSL* ssl, struct lruhash* h, time_t now)
|
||||
dump_rrset_lruhash(RES* ssl, struct lruhash* h, time_t now)
|
||||
{
|
||||
struct lruhash_entry* e;
|
||||
/* lruhash already locked by caller */
|
||||
@@ -118,7 +118,7 @@ dump_rrset_lruhash(SSL* ssl, struct lruhash* h, time_t now)
|
||||
|
||||
/** dump rrset cache */
|
||||
static int
|
||||
dump_rrset_cache(SSL* ssl, struct worker* worker)
|
||||
dump_rrset_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
struct rrset_cache* r = worker->env.rrset_cache;
|
||||
size_t slab;
|
||||
@@ -137,7 +137,7 @@ dump_rrset_cache(SSL* ssl, struct worker* worker)
|
||||
|
||||
/** dump message to rrset reference */
|
||||
static int
|
||||
dump_msg_ref(SSL* ssl, struct ub_packed_rrset_key* k)
|
||||
dump_msg_ref(RES* ssl, struct ub_packed_rrset_key* k)
|
||||
{
|
||||
char* nm, *tp, *cl;
|
||||
nm = sldns_wire2str_dname(k->rk.dname, k->rk.dname_len);
|
||||
@@ -164,7 +164,7 @@ dump_msg_ref(SSL* ssl, struct ub_packed_rrset_key* k)
|
||||
|
||||
/** dump message entry */
|
||||
static int
|
||||
dump_msg(SSL* ssl, struct query_info* k, struct reply_info* d,
|
||||
dump_msg(RES* ssl, struct query_info* k, struct reply_info* d,
|
||||
time_t now)
|
||||
{
|
||||
size_t i;
|
||||
@@ -246,7 +246,7 @@ copy_msg(struct regional* region, struct lruhash_entry* e,
|
||||
|
||||
/** dump lruhash msg cache */
|
||||
static int
|
||||
dump_msg_lruhash(SSL* ssl, struct worker* worker, struct lruhash* h)
|
||||
dump_msg_lruhash(RES* ssl, struct worker* worker, struct lruhash* h)
|
||||
{
|
||||
struct lruhash_entry* e;
|
||||
struct query_info* k;
|
||||
@@ -274,7 +274,7 @@ dump_msg_lruhash(SSL* ssl, struct worker* worker, struct lruhash* h)
|
||||
|
||||
/** dump msg cache */
|
||||
static int
|
||||
dump_msg_cache(SSL* ssl, struct worker* worker)
|
||||
dump_msg_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
struct slabhash* sh = worker->env.msg_cache;
|
||||
size_t slab;
|
||||
@@ -291,7 +291,7 @@ dump_msg_cache(SSL* ssl, struct worker* worker)
|
||||
}
|
||||
|
||||
int
|
||||
dump_cache(SSL* ssl, struct worker* worker)
|
||||
dump_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
if(!dump_rrset_cache(ssl, worker))
|
||||
return 0;
|
||||
@@ -302,7 +302,7 @@ dump_cache(SSL* ssl, struct worker* worker)
|
||||
|
||||
/** read a line from ssl into buffer */
|
||||
static int
|
||||
ssl_read_buf(SSL* ssl, sldns_buffer* buf)
|
||||
ssl_read_buf(RES* ssl, sldns_buffer* buf)
|
||||
{
|
||||
return ssl_read_line(ssl, (char*)sldns_buffer_begin(buf),
|
||||
sldns_buffer_capacity(buf));
|
||||
@@ -310,7 +310,7 @@ ssl_read_buf(SSL* ssl, sldns_buffer* buf)
|
||||
|
||||
/** check fixed text on line */
|
||||
static int
|
||||
read_fixed(SSL* ssl, sldns_buffer* buf, const char* str)
|
||||
read_fixed(RES* ssl, sldns_buffer* buf, const char* str)
|
||||
{
|
||||
if(!ssl_read_buf(ssl, buf)) return 0;
|
||||
return (strcmp((char*)sldns_buffer_begin(buf), str) == 0);
|
||||
@@ -318,7 +318,7 @@ read_fixed(SSL* ssl, sldns_buffer* buf, const char* str)
|
||||
|
||||
/** load an RR into rrset */
|
||||
static int
|
||||
load_rr(SSL* ssl, sldns_buffer* buf, struct regional* region,
|
||||
load_rr(RES* ssl, sldns_buffer* buf, struct regional* region,
|
||||
struct ub_packed_rrset_key* rk, struct packed_rrset_data* d,
|
||||
unsigned int i, int is_rrsig, int* go_on, time_t now)
|
||||
{
|
||||
@@ -435,7 +435,7 @@ move_into_cache(struct ub_packed_rrset_key* k,
|
||||
|
||||
/** load an rrset entry */
|
||||
static int
|
||||
load_rrset(SSL* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
load_rrset(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
{
|
||||
char* s = (char*)sldns_buffer_begin(buf);
|
||||
struct regional* region = worker->scratchpad;
|
||||
@@ -519,7 +519,7 @@ load_rrset(SSL* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
|
||||
/** load rrset cache */
|
||||
static int
|
||||
load_rrset_cache(SSL* ssl, struct worker* worker)
|
||||
load_rrset_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
sldns_buffer* buf = worker->env.scratch_buffer;
|
||||
if(!read_fixed(ssl, buf, "START_RRSET_CACHE")) return 0;
|
||||
@@ -575,7 +575,7 @@ load_qinfo(char* str, struct query_info* qinfo, struct regional* region)
|
||||
|
||||
/** load a msg rrset reference */
|
||||
static int
|
||||
load_ref(SSL* ssl, sldns_buffer* buf, struct worker* worker,
|
||||
load_ref(RES* ssl, sldns_buffer* buf, struct worker* worker,
|
||||
struct regional *region, struct ub_packed_rrset_key** rrset,
|
||||
int* go_on)
|
||||
{
|
||||
@@ -620,7 +620,7 @@ load_ref(SSL* ssl, sldns_buffer* buf, struct worker* worker,
|
||||
|
||||
/** load a msg entry */
|
||||
static int
|
||||
load_msg(SSL* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
{
|
||||
struct regional* region = worker->scratchpad;
|
||||
struct query_info qinf;
|
||||
@@ -653,6 +653,7 @@ load_msg(SSL* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
rep.qdcount = (uint16_t)qdcount;
|
||||
rep.ttl = (time_t)ttl;
|
||||
rep.prefetch_ttl = PREFETCH_TTL_CALC(rep.ttl);
|
||||
rep.serve_expired_ttl = rep.ttl + SERVE_EXPIRED_TTL;
|
||||
rep.security = (enum sec_status)security;
|
||||
if(an > RR_COUNT_MAX || ns > RR_COUNT_MAX || ar > RR_COUNT_MAX) {
|
||||
log_warn("error too many rrsets");
|
||||
@@ -685,7 +686,7 @@ load_msg(SSL* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
|
||||
/** load msg cache */
|
||||
static int
|
||||
load_msg_cache(SSL* ssl, struct worker* worker)
|
||||
load_msg_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
sldns_buffer* buf = worker->env.scratch_buffer;
|
||||
if(!read_fixed(ssl, buf, "START_MSG_CACHE")) return 0;
|
||||
@@ -698,7 +699,7 @@ load_msg_cache(SSL* ssl, struct worker* worker)
|
||||
}
|
||||
|
||||
int
|
||||
load_cache(SSL* ssl, struct worker* worker)
|
||||
load_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
if(!load_rrset_cache(ssl, worker))
|
||||
return 0;
|
||||
@@ -709,7 +710,7 @@ load_cache(SSL* ssl, struct worker* worker)
|
||||
|
||||
/** print details on a delegation point */
|
||||
static void
|
||||
print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp)
|
||||
print_dp_details(RES* ssl, struct worker* worker, struct delegpt* dp)
|
||||
{
|
||||
char buf[257];
|
||||
struct delegpt_addr* a;
|
||||
@@ -785,7 +786,7 @@ print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp)
|
||||
|
||||
/** print main dp info */
|
||||
static void
|
||||
print_dp_main(SSL* ssl, struct delegpt* dp, struct dns_msg* msg)
|
||||
print_dp_main(RES* ssl, struct delegpt* dp, struct dns_msg* msg)
|
||||
{
|
||||
size_t i, n_ns, n_miss, n_addr, n_res, n_avail;
|
||||
|
||||
@@ -813,7 +814,7 @@ print_dp_main(SSL* ssl, struct delegpt* dp, struct dns_msg* msg)
|
||||
return;
|
||||
}
|
||||
|
||||
int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
|
||||
int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
||||
size_t nmlen, int ATTR_UNUSED(nmlabs))
|
||||
{
|
||||
/* deep links into the iterator module */
|
||||
|
||||
+4
-3
@@ -72,6 +72,7 @@
|
||||
#ifndef DAEMON_DUMPCACHE_H
|
||||
#define DAEMON_DUMPCACHE_H
|
||||
struct worker;
|
||||
#include "daemon/remote.h"
|
||||
|
||||
/**
|
||||
* Dump cache(s) to text
|
||||
@@ -80,7 +81,7 @@ struct worker;
|
||||
* ptrs to the caches.
|
||||
* @return false on ssl print error.
|
||||
*/
|
||||
int dump_cache(SSL* ssl, struct worker* worker);
|
||||
int dump_cache(RES* ssl, struct worker* worker);
|
||||
|
||||
/**
|
||||
* Load cache(s) from text
|
||||
@@ -89,7 +90,7 @@ int dump_cache(SSL* ssl, struct worker* worker);
|
||||
* ptrs to the caches.
|
||||
* @return false on ssl error.
|
||||
*/
|
||||
int load_cache(SSL* ssl, struct worker* worker);
|
||||
int load_cache(RES* ssl, struct worker* worker);
|
||||
|
||||
/**
|
||||
* Print the delegation used to lookup for this name.
|
||||
@@ -101,7 +102,7 @@ int load_cache(SSL* ssl, struct worker* worker);
|
||||
* @param nmlabs: labels in name.
|
||||
* @return false on ssl error.
|
||||
*/
|
||||
int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
|
||||
int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
||||
size_t nmlen, int nmlabs);
|
||||
|
||||
#endif /* DAEMON_DUMPCACHE_H */
|
||||
|
||||
+21
-16
@@ -76,6 +76,7 @@
|
||||
#include "util/shm_side/shm_main.h"
|
||||
#include "util/storage/lookup3.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/tcp_conn_limit.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/cache/infra.h"
|
||||
@@ -104,10 +105,8 @@ static int sig_record_reload = 0;
|
||||
/** cleaner ssl memory freeup */
|
||||
static void* comp_meth = NULL;
|
||||
#endif
|
||||
#ifdef LEX_HAS_YYLEX_DESTROY
|
||||
/** remove buffers for parsing and init */
|
||||
int ub_c_lex_destroy(void);
|
||||
#endif
|
||||
|
||||
/** used when no other sighandling happens, so we don't die
|
||||
* when multiple signals in quick succession are sent to us.
|
||||
@@ -182,15 +181,8 @@ static void
|
||||
signal_handling_playback(struct worker* wrk)
|
||||
{
|
||||
#ifdef SIGHUP
|
||||
if(sig_record_reload) {
|
||||
# ifdef HAVE_SYSTEMD
|
||||
sd_notify(0, "RELOADING=1");
|
||||
# endif
|
||||
if(sig_record_reload)
|
||||
worker_sighandler(SIGHUP, wrk);
|
||||
# ifdef HAVE_SYSTEMD
|
||||
sd_notify(0, "READY=1");
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
if(sig_record_quit)
|
||||
worker_sighandler(SIGTERM, wrk);
|
||||
@@ -279,11 +271,20 @@ daemon_init(void)
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
daemon->tcl = tcl_list_create();
|
||||
if(!daemon->tcl) {
|
||||
acl_list_delete(daemon->acl);
|
||||
edns_known_options_delete(daemon->env);
|
||||
free(daemon->env);
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
if(gettimeofday(&daemon->time_boot, NULL) < 0)
|
||||
log_err("gettimeofday: %s", strerror(errno));
|
||||
daemon->time_last_stat = daemon->time_boot;
|
||||
if((daemon->env->auth_zones = auth_zones_create()) == 0) {
|
||||
acl_list_delete(daemon->acl);
|
||||
tcl_list_delete(daemon->tcl);
|
||||
edns_known_options_delete(daemon->env);
|
||||
free(daemon->env);
|
||||
free(daemon);
|
||||
@@ -584,6 +585,8 @@ daemon_fork(struct daemon* daemon)
|
||||
|
||||
if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->views))
|
||||
fatal_exit("Could not setup access control list");
|
||||
if(!tcl_list_apply_cfg(daemon->tcl, daemon->cfg))
|
||||
fatal_exit("Could not setup TCP connection limits");
|
||||
if(daemon->cfg->dnscrypt) {
|
||||
#ifdef USE_DNSCRYPT
|
||||
daemon->dnscenv = dnsc_create();
|
||||
@@ -662,7 +665,10 @@ daemon_fork(struct daemon* daemon)
|
||||
log_info("start of service (%s).", PACKAGE_STRING);
|
||||
worker_work(daemon->workers[0]);
|
||||
#ifdef HAVE_SYSTEMD
|
||||
sd_notify(0, "STOPPING=1");
|
||||
if (daemon->workers[0]->need_to_exit)
|
||||
sd_notify(0, "STOPPING=1");
|
||||
else
|
||||
sd_notify(0, "RELOADING=1");
|
||||
#endif
|
||||
log_info("service stopped (%s).", PACKAGE_STRING);
|
||||
|
||||
@@ -704,6 +710,7 @@ daemon_cleanup(struct daemon* daemon)
|
||||
free(daemon->workers);
|
||||
daemon->workers = NULL;
|
||||
daemon->num = 0;
|
||||
alloc_clear_special(&daemon->superalloc);
|
||||
#ifdef USE_DNSTAP
|
||||
dt_delete(daemon->dtenv);
|
||||
daemon->dtenv = NULL;
|
||||
@@ -737,6 +744,7 @@ daemon_delete(struct daemon* daemon)
|
||||
ub_randfree(daemon->rand);
|
||||
alloc_clear(&daemon->superalloc);
|
||||
acl_list_delete(daemon->acl);
|
||||
tcl_list_delete(daemon->tcl);
|
||||
free(daemon->chroot);
|
||||
free(daemon->pidfile);
|
||||
free(daemon->env);
|
||||
@@ -745,10 +753,8 @@ daemon_delete(struct daemon* daemon)
|
||||
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 */
|
||||
#ifdef HAVE_SSL
|
||||
# if defined(USE_GOST) && defined(HAVE_LDNS_KEY_EVP_UNLOAD_GOST)
|
||||
@@ -799,9 +805,8 @@ void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg)
|
||||
{
|
||||
daemon->cfg = cfg;
|
||||
config_apply(cfg);
|
||||
if(!daemon->env->msg_cache ||
|
||||
cfg->msg_cache_size != slabhash_get_size(daemon->env->msg_cache) ||
|
||||
cfg->msg_cache_slabs != daemon->env->msg_cache->size) {
|
||||
if(!slabhash_is_size(daemon->env->msg_cache, cfg->msg_cache_size,
|
||||
cfg->msg_cache_slabs)) {
|
||||
slabhash_delete(daemon->env->msg_cache);
|
||||
daemon->env->msg_cache = slabhash_create(cfg->msg_cache_slabs,
|
||||
HASH_DEFAULT_STARTARRAY, cfg->msg_cache_size,
|
||||
|
||||
@@ -113,6 +113,8 @@ struct daemon {
|
||||
struct module_stack mods;
|
||||
/** access control, which client IPs are allowed to connect */
|
||||
struct acl_list* acl;
|
||||
/** TCP connection limit, limit connections from client IPs */
|
||||
struct tcl_list* tcl;
|
||||
/** local authority zones */
|
||||
struct local_zones* local_zones;
|
||||
/** last time of statistics printout */
|
||||
|
||||
+366
-268
File diff suppressed because it is too large
Load Diff
+21
-6
@@ -73,6 +73,8 @@ struct rc_state {
|
||||
/** the ssl state */
|
||||
SSL* ssl;
|
||||
#endif
|
||||
/** file descriptor */
|
||||
int fd;
|
||||
/** the rc this is part of */
|
||||
struct daemon_remote* rc;
|
||||
};
|
||||
@@ -103,6 +105,19 @@ struct daemon_remote {
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Connection to print to, either SSL or plain over fd
|
||||
*/
|
||||
struct remote_stream {
|
||||
#ifdef HAVE_SSL
|
||||
/** SSL structure, nonNULL if using SSL */
|
||||
SSL* ssl;
|
||||
#endif
|
||||
/** file descriptor for plain transfer */
|
||||
int fd;
|
||||
};
|
||||
typedef struct remote_stream RES;
|
||||
|
||||
/**
|
||||
* Create new remote control state for the daemon.
|
||||
* @param cfg: config file with key file settings.
|
||||
@@ -166,26 +181,26 @@ void daemon_remote_exec(struct worker* worker);
|
||||
* @param text: the text.
|
||||
* @return false on connection failure.
|
||||
*/
|
||||
int ssl_print_text(SSL* ssl, const char* text);
|
||||
int ssl_print_text(RES* ssl, const char* text);
|
||||
|
||||
/**
|
||||
* printf style printing to the ssl connection
|
||||
* @param ssl: the SSL connection to print to. Blocking.
|
||||
* @param ssl: the RES connection to print to. Blocking.
|
||||
* @param format: printf style format string.
|
||||
* @return success or false on a network failure.
|
||||
*/
|
||||
int ssl_printf(SSL* ssl, const char* format, ...)
|
||||
int ssl_printf(RES* ssl, const char* format, ...)
|
||||
ATTR_FORMAT(printf, 2, 3);
|
||||
|
||||
/**
|
||||
* Read until \n is encountered
|
||||
* If SSL signals EOF, the string up to then is returned (without \n).
|
||||
* @param ssl: the SSL connection to read from. blocking.
|
||||
* If stream signals EOF, the string up to then is returned (without \n).
|
||||
* @param ssl: the RES connection to read from. blocking.
|
||||
* @param buf: buffer to read to.
|
||||
* @param max: size of buffer.
|
||||
* @return false on connection failure.
|
||||
*/
|
||||
int ssl_read_line(SSL* ssl, char* buf, size_t max);
|
||||
int ssl_read_line(RES* ssl, char* buf, size_t max);
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
#endif /* DAEMON_REMOTE_H */
|
||||
|
||||
+42
-1
@@ -63,6 +63,9 @@
|
||||
#include "services/authzone.h"
|
||||
#include "validator/val_kcache.h"
|
||||
#include "validator/val_neg.h"
|
||||
#ifdef CLIENT_SUBNET
|
||||
#include "edns-subnet/subnetmod.h"
|
||||
#endif
|
||||
|
||||
/** add timers and the values do not overflow or become negative */
|
||||
static void
|
||||
@@ -124,6 +127,33 @@ void server_stats_log(struct ub_server_stats* stats, struct worker* worker,
|
||||
(unsigned)worker->env.mesh->stats_jostled);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CLIENT_SUBNET
|
||||
/** Set the EDNS Subnet stats. */
|
||||
static void
|
||||
set_subnet_stats(struct worker* worker, struct ub_server_stats* svr,
|
||||
int reset)
|
||||
{
|
||||
int m = modstack_find(&worker->env.mesh->mods, "subnet");
|
||||
struct subnet_env* sne;
|
||||
if(m == -1)
|
||||
return;
|
||||
sne = (struct subnet_env*)worker->env.modinfo[m];
|
||||
if(reset && !worker->env.cfg->stat_cumulative) {
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
} else {
|
||||
lock_rw_rdlock(&sne->biglock);
|
||||
}
|
||||
svr->num_query_subnet = (long long)(sne->num_msg_nocache + sne->num_msg_cache);
|
||||
svr->num_query_subnet_cache = (long long)sne->num_msg_cache;
|
||||
if(reset && !worker->env.cfg->stat_cumulative) {
|
||||
sne->num_msg_cache = 0;
|
||||
sne->num_msg_nocache = 0;
|
||||
}
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
}
|
||||
#endif /* CLIENT_SUBNET */
|
||||
|
||||
/** Set the neg cache stats. */
|
||||
static void
|
||||
set_neg_cache_stats(struct worker* worker, struct ub_server_stats* svr,
|
||||
@@ -301,6 +331,13 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
|
||||
/* Set neg cache usage numbers */
|
||||
set_neg_cache_stats(worker, &s->svr, reset);
|
||||
#ifdef CLIENT_SUBNET
|
||||
/* EDNS Subnet usage numbers */
|
||||
set_subnet_stats(worker, &s->svr, reset);
|
||||
#else
|
||||
s->svr.num_query_subnet = 0;
|
||||
s->svr.num_query_subnet_cache = 0;
|
||||
#endif
|
||||
|
||||
/* get tcp accept usage */
|
||||
s->svr.tcp_accept_usage = 0;
|
||||
@@ -374,6 +411,7 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
||||
total->svr.qclass_big += a->svr.qclass_big;
|
||||
total->svr.qtcp += a->svr.qtcp;
|
||||
total->svr.qtcp_outgoing += a->svr.qtcp_outgoing;
|
||||
total->svr.qtls += a->svr.qtls;
|
||||
total->svr.qipv6 += a->svr.qipv6;
|
||||
total->svr.qbit_QR += a->svr.qbit_QR;
|
||||
total->svr.qbit_AA += a->svr.qbit_AA;
|
||||
@@ -428,8 +466,11 @@ void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
|
||||
stats->qclass[qclass]++;
|
||||
else stats->qclass_big++;
|
||||
stats->qopcode[ LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) ]++;
|
||||
if(c->type != comm_udp)
|
||||
if(c->type != comm_udp) {
|
||||
stats->qtcp++;
|
||||
if(c->ssl != NULL)
|
||||
stats->qtls++;
|
||||
}
|
||||
if(repinfo && addr_is_ip6(&repinfo->addr, repinfo->addrlen))
|
||||
stats->qipv6++;
|
||||
if( (flags&BIT_QR) )
|
||||
|
||||
+7
-4
@@ -101,6 +101,7 @@ static void usage(void)
|
||||
printf("-c file config file to read instead of %s\n", CONFIGFILE);
|
||||
printf(" file format is described in unbound.conf(5).\n");
|
||||
printf("-d do not fork into the background.\n");
|
||||
printf("-p do not create a pidfile.\n");
|
||||
printf("-v verbose (more times to increase verbosity)\n");
|
||||
#ifdef UB_ON_WINDOWS
|
||||
printf("-w opt windows option: \n");
|
||||
@@ -431,7 +432,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
fatal_exit("could not set up listen SSL_CTX");
|
||||
}
|
||||
if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL,
|
||||
cfg->tls_cert_bundle)))
|
||||
cfg->tls_cert_bundle, cfg->tls_win_cert)))
|
||||
fatal_exit("could not set up connect SSL_CTX");
|
||||
#endif
|
||||
|
||||
@@ -626,8 +627,10 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char*
|
||||
fatal_exit("Could not alloc config defaults");
|
||||
if(!config_read(cfg, cfgfile, daemon->chroot)) {
|
||||
if(errno != ENOENT)
|
||||
fatal_exit("Could not read config file: %s",
|
||||
cfgfile);
|
||||
fatal_exit("Could not read config file: %s."
|
||||
" Maybe try unbound -dd, it stays on "
|
||||
"the commandline to see more errors, "
|
||||
"or unbound-checkconf", cfgfile);
|
||||
log_warn("Continuing with default config settings");
|
||||
}
|
||||
apply_settings(daemon, cfg, cmdline_verbose, debug_mode, log_default_identity);
|
||||
@@ -727,7 +730,7 @@ main(int argc, char* argv[])
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
/* argv += optind; not using further arguments */
|
||||
|
||||
if(winopt) {
|
||||
#ifdef UB_ON_WINDOWS
|
||||
|
||||
+114
-68
@@ -66,6 +66,7 @@
|
||||
#include "util/data/dname.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "util/tube.h"
|
||||
#include "util/edns.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
#include "validator/autotrust.h"
|
||||
@@ -477,6 +478,7 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
* Then check if it needs validation, if so, this routine fails,
|
||||
* so that iterator can prime and validator can verify rrsets.
|
||||
*/
|
||||
struct edns_data edns_bak;
|
||||
uint16_t udpsize = edns->udp_size;
|
||||
int secure = 0;
|
||||
time_t timenow = *worker->env.now;
|
||||
@@ -509,7 +511,7 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
edns->ext_rcode = 0;
|
||||
edns->bits &= EDNS_DO;
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL,
|
||||
msg->rep, LDNS_RCODE_SERVFAIL, edns, worker->scratchpad))
|
||||
msg->rep, LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad))
|
||||
return 0;
|
||||
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
&msg->qinfo, id, flags, edns);
|
||||
@@ -534,19 +536,22 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
}
|
||||
}
|
||||
/* return this delegation from the cache */
|
||||
edns_bak = *edns;
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns->ext_rcode = 0;
|
||||
edns->bits &= EDNS_DO;
|
||||
if(!inplace_cb_reply_cache_call(&worker->env, qinfo, NULL, msg->rep,
|
||||
(int)(flags&LDNS_RCODE_MASK), edns, worker->scratchpad))
|
||||
(int)(flags&LDNS_RCODE_MASK), edns, repinfo, worker->scratchpad))
|
||||
return 0;
|
||||
msg->rep->flags |= BIT_QR|BIT_RA;
|
||||
if(!reply_info_answer_encode(&msg->qinfo, msg->rep, id, flags,
|
||||
if(!apply_edns_options(edns, &edns_bak, worker->env.cfg,
|
||||
repinfo->c, worker->scratchpad) ||
|
||||
!reply_info_answer_encode(&msg->qinfo, msg->rep, id, flags,
|
||||
repinfo->c->buffer, 0, 1, worker->scratchpad,
|
||||
udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) {
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL,
|
||||
LDNS_RCODE_SERVFAIL, edns, worker->scratchpad))
|
||||
LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad))
|
||||
edns->opt_list = NULL;
|
||||
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
&msg->qinfo, id, flags, edns);
|
||||
@@ -614,6 +619,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
struct reply_info* rep, uint16_t id, uint16_t flags,
|
||||
struct comm_reply* repinfo, struct edns_data* edns)
|
||||
{
|
||||
struct edns_data edns_bak;
|
||||
time_t timenow = *worker->env.now;
|
||||
uint16_t udpsize = edns->udp_size;
|
||||
struct reply_info* encode_rep = rep;
|
||||
@@ -623,7 +629,9 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
&& worker->env.need_to_validate;
|
||||
*partial_repp = NULL; /* avoid accidental further pass */
|
||||
if(worker->env.cfg->serve_expired) {
|
||||
/* always lock rrsets, rep->ttl is ignored */
|
||||
if(worker->env.cfg->serve_expired_ttl &&
|
||||
rep->serve_expired_ttl < timenow)
|
||||
return 0;
|
||||
if(!rrset_array_lock(rep->ref, rep->rrset_count, 0))
|
||||
return 0;
|
||||
/* below, rrsets with ttl before timenow become TTL 0 in
|
||||
@@ -667,7 +675,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
edns->ext_rcode = 0;
|
||||
edns->bits &= EDNS_DO;
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, rep,
|
||||
LDNS_RCODE_SERVFAIL, edns, worker->scratchpad))
|
||||
LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad))
|
||||
goto bail_out;
|
||||
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, id, flags, edns);
|
||||
@@ -695,12 +703,13 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
}
|
||||
} else secure = 0;
|
||||
|
||||
edns_bak = *edns;
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns->ext_rcode = 0;
|
||||
edns->bits &= EDNS_DO;
|
||||
if(!inplace_cb_reply_cache_call(&worker->env, qinfo, NULL, rep,
|
||||
(int)(flags&LDNS_RCODE_MASK), edns, worker->scratchpad))
|
||||
(int)(flags&LDNS_RCODE_MASK), edns, repinfo, worker->scratchpad))
|
||||
goto bail_out;
|
||||
*alias_rrset = NULL; /* avoid confusion if caller set it to non-NULL */
|
||||
if(worker->daemon->use_response_ip && !partial_rep &&
|
||||
@@ -728,11 +737,13 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
if(!*partial_repp)
|
||||
goto bail_out;
|
||||
}
|
||||
} else if(!reply_info_answer_encode(qinfo, encode_rep, id, flags,
|
||||
} else if(!apply_edns_options(edns, &edns_bak, worker->env.cfg,
|
||||
repinfo->c, worker->scratchpad) ||
|
||||
!reply_info_answer_encode(qinfo, encode_rep, id, flags,
|
||||
repinfo->c->buffer, timenow, 1, worker->scratchpad,
|
||||
udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) {
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL,
|
||||
LDNS_RCODE_SERVFAIL, edns, worker->scratchpad))
|
||||
LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad))
|
||||
edns->opt_list = NULL;
|
||||
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, id, flags, edns);
|
||||
@@ -779,10 +790,11 @@ reply_and_prefetch(struct worker* worker, struct query_info* qinfo,
|
||||
* @param num: number of strings in array.
|
||||
* @param edns: edns reply information.
|
||||
* @param worker: worker with scratch region.
|
||||
* @param repinfo: reply information for a communication point.
|
||||
*/
|
||||
static void
|
||||
chaos_replystr(sldns_buffer* pkt, char** str, int num, struct edns_data* edns,
|
||||
struct worker* worker)
|
||||
struct worker* worker, struct comm_reply* repinfo)
|
||||
{
|
||||
int i;
|
||||
unsigned int rd = LDNS_RD_WIRE(sldns_buffer_begin(pkt));
|
||||
@@ -815,7 +827,7 @@ chaos_replystr(sldns_buffer* pkt, char** str, int num, struct edns_data* edns,
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns->bits &= EDNS_DO;
|
||||
if(!inplace_cb_reply_local_call(&worker->env, NULL, NULL, NULL,
|
||||
LDNS_RCODE_NOERROR, edns, worker->scratchpad))
|
||||
LDNS_RCODE_NOERROR, edns, repinfo, worker->scratchpad))
|
||||
edns->opt_list = NULL;
|
||||
if(sldns_buffer_capacity(pkt) >=
|
||||
sldns_buffer_limit(pkt)+calc_edns_field_size(edns))
|
||||
@@ -825,9 +837,9 @@ chaos_replystr(sldns_buffer* pkt, char** str, int num, struct edns_data* edns,
|
||||
/** Reply with one string */
|
||||
static void
|
||||
chaos_replyonestr(sldns_buffer* pkt, const char* str, struct edns_data* edns,
|
||||
struct worker* worker)
|
||||
struct worker* worker, struct comm_reply* repinfo)
|
||||
{
|
||||
chaos_replystr(pkt, (char**)&str, 1, edns, worker);
|
||||
chaos_replystr(pkt, (char**)&str, 1, edns, worker, repinfo);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -835,9 +847,11 @@ chaos_replyonestr(sldns_buffer* pkt, const char* str, struct edns_data* edns,
|
||||
* @param pkt: buffer
|
||||
* @param edns: edns reply information.
|
||||
* @param w: worker with scratch region.
|
||||
* @param repinfo: reply information for a communication point.
|
||||
*/
|
||||
static void
|
||||
chaos_trustanchor(sldns_buffer* pkt, struct edns_data* edns, struct worker* w)
|
||||
chaos_trustanchor(sldns_buffer* pkt, struct edns_data* edns, struct worker* w,
|
||||
struct comm_reply* repinfo)
|
||||
{
|
||||
#define TA_RESPONSE_MAX_TXT 16 /* max number of TXT records */
|
||||
#define TA_RESPONSE_MAX_TAGS 32 /* max number of tags printed per zone */
|
||||
@@ -848,7 +862,7 @@ chaos_trustanchor(sldns_buffer* pkt, struct edns_data* edns, struct worker* w)
|
||||
|
||||
if(!w->env.need_to_validate) {
|
||||
/* no validator module, reply no trustanchors */
|
||||
chaos_replystr(pkt, NULL, 0, edns, w);
|
||||
chaos_replystr(pkt, NULL, 0, edns, w, repinfo);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -882,7 +896,7 @@ chaos_trustanchor(sldns_buffer* pkt, struct edns_data* edns, struct worker* w)
|
||||
}
|
||||
lock_basic_unlock(&w->env.anchors->lock);
|
||||
|
||||
chaos_replystr(pkt, str_array, num, edns, w);
|
||||
chaos_replystr(pkt, str_array, num, edns, w, repinfo);
|
||||
regional_free_all(w->scratchpad);
|
||||
}
|
||||
|
||||
@@ -891,12 +905,13 @@ chaos_trustanchor(sldns_buffer* pkt, struct edns_data* edns, struct worker* w)
|
||||
* @param w: worker
|
||||
* @param qinfo: query info. Pointer into packet buffer.
|
||||
* @param edns: edns info from query.
|
||||
* @param repinfo: reply information for a communication point.
|
||||
* @param pkt: packet buffer.
|
||||
* @return: true if a reply is to be sent.
|
||||
*/
|
||||
static int
|
||||
answer_chaos(struct worker* w, struct query_info* qinfo,
|
||||
struct edns_data* edns, sldns_buffer* pkt)
|
||||
answer_chaos(struct worker* w, struct query_info* qinfo,
|
||||
struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* pkt)
|
||||
{
|
||||
struct config_file* cfg = w->env.cfg;
|
||||
if(qinfo->qtype != LDNS_RR_TYPE_ANY && qinfo->qtype != LDNS_RR_TYPE_TXT)
|
||||
@@ -912,13 +927,13 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
|
||||
char buf[MAXHOSTNAMELEN+1];
|
||||
if (gethostname(buf, MAXHOSTNAMELEN) == 0) {
|
||||
buf[MAXHOSTNAMELEN] = 0;
|
||||
chaos_replyonestr(pkt, buf, edns, w);
|
||||
chaos_replyonestr(pkt, buf, edns, w, repinfo);
|
||||
} else {
|
||||
log_err("gethostname: %s", strerror(errno));
|
||||
chaos_replyonestr(pkt, "no hostname", edns, w);
|
||||
chaos_replyonestr(pkt, "no hostname", edns, w, repinfo);
|
||||
}
|
||||
}
|
||||
else chaos_replyonestr(pkt, cfg->identity, edns, w);
|
||||
else chaos_replyonestr(pkt, cfg->identity, edns, w, repinfo);
|
||||
return 1;
|
||||
}
|
||||
if(query_dname_compare(qinfo->qname,
|
||||
@@ -929,8 +944,8 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
|
||||
if(cfg->hide_version)
|
||||
return 0;
|
||||
if(cfg->version==NULL || cfg->version[0]==0)
|
||||
chaos_replyonestr(pkt, PACKAGE_STRING, edns, w);
|
||||
else chaos_replyonestr(pkt, cfg->version, edns, w);
|
||||
chaos_replyonestr(pkt, PACKAGE_STRING, edns, w, repinfo);
|
||||
else chaos_replyonestr(pkt, cfg->version, edns, w, repinfo);
|
||||
return 1;
|
||||
}
|
||||
if(query_dname_compare(qinfo->qname,
|
||||
@@ -938,7 +953,7 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
|
||||
{
|
||||
if(cfg->hide_trustanchor)
|
||||
return 0;
|
||||
chaos_trustanchor(pkt, edns, w);
|
||||
chaos_trustanchor(pkt, edns, w, repinfo);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1165,7 +1180,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
char addrbuf[128];
|
||||
addr_to_str(&repinfo->addr, repinfo->addrlen,
|
||||
addrbuf, sizeof(addrbuf));
|
||||
verbose(VERB_OPS, "ip_ratelimit allowed through for ip address %s ",
|
||||
verbose(VERB_QUERY, "ip_ratelimit allowed through for ip address %s because of slip in ip_ratelimit_factor",
|
||||
addrbuf);
|
||||
} else {
|
||||
worker->stats.num_queries_ip_ratelimited++;
|
||||
@@ -1246,29 +1261,52 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
server_stats_insrcode(&worker->stats, c->buffer);
|
||||
goto send_reply;
|
||||
}
|
||||
if(edns.edns_present && edns.edns_version != 0) {
|
||||
edns.ext_rcode = (uint8_t)(EDNS_RCODE_BADVERS>>4);
|
||||
edns.edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns.bits &= EDNS_DO;
|
||||
edns.opt_list = NULL;
|
||||
verbose(VERB_ALGO, "query with bad edns version.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
error_encode(c->buffer, EDNS_RCODE_BADVERS&0xf, &qinfo,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), NULL);
|
||||
if(sldns_buffer_capacity(c->buffer) >=
|
||||
sldns_buffer_limit(c->buffer)+calc_edns_field_size(&edns))
|
||||
attach_edns_record(c->buffer, &edns);
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply;
|
||||
}
|
||||
if(edns.edns_present && edns.udp_size < NORMAL_UDP_SIZE &&
|
||||
worker->daemon->cfg->harden_short_bufsize) {
|
||||
verbose(VERB_QUERY, "worker request: EDNS bufsize %d ignored",
|
||||
(int)edns.udp_size);
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
edns.udp_size = NORMAL_UDP_SIZE;
|
||||
if(edns.edns_present) {
|
||||
struct edns_option* edns_opt;
|
||||
if(edns.edns_version != 0) {
|
||||
edns.ext_rcode = (uint8_t)(EDNS_RCODE_BADVERS>>4);
|
||||
edns.edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns.bits &= EDNS_DO;
|
||||
edns.opt_list = NULL;
|
||||
verbose(VERB_ALGO, "query with bad edns version.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
error_encode(c->buffer, EDNS_RCODE_BADVERS&0xf, &qinfo,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), NULL);
|
||||
if(sldns_buffer_capacity(c->buffer) >=
|
||||
sldns_buffer_limit(c->buffer)+calc_edns_field_size(&edns))
|
||||
attach_edns_record(c->buffer, &edns);
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply;
|
||||
}
|
||||
if(edns.udp_size < NORMAL_UDP_SIZE &&
|
||||
worker->daemon->cfg->harden_short_bufsize) {
|
||||
verbose(VERB_QUERY, "worker request: EDNS bufsize %d ignored",
|
||||
(int)edns.udp_size);
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
edns.udp_size = NORMAL_UDP_SIZE;
|
||||
}
|
||||
if(c->type != comm_udp) {
|
||||
edns_opt = edns_opt_list_find(edns.opt_list, LDNS_EDNS_KEEPALIVE);
|
||||
if(edns_opt && edns_opt->opt_len > 0) {
|
||||
edns.ext_rcode = 0;
|
||||
edns.edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns.bits &= EDNS_DO;
|
||||
edns.opt_list = NULL;
|
||||
verbose(VERB_ALGO, "query with bad edns keepalive.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
error_encode(c->buffer, LDNS_RCODE_FORMERR, &qinfo,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), NULL);
|
||||
if(sldns_buffer_capacity(c->buffer) >=
|
||||
sldns_buffer_limit(c->buffer)+calc_edns_field_size(&edns))
|
||||
attach_edns_record(c->buffer, &edns);
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(edns.udp_size > worker->daemon->cfg->max_udp_size &&
|
||||
c->type == comm_udp) {
|
||||
@@ -1298,7 +1336,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
if(c->type != comm_udp)
|
||||
edns.udp_size = 65535; /* max size for TCP replies */
|
||||
if(qinfo.qclass == LDNS_RR_CLASS_CH && answer_chaos(worker, &qinfo,
|
||||
&edns, c->buffer)) {
|
||||
&edns, repinfo, c->buffer)) {
|
||||
server_stats_insrcode(&worker->stats, c->buffer);
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply;
|
||||
@@ -1325,7 +1363,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
}
|
||||
if(worker->env.auth_zones &&
|
||||
auth_zones_answer(worker->env.auth_zones, &worker->env,
|
||||
&qinfo, &edns, c->buffer, worker->scratchpad)) {
|
||||
&qinfo, &edns, repinfo, c->buffer, worker->scratchpad)) {
|
||||
regional_free_all(worker->scratchpad);
|
||||
if(sldns_buffer_limit(c->buffer) == 0) {
|
||||
comm_point_drop_reply(repinfo);
|
||||
@@ -1350,6 +1388,13 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If this request does not have the recursion bit set, verify
|
||||
* ACLs allow the recursion bit to be treated as set. */
|
||||
if(!(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) &&
|
||||
acl == acl_allow_setrd ) {
|
||||
LDNS_RD_SET(sldns_buffer_begin(c->buffer));
|
||||
}
|
||||
|
||||
/* If this request does not have the recursion bit set, verify
|
||||
* ACLs allow the snooping. */
|
||||
if(!(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) &&
|
||||
@@ -1626,14 +1671,14 @@ worker_create(struct daemon* daemon, int id, int* ports, int n)
|
||||
(((unsigned int)worker->thread_num)<<17);
|
||||
/* shift thread_num so it does not match out pid bits */
|
||||
if(!(worker->rndstate = ub_initstate(seed, daemon->rand))) {
|
||||
seed = 0;
|
||||
explicit_bzero(&seed, sizeof(seed));
|
||||
log_err("could not init random numbers.");
|
||||
tube_delete(worker->cmd);
|
||||
free(worker->ports);
|
||||
free(worker);
|
||||
return NULL;
|
||||
}
|
||||
seed = 0;
|
||||
explicit_bzero(&seed, sizeof(seed));
|
||||
#ifdef USE_DNSTAP
|
||||
if(daemon->cfg->dnstap) {
|
||||
log_assert(daemon->dtenv != NULL);
|
||||
@@ -1701,9 +1746,13 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
worker->comsig = NULL;
|
||||
}
|
||||
worker->front = listen_create(worker->base, ports,
|
||||
cfg->msg_buffer_size, (int)cfg->incoming_num_tcp,
|
||||
worker->daemon->listen_sslctx, dtenv, worker_handle_request,
|
||||
worker);
|
||||
cfg->msg_buffer_size, (int)cfg->incoming_num_tcp,
|
||||
cfg->do_tcp_keepalive
|
||||
? cfg->tcp_keepalive_timeout
|
||||
: cfg->tcp_idle_timeout,
|
||||
worker->daemon->tcl,
|
||||
worker->daemon->listen_sslctx,
|
||||
dtenv, worker_handle_request, worker);
|
||||
if(!worker->front) {
|
||||
log_err("could not create listening sockets");
|
||||
worker_delete(worker);
|
||||
@@ -1753,8 +1802,6 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
alloc_set_id_cleanup(&worker->alloc, &worker_alloc_cleanup, worker);
|
||||
worker->env = *worker->daemon->env;
|
||||
comm_base_timept(worker->base, &worker->env.now, &worker->env.now_tv);
|
||||
if(worker->thread_num == 0)
|
||||
log_set_time(worker->env.now);
|
||||
worker->env.worker = worker;
|
||||
worker->env.worker_base = worker->base;
|
||||
worker->env.send_query = &worker_send_query;
|
||||
@@ -1860,7 +1907,6 @@ worker_delete(struct worker* worker)
|
||||
comm_timer_delete(worker->env.probe_timer);
|
||||
free(worker->ports);
|
||||
if(worker->thread_num == 0) {
|
||||
log_set_time(NULL);
|
||||
#ifdef UB_ON_WINDOWS
|
||||
wsvc_desetup_worker(worker);
|
||||
#endif /* UB_ON_WINDOWS */
|
||||
@@ -1965,22 +2011,22 @@ void libworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube),
|
||||
}
|
||||
|
||||
void libworker_fg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
|
||||
sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s),
|
||||
char* ATTR_UNUSED(why_bogus))
|
||||
sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s),
|
||||
char* ATTR_UNUSED(why_bogus), int ATTR_UNUSED(was_ratelimited))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void libworker_bg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
|
||||
sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s),
|
||||
char* ATTR_UNUSED(why_bogus))
|
||||
sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s),
|
||||
char* ATTR_UNUSED(why_bogus), int ATTR_UNUSED(was_ratelimited))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void libworker_event_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
|
||||
sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s),
|
||||
char* ATTR_UNUSED(why_bogus))
|
||||
sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s),
|
||||
char* ATTR_UNUSED(why_bogus), int ATTR_UNUSED(was_ratelimited))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
@@ -1993,13 +2039,13 @@ int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||
|
||||
int order_lock_cmp(const void* ATTR_UNUSED(e1), const void* ATTR_UNUSED(e2))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+176
-28
@@ -48,6 +48,9 @@
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/storage/dnstree.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "sldns/str2wire.h"
|
||||
|
||||
/******************************************************************************
|
||||
* *
|
||||
@@ -67,12 +70,9 @@ static const char DEFAULT_DNS64_PREFIX[] = "64:ff9b::/96";
|
||||
#define MAX_PTR_QNAME_IPV4 30
|
||||
|
||||
/**
|
||||
* Per-query module-specific state. This is usually a dynamically-allocated
|
||||
* structure, but in our case we only need to store one variable describing the
|
||||
* state the query is in. So we repurpose the minfo pointer by storing an
|
||||
* integer in there.
|
||||
* State of DNS64 processing for a query.
|
||||
*/
|
||||
enum dns64_qstate {
|
||||
enum dns64_state {
|
||||
DNS64_INTERNAL_QUERY, /**< Internally-generated query, no DNS64
|
||||
processing. */
|
||||
DNS64_NEW_QUERY, /**< Query for which we're the first module in
|
||||
@@ -81,6 +81,19 @@ enum dns64_qstate {
|
||||
for which this sub-query is finished. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Per-query module-specific state. For the DNS64 module.
|
||||
*/
|
||||
struct dns64_qstate {
|
||||
/** State of the DNS64 module. */
|
||||
enum dns64_state state;
|
||||
/** If the dns64 module started with no_cache bool set in the qstate,
|
||||
* a message to tell it to not modify the cache contents, then this
|
||||
* is true. The dns64 module is then free to modify that flag for
|
||||
* its own purposes.
|
||||
* Otherwise, it is false, the dns64 module was not told to no_cache */
|
||||
int started_no_cache_store;
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* *
|
||||
@@ -111,6 +124,11 @@ struct dns64_env {
|
||||
* This is the CIDR length of the prefix. It needs to be between 0 and 96.
|
||||
*/
|
||||
int prefix_net;
|
||||
|
||||
/**
|
||||
* Tree of names for which AAAA is ignored. always synthesize from A.
|
||||
*/
|
||||
rbtree_type ignore_aaaa;
|
||||
};
|
||||
|
||||
|
||||
@@ -284,6 +302,40 @@ synthesize_aaaa(const uint8_t prefix_addr[16], int prefix_net,
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* insert ignore_aaaa element into the tree
|
||||
* @param dns64_env: module env.
|
||||
* @param str: string with domain name.
|
||||
* @return false on failure.
|
||||
*/
|
||||
static int
|
||||
dns64_insert_ignore_aaaa(struct dns64_env* dns64_env, char* str)
|
||||
{
|
||||
/* parse and insert element */
|
||||
struct name_tree_node* node;
|
||||
node = (struct name_tree_node*)calloc(1, sizeof(*node));
|
||||
if(!node) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
node->name = sldns_str2wire_dname(str, &node->len);
|
||||
if(!node->name) {
|
||||
free(node);
|
||||
log_err("cannot parse dns64-ignore-aaaa: %s", str);
|
||||
return 0;
|
||||
}
|
||||
node->labs = dname_count_labels(node->name);
|
||||
node->dclass = LDNS_RR_CLASS_IN;
|
||||
if(!name_tree_insert(&dns64_env->ignore_aaaa, node,
|
||||
node->name, node->len, node->labs, node->dclass)) {
|
||||
/* ignore duplicate element */
|
||||
free(node->name);
|
||||
free(node);
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function applies the configuration found in the parsed configuration
|
||||
* file \a cfg to this instance of the dns64 module. Currently only the DNS64
|
||||
@@ -295,6 +347,7 @@ synthesize_aaaa(const uint8_t prefix_addr[16], int prefix_net,
|
||||
static int
|
||||
dns64_apply_cfg(struct dns64_env* dns64_env, struct config_file* cfg)
|
||||
{
|
||||
struct config_strlist* s;
|
||||
verbose(VERB_ALGO, "dns64-prefix: %s", cfg->dns64_prefix);
|
||||
if (!netblockstrtoaddr(cfg->dns64_prefix ? cfg->dns64_prefix :
|
||||
DEFAULT_DNS64_PREFIX, 0, &dns64_env->prefix_addr,
|
||||
@@ -311,6 +364,11 @@ dns64_apply_cfg(struct dns64_env* dns64_env, struct config_file* cfg)
|
||||
cfg->dns64_prefix);
|
||||
return 0;
|
||||
}
|
||||
for(s = cfg->dns64_ignore_aaaa; s; s = s->next) {
|
||||
if(!dns64_insert_ignore_aaaa(dns64_env, s->str))
|
||||
return 0;
|
||||
}
|
||||
name_tree_init_parents(&dns64_env->ignore_aaaa);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -329,7 +387,8 @@ dns64_init(struct module_env* env, int id)
|
||||
log_err("malloc failure");
|
||||
return 0;
|
||||
}
|
||||
env->modinfo[id] = (void*)dns64_env;
|
||||
env->modinfo[id] = (void*)dns64_env;
|
||||
name_tree_init(&dns64_env->ignore_aaaa);
|
||||
if (!dns64_apply_cfg(dns64_env, env->cfg)) {
|
||||
log_err("dns64: could not apply configuration settings.");
|
||||
return 0;
|
||||
@@ -337,6 +396,16 @@ dns64_init(struct module_env* env, int id)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** free ignore AAAA elements */
|
||||
static void
|
||||
free_ignore_aaaa_node(rbnode_type* node, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct name_tree_node* n = (struct name_tree_node*)node;
|
||||
if(!n) return;
|
||||
free(n->name);
|
||||
free(n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deinitializes this instance of the dns64 module.
|
||||
*
|
||||
@@ -346,8 +415,14 @@ dns64_init(struct module_env* env, int id)
|
||||
void
|
||||
dns64_deinit(struct module_env* env, int id)
|
||||
{
|
||||
struct dns64_env* dns64_env;
|
||||
if (!env)
|
||||
return;
|
||||
dns64_env = (struct dns64_env*)env->modinfo[id];
|
||||
if(dns64_env) {
|
||||
traverse_postorder(&dns64_env->ignore_aaaa, free_ignore_aaaa_node,
|
||||
NULL);
|
||||
}
|
||||
free(env->modinfo[id]);
|
||||
env->modinfo[id] = NULL;
|
||||
}
|
||||
@@ -405,7 +480,7 @@ handle_ipv6_ptr(struct module_qstate* qstate, int id)
|
||||
if (subq) {
|
||||
subq->curmod = id;
|
||||
subq->ext_state[id] = module_state_initial;
|
||||
subq->minfo[id] = NULL;
|
||||
subq->minfo[id] = NULL;
|
||||
}
|
||||
|
||||
return module_wait_subquery;
|
||||
@@ -440,6 +515,25 @@ generate_type_A_query(struct module_qstate* qstate, int id)
|
||||
return module_wait_subquery;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if query name is in the always synth config.
|
||||
* The ignore-aaaa list has names for which the AAAA for the domain is
|
||||
* ignored and the A is always used to create the answer.
|
||||
* @param qstate: query state.
|
||||
* @param id: module id.
|
||||
* @return true if the name is covered by ignore-aaaa.
|
||||
*/
|
||||
static int
|
||||
dns64_always_synth_for_qname(struct module_qstate* qstate, int id)
|
||||
{
|
||||
struct dns64_env* dns64_env = (struct dns64_env*)qstate->env->modinfo[id];
|
||||
int labs = dname_count_labels(qstate->qinfo.qname);
|
||||
struct name_tree_node* node = name_tree_lookup(&dns64_env->ignore_aaaa,
|
||||
qstate->qinfo.qname, qstate->qinfo.qname_len, labs,
|
||||
qstate->qinfo.qclass);
|
||||
return (node != NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the "pass" event for a query. This event is received when a new query
|
||||
* is received by this module. The query may have been generated internally by
|
||||
@@ -456,7 +550,8 @@ generate_type_A_query(struct module_qstate* qstate, int id)
|
||||
static enum module_ext_state
|
||||
handle_event_pass(struct module_qstate* qstate, int id)
|
||||
{
|
||||
if ((uintptr_t)qstate->minfo[id] == DNS64_NEW_QUERY
|
||||
struct dns64_qstate* iq = (struct dns64_qstate*)qstate->minfo[id];
|
||||
if (iq && iq->state == DNS64_NEW_QUERY
|
||||
&& qstate->qinfo.qtype == LDNS_RR_TYPE_PTR
|
||||
&& qstate->qinfo.qname_len == 74
|
||||
&& !strcmp((char*)&qstate->qinfo.qname[64], "\03ip6\04arpa"))
|
||||
@@ -464,12 +559,20 @@ handle_event_pass(struct module_qstate* qstate, int id)
|
||||
return handle_ipv6_ptr(qstate, id);
|
||||
|
||||
if (qstate->env->cfg->dns64_synthall &&
|
||||
(uintptr_t)qstate->minfo[id] == DNS64_NEW_QUERY
|
||||
iq && iq->state == DNS64_NEW_QUERY
|
||||
&& qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA)
|
||||
return generate_type_A_query(qstate, id);
|
||||
|
||||
if(dns64_always_synth_for_qname(qstate, id) &&
|
||||
iq && iq->state == DNS64_NEW_QUERY
|
||||
&& !(qstate->query_flags & BIT_CD)
|
||||
&& qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) {
|
||||
verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway");
|
||||
return generate_type_A_query(qstate, id);
|
||||
}
|
||||
|
||||
/* We are finished when our sub-query is finished. */
|
||||
if ((uintptr_t)qstate->minfo[id] == DNS64_SUBQUERY_FINISHED)
|
||||
if (iq && iq->state == DNS64_SUBQUERY_FINISHED)
|
||||
return module_finished;
|
||||
|
||||
/* Otherwise, pass request to next module. */
|
||||
@@ -490,6 +593,7 @@ handle_event_pass(struct module_qstate* qstate, int id)
|
||||
static enum module_ext_state
|
||||
handle_event_moddone(struct module_qstate* qstate, int id)
|
||||
{
|
||||
struct dns64_qstate* iq = (struct dns64_qstate*)qstate->minfo[id];
|
||||
/*
|
||||
* In many cases we have nothing special to do. From most to least common:
|
||||
*
|
||||
@@ -501,17 +605,35 @@ handle_event_moddone(struct module_qstate* qstate, int id)
|
||||
* synthesize in (sec 5.1.2 of RFC6147).
|
||||
* - A successful AAAA query with an answer.
|
||||
*/
|
||||
if ( (enum dns64_qstate)qstate->minfo[id] == DNS64_INTERNAL_QUERY
|
||||
|| qstate->qinfo.qtype != LDNS_RR_TYPE_AAAA
|
||||
|| (qstate->query_flags & BIT_CD)
|
||||
|| (qstate->return_msg &&
|
||||
if((!iq || iq->state != DNS64_INTERNAL_QUERY)
|
||||
&& qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA
|
||||
&& !(qstate->query_flags & BIT_CD)
|
||||
&& !(qstate->return_msg &&
|
||||
qstate->return_msg->rep &&
|
||||
reply_find_answer_rrset(&qstate->qinfo,
|
||||
qstate->return_msg->rep)))
|
||||
return module_finished;
|
||||
/* not internal, type AAAA, not CD, and no answer RRset,
|
||||
* So, this is a AAAA noerror/nodata answer */
|
||||
return generate_type_A_query(qstate, id);
|
||||
|
||||
/* So, this is a AAAA noerror/nodata answer */
|
||||
return generate_type_A_query(qstate, id);
|
||||
if((!iq || iq->state != DNS64_INTERNAL_QUERY)
|
||||
&& qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA
|
||||
&& !(qstate->query_flags & BIT_CD)
|
||||
&& dns64_always_synth_for_qname(qstate, id)) {
|
||||
/* if it is not internal, AAAA, not CD and listed domain,
|
||||
* generate from A record and ignore AAAA */
|
||||
verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway");
|
||||
return generate_type_A_query(qstate, id);
|
||||
}
|
||||
|
||||
/* Store the response in cache. */
|
||||
if ( (!iq || !iq->started_no_cache_store) &&
|
||||
!dns_cache_store(qstate->env, &qstate->qinfo, qstate->return_msg->rep,
|
||||
0, 0, 0, NULL, qstate->query_flags))
|
||||
log_err("out of memory");
|
||||
|
||||
/* do nothing */
|
||||
return module_finished;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -530,6 +652,7 @@ void
|
||||
dns64_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
struct outbound_entry* outbound)
|
||||
{
|
||||
struct dns64_qstate* iq;
|
||||
(void)outbound;
|
||||
verbose(VERB_QUERY, "dns64[module %d] operate: extstate:%s event:%s",
|
||||
id, strextstate(qstate->ext_state[id]),
|
||||
@@ -539,7 +662,12 @@ dns64_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
switch(event) {
|
||||
case module_event_new:
|
||||
/* Tag this query as being new and fall through. */
|
||||
qstate->minfo[id] = (void*)DNS64_NEW_QUERY;
|
||||
iq = (struct dns64_qstate*)regional_alloc(
|
||||
qstate->region, sizeof(*iq));
|
||||
qstate->minfo[id] = iq;
|
||||
iq->state = DNS64_NEW_QUERY;
|
||||
iq->started_no_cache_store = qstate->no_cache_store;
|
||||
qstate->no_cache_store = 1;
|
||||
/* fallthrough */
|
||||
case module_event_pass:
|
||||
qstate->ext_state[id] = handle_event_pass(qstate, id);
|
||||
@@ -551,6 +679,11 @@ dns64_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
qstate->ext_state[id] = module_finished;
|
||||
break;
|
||||
}
|
||||
if(qstate->ext_state[id] == module_finished) {
|
||||
iq = (struct dns64_qstate*)qstate->minfo[id];
|
||||
if(iq && iq->state != DNS64_INTERNAL_QUERY)
|
||||
qstate->no_cache_store = iq->started_no_cache_store;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -677,8 +810,9 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
||||
* Build the actual reply.
|
||||
*/
|
||||
cp = construct_reply_info_base(super->region, rep->flags, rep->qdcount,
|
||||
rep->ttl, rep->prefetch_ttl, rep->an_numrrsets, rep->ns_numrrsets,
|
||||
rep->ar_numrrsets, rep->rrset_count, rep->security);
|
||||
rep->ttl, rep->prefetch_ttl, rep->serve_expired_ttl,
|
||||
rep->an_numrrsets, rep->ns_numrrsets, rep->ar_numrrsets,
|
||||
rep->rrset_count, rep->security);
|
||||
if(!cp)
|
||||
return;
|
||||
|
||||
@@ -705,6 +839,12 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
||||
rrset_cache_remove(super->env->rrset_cache, dk->rk.dname,
|
||||
dk->rk.dname_len, LDNS_RR_TYPE_AAAA,
|
||||
LDNS_RR_CLASS_IN, 0);
|
||||
/* Delete negative AAAA in msg cache for CNAMEs,
|
||||
* stored by the iterator module */
|
||||
if(i != 0) /* if not the first RR */
|
||||
msg_cache_remove(super->env, dk->rk.dname,
|
||||
dk->rk.dname_len, LDNS_RR_TYPE_AAAA,
|
||||
LDNS_RR_CLASS_IN, 0);
|
||||
} else {
|
||||
dk->entry.hash = fk->entry.hash;
|
||||
dk->rk.dname = (uint8_t*)regional_alloc_init(super->region,
|
||||
@@ -756,9 +896,10 @@ dns64_adjust_ptr(struct module_qstate* qstate, struct module_qstate* super)
|
||||
* initial query's domain name.
|
||||
*/
|
||||
answer = reply_find_answer_rrset(&qstate->qinfo, super->return_msg->rep);
|
||||
log_assert(answer);
|
||||
answer->rk.dname = super->qinfo.qname;
|
||||
answer->rk.dname_len = super->qinfo.qname_len;
|
||||
if(answer) {
|
||||
answer->rk.dname = super->qinfo.qname;
|
||||
answer->rk.dname_len = super->qinfo.qname_len;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -774,6 +915,7 @@ void
|
||||
dns64_inform_super(struct module_qstate* qstate, int id,
|
||||
struct module_qstate* super)
|
||||
{
|
||||
struct dns64_qstate* super_dq = (struct dns64_qstate*)super->minfo[id];
|
||||
log_query_info(VERB_ALGO, "dns64: inform_super, sub is",
|
||||
&qstate->qinfo);
|
||||
log_query_info(VERB_ALGO, "super is", &super->qinfo);
|
||||
@@ -782,15 +924,21 @@ dns64_inform_super(struct module_qstate* qstate, int id,
|
||||
* Signal that the sub-query is finished, no matter whether we are
|
||||
* successful or not. This lets the state machine terminate.
|
||||
*/
|
||||
super->minfo[id] = (void*)DNS64_SUBQUERY_FINISHED;
|
||||
if(!super_dq) {
|
||||
super_dq = (struct dns64_qstate*)regional_alloc(qstate->region,
|
||||
sizeof(*super_dq));
|
||||
super->minfo[id] = super_dq;
|
||||
memset(super_dq, 0, sizeof(*super_dq));
|
||||
super_dq->started_no_cache_store = super->no_cache_store;
|
||||
}
|
||||
super_dq->state = DNS64_SUBQUERY_FINISHED;
|
||||
|
||||
/* If there is no successful answer, we're done. */
|
||||
if (qstate->return_rcode != LDNS_RCODE_NOERROR
|
||||
|| !qstate->return_msg
|
||||
|| !qstate->return_msg->rep
|
||||
|| !reply_find_answer_rrset(&qstate->qinfo,
|
||||
qstate->return_msg->rep))
|
||||
|| !qstate->return_msg->rep) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Use return code from A query in response to client. */
|
||||
if (super->return_rcode != LDNS_RCODE_NOERROR)
|
||||
@@ -805,7 +953,7 @@ dns64_inform_super(struct module_qstate* qstate, int id,
|
||||
}
|
||||
|
||||
/* Store the generated response in cache. */
|
||||
if (!super->no_cache_store &&
|
||||
if ( (!super_dq || !super_dq->started_no_cache_store) &&
|
||||
!dns_cache_store(super->env, &super->qinfo, super->return_msg->rep,
|
||||
0, 0, 0, NULL, super->query_flags))
|
||||
log_err("out of memory");
|
||||
|
||||
+2
-1
@@ -772,12 +772,13 @@ key_get_es_version(uint8_t version[2])
|
||||
const char *name;
|
||||
};
|
||||
|
||||
const int num_versions = 2;
|
||||
struct es_version es_versions[] = {
|
||||
{{0x00, 0x01}, "X25519-XSalsa20Poly1305"},
|
||||
{{0x00, 0x02}, "X25519-XChacha20Poly1305"},
|
||||
};
|
||||
int i;
|
||||
for(i=0; i < (int)sizeof(es_versions); i++){
|
||||
for(i=0; i < num_versions; i++){
|
||||
if(es_versions[i].es_version[0] == version[0] &&
|
||||
es_versions[i].es_version[1] == version[1]){
|
||||
return es_versions[i].name;
|
||||
|
||||
@@ -39,6 +39,10 @@
|
||||
#include "config.h"
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
@@ -118,6 +122,18 @@ dt_msg_init(const struct dt_env *env,
|
||||
}
|
||||
}
|
||||
|
||||
/* check that the socket file can be opened and exists, print error if not */
|
||||
static void
|
||||
check_socket_file(const char* socket_path)
|
||||
{
|
||||
struct stat statbuf;
|
||||
memset(&statbuf, 0, sizeof(statbuf));
|
||||
if(stat(socket_path, &statbuf) < 0) {
|
||||
log_warn("could not open dnstap-socket-path: %s, %s",
|
||||
socket_path, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
struct dt_env *
|
||||
dt_create(const char *socket_path, unsigned num_workers)
|
||||
{
|
||||
@@ -134,6 +150,7 @@ dt_create(const char *socket_path, unsigned num_workers)
|
||||
socket_path);
|
||||
log_assert(socket_path != NULL);
|
||||
log_assert(num_workers > 0);
|
||||
check_socket_file(socket_path);
|
||||
|
||||
env = (struct dt_env *) calloc(1, sizeof(struct dt_env));
|
||||
if (!env)
|
||||
|
||||
+555
-2
@@ -1,8 +1,561 @@
|
||||
29 November 2018: Wouter
|
||||
- iana portlist updated.
|
||||
- Fix chroot auth-zone fix to remove chroot prefix.
|
||||
|
||||
28 November 2018: Wouter
|
||||
- Fix leak in chroot fix for auth-zone.
|
||||
- Fix clang analysis for outside directory build test.
|
||||
|
||||
27 November 2018: Wouter
|
||||
- Fix DNS64 to not store intermediate results in cache, this avoids
|
||||
other threads from picking up the wrong data. The module restores
|
||||
the previous no_cache_store setting when the the module is finished.
|
||||
- Fix #4208: 'stub-no-cache' and 'forward-no-cache' not work.
|
||||
- New and better fix for Fix #4193: Fix that prefetch failure does
|
||||
not overwrite valid cache entry with SERVFAIL.
|
||||
- auth-zone give SERVFAIL when expired, fallback activates when
|
||||
expired, and this is documented in the man page.
|
||||
- stat count SERVFAIL downstream auth-zone queries for expired zones.
|
||||
- Put new logos into windows installer.
|
||||
- Fix windows compile for new rrset roundrobin fix.
|
||||
- Update contrib fastrpz patch for latest release.
|
||||
|
||||
26 November 2018: Wouter
|
||||
- Fix to not set GLOB_NOSORT so the unbound.conf include: files are
|
||||
sorted and in a predictable order.
|
||||
- Fix #4193: Fix that prefetch failure does not overwrite valid cache
|
||||
entry with SERVFAIL.
|
||||
- Add unbound-control view_local_datas command, like local_datas.
|
||||
- Fix that unbound-control can send file for view_local_datas.
|
||||
|
||||
22 November 2018: Wouter
|
||||
- With ./configure --with-pyunbound --with-pythonmodule
|
||||
PYTHON_VERSION=3.6 or with 2.7 unbound can compile and unit tests
|
||||
succeed for the python module.
|
||||
- pythonmod logs the python error and traceback on failure.
|
||||
- ignore debug python module for test in doxygen output.
|
||||
- review fixes for python module.
|
||||
- Fix #4209: Crash in libunbound when called from getdns.
|
||||
- auth zone zonefiles can be in a chroot, the chroot directory
|
||||
components are removed before use.
|
||||
- Fix that empty zonefile means the zonefile is not set and not used.
|
||||
- make depend.
|
||||
|
||||
21 November 2018: Wouter
|
||||
- Scrub NS records from NODATA responses as well.
|
||||
|
||||
20 November 2018: Wouter
|
||||
- Scrub NS records from NXDOMAIN responses to stop fragmentation
|
||||
poisoning of the cache.
|
||||
- Add patch from Jan Vcelak for pythonmod,
|
||||
add sockaddr_storage getters, add support for query callbacks,
|
||||
allow raw address access via comm_reply and update API documentation.
|
||||
- Removed compile warnings in pythonmod sockaddr routines.
|
||||
|
||||
19 November 2018: Wouter
|
||||
- Support SO_REUSEPORT_LB in FreeBSD 12 with the so-reuseport: yes
|
||||
option in unbound.conf.
|
||||
|
||||
6 November 2018: Ralph
|
||||
- Bugfix min-client-subnet-ipv6
|
||||
|
||||
25 October 2018: Ralph
|
||||
- Add min-client-subnet-ipv6 and min-client-subnet-ipv4 options.
|
||||
|
||||
25 October 2018: Wouter
|
||||
- Fix #4191: NXDOMAIN vs SERVFAIL during dns64 PTR query.
|
||||
- Fix #4190: Please create a "ANY" deny option, adds the option
|
||||
deny-any: yes in unbound.conf. This responds with an empty message
|
||||
to queries of type ANY.
|
||||
- Fix #4141: More randomness to rrset-roundrobin.
|
||||
- Fix #4132: Openness/closeness of RANGE intervals in rpl files.
|
||||
- Fix #4126: RTT_band too low on VSAT links with 600+ms latency,
|
||||
adds the option unknown-server-time-limit to unbound.conf that
|
||||
can be increased to avoid the problem.
|
||||
- remade makefile dependencies.
|
||||
- Fix #4152: Logs shows wrong time when using log-time-ascii: yes.
|
||||
|
||||
24 October 2018: Ralph
|
||||
- Add markdel function to ECS slabhash.
|
||||
- Limit ECS scope returned to client to the scope used for caching.
|
||||
- Make lint like previous #4154 fix.
|
||||
|
||||
22 October 2018: Wouter
|
||||
- Fix #4192: unbound-control-setup generates keys not readable by
|
||||
group.
|
||||
- check that the dnstap socket file can be opened and exists, print
|
||||
error if not.
|
||||
- Fix #4154: make ECS_MAX_TREESIZE configurable, with
|
||||
the max-ecs-tree-size-ipv4 and max-ecs-tree-size-ipv6 options.
|
||||
|
||||
22 October 2018: Ralph
|
||||
- Change fast-server-num default to 3.
|
||||
|
||||
8 October 2018: Ralph
|
||||
- Add fast-server-permil and fast-server-num options.
|
||||
- Deprecate low-rtt and low-rtt-permil options.
|
||||
|
||||
8 October 2018: Wouter
|
||||
- Squelch log of failed to tcp initiate after TCP Fastopen failure.
|
||||
|
||||
5 October 2018: Wouter
|
||||
- Squelch EADDRNOTAVAIL errors when the interface goes away,
|
||||
this omits 'can't assign requested address' errors unless
|
||||
verbosity is set to a high value.
|
||||
- Set default for so-reuseport to no for FreeBSD. It is enabled
|
||||
by default for Linux and DragonFlyBSD. The setting can
|
||||
be configured in unbound.conf to override the default.
|
||||
- iana port update.
|
||||
|
||||
2 October 2018: Wouter
|
||||
- updated contrib/fastrpz.patch to apply for this version
|
||||
- dnscrypt.c removed sizeof to get array bounds.
|
||||
- Fix testlock code to set noreturn on error routine.
|
||||
- Remove unused variable from contrib fastrpz/rpz.c and
|
||||
remove unused diagnostic pragmas that themselves generate warnings
|
||||
- clang analyze test is used only when assertions are enabled.
|
||||
|
||||
1 October 2018: Wouter
|
||||
- tag for release 1.8.1rc1. Became release 1.8.1 on 8 oct, with
|
||||
fastrpz.patch fix included. Trunk has 1.8.2 in development.
|
||||
|
||||
27 September 2018: Wouter
|
||||
- Fix #4188: IPv6 forwarders without ipv6 result in SERVFAIL, fixes
|
||||
qname minimisation with a forwarder when connectivity has issues
|
||||
from rejecting responses.
|
||||
|
||||
25 September 2018: Wouter
|
||||
- Perform TLS SNI indication of the host that is being contacted
|
||||
for DNS over TLS service. It sets the configured tls auth name.
|
||||
This is useful for hosts that apart from the DNS over TLS services
|
||||
also provide other (web) services.
|
||||
- Fix #4149: Add SSL cleanup for tcp timeout.
|
||||
|
||||
17 September 2018: Wouter
|
||||
- Fix compile on Mac for unbound, provide explicit_bzero when libc
|
||||
does not have it.
|
||||
- Fix unbound for openssl in FIPS mode, it uses the digests with
|
||||
the EVP call contexts.
|
||||
- Fix that with harden-below-nxdomain and qname minisation enabled
|
||||
some iterator states for nonresponsive domains can get into a
|
||||
state where they waited for an empty list.
|
||||
- Stop UDP to TCP failover after timeouts that causes the ping count
|
||||
to be reset by the TCP time measurement (that exists for TLS),
|
||||
because that causes the UDP part to not be measured as timeout.
|
||||
- Fix #4156: Fix systemd service manager state change notification.
|
||||
|
||||
13 September 2018: Wouter
|
||||
- Fix seed for random backup code to use explicit zero when wiped.
|
||||
- exit log routine is annotated as noreturn function.
|
||||
- free memory leaks in config strlist and str2list insert functions.
|
||||
- do not move unused argv variable after getopt.
|
||||
- Remove unused if clause in testcode.
|
||||
- in testcode, free async ids, initialise array, and check for null
|
||||
pointer during test of the test. And use exit for return to note
|
||||
irregular program stop.
|
||||
- Free memory leak in config strlist append.
|
||||
- make sure nsec3 comparison salt is initialized.
|
||||
- unit test has clang analysis.
|
||||
- remove unused variable assignment from iterator scrub routine.
|
||||
- check for null in delegation point during iterator refetch
|
||||
in forward zone.
|
||||
- neater pointer cast in libunbound context quit routine.
|
||||
- initialize statistics totals for printout.
|
||||
- in authzone check that node exists before adding rrset.
|
||||
- in unbound-anchor, use readwrite memory BIO.
|
||||
- assertion in autotrust that packed rrset is formed correctly.
|
||||
- Fix memory leak when message parse fails partway through copy.
|
||||
- remove unused udpsize assignment in message encode.
|
||||
- nicer bio free code in unbound-anchor.
|
||||
- annotate exit functions with noreturn in unbound-control.
|
||||
|
||||
11 September 2018: Wouter
|
||||
- Fixed unused return value warnings in contrib/fastrpz.patch for
|
||||
asprintf.
|
||||
- Fix to squelch respip warning in unit test, it is printed at
|
||||
higher verbosity settings.
|
||||
- Fix spelling errors.
|
||||
- Fix initialisation in remote.c
|
||||
|
||||
10 September 2018: Wouter
|
||||
- 1.8.1 in svn trunk. (changes from 4,5,.. sep apply).
|
||||
- iana port update.
|
||||
|
||||
5 September 2018: Wouter
|
||||
- Fix spelling error in header, from getdns commit by Andreas Gelmini.
|
||||
|
||||
4 September 2018: Ralph
|
||||
- More explicitly mention the type of ratelimit when applying
|
||||
ip-ratelimit.
|
||||
|
||||
4 September 2018: Wouter
|
||||
- Tag for 1.8.0rc1 release, became 1.8.0 release on 10 Sep 2018.
|
||||
|
||||
31 August 2018: Wouter
|
||||
- Disable minimal-responses in subnet unit tests.
|
||||
|
||||
30 August 2018: Wouter
|
||||
- Fix that a local-zone with a local-zone-type that is transparent
|
||||
in a view with view-first, makes queries check for answers from the
|
||||
local-zones defined outside of views.
|
||||
|
||||
28 August 2018: Ralph
|
||||
- Disable minimal-responses in ipsecmod unit tests.
|
||||
- Added serve-expired-ttl and serve-expired-ttl-reset options.
|
||||
|
||||
27 August 2018: Wouter
|
||||
- Set defaults to yes for a number of options to increase speed and
|
||||
resilience of the server. The so-reuseport, harden-below-nxdomain,
|
||||
and minimal-responses options are enabled by default. They used
|
||||
to be disabled by default, waiting to make sure they worked. They
|
||||
are enabled by default now, and can be disabled explicitly by
|
||||
setting them to "no" in the unbound.conf config file. The reuseport
|
||||
and minimal options increases speed of the server, and should be
|
||||
otherwise harmless. The harden-below-nxdomain option works well
|
||||
together with the recently default enabled qname minimisation, this
|
||||
causes more fetches to use information from the cache.
|
||||
- next release is called 1.8.0.
|
||||
- Fix lintflags for lint on FreeBSD.
|
||||
|
||||
22 August 2018: George
|
||||
- #4140: Expose repinfo (comm_reply) to the inplace_callbacks. This
|
||||
gives access to reply information for the client's communication
|
||||
point when the callback is called before the mesh state (modules).
|
||||
Changes to C and Python's inplace_callback signatures were also
|
||||
necessary.
|
||||
|
||||
21 August 2018: Wouter
|
||||
- log-local-actions: yes option for unbound.conf that logs all the
|
||||
local zone actions, a patch from Saksham Manchanda (Secure64).
|
||||
- #4146: num.query.subnet and num.query.subnet_cache counters.
|
||||
- Fix only misc failure from log-servfail when val-log-level is not
|
||||
enabled.
|
||||
|
||||
17 August 2018: Ralph
|
||||
- Fix classification for QTYPE=CNAME queries when QNAME minimisation is
|
||||
enabled.
|
||||
|
||||
17 August 2018: Wouter
|
||||
- Set libunbound to increase current, because the libunbound change
|
||||
to the event callback function signature. That needs programs,
|
||||
that use it, to recompile against the new header definition.
|
||||
- print servfail info to log as error.
|
||||
- added more servfail printout statements, to the iterator.
|
||||
- log-servfail: yes prints log lines that say why queries are
|
||||
returning SERVFAIL to clients.
|
||||
|
||||
16 August 2018: Wouter
|
||||
- Fix warning on compile without threads.
|
||||
- Fix contrib/fastrpz.patch.
|
||||
|
||||
15 August 2018: Wouter
|
||||
- Fix segfault in auth-zone read and reorder of RRSIGs.
|
||||
|
||||
14 August 2018: Wouter
|
||||
- Fix that printout of error for cycle targets is a verbosity 4
|
||||
printout and does not wrongly print it is a memory error.
|
||||
- Upgraded crosscompile script to include libunbound DLL in the
|
||||
zipfile.
|
||||
|
||||
10 August 2018: Wouter
|
||||
- Fix #4144: dns64 module caches wrong (negative) information.
|
||||
|
||||
9 August 2018: Wouter
|
||||
- unbound-checkconf checks if modules exist and prints if they are
|
||||
not compiled in the name of the wrong module.
|
||||
- document --enable-subnet in doc/README.
|
||||
- Patch for stub-no-cache and forward-no-cache options that disable
|
||||
caching for the contents of that stub or forward, for when you
|
||||
want immediate changes visible, from Bjoern A. Zeeb.
|
||||
|
||||
7 August 2018: Ralph
|
||||
- Make capsforid fallback QNAME minimisation aware.
|
||||
|
||||
7 August 2018: Wouter
|
||||
- Fix #4142: unbound.service.in: improvements and fixes.
|
||||
Add unit dependency ordering (based on systemd-resolved).
|
||||
Add 'CAP_SYS_RESOURCE' to 'CapabilityBoundingSet' (fixes warnings
|
||||
about missing privileges during startup). Add 'AF_INET6' to
|
||||
'RestrictAddressFamilies' (without it IPV6 can't work). From
|
||||
Guido Shanahan.
|
||||
- Patch to implement tcp-connection-limit from Jim Hague (Sinodun).
|
||||
This limits the number of simultaneous TCP client connections
|
||||
from a nominated netblock.
|
||||
- make depend, yacc, lex, doc, headers. And log the limit exceeded
|
||||
message only on high verbosity, so as to not spam the logs when
|
||||
it is busy.
|
||||
|
||||
6 August 2018: Wouter
|
||||
- Fix for #4136: Fix to unconditionally call destroy in daemon.c.
|
||||
|
||||
3 August 2018: George
|
||||
- Expose if a query (or a subquery) was ratelimited (not src IP
|
||||
ratelimiting) to libunbound under 'ub_result.was_ratelimited'.
|
||||
This also introduces a change to 'ub_event_callback_type' in
|
||||
libunbound/unbound-event.h.
|
||||
- Tidy pylib tests.
|
||||
|
||||
3 August 2018: Wouter
|
||||
- Revert previous change for #4136: because it introduces build
|
||||
problems.
|
||||
- New fix for #4136: This one ignores lex without without
|
||||
yylex_destroy.
|
||||
|
||||
1 August 2018: Wouter
|
||||
- Fix to remove systemd sockaddr function check, that is not
|
||||
always present. Make socket activation more lenient. But not
|
||||
different when socket activation is not used.
|
||||
- iana port list update.
|
||||
|
||||
31 July 2018: Wouter
|
||||
- Patches from Jim Hague (Sinodun) for EDNS KeepAlive.
|
||||
- Sort out test runs when the build directory isn't the project
|
||||
root directory.
|
||||
- Add config tcp-idle-timeout (default 30s). This applies to
|
||||
client connections only; the timeout on TCP connections upstream
|
||||
is unaffected.
|
||||
- Error if EDNS Keepalive received over UDP.
|
||||
- Add edns-tcp-keepalive and edns-tcp-keepalive timeout options
|
||||
and implement option in client responses.
|
||||
- Correct and expand manual page entries for keepalive and idle timeout.
|
||||
- Implement progressive backoff of TCP idle/keepalive timeout.
|
||||
- Fix 'make depend' to work when build dir is not project root.
|
||||
- Add delay parameter to streamtcp, -d secs.
|
||||
To be used when testing idle timeout.
|
||||
- From Wouter: make depend, the dependencies in the patches did not
|
||||
apply cleanly. Also remade yacc and lex.
|
||||
- Fix mesh.c incompatible pointer pass.
|
||||
- Please doxygen so it passes.
|
||||
- Fix #4139: Fix unbound-host leaks memory on ANY.
|
||||
|
||||
30 July 2018: Wouter
|
||||
- Fix #4136: insufficiency from mismatch of FLEX capability between
|
||||
released tarball and build host.
|
||||
|
||||
27 July 2018: Wouter
|
||||
- Fix man page, say that chroot is enabled by default.
|
||||
|
||||
26 July 2018: Wouter
|
||||
- Fix #4135: 64-bit Windows Installer Creates Entries Under The
|
||||
Wrong Registry Key, reported by Brian White.
|
||||
|
||||
23 July 2018: Wouter
|
||||
- Fix use-systemd readiness signalling, only when use-systemd is yes
|
||||
and not in signal handler.
|
||||
|
||||
20 July 2018: Wouter
|
||||
- Fix #4130: print text describing -dd and unbound-checkconf on
|
||||
config file read error at startup, the errors may have been moved
|
||||
away by the startup process.
|
||||
- Fix #4131: for solaris, error YY_CURRENT_BUFFER undeclared.
|
||||
|
||||
19 July 2018: Wouter
|
||||
- Fix #4129 unbound-control error message with wrong cert permissions
|
||||
is too cryptic.
|
||||
|
||||
17 July 2018: Wouter
|
||||
- Fix #4127 unbound -h does not list -p help.
|
||||
- Print error if SSL name verification configured but not available
|
||||
in the ssl library.
|
||||
- Fix that ratelimit and ip-ratelimit are applied after reload of
|
||||
changed config file.
|
||||
- Resize ratelimit and ip-ratelimit caches if changed on reload.
|
||||
|
||||
16 July 2018: Wouter
|
||||
- Fix qname minimisation NXDOMAIN validation lookup failures causing
|
||||
error_supers assertion fails.
|
||||
- Squelch can't bind socket errors with Permission denied unless
|
||||
verbosity is 4 or higher, for UDP outgoing sockets.
|
||||
|
||||
12 July 2018: Wouter
|
||||
- Fix to improve systemd socket activation code file descriptor
|
||||
assignment.
|
||||
- Fix for 4126 that the #define for UNKNOWN_SERVER_NICENESS can be more
|
||||
easily changed to adjust default rtt assumptions.
|
||||
|
||||
10 July 2018: Wouter
|
||||
- Note in documentation that the cert name match code needs
|
||||
OpenSSL 1.1.0 or later to be enabled.
|
||||
|
||||
6 July 2018: Wouter
|
||||
- Fix documentation ambiguity for tls-win-cert in tls-upstream and
|
||||
forward-tls-upstream docs.
|
||||
- iana port update.
|
||||
- Note RFC8162 support. SMIMEA record type can be read in by the
|
||||
zone record parser.
|
||||
- Fix round robin for failed addresses with prefer-ip6: yes
|
||||
|
||||
4 July 2018: Wouter
|
||||
- Fix #4112: Fix that unbound-anchor -f /etc/resolv.conf will not pass
|
||||
if DNSSEC is not enabled. New option -R allows fallback from
|
||||
resolv.conf to direct queries.
|
||||
|
||||
3 July 2018: Wouter
|
||||
- Better documentation for unblock-lan-zones and insecure-lan-zones
|
||||
config statements.
|
||||
- Fix permission denied printed for auth zone probe random port nrs.
|
||||
|
||||
2 July 2018: Wouter
|
||||
- Fix checking for libhiredis printout in configure output.
|
||||
- Fix typo on man page in ip-address description.
|
||||
- Update libunbound/python/examples/dnssec_test.py example code to
|
||||
also set the 20326 trust anchor for the root in the example code.
|
||||
|
||||
29 June 2018: Wouter
|
||||
- dns64-ignore-aaaa: config option to list domain names for which the
|
||||
existing AAAA is ignored and dns64 processing is used on the A
|
||||
record.
|
||||
|
||||
28 June 2018: Wouter
|
||||
- num.queries.tls counter for queries over TLS.
|
||||
- log port number with err_addr logs.
|
||||
|
||||
27 June 2018: Wouter
|
||||
- #4109: Fix that package config depends on python unconditionally.
|
||||
- Patch, do not export python from pkg-config, from Petr Menšík.
|
||||
|
||||
26 June 2018: Wouter
|
||||
- Partial fix for permission denied on IPv6 address on FreeBSD.
|
||||
- Fix that auth-zone master reply with current SOA serial does not
|
||||
stop scan of masters for an updated zone.
|
||||
- Fix that auth-zone does not start the wait timer without checking
|
||||
if the wait timer has already been started.
|
||||
|
||||
21 June 2018: Wouter
|
||||
- #4108: systemd reload hang fix.
|
||||
- Fix usage printout for unbound-host, hostname has to be last
|
||||
argument on BSDs and Windows.
|
||||
|
||||
19 June 2018: Wouter
|
||||
- Fix for unbound-control on Windows and set TCP socket parameters
|
||||
more closely.
|
||||
This fix is part of 1.7.3.
|
||||
- Windows example service.conf edited with more windows specific
|
||||
configuration.
|
||||
- Fix windows unbound-control no cert bad file descriptor error.
|
||||
This fix is part of 1.7.3.
|
||||
|
||||
18 June 2018: Wouter
|
||||
- Fix that control-use-cert: no works for 127.0.0.1 to disable certs.
|
||||
This fix is part of 1.7.3rc2.
|
||||
- Fix unbound-checkconf for control-use-cert.
|
||||
This fix is part of 1.7.3.
|
||||
|
||||
15 June 2018: Wouter
|
||||
- tag for 1.7.3rc1.
|
||||
- trunk has 1.7.4.
|
||||
- unbound-control auth_zone_reload _zone_ option rereads the zonefile.
|
||||
- unbound-control auth_zone_transfer _zone_ option starts the probe
|
||||
sequence for a master to transfer the zone from and transfers when
|
||||
a new zone version is available.
|
||||
|
||||
14 June 2018: Wouter
|
||||
- #4103: Fix that auth-zone does not insist on SOA record first in
|
||||
file for url downloads.
|
||||
- Fix that first control-interface determines if TLS is used. Warn
|
||||
when IP address interfaces are used without TLS.
|
||||
- Fix nettle compile.
|
||||
|
||||
12 June 2018: Ralph
|
||||
- Don't count CNAME response types received during qname minimisation as
|
||||
query restart.
|
||||
|
||||
12 June 2018: Wouter
|
||||
- #4102 for NSD, but for Unbound. Named unix pipes do not use
|
||||
certificate and key files, access can be restricted with file and
|
||||
directory permissions. The option control-use-cert is no longer
|
||||
used, and ignored if found in unbound.conf.
|
||||
- Rename tls-additional-ports to tls-additional-port, because every
|
||||
line adds one port.
|
||||
- Fix buffer size warning in unit test.
|
||||
- remade dependencies in the Makefile.
|
||||
|
||||
6 June 2018: Wouter
|
||||
- Patch to fix openwrt for mac os build darwin detection in configure.
|
||||
|
||||
5 June 2018: Wouter
|
||||
- Fix crash if ratelimit taken into use with unbound-control
|
||||
instead of with unbound.conf.
|
||||
|
||||
4 June 2018: Wouter
|
||||
- Fix deadlock caused by incoming notify for auth-zone.
|
||||
- tag for 1.7.2rc1, became 1.7.2 release on 11 June 2018,
|
||||
trunk is 1.7.3 in development from this point.
|
||||
- #4100: Fix stub reprime when it becomes useless.
|
||||
|
||||
1 June 2018: Wouter
|
||||
- Rename additional-tls-port to tls-additional-ports.
|
||||
The older name is accepted for backwards compatibility.
|
||||
|
||||
30 May 2018: Wouter
|
||||
- Patch from Syzdek: Add ability to ignore RD bit and treat all
|
||||
requests as if the RD bit is set.
|
||||
|
||||
29 May 2018: Wouter
|
||||
- in compat/arc4random call getentropy_urandom when getentropy fails
|
||||
with ENOSYS.
|
||||
- Fix that fallback for windows port.
|
||||
|
||||
28 May 2018: Wouter
|
||||
- Fix windows tcp and tls spin on events.
|
||||
- Add routine from getdns to add windows cert store to the SSL_CTX.
|
||||
- tls-win-cert option that adds the system certificate store for
|
||||
authenticating DNS-over-TLS connections. It can be used instead
|
||||
of the tls-cert-bundle option, or with it to add certificates.
|
||||
|
||||
25 May 2018: Wouter
|
||||
- For TCP and TLS connections that don't establish, perform address
|
||||
update in infra cache, so future selections can exclude them.
|
||||
- Fix that tcp sticky events are removed for closed fd on windows.
|
||||
- Fix close events for tcp only.
|
||||
|
||||
24 May 2018: Wouter
|
||||
- Fix that libunbound can do DNS-over-TLS, when configured.
|
||||
- Fix that windows unbound service can use DNS-over-TLS.
|
||||
- unbound-host initializes ssl (for potential DNS-over-TLS usage
|
||||
inside libunbound), when ssl upstream or a cert-bundle is configured.
|
||||
|
||||
23 May 2018: Wouter
|
||||
- Use accept4 to speed up incoming TCP (and TLS) connections,
|
||||
available on Linux, FreeBSD and OpenBSD.
|
||||
|
||||
17 May 2018: Ralph
|
||||
- Qname minimisation default changed to yes.
|
||||
|
||||
15 May 2018: Wouter
|
||||
- Fix low-rtt-pct to low-rtt-permil, as it is parts in one thousand.
|
||||
|
||||
11 May 2018: Wouter
|
||||
- Fix contrib/libunbound.pc for libssl libcrypto references,
|
||||
from https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=226914
|
||||
|
||||
7 May 2018: Wouter
|
||||
- Fix windows to not have sticky TLS events for TCP.
|
||||
- Fix read of DNS over TLS length and data in one read call.
|
||||
- Fix mesh state assertion failure due to callback removal.
|
||||
|
||||
3 May 2018: Wouter
|
||||
- Fix that configure --with-libhiredis also turns on cachedb.
|
||||
- Fix gcc 8 buffer warning in testcode.
|
||||
- Fix function type cast warning in libunbound context callback type.
|
||||
|
||||
2 May 2018: Wouter
|
||||
- Fix fail to reject dead peers in forward-zone, with ssl-upstream.
|
||||
|
||||
1 May 2018: Wouter
|
||||
- Fix that unbound-control reload frees the rrset keys and returns
|
||||
the memory pages to the system.
|
||||
|
||||
30 April 2018: Wouter
|
||||
- Fix spelling error in man page and note defaults as no instead of
|
||||
off.
|
||||
|
||||
26 April 2018: Wouter
|
||||
- Fix for crash in daemon_cleanup with dnstap during reload,
|
||||
from Saksham Manchanda.
|
||||
- Also that for dnscrypt.
|
||||
- tag for 1.7.1rc1 release.
|
||||
- tag for 1.7.1rc1 release. Became 1.7.1 release on 3 May, trunk
|
||||
is from here 1.7.2 in development.
|
||||
|
||||
25 April 2018: Ralph
|
||||
- Fix memory leak when caching wildcard records for aggressive NSEC use
|
||||
@@ -1493,7 +2046,7 @@
|
||||
compatibility with cisco dns guard. This lowers false positives.
|
||||
|
||||
18 April 2016: Wouter
|
||||
- Fix some malformed reponses to edns queries get fallback to nonedns.
|
||||
- Fix some malformed responses to edns queries get fallback to nonedns.
|
||||
|
||||
15 April 2016: Wouter
|
||||
- cachedb module event handling design.
|
||||
|
||||
@@ -76,6 +76,8 @@ The DNSTAP code has BSD license in dnstap/dnstap.c.
|
||||
Disable support for RSASHA256 and RSASHA512 crypto.
|
||||
* --disable-gost
|
||||
Disable support for GOST crypto, RFC 5933.
|
||||
* --enable-subnet
|
||||
Enable EDNS client subnet processing.
|
||||
|
||||
* 'make test' runs a series of self checks.
|
||||
|
||||
|
||||
+62
-15
@@ -103,7 +103,7 @@ server:
|
||||
# so-sndbuf: 0
|
||||
|
||||
# use SO_REUSEPORT to distribute queries over threads.
|
||||
# so-reuseport: no
|
||||
# so-reuseport: yes
|
||||
|
||||
# use IP_TRANSPARENT so the interface: addresses can be non-local
|
||||
# and you can config non-existing IPs that are going to work later on
|
||||
@@ -145,6 +145,10 @@ server:
|
||||
# msec to wait before close of port on timeout UDP. 0 disables.
|
||||
# delay-close: 0
|
||||
|
||||
# msec for waiting for an unknown server to reply. Increase if you
|
||||
# are behind a slow satellite link, to eg. 1128.
|
||||
# unknown-server-time-limit: 376
|
||||
|
||||
# the amount of memory to use for the RRset cache.
|
||||
# plain value in bytes or you can append k, m or G. default is "4Mb".
|
||||
# rrset-cache-size: 4m
|
||||
@@ -212,6 +216,15 @@ server:
|
||||
# Default is 0, system default MSS.
|
||||
# outgoing-tcp-mss: 0
|
||||
|
||||
# Idle TCP timeout, connection closed in milliseconds
|
||||
# tcp-idle-timeout: 30000
|
||||
|
||||
# Enable EDNS TCP keepalive option.
|
||||
# edns-tcp-keepalive: no
|
||||
|
||||
# Timeout for EDNS TCP keepalive, in msec.
|
||||
# edns-tcp-keepalive-timeout: 120000
|
||||
|
||||
# Use systemd socket activation for UDP, TCP, and control sockets.
|
||||
# use-systemd: no
|
||||
|
||||
@@ -223,7 +236,8 @@ server:
|
||||
# to this server. Specify classless netblocks with /size and action.
|
||||
# By default everything is refused, except for localhost.
|
||||
# Choose deny (drop message), refuse (polite error reply),
|
||||
# allow (recursive ok), allow_snoop (recursive and nonrecursive ok)
|
||||
# allow (recursive ok), allow_setrd (recursive ok, rd bit is forced on),
|
||||
# allow_snoop (recursive and nonrecursive ok)
|
||||
# deny_non_local (drop queries unless can be answered from local-data)
|
||||
# refuse_non_local (like deny_non_local but polite error reply).
|
||||
# access-control: 0.0.0.0/0 refuse
|
||||
@@ -308,6 +322,13 @@ server:
|
||||
# timetoresolve, fromcache and responsesize.
|
||||
# log-replies: no
|
||||
|
||||
# log the local-zone actions, like local-zone type inform is enabled
|
||||
# also for the other local zone types.
|
||||
# log-local-actions: no
|
||||
|
||||
# print log lines that say why queries return SERVFAIL to clients.
|
||||
# log-servfail: no
|
||||
|
||||
# the pid file. Can be an absolute path outside of chroot/work dir.
|
||||
# pidfile: "@UNBOUND_PIDFILE@"
|
||||
|
||||
@@ -356,7 +377,7 @@ server:
|
||||
# harden-dnssec-stripped: yes
|
||||
|
||||
# Harden against queries that fall under dnssec-signed nxdomain names.
|
||||
# harden-below-nxdomain: no
|
||||
# harden-below-nxdomain: yes
|
||||
|
||||
# Harden the referral path by performing additional queries for
|
||||
# infrastructure data. Validates the replies (if possible).
|
||||
@@ -372,7 +393,7 @@ server:
|
||||
# Sent minimum amount of information to upstream servers to enhance
|
||||
# privacy. Only sent minimum required labels of the QNAME and set QTYPE
|
||||
# to A when possible.
|
||||
# qname-minimisation: no
|
||||
# qname-minimisation: yes
|
||||
|
||||
# QNAME minimisation in strict mode. Do not fall-back to sending full
|
||||
# QNAME to potentially broken nameservers. A lot of domains will not be
|
||||
@@ -432,12 +453,15 @@ server:
|
||||
# if yes, perform key lookups adjacent to normal lookups.
|
||||
# prefetch-key: no
|
||||
|
||||
# deny queries of type ANY with an empty response.
|
||||
# deny-any: 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
|
||||
# minimal-responses: yes
|
||||
|
||||
# true to disable DNSSEC lameness check in iterator.
|
||||
# disable-dnssec-lame-check: no
|
||||
@@ -526,6 +550,16 @@ server:
|
||||
# Serve expired responses from cache, with TTL 0 in the response,
|
||||
# and then attempt to fetch the data afresh.
|
||||
# serve-expired: no
|
||||
#
|
||||
# Limit serving of expired responses to configured seconds after
|
||||
# expiration. 0 disables the limit.
|
||||
# serve-expired-ttl: 0
|
||||
#
|
||||
# Set the TTL of expired records to the serve-expired-ttl value after a
|
||||
# failed attempt to retrieve the record from upstream. This makes sure
|
||||
# that the expired records will be served as long as there are queries
|
||||
# for it.
|
||||
# serve-expired-ttl-reset: no
|
||||
|
||||
# Have the validator log failed validations for your diagnosis.
|
||||
# 0: off. 1: A line per failed user query. 2: With reason and bad IP.
|
||||
@@ -681,13 +715,19 @@ server:
|
||||
# Certificates used to authenticate connections made upstream.
|
||||
# tls-cert-bundle: ""
|
||||
|
||||
# Add system certs to the cert bundle, from the Windows Cert Store
|
||||
# tls-win-cert: no
|
||||
|
||||
# Also serve tls on these port numbers (eg. 443, ...), by listing
|
||||
# additional-tls-port: portno for each of the port numbers.
|
||||
# tls-additional-port: portno for each of the port numbers.
|
||||
|
||||
# DNS64 prefix. Must be specified when DNS64 is use.
|
||||
# Enable dns64 in module-config. Used to synthesize IPv6 from IPv4.
|
||||
# dns64-prefix: 64:ff9b::0/96
|
||||
|
||||
# DNS64 ignore AAAA records for these domains and use A instead.
|
||||
# dns64-ignore-aaaa: "example.com"
|
||||
|
||||
# ratelimit for uncached, new queries, this limits recursion effort.
|
||||
# ratelimiting is experimental, and may help against randomqueryflood.
|
||||
# if 0(default) it is disabled, otherwise state qps allowed per zone.
|
||||
@@ -721,12 +761,15 @@ server:
|
||||
# 0 blocks when ip is ratelimited, otherwise let 1/xth traffic through
|
||||
# ip-ratelimit-factor: 10
|
||||
|
||||
# what is considered a low rtt (ping time for upstream server), in msec
|
||||
# low-rtt: 45
|
||||
# select low rtt this many times out of 1000. 0 means the fast server
|
||||
# select is disabled. prefetches are not sped up.
|
||||
# low-rtt-pct: 0
|
||||
# Limit the number of connections simultaneous from a netblock
|
||||
# tcp-connection-limit: 192.0.2.0/24 12
|
||||
|
||||
# select from the fastest servers this many times out of 1000. 0 means
|
||||
# the fast server select is disabled. prefetches are not sped up.
|
||||
# fast-server-permil: 0
|
||||
# the number of servers that will be used in the fast server selection.
|
||||
# fast-server-num: 3
|
||||
|
||||
# Specific options for ipsecmod. unbound needs to be configured with
|
||||
# --enable-ipsecmod for these to take effect.
|
||||
#
|
||||
@@ -770,18 +813,20 @@ remote-control:
|
||||
# set up the keys and certificates with unbound-control-setup.
|
||||
# control-enable: no
|
||||
|
||||
# Set to no and use an absolute path as control-interface to use
|
||||
# a unix local named pipe for unbound-control.
|
||||
# control-use-cert: yes
|
||||
|
||||
# what interfaces are listened to for remote control.
|
||||
# give 0.0.0.0 and ::0 to listen to all interfaces.
|
||||
# set to an absolute path to use a unix local name pipe, certificates
|
||||
# are not used for that, so key and cert files need not be present.
|
||||
# control-interface: 127.0.0.1
|
||||
# control-interface: ::1
|
||||
|
||||
# port number for remote control operations.
|
||||
# control-port: 8953
|
||||
|
||||
# for localhost, you can disable use of TLS by setting this to "no"
|
||||
# For local sockets this option is ignored, and TLS is not used.
|
||||
# control-use-cert: "yes"
|
||||
|
||||
# unbound server key file.
|
||||
# server-key-file: "@UNBOUND_RUN_DIR@/unbound_server.key"
|
||||
|
||||
@@ -808,6 +853,7 @@ remote-control:
|
||||
# stub-prime: no
|
||||
# stub-first: no
|
||||
# stub-tls-upstream: no
|
||||
# stub-no-cache: no
|
||||
# stub-zone:
|
||||
# name: "example.org"
|
||||
# stub-host: ns.example.com.
|
||||
@@ -824,6 +870,7 @@ remote-control:
|
||||
# forward-addr: 192.0.2.73@5355 # forward to port 5355.
|
||||
# forward-first: no
|
||||
# forward-tls-upstream: no
|
||||
# forward-no-cache: no
|
||||
# forward-zone:
|
||||
# name: "example.org"
|
||||
# forward-host: fwd.example.com
|
||||
|
||||
@@ -109,6 +109,11 @@ It does so, because the tool when used for bootstrapping the recursive
|
||||
resolver, cannot use that recursive resolver itself because it is bootstrapping
|
||||
that server.
|
||||
.TP
|
||||
.B \-R
|
||||
Allow fallback from \-f resolv.conf file to direct root servers query.
|
||||
It allows you to prefer local resolvers, but fallback automatically
|
||||
to direct root query if they do not respond or do not support DNSSEC.
|
||||
.TP
|
||||
.B \-v
|
||||
More verbose. Once prints informational messages, multiple times may enable
|
||||
large debug amounts (such as full certificates or byte\-dumps of downloaded
|
||||
|
||||
@@ -293,6 +293,18 @@ ips are dropped before checking the cache.
|
||||
List the auth zones that are configured. Printed one per line with a
|
||||
status, indicating if the zone is expired and current serial number.
|
||||
.TP
|
||||
.B auth_zone_reload \fIzone\fR
|
||||
Reload the auth zone from zonefile. The zonefile is read in overwriting
|
||||
the current contents of the zone in memory. This changes the auth zone
|
||||
contents itself, not the cache contents. Such cache contents exists if
|
||||
you set unbound to validate with for-upstream yes and that can be cleared
|
||||
with \fBflush_zone\fR \fIzone\fR.
|
||||
.TP
|
||||
.B auth_zone_transfer \fIzone\fR
|
||||
Transfer the auth zone from master. The auth zone probe sequence is started,
|
||||
where the masters are probed to see if they have an updated zone (with the SOA
|
||||
serial check). And then the zone is transferred for a newer zone version.
|
||||
.TP
|
||||
.B view_list_local_zones \fIview\fR
|
||||
\fIlist_local_zones\fR for given view.
|
||||
.TP
|
||||
@@ -310,6 +322,9 @@ status, indicating if the zone is expired and current serial number.
|
||||
.TP
|
||||
.B view_local_data_remove \fIview\fR \fIname
|
||||
\fIlocal_data_remove\fR for given view.
|
||||
.TP
|
||||
.B view_local_datas \fIview\fR
|
||||
Add a list of \fIlocal_data\fR for given view from stdin. Like local_datas.
|
||||
.SH "EXIT CODE"
|
||||
The unbound\-control program exits with status code 1 on error, 0 on success.
|
||||
.SH "SET UP"
|
||||
@@ -515,6 +530,10 @@ Number of queries that were made using TCP towards the unbound server.
|
||||
Number of queries that the unbound server made using TCP outgoing towards
|
||||
other servers.
|
||||
.TP
|
||||
.I num.query.tls
|
||||
Number of queries that were made using TLS towards the unbound server.
|
||||
These are also counted in num.query.tcp, because TLS uses TCP.
|
||||
.TP
|
||||
.I num.query.ipv6
|
||||
Number of queries that were made using IPv6 towards the unbound server.
|
||||
.TP
|
||||
@@ -625,6 +644,14 @@ answered using cached data.
|
||||
The number of queries answered using cached NSEC records with NXDOMAIN RCODE.
|
||||
These queries would otherwise have been sent to the internet, but are now
|
||||
answered using cached data.
|
||||
.TP
|
||||
.I num.query.subnet
|
||||
Number of queries that got an answer that contained EDNS client subnet data.
|
||||
.TP
|
||||
.I num.query.subnet_cache
|
||||
Number of queries answered from the edns client subnet cache. These are
|
||||
counted as cachemiss by the main counters, but hit the client subnet
|
||||
specific cache, after getting processed by the edns client subnet module.
|
||||
.SH "FILES"
|
||||
.TP
|
||||
.I @ub_conf_file@
|
||||
|
||||
@@ -12,20 +12,20 @@
|
||||
\- unbound DNS lookup utility
|
||||
.SH "SYNOPSIS"
|
||||
.B unbound\-host
|
||||
.RB [ \-C
|
||||
.IR configfile ]
|
||||
.RB [ \-vdhr46D ]
|
||||
.RB [ \-c
|
||||
.IR class ]
|
||||
.RB [ \-t
|
||||
.IR type ]
|
||||
.I hostname
|
||||
.RB [ \-y
|
||||
.IR key ]
|
||||
.RB [ \-f
|
||||
.IR keyfile ]
|
||||
.RB [ \-F
|
||||
.IR namedkeyfile ]
|
||||
.RB [ \-C
|
||||
.IR configfile ]
|
||||
.I hostname
|
||||
.SH "DESCRIPTION"
|
||||
.B Unbound\-host
|
||||
uses the unbound validating resolver to query for the hostname and display
|
||||
@@ -86,6 +86,8 @@ are read.
|
||||
.B \-C \fIconfigfile
|
||||
Uses the specified unbound.conf to prime
|
||||
.IR libunbound (3).
|
||||
Pass it as first argument if you want to override some options from the
|
||||
config file with further arguments on the commandline.
|
||||
.TP
|
||||
.B \-r
|
||||
Read /etc/resolv.conf, and use the forward DNS servers from there (those could
|
||||
|
||||
+176
-40
@@ -121,7 +121,7 @@ interface and port number), if not specified the default port (from
|
||||
\fBport\fR) is used.
|
||||
.TP
|
||||
.B ip\-address: \fI<ip address[@port]>
|
||||
Same as interface: (for easy of compatibility with nsd.conf).
|
||||
Same as interface: (for ease of compatibility with nsd.conf).
|
||||
.TP
|
||||
.B interface\-automatic: \fI<yes or no>
|
||||
Detect source interface on UDP queries and copy them to replies. This
|
||||
@@ -253,6 +253,12 @@ eg. 1500 msec. When timeouts happen you need extra sockets, it checks
|
||||
the ID and remote IP of packets, and unwanted packets are added to the
|
||||
unwanted packet counter.
|
||||
.TP
|
||||
.B unknown\-server\-time\-limit: \fI<msec>
|
||||
The wait time in msec for waiting for an unknown server to reply.
|
||||
Increase this if you are behind a slow satellite link, to eg. 1128.
|
||||
That would then avoid re\-querying every initial query because it times out.
|
||||
Default is 376 msec.
|
||||
.TP
|
||||
.B so\-rcvbuf: \fI<number>
|
||||
If not 0, then set the SO_RCVBUF socket option to get more buffer
|
||||
space on UDP port 53 incoming queries. So that short spikes on busy
|
||||
@@ -278,9 +284,9 @@ to so\-rcvbuf.
|
||||
.B so\-reuseport: \fI<yes or no>
|
||||
If yes, then open dedicated listening sockets for incoming queries for each
|
||||
thread and try to set the SO_REUSEPORT socket option on each socket. May
|
||||
distribute incoming queries to threads more evenly. Default is no. On Linux
|
||||
it is supported in kernels >= 3.9. On other systems, FreeBSD, OSX it may
|
||||
also work. You can enable it (on any platform and kernel),
|
||||
distribute incoming queries to threads more evenly. Default is yes.
|
||||
On Linux it is supported in kernels >= 3.9. On other systems, FreeBSD, OSX
|
||||
it may also work. You can enable it (on any platform and kernel),
|
||||
it then attempts to open the port and passes the option if it was available
|
||||
at compile time, if that works it is used, if it fails, it continues
|
||||
silently (unless verbosity 3) without the option.
|
||||
@@ -389,6 +395,37 @@ Note that not all platform supports socket option to set MSS (TCP_MAXSEG).
|
||||
Default is system default MSS determined by interface MTU and
|
||||
negotiation between Unbound and other servers.
|
||||
.TP
|
||||
.B tcp-idle-timeout: \fI<msec>\fR
|
||||
The period Unbound will wait for a query on a TCP connection.
|
||||
If this timeout expires Unbound closes the connection.
|
||||
This option defaults to 30000 milliseconds.
|
||||
When the number of free incoming TCP buffers falls below 50% of the
|
||||
total number configured, the option value used is progressively
|
||||
reduced, first to 1% of the configured value, then to 0.2% of the
|
||||
configured value if the number of free buffers falls below 35% of the
|
||||
total number configured, and finally to 0 if the number of free buffers
|
||||
falls below 20% of the total number configured. A minimum timeout of
|
||||
200 milliseconds is observed regardless of the option value used.
|
||||
.TP
|
||||
.B edns-tcp-keepalive: \fI<yes or no>\fR
|
||||
Enable or disable EDNS TCP Keepalive. Default is no.
|
||||
.TP
|
||||
.B edns-tcp-keepalive-timeout: \fI<msec>\fR
|
||||
The period Unbound will wait for a query on a TCP connection when
|
||||
EDNS TCP Keepalive is active. If this timeout expires Unbound closes
|
||||
the connection. If the client supports the EDNS TCP Keepalive option,
|
||||
Unbound sends the timeout value to the client to encourage it to
|
||||
close the connection before the server times out.
|
||||
This option defaults to 120000 milliseconds.
|
||||
When the number of free incoming TCP buffers falls below 50% of
|
||||
the total number configured, the advertised timeout is progressively
|
||||
reduced to 1% of the configured value, then to 0.2% of the configured
|
||||
value if the number of free buffers falls below 35% of the total number
|
||||
configured, and finally to 0 if the number of free buffers falls below
|
||||
20% of the total number configured.
|
||||
A minimum actual timeout of 200 milliseconds is observed regardless of the
|
||||
advertised timeout.
|
||||
.TP
|
||||
.B tcp\-upstream: \fI<yes or no>
|
||||
Enable or disable whether the upstream queries use TCP only for transport.
|
||||
Default is no. Useful in tunneling scenarios.
|
||||
@@ -403,6 +440,8 @@ Enabled or disable whether the upstream queries use TLS only for transport.
|
||||
Default is no. Useful in tunneling scenarios. The TLS contains plain DNS in
|
||||
TCP wireformat. The other server must support this (see
|
||||
\fBtls\-service\-key\fR).
|
||||
If you enable this, also configure a tls\-cert\-bundle or use tls\-win\-cert to
|
||||
load CA certs, otherwise the connections cannot be authenticated.
|
||||
.TP
|
||||
.B ssl\-upstream: \fI<yes or no>
|
||||
Alternate syntax for \fBtls\-upstream\fR. If both are present in the config
|
||||
@@ -444,8 +483,14 @@ urls, and also DNS over TLS connections.
|
||||
.B ssl\-cert\-bundle: \fI<file>
|
||||
Alternate syntax for \fBtls\-cert\-bundle\fR.
|
||||
.TP
|
||||
.B additional\-tls\-port: \fI<portnr>
|
||||
List portnumbers as additional\-tls\-port, and when interfaces are defined,
|
||||
.B tls\-win\-cert: \fI<yes or no>
|
||||
Add the system certificates to the cert bundle certificates for authentication.
|
||||
If no cert bundle, it uses only these certificates. Default is no.
|
||||
On windows this option uses the certificates from the cert store. Use
|
||||
the tls\-cert\-bundle option on other systems.
|
||||
.TP
|
||||
.B tls\-additional\-port: \fI<portnr>
|
||||
List portnumbers as tls\-additional\-port, and when interfaces are defined,
|
||||
eg. with the @port suffix, as this port number, they provide dns over TLS
|
||||
service. Can list multiple, each on a new statement.
|
||||
.TP
|
||||
@@ -458,10 +503,16 @@ Enable or disable whether the unbound server forks into the background as
|
||||
a daemon. Set the value to \fIno\fR when unbound runs as systemd service.
|
||||
Default is yes.
|
||||
.TP
|
||||
.B tcp\-connection\-limit: \fI<IP netblock> <limit>
|
||||
Allow up to \fIlimit\fR simultaneous TCP connections from the given netblock.
|
||||
When at the limit, further connections are accepted but closed immediately.
|
||||
This option is experimental at this time.
|
||||
.TP
|
||||
.B access\-control: \fI<IP netblock> <action>
|
||||
The netblock is given as an IP4 or IP6 address with /size appended for a
|
||||
classless network block. The action can be \fIdeny\fR, \fIrefuse\fR,
|
||||
\fIallow\fR, \fIallow_snoop\fR, \fIdeny_non_local\fR or \fIrefuse_non_local\fR.
|
||||
\fIallow\fR, \fIallow_setrd\fR, \fIallow_snoop\fR, \fIdeny_non_local\fR or
|
||||
\fIrefuse_non_local\fR.
|
||||
The most specific netblock match is used, if none match \fIdeny\fR is used.
|
||||
.IP
|
||||
The action \fIdeny\fR stops queries from hosts from that netblock.
|
||||
@@ -480,6 +531,15 @@ in the reply. This supports normal operations where nonrecursive queries
|
||||
are made for the authoritative data. For nonrecursive queries any replies
|
||||
from the dynamic cache are refused.
|
||||
.IP
|
||||
The \fIallow_setrd\fR action ignores the recursion desired (RD) bit and
|
||||
treats all requests as if the recursion desired bit is set. Note that this
|
||||
behavior violates RFC 1034 which states that a name server should never perform
|
||||
recursive service unless asked via the RD bit since this interferes with
|
||||
trouble shooting of name servers and their databases. This prohibited behavior
|
||||
may be useful if another DNS server must forward requests for specific
|
||||
zones to a resolver DNS server, but only supports stub domains and
|
||||
sends queries to the resolver DNS server with the RD bit cleared.
|
||||
.IP
|
||||
The action \fIallow_snoop\fR gives nonrecursive access too. This give
|
||||
both recursive and non recursive access. The name \fIallow_snoop\fR refers
|
||||
to cache snooping, a technique to use nonrecursive queries to examine
|
||||
@@ -539,8 +599,9 @@ to chroot and dropping permissions. This allows the pidfile to be
|
||||
Additionally, unbound may need to access /dev/random (for entropy)
|
||||
from inside the chroot.
|
||||
.IP
|
||||
If given a chroot is done to the given directory. The default is
|
||||
"@UNBOUND_CHROOT_DIR@". If you give "" no chroot is performed.
|
||||
If given a chroot is done to the given directory. By default chroot is
|
||||
enabled and the default is "@UNBOUND_CHROOT_DIR@". If you give "" no
|
||||
chroot is performed.
|
||||
.TP
|
||||
.B username: \fI<name>
|
||||
If given, after binding the port the user privileges are dropped. Default is
|
||||
@@ -600,6 +661,16 @@ Default is no. Note that it takes time to print these
|
||||
lines which makes the server (significantly) slower. Odd (nonprintable)
|
||||
characters in names are printed as '?'.
|
||||
.TP
|
||||
.B log\-local\-actions: \fI<yes or no>
|
||||
Print log lines to inform about local zone actions. These lines are like the
|
||||
local\-zone type inform prints out, but they are also printed for the other
|
||||
types of local zones.
|
||||
.TP
|
||||
.B log\-servfail: \fI<yes or no>
|
||||
Print log lines that say why queries return SERVFAIL to clients.
|
||||
This is separate from the verbosity debug logs, much smaller, and printed
|
||||
at the error level, not the info level of debug info from verbosity.
|
||||
.TP
|
||||
.B pidfile: \fI<filename>
|
||||
The process id is written to the file. Default is "@UNBOUND_PIDFILE@".
|
||||
So,
|
||||
@@ -682,7 +753,7 @@ noerror for empty nonterminals, hence this is possible. Very old software
|
||||
might return nxdomain for empty nonterminals (that usually happen for reverse
|
||||
IP address lookups), and thus may be incompatible with this. To try to avoid
|
||||
this only DNSSEC-secure nxdomains are used, because the old software does not
|
||||
have DNSSEC. Default is off.
|
||||
have DNSSEC. Default is on.
|
||||
The nxdomain must be secure, this means nsec3 with optout is insufficient.
|
||||
.TP
|
||||
.B harden\-referral\-path: \fI<yes or no>
|
||||
@@ -691,7 +762,7 @@ infrastructure data. Validates the replies if trust anchors are configured
|
||||
and the zones are signed. This enforces DNSSEC validation on nameserver
|
||||
NS sets and the nameserver addresses that are encountered on the referral
|
||||
path to the answer.
|
||||
Default off, because it burdens the authority servers, and it is
|
||||
Default no, because it burdens the authority servers, and it is
|
||||
not RFC standard, and could lead to performance problems because of the
|
||||
extra query load that is generated. Experimental option.
|
||||
If you enable it consider adding more numbers after the target\-fetch\-policy
|
||||
@@ -722,7 +793,7 @@ Send minimum amount of information to upstream servers to enhance privacy.
|
||||
Only sent minimum required labels of the QNAME and set QTYPE to A when
|
||||
possible. Best effort approach; full QNAME and original QTYPE will be sent when
|
||||
upstream replies with a RCODE other than NOERROR, except when receiving
|
||||
NXDOMAIN from a DNSSEC signed zone. Default is off.
|
||||
NXDOMAIN from a DNSSEC signed zone. Default is yes.
|
||||
.TP
|
||||
.B qname\-minimisation\-strict: \fI<yes or no>
|
||||
QNAME minimisation in strict mode. Do not fall-back to sending full QNAME to
|
||||
@@ -783,12 +854,18 @@ keep the cache up to date. Default is no. Turning it on gives about
|
||||
10 percent more traffic and load on the machine, but popular items do
|
||||
not expire from the cache.
|
||||
.TP
|
||||
.B prefetch-key: \fI<yes or no>
|
||||
.B prefetch\-key: \fI<yes or no>
|
||||
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>
|
||||
.B deny\-any: \fI<yes or no>
|
||||
If yes, deny queries of type ANY with an empty response. Default is no.
|
||||
If disabled, unbound responds with a short list of resource records if some
|
||||
can be found in the cache and makes the upstream type ANY query if there
|
||||
are none.
|
||||
.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
|
||||
@@ -796,9 +873,11 @@ from the query ID, for speed and thread safety). Default is 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
|
||||
This may cause a slight speedup. The default is yes, even though the DNS
|
||||
protocol RFCs mandate these sections, and the additional content could
|
||||
be of use and save roundtrips for clients.
|
||||
be of use and save roundtrips for clients. Because they are not used,
|
||||
and the saved roundtrips are easier saved with prefetch, whilst this is
|
||||
faster.
|
||||
.TP
|
||||
.B disable-dnssec-lame-check: \fI<yes or no>
|
||||
If true, disables the DNSSEC lameness check in the iterator. This check
|
||||
@@ -946,6 +1025,17 @@ If enabled, unbound attempts to serve old responses from cache with a
|
||||
TTL of 0 in the response without waiting for the actual resolution to finish.
|
||||
The actual resolution answer ends up in the cache later on. Default is "no".
|
||||
.TP
|
||||
.B serve\-expired\-ttl: \fI<seconds>
|
||||
Limit serving of expired responses to configured seconds after expiration. 0
|
||||
disables the limit. This option only applies when \fBserve\-expired\fR is
|
||||
enabled. The default is 0.
|
||||
.TP
|
||||
.B serve\-expired\-ttl\-reset: \fI<yes or no>
|
||||
Set the TTL of expired records to the \fBserve\-expired\-ttl\fR value after a
|
||||
failed attempt to retrieve the record from upstream. This makes sure that the
|
||||
expired records will be served as long as there are queries for it. Default is
|
||||
"no".
|
||||
.TP
|
||||
.B val\-nsec3\-keysize\-iterations: \fI<"list of values">
|
||||
List of keysize and iteration count values, separated by spaces, surrounded
|
||||
by quotes. Default is "1024 150 2048 500 4096 2500". This determines the
|
||||
@@ -994,7 +1084,7 @@ Number of bytes size of the aggressive negative cache. Default is 1 megabyte.
|
||||
A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes
|
||||
or gigabytes (1024*1024 bytes in a megabyte).
|
||||
.TP
|
||||
.B unblock\-lan\-zones: \fI<yesno>
|
||||
.B unblock\-lan\-zones: \fI<yes or no>
|
||||
Default is disabled. If enabled, then for private address space,
|
||||
the reverse lookups are no longer filtered. This allows unbound when
|
||||
running as dns service on a host where it provides service for that host,
|
||||
@@ -1005,7 +1095,7 @@ as a (DHCP-) DNS network resolver for a group of machines, where such
|
||||
lookups should be filtered (RFC compliance), this also stops potential
|
||||
data leakage about the local network to the upstream DNS servers.
|
||||
.TP
|
||||
.B insecure\-lan\-zones: \fI<yesno>
|
||||
.B insecure\-lan\-zones: \fI<yes or no>
|
||||
Default is disabled. If enabled, then reverse lookups in private
|
||||
address space are not validated. This is usually required whenever
|
||||
\fIunblock\-lan\-zones\fR is used.
|
||||
@@ -1313,22 +1403,20 @@ This can make ordinary queries complete (if repeatedly queried for),
|
||||
and enter the cache, whilst also mitigating the traffic flow by the
|
||||
factor given.
|
||||
.TP 5
|
||||
.B low\-rtt: \fI<msec time>
|
||||
Set the time in millisecond that is considere a low ping time for fast
|
||||
server selection with the low\-rtt\-pct option, that turns this on or off.
|
||||
The default is 45 msec, a number from IPv6 quick response documents.
|
||||
.B fast\-server\-permil: \fI<number>
|
||||
Specify how many times out of 1000 to pick from the set of fastest servers.
|
||||
0 turns the feature off. A value of 900 would pick from the fastest
|
||||
servers 90 percent of the time, and would perform normal exploration of random
|
||||
servers for the remaining time. When prefetch is enabled (or serve\-expired),
|
||||
such prefetches are not sped up, because there is no one waiting for it, and it
|
||||
presents a good moment to perform server exploration. The
|
||||
\fBfast\-server\-num\fR option can be used to specify the size of the fastest
|
||||
servers set. The default for fast\-server\-permil is 0.
|
||||
.TP 5
|
||||
.B low\-rtt\-pct: \fI<number>
|
||||
Specify how many times out of 1000 to pick the fast server from the low
|
||||
rtt band. 0 turns the feature off. A value of 900 would pick the fast
|
||||
server when such fast servers are available 90 percent of the time, and
|
||||
the remaining time perform normal exploration of random servers.
|
||||
When prefetch is enabled (or serve\-expired), such prefetches are not
|
||||
sped up, because there is no one waiting for it, and it presents a good
|
||||
moment to perform server exploration. The low\-rtt option can be used
|
||||
to specify which servers are picked for fast server selection, servers
|
||||
with a ping roundtrip time below that value are considered.
|
||||
The default for low\-rtt\-pct is 0.
|
||||
.B fast\-server\-num: \fI<number>
|
||||
Set the number of servers that should be used for fast server selection. Only
|
||||
use the fastest specified number of servers with the fast\-server\-permil
|
||||
option, that turns this on or off. The default is to use the fastest 3 servers.
|
||||
.SS "Remote Control Options"
|
||||
In the
|
||||
.B remote\-control:
|
||||
@@ -1351,6 +1439,14 @@ By default localhost (127.0.0.1 and ::1) is listened to.
|
||||
Use 0.0.0.0 and ::0 to listen to all interfaces.
|
||||
If you change this and permissions have been dropped, you must restart
|
||||
the server for the change to take effect.
|
||||
.IP
|
||||
If you set it to an absolute path, a local socket is used. The local socket
|
||||
does not use the certificates and keys, so those files need not be present.
|
||||
To restrict access, unbound sets permissions on the file to the user and
|
||||
group that is configured, the access bits are set to allow the group members
|
||||
to access the control socket file. Put users that need to access the socket
|
||||
in the that group. To restrict access further, create a directory to put
|
||||
the control socket in and restrict access to that directory.
|
||||
.TP 5
|
||||
.B control\-port: \fI<port number>
|
||||
The port number to listen on for IPv4 or IPv6 control interfaces,
|
||||
@@ -1359,11 +1455,9 @@ If you change this and permissions have been dropped, you must restart
|
||||
the server for the change to take effect.
|
||||
.TP 5
|
||||
.B control\-use\-cert: \fI<yes or no>
|
||||
Whether to require certificate authentication of control connections.
|
||||
The default is "yes".
|
||||
This should not be changed unless there are other mechanisms in place
|
||||
to prevent untrusted users from accessing the remote control
|
||||
interface.
|
||||
For localhost control-interface you can disable the use of TLS by setting
|
||||
this option to "no", default is "yes". For local sockets, TLS is disabled
|
||||
and the value of this option is ignored.
|
||||
.TP 5
|
||||
.B server\-key\-file: \fI<private key file>
|
||||
Path to the server private key, by default unbound_server.key.
|
||||
@@ -1429,7 +1523,7 @@ IP address of stub zone nameserver. Can be IP 4 or IP 6.
|
||||
To use a nondefault port for DNS communication append '@' with the port number.
|
||||
.TP
|
||||
.B stub\-prime: \fI<yes or no>
|
||||
This option is by default off. If enabled it performs NS set priming,
|
||||
This option is by default no. 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.
|
||||
@@ -1446,6 +1540,10 @@ Default is no.
|
||||
.TP
|
||||
.B stub\-ssl\-upstream: \fI<yes or no>
|
||||
Alternate syntax for \fBstub\-tls\-upstream\fR.
|
||||
.TP
|
||||
.B stub\-no\-cache: \fI<yes or no>
|
||||
Default is no. If enabled, data inside the stub is not cached. This is
|
||||
useful when you want immediate changes to be visible.
|
||||
.SS "Forward Zone Options"
|
||||
.LP
|
||||
There may be multiple
|
||||
@@ -1480,6 +1578,7 @@ the '@' and '#', the '@' comes first.
|
||||
At high verbosity it logs the TLS certificate, with TLS enabled.
|
||||
If you leave out the '#' and auth name from the forward\-addr, any
|
||||
name is accepted. The cert must also match a CA from the tls\-cert\-bundle.
|
||||
The cert name match code needs OpenSSL 1.1.0 or later to be enabled.
|
||||
.TP
|
||||
.B forward\-first: \fI<yes or no>
|
||||
If enabled, a query is attempted without the forward clause if it fails.
|
||||
@@ -1490,9 +1589,15 @@ The default is no.
|
||||
.B forward\-tls\-upstream: \fI<yes or no>
|
||||
Enabled or disable whether the queries to this forwarder use TLS for transport.
|
||||
Default is no.
|
||||
If you enable this, also configure a tls\-cert\-bundle or use tls\-win\-cert to
|
||||
load CA certs, otherwise the connections cannot be authenticated.
|
||||
.TP
|
||||
.B forward\-ssl\-upstream: \fI<yes or no>
|
||||
Alternate syntax for \fBforward\-tls\-upstream\fR.
|
||||
.TP
|
||||
.B forward\-no\-cache: \fI<yes or no>
|
||||
Default is no. If enabled, data inside the forward is not cached. This is
|
||||
useful when you want immediate changes to be visible.
|
||||
.SS "Authority Zone Options"
|
||||
.LP
|
||||
Authority zones are configured with \fBauth\-zone:\fR, and each one must
|
||||
@@ -1509,6 +1614,13 @@ lookups of that data.
|
||||
Authority zones can be read from zonefile. And can be kept updated via
|
||||
AXFR and IXFR. After update the zonefile is rewritten. The update mechanism
|
||||
uses the SOA timer values and performs SOA UDP queries to detect zone changes.
|
||||
.LP
|
||||
If the update fetch fails, the timers in the SOA record are used to time
|
||||
another fetch attempt. Until the SOA expiry timer is reached. Then the
|
||||
zone is expired. When a zone is expired, queries are SERVFAIL, and
|
||||
any new serial number is accepted from the master (even if older), and if
|
||||
fallback is enabled, the fallback activates to fetch from the upstream instead
|
||||
of the SERVFAIL.
|
||||
.TP
|
||||
.B name: \fI<zone name>
|
||||
Name of the authority zone.
|
||||
@@ -1627,6 +1739,12 @@ It must be /96 or shorter. The default prefix is 64:ff9b::/96.
|
||||
.B dns64\-synthall: \fI<yes or no>\fR
|
||||
Debug option, default no. If enabled, synthesize all AAAA records
|
||||
despite the presence of actual AAAA records.
|
||||
.TP
|
||||
.B dns64\-ignore\-aaaa: \fI<name>\fR
|
||||
List domain for which the AAAA records are ignored and the A record is
|
||||
used by dns64 processing instead. Can be entered multiple times, list a
|
||||
new domain for which it applies, one per line. Applies also to names
|
||||
underneath the name given.
|
||||
.SS "DNSCrypt Options"
|
||||
.LP
|
||||
The
|
||||
@@ -1742,6 +1860,24 @@ to expose to third parties for IPv6. Defaults to 56.
|
||||
.B max\-client\-subnet\-ipv4: \fI<number>\fR
|
||||
Specifies the maximum prefix length of the client source address we are willing
|
||||
to expose to third parties for IPv4. Defaults to 24.
|
||||
.TP
|
||||
.B min\-client\-subnet\-ipv6: \fI<number>\fR
|
||||
Specifies the minimum prefix length of the IPv6 source mask we are willing to
|
||||
accept in queries. Shorter source masks result in REFUSED answers. Source mask
|
||||
of 0 is always accepted. Default is 0.
|
||||
.TP
|
||||
.B min\-client\-subnet\-ipv4: \fI<number>\fR
|
||||
Specifies the minimum prefix length of the IPv4 source mask we are willing to
|
||||
accept in queries. Shorter source masks result in REFUSED answers. Source mask
|
||||
of 0 is always accepted. Default is 0.
|
||||
.TP
|
||||
.B max\-ecs\-tree\-size\-ipv4: \fI<number>\fR
|
||||
Specifies the maximum number of subnets ECS answers kept in the ECS radix tree.
|
||||
This number applies for each qname/qclass/qtype tuple. Defaults to 100.
|
||||
.TP
|
||||
.B max\-ecs\-tree\-size\-ipv6: \fI<number>\fR
|
||||
Specifies the maximum number of subnets ECS answers kept in the ECS radix tree.
|
||||
This number applies for each qname/qclass/qtype tuple. Defaults to 100.
|
||||
.SS "Opportunistic IPsec Support Module Options"
|
||||
.LP
|
||||
The IPsec module must be configured in the \fBmodule\-config:\fR "ipsecmod
|
||||
@@ -1827,7 +1963,7 @@ If Unbound was built with
|
||||
on a system that has installed the hiredis C client library of Redis,
|
||||
then the "redis" backend can be used.
|
||||
This backend communicates with the specified Redis server over a TCP
|
||||
connection to store and retrive cache data.
|
||||
connection to store and retrieve cache data.
|
||||
It can be used as a persistent and/or shared cache backend.
|
||||
It should be noted that Unbound never removes data stored in the Redis server,
|
||||
even if some data have expired in terms of DNS TTL or the Redis server has
|
||||
|
||||
+8
-3
@@ -612,17 +612,22 @@ RECURSIVE = YES
|
||||
|
||||
EXCLUDE = ./build \
|
||||
./compat \
|
||||
./contrib \
|
||||
util/configparser.c \
|
||||
util/configparser.h \
|
||||
util/configlexer.c \
|
||||
util/locks.h \
|
||||
pythonmod/doc \
|
||||
pythonmod/examples \
|
||||
pythonmod/unboundmodule.py \
|
||||
pythonmod/interface.h \
|
||||
pythonmod/examples/resgen.py \
|
||||
pythonmod/examples/resmod.py \
|
||||
pythonmod/examples/resip.py \
|
||||
pythonmod/ubmodule-msg.py \
|
||||
pythonmod/ubmodule-tst.py \
|
||||
unboundmodule.py \
|
||||
libunbound/python/unbound.py \
|
||||
libunbound/python/libunbound_wrap.c \
|
||||
libunbound/python/doc \
|
||||
libunbound/python/examples \
|
||||
./ldns-src \
|
||||
doc/control_proto_spec.txt \
|
||||
doc/requirements.txt
|
||||
|
||||
@@ -119,7 +119,7 @@ node_size(const struct addrtree *tree, const struct addrnode *n)
|
||||
|
||||
struct addrtree *
|
||||
addrtree_create(addrlen_t max_depth, void (*delfunc)(void *, void *),
|
||||
size_t (*sizefunc)(void *), void *env, unsigned int max_node_count)
|
||||
size_t (*sizefunc)(void *), void *env, uint32_t max_node_count)
|
||||
{
|
||||
struct addrtree *tree;
|
||||
log_assert(delfunc != NULL);
|
||||
|
||||
@@ -66,10 +66,10 @@ struct addrtree {
|
||||
struct addrnode *root;
|
||||
/** Number of elements in the tree (not always equal to number of
|
||||
* nodes) */
|
||||
unsigned int node_count;
|
||||
uint32_t node_count;
|
||||
/** Maximum number of allowed nodes, will be enforced by LRU list.
|
||||
* Excluding the root node, 0 for unlimited */
|
||||
unsigned int max_node_count;
|
||||
uint32_t max_node_count;
|
||||
/** Size of tree in bytes */
|
||||
size_t size_bytes;
|
||||
/** Maximum prefix length we are willing to cache. */
|
||||
@@ -137,7 +137,7 @@ size_t addrtree_size(const struct addrtree *tree);
|
||||
*/
|
||||
struct addrtree *
|
||||
addrtree_create(addrlen_t max_depth, void (*delfunc)(void *, void *),
|
||||
size_t (*sizefunc)(void *), void *env, unsigned int max_node_count);
|
||||
size_t (*sizefunc)(void *), void *env, uint32_t max_node_count);
|
||||
|
||||
/**
|
||||
* Free tree and all nodes below.
|
||||
|
||||
+59
-11
@@ -55,8 +55,7 @@
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
|
||||
#define ECS_MAX_TREESIZE 100
|
||||
#include "iterator/iter_utils.h"
|
||||
|
||||
/** externally called */
|
||||
void
|
||||
@@ -93,6 +92,7 @@ subnet_new_qstate(struct module_qstate *qstate, int id)
|
||||
return 0;
|
||||
qstate->minfo[id] = sq;
|
||||
memset(sq, 0, sizeof(*sq));
|
||||
sq->started_no_cache_store = qstate->no_cache_store;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -150,7 +150,9 @@ int ecs_whitelist_check(struct query_info* qinfo,
|
||||
|
||||
/* Cache by default, might be disabled after parsing EDNS option
|
||||
* received from nameserver. */
|
||||
qstate->no_cache_store = 0;
|
||||
if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo)) {
|
||||
qstate->no_cache_store = 0;
|
||||
}
|
||||
|
||||
if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream &&
|
||||
qstate->env->cfg->client_subnet_always_forward) ||
|
||||
@@ -177,6 +179,14 @@ int ecs_whitelist_check(struct query_info* qinfo,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
subnet_markdel(void* key)
|
||||
{
|
||||
struct msgreply_entry *e = (struct msgreply_entry*)key;
|
||||
e->key.qtype = 0;
|
||||
e->key.qclass = 0;
|
||||
}
|
||||
|
||||
int
|
||||
subnetmod_init(struct module_env *env, int id)
|
||||
{
|
||||
@@ -193,6 +203,7 @@ subnetmod_init(struct module_env *env, int id)
|
||||
HASH_DEFAULT_STARTARRAY, env->cfg->msg_cache_size,
|
||||
msg_cache_sizefunc, query_info_compare, query_entry_delete,
|
||||
subnet_data_delete, NULL);
|
||||
slabhash_setmarkdel(sn_env->subnet_msg_cache, &subnet_markdel);
|
||||
if(!sn_env->subnet_msg_cache) {
|
||||
log_err("subnet: could not create cache");
|
||||
free(sn_env);
|
||||
@@ -291,13 +302,13 @@ get_tree(struct subnet_msg_cache_data *data, struct ecs_data *edns,
|
||||
if (!data->tree4)
|
||||
data->tree4 = addrtree_create(
|
||||
cfg->max_client_subnet_ipv4, &delfunc,
|
||||
&sizefunc, env, ECS_MAX_TREESIZE);
|
||||
&sizefunc, env, cfg->max_ecs_tree_size_ipv4);
|
||||
tree = data->tree4;
|
||||
} else {
|
||||
if (!data->tree6)
|
||||
data->tree6 = addrtree_create(
|
||||
cfg->max_client_subnet_ipv6, &delfunc,
|
||||
&sizefunc, env, ECS_MAX_TREESIZE);
|
||||
&sizefunc, env, cfg->max_ecs_tree_size_ipv6);
|
||||
tree = data->tree6;
|
||||
}
|
||||
return tree;
|
||||
@@ -464,7 +475,12 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
|
||||
memset(c_out, 0, sizeof(*c_out));
|
||||
|
||||
if (!qstate->return_msg) return module_error;
|
||||
if (!qstate->return_msg) {
|
||||
/* already an answer and its not a message, but retain
|
||||
* the actual rcode, instead of module_error, so send
|
||||
* module_finished */
|
||||
return module_finished;
|
||||
}
|
||||
|
||||
/* We have not asked for subnet data */
|
||||
if (!sq->subnet_sent) {
|
||||
@@ -482,9 +498,11 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
* is still usefull to put it in the edns subnet cache for
|
||||
* when a client explicitly asks for subnet specific answer. */
|
||||
verbose(VERB_QUERY, "subnet: Authority indicates no support");
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
update_cache(qstate, id);
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
if(!sq->started_no_cache_store) {
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
update_cache(qstate, id);
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
}
|
||||
if (sq->subnet_downstream)
|
||||
cp_edns_bad_response(c_out, c_in);
|
||||
return module_finished;
|
||||
@@ -510,7 +528,10 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
}
|
||||
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
update_cache(qstate, id);
|
||||
if(!sq->started_no_cache_store) {
|
||||
update_cache(qstate, id);
|
||||
}
|
||||
sne->num_msg_nocache++;
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
|
||||
if (sq->subnet_downstream) {
|
||||
@@ -520,6 +541,19 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
c_out->subnet_source_mask = c_in->subnet_source_mask;
|
||||
memcpy(&c_out->subnet_addr, &c_in->subnet_addr, INET6_SIZE);
|
||||
c_out->subnet_scope_mask = s_in->subnet_scope_mask;
|
||||
/* Limit scope returned to client to scope used for caching. */
|
||||
if(c_out->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
|
||||
if(c_out->subnet_scope_mask >
|
||||
qstate->env->cfg->max_client_subnet_ipv4) {
|
||||
c_out->subnet_scope_mask =
|
||||
qstate->env->cfg->max_client_subnet_ipv4;
|
||||
}
|
||||
}
|
||||
else if(c_out->subnet_scope_mask >
|
||||
qstate->env->cfg->max_client_subnet_ipv6) {
|
||||
c_out->subnet_scope_mask =
|
||||
qstate->env->cfg->max_client_subnet_ipv6;
|
||||
}
|
||||
c_out->subnet_validdata = 1;
|
||||
}
|
||||
return module_finished;
|
||||
@@ -691,8 +725,20 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
return;
|
||||
}
|
||||
|
||||
/* Limit to minimum allowed source mask */
|
||||
if(sq->ecs_client_in.subnet_source_mask != 0 && (
|
||||
(sq->ecs_client_in.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 &&
|
||||
sq->ecs_client_in.subnet_source_mask < qstate->env->cfg->min_client_subnet_ipv4) ||
|
||||
(sq->ecs_client_in.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6 &&
|
||||
sq->ecs_client_in.subnet_source_mask < qstate->env->cfg->min_client_subnet_ipv6))) {
|
||||
qstate->return_rcode = LDNS_RCODE_REFUSED;
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
if (lookup_and_reply(qstate, id, sq)) {
|
||||
sne->num_msg_cache++;
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
verbose(VERB_QUERY, "subnet: answered from cache");
|
||||
qstate->ext_state[id] = module_finished;
|
||||
@@ -741,10 +787,12 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
/* Query handed back by next module, we have a 'final' answer */
|
||||
if(sq && event == module_event_moddone) {
|
||||
qstate->ext_state[id] = eval_response(qstate, id, sq);
|
||||
if(qstate->ext_state[id] == module_finished) {
|
||||
if(qstate->ext_state[id] == module_finished &&
|
||||
qstate->return_msg) {
|
||||
ecs_opt_list_append(&sq->ecs_client_out,
|
||||
&qstate->edns_opts_front_out, qstate);
|
||||
}
|
||||
qstate->no_cache_store = sq->started_no_cache_store;
|
||||
return;
|
||||
}
|
||||
if(sq && outbound) {
|
||||
|
||||
@@ -61,6 +61,10 @@ struct subnet_env {
|
||||
/** allocation service */
|
||||
struct alloc_cache alloc;
|
||||
lock_rw_type biglock;
|
||||
/** number of messages from cache */
|
||||
size_t num_msg_cache;
|
||||
/** number of messages not from cache */
|
||||
size_t num_msg_nocache;
|
||||
};
|
||||
|
||||
struct subnet_msg_cache_data {
|
||||
@@ -79,6 +83,8 @@ struct subnet_qstate {
|
||||
struct ecs_data ecs_server_out;
|
||||
int subnet_downstream;
|
||||
int subnet_sent;
|
||||
/** has the subnet module been started with no_cache_store? */
|
||||
int started_no_cache_store;
|
||||
};
|
||||
|
||||
void subnet_data_delete(void* d, void* ATTR_UNUSED(arg));
|
||||
@@ -127,4 +133,7 @@ int ecs_edns_back_parsed(struct module_qstate* qstate, int id, void* cbargs);
|
||||
int ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
|
||||
int id, void* cbargs);
|
||||
|
||||
/** mark subnet msg to be deleted */
|
||||
void subnet_markdel(void* key);
|
||||
|
||||
#endif /* SUBNETMOD_H */
|
||||
|
||||
@@ -341,6 +341,8 @@ ipsecmod_handle_query(struct module_qstate* qstate,
|
||||
qstate->env->cfg->ipsecmod_max_ttl;
|
||||
qstate->return_msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(
|
||||
qstate->return_msg->rep->ttl);
|
||||
qstate->return_msg->rep->serve_expired_ttl = qstate->return_msg->rep->ttl +
|
||||
qstate->env->cfg->serve_expired_ttl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +85,8 @@ struct delegpt {
|
||||
uint8_t ssl_upstream;
|
||||
/** delegpt from authoritative zone that is locally hosted */
|
||||
uint8_t auth_dp;
|
||||
/*** no cache */
|
||||
int no_cache;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -239,6 +239,11 @@ read_fwds_addr(struct config_stub* s, struct delegpt* dp)
|
||||
s->name, p->str);
|
||||
return 0;
|
||||
}
|
||||
#ifndef HAVE_SSL_SET1_HOST
|
||||
if(tls_auth_name)
|
||||
log_err("no name verification functionality in "
|
||||
"ssl library, ignored name for %s", p->str);
|
||||
#endif
|
||||
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
|
||||
tls_auth_name)) {
|
||||
log_err("out of memory");
|
||||
@@ -267,6 +272,8 @@ read_forwards(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
* 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;
|
||||
/* Do not cache if set. */
|
||||
dp->no_cache = s->no_cache;
|
||||
/* use SSL for queries to this forwarder */
|
||||
dp->ssl_upstream = (uint8_t)s->ssl_upstream;
|
||||
verbose(VERB_QUERY, "Forward zone server list:");
|
||||
|
||||
@@ -252,6 +252,11 @@ read_stubs_addr(struct config_stub* s, struct delegpt* dp)
|
||||
s->name, p->str);
|
||||
return 0;
|
||||
}
|
||||
#ifndef HAVE_SSL_SET1_HOST
|
||||
if(auth_name)
|
||||
log_err("no name verification functionality in "
|
||||
"ssl library, ignored name for %s", p->str);
|
||||
#endif
|
||||
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
|
||||
auth_name)) {
|
||||
log_err("out of memory");
|
||||
@@ -278,6 +283,8 @@ read_stubs(struct iter_hints* hints, struct config_file* cfg)
|
||||
* 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;
|
||||
/* Do not cache if set. */
|
||||
dp->no_cache = s->no_cache;
|
||||
/* ssl_upstream */
|
||||
dp->ssl_upstream = (uint8_t)s->ssl_upstream;
|
||||
delegpt_log(VERB_QUERY, dp);
|
||||
|
||||
+28
-13
@@ -316,6 +316,18 @@ sub_of_pkt(sldns_buffer* pkt, uint8_t* zone, uint8_t* comprname)
|
||||
return dname_subdomain_c(zone, buf);
|
||||
}
|
||||
|
||||
/** Check if there are SOA records in the authority section (negative) */
|
||||
static int
|
||||
soa_in_auth(struct msg_parse* msg)
|
||||
{
|
||||
struct rrset_parse* rrset;
|
||||
for(rrset = msg->rrset_first; rrset; rrset = rrset->rrset_all_next)
|
||||
if(rrset->type == LDNS_RR_TYPE_SOA &&
|
||||
rrset->section == LDNS_SECTION_AUTHORITY)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine normalizes a response. This includes removing "irrelevant"
|
||||
* records from the answer and additional sections and (re)synthesizing
|
||||
@@ -437,7 +449,9 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
rrset->rrset_all_next =
|
||||
nx->rrset_all_next;
|
||||
nx->rrset_all_next = rrset;
|
||||
prev = nx;
|
||||
/* prev = nx; unused, enable if there
|
||||
* is other rrset removal code after
|
||||
* this */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,6 +509,19 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
/* we don't want NS sets for NXDOMAIN answers,
|
||||
* because they could contain poisonous contents,
|
||||
* from. eg. fragmentation attacks, inserted after
|
||||
* long RRSIGs in the packet get to the packet
|
||||
* border and such */
|
||||
/* also for NODATA answers */
|
||||
if(FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NXDOMAIN ||
|
||||
(FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR
|
||||
&& soa_in_auth(msg) && msg->an_rrsets == 0)) {
|
||||
remove_rrset("normalize: removing irrelevant "
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
if(nsset == NULL) {
|
||||
nsset = rrset;
|
||||
} else {
|
||||
@@ -593,18 +620,6 @@ store_rrset(sldns_buffer* pkt, struct msg_parse* msg, struct module_env* env,
|
||||
(void)rrset_cache_update(env->rrset_cache, &ref, env->alloc, now);
|
||||
}
|
||||
|
||||
/** Check if there are SOA records in the authority section (negative) */
|
||||
static int
|
||||
soa_in_auth(struct msg_parse* msg)
|
||||
{
|
||||
struct rrset_parse* rrset;
|
||||
for(rrset = msg->rrset_first; rrset; rrset = rrset->rrset_all_next)
|
||||
if(rrset->type == LDNS_RR_TYPE_SOA &&
|
||||
rrset->section == LDNS_SECTION_AUTHORITY)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if right hand name in NSEC is within zone
|
||||
* @param rrset: the NSEC rrset
|
||||
|
||||
+139
-10
@@ -282,10 +282,13 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
|
||||
static int
|
||||
iter_fill_rtt(struct iter_env* iter_env, struct module_env* env,
|
||||
uint8_t* name, size_t namelen, uint16_t qtype, time_t now,
|
||||
struct delegpt* dp, int* best_rtt, struct sock_list* blacklist)
|
||||
struct delegpt* dp, int* best_rtt, struct sock_list* blacklist,
|
||||
size_t* num_suitable_results)
|
||||
{
|
||||
int got_it = 0;
|
||||
struct delegpt_addr* a;
|
||||
*num_suitable_results = 0;
|
||||
|
||||
if(dp->bogus)
|
||||
return 0; /* NS bogus, all bogus, nothing found */
|
||||
for(a=dp->result_list; a; a = a->next_result) {
|
||||
@@ -301,11 +304,58 @@ iter_fill_rtt(struct iter_env* iter_env, struct module_env* env,
|
||||
} else if(a->sel_rtt < *best_rtt) {
|
||||
*best_rtt = a->sel_rtt;
|
||||
}
|
||||
(*num_suitable_results)++;
|
||||
}
|
||||
}
|
||||
return got_it;
|
||||
}
|
||||
|
||||
/** compare two rtts, return -1, 0 or 1 */
|
||||
static int
|
||||
rtt_compare(const void* x, const void* y)
|
||||
{
|
||||
if(*(int*)x == *(int*)y)
|
||||
return 0;
|
||||
if(*(int*)x > *(int*)y)
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** get RTT for the Nth fastest server */
|
||||
static int
|
||||
nth_rtt(struct delegpt_addr* result_list, size_t num_results, size_t n)
|
||||
{
|
||||
int rtt_band;
|
||||
size_t i;
|
||||
int* rtt_list, *rtt_index;
|
||||
|
||||
if(num_results < 1 || n >= num_results) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rtt_list = calloc(num_results, sizeof(int));
|
||||
if(!rtt_list) {
|
||||
log_err("malloc failure: allocating rtt_list");
|
||||
return -1;
|
||||
}
|
||||
rtt_index = rtt_list;
|
||||
|
||||
for(i=0; i<num_results && result_list; i++) {
|
||||
if(result_list->sel_rtt != -1) {
|
||||
*rtt_index = result_list->sel_rtt;
|
||||
rtt_index++;
|
||||
}
|
||||
result_list=result_list->next_result;
|
||||
}
|
||||
qsort(rtt_list, num_results, sizeof(*rtt_list), rtt_compare);
|
||||
|
||||
log_assert(n > 0);
|
||||
rtt_band = rtt_list[n-1];
|
||||
free(rtt_list);
|
||||
|
||||
return rtt_band;
|
||||
}
|
||||
|
||||
/** filter the address list, putting best targets at front,
|
||||
* returns number of best targets (or 0, no suitable targets) */
|
||||
static int
|
||||
@@ -314,12 +364,13 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
|
||||
struct delegpt* dp, int* selected_rtt, int open_target,
|
||||
struct sock_list* blacklist, time_t prefetch)
|
||||
{
|
||||
int got_num = 0, low_rtt = 0, swap_to_front, rtt_band = RTT_BAND;
|
||||
int got_num = 0, low_rtt = 0, swap_to_front, rtt_band = RTT_BAND, nth;
|
||||
size_t num_results;
|
||||
struct delegpt_addr* a, *n, *prev=NULL;
|
||||
|
||||
/* fillup sel_rtt and find best rtt in the bunch */
|
||||
got_num = iter_fill_rtt(iter_env, env, name, namelen, qtype, now, dp,
|
||||
&low_rtt, blacklist);
|
||||
&low_rtt, blacklist, &num_results);
|
||||
if(got_num == 0)
|
||||
return 0;
|
||||
if(low_rtt >= USEFUL_SERVER_TOP_TIMEOUT &&
|
||||
@@ -329,14 +380,19 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
|
||||
return 0 to force the caller to fetch more */
|
||||
}
|
||||
|
||||
if(env->cfg->low_rtt_pct != 0 && prefetch == 0 &&
|
||||
low_rtt < env->cfg->low_rtt &&
|
||||
ub_random_max(env->rnd, 1000) < env->cfg->low_rtt_pct) {
|
||||
if(env->cfg->fast_server_permil != 0 && prefetch == 0 &&
|
||||
num_results > env->cfg->fast_server_num &&
|
||||
ub_random_max(env->rnd, 1000) < env->cfg->fast_server_permil) {
|
||||
/* the query is not prefetch, but for a downstream client,
|
||||
* there is a low_rtt (fast) server. We choose that x% of the
|
||||
* time */
|
||||
/* pick rtt numbers from 0..LOWBAND_RTT */
|
||||
rtt_band = env->cfg->low_rtt - low_rtt;
|
||||
* there are more servers available then the fastest N we want
|
||||
* to choose from. Limit our choice to the fastest servers. */
|
||||
nth = nth_rtt(dp->result_list, num_results,
|
||||
env->cfg->fast_server_num);
|
||||
if(nth > 0) {
|
||||
rtt_band = nth - low_rtt;
|
||||
if(rtt_band > RTT_BAND)
|
||||
rtt_band = RTT_BAND;
|
||||
}
|
||||
}
|
||||
|
||||
got_num = 0;
|
||||
@@ -375,11 +431,34 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
|
||||
int got_num6 = 0;
|
||||
int low_rtt6 = 0;
|
||||
int i;
|
||||
int attempt = -1; /* filter to make sure addresses have
|
||||
less attempts on them than the first, to force round
|
||||
robin when all the IPv6 addresses fail */
|
||||
int num4ok = 0; /* number ip4 at low attempt count */
|
||||
int num4_lowrtt = 0;
|
||||
prev = NULL;
|
||||
a = dp->result_list;
|
||||
for(i = 0; i < got_num; i++) {
|
||||
swap_to_front = 0;
|
||||
if(a->addr.ss_family != AF_INET6 && attempt == -1) {
|
||||
/* if we only have ip4 at low attempt count,
|
||||
* then ip6 is failing, and we need to
|
||||
* select one of the remaining IPv4 addrs */
|
||||
attempt = a->attempts;
|
||||
num4ok++;
|
||||
num4_lowrtt = a->sel_rtt;
|
||||
} else if(a->addr.ss_family != AF_INET6 && attempt == a->attempts) {
|
||||
num4ok++;
|
||||
if(num4_lowrtt == 0 || a->sel_rtt < num4_lowrtt) {
|
||||
num4_lowrtt = a->sel_rtt;
|
||||
}
|
||||
}
|
||||
if(a->addr.ss_family == AF_INET6) {
|
||||
if(attempt == -1) {
|
||||
attempt = a->attempts;
|
||||
} else if(a->attempts > attempt) {
|
||||
break;
|
||||
}
|
||||
got_num6++;
|
||||
swap_to_front = 1;
|
||||
if(low_rtt6 == 0 || a->sel_rtt < low_rtt6) {
|
||||
@@ -401,6 +480,9 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
|
||||
if(got_num6 > 0) {
|
||||
got_num = got_num6;
|
||||
*selected_rtt = low_rtt6;
|
||||
} else if(num4ok > 0) {
|
||||
got_num = num4ok;
|
||||
*selected_rtt = num4_lowrtt;
|
||||
}
|
||||
}
|
||||
return got_num;
|
||||
@@ -1184,3 +1266,50 @@ int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf)
|
||||
{
|
||||
struct iter_hints_stub *stub;
|
||||
struct delegpt *dp;
|
||||
|
||||
/* Check for stub. */
|
||||
stub = hints_lookup_stub(qstate->env->hints, qinf->qname,
|
||||
qinf->qclass, NULL);
|
||||
dp = forwards_lookup(qstate->env->fwds, qinf->qname, qinf->qclass);
|
||||
|
||||
/* see if forward or stub is more pertinent */
|
||||
if(stub && stub->dp && dp) {
|
||||
if(dname_strict_subdomain(dp->name, dp->namelabs,
|
||||
stub->dp->name, stub->dp->namelabs)) {
|
||||
stub = NULL; /* ignore stub, forward is lower */
|
||||
} else {
|
||||
dp = NULL; /* ignore forward, stub is lower */
|
||||
}
|
||||
}
|
||||
|
||||
/* check stub */
|
||||
if (stub != NULL && stub->dp != NULL) {
|
||||
if(stub->dp->no_cache) {
|
||||
char qname[255+1];
|
||||
char dpname[255+1];
|
||||
dname_str(qinf->qname, qname);
|
||||
dname_str(stub->dp->name, dpname);
|
||||
verbose(VERB_ALGO, "stub for %s %s has no_cache", qname, dpname);
|
||||
}
|
||||
return (stub->dp->no_cache);
|
||||
}
|
||||
|
||||
/* Check for forward. */
|
||||
if (dp) {
|
||||
if(dp->no_cache) {
|
||||
char qname[255+1];
|
||||
char dpname[255+1];
|
||||
dname_str(qinf->qname, qname);
|
||||
dname_str(dp->name, dpname);
|
||||
verbose(VERB_ALGO, "forward for %s %s has no_cache", qname, dpname);
|
||||
}
|
||||
return (dp->no_cache);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -369,4 +369,13 @@ int iter_ds_toolow(struct dns_msg* msg, struct delegpt* dp);
|
||||
*/
|
||||
int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp);
|
||||
|
||||
/**
|
||||
* Lookup if no_cache is set in stub or fwd.
|
||||
* @param qstate: query state with env with hints and fwds.
|
||||
* @param qinf: query name to lookup for.
|
||||
* @return true if no_cache is set in stub or fwd.
|
||||
*/
|
||||
int iter_stub_fwd_no_cache(struct module_qstate *qstate,
|
||||
struct query_info *qinf);
|
||||
|
||||
#endif /* ITERATOR_ITER_UTILS_H */
|
||||
|
||||
+200
-28
@@ -69,6 +69,9 @@
|
||||
#include "sldns/parseutil.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
|
||||
/* in msec */
|
||||
int UNKNOWN_SERVER_NICENESS = 376;
|
||||
|
||||
int
|
||||
iter_init(struct module_env* env, int id)
|
||||
{
|
||||
@@ -230,11 +233,12 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)
|
||||
qstate->qinfo.qname, qstate->qinfo.qname_len);
|
||||
if(!dpns) {
|
||||
/* not interested */
|
||||
/* this can happen, for eg. qname minimisation asked
|
||||
* for an NXDOMAIN to be validated, and used qtype
|
||||
* A for that, and the error of that, the name, is
|
||||
* not listed in super_iq->dp */
|
||||
verbose(VERB_ALGO, "subq error, but not interested");
|
||||
log_query_info(VERB_ALGO, "superq", &super->qinfo);
|
||||
if(super_iq->dp)
|
||||
delegpt_log(VERB_ALGO, super_iq->dp);
|
||||
log_assert(0);
|
||||
return;
|
||||
} else {
|
||||
/* see if the failure did get (parent-lame) info */
|
||||
@@ -303,14 +307,49 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)
|
||||
if((msg=msg_cache_lookup(qstate->env,
|
||||
qstate->qinfo.qname, qstate->qinfo.qname_len,
|
||||
qstate->qinfo.qtype, qstate->qinfo.qclass,
|
||||
qstate->query_flags, 0, 0))
|
||||
qstate->query_flags, 0,
|
||||
qstate->env->cfg->serve_expired_ttl_reset))
|
||||
!= NULL) {
|
||||
if(qstate->env->cfg->serve_expired_ttl_reset) {
|
||||
struct reply_info* rep =
|
||||
(struct reply_info*)msg->entry.data;
|
||||
if(rep && *qstate->env->now +
|
||||
qstate->env->cfg->serve_expired_ttl >
|
||||
rep->serve_expired_ttl) {
|
||||
rep->serve_expired_ttl =
|
||||
*qstate->env->now +
|
||||
qstate->env->cfg->serve_expired_ttl;
|
||||
}
|
||||
}
|
||||
lock_rw_unlock(&msg->entry.lock);
|
||||
return error_response(qstate, id, rcode);
|
||||
}
|
||||
/* serving expired contents, but nothing is cached
|
||||
* at all, so the servfail cache entry is useful
|
||||
* (stops waste of time on this servfail NORR_TTL) */
|
||||
} else {
|
||||
/* don't overwrite existing (non-expired) data in
|
||||
* cache with a servfail */
|
||||
struct msgreply_entry* msg;
|
||||
if((msg=msg_cache_lookup(qstate->env,
|
||||
qstate->qinfo.qname, qstate->qinfo.qname_len,
|
||||
qstate->qinfo.qtype, qstate->qinfo.qclass,
|
||||
qstate->query_flags, *qstate->env->now, 0))
|
||||
!= NULL) {
|
||||
struct reply_info* rep = (struct reply_info*)
|
||||
msg->entry.data;
|
||||
if(FLAGS_GET_RCODE(rep->flags) ==
|
||||
LDNS_RCODE_NOERROR ||
|
||||
FLAGS_GET_RCODE(rep->flags) ==
|
||||
LDNS_RCODE_NXDOMAIN) {
|
||||
/* we have a good entry,
|
||||
* don't overwrite */
|
||||
lock_rw_unlock(&msg->entry.lock);
|
||||
return error_response(qstate, id, rcode);
|
||||
}
|
||||
lock_rw_unlock(&msg->entry.lock);
|
||||
}
|
||||
|
||||
}
|
||||
memset(&err, 0, sizeof(err));
|
||||
err.flags = (uint16_t)(BIT_QR | BIT_RA);
|
||||
@@ -318,6 +357,7 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)
|
||||
err.qdcount = 1;
|
||||
err.ttl = NORR_TTL;
|
||||
err.prefetch_ttl = PREFETCH_TTL_CALC(err.ttl);
|
||||
err.serve_expired_ttl = NORR_TTL;
|
||||
/* do not waste time trying to validate this servfail */
|
||||
err.security = sec_status_indeterminate;
|
||||
verbose(VERB_ALGO, "store error response in message cache");
|
||||
@@ -536,7 +576,7 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/** see if last resort is possible - does config allow queries to parent */
|
||||
static int
|
||||
can_have_last_resort(struct module_env* env, uint8_t* nm, size_t nmlen,
|
||||
uint16_t qclass)
|
||||
uint16_t qclass, struct delegpt** retdp)
|
||||
{
|
||||
struct delegpt* fwddp;
|
||||
struct iter_hints_stub* stub;
|
||||
@@ -549,12 +589,14 @@ can_have_last_resort(struct module_env* env, uint8_t* nm, size_t nmlen,
|
||||
/* has_parent side is turned off for stub_first, where we
|
||||
* are allowed to go to the parent */
|
||||
stub->dp->has_parent_side_NS) {
|
||||
if(retdp) *retdp = stub->dp;
|
||||
return 0;
|
||||
}
|
||||
if((fwddp = forwards_find(env->fwds, nm, qclass)) &&
|
||||
/* has_parent_side is turned off for forward_first, where
|
||||
* we are allowed to go to the parent */
|
||||
fwddp->has_parent_side_NS) {
|
||||
if(retdp) *retdp = fwddp;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -787,6 +829,7 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
||||
iq->dp = delegpt_copy(stub_dp, qstate->region);
|
||||
if(!iq->dp) {
|
||||
log_err("out of memory priming stub");
|
||||
errinf(qstate, "malloc failure, priming stub");
|
||||
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
return 1; /* return 1 to make module stop, with error */
|
||||
}
|
||||
@@ -805,6 +848,7 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
||||
LDNS_RR_TYPE_NS, qclass, qstate, id, iq,
|
||||
QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0)) {
|
||||
verbose(VERB_ALGO, "could not prime stub");
|
||||
errinf(qstate, "could not generate lookup for stub prime");
|
||||
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
return 1; /* return 1 to make module stop, with error */
|
||||
}
|
||||
@@ -820,6 +864,7 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
||||
fptr_ok(fptr_whitelist_modenv_kill_sub(
|
||||
qstate->env->kill_sub));
|
||||
(*qstate->env->kill_sub)(subq);
|
||||
errinf(qstate, "malloc failure, in stub prime");
|
||||
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
return 1; /* return 1 to make module stop, with error */
|
||||
}
|
||||
@@ -903,6 +948,7 @@ auth_zone_delegpt(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 1; /* just fallback */
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
errinf(qstate, "malloc failure");
|
||||
return 0;
|
||||
}
|
||||
dp->name = regional_alloc_init(qstate->region,
|
||||
@@ -914,6 +960,7 @@ auth_zone_delegpt(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 1; /* just fallback */
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
errinf(qstate, "malloc failure");
|
||||
return 0;
|
||||
}
|
||||
dp->namelen = z->namelen;
|
||||
@@ -1000,7 +1047,7 @@ generate_ns_check(struct module_qstate* qstate, struct iter_qstate* iq, int id)
|
||||
if(iq->depth == ie->max_dependency_depth)
|
||||
return;
|
||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
|
||||
iq->qchase.qclass))
|
||||
iq->qchase.qclass, NULL))
|
||||
return;
|
||||
/* is this query the same as the nscheck? */
|
||||
if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS &&
|
||||
@@ -1104,7 +1151,7 @@ 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) {
|
||||
if(iq->refetch_glue && iq->dp) {
|
||||
delname = iq->dp->name;
|
||||
delnamelen = iq->dp->namelen;
|
||||
}
|
||||
@@ -1157,6 +1204,10 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if(iq->query_restart_count > MAX_RESTART_COUNT) {
|
||||
verbose(VERB_QUERY, "request has exceeded the maximum number"
|
||||
" of query restarts with %d", iq->query_restart_count);
|
||||
errinf(qstate, "request has exceeded the maximum number "
|
||||
"restarts (eg. indirections)");
|
||||
if(iq->qchase.qname)
|
||||
errinf_dname(qstate, "stop at", iq->qchase.qname);
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
@@ -1168,6 +1219,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if(iq->depth > ie->max_dependency_depth) {
|
||||
verbose(VERB_QUERY, "request has exceeded the maximum "
|
||||
"dependency depth with depth of %d", iq->depth);
|
||||
errinf(qstate, "request has exceeded the maximum dependency "
|
||||
"depth (eg. nameserver lookup recursion)");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
@@ -1184,10 +1237,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
*/
|
||||
if (iq->refetch_glue &&
|
||||
iq->dp &&
|
||||
!can_have_last_resort(qstate->env,
|
||||
iq->dp->name,
|
||||
iq->dp->namelen,
|
||||
iq->qchase.qclass)) {
|
||||
!can_have_last_resort(qstate->env, iq->dp->name,
|
||||
iq->dp->namelen, iq->qchase.qclass, NULL)) {
|
||||
iq->refetch_glue = 0;
|
||||
}
|
||||
|
||||
@@ -1196,7 +1247,13 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* This either results in a query restart (CNAME cache response), a
|
||||
* terminating response (ANSWER), or a cache miss (null). */
|
||||
|
||||
if(qstate->blacklist) {
|
||||
if (iter_stub_fwd_no_cache(qstate, &iq->qchase)) {
|
||||
/* Asked to not query cache. */
|
||||
verbose(VERB_ALGO, "no-cache set, going to the network");
|
||||
qstate->no_cache_lookup = 1;
|
||||
qstate->no_cache_store = 1;
|
||||
msg = NULL;
|
||||
} else if(qstate->blacklist) {
|
||||
/* if cache, or anything else, was blacklisted then
|
||||
* getting older results from cache is a bad idea, no cache */
|
||||
verbose(VERB_ALGO, "cache blacklisted, going to the network");
|
||||
@@ -1240,9 +1297,12 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
verbose(VERB_ALGO, "returning CNAME response from "
|
||||
"cache");
|
||||
if(!handle_cname_response(qstate, iq, msg,
|
||||
&sname, &slen))
|
||||
&sname, &slen)) {
|
||||
errinf(qstate, "failed to prepend CNAME "
|
||||
"components, malloc failure");
|
||||
return error_response(qstate, id,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
iq->qchase.qname = sname;
|
||||
iq->qchase.qname_len = slen;
|
||||
/* This *is* a query restart, even if it is a cheap
|
||||
@@ -1260,6 +1320,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* if from cache, NULL, else insert 'cache IP' len=0 */
|
||||
if(qstate->reply_origin)
|
||||
sock_list_insert(&qstate->reply_origin, NULL, 0, qstate->region);
|
||||
if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_SERVFAIL)
|
||||
errinf(qstate, "SERVFAIL in cache");
|
||||
/* it is an answer, response, to final state */
|
||||
verbose(VERB_ALGO, "returning answer from cache.");
|
||||
iq->response = msg;
|
||||
@@ -1271,6 +1333,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
{
|
||||
if(!iq->dp) {
|
||||
log_err("alloc failure for forward dp");
|
||||
errinf(qstate, "malloc failure for forward zone");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
iq->refetch_glue = 0;
|
||||
@@ -1290,6 +1353,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if(iq->refetch_glue) {
|
||||
if(!iq->dp) {
|
||||
log_err("internal or malloc fail: no dp for refetch");
|
||||
errinf(qstate, "malloc failure, for delegation info");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
delname = iq->dp->name;
|
||||
@@ -1300,7 +1364,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue ||
|
||||
(iq->qchase.qtype == LDNS_RR_TYPE_NS && qstate->prefetch_leeway
|
||||
&& can_have_last_resort(qstate->env, delname, delnamelen, iq->qchase.qclass))) {
|
||||
&& can_have_last_resort(qstate->env, delname, delnamelen, iq->qchase.qclass, NULL))) {
|
||||
/* remove first label from delname, root goes to hints,
|
||||
* but only to fetch glue, not for qtype=DS. */
|
||||
/* also when prefetching an NS record, fetch it again from
|
||||
@@ -1349,12 +1413,14 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->qchase.qclass);
|
||||
if(!iq->dp) {
|
||||
log_err("internal error: no hints dp");
|
||||
errinf(qstate, "no hints for this class");
|
||||
return error_response(qstate, id,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
iq->dp = delegpt_copy(iq->dp, qstate->region);
|
||||
if(!iq->dp) {
|
||||
log_err("out of memory in safety belt");
|
||||
errinf(qstate, "malloc failure, in safety belt");
|
||||
return error_response(qstate, id,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
@@ -1398,6 +1464,9 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
log_nametypeclass(VERB_ALGO, "ratelimit exceeded with "
|
||||
"delegation point", iq->dp->name,
|
||||
LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN);
|
||||
qstate->was_ratelimited = 1;
|
||||
errinf(qstate, "query was ratelimited");
|
||||
errinf_dname(qstate, "for zone", iq->dp->name);
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
}
|
||||
@@ -1416,9 +1485,29 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
*/
|
||||
if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
|
||||
iq->dp)) {
|
||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass)) {
|
||||
struct delegpt* retdp = NULL;
|
||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &retdp)) {
|
||||
if(retdp) {
|
||||
verbose(VERB_QUERY, "cache has stub "
|
||||
"or fwd but no addresses, "
|
||||
"fallback to config");
|
||||
iq->dp = delegpt_copy(retdp,
|
||||
qstate->region);
|
||||
if(!iq->dp) {
|
||||
log_err("out of memory in "
|
||||
"stub/fwd fallback");
|
||||
errinf(qstate, "malloc failure, for fallback to config");
|
||||
return error_response(qstate,
|
||||
id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
verbose(VERB_ALGO, "useless dp "
|
||||
"but cannot go up, servfail");
|
||||
delegpt_log(VERB_ALGO, iq->dp);
|
||||
errinf(qstate, "no useful nameservers, "
|
||||
"and cannot go up");
|
||||
errinf_dname(qstate, "for zone", iq->dp->name);
|
||||
return error_response(qstate, id,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
@@ -1438,6 +1527,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->dp = delegpt_copy(iq->dp, qstate->region);
|
||||
if(!iq->dp) {
|
||||
log_err("out of memory in safety belt");
|
||||
errinf(qstate, "malloc failure, in safety belt, for root");
|
||||
return error_response(qstate, id,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
@@ -1492,6 +1582,7 @@ processInitRequest2(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
struct iter_hints_stub* stub;
|
||||
if(!iq->dp) {
|
||||
log_err("internal or malloc fail: no dp for refetch");
|
||||
errinf(qstate, "malloc failure, no delegation info");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
/* Do not send queries above stub, do not set delname to dp if
|
||||
@@ -1779,9 +1870,11 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
log_assert(iq->dp);
|
||||
|
||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
|
||||
iq->qchase.qclass)) {
|
||||
iq->qchase.qclass, NULL)) {
|
||||
/* fail -- no more targets, no more hope of targets, no hope
|
||||
* of a response. */
|
||||
errinf(qstate, "all the configured stub or forward servers failed,");
|
||||
errinf_dname(qstate, "at zone", iq->dp->name);
|
||||
verbose(VERB_QUERY, "configured stub or forward servers failed -- returning SERVFAIL");
|
||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
@@ -1841,6 +1934,8 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
int qs = 0;
|
||||
verbose(VERB_ALGO, "try parent-side target name");
|
||||
if(!query_for_targets(qstate, iq, ie, id, 1, &qs)) {
|
||||
errinf(qstate, "could not fetch nameserver");
|
||||
errinf_dname(qstate, "at zone", iq->dp->name);
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
iq->num_target_queries += qs;
|
||||
@@ -1852,6 +1947,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
if(iq->depth == ie->max_dependency_depth) {
|
||||
verbose(VERB_QUERY, "maxdepth and need more nameservers, fail");
|
||||
errinf(qstate, "cannot fetch more nameservers because at max dependency depth");
|
||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(iq->depth > 0 && iq->target_count &&
|
||||
@@ -1860,6 +1956,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
dname_str(qstate->qinfo.qname, s);
|
||||
verbose(VERB_QUERY, "request %s has exceeded the maximum "
|
||||
"number of glue fetches %d", s, iq->target_count[1]);
|
||||
errinf(qstate, "exceeded the maximum number of glue fetches");
|
||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
/* mark cycle targets for parent-side lookups */
|
||||
@@ -1872,7 +1969,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if( ((ie->supports_ipv6 && !ns->done_pside6) ||
|
||||
(ie->supports_ipv4 && !ns->done_pside4)) &&
|
||||
!can_have_last_resort(qstate->env, ns->name, ns->namelen,
|
||||
iq->qchase.qclass)) {
|
||||
iq->qchase.qclass, NULL)) {
|
||||
log_nametypeclass(VERB_ALGO, "cannot pside lookup ns "
|
||||
"because it is also a stub/forward,",
|
||||
ns->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
|
||||
@@ -1885,9 +1982,11 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* Send the AAAA request. */
|
||||
if(!generate_parentside_target_query(qstate, iq, id,
|
||||
ns->name, ns->namelen,
|
||||
LDNS_RR_TYPE_AAAA, iq->qchase.qclass))
|
||||
LDNS_RR_TYPE_AAAA, iq->qchase.qclass)) {
|
||||
errinf_dname(qstate, "could not generate nameserver AAAA lookup for", ns->name);
|
||||
return error_response(qstate, id,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
ns->done_pside6 = 1;
|
||||
query_count++;
|
||||
}
|
||||
@@ -1895,9 +1994,11 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* Send the A request. */
|
||||
if(!generate_parentside_target_query(qstate, iq, id,
|
||||
ns->name, ns->namelen,
|
||||
LDNS_RR_TYPE_A, iq->qchase.qclass))
|
||||
LDNS_RR_TYPE_A, iq->qchase.qclass)) {
|
||||
errinf_dname(qstate, "could not generate nameserver A lookup for", ns->name);
|
||||
return error_response(qstate, id,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
ns->done_pside4 = 1;
|
||||
query_count++;
|
||||
}
|
||||
@@ -1918,6 +2019,8 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->deleg_msg?iq->deleg_msg->rep:
|
||||
(iq->response?iq->response->rep:NULL));
|
||||
|
||||
errinf(qstate, "all servers for this domain failed,");
|
||||
errinf_dname(qstate, "at zone", iq->dp->name);
|
||||
verbose(VERB_QUERY, "out of query targets -- returning SERVFAIL");
|
||||
/* fail -- no more targets, no more hope of targets, no hope
|
||||
* of a response. */
|
||||
@@ -1951,6 +2054,7 @@ processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id)
|
||||
}
|
||||
/* robustcheck for internal error: we are not underneath the dp */
|
||||
if(!dname_subdomain_c(iq->dsns_point, iq->dp->name)) {
|
||||
errinf_dname(qstate, "for DS query parent-child nameserver search the query is not under the zone", iq->dp->name);
|
||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
@@ -1971,6 +2075,7 @@ processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id)
|
||||
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)) {
|
||||
errinf_dname(qstate, "for DS query parent-child nameserver search, could not generate NS lookup for", iq->dsns_point);
|
||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
@@ -2016,11 +2121,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if(iq->referral_count > MAX_REFERRAL_COUNT) {
|
||||
verbose(VERB_QUERY, "request has exceeded the maximum "
|
||||
"number of referrrals with %d", iq->referral_count);
|
||||
errinf(qstate, "exceeded the maximum of referrals");
|
||||
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);
|
||||
errinf(qstate, "exceeded the maximum number of sends");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
@@ -2028,6 +2135,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* or another failure occurred */
|
||||
if(!iq->dp) {
|
||||
verbose(VERB_QUERY, "Failed to get a delegation, giving up");
|
||||
errinf(qstate, "failed to get a delegation (eg. prime failure)");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(!ie->supports_ipv6)
|
||||
@@ -2045,7 +2153,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(iq->minimisation_state == INIT_MINIMISE_STATE) {
|
||||
if(iq->minimisation_state == INIT_MINIMISE_STATE
|
||||
&& !(iq->chase_flags & BIT_RD)) {
|
||||
/* (Re)set qinfo_out to (new) delegation point, except when
|
||||
* qinfo_out is already a subdomain of dp. This happens when
|
||||
* increasing by more than one label at once (QNAMEs with more
|
||||
@@ -2187,6 +2296,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* no internet fallback */
|
||||
verbose(VERB_ALGO, "auth zone lookup failed, no fallback,"
|
||||
" servfail");
|
||||
errinf(qstate, "auth zone lookup failed, fallback is off");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(iq->dp && iq->dp->auth_dp) {
|
||||
@@ -2212,6 +2322,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
int extra = 0;
|
||||
size_t naddr, nres, navail;
|
||||
if(!query_for_targets(qstate, iq, ie, id, -1, &extra)) {
|
||||
errinf(qstate, "could not fetch nameservers for 0x20 fallback");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
iq->num_target_queries += extra;
|
||||
@@ -2292,6 +2403,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
"missing target");
|
||||
if(!query_for_targets(qstate, iq, ie, id,
|
||||
1, &qs)) {
|
||||
errinf(qstate, "could not fetch nameserver");
|
||||
errinf_dname(qstate, "at zone", iq->dp->name);
|
||||
return error_response(qstate, id,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
@@ -2362,6 +2475,9 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
ie->num_queries_ratelimited++;
|
||||
lock_basic_unlock(&ie->queries_ratelimit_lock);
|
||||
verbose(VERB_ALGO, "query exceeded ratelimits");
|
||||
qstate->was_ratelimited = 1;
|
||||
errinf_dname(qstate, "exceeded ratelimit for zone",
|
||||
iq->dp->name);
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
}
|
||||
@@ -2526,6 +2642,15 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* DNAME to a subdomain loop; do not recurse */
|
||||
type = RESPONSE_TYPE_ANSWER;
|
||||
}
|
||||
} else if(type == RESPONSE_TYPE_CNAME &&
|
||||
iq->qchase.qtype == LDNS_RR_TYPE_CNAME &&
|
||||
iq->minimisation_state == MINIMISE_STATE &&
|
||||
query_dname_compare(iq->qchase.qname, iq->qinfo_out.qname) == 0) {
|
||||
/* The minimised query for full QTYPE and hidden QTYPE can be
|
||||
* classified as CNAME response type, even when the original
|
||||
* QTYPE=CNAME. This should be treated as answer response type.
|
||||
*/
|
||||
type = RESPONSE_TYPE_ANSWER;
|
||||
}
|
||||
|
||||
/* handle each of the type cases */
|
||||
@@ -2570,7 +2695,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
sock_list_insert(&qstate->reply_origin,
|
||||
&qstate->reply->addr, qstate->reply->addrlen,
|
||||
qstate->region);
|
||||
if(iq->minimisation_state != DONOT_MINIMISE_STATE) {
|
||||
if(iq->minimisation_state != DONOT_MINIMISE_STATE
|
||||
&& !(iq->chase_flags & BIT_RD)) {
|
||||
if(FLAGS_GET_RCODE(iq->response->rep->flags) !=
|
||||
LDNS_RCODE_NOERROR) {
|
||||
if(qstate->env->cfg->qname_minimisation_strict)
|
||||
@@ -2607,6 +2733,12 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
verbose(VERB_ALGO,
|
||||
"could not validate NXDOMAIN "
|
||||
"response");
|
||||
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 next_state(iq, QUERYTARGETS_STATE);
|
||||
@@ -2674,11 +2806,15 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->dp = delegpt_from_message(iq->response, qstate->region);
|
||||
if (qstate->env->cfg->qname_minimisation)
|
||||
iq->minimisation_state = INIT_MINIMISE_STATE;
|
||||
if(!iq->dp)
|
||||
if(!iq->dp) {
|
||||
errinf(qstate, "malloc failure, for delegation point");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(!cache_fill_missing(qstate->env, iq->qchase.qclass,
|
||||
qstate->region, iq->dp))
|
||||
qstate->region, iq->dp)) {
|
||||
errinf(qstate, "malloc failure, copy extra info into delegation point");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(iq->store_parent_NS && query_dname_compare(iq->dp->name,
|
||||
iq->store_parent_NS->name) == 0)
|
||||
iter_merge_retry_counts(iq->dp, iq->store_parent_NS);
|
||||
@@ -2740,8 +2876,10 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
/* Process the CNAME response. */
|
||||
if(!handle_cname_response(qstate, iq, iq->response,
|
||||
&sname, &snamelen))
|
||||
&sname, &snamelen)) {
|
||||
errinf(qstate, "malloc failure, CNAME info");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
/* cache the CNAME response under the current query */
|
||||
/* NOTE : set referral=1, so that rrsets get stored but not
|
||||
* the partial query answer (CNAME only). */
|
||||
@@ -2754,16 +2892,18 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* set the current request's qname to the new value. */
|
||||
iq->qchase.qname = sname;
|
||||
iq->qchase.qname_len = snamelen;
|
||||
if (qstate->env->cfg->qname_minimisation)
|
||||
iq->minimisation_state = INIT_MINIMISE_STATE;
|
||||
/* Clear the query state, since this is a query restart. */
|
||||
iq->deleg_msg = NULL;
|
||||
iq->dp = NULL;
|
||||
iq->dsns_point = NULL;
|
||||
iq->auth_zone_response = 0;
|
||||
/* Note the query restart. */
|
||||
iq->query_restart_count++;
|
||||
iq->sent_count = 0;
|
||||
if(iq->minimisation_state != MINIMISE_STATE)
|
||||
/* Only count as query restart when it is not an extra
|
||||
* query as result of qname minimisation. */
|
||||
iq->query_restart_count++;
|
||||
if(qstate->env->cfg->qname_minimisation)
|
||||
iq->minimisation_state = INIT_MINIMISE_STATE;
|
||||
|
||||
/* stop current outstanding queries.
|
||||
* FIXME: should the outstanding queries be waited for and
|
||||
@@ -2840,6 +2980,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->dp->name, iq->dp->namelen, qstate->qinfo.qclass)) {
|
||||
verbose(VERB_ALGO, "auth zone response bad, and no"
|
||||
" fallback possible, servfail");
|
||||
errinf_dname(qstate, "response is bad, no fallback, "
|
||||
"for auth zone", iq->dp->name);
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
verbose(VERB_ALGO, "auth zone response was bad, "
|
||||
@@ -2930,6 +3072,8 @@ processPrimeResponse(struct module_qstate* qstate, int id)
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
qstate->return_msg = iq->response;
|
||||
} else {
|
||||
errinf(qstate, "prime response did not get an answer");
|
||||
errinf_dname(qstate, "for", qstate->qinfo.qname);
|
||||
qstate->return_rcode = LDNS_RCODE_SERVFAIL;
|
||||
qstate->return_msg = NULL;
|
||||
}
|
||||
@@ -3073,6 +3217,7 @@ processDSNSResponse(struct module_qstate* qstate, int id,
|
||||
foriq->dp = delegpt_from_message(qstate->return_msg, forq->region);
|
||||
if(!foriq->dp) {
|
||||
log_err("out of memory in dsns dp alloc");
|
||||
errinf(qstate, "malloc failure, in DS search");
|
||||
return; /* dp==NULL in QUERYTARGETS makes SERVFAIL */
|
||||
}
|
||||
/* success, go query the querytargets in the new dp (and go down) */
|
||||
@@ -3173,6 +3318,8 @@ processClassResponse(struct module_qstate* qstate, int id,
|
||||
to->rep->ttl = from->rep->ttl;
|
||||
if(from->rep->prefetch_ttl < to->rep->prefetch_ttl)
|
||||
to->rep->prefetch_ttl = from->rep->prefetch_ttl;
|
||||
if(from->rep->serve_expired_ttl < to->rep->serve_expired_ttl)
|
||||
to->rep->serve_expired_ttl = from->rep->serve_expired_ttl;
|
||||
}
|
||||
/* are we done? */
|
||||
foriq->num_current_queries --;
|
||||
@@ -3211,6 +3358,8 @@ processCollectClass(struct module_qstate* qstate, int id)
|
||||
c, qstate, id, iq, INIT_REQUEST_STATE,
|
||||
FINISHED_STATE, &subq,
|
||||
(int)!(qstate->query_flags&BIT_CD))) {
|
||||
errinf(qstate, "could not generate class ANY"
|
||||
" lookup query");
|
||||
return error_response(qstate, id,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
@@ -3257,6 +3406,7 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
(iq->response?iq->response->rep:NULL));
|
||||
if(!iq->response) {
|
||||
verbose(VERB_ALGO, "No response is set, servfail");
|
||||
errinf(qstate, "(no response found at query finish)");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
@@ -3427,6 +3577,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->caps_server = 0;
|
||||
iq->caps_reply = NULL;
|
||||
iq->caps_response = NULL;
|
||||
iq->caps_minimisation_state = DONOT_MINIMISE_STATE;
|
||||
iq->state = QUERYTARGETS_STATE;
|
||||
iq->num_current_queries--;
|
||||
/* need fresh attempts for the 0x20 fallback, if
|
||||
@@ -3441,6 +3592,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
|| !qstate->reply) {
|
||||
log_err("Bad event combined with response");
|
||||
outbound_list_remove(&iq->outlist, outbound);
|
||||
errinf(qstate, "module iterator received wrong internal event with a response message");
|
||||
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
return;
|
||||
}
|
||||
@@ -3493,6 +3645,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->caps_server = 0;
|
||||
iq->caps_reply = NULL;
|
||||
iq->caps_response = NULL;
|
||||
iq->caps_minimisation_state = DONOT_MINIMISE_STATE;
|
||||
iq->state = QUERYTARGETS_STATE;
|
||||
iq->num_current_queries--;
|
||||
verbose(VERB_DETAIL, "Capsforid: scrub failed, starting fallback with no response");
|
||||
@@ -3512,15 +3665,30 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->response->rep);
|
||||
|
||||
if(event == module_event_capsfail || iq->caps_fallback) {
|
||||
if(qstate->env->cfg->qname_minimisation &&
|
||||
iq->minimisation_state != DONOT_MINIMISE_STATE) {
|
||||
/* Skip QNAME minimisation for next query, since that
|
||||
* one has to match the current query. */
|
||||
iq->minimisation_state = SKIP_MINIMISE_STATE;
|
||||
}
|
||||
/* for fallback we care about main answer, not additionals */
|
||||
/* removing that makes comparison more likely to succeed */
|
||||
caps_strip_reply(iq->response->rep);
|
||||
|
||||
if(iq->caps_fallback &&
|
||||
iq->caps_minimisation_state != iq->minimisation_state) {
|
||||
/* QNAME minimisation state has changed, restart caps
|
||||
* fallback. */
|
||||
iq->caps_fallback = 0;
|
||||
}
|
||||
|
||||
if(!iq->caps_fallback) {
|
||||
/* start fallback */
|
||||
iq->caps_fallback = 1;
|
||||
iq->caps_server = 0;
|
||||
iq->caps_reply = iq->response->rep;
|
||||
iq->caps_response = iq->response;
|
||||
iq->caps_minimisation_state = iq->minimisation_state;
|
||||
iq->state = QUERYTARGETS_STATE;
|
||||
iq->num_current_queries--;
|
||||
verbose(VERB_DETAIL, "Capsforid: starting fallback");
|
||||
@@ -3552,6 +3720,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
verbose(VERB_DETAIL, "Capsforid fallback: "
|
||||
"getting different replies, failed");
|
||||
outbound_list_remove(&iq->outlist, outbound);
|
||||
errinf(qstate, "0x20 failed, then got different replies in fallback");
|
||||
(void)error_response(qstate, id,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
return;
|
||||
@@ -3590,6 +3759,7 @@ iter_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
if((event == module_event_new || event == module_event_pass) &&
|
||||
iq == NULL) {
|
||||
if(!iter_new(qstate, id)) {
|
||||
errinf(qstate, "malloc failure, new iterator module allocation");
|
||||
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
return;
|
||||
}
|
||||
@@ -3607,11 +3777,13 @@ iter_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
}
|
||||
if(event == module_event_error) {
|
||||
verbose(VERB_ALGO, "got called with event error, giving up");
|
||||
errinf(qstate, "iterator module got the error event");
|
||||
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
log_err("bad event for iterator");
|
||||
errinf(qstate, "iterator module received wrong event");
|
||||
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -83,7 +83,7 @@ struct rbtree_type;
|
||||
/** how nice is a server without further information, in msec
|
||||
* Equals rtt initial timeout value.
|
||||
*/
|
||||
#define UNKNOWN_SERVER_NICENESS 376
|
||||
extern int UNKNOWN_SERVER_NICENESS;
|
||||
/** maximum timeout before a host is deemed unsuitable, in msec.
|
||||
* After host_ttl this will be timed out and the host will be tried again.
|
||||
* Equals RTT_MAX_TIMEOUT
|
||||
@@ -371,6 +371,9 @@ struct iter_qstate {
|
||||
/** QNAME minimisation state, RFC7816 */
|
||||
enum minimisation_state minimisation_state;
|
||||
|
||||
/** State for capsfail: QNAME minimisation state for comparisons. */
|
||||
enum minimisation_state caps_minimisation_state;
|
||||
|
||||
/**
|
||||
* The query info that is sent upstream. Will be a subset of qchase
|
||||
* when qname minimisation is enabled.
|
||||
|
||||
+24
-19
@@ -71,9 +71,8 @@ context_finalize(struct ub_ctx* ctx)
|
||||
return UB_INITFAIL;
|
||||
if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1))
|
||||
return UB_INITFAIL;
|
||||
if(!ctx->env->msg_cache ||
|
||||
cfg->msg_cache_size != slabhash_get_size(ctx->env->msg_cache) ||
|
||||
cfg->msg_cache_slabs != ctx->env->msg_cache->size) {
|
||||
if(!slabhash_is_size(ctx->env->msg_cache, cfg->msg_cache_size,
|
||||
cfg->msg_cache_slabs)) {
|
||||
slabhash_delete(ctx->env->msg_cache);
|
||||
ctx->env->msg_cache = slabhash_create(cfg->msg_cache_slabs,
|
||||
HASH_DEFAULT_STARTARRAY, cfg->msg_cache_size,
|
||||
@@ -130,7 +129,7 @@ find_id(struct ub_ctx* ctx, int* id)
|
||||
|
||||
struct ctx_query*
|
||||
context_new(struct ub_ctx* ctx, const char* name, int rrtype, int rrclass,
|
||||
ub_callback_type cb, void* cbarg)
|
||||
ub_callback_type cb, ub_event_callback_type cb_event, void* cbarg)
|
||||
{
|
||||
struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q));
|
||||
if(!q) return NULL;
|
||||
@@ -142,8 +141,9 @@ context_new(struct ub_ctx* ctx, const char* name, int rrtype, int rrclass,
|
||||
}
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
q->node.key = &q->querynum;
|
||||
q->async = (cb != NULL);
|
||||
q->async = (cb != NULL || cb_event != NULL);
|
||||
q->cb = cb;
|
||||
q->cb_event = cb_event;
|
||||
q->cb_arg = cbarg;
|
||||
q->res = (struct ub_result*)calloc(1, sizeof(*q->res));
|
||||
if(!q->res) {
|
||||
@@ -293,26 +293,29 @@ context_serialize_answer(struct ctx_query* q, int err, sldns_buffer* pkt,
|
||||
* o uint32 id
|
||||
* o uint32 error_code
|
||||
* o uint32 msg_security
|
||||
* o uint32 was_ratelimited
|
||||
* o uint32 length of why_bogus string (+1 for eos); 0 absent.
|
||||
* o why_bogus_string
|
||||
* o the remainder is the answer msg from resolver lookup.
|
||||
* remainder can be length 0.
|
||||
*/
|
||||
size_t size_of_uint32s = 6 * sizeof(uint32_t);
|
||||
size_t pkt_len = pkt?sldns_buffer_remaining(pkt):0;
|
||||
size_t wlen = (pkt&&q->res->why_bogus)?strlen(q->res->why_bogus)+1:0;
|
||||
uint8_t* p;
|
||||
*len = sizeof(uint32_t)*5 + pkt_len + wlen;
|
||||
*len = size_of_uint32s + pkt_len + wlen;
|
||||
p = (uint8_t*)malloc(*len);
|
||||
if(!p) return NULL;
|
||||
sldns_write_uint32(p, UB_LIBCMD_ANSWER);
|
||||
sldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum);
|
||||
sldns_write_uint32(p+2*sizeof(uint32_t), (uint32_t)err);
|
||||
sldns_write_uint32(p+3*sizeof(uint32_t), (uint32_t)q->msg_security);
|
||||
sldns_write_uint32(p+4*sizeof(uint32_t), (uint32_t)wlen);
|
||||
sldns_write_uint32(p+4*sizeof(uint32_t), (uint32_t)q->res->was_ratelimited);
|
||||
sldns_write_uint32(p+5*sizeof(uint32_t), (uint32_t)wlen);
|
||||
if(wlen > 0)
|
||||
memmove(p+5*sizeof(uint32_t), q->res->why_bogus, wlen);
|
||||
memmove(p+size_of_uint32s, q->res->why_bogus, wlen);
|
||||
if(pkt_len > 0)
|
||||
memmove(p+5*sizeof(uint32_t)+wlen,
|
||||
memmove(p+size_of_uint32s+wlen,
|
||||
sldns_buffer_begin(pkt), pkt_len);
|
||||
return p;
|
||||
}
|
||||
@@ -321,21 +324,23 @@ struct ctx_query*
|
||||
context_deserialize_answer(struct ub_ctx* ctx,
|
||||
uint8_t* p, uint32_t len, int* err)
|
||||
{
|
||||
size_t size_of_uint32s = 6 * sizeof(uint32_t);
|
||||
struct ctx_query* q = NULL ;
|
||||
int id;
|
||||
size_t wlen;
|
||||
if(len < 5*sizeof(uint32_t)) return NULL;
|
||||
if(len < size_of_uint32s) return NULL;
|
||||
log_assert( sldns_read_uint32(p) == UB_LIBCMD_ANSWER);
|
||||
id = (int)sldns_read_uint32(p+sizeof(uint32_t));
|
||||
q = (struct ctx_query*)rbtree_search(&ctx->queries, &id);
|
||||
if(!q) return NULL;
|
||||
*err = (int)sldns_read_uint32(p+2*sizeof(uint32_t));
|
||||
q->msg_security = sldns_read_uint32(p+3*sizeof(uint32_t));
|
||||
wlen = (size_t)sldns_read_uint32(p+4*sizeof(uint32_t));
|
||||
if(len > 5*sizeof(uint32_t) && wlen > 0) {
|
||||
if(len >= 5*sizeof(uint32_t)+wlen)
|
||||
q->res->was_ratelimited = (int)sldns_read_uint32(p+4*sizeof(uint32_t));
|
||||
wlen = (size_t)sldns_read_uint32(p+5*sizeof(uint32_t));
|
||||
if(len > size_of_uint32s && wlen > 0) {
|
||||
if(len >= size_of_uint32s+wlen)
|
||||
q->res->why_bogus = (char*)memdup(
|
||||
p+5*sizeof(uint32_t), wlen);
|
||||
p+size_of_uint32s, wlen);
|
||||
if(!q->res->why_bogus) {
|
||||
/* pass malloc failure to the user callback */
|
||||
q->msg_len = 0;
|
||||
@@ -344,9 +349,9 @@ context_deserialize_answer(struct ub_ctx* ctx,
|
||||
}
|
||||
q->res->why_bogus[wlen-1] = 0; /* zero terminated for sure */
|
||||
}
|
||||
if(len > 5*sizeof(uint32_t)+wlen) {
|
||||
q->msg_len = len - 5*sizeof(uint32_t) - wlen;
|
||||
q->msg = (uint8_t*)memdup(p+5*sizeof(uint32_t)+wlen,
|
||||
if(len > size_of_uint32s+wlen) {
|
||||
q->msg_len = len - size_of_uint32s - wlen;
|
||||
q->msg = (uint8_t*)memdup(p+size_of_uint32s+wlen,
|
||||
q->msg_len);
|
||||
if(!q->msg) {
|
||||
/* pass malloc failure to the user callback */
|
||||
@@ -387,12 +392,12 @@ struct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx,
|
||||
uint8_t*
|
||||
context_serialize_quit(uint32_t* len)
|
||||
{
|
||||
uint8_t* p = (uint8_t*)malloc(sizeof(uint32_t));
|
||||
uint32_t* p = (uint32_t*)malloc(sizeof(uint32_t));
|
||||
if(!p)
|
||||
return NULL;
|
||||
*len = sizeof(uint32_t);
|
||||
sldns_write_uint32(p, UB_LIBCMD_QUIT);
|
||||
return p;
|
||||
return (uint8_t*)p;
|
||||
}
|
||||
|
||||
enum ub_ctx_cmd context_serial_getcmd(uint8_t* p, uint32_t len)
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "util/rbtree.h"
|
||||
#include "services/modstack.h"
|
||||
#include "libunbound/unbound.h"
|
||||
#include "libunbound/unbound-event.h"
|
||||
#include "util/data/packed_rrset.h"
|
||||
struct libworker;
|
||||
struct tube;
|
||||
@@ -148,8 +149,10 @@ struct ctx_query {
|
||||
/** was this query cancelled (for bg worker) */
|
||||
int cancelled;
|
||||
|
||||
/** for async query, the callback function */
|
||||
/** for async query, the callback function of type ub_callback_type */
|
||||
ub_callback_type cb;
|
||||
/** for event callbacks the type is ub_event_callback_type */
|
||||
ub_event_callback_type cb_event;
|
||||
/** for async query, the callback user arg */
|
||||
void* cb_arg;
|
||||
|
||||
@@ -238,11 +241,13 @@ void context_query_delete(struct ctx_query* q);
|
||||
* @param rrtype: type
|
||||
* @param rrclass: class
|
||||
* @param cb: callback for async, or NULL for sync.
|
||||
* @param cb_event: event callback for async, or NULL for sync.
|
||||
* @param cbarg: user arg for async queries.
|
||||
* @return new ctx_query or NULL for malloc failure.
|
||||
*/
|
||||
struct ctx_query* context_new(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
int rrclass, ub_callback_type cb, void* cbarg);
|
||||
int rrclass, ub_callback_type cb, ub_event_callback_type cb_event,
|
||||
void* cbarg);
|
||||
|
||||
/**
|
||||
* Get a new alloc. Creates a new one or uses a cached one.
|
||||
|
||||
+5
-13
@@ -109,13 +109,13 @@ static struct ub_ctx* ub_ctx_create_nopipe(void)
|
||||
alloc_init(&ctx->superalloc, NULL, 0);
|
||||
seed = (unsigned int)time(NULL) ^ (unsigned int)getpid();
|
||||
if(!(ctx->seed_rnd = ub_initstate(seed, NULL))) {
|
||||
seed = 0;
|
||||
explicit_bzero(&seed, sizeof(seed));
|
||||
ub_randfree(ctx->seed_rnd);
|
||||
free(ctx);
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
seed = 0;
|
||||
explicit_bzero(&seed, sizeof(seed));
|
||||
lock_basic_init(&ctx->qqpipe_lock);
|
||||
lock_basic_init(&ctx->rrpipe_lock);
|
||||
lock_basic_init(&ctx->cfglock);
|
||||
@@ -392,7 +392,6 @@ ub_ctx_add_ta(struct ub_ctx* ctx, const char* ta)
|
||||
}
|
||||
if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_list, dup)) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
free(dup);
|
||||
return UB_NOMEM;
|
||||
}
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
@@ -412,7 +411,6 @@ ub_ctx_add_ta_file(struct ub_ctx* ctx, const char* fname)
|
||||
}
|
||||
if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_file_list, dup)) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
free(dup);
|
||||
return UB_NOMEM;
|
||||
}
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
@@ -432,7 +430,6 @@ int ub_ctx_add_ta_autr(struct ub_ctx* ctx, const char* fname)
|
||||
if(!cfg_strlist_insert(&ctx->env->cfg->auto_trust_anchor_file_list,
|
||||
dup)) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
free(dup);
|
||||
return UB_NOMEM;
|
||||
}
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
@@ -452,7 +449,6 @@ ub_ctx_trustedkeys(struct ub_ctx* ctx, const char* fname)
|
||||
}
|
||||
if(!cfg_strlist_insert(&ctx->env->cfg->trusted_keys_file_list, dup)) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
free(dup);
|
||||
return UB_NOMEM;
|
||||
}
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
@@ -690,7 +686,7 @@ ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
}
|
||||
/* create new ctx_query and attempt to add to the list */
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
q = context_new(ctx, name, rrtype, rrclass, NULL, NULL);
|
||||
q = context_new(ctx, name, rrtype, rrclass, NULL, NULL, NULL);
|
||||
if(!q)
|
||||
return UB_NOMEM;
|
||||
/* become a resolver thread for a bit */
|
||||
@@ -747,8 +743,7 @@ ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
ub_comm_base_now(ctx->event_worker->base);
|
||||
|
||||
/* create new ctx_query and attempt to add to the list */
|
||||
q = context_new(ctx, name, rrtype, rrclass, (ub_callback_type)callback,
|
||||
mydata);
|
||||
q = context_new(ctx, name, rrtype, rrclass, NULL, callback, mydata);
|
||||
if(!q)
|
||||
return UB_NOMEM;
|
||||
|
||||
@@ -793,7 +788,7 @@ ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
}
|
||||
|
||||
/* create new ctx_query and attempt to add to the list */
|
||||
q = context_new(ctx, name, rrtype, rrclass, callback, mydata);
|
||||
q = context_new(ctx, name, rrtype, rrclass, callback, NULL, mydata);
|
||||
if(!q)
|
||||
return UB_NOMEM;
|
||||
|
||||
@@ -963,7 +958,6 @@ ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr)
|
||||
return UB_NOMEM;
|
||||
}
|
||||
if(!cfg_strlist_insert(&s->addrs, dupl)) {
|
||||
free(dupl);
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
errno=ENOMEM;
|
||||
return UB_NOMEM;
|
||||
@@ -1046,7 +1040,6 @@ int ub_ctx_set_stub(struct ub_ctx* ctx, const char* zone, const char* addr,
|
||||
}
|
||||
if(!cfg_strlist_insert(&elem->addrs, a)) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
free(a);
|
||||
errno = ENOMEM;
|
||||
return UB_NOMEM;
|
||||
}
|
||||
@@ -1234,7 +1227,6 @@ ub_ctx_hosts(struct ub_ctx* ctx, const char* fname)
|
||||
ins)) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
fclose(in);
|
||||
free(ins);
|
||||
errno=ENOMEM;
|
||||
return UB_NOMEM;
|
||||
}
|
||||
|
||||
+38
-32
@@ -158,9 +158,9 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
|
||||
hints_delete(w->env->hints);
|
||||
w->env->hints = NULL;
|
||||
}
|
||||
if(cfg->ssl_upstream) {
|
||||
if(cfg->ssl_upstream || (cfg->tls_cert_bundle && cfg->tls_cert_bundle[0]) || cfg->tls_win_cert) {
|
||||
w->sslctx = connect_sslctx_create(NULL, NULL,
|
||||
cfg->tls_cert_bundle);
|
||||
cfg->tls_cert_bundle, cfg->tls_win_cert);
|
||||
if(!w->sslctx) {
|
||||
/* to make the setup fail after unlock */
|
||||
hints_delete(w->env->hints);
|
||||
@@ -187,7 +187,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
}
|
||||
seed = 0;
|
||||
explicit_bzero(&seed, sizeof(seed));
|
||||
libworker_delete(w);
|
||||
return NULL;
|
||||
}
|
||||
@@ -207,7 +207,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
|
||||
hash_set_raninit((uint32_t)ub_random(w->env->rnd));
|
||||
}
|
||||
}
|
||||
seed = 0;
|
||||
explicit_bzero(&seed, sizeof(seed));
|
||||
|
||||
if(eb)
|
||||
w->base = comm_base_create_event(eb);
|
||||
@@ -521,8 +521,9 @@ libworker_enter_result(struct ub_result* res, sldns_buffer* buf,
|
||||
/** fillup fg results */
|
||||
static void
|
||||
libworker_fillup_fg(struct ctx_query* q, int rcode, sldns_buffer* buf,
|
||||
enum sec_status s, char* why_bogus)
|
||||
enum sec_status s, char* why_bogus, int was_ratelimited)
|
||||
{
|
||||
q->res->was_ratelimited = was_ratelimited;
|
||||
if(why_bogus)
|
||||
q->res->why_bogus = strdup(why_bogus);
|
||||
if(rcode != 0) {
|
||||
@@ -546,13 +547,13 @@ libworker_fillup_fg(struct ctx_query* q, int rcode, sldns_buffer* buf,
|
||||
|
||||
void
|
||||
libworker_fg_done_cb(void* arg, int rcode, sldns_buffer* buf, enum sec_status s,
|
||||
char* why_bogus)
|
||||
char* why_bogus, int was_ratelimited)
|
||||
{
|
||||
struct ctx_query* q = (struct ctx_query*)arg;
|
||||
/* fg query is done; exit comm base */
|
||||
comm_base_exit(q->w->base);
|
||||
|
||||
libworker_fillup_fg(q, rcode, buf, s, why_bogus);
|
||||
libworker_fillup_fg(q, rcode, buf, s, why_bogus, was_ratelimited);
|
||||
}
|
||||
|
||||
/** setup qinfo and edns */
|
||||
@@ -603,16 +604,16 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
|
||||
NULL, 0, NULL, 0, NULL)) {
|
||||
regional_free_all(w->env->scratch);
|
||||
libworker_fillup_fg(q, LDNS_RCODE_NOERROR,
|
||||
w->back->udp_buff, sec_status_insecure, NULL);
|
||||
w->back->udp_buff, sec_status_insecure, NULL, 0);
|
||||
libworker_delete(w);
|
||||
free(qinfo.qname);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
if(ctx->env->auth_zones && auth_zones_answer(ctx->env->auth_zones,
|
||||
w->env, &qinfo, &edns, w->back->udp_buff, w->env->scratch)) {
|
||||
w->env, &qinfo, &edns, NULL, w->back->udp_buff, w->env->scratch)) {
|
||||
regional_free_all(w->env->scratch);
|
||||
libworker_fillup_fg(q, LDNS_RCODE_NOERROR,
|
||||
w->back->udp_buff, sec_status_insecure, NULL);
|
||||
w->back->udp_buff, sec_status_insecure, NULL, 0);
|
||||
libworker_delete(w);
|
||||
free(qinfo.qname);
|
||||
return UB_NOERROR;
|
||||
@@ -634,10 +635,10 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
|
||||
|
||||
void
|
||||
libworker_event_done_cb(void* arg, int rcode, sldns_buffer* buf,
|
||||
enum sec_status s, char* why_bogus)
|
||||
enum sec_status s, char* why_bogus, int was_ratelimited)
|
||||
{
|
||||
struct ctx_query* q = (struct ctx_query*)arg;
|
||||
ub_event_callback_type cb = (ub_event_callback_type)q->cb;
|
||||
ub_event_callback_type cb = q->cb_event;
|
||||
void* cb_arg = q->cb_arg;
|
||||
int cancelled = q->cancelled;
|
||||
|
||||
@@ -656,8 +657,8 @@ libworker_event_done_cb(void* arg, int rcode, sldns_buffer* buf,
|
||||
sec = 1;
|
||||
else if(s == sec_status_secure)
|
||||
sec = 2;
|
||||
(*cb)(cb_arg, rcode, (void*)sldns_buffer_begin(buf),
|
||||
(int)sldns_buffer_limit(buf), sec, why_bogus);
|
||||
(*cb)(cb_arg, rcode, (buf?(void*)sldns_buffer_begin(buf):NULL),
|
||||
(buf?(int)sldns_buffer_limit(buf):0), sec, why_bogus, was_ratelimited);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -684,15 +685,15 @@ int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q,
|
||||
regional_free_all(w->env->scratch);
|
||||
free(qinfo.qname);
|
||||
libworker_event_done_cb(q, LDNS_RCODE_NOERROR,
|
||||
w->back->udp_buff, sec_status_insecure, NULL);
|
||||
w->back->udp_buff, sec_status_insecure, NULL, 0);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
if(ctx->env->auth_zones && auth_zones_answer(ctx->env->auth_zones,
|
||||
w->env, &qinfo, &edns, w->back->udp_buff, w->env->scratch)) {
|
||||
w->env, &qinfo, &edns, NULL, w->back->udp_buff, w->env->scratch)) {
|
||||
regional_free_all(w->env->scratch);
|
||||
free(qinfo.qname);
|
||||
libworker_event_done_cb(q, LDNS_RCODE_NOERROR,
|
||||
w->back->udp_buff, sec_status_insecure, NULL);
|
||||
w->back->udp_buff, sec_status_insecure, NULL, 0);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
/* process new query */
|
||||
@@ -710,7 +711,7 @@ int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q,
|
||||
/** add result to the bg worker result queue */
|
||||
static void
|
||||
add_bg_result(struct libworker* w, struct ctx_query* q, sldns_buffer* pkt,
|
||||
int err, char* reason)
|
||||
int err, char* reason, int was_ratelimited)
|
||||
{
|
||||
uint8_t* msg = NULL;
|
||||
uint32_t len = 0;
|
||||
@@ -724,19 +725,23 @@ add_bg_result(struct libworker* w, struct ctx_query* q, sldns_buffer* pkt,
|
||||
lock_basic_lock(&w->ctx->cfglock);
|
||||
if(reason)
|
||||
q->res->why_bogus = strdup(reason);
|
||||
q->res->was_ratelimited = was_ratelimited;
|
||||
if(pkt) {
|
||||
q->msg_len = sldns_buffer_remaining(pkt);
|
||||
q->msg = memdup(sldns_buffer_begin(pkt), q->msg_len);
|
||||
if(!q->msg)
|
||||
msg = context_serialize_answer(q, UB_NOMEM,
|
||||
NULL, &len);
|
||||
else msg = context_serialize_answer(q, err,
|
||||
NULL, &len);
|
||||
} else msg = context_serialize_answer(q, err, NULL, &len);
|
||||
if(!q->msg) {
|
||||
msg = context_serialize_answer(q, UB_NOMEM, NULL, &len);
|
||||
} else {
|
||||
msg = context_serialize_answer(q, err, NULL, &len);
|
||||
}
|
||||
} else {
|
||||
msg = context_serialize_answer(q, err, NULL, &len);
|
||||
}
|
||||
lock_basic_unlock(&w->ctx->cfglock);
|
||||
} else {
|
||||
if(reason)
|
||||
q->res->why_bogus = strdup(reason);
|
||||
q->res->was_ratelimited = was_ratelimited;
|
||||
msg = context_serialize_answer(q, err, pkt, &len);
|
||||
(void)rbtree_delete(&w->ctx->queries, q->node.key);
|
||||
w->ctx->num_async--;
|
||||
@@ -755,7 +760,7 @@ add_bg_result(struct libworker* w, struct ctx_query* q, sldns_buffer* pkt,
|
||||
|
||||
void
|
||||
libworker_bg_done_cb(void* arg, int rcode, sldns_buffer* buf, enum sec_status s,
|
||||
char* why_bogus)
|
||||
char* why_bogus, int was_ratelimited)
|
||||
{
|
||||
struct ctx_query* q = (struct ctx_query*)arg;
|
||||
|
||||
@@ -773,12 +778,13 @@ libworker_bg_done_cb(void* arg, int rcode, sldns_buffer* buf, enum sec_status s,
|
||||
return;
|
||||
}
|
||||
q->msg_security = s;
|
||||
if(!buf)
|
||||
if(!buf) {
|
||||
buf = q->w->env->scratch_buffer;
|
||||
}
|
||||
if(rcode != 0) {
|
||||
error_encode(buf, rcode, NULL, 0, BIT_RD, NULL);
|
||||
}
|
||||
add_bg_result(q->w, q, buf, UB_NOERROR, why_bogus);
|
||||
add_bg_result(q->w, q, buf, UB_NOERROR, why_bogus, was_ratelimited);
|
||||
}
|
||||
|
||||
|
||||
@@ -803,7 +809,7 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
|
||||
return;
|
||||
}
|
||||
if(!setup_qinfo_edns(w, q, &qinfo, &edns)) {
|
||||
add_bg_result(w, q, NULL, UB_SYNTAX, NULL);
|
||||
add_bg_result(w, q, NULL, UB_SYNTAX, NULL, 0);
|
||||
return;
|
||||
}
|
||||
qid = 0;
|
||||
@@ -816,15 +822,15 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
|
||||
NULL, 0, NULL, 0, NULL)) {
|
||||
regional_free_all(w->env->scratch);
|
||||
q->msg_security = sec_status_insecure;
|
||||
add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL);
|
||||
add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL, 0);
|
||||
free(qinfo.qname);
|
||||
return;
|
||||
}
|
||||
if(w->ctx->env->auth_zones && auth_zones_answer(w->ctx->env->auth_zones,
|
||||
w->env, &qinfo, &edns, w->back->udp_buff, w->env->scratch)) {
|
||||
w->env, &qinfo, &edns, NULL, w->back->udp_buff, w->env->scratch)) {
|
||||
regional_free_all(w->env->scratch);
|
||||
q->msg_security = sec_status_insecure;
|
||||
add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL);
|
||||
add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL, 0);
|
||||
free(qinfo.qname);
|
||||
return;
|
||||
}
|
||||
@@ -832,7 +838,7 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
|
||||
/* process new query */
|
||||
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
|
||||
w->back->udp_buff, qid, libworker_bg_done_cb, q)) {
|
||||
add_bg_result(w, q, NULL, UB_NOMEM, NULL);
|
||||
add_bg_result(w, q, NULL, UB_NOMEM, NULL, 0);
|
||||
}
|
||||
free(qinfo.qname);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ def dnssecParse(domain, rrType=RR_TYPE_A):
|
||||
|
||||
resolver = ub_ctx()
|
||||
resolver.add_ta(". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5")
|
||||
resolver.add_ta(". IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D")
|
||||
|
||||
dnssecParse("nic.cz")
|
||||
dnssecParse("nonexistent-domain-blablabla.cz")
|
||||
|
||||
@@ -170,7 +170,7 @@ struct ub_event {
|
||||
struct ub_event_vmt* vmt;
|
||||
};
|
||||
|
||||
typedef void (*ub_event_callback_type)(void*, int, void*, int, int, char*);
|
||||
typedef void (*ub_event_callback_type)(void*, int, void*, int, int, char*, int);
|
||||
|
||||
/**
|
||||
* Create a resolving and validation context.
|
||||
|
||||
@@ -203,6 +203,12 @@ struct ub_result {
|
||||
*/
|
||||
char* why_bogus;
|
||||
|
||||
/**
|
||||
* If the query or one of its subqueries was ratelimited. Useful if
|
||||
* ratelimiting is enabled and answer is SERVFAIL.
|
||||
*/
|
||||
int was_ratelimited;
|
||||
|
||||
/**
|
||||
* TTL for the result, in seconds. If the security is bogus, then
|
||||
* you also cannot trust this value.
|
||||
@@ -674,6 +680,8 @@ struct ub_server_stats {
|
||||
long long qtcp;
|
||||
/** number of outgoing queries over TCP */
|
||||
long long qtcp_outgoing;
|
||||
/** number of queries over (DNS over) TLS */
|
||||
long long qtls;
|
||||
/** number of queries over IPv6 */
|
||||
long long qipv6;
|
||||
/** number of queries with QR bit */
|
||||
@@ -757,6 +765,11 @@ struct ub_server_stats {
|
||||
/** number of times neg cache records were used to generate NXDOMAIN
|
||||
* responses. */
|
||||
long long num_neg_cache_nxdomain;
|
||||
/** number of queries answered from edns-subnet specific data */
|
||||
long long num_query_subnet;
|
||||
/** number of queries answered from edns-subnet specific data, and
|
||||
* the answer was from the edns-subnet cache. */
|
||||
long long num_query_subnet_cache;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+3
-3
@@ -89,15 +89,15 @@ void libworker_handle_control_cmd(struct tube* tube, uint8_t* msg, size_t len,
|
||||
|
||||
/** mesh callback with fg results */
|
||||
void libworker_fg_done_cb(void* arg, int rcode, sldns_buffer* buf,
|
||||
enum sec_status s, char* why_bogus);
|
||||
enum sec_status s, char* why_bogus, int was_ratelimited);
|
||||
|
||||
/** mesh callback with bg results */
|
||||
void libworker_bg_done_cb(void* arg, int rcode, sldns_buffer* buf,
|
||||
enum sec_status s, char* why_bogus);
|
||||
enum sec_status s, char* why_bogus, int was_ratelimited);
|
||||
|
||||
/** mesh callback with event results */
|
||||
void libworker_event_done_cb(void* arg, int rcode, struct sldns_buffer* buf,
|
||||
enum sec_status s, char* why_bogus);
|
||||
enum sec_status s, char* why_bogus, int was_ratelimited);
|
||||
|
||||
/**
|
||||
* Worker signal handler function. User argument is the worker itself.
|
||||
|
||||
+50
-11
@@ -181,6 +181,7 @@ DOWIN="no"
|
||||
W64="yes"
|
||||
WINSSL=""
|
||||
WINEXPAT=""
|
||||
MINJ=""
|
||||
|
||||
# Parse the command line arguments.
|
||||
while [ "$1" ]; do
|
||||
@@ -239,6 +240,7 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
makensis="makensis" # from mingw32-nsis package
|
||||
# flags for crosscompiled dependency libraries
|
||||
cross_flag=""
|
||||
shared_cross_flag=""
|
||||
|
||||
check_svn_root
|
||||
create_temp_dir
|
||||
@@ -249,24 +251,37 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
info "winssl tar unpack"
|
||||
(cd ..; gzip -cd $WINSSL) | tar xf - || error_cleanup "tar unpack of $WINSSL failed"
|
||||
sslinstall="`pwd`/sslinstall"
|
||||
cp -r openssl-* openssl_shared
|
||||
cd openssl-* || error_cleanup "no openssl-X dir in tarball"
|
||||
# configure for crosscompile, without CAPI because it fails
|
||||
# cross-compilation and it is not used anyway
|
||||
# before 1.0.1i need --cross-compile-prefix=i686-w64-mingw32-
|
||||
if test "$mw64" = "mingw64"; then
|
||||
sslflags="no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64"
|
||||
sslflags="no-asm -DOPENSSL_NO_CAPIENG mingw64"
|
||||
else
|
||||
sslflags="no-shared no-asm -DOPENSSL_NO_CAPIENG mingw"
|
||||
sslflags="no-asm -DOPENSSL_NO_CAPIENG mingw"
|
||||
fi
|
||||
info "winssl: Configure $sslflags"
|
||||
CC=${warch}-w64-mingw32-gcc AR=${warch}-w64-mingw32-ar RANLIB=${warch}-w64-mingw32-ranlib WINDRES=${warch}-w64-mingw32-windres ./Configure --prefix="$sslinstall" $sslflags || error_cleanup "OpenSSL Configure failed"
|
||||
info "winssl: Configure no-shared $sslflags"
|
||||
CC=${warch}-w64-mingw32-gcc AR=${warch}-w64-mingw32-ar RANLIB=${warch}-w64-mingw32-ranlib WINDRES=${warch}-w64-mingw32-windres ./Configure --prefix="$sslinstall" no-shared $sslflags || error_cleanup "OpenSSL Configure failed"
|
||||
info "winssl: make"
|
||||
make || error_cleanup "OpenSSL crosscompile failed"
|
||||
make $MINJ || error_cleanup "OpenSSL crosscompile failed"
|
||||
# only install sw not docs, which take a long time.
|
||||
info "winssl: make install_sw"
|
||||
make install_sw || error_cleanup "OpenSSL install failed"
|
||||
cross_flag="$cross_flag --with-ssl=$sslinstall"
|
||||
cd ..
|
||||
|
||||
# shared compile
|
||||
sslsharedinstall="`pwd`/sslsharedinstall"
|
||||
cd openssl_shared
|
||||
info "winssl: Configure shared $sslflags"
|
||||
CC=${warch}-w64-mingw32-gcc AR=${warch}-w64-mingw32-ar RANLIB=${warch}-w64-mingw32-ranlib WINDRES=${warch}-w64-mingw32-windres ./Configure --prefix="$sslsharedinstall" shared $sslflags || error_cleanup "OpenSSL Configure failed"
|
||||
info "winssl: make"
|
||||
make $MINJ || error_cleanup "OpenSSL crosscompile failed"
|
||||
info "winssl: make install_sw"
|
||||
make install_sw || error_cleanup "OpenSSL install failed"
|
||||
shared_cross_flag="$shared_cross_flag --with-ssl=$sslsharedinstall"
|
||||
cd ..
|
||||
fi
|
||||
|
||||
if test -n "$WINEXPAT"; then
|
||||
@@ -277,11 +292,12 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
cd expat-* || error_cleanup "no expat-X dir in tarball"
|
||||
info "wxp: configure"
|
||||
$configure --prefix="$wxpinstall" --exec-prefix="$wxpinstall" --bindir="$wxpinstall/bin" --includedir="$wxpinstall/include" --mandir="$wxpinstall/man" --libdir="$wxpinstall/lib" || error_cleanup "libexpat configure failed"
|
||||
#info "wxp: make"
|
||||
#make || error_cleanup "libexpat crosscompile failed"
|
||||
info "wxp: make"
|
||||
make $MINJ || error_cleanup "libexpat crosscompile failed"
|
||||
info "wxp: make install"
|
||||
make install || error_cleanup "libexpat install failed"
|
||||
cross_flag="$cross_flag --with-libexpat=$wxpinstall"
|
||||
shared_cross_flag="$shared_cross_flag --with-libexpat=$wxpinstall"
|
||||
cd ..
|
||||
fi
|
||||
|
||||
@@ -320,6 +336,10 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
rm -r autom4te* || echo "ignored"
|
||||
fi
|
||||
|
||||
if test "`uname`" = "Linux"; then
|
||||
(cd ..; cp -r unbound unbound_shared)
|
||||
fi
|
||||
|
||||
# procedure for making unbound installer on mingw.
|
||||
info "Creating windows dist unbound $version"
|
||||
info "Calling configure"
|
||||
@@ -338,9 +358,26 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
|| error_cleanup "Could not configure"
|
||||
fi
|
||||
info "Calling make"
|
||||
make || error_cleanup "Could not make"
|
||||
make $MINJ || error_cleanup "Could not make"
|
||||
info "Make complete"
|
||||
|
||||
if test "`uname`" = "Linux"; then
|
||||
info "Make DLL"
|
||||
cd ../unbound_shared
|
||||
echo "$configure"' --enable-debug --disable-flto '"$* $shared_cross_flag "$file_flag" "$file2_flag" "$file3_flag""
|
||||
if test "$W64" = "no"; then
|
||||
$configure --enable-debug --disable-flto $* $shared_cross_flag "$file_flag" "$file2_flag" "$file3_flag" \
|
||||
|| error_cleanup "Could not configure"
|
||||
else
|
||||
$configure --enable-debug --disable-flto $* $shared_cross_flag \
|
||||
|| error_cleanup "Could not configure"
|
||||
fi
|
||||
info "Calling make for DLL"
|
||||
make $MINJ || error_cleanup "Could not make DLL"
|
||||
info "Make DLL complete"
|
||||
cd ../unbound
|
||||
fi
|
||||
|
||||
info "Unbound version: $version"
|
||||
file="unbound-$version.zip"
|
||||
rm -f $file
|
||||
@@ -360,17 +397,19 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
cp ../root.key .
|
||||
cp ../doc/example.conf ../doc/Changelog .
|
||||
cp ../unbound.exe ../unbound-anchor.exe ../unbound-host.exe ../unbound-control.exe ../unbound-checkconf.exe ../unbound-service-install.exe ../unbound-service-remove.exe ../LICENSE ../winrc/unbound-control-setup.cmd ../winrc/unbound-website.url ../winrc/service.conf ../winrc/README.txt ../contrib/create_unbound_ad_servers.cmd ../contrib/warmup.cmd ../contrib/unbound_cache.cmd .
|
||||
mkdir libunbound
|
||||
cp ../../unbound_shared/unbound.h ../../unbound_shared/.libs/libunbound*.dll ../../unbound_shared/.libs/libunbound.dll.a ../../unbound_shared/.libs/libunbound.a ../../unbound_shared/.libs/libunbound*.def ../../sslsharedinstall/lib/libcrypto.dll.a ../../sslsharedinstall/lib/libssl.dll.a ../../sslsharedinstall/bin/libcrypto*.dll ../../sslsharedinstall/bin/libssl*.dll ../../wxpinstall/bin/libexpat*.dll ../../wxpinstall/lib/libexpat.dll.a libunbound/.
|
||||
# zipfile
|
||||
zip ../$file LICENSE README.txt unbound.exe unbound-anchor.exe unbound-host.exe unbound-control.exe unbound-checkconf.exe unbound-service-install.exe unbound-service-remove.exe unbound-control-setup.cmd example.conf service.conf root.key unbound-website.url create_unbound_ad_servers.cmd warmup.cmd unbound_cache.cmd Changelog
|
||||
zip -r ../$file LICENSE README.txt unbound.exe unbound-anchor.exe unbound-host.exe unbound-control.exe unbound-checkconf.exe unbound-service-install.exe unbound-service-remove.exe unbound-control-setup.cmd example.conf service.conf root.key unbound-website.url create_unbound_ad_servers.cmd warmup.cmd unbound_cache.cmd Changelog libunbound
|
||||
info "Testing $file"
|
||||
(cd .. ; zip -T $file )
|
||||
# installer
|
||||
info "Creating installer"
|
||||
quadversion=`cat ../config.h | grep RSRC_PACKAGE_VERSION | sed -e 's/#define RSRC_PACKAGE_VERSION //' -e 's/,/\\./g'`
|
||||
cat ../winrc/setup.nsi | sed -e 's/define VERSION.*$/define VERSION "'$version'"/' -e 's/define QUADVERSION.*$/define QUADVERSION "'$quadversion'"/' > ../winrc/setup_ed.nsi
|
||||
if test "$W64" = "yes"; then
|
||||
if test "$W64" = "no"; then
|
||||
mv ../winrc/setup_ed.nsi ../winrc/setup_ed_old.nsi
|
||||
cat ../winrc/setup_ed_old.nsi | sed -e 's/PROGRAMFILES/PROGRAMFILES64/' > ../winrc/setup_ed.nsi
|
||||
cat ../winrc/setup_ed_old.nsi | sed -e 's/PROGRAMFILES64/PROGRAMFILES/' -e 's/SetRegView 64/SetRegView 32/' > ../winrc/setup_ed.nsi
|
||||
fi
|
||||
"$makensis" ../winrc/setup_ed.nsi
|
||||
info "Created installer"
|
||||
|
||||
@@ -40,9 +40,12 @@ The callback function's prototype is the following:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def inplace_reply_callback(qinfo, qstate, rep, rcode, edns, opt_list_out, region):
|
||||
"""Function that will be registered as an inplace callback function.
|
||||
def inplace_reply_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
region, **kwargs):
|
||||
"""
|
||||
Function that will be registered as an inplace callback function.
|
||||
It will be called when answering with a resolved query.
|
||||
|
||||
:param qinfo: query_info struct;
|
||||
:param qstate: module qstate. It contains the available opt_lists; It
|
||||
SHOULD NOT be altered;
|
||||
@@ -54,7 +57,13 @@ The callback function's prototype is the following:
|
||||
reply. It can be populated with EDNS options;
|
||||
:param region: region to allocate temporary data. Needs to be used when we
|
||||
want to append a new option to opt_list_out.
|
||||
:param **kwargs: Dictionary that may contain parameters added in a future
|
||||
release. Current parameters:
|
||||
``repinfo``: Reply information for a communication point (comm_reply).
|
||||
It is None when the callback happens in the mesh states.
|
||||
|
||||
:return: True on success, False on failure.
|
||||
|
||||
"""
|
||||
|
||||
.. note:: The function's name is irrelevant.
|
||||
@@ -76,9 +85,12 @@ The callback function's prototype is the following:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def inplace_cache_callback(qinfo, qstate, rep, rcode, edns, opt_list_out, region):
|
||||
"""Function that will be registered as an inplace callback function.
|
||||
def inplace_cache_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
region, **kwargs):
|
||||
"""
|
||||
Function that will be registered as an inplace callback function.
|
||||
It will be called when answering from the cache.
|
||||
|
||||
:param qinfo: query_info struct;
|
||||
:param qstate: module qstate. None;
|
||||
:param rep: reply_info struct;
|
||||
@@ -90,7 +102,17 @@ The callback function's prototype is the following:
|
||||
reply. It can be populated with EDNS options;
|
||||
:param region: region to allocate temporary data. Needs to be used when we
|
||||
want to append a new option to opt_list_out.
|
||||
:param **kwargs: Dictionary that may contain parameters added in a future
|
||||
release. Current parameters:
|
||||
``repinfo``: Reply information for a communication point (comm_reply).
|
||||
It is None when the callback happens in the mesh
|
||||
states(modules).
|
||||
|
||||
:return: True on success, False on failure.
|
||||
|
||||
For demonstration purposes we want to see if EDNS option 65002 is present
|
||||
and reply with a new value.
|
||||
|
||||
"""
|
||||
|
||||
.. note:: The function's name is irrelevant.
|
||||
@@ -112,9 +134,12 @@ The callback function's prototype is the following:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def inplace_local_callback(qinfo, qstate, rep, rcode, edns, opt_list_out, region):
|
||||
"""Function that will be registered as an inplace callback function.
|
||||
def inplace_local_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
region, **kwargs):
|
||||
"""
|
||||
Function that will be registered as an inplace callback function.
|
||||
It will be called when answering from local data.
|
||||
|
||||
:param qinfo: query_info struct;
|
||||
:param qstate: module qstate. None;
|
||||
:param rep: reply_info struct;
|
||||
@@ -126,7 +151,14 @@ The callback function's prototype is the following:
|
||||
reply. It can be populated with EDNS options;
|
||||
:param region: region to allocate temporary data. Needs to be used when we
|
||||
want to append a new option to opt_list_out.
|
||||
:param **kwargs: Dictionary that may contain parameters added in a future
|
||||
release. Current parameters:
|
||||
``repinfo``: Reply information for a communication point (comm_reply).
|
||||
It is None when the callback happens in the mesh
|
||||
states(modules).
|
||||
|
||||
:return: True on success, False on failure.
|
||||
|
||||
"""
|
||||
|
||||
.. note:: The function's name is irrelevant.
|
||||
@@ -148,9 +180,12 @@ The callback function's prototype is the following:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def inplace_servfail_callback(qinfo, qstate, rep, rcode, edns, opt_list_out, region):
|
||||
"""Function that will be registered as an inplace callback function.
|
||||
def inplace_servfail_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
region, **kwargs):
|
||||
"""
|
||||
Function that will be registered as an inplace callback function.
|
||||
It will be called when answering with SERVFAIL.
|
||||
|
||||
:param qinfo: query_info struct;
|
||||
:param qstate: module qstate. If not None the relevant opt_lists are
|
||||
available here;
|
||||
@@ -163,7 +198,17 @@ The callback function's prototype is the following:
|
||||
reply. It can be populated with EDNS options;
|
||||
:param region: region to allocate temporary data. Needs to be used when we
|
||||
want to append a new option to opt_list_out.
|
||||
:param **kwargs: Dictionary that may contain parameters added in a future
|
||||
release. Current parameters:
|
||||
``repinfo``: Reply information for a communication point (comm_reply).
|
||||
It is None when the callback happens in the mesh
|
||||
states(modules).
|
||||
|
||||
:return: True on success, False on failure.
|
||||
|
||||
For demonstration purposes we want to reply with an empty EDNS code '65003'
|
||||
and log the IP address(es) of the client(s).
|
||||
|
||||
"""
|
||||
|
||||
.. note:: The function's name is irrelevant.
|
||||
|
||||
@@ -103,42 +103,67 @@ Inplace callbacks
|
||||
:param opt_list_out: :class:`edns_option`. EDNS option list to append options to.
|
||||
:param region: :class:`regional`
|
||||
|
||||
.. function:: register_inplace_cb_reply(py_cb, env)
|
||||
.. function:: inplace_cb_query(qinfo, flags, qstate, addr, zone, region)
|
||||
|
||||
Function prototype for callback functions used in
|
||||
`register_inplace_cb_query`_.
|
||||
|
||||
:param qinfo: :class:`query_info`
|
||||
:param flags: query flags (integer)
|
||||
:param qstate: :class:`module_qstate`
|
||||
:param addr: :class:`sockaddr_storage`
|
||||
:param zone: zone name in wire format (bytes)
|
||||
:param region: :class:`regional`
|
||||
|
||||
.. function:: register_inplace_cb_reply(py_cb, env, id)
|
||||
|
||||
Register py_cb as an inplace reply callback function.
|
||||
|
||||
:param py_cb: Python function that follows `inplace_cb_reply`_'s prototype. **Must** be callable.
|
||||
:param env: :class:`module_env`
|
||||
:param id: Module ID.
|
||||
:return: True on success, False otherwise
|
||||
:rtype: boolean
|
||||
|
||||
.. function:: register_inplace_cb_reply_cache(py_cb, env)
|
||||
.. function:: register_inplace_cb_reply_cache(py_cb, env, id)
|
||||
|
||||
Register py_cb as an inplace reply_cache callback function.
|
||||
|
||||
:param py_cb: Python function that follows `inplace_cb_reply`_'s prototype. **Must** be callable.
|
||||
:param env: :class:`module_env`
|
||||
:param id: Module ID.
|
||||
:return: True on success, False otherwise
|
||||
:rtype: boolean
|
||||
|
||||
.. function:: register_inplace_cb_reply_local(py_cb, env)
|
||||
.. function:: register_inplace_cb_reply_local(py_cb, env, id)
|
||||
|
||||
Register py_cb as an inplace reply_local callback function.
|
||||
|
||||
:param py_cb: Python function that follows `inplace_cb_reply`_'s prototype. **Must** be callable.
|
||||
:param env: :class:`module_env`
|
||||
:param id: Module ID.
|
||||
:return: True on success, False otherwise
|
||||
:rtype: boolean
|
||||
|
||||
.. function:: register_inplace_cb_reply_servfail(py_cb, env)
|
||||
.. function:: register_inplace_cb_reply_servfail(py_cb, env, id)
|
||||
|
||||
Register py_cb as an inplace reply_servfail callback function.
|
||||
|
||||
:param py_cb: Python function that follows `inplace_cb_reply`_'s prototype. **Must** be callable.
|
||||
:param env: :class:`module_env`
|
||||
:param id: Module ID.
|
||||
:return: True on success, False otherwise
|
||||
:rtype: boolean
|
||||
|
||||
.. function:: register_inplace_cb_query(py_cb, env, id)
|
||||
|
||||
Register py_cb as an inplace query callback function.
|
||||
|
||||
:param py_cb: Python function that follows `inplace_cb_query`_'s prototype. **Must** be callable.
|
||||
:param env: :class:`module_env`
|
||||
:param id: Module ID.
|
||||
:return: True on success, False otherwise
|
||||
:rtype: boolean
|
||||
|
||||
Logging
|
||||
-------
|
||||
|
||||
@@ -514,3 +514,33 @@ pythonmod_qstate
|
||||
|
||||
Here you can keep your own private data (each thread has own data object).
|
||||
|
||||
sockaddr_storage
|
||||
-------------------------
|
||||
|
||||
.. class:: sockaddr_storage
|
||||
|
||||
The :class:`sockaddr_storage` provides these data attributes:
|
||||
|
||||
.. attribute:: family
|
||||
|
||||
Address family name as a string. Possible values are `ip4`, `ip6`, and `unix`.
|
||||
|
||||
.. attribute:: addr
|
||||
|
||||
Address in presentation format.
|
||||
|
||||
.. attribute:: raw_addr
|
||||
|
||||
Address in network wire format.
|
||||
|
||||
.. attribute:: port
|
||||
|
||||
Port number. Invalid for Unix address.
|
||||
|
||||
.. attribute:: flowinfo
|
||||
|
||||
Flow info value. Valid only for IPv6 address.
|
||||
|
||||
.. attribute:: scope_id
|
||||
|
||||
Scope ID value. Valid only for IPv6 address.
|
||||
|
||||
@@ -6,18 +6,18 @@
|
||||
Copyright (c) 2016, NLnet Labs.
|
||||
|
||||
This software is open source.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
|
||||
* Neither the name of the organization nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
@@ -43,6 +43,8 @@
|
||||
# This query returns SERVFAIL as the txt record of bogus.nlnetlabs.nl is
|
||||
# intentionally bogus. The reply will contain an empty EDNS option
|
||||
# with option code 65003.
|
||||
# Unbound will also log the source address(es) of the client(s) that made
|
||||
# the request.
|
||||
# (unbound needs to be validating for this example to work)
|
||||
|
||||
# Useful functions:
|
||||
@@ -70,9 +72,11 @@
|
||||
|
||||
|
||||
def inplace_reply_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
region):
|
||||
"""Function that will be registered as an inplace callback function.
|
||||
region, **kwargs):
|
||||
"""
|
||||
Function that will be registered as an inplace callback function.
|
||||
It will be called when answering with a resolved query.
|
||||
|
||||
:param qinfo: query_info struct;
|
||||
:param qstate: module qstate. It contains the available opt_lists; It
|
||||
SHOULD NOT be altered;
|
||||
@@ -84,16 +88,25 @@ def inplace_reply_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
reply. It can be populated with EDNS options;
|
||||
:param region: region to allocate temporary data. Needs to be used when we
|
||||
want to append a new option to opt_list_out.
|
||||
:param **kwargs: Dictionary that may contain parameters added in a future
|
||||
release. Current parameters:
|
||||
``repinfo``: Reply information for a communication point (comm_reply).
|
||||
It is None when the callback happens in the mesh
|
||||
states(modules).
|
||||
|
||||
:return: True on success, False on failure.
|
||||
|
||||
"""
|
||||
log_info("python: called back while replying.")
|
||||
return True
|
||||
|
||||
|
||||
def inplace_cache_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
region):
|
||||
"""Function that will be registered as an inplace callback function.
|
||||
region, **kwargs):
|
||||
"""
|
||||
Function that will be registered as an inplace callback function.
|
||||
It will be called when answering from the cache.
|
||||
|
||||
:param qinfo: query_info struct;
|
||||
:param qstate: module qstate. None;
|
||||
:param rep: reply_info struct;
|
||||
@@ -105,10 +118,17 @@ def inplace_cache_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
reply. It can be populated with EDNS options;
|
||||
:param region: region to allocate temporary data. Needs to be used when we
|
||||
want to append a new option to opt_list_out.
|
||||
:param **kwargs: Dictionary that may contain parameters added in a future
|
||||
release. Current parameters:
|
||||
``repinfo``: Reply information for a communication point (comm_reply).
|
||||
It is None when the callback happens in the mesh
|
||||
states(modules).
|
||||
|
||||
:return: True on success, False on failure.
|
||||
|
||||
For demonstration purposes we want to see if EDNS option 65002 is present
|
||||
and reply with a new value.
|
||||
|
||||
"""
|
||||
log_info("python: called back while answering from cache.")
|
||||
# Inspect the incoming EDNS options.
|
||||
@@ -134,9 +154,11 @@ def inplace_cache_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
|
||||
|
||||
def inplace_local_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
region):
|
||||
"""Function that will be registered as an inplace callback function.
|
||||
region, **kwargs):
|
||||
"""
|
||||
Function that will be registered as an inplace callback function.
|
||||
It will be called when answering from local data.
|
||||
|
||||
:param qinfo: query_info struct;
|
||||
:param qstate: module qstate. None;
|
||||
:param rep: reply_info struct;
|
||||
@@ -148,7 +170,14 @@ def inplace_local_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
reply. It can be populated with EDNS options;
|
||||
:param region: region to allocate temporary data. Needs to be used when we
|
||||
want to append a new option to opt_list_out.
|
||||
:param **kwargs: Dictionary that may contain parameters added in a future
|
||||
release. Current parameters:
|
||||
``repinfo``: Reply information for a communication point (comm_reply).
|
||||
It is None when the callback happens in the mesh
|
||||
states(modules).
|
||||
|
||||
:return: True on success, False on failure.
|
||||
|
||||
"""
|
||||
log_info("python: called back while replying with local data or chaos"
|
||||
" reply.")
|
||||
@@ -156,9 +185,11 @@ def inplace_local_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
|
||||
|
||||
def inplace_servfail_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
region):
|
||||
"""Function that will be registered as an inplace callback function.
|
||||
region, **kwargs):
|
||||
"""
|
||||
Function that will be registered as an inplace callback function.
|
||||
It will be called when answering with SERVFAIL.
|
||||
|
||||
:param qinfo: query_info struct;
|
||||
:param qstate: module qstate. If not None the relevant opt_lists are
|
||||
available here;
|
||||
@@ -171,23 +202,81 @@ def inplace_servfail_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
reply. It can be populated with EDNS options;
|
||||
:param region: region to allocate temporary data. Needs to be used when we
|
||||
want to append a new option to opt_list_out.
|
||||
:param **kwargs: Dictionary that may contain parameters added in a future
|
||||
release. Current parameters:
|
||||
``repinfo``: Reply information for a communication point (comm_reply).
|
||||
It is None when the callback happens in the mesh
|
||||
states(modules).
|
||||
|
||||
:return: True on success, False on failure.
|
||||
|
||||
For demonstration purposes we want to reply with an empty EDNS code '65003'.
|
||||
For demonstration purposes we want to reply with an empty EDNS code '65003'
|
||||
and log the IP address(es) of the client(s).
|
||||
|
||||
"""
|
||||
log_info("python: called back while servfail.")
|
||||
# Append the example ENDS option
|
||||
b = bytearray.fromhex("")
|
||||
edns_opt_list_append(opt_list_out, 65003, b, region)
|
||||
|
||||
# Log the client(s) IP address(es)
|
||||
comm_reply = kwargs['repinfo']
|
||||
if comm_reply:
|
||||
# If it is not None this callback was called before the query reached
|
||||
# the mesh states(modules). There is only one client associated with
|
||||
# this query.
|
||||
addr = comm_reply.addr
|
||||
port = comm_reply.port
|
||||
addr_family = comm_reply.family
|
||||
log_info("python: Client IP: {}({}), port: {}"
|
||||
"".format(addr, addr_family, port))
|
||||
else:
|
||||
# If it is not None this callback was called while the query is in the
|
||||
# mesh states(modules). In this case they may be multiple clients
|
||||
# waiting for this query.
|
||||
# The following code is the same as with the resip.py example.
|
||||
rl = qstate.mesh_info.reply_list
|
||||
while (rl):
|
||||
if rl.query_reply:
|
||||
q = rl.query_reply
|
||||
log_info("python: Client IP: {}({}), port: {}"
|
||||
"".format(q.addr, q.family, q.port))
|
||||
rl = rl.next
|
||||
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def inplace_query_callback(qinfo, flags, qstate, addr, zone, region, **kwargs):
|
||||
"""
|
||||
Function that will be registered as an inplace callback function.
|
||||
It will be called before sending a query to a backend server.
|
||||
|
||||
:param qinfo: query_info struct;
|
||||
:param flags: flags of the query;
|
||||
:param qstate: module qstate. opt_lists are available here;
|
||||
:param addr: struct sockaddr_storage. Address of the backend server;
|
||||
:param zone: zone name in binary;
|
||||
:param region: region to allocate temporary data. Needs to be used when we
|
||||
want to append a new option to opt_lists.
|
||||
:param **kwargs: Dictionary that may contain parameters added in a future
|
||||
release.
|
||||
"""
|
||||
log_info("python: outgoing query to {}@{}".format(addr.addr, addr.port))
|
||||
return True
|
||||
|
||||
|
||||
def init_standard(id, env):
|
||||
"""New version of the init function.
|
||||
"""
|
||||
New version of the init function.
|
||||
|
||||
The function's signature is the same as the C counterpart and allows for
|
||||
extra functionality during init.
|
||||
|
||||
..note:: This function is preferred by unbound over the old init function.
|
||||
..note:: The previously accessible configuration options can now be found in
|
||||
env.cgf.
|
||||
|
||||
"""
|
||||
log_info("python: inited script {}".format(env.cfg.python_script))
|
||||
|
||||
@@ -211,15 +300,23 @@ def init_standard(id, env):
|
||||
if not register_inplace_cb_reply_servfail(inplace_servfail_callback, env, id):
|
||||
return False
|
||||
|
||||
# Register the inplace_query_callback function as an inplace callback
|
||||
# before sending a query to a backend server.
|
||||
if not register_inplace_cb_query(inplace_query_callback, env, id):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def init(id, cfg):
|
||||
"""Previous version init function.
|
||||
"""
|
||||
Previous version of the init function.
|
||||
|
||||
..note:: This function is still supported for backwards compatibility when
|
||||
the init_standard function is missing. When init_standard is
|
||||
present this function SHOULD be omitted to avoid confusion to the
|
||||
reader.
|
||||
|
||||
"""
|
||||
return True
|
||||
|
||||
|
||||
+10
-10
@@ -47,7 +47,7 @@ def deinit(id): return True
|
||||
def inform_super(id, qstate, superqstate, qdata): return True
|
||||
|
||||
def operate(id, event, qstate, qdata):
|
||||
print "Operate", event,"state:",qstate
|
||||
print("Operate {} state: {}".format(event, qstate))
|
||||
|
||||
# Please note that if this module blocks, by moving to the validator
|
||||
# to validate or iterator to lookup or spawn a subquery to look up,
|
||||
@@ -61,14 +61,14 @@ def operate(id, event, qstate, qdata):
|
||||
msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_TXT, RR_CLASS_IN, PKT_QR | PKT_RA | PKT_AA)
|
||||
#append RR
|
||||
if (qstate.qinfo.qtype == RR_TYPE_TXT) or (qstate.qinfo.qtype == RR_TYPE_ANY):
|
||||
rl = qstate.mesh_info.reply_list
|
||||
while (rl):
|
||||
if rl.query_reply:
|
||||
q = rl.query_reply
|
||||
# The TTL of 0 is mandatory, otherwise it ends up in
|
||||
# the cache, and is returned to other IP addresses.
|
||||
msg.answer.append("%s 0 IN TXT \"%s %d (%s)\"" % (qstate.qinfo.qname_str, q.addr,q.port,q.family))
|
||||
rl = rl.next
|
||||
rl = qstate.mesh_info.reply_list
|
||||
while (rl):
|
||||
if rl.query_reply:
|
||||
q = rl.query_reply
|
||||
# The TTL of 0 is mandatory, otherwise it ends up in
|
||||
# the cache, and is returned to other IP addresses.
|
||||
msg.answer.append("%s 0 IN TXT \"%s %d (%s)\"" % (qstate.qinfo.qname_str, q.addr,q.port,q.family))
|
||||
rl = rl.next
|
||||
|
||||
#set qstate.return_msg
|
||||
if not msg.set_return_msg(qstate):
|
||||
@@ -90,7 +90,7 @@ def operate(id, event, qstate, qdata):
|
||||
log_info("pythonmod: iterator module done")
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
|
||||
|
||||
log_err("pythonmod: bad event")
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
||||
|
||||
+262
-52
@@ -12,6 +12,8 @@
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/un.h>
|
||||
#include <stdarg.h>
|
||||
#include "config.h"
|
||||
#include "util/log.h"
|
||||
@@ -43,15 +45,21 @@
|
||||
|
||||
i = 0;
|
||||
while (i < len) {
|
||||
i += name[i] + 1;
|
||||
i += ((unsigned int)name[i]) + 1;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
list = PyList_New(cnt);
|
||||
i = 0; cnt = 0;
|
||||
while (i < len) {
|
||||
PyList_SetItem(list, cnt, PyBytes_FromStringAndSize(name + i + 1, name[i]));
|
||||
i += name[i] + 1;
|
||||
char buf[LDNS_MAX_LABELLEN+1];
|
||||
if(((unsigned int)name[i])+1 <= (unsigned int)sizeof(buf) &&
|
||||
i+(int)((unsigned int)name[i]) < len) {
|
||||
memmove(buf, name + i + 1, (unsigned int)name[i]);
|
||||
buf[(unsigned int)name[i]] = 0;
|
||||
PyList_SetItem(list, cnt, PyString_FromString(buf));
|
||||
}
|
||||
i += ((unsigned int)name[i]) + 1;
|
||||
cnt++;
|
||||
}
|
||||
return list;
|
||||
@@ -159,11 +167,11 @@ struct query_info {
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
PyObject* dnameAsStr(const char* dname) {
|
||||
PyObject* dnameAsStr(PyObject* dname) {
|
||||
char buf[LDNS_MAX_DOMAINLEN+1];
|
||||
buf[0] = '\0';
|
||||
dname_str((uint8_t*)dname, buf);
|
||||
return PyBytes_FromString(buf);
|
||||
dname_str((uint8_t*)PyBytes_AsString(dname), buf);
|
||||
return PyString_FromString(buf);
|
||||
}
|
||||
%}
|
||||
|
||||
@@ -426,6 +434,164 @@ struct dns_msg {
|
||||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
Structure sockaddr_storage
|
||||
* ************************************************************************************ */
|
||||
|
||||
struct sockaddr_storage {};
|
||||
|
||||
%inline %{
|
||||
static size_t _sockaddr_storage_len(const struct sockaddr_storage *ss) {
|
||||
if (ss == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (ss->ss_family) {
|
||||
case AF_INET: return sizeof(struct sockaddr_in);
|
||||
case AF_INET6: return sizeof(struct sockaddr_in6);
|
||||
case AF_UNIX: return sizeof(struct sockaddr_un);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *_sockaddr_storage_family(const struct sockaddr_storage *ss) {
|
||||
if (ss == NULL) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
switch (ss->ss_family) {
|
||||
case AF_INET: return PyUnicode_FromString("ip4");
|
||||
case AF_INET6: return PyUnicode_FromString("ip6");
|
||||
case AF_UNIX: return PyUnicode_FromString("unix");
|
||||
default:
|
||||
return Py_None;
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *_sockaddr_storage_addr(const struct sockaddr_storage *ss) {
|
||||
const struct sockaddr *sa;
|
||||
size_t sa_len;
|
||||
char name[NI_MAXHOST] = {0};
|
||||
|
||||
if (ss == NULL) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
sa = (struct sockaddr *)ss;
|
||||
sa_len = _sockaddr_storage_len(ss);
|
||||
if (sa_len == 0) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
if (getnameinfo(sa, sa_len, name, sizeof(name), NULL, 0, NI_NUMERICHOST) != 0) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
return PyUnicode_FromString(name);
|
||||
}
|
||||
|
||||
PyObject *_sockaddr_storage_raw_addr(const struct sockaddr_storage *ss) {
|
||||
size_t sa_len;
|
||||
|
||||
if (ss == NULL) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
sa_len = _sockaddr_storage_len(ss);
|
||||
if (sa_len == 0) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
if (ss->ss_family == AF_INET) {
|
||||
const struct sockaddr_in *sa = (struct sockaddr_in *)ss;
|
||||
const struct in_addr *raw = (struct in_addr *)&sa->sin_addr;
|
||||
return PyBytes_FromStringAndSize((const char *)raw, sizeof(*raw));
|
||||
}
|
||||
|
||||
if (ss->ss_family == AF_INET6) {
|
||||
const struct sockaddr_in6 *sa = (struct sockaddr_in6 *)ss;
|
||||
const struct in6_addr *raw = (struct in6_addr *)&sa->sin6_addr;
|
||||
return PyBytes_FromStringAndSize((const char *)raw, sizeof(*raw));
|
||||
}
|
||||
|
||||
if (ss->ss_family == AF_UNIX) {
|
||||
const struct sockaddr_un *sa = (struct sockaddr_un *)ss;
|
||||
return PyBytes_FromString(sa->sun_path);
|
||||
}
|
||||
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *_sockaddr_storage_port(const struct sockaddr_storage *ss) {
|
||||
if (ss == NULL) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
if (ss->ss_family == AF_INET) {
|
||||
const struct sockaddr_in *sa4 = (struct sockaddr_in *)ss;
|
||||
return PyInt_FromLong(ntohs(sa4->sin_port));
|
||||
}
|
||||
|
||||
if (ss->ss_family == AF_INET6) {
|
||||
const struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)ss;
|
||||
return PyInt_FromLong(ntohs(sa6->sin6_port));
|
||||
}
|
||||
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *_sockaddr_storage_flowinfo(const struct sockaddr_storage *ss) {
|
||||
const struct sockaddr_in6 *sa6;
|
||||
|
||||
if (ss == NULL || ss->ss_family != AF_INET6) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
sa6 = (struct sockaddr_in6 *)ss;
|
||||
return PyInt_FromLong(ntohl(sa6->sin6_flowinfo));
|
||||
}
|
||||
|
||||
PyObject *_sockaddr_storage_scope_id(const struct sockaddr_storage *ss) {
|
||||
const struct sockaddr_in6 *sa6;
|
||||
|
||||
if (ss == NULL || ss->ss_family != AF_INET6) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
sa6 = (struct sockaddr_in6 *)ss;
|
||||
return PyInt_FromLong(ntohl(sa6->sin6_scope_id));
|
||||
}
|
||||
%}
|
||||
|
||||
%extend sockaddr_storage {
|
||||
%pythoncode %{
|
||||
def _family_get(self): return _sockaddr_storage_family(self)
|
||||
__swig_getmethods__["family"] = _family_get
|
||||
if _newclass: family = _swig_property(_family_get)
|
||||
|
||||
def _addr_get(self): return _sockaddr_storage_addr(self)
|
||||
__swig_getmethods__["addr"] = _addr_get
|
||||
if _newclass: addr = _swig_property(_addr_get)
|
||||
|
||||
def _raw_addr_get(self): return _sockaddr_storage_raw_addr(self)
|
||||
__swig_getmethods__["raw_addr"] = _raw_addr_get
|
||||
if _newclass: raw_addr = _swig_property(_raw_addr_get)
|
||||
|
||||
def _port_get(self): return _sockaddr_storage_port(self)
|
||||
__swig_getmethods__["port"] = _port_get
|
||||
if _newclass: port = _swig_property(_port_get)
|
||||
|
||||
def _flowinfo_get(self): return _sockaddr_storage_flowinfo(self)
|
||||
__swig_getmethods__["flowinfo"] = _flowinfo_get
|
||||
if _newclass: flowinfo = _swig_property(_flowinfo_get)
|
||||
|
||||
def _scope_id_get(self): return _sockaddr_storage_scope_id(self)
|
||||
__swig_getmethods__["scope_id"] = _scope_id_get
|
||||
if _newclass: scope_id = _swig_property(_scope_id_get)
|
||||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
Structure mesh_state
|
||||
* ************************************************************************************ */
|
||||
@@ -438,52 +604,22 @@ struct mesh_reply {
|
||||
struct comm_reply query_reply;
|
||||
};
|
||||
|
||||
%rename(_addr) comm_reply::addr;
|
||||
struct comm_reply {
|
||||
|
||||
struct sockaddr_storage addr;
|
||||
};
|
||||
|
||||
%inline %{
|
||||
|
||||
PyObject* _comm_reply_addr_get(struct comm_reply* reply) {
|
||||
char dest[64];
|
||||
reply_addr2str(reply, dest, 64);
|
||||
if (dest[0] == 0)
|
||||
return Py_None;
|
||||
return PyBytes_FromString(dest);
|
||||
}
|
||||
|
||||
PyObject* _comm_reply_family_get(struct comm_reply* reply) {
|
||||
|
||||
int af = (int)((struct sockaddr_in*) &(reply->addr))->sin_family;
|
||||
|
||||
switch(af) {
|
||||
case AF_INET: return PyBytes_FromString("ip4");
|
||||
case AF_INET6: return PyBytes_FromString("ip6");
|
||||
case AF_UNIX: return PyBytes_FromString("unix");
|
||||
}
|
||||
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject* _comm_reply_port_get(struct comm_reply* reply) {
|
||||
uint16_t port;
|
||||
port = ntohs(((struct sockaddr_in*)&(reply->addr))->sin_port);
|
||||
return PyInt_FromLong(port);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%extend comm_reply {
|
||||
%pythoncode %{
|
||||
def _addr_get(self): return _comm_reply_addr_get(self)
|
||||
def _addr_get(self): return _sockaddr_storage_addr(self._addr)
|
||||
__swig_getmethods__["addr"] = _addr_get
|
||||
if _newclass:addr = _swig_property(_addr_get)
|
||||
|
||||
def _port_get(self): return _comm_reply_port_get(self)
|
||||
def _port_get(self): return _sockaddr_storage_port(self._addr)
|
||||
__swig_getmethods__["port"] = _port_get
|
||||
if _newclass:port = _swig_property(_port_get)
|
||||
|
||||
def _family_get(self): return _comm_reply_family_get(self)
|
||||
def _family_get(self): return _sockaddr_storage_family(self._addr)
|
||||
__swig_getmethods__["family"] = _family_get
|
||||
if _newclass:family = _swig_property(_family_get)
|
||||
%}
|
||||
@@ -883,7 +1019,7 @@ struct config_file {
|
||||
struct config_strlist* local_zones_nodefault;
|
||||
struct config_strlist* local_data;
|
||||
int remote_control_enable;
|
||||
struct config_strlist* control_ifs;
|
||||
struct config_strlist_head control_ifs;
|
||||
int control_port;
|
||||
char* server_key_file;
|
||||
char* server_cert_file;
|
||||
@@ -1081,7 +1217,7 @@ int checkList(PyObject *l)
|
||||
for (i=0; i < PyList_Size(l); i++)
|
||||
{
|
||||
item = PyList_GetItem(l, i);
|
||||
if (!PyBytes_Check(item))
|
||||
if (!PyBytes_Check(item) && !PyUnicode_Check(item))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -1096,23 +1232,40 @@ int pushRRList(sldns_buffer* qb, PyObject *l, uint32_t default_ttl, int qsec,
|
||||
PyObject* item;
|
||||
int i;
|
||||
size_t len;
|
||||
char* s;
|
||||
PyObject* ascstr;
|
||||
|
||||
for (i=0; i < PyList_Size(l); i++)
|
||||
{
|
||||
ascstr = NULL;
|
||||
item = PyList_GetItem(l, i);
|
||||
if(PyObject_TypeCheck(item, &PyBytes_Type)) {
|
||||
s = PyBytes_AsString(item);
|
||||
} else {
|
||||
ascstr = PyUnicode_AsASCIIString(item);
|
||||
s = PyBytes_AsString(ascstr);
|
||||
}
|
||||
|
||||
len = sldns_buffer_remaining(qb);
|
||||
if(qsec) {
|
||||
if(sldns_str2wire_rr_question_buf(PyBytes_AsString(item),
|
||||
if(sldns_str2wire_rr_question_buf(s,
|
||||
sldns_buffer_current(qb), &len, NULL, NULL, 0, NULL, 0)
|
||||
!= 0)
|
||||
!= 0) {
|
||||
if(ascstr)
|
||||
Py_DECREF(ascstr);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if(sldns_str2wire_rr_buf(PyBytes_AsString(item),
|
||||
if(sldns_str2wire_rr_buf(s,
|
||||
sldns_buffer_current(qb), &len, NULL, default_ttl,
|
||||
NULL, 0, NULL, 0) != 0)
|
||||
NULL, 0, NULL, 0) != 0) {
|
||||
if(ascstr)
|
||||
Py_DECREF(ascstr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if(ascstr)
|
||||
Py_DECREF(ascstr);
|
||||
sldns_buffer_skip(qb, len);
|
||||
|
||||
sldns_buffer_write_u16_at(qb, count_offset,
|
||||
@@ -1365,11 +1518,12 @@ int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
|
||||
int python_inplace_cb_reply_generic(struct query_info* qinfo,
|
||||
struct module_qstate* qstate, struct reply_info* rep, int rcode,
|
||||
struct edns_data* edns, struct edns_option** opt_list_out,
|
||||
struct regional* region, int id, void* python_callback)
|
||||
struct comm_reply* repinfo, struct regional* region, int id,
|
||||
void* python_callback)
|
||||
{
|
||||
PyObject *func, *py_edns, *py_qstate, *py_opt_list_out, *py_qinfo;
|
||||
PyObject *py_rep, *py_region;
|
||||
PyObject *result;
|
||||
PyObject *py_rep, *py_repinfo, *py_region;
|
||||
PyObject *py_args, *py_kwargs, *result;
|
||||
int res = 0;
|
||||
|
||||
PyGILState_STATE gstate = PyGILState_Ensure();
|
||||
@@ -1381,15 +1535,21 @@ int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
|
||||
SWIGTYPE_p_p_edns_option, 0);
|
||||
py_qinfo = SWIG_NewPointerObj((void*) qinfo, SWIGTYPE_p_query_info, 0);
|
||||
py_rep = SWIG_NewPointerObj((void*) rep, SWIGTYPE_p_reply_info, 0);
|
||||
py_repinfo = SWIG_NewPointerObj((void*) repinfo, SWIGTYPE_p_comm_reply, 0);
|
||||
py_region = SWIG_NewPointerObj((void*) region, SWIGTYPE_p_regional, 0);
|
||||
result = PyObject_CallFunction(func, "OOOiOOO", py_qinfo, py_qstate,
|
||||
py_rep, rcode, py_edns, py_opt_list_out, py_region);
|
||||
py_args = Py_BuildValue("(OOOiOOO)", py_qinfo, py_qstate, py_rep,
|
||||
rcode, py_edns, py_opt_list_out, py_region);
|
||||
py_kwargs = Py_BuildValue("{s:O}", "repinfo", py_repinfo);
|
||||
result = PyObject_Call(func, py_args, py_kwargs);
|
||||
Py_XDECREF(py_edns);
|
||||
Py_XDECREF(py_qstate);
|
||||
Py_XDECREF(py_opt_list_out);
|
||||
Py_XDECREF(py_qinfo);
|
||||
Py_XDECREF(py_rep);
|
||||
Py_XDECREF(py_repinfo);
|
||||
Py_XDECREF(py_region);
|
||||
Py_XDECREF(py_args);
|
||||
Py_XDECREF(py_kwargs);
|
||||
if (result) {
|
||||
res = PyInt_AsLong(result);
|
||||
}
|
||||
@@ -1430,6 +1590,54 @@ int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
|
||||
return python_inplace_cb_register(inplace_cb_reply_servfail,
|
||||
py_cb, env, id);
|
||||
}
|
||||
|
||||
int python_inplace_cb_query_generic(
|
||||
struct query_info* qinfo, uint16_t flags, struct module_qstate* qstate,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, struct regional* region, int id,
|
||||
void* python_callback)
|
||||
{
|
||||
int res = 0;
|
||||
PyObject *func = python_callback;
|
||||
|
||||
PyGILState_STATE gstate = PyGILState_Ensure();
|
||||
|
||||
PyObject *py_qinfo = SWIG_NewPointerObj((void*) qinfo, SWIGTYPE_p_query_info, 0);
|
||||
PyObject *py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
|
||||
PyObject *py_addr = SWIG_NewPointerObj((void *) addr, SWIGTYPE_p_sockaddr_storage, 0);
|
||||
PyObject *py_zone = PyBytes_FromStringAndSize((const char *)zone, zonelen);
|
||||
PyObject *py_region = SWIG_NewPointerObj((void*) region, SWIGTYPE_p_regional, 0);
|
||||
|
||||
PyObject *py_args = Py_BuildValue("(OiOOOO)", py_qinfo, flags, py_qstate, py_addr, py_zone, py_region);
|
||||
PyObject *py_kwargs = Py_BuildValue("{}");
|
||||
PyObject *result = PyObject_Call(func, py_args, py_kwargs);
|
||||
if (result) {
|
||||
res = PyInt_AsLong(result);
|
||||
}
|
||||
|
||||
Py_XDECREF(py_qinfo);
|
||||
Py_XDECREF(py_qstate);
|
||||
Py_XDECREF(py_addr);
|
||||
Py_XDECREF(py_zone);
|
||||
Py_XDECREF(py_region);
|
||||
|
||||
Py_XDECREF(py_args);
|
||||
Py_XDECREF(py_kwargs);
|
||||
Py_XDECREF(result);
|
||||
|
||||
PyGILState_Release(gstate);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int register_inplace_cb_query(PyObject* py_cb,
|
||||
struct module_env* env, int id)
|
||||
{
|
||||
int ret = inplace_cb_register(python_inplace_cb_query_generic,
|
||||
inplace_cb_query, (void*) py_cb, env, id);
|
||||
if (ret) Py_INCREF(py_cb);
|
||||
return ret;
|
||||
}
|
||||
%}
|
||||
/* C declarations */
|
||||
int inplace_cb_register(void* cb, enum inplace_cb_list_type type, void* cbarg,
|
||||
@@ -1444,3 +1652,5 @@ static int register_inplace_cb_reply_local(PyObject* py_cb,
|
||||
struct module_env* env, int id);
|
||||
static int register_inplace_cb_reply_servfail(PyObject* py_cb,
|
||||
struct module_env* env, int id);
|
||||
static int register_inplace_cb_query(PyObject *py_cb,
|
||||
struct module_env* env, int id);
|
||||
|
||||
+150
-7
@@ -110,6 +110,136 @@ struct pythonmod_qstate {
|
||||
#include "pythonmod/interface.h"
|
||||
#endif
|
||||
|
||||
/** log python error */
|
||||
static void
|
||||
log_py_err(void)
|
||||
{
|
||||
char *result = NULL;
|
||||
const char* iomod = "cStringIO";
|
||||
PyObject *modStringIO = NULL;
|
||||
PyObject *modTB = NULL;
|
||||
PyObject *obFuncStringIO = NULL;
|
||||
PyObject *obStringIO = NULL;
|
||||
PyObject *obFuncTB = NULL;
|
||||
PyObject *argsTB = NULL;
|
||||
PyObject *obResult = NULL;
|
||||
PyObject *ascstr = NULL;
|
||||
PyObject *exc_typ, *exc_val, *exc_tb;
|
||||
|
||||
/* Fetch the error state now before we cruch it */
|
||||
/* exc val contains the error message
|
||||
* exc tb contains stack traceback and other info. */
|
||||
PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
|
||||
PyErr_NormalizeException(&exc_typ, &exc_val, &exc_tb);
|
||||
|
||||
/* Import the modules we need - cStringIO and traceback */
|
||||
modStringIO = PyImport_ImportModule("cStringIO");
|
||||
if (modStringIO==NULL) {
|
||||
/* python 1.4 and before */
|
||||
modStringIO = PyImport_ImportModule("StringIO");
|
||||
iomod = "StringIO";
|
||||
}
|
||||
if (modStringIO==NULL) {
|
||||
/* python 3 */
|
||||
modStringIO = PyImport_ImportModule("io");
|
||||
iomod = "io";
|
||||
}
|
||||
if (modStringIO==NULL) {
|
||||
log_err("pythonmod: cannot print exception, "
|
||||
"cannot ImportModule cStringIO or StringIO or io");
|
||||
goto cleanup;
|
||||
}
|
||||
modTB = PyImport_ImportModule("traceback");
|
||||
if (modTB==NULL) {
|
||||
log_err("pythonmod: cannot print exception, "
|
||||
"cannot ImportModule traceback");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Construct a cStringIO object */
|
||||
obFuncStringIO = PyObject_GetAttrString(modStringIO, "StringIO");
|
||||
if (obFuncStringIO==NULL) {
|
||||
log_err("pythonmod: cannot print exception, "
|
||||
"cannot GetAttrString %s.StringIO", iomod);
|
||||
goto cleanup;
|
||||
}
|
||||
obStringIO = PyObject_CallObject(obFuncStringIO, NULL);
|
||||
if (obStringIO==NULL) {
|
||||
log_err("pythonmod: cannot print exception, "
|
||||
"cannot call %s.StringIO()", iomod);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Get the traceback.print_exception function, and call it. */
|
||||
obFuncTB = PyObject_GetAttrString(modTB, "print_exception");
|
||||
if (obFuncTB==NULL) {
|
||||
log_err("pythonmod: cannot print exception, "
|
||||
"cannot GetAttrString traceback.print_exception");
|
||||
goto cleanup;
|
||||
}
|
||||
argsTB = Py_BuildValue("OOOOO", (exc_typ ? exc_typ : Py_None),
|
||||
(exc_val ? exc_val : Py_None), (exc_tb ? exc_tb : Py_None),
|
||||
Py_None, obStringIO);
|
||||
if (argsTB==NULL) {
|
||||
log_err("pythonmod: cannot print exception, "
|
||||
"cannot BuildValue for print_exception");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
obResult = PyObject_CallObject(obFuncTB, argsTB);
|
||||
if (obResult==NULL) {
|
||||
PyErr_Print();
|
||||
log_err("pythonmod: cannot print exception, "
|
||||
"call traceback.print_exception() failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Now call the getvalue() method in the StringIO instance */
|
||||
Py_DECREF(obFuncStringIO);
|
||||
obFuncStringIO = PyObject_GetAttrString(obStringIO, "getvalue");
|
||||
if (obFuncStringIO==NULL) {
|
||||
log_err("pythonmod: cannot print exception, "
|
||||
"cannot GetAttrString StringIO.getvalue");
|
||||
goto cleanup;
|
||||
}
|
||||
Py_DECREF(obResult);
|
||||
obResult = PyObject_CallObject(obFuncStringIO, NULL);
|
||||
if (obResult==NULL) {
|
||||
log_err("pythonmod: cannot print exception, "
|
||||
"call StringIO.getvalue() failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* And it should be a string all ready to go - duplicate it. */
|
||||
if (!PyString_Check(obResult) && !PyUnicode_Check(obResult)) {
|
||||
log_err("pythonmod: cannot print exception, "
|
||||
"StringIO.getvalue() result did not String_Check"
|
||||
" or Unicode_Check");
|
||||
goto cleanup;
|
||||
}
|
||||
if(PyString_Check(obResult)) {
|
||||
result = PyString_AsString(obResult);
|
||||
} else {
|
||||
ascstr = PyUnicode_AsASCIIString(obResult);
|
||||
result = PyBytes_AsString(ascstr);
|
||||
}
|
||||
log_err("pythonmod: python error: %s", result);
|
||||
|
||||
cleanup:
|
||||
Py_XDECREF(modStringIO);
|
||||
Py_XDECREF(modTB);
|
||||
Py_XDECREF(obFuncStringIO);
|
||||
Py_XDECREF(obStringIO);
|
||||
Py_XDECREF(obFuncTB);
|
||||
Py_XDECREF(argsTB);
|
||||
Py_XDECREF(obResult);
|
||||
Py_XDECREF(ascstr);
|
||||
|
||||
/* clear the exception, by not restoring it */
|
||||
/* Restore the exception state */
|
||||
/* PyErr_Restore(exc_typ, exc_val, exc_tb); */
|
||||
}
|
||||
|
||||
int pythonmod_init(struct module_env* env, int id)
|
||||
{
|
||||
/* Initialize module */
|
||||
@@ -193,13 +323,26 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
|
||||
/* TODO: deallocation of pe->... if an error occurs */
|
||||
|
||||
if (PyRun_SimpleFile(script_py, pe->fname) < 0)
|
||||
{
|
||||
if (PyRun_SimpleFile(script_py, pe->fname) < 0) {
|
||||
log_err("pythonmod: can't parse Python script %s", pe->fname);
|
||||
/* print the error to logs too, run it again */
|
||||
fseek(script_py, 0, SEEK_SET);
|
||||
/* we don't run the file, like this, because then side-effects
|
||||
* s = PyRun_File(script_py, pe->fname, Py_file_input,
|
||||
* PyModule_GetDict(PyImport_AddModule("__main__")), pe->dict);
|
||||
* could happen (again). Instead we parse the file again to get
|
||||
* the error string in the logs, for when the daemon has stderr
|
||||
* removed. SimpleFile run already printed to stderr, for then
|
||||
* this is called from unbound-checkconf or unbound -dd the user
|
||||
* has a nice formatted error.
|
||||
*/
|
||||
/* ignore the NULL return of _node, it is NULL due to the parse failure
|
||||
* that we are expecting */
|
||||
(void)PyParser_SimpleParseFile(script_py, pe->fname, Py_file_input);
|
||||
log_py_err();
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fclose(script_py);
|
||||
|
||||
if ((pe->func_init = PyDict_GetItemString(pe->dict, "init_standard")) == NULL)
|
||||
@@ -244,7 +387,7 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
log_err("pythonmod: Exception occurred in function init");
|
||||
PyErr_Print();
|
||||
log_py_err();
|
||||
Py_XDECREF(res);
|
||||
Py_XDECREF(py_init_arg);
|
||||
PyGILState_Release(gil);
|
||||
@@ -274,7 +417,7 @@ void pythonmod_deinit(struct module_env* env, int id)
|
||||
res = PyObject_CallFunction(pe->func_deinit, "i", id);
|
||||
if (PyErr_Occurred()) {
|
||||
log_err("pythonmod: Exception occurred in function deinit");
|
||||
PyErr_Print();
|
||||
log_py_err();
|
||||
}
|
||||
/* Free result if any */
|
||||
Py_XDECREF(res);
|
||||
@@ -312,7 +455,7 @@ void pythonmod_inform_super(struct module_qstate* qstate, int id, struct module_
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
log_err("pythonmod: Exception occurred in function inform_super");
|
||||
PyErr_Print();
|
||||
log_py_err();
|
||||
qstate->ext_state[id] = module_error;
|
||||
}
|
||||
else if ((res == NULL) || (!PyObject_IsTrue(res)))
|
||||
@@ -353,7 +496,7 @@ void pythonmod_operate(struct module_qstate* qstate, enum module_ev event,
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
log_err("pythonmod: Exception occurred in function operate, event: %s", strmodulevent(event));
|
||||
PyErr_Print();
|
||||
log_py_err();
|
||||
qstate->ext_state[id] = module_error;
|
||||
}
|
||||
else if ((res == NULL) || (!PyObject_IsTrue(res)))
|
||||
|
||||
+10
-1
@@ -72,5 +72,14 @@ size_t pythonmod_get_mem(struct module_env* env, int id);
|
||||
int python_inplace_cb_reply_generic(struct query_info* qinfo,
|
||||
struct module_qstate* qstate, struct reply_info* rep, int rcode,
|
||||
struct edns_data* edns, struct edns_option** opt_list_out,
|
||||
struct regional* region, int id, void* python_callback);
|
||||
struct comm_reply* repinfo, struct regional* region, int id,
|
||||
void* python_callback);
|
||||
|
||||
/** Declared here for fptr_wlist access. The definition is in interface.i. */
|
||||
int python_inplace_cb_query_generic(
|
||||
struct query_info* qinfo, uint16_t flags, struct module_qstate* qstate,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, struct regional* region, int id,
|
||||
void* python_callback);
|
||||
|
||||
#endif /* PYTHONMOD_H */
|
||||
|
||||
+4
-3
@@ -172,7 +172,7 @@ respip_action_cfg(struct respip_set* set, const char* ipstr,
|
||||
if(!(node=respip_find_or_create(set, ipstr, 1)))
|
||||
return 0;
|
||||
if(node->action != respip_none) {
|
||||
log_warn("duplicate response-ip action for '%s', overridden.",
|
||||
verbose(VERB_QUERY, "duplicate response-ip action for '%s', overridden.",
|
||||
ipstr);
|
||||
}
|
||||
if(strcmp(actnstr, "deny") == 0)
|
||||
@@ -611,8 +611,9 @@ make_new_reply_info(const struct reply_info* rep, struct regional* region,
|
||||
* EDNS0 OPT RR in the additional section appended on sending it out),
|
||||
* so the total number of RRsets is an_numrrsets. */
|
||||
new_rep = construct_reply_info_base(region, rep->flags,
|
||||
rep->qdcount, rep->ttl, rep->prefetch_ttl, an_numrrsets,
|
||||
0, 0, an_numrrsets, sec_status_insecure);
|
||||
rep->qdcount, rep->ttl, rep->prefetch_ttl,
|
||||
rep->serve_expired_ttl, an_numrrsets, 0, 0, an_numrrsets,
|
||||
sec_status_insecure);
|
||||
if(!new_rep)
|
||||
return NULL;
|
||||
if(!reply_info_alloc_rrset_keys(new_rep, NULL, region))
|
||||
|
||||
+152
-81
@@ -185,11 +185,13 @@ msg_ttl(struct dns_msg* msg)
|
||||
if(msg->rep->rrset_count == 1) {
|
||||
msg->rep->ttl = get_rrset_ttl(msg->rep->rrsets[0]);
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
|
||||
} else if(get_rrset_ttl(msg->rep->rrsets[msg->rep->rrset_count-1]) <
|
||||
msg->rep->ttl) {
|
||||
msg->rep->ttl = get_rrset_ttl(msg->rep->rrsets[
|
||||
msg->rep->rrset_count-1]);
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +218,7 @@ msg_add_rrset_an(struct auth_zone* z, struct regional* region,
|
||||
{
|
||||
log_assert(msg->rep->ns_numrrsets == 0);
|
||||
log_assert(msg->rep->ar_numrrsets == 0);
|
||||
if(!rrset)
|
||||
if(!rrset || !node)
|
||||
return 1;
|
||||
if(msg_rrset_duplicate(msg, node->name, node->namelen, rrset->type,
|
||||
z->dclass))
|
||||
@@ -240,7 +242,7 @@ msg_add_rrset_ns(struct auth_zone* z, struct regional* region,
|
||||
struct dns_msg* msg, struct auth_data* node, struct auth_rrset* rrset)
|
||||
{
|
||||
log_assert(msg->rep->ar_numrrsets == 0);
|
||||
if(!rrset)
|
||||
if(!rrset || !node)
|
||||
return 1;
|
||||
if(msg_rrset_duplicate(msg, node->name, node->namelen, rrset->type,
|
||||
z->dclass))
|
||||
@@ -263,7 +265,7 @@ static int
|
||||
msg_add_rrset_ar(struct auth_zone* z, struct regional* region,
|
||||
struct dns_msg* msg, struct auth_data* node, struct auth_rrset* rrset)
|
||||
{
|
||||
if(!rrset)
|
||||
if(!rrset || !node)
|
||||
return 1;
|
||||
if(msg_rrset_duplicate(msg, node->name, node->namelen, rrset->type,
|
||||
z->dclass))
|
||||
@@ -1014,7 +1016,8 @@ rrset_moveover_rrsigs(struct auth_data* node, uint16_t rr_type,
|
||||
}
|
||||
/* copy base values */
|
||||
memcpy(sigd, sigold, sizeof(struct packed_rrset_data));
|
||||
sigd->rrsig_count -= sigs;
|
||||
/* in sigd the RRSIGs are stored in the base of the RR, in count */
|
||||
sigd->count -= sigs;
|
||||
/* setup rr_len */
|
||||
sigd->rr_len = (size_t*)((uint8_t*)sigd +
|
||||
sizeof(struct packed_rrset_data));
|
||||
@@ -1447,11 +1450,13 @@ az_remove_rr_decompress(struct auth_zone* z, uint8_t* pkt, size_t pktlen,
|
||||
* The lineno is set at 1 and then increased by the function.
|
||||
* @param fname: file name.
|
||||
* @param depth: recursion depth for includes
|
||||
* @param cfg: config for chroot.
|
||||
* returns false on failure, has printed an error message
|
||||
*/
|
||||
static int
|
||||
az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
|
||||
struct sldns_file_parse_state* state, char* fname, int depth)
|
||||
struct sldns_file_parse_state* state, char* fname, int depth,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
size_t rr_len, dname_len;
|
||||
int status;
|
||||
@@ -1477,6 +1482,11 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
|
||||
/* skip spaces */
|
||||
while(*incfile == ' ' || *incfile == '\t')
|
||||
incfile++;
|
||||
/* adjust for chroot on include file */
|
||||
if(cfg->chrootdir && cfg->chrootdir[0] &&
|
||||
strncmp(incfile, cfg->chrootdir,
|
||||
strlen(cfg->chrootdir)) == 0)
|
||||
incfile += strlen(cfg->chrootdir);
|
||||
incfile = strdup(incfile);
|
||||
if(!incfile) {
|
||||
log_err("malloc failure");
|
||||
@@ -1487,7 +1497,7 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
|
||||
inc = fopen(incfile, "r");
|
||||
if(!inc) {
|
||||
log_err("%s:%d cannot open include "
|
||||
"file %s: %s", z->zonefile,
|
||||
"file %s: %s", fname,
|
||||
lineno_orig, incfile,
|
||||
strerror(errno));
|
||||
free(incfile);
|
||||
@@ -1495,7 +1505,7 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
|
||||
}
|
||||
/* recurse read that file now */
|
||||
if(!az_parse_file(z, inc, rr, rrbuflen,
|
||||
state, incfile, depth+1)) {
|
||||
state, incfile, depth+1, cfg)) {
|
||||
log_err("%s:%d cannot parse include "
|
||||
"file %s", fname,
|
||||
lineno_orig, incfile);
|
||||
@@ -1535,30 +1545,36 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
|
||||
}
|
||||
|
||||
int
|
||||
auth_zone_read_zonefile(struct auth_zone* z)
|
||||
auth_zone_read_zonefile(struct auth_zone* z, struct config_file* cfg)
|
||||
{
|
||||
uint8_t rr[LDNS_RR_BUF_SIZE];
|
||||
struct sldns_file_parse_state state;
|
||||
char* zfilename;
|
||||
FILE* in;
|
||||
if(!z || !z->zonefile || z->zonefile[0]==0)
|
||||
return 1; /* no file, or "", nothing to read */
|
||||
|
||||
zfilename = z->zonefile;
|
||||
if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(zfilename,
|
||||
cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
|
||||
zfilename += strlen(cfg->chrootdir);
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char nm[255+1];
|
||||
dname_str(z->name, nm);
|
||||
verbose(VERB_ALGO, "read zonefile %s for %s", z->zonefile, nm);
|
||||
verbose(VERB_ALGO, "read zonefile %s for %s", zfilename, nm);
|
||||
}
|
||||
in = fopen(z->zonefile, "r");
|
||||
in = fopen(zfilename, "r");
|
||||
if(!in) {
|
||||
char* n = sldns_wire2str_dname(z->name, z->namelen);
|
||||
if(z->zone_is_slave && errno == ENOENT) {
|
||||
/* we fetch the zone contents later, no file yet */
|
||||
verbose(VERB_ALGO, "no zonefile %s for %s",
|
||||
z->zonefile, n?n:"error");
|
||||
zfilename, n?n:"error");
|
||||
free(n);
|
||||
return 1;
|
||||
}
|
||||
log_err("cannot open zonefile %s for %s: %s",
|
||||
z->zonefile, n?n:"error", strerror(errno));
|
||||
zfilename, n?n:"error", strerror(errno));
|
||||
free(n);
|
||||
return 0;
|
||||
}
|
||||
@@ -1576,10 +1592,10 @@ auth_zone_read_zonefile(struct auth_zone* z)
|
||||
state.origin_len = z->namelen;
|
||||
}
|
||||
/* parse the (toplevel) file */
|
||||
if(!az_parse_file(z, in, rr, sizeof(rr), &state, z->zonefile, 0)) {
|
||||
if(!az_parse_file(z, in, rr, sizeof(rr), &state, zfilename, 0, cfg)) {
|
||||
char* n = sldns_wire2str_dname(z->name, z->namelen);
|
||||
log_err("error parsing zonefile %s for %s",
|
||||
z->zonefile, n?n:"error");
|
||||
zfilename, n?n:"error");
|
||||
free(n);
|
||||
fclose(in);
|
||||
return 0;
|
||||
@@ -1707,13 +1723,13 @@ int auth_zone_write_file(struct auth_zone* z, const char* fname)
|
||||
|
||||
/** read all auth zones from file (if they have) */
|
||||
static int
|
||||
auth_zones_read_zones(struct auth_zones* az)
|
||||
auth_zones_read_zones(struct auth_zones* az, struct config_file* cfg)
|
||||
{
|
||||
struct auth_zone* z;
|
||||
lock_rw_wrlock(&az->lock);
|
||||
RBTREE_FOR(z, struct auth_zone*, &az->ztree) {
|
||||
lock_rw_wrlock(&z->lock);
|
||||
if(!auth_zone_read_zonefile(z)) {
|
||||
if(!auth_zone_read_zonefile(z, cfg)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
lock_rw_unlock(&az->lock);
|
||||
return 0;
|
||||
@@ -1950,7 +1966,7 @@ int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
|
||||
}
|
||||
}
|
||||
az_delete_deleted_zones(az);
|
||||
if(!auth_zones_read_zones(az))
|
||||
if(!auth_zones_read_zones(az, cfg))
|
||||
return 0;
|
||||
if(setup) {
|
||||
if(!auth_zones_setup_zones(az))
|
||||
@@ -2284,6 +2300,7 @@ az_add_negative_soa(struct auth_zone* z, struct regional* region,
|
||||
d->rr_ttl[0] = (time_t)minimum;
|
||||
msg->rep->ttl = get_rrset_ttl(msg->rep->rrsets[0]);
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2824,7 +2841,7 @@ az_generate_any_answer(struct auth_zone* z, struct regional* region,
|
||||
if(!msg_add_rrset_an(z, region, msg, node, rrset)) return 0;
|
||||
added++;
|
||||
}
|
||||
if(added == 0 && node->rrsets) {
|
||||
if(added == 0 && node && node->rrsets) {
|
||||
if(!msg_add_rrset_an(z, region, msg, node,
|
||||
node->rrsets)) return 0;
|
||||
}
|
||||
@@ -3159,6 +3176,11 @@ int auth_zones_lookup(struct auth_zones* az, struct query_info* qinfo,
|
||||
*fallback = 1;
|
||||
return 0;
|
||||
}
|
||||
if(z->zone_expired) {
|
||||
*fallback = z->fallback_enabled;
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 0;
|
||||
}
|
||||
/* see what answer that zone would generate */
|
||||
r = auth_zone_generate_answer(z, qinfo, region, msg, fallback);
|
||||
lock_rw_unlock(&z->lock);
|
||||
@@ -3168,8 +3190,8 @@ int auth_zones_lookup(struct auth_zones* az, struct query_info* qinfo,
|
||||
/** encode auth answer */
|
||||
static void
|
||||
auth_answer_encode(struct query_info* qinfo, struct module_env* env,
|
||||
struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
|
||||
struct dns_msg* msg)
|
||||
struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
|
||||
struct regional* temp, struct dns_msg* msg)
|
||||
{
|
||||
uint16_t udpsize;
|
||||
udpsize = edns->udp_size;
|
||||
@@ -3179,7 +3201,7 @@ auth_answer_encode(struct query_info* qinfo, struct module_env* env,
|
||||
edns->bits &= EDNS_DO;
|
||||
|
||||
if(!inplace_cb_reply_local_call(env, qinfo, NULL, msg->rep,
|
||||
(int)FLAGS_GET_RCODE(msg->rep->flags), edns, temp)
|
||||
(int)FLAGS_GET_RCODE(msg->rep->flags), edns, repinfo, temp)
|
||||
|| !reply_info_answer_encode(qinfo, msg->rep,
|
||||
*(uint16_t*)sldns_buffer_begin(buf),
|
||||
sldns_buffer_read_u16_at(buf, 2),
|
||||
@@ -3194,8 +3216,8 @@ auth_answer_encode(struct query_info* qinfo, struct module_env* env,
|
||||
/** encode auth error answer */
|
||||
static void
|
||||
auth_error_encode(struct query_info* qinfo, struct module_env* env,
|
||||
struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
|
||||
int rcode)
|
||||
struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
|
||||
struct regional* temp, int rcode)
|
||||
{
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
@@ -3203,7 +3225,7 @@ auth_error_encode(struct query_info* qinfo, struct module_env* env,
|
||||
edns->bits &= EDNS_DO;
|
||||
|
||||
if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL,
|
||||
rcode, edns, temp))
|
||||
rcode, edns, repinfo, temp))
|
||||
edns->opt_list = NULL;
|
||||
error_encode(buf, rcode|BIT_AA, qinfo,
|
||||
*(uint16_t*)sldns_buffer_begin(buf),
|
||||
@@ -3211,8 +3233,8 @@ auth_error_encode(struct query_info* qinfo, struct module_env* env,
|
||||
}
|
||||
|
||||
int auth_zones_answer(struct auth_zones* az, struct module_env* env,
|
||||
struct query_info* qinfo, struct edns_data* edns, struct sldns_buffer* buf,
|
||||
struct regional* temp)
|
||||
struct query_info* qinfo, struct edns_data* edns,
|
||||
struct comm_reply* repinfo, struct sldns_buffer* buf, struct regional* temp)
|
||||
{
|
||||
struct dns_msg* msg = NULL;
|
||||
struct auth_zone* z;
|
||||
@@ -3246,6 +3268,19 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env,
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 0;
|
||||
}
|
||||
if(z->zone_expired) {
|
||||
if(z->fallback_enabled) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
lock_rw_wrlock(&az->lock);
|
||||
az->num_query_down++;
|
||||
lock_rw_unlock(&az->lock);
|
||||
auth_error_encode(qinfo, env, edns, repinfo, buf, temp,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* answer it from zone z */
|
||||
r = auth_zone_generate_answer(z, qinfo, temp, &msg, &fallback);
|
||||
@@ -3260,9 +3295,9 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env,
|
||||
|
||||
/* encode answer */
|
||||
if(!r)
|
||||
auth_error_encode(qinfo, env, edns, buf, temp,
|
||||
auth_error_encode(qinfo, env, edns, repinfo, buf, temp,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
else auth_answer_encode(qinfo, env, edns, buf, temp, msg);
|
||||
else auth_answer_encode(qinfo, env, edns, repinfo, buf, temp, msg);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -3425,14 +3460,17 @@ xfr_process_notify(struct auth_xfer* xfr, struct module_env* env,
|
||||
{
|
||||
/* if the serial of notify is older than we have, don't fetch
|
||||
* a zone, we already have it */
|
||||
if(has_serial && !xfr_serial_means_update(xfr, serial))
|
||||
if(has_serial && !xfr_serial_means_update(xfr, serial)) {
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
return;
|
||||
}
|
||||
/* start new probe with this addr src, or note serial */
|
||||
if(!xfr_start_probe(xfr, env, fromhost)) {
|
||||
/* not started because already in progress, note the serial */
|
||||
xfr_note_notify_serial(xfr, has_serial, serial);
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
}
|
||||
/* successful end of start_probe unlocked xfr->lock */
|
||||
}
|
||||
|
||||
int auth_zones_notify(struct auth_zones* az, struct module_env* env,
|
||||
@@ -3467,6 +3505,23 @@ int auth_zones_notify(struct auth_zones* az, struct module_env* env,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int auth_zones_startprobesequence(struct auth_zones* az,
|
||||
struct module_env* env, uint8_t* nm, size_t nmlen, uint16_t dclass)
|
||||
{
|
||||
struct auth_xfer* xfr;
|
||||
lock_rw_rdlock(&az->lock);
|
||||
xfr = auth_xfer_find(az, nm, nmlen, dclass);
|
||||
if(!xfr) {
|
||||
lock_rw_unlock(&az->lock);
|
||||
return 0;
|
||||
}
|
||||
lock_basic_lock(&xfr->lock);
|
||||
lock_rw_unlock(&az->lock);
|
||||
|
||||
xfr_process_notify(xfr, env, 0, 0, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** set a zone expired */
|
||||
static void
|
||||
auth_xfer_set_expired(struct auth_xfer* xfr, struct module_env* env,
|
||||
@@ -4161,8 +4216,8 @@ chunkline_non_comment_RR(struct auth_chunk** chunk, size_t* chunk_pos,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** check syntax of chunklist zonefile, parse SOA RR, return false on
|
||||
* failure and return a string in the scratch buffer (SOA RR string)
|
||||
/** check syntax of chunklist zonefile, parse first RR, return false on
|
||||
* failure and return a string in the scratch buffer (first RR string)
|
||||
* on failure. */
|
||||
static int
|
||||
http_zonefile_syntax_check(struct auth_xfer* xfr, sldns_buffer* buf)
|
||||
@@ -4190,26 +4245,11 @@ http_zonefile_syntax_check(struct auth_xfer* xfr, sldns_buffer* buf)
|
||||
pstate.origin_len?pstate.origin:NULL, pstate.origin_len,
|
||||
pstate.prev_rr_len?pstate.prev_rr:NULL, pstate.prev_rr_len);
|
||||
if(e != 0) {
|
||||
log_err("parse failure on SOA RR[%d]: %s",
|
||||
log_err("parse failure on first RR[%d]: %s",
|
||||
LDNS_WIREPARSE_OFFSET(e),
|
||||
sldns_get_errorstr_parse(LDNS_WIREPARSE_ERROR(e)));
|
||||
return 0;
|
||||
}
|
||||
/* check that name is correct */
|
||||
if(query_dname_compare(rr, xfr->name) != 0) {
|
||||
char nm[255+1], zname[255+1];
|
||||
dname_str(rr, nm);
|
||||
dname_str(xfr->name, zname);
|
||||
log_err("parse failure for %s, SOA RR for %s found instead",
|
||||
zname, nm);
|
||||
return 0;
|
||||
}
|
||||
/* check that type is SOA */
|
||||
if(sldns_wirerr_get_type(rr, rr_len, dname_len) != LDNS_RR_TYPE_SOA) {
|
||||
log_err("parse failure: first record in downloaded zonefile "
|
||||
"not of type SOA");
|
||||
return 0;
|
||||
}
|
||||
/* check that class is correct */
|
||||
if(sldns_wirerr_get_class(rr, rr_len, dname_len) != xfr->dclass) {
|
||||
log_err("parse failure: first record in downloaded zonefile "
|
||||
@@ -4764,8 +4804,10 @@ auth_zone_write_chunks(struct auth_xfer* xfr, const char* fname)
|
||||
static void
|
||||
xfr_write_after_update(struct auth_xfer* xfr, struct module_env* env)
|
||||
{
|
||||
struct config_file* cfg = env->cfg;
|
||||
struct auth_zone* z;
|
||||
char tmpfile[1024];
|
||||
char* zfilename;
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
|
||||
/* get lock again, so it is a readlock and concurrently queries
|
||||
@@ -4783,20 +4825,24 @@ xfr_write_after_update(struct auth_xfer* xfr, struct module_env* env)
|
||||
lock_basic_lock(&xfr->lock);
|
||||
lock_rw_unlock(&env->auth_zones->lock);
|
||||
|
||||
if(z->zonefile == NULL) {
|
||||
if(z->zonefile == NULL || z->zonefile[0] == 0) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
/* no write needed, no zonefile set */
|
||||
return;
|
||||
}
|
||||
zfilename = z->zonefile;
|
||||
if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(zfilename,
|
||||
cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
|
||||
zfilename += strlen(cfg->chrootdir);
|
||||
|
||||
/* write to tempfile first */
|
||||
if((size_t)strlen(z->zonefile) + 16 > sizeof(tmpfile)) {
|
||||
if((size_t)strlen(zfilename) + 16 > sizeof(tmpfile)) {
|
||||
verbose(VERB_ALGO, "tmpfilename too long, cannot update "
|
||||
" zonefile %s", z->zonefile);
|
||||
" zonefile %s", zfilename);
|
||||
lock_rw_unlock(&z->lock);
|
||||
return;
|
||||
}
|
||||
snprintf(tmpfile, sizeof(tmpfile), "%s.tmp%u", z->zonefile,
|
||||
snprintf(tmpfile, sizeof(tmpfile), "%s.tmp%u", zfilename,
|
||||
(unsigned)getpid());
|
||||
if(xfr->task_transfer->master->http) {
|
||||
/* use the stored chunk list to write them */
|
||||
@@ -4809,8 +4855,8 @@ xfr_write_after_update(struct auth_xfer* xfr, struct module_env* env)
|
||||
lock_rw_unlock(&z->lock);
|
||||
return;
|
||||
}
|
||||
if(rename(tmpfile, z->zonefile) < 0) {
|
||||
log_err("could not rename(%s, %s): %s", tmpfile, z->zonefile,
|
||||
if(rename(tmpfile, zfilename) < 0) {
|
||||
log_err("could not rename(%s, %s): %s", tmpfile, zfilename,
|
||||
strerror(errno));
|
||||
unlink(tmpfile);
|
||||
lock_rw_unlock(&z->lock);
|
||||
@@ -5085,7 +5131,8 @@ xfr_transfer_nexttarget_or_end(struct auth_xfer* xfr, struct module_env* env)
|
||||
xfr_transfer_disown(xfr);
|
||||
|
||||
/* pick up the nextprobe task and wait */
|
||||
xfr_set_timeout(xfr, env, 1, 0);
|
||||
if(xfr->task_nextprobe->worker == NULL)
|
||||
xfr_set_timeout(xfr, env, 1, 0);
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
}
|
||||
|
||||
@@ -5144,7 +5191,8 @@ xfr_master_add_addrs(struct auth_master* m, struct ub_packed_rrset_key* rrset,
|
||||
|
||||
/** callback for task_transfer lookup of host name, of A or AAAA */
|
||||
void auth_xfer_transfer_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
|
||||
enum sec_status ATTR_UNUSED(sec), char* ATTR_UNUSED(why_bogus))
|
||||
enum sec_status ATTR_UNUSED(sec), char* ATTR_UNUSED(why_bogus),
|
||||
int ATTR_UNUSED(was_ratelimited))
|
||||
{
|
||||
struct auth_xfer* xfr = (struct auth_xfer*)arg;
|
||||
struct module_env* env;
|
||||
@@ -5542,7 +5590,8 @@ process_list_end_transfer(struct auth_xfer* xfr, struct module_env* env)
|
||||
return;
|
||||
} else {
|
||||
/* pick up the nextprobe task and wait (normail wait time) */
|
||||
xfr_set_timeout(xfr, env, 0, 0);
|
||||
if(xfr->task_nextprobe->worker == NULL)
|
||||
xfr_set_timeout(xfr, env, 0, 0);
|
||||
}
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
return;
|
||||
@@ -5883,29 +5932,35 @@ auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err,
|
||||
return 0;
|
||||
|
||||
}
|
||||
/* other tasks are running, we don't do this anymore */
|
||||
xfr_probe_disown(xfr);
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
/* return, we don't sent a reply to this udp packet,
|
||||
* and we setup the tasks to do next */
|
||||
return 0;
|
||||
} else {
|
||||
/* if zone not updated, start the wait timer again */
|
||||
verbose(VERB_ALGO, "auth_zone unchanged, new lease, wait");
|
||||
if(xfr->have_zone)
|
||||
xfr->lease_time = *env->now;
|
||||
if(xfr->task_nextprobe->worker == NULL)
|
||||
xfr_set_timeout(xfr, env, 0, 0);
|
||||
verbose(VERB_ALGO, "auth_zone master reports unchanged soa serial");
|
||||
/* we if cannot find updates amongst the
|
||||
* masters, this means we then have a new lease
|
||||
* on the zone */
|
||||
xfr->task_probe->have_new_lease = 1;
|
||||
}
|
||||
/* other tasks are running, we don't do this anymore */
|
||||
xfr_probe_disown(xfr);
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
/* return, we don't sent a reply to this udp packet,
|
||||
* and we setup the tasks to do next */
|
||||
return 0;
|
||||
} else {
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char buf[256];
|
||||
dname_str(xfr->name, buf);
|
||||
verbose(VERB_ALGO, "auth zone %s: bad reply to soa probe", buf);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char buf[256];
|
||||
dname_str(xfr->name, buf);
|
||||
verbose(VERB_ALGO, "auth zone %s: soa probe failed", buf);
|
||||
}
|
||||
}
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char buf[256];
|
||||
dname_str(xfr->name, buf);
|
||||
verbose(VERB_ALGO, "auth zone %s: soa probe failed", buf);
|
||||
}
|
||||
|
||||
/* failed lookup */
|
||||
/* failed lookup or not an update */
|
||||
/* delete commpoint so a new one is created, with a fresh port nr */
|
||||
comm_point_delete(xfr->task_probe->cp);
|
||||
xfr->task_probe->cp = NULL;
|
||||
@@ -6008,7 +6063,8 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
|
||||
/* only wanted lookups for copy, stop probe and start wait */
|
||||
xfr->task_probe->only_lookup = 0;
|
||||
xfr_probe_disown(xfr);
|
||||
xfr_set_timeout(xfr, env, 0, 0);
|
||||
if(xfr->task_nextprobe->worker == NULL)
|
||||
xfr_set_timeout(xfr, env, 0, 0);
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
return;
|
||||
}
|
||||
@@ -6024,18 +6080,31 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
|
||||
xfr_probe_nextmaster(xfr);
|
||||
}
|
||||
|
||||
/* we failed to send this as well, move to the wait task,
|
||||
* use the shorter retry timeout */
|
||||
xfr_probe_disown(xfr);
|
||||
/* done with probe sequence, wait */
|
||||
if(xfr->task_probe->have_new_lease) {
|
||||
/* if zone not updated, start the wait timer again */
|
||||
verbose(VERB_ALGO, "auth_zone unchanged, new lease, wait");
|
||||
xfr_probe_disown(xfr);
|
||||
if(xfr->have_zone)
|
||||
xfr->lease_time = *env->now;
|
||||
if(xfr->task_nextprobe->worker == NULL)
|
||||
xfr_set_timeout(xfr, env, 0, 0);
|
||||
} else {
|
||||
/* we failed to send this as well, move to the wait task,
|
||||
* use the shorter retry timeout */
|
||||
xfr_probe_disown(xfr);
|
||||
/* pick up the nextprobe task and wait */
|
||||
if(xfr->task_nextprobe->worker == NULL)
|
||||
xfr_set_timeout(xfr, env, 1, 0);
|
||||
}
|
||||
|
||||
/* pick up the nextprobe task and wait */
|
||||
xfr_set_timeout(xfr, env, 1, 0);
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
}
|
||||
|
||||
/** callback for task_probe lookup of host name, of A or AAAA */
|
||||
void auth_xfer_probe_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
|
||||
enum sec_status ATTR_UNUSED(sec), char* ATTR_UNUSED(why_bogus))
|
||||
enum sec_status ATTR_UNUSED(sec), char* ATTR_UNUSED(why_bogus),
|
||||
int ATTR_UNUSED(was_ratelimited))
|
||||
{
|
||||
struct auth_xfer* xfr = (struct auth_xfer*)arg;
|
||||
struct module_env* env;
|
||||
@@ -6163,6 +6232,8 @@ xfr_start_probe(struct auth_xfer* xfr, struct module_env* env,
|
||||
xfr->task_probe->cp = NULL;
|
||||
|
||||
/* start the task */
|
||||
/* have not seen a new lease yet, this scan */
|
||||
xfr->task_probe->have_new_lease = 0;
|
||||
/* if this was a timeout, no specific first master to scan */
|
||||
/* otherwise, spec is nonNULL the notified master, scan
|
||||
* first and also transfer first from it */
|
||||
|
||||
+17
-5
@@ -309,6 +309,9 @@ struct auth_probe {
|
||||
/** we only want to do lookups for making config work (for notify),
|
||||
* don't proceed with UDP SOA probe queries */
|
||||
int only_lookup;
|
||||
/** we have seen a new lease this scan, because one of the masters
|
||||
* replied with the current SOA serial version */
|
||||
int have_new_lease;
|
||||
|
||||
/** once notified, or the timeout has been reached. a scan starts. */
|
||||
/** the scan specific target (notify source), or NULL if none */
|
||||
@@ -509,12 +512,13 @@ int auth_zones_lookup(struct auth_zones* az, struct query_info* qinfo,
|
||||
* @param qinfo: query info (parsed).
|
||||
* @param edns: edns info (parsed).
|
||||
* @param buf: buffer with query ID and flags, also for reply.
|
||||
* @param repinfo: reply information for a communication point.
|
||||
* @param temp: temporary storage region.
|
||||
* @return false if not answered
|
||||
*/
|
||||
int auth_zones_answer(struct auth_zones* az, struct module_env* env,
|
||||
struct query_info* qinfo, struct edns_data* edns, struct sldns_buffer* buf,
|
||||
struct regional* temp);
|
||||
struct query_info* qinfo, struct edns_data* edns,
|
||||
struct comm_reply* repinfo, struct sldns_buffer* buf, struct regional* temp);
|
||||
|
||||
/**
|
||||
* Find the auth zone that is above the given qname.
|
||||
@@ -588,8 +592,14 @@ int auth_zones_notify(struct auth_zones* az, struct module_env* env,
|
||||
* returns 0 if no soa record in the notify */
|
||||
int auth_zone_parse_notify_serial(struct sldns_buffer* pkt, uint32_t *serial);
|
||||
|
||||
/** for the zone and if not already going, starts the probe sequence.
|
||||
* false if zone cannot be found. This is like a notify arrived and was
|
||||
* accepted for that zone. */
|
||||
int auth_zones_startprobesequence(struct auth_zones* az,
|
||||
struct module_env* env, uint8_t* nm, size_t nmlen, uint16_t dclass);
|
||||
|
||||
/** read auth zone from zonefile. caller must lock zone. false on failure */
|
||||
int auth_zone_read_zonefile(struct auth_zone* z);
|
||||
int auth_zone_read_zonefile(struct auth_zone* z, struct config_file* cfg);
|
||||
|
||||
/** find serial number of zone or false if none (no SOA record) */
|
||||
int auth_zone_get_serial(struct auth_zone* z, uint32_t* serial);
|
||||
@@ -637,10 +647,12 @@ int auth_xfer_transfer_http_callback(struct comm_point* c, void* arg, int err,
|
||||
void auth_xfer_probe_timer_callback(void* arg);
|
||||
/** mesh callback for task_probe on lookup of host names */
|
||||
void auth_xfer_probe_lookup_callback(void* arg, int rcode,
|
||||
struct sldns_buffer* buf, enum sec_status sec, char* why_bogus);
|
||||
struct sldns_buffer* buf, enum sec_status sec, char* why_bogus,
|
||||
int was_ratelimited);
|
||||
/** mesh callback for task_transfer on lookup of host names */
|
||||
void auth_xfer_transfer_lookup_callback(void* arg, int rcode,
|
||||
struct sldns_buffer* buf, enum sec_status sec, char* why_bogus);
|
||||
struct sldns_buffer* buf, enum sec_status sec, char* why_bogus,
|
||||
int was_ratelimited);
|
||||
|
||||
/*
|
||||
* Compares two 32-bit serial numbers as defined in RFC1982. Returns
|
||||
|
||||
Vendored
+16
-1
@@ -109,7 +109,7 @@ store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
|
||||
}
|
||||
|
||||
/** delete message from message cache */
|
||||
static void
|
||||
void
|
||||
msg_cache_remove(struct module_env* env, uint8_t* qname, size_t qnamelen,
|
||||
uint16_t qtype, uint16_t qclass, uint16_t flags)
|
||||
{
|
||||
@@ -547,6 +547,7 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
|
||||
if(r->prefetch_ttl > now)
|
||||
msg->rep->prefetch_ttl = r->prefetch_ttl - now;
|
||||
else msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
|
||||
msg->rep->security = r->security;
|
||||
msg->rep->an_numrrsets = r->an_numrrsets;
|
||||
msg->rep->ns_numrrsets = r->ns_numrrsets;
|
||||
@@ -601,6 +602,7 @@ rrset_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
msg->rep->qdcount = 1;
|
||||
msg->rep->ttl = d->ttl - now;
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
|
||||
msg->rep->security = sec_status_unchecked;
|
||||
msg->rep->an_numrrsets = 1;
|
||||
msg->rep->ns_numrrsets = 0;
|
||||
@@ -638,6 +640,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
msg->rep->qdcount = 1;
|
||||
msg->rep->ttl = d->ttl - now;
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
|
||||
msg->rep->security = sec_status_unchecked;
|
||||
msg->rep->an_numrrsets = 1;
|
||||
msg->rep->ns_numrrsets = 0;
|
||||
@@ -696,6 +699,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
newd->rr_ttl[0] = newd->ttl;
|
||||
msg->rep->ttl = newd->ttl;
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(newd->ttl);
|
||||
msg->rep->serve_expired_ttl = newd->ttl + SERVE_EXPIRED_TTL;
|
||||
sldns_write_uint16(newd->rr_data[0], newlen);
|
||||
memmove(newd->rr_data[0] + sizeof(uint16_t), newname, newlen);
|
||||
msg->rep->an_numrrsets ++;
|
||||
@@ -717,6 +721,17 @@ fill_any(struct module_env* env,
|
||||
int i, num=6; /* number of RR types to look up */
|
||||
log_assert(lookup[num] == 0);
|
||||
|
||||
if(env->cfg->deny_any) {
|
||||
/* return empty message */
|
||||
msg = dns_msg_create(qname, qnamelen, qtype, qclass,
|
||||
region, 0);
|
||||
if(!msg) {
|
||||
return NULL;
|
||||
}
|
||||
msg->rep->security = sec_status_indeterminate;
|
||||
return msg;
|
||||
}
|
||||
|
||||
for(i=0; i<num; i++) {
|
||||
/* look up this RR for inclusion in type ANY response */
|
||||
struct ub_packed_rrset_key* rrset = rrset_cache_lookup(
|
||||
|
||||
Vendored
+12
@@ -238,4 +238,16 @@ struct msgreply_entry* msg_cache_lookup(struct module_env* env,
|
||||
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
|
||||
uint16_t flags, time_t now, int wr);
|
||||
|
||||
/**
|
||||
* Remove entry from the message cache. For unwanted entries.
|
||||
* @param env: with message cache.
|
||||
* @param qname: query name, in wireformat
|
||||
* @param qnamelen: length of qname, including terminating 0.
|
||||
* @param qtype: query type, host order.
|
||||
* @param qclass: query class, host order.
|
||||
* @param flags: flags
|
||||
*/
|
||||
void msg_cache_remove(struct module_env* env, uint8_t* qname, size_t qnamelen,
|
||||
uint16_t qtype, uint16_t qclass, uint16_t flags);
|
||||
|
||||
#endif /* SERVICES_CACHE_DNS_H */
|
||||
|
||||
Vendored
+44
-20
@@ -215,6 +215,18 @@ static int infra_ratelimit_cfg_insert(struct infra_cache* infra,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** setup domain limits tree (0 on failure) */
|
||||
static int
|
||||
setup_domain_limits(struct infra_cache* infra, struct config_file* cfg)
|
||||
{
|
||||
name_tree_init(&infra->domain_limits);
|
||||
if(!infra_ratelimit_cfg_insert(infra, cfg)) {
|
||||
return 0;
|
||||
}
|
||||
name_tree_init_parents(&infra->domain_limits);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct infra_cache*
|
||||
infra_create(struct config_file* cfg)
|
||||
{
|
||||
@@ -230,23 +242,19 @@ infra_create(struct config_file* cfg)
|
||||
return NULL;
|
||||
}
|
||||
infra->host_ttl = cfg->host_ttl;
|
||||
name_tree_init(&infra->domain_limits);
|
||||
infra_dp_ratelimit = cfg->ratelimit;
|
||||
if(cfg->ratelimit != 0) {
|
||||
infra->domain_rates = slabhash_create(cfg->ratelimit_slabs,
|
||||
INFRA_HOST_STARTSIZE, cfg->ratelimit_size,
|
||||
&rate_sizefunc, &rate_compfunc, &rate_delkeyfunc,
|
||||
&rate_deldatafunc, NULL);
|
||||
if(!infra->domain_rates) {
|
||||
infra_delete(infra);
|
||||
return NULL;
|
||||
}
|
||||
/* insert config data into ratelimits */
|
||||
if(!infra_ratelimit_cfg_insert(infra, cfg)) {
|
||||
infra_delete(infra);
|
||||
return NULL;
|
||||
}
|
||||
name_tree_init_parents(&infra->domain_limits);
|
||||
infra->domain_rates = slabhash_create(cfg->ratelimit_slabs,
|
||||
INFRA_HOST_STARTSIZE, cfg->ratelimit_size,
|
||||
&rate_sizefunc, &rate_compfunc, &rate_delkeyfunc,
|
||||
&rate_deldatafunc, NULL);
|
||||
if(!infra->domain_rates) {
|
||||
infra_delete(infra);
|
||||
return NULL;
|
||||
}
|
||||
/* insert config data into ratelimits */
|
||||
if(!setup_domain_limits(infra, cfg)) {
|
||||
infra_delete(infra);
|
||||
return NULL;
|
||||
}
|
||||
infra_ip_ratelimit = cfg->ip_ratelimit;
|
||||
infra->client_ip_rates = slabhash_create(cfg->ip_ratelimit_slabs,
|
||||
@@ -287,12 +295,28 @@ infra_adjust(struct infra_cache* infra, struct config_file* cfg)
|
||||
if(!infra)
|
||||
return infra_create(cfg);
|
||||
infra->host_ttl = cfg->host_ttl;
|
||||
infra_dp_ratelimit = cfg->ratelimit;
|
||||
infra_ip_ratelimit = cfg->ip_ratelimit;
|
||||
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) {
|
||||
/* divide cachesize by slabs and multiply by slabs, because if the
|
||||
* cachesize is not an even multiple of slabs, that is the resulting
|
||||
* size of the slabhash */
|
||||
if(!slabhash_is_size(infra->hosts, maxmem, cfg->infra_cache_slabs) ||
|
||||
!slabhash_is_size(infra->domain_rates, cfg->ratelimit_size,
|
||||
cfg->ratelimit_slabs) ||
|
||||
!slabhash_is_size(infra->client_ip_rates, cfg->ip_ratelimit_size,
|
||||
cfg->ip_ratelimit_slabs)) {
|
||||
infra_delete(infra);
|
||||
infra = infra_create(cfg);
|
||||
} else {
|
||||
/* reapply domain limits */
|
||||
traverse_postorder(&infra->domain_limits, domain_limit_free,
|
||||
NULL);
|
||||
if(!setup_domain_limits(infra, cfg)) {
|
||||
infra_delete(infra);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return infra;
|
||||
}
|
||||
@@ -989,8 +1013,8 @@ int infra_ip_ratelimit_inc(struct infra_cache* infra,
|
||||
char client_ip[128];
|
||||
addr_to_str((struct sockaddr_storage *)&repinfo->addr,
|
||||
repinfo->addrlen, client_ip, sizeof(client_ip));
|
||||
verbose(VERB_OPS, "ratelimit exceeded %s %d", client_ip,
|
||||
infra_ip_ratelimit);
|
||||
verbose(VERB_OPS, "ip_ratelimit exceeded %s %d",
|
||||
client_ip, infra_ip_ratelimit);
|
||||
}
|
||||
return (max <= infra_ip_ratelimit);
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -81,8 +81,8 @@ void rrset_cache_delete(struct rrset_cache* r)
|
||||
struct rrset_cache* rrset_cache_adjust(struct rrset_cache *r,
|
||||
struct config_file* cfg, struct alloc_cache* alloc)
|
||||
{
|
||||
if(!r || !cfg || cfg->rrset_cache_slabs != r->table.size ||
|
||||
cfg->rrset_cache_size != slabhash_get_size(&r->table))
|
||||
if(!r || !cfg || !slabhash_is_size(&r->table, cfg->rrset_cache_size,
|
||||
cfg->rrset_cache_slabs))
|
||||
{
|
||||
rrset_cache_delete(r);
|
||||
r = rrset_cache_create(cfg, alloc);
|
||||
|
||||
+44
-14
@@ -247,6 +247,26 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
}
|
||||
#endif /* SO_REUSEADDR */
|
||||
#ifdef SO_REUSEPORT
|
||||
# ifdef SO_REUSEPORT_LB
|
||||
/* on FreeBSD 12 we have SO_REUSEPORT_LB that does loadbalance
|
||||
* like SO_REUSEPORT on Linux. This is what the users want
|
||||
* with the config option in unbound.conf; if we actually
|
||||
* need local address and port reuse they'll also need to
|
||||
* have SO_REUSEPORT set for them, assume it was _LB they want.
|
||||
*/
|
||||
if (reuseport && *reuseport &&
|
||||
setsockopt(s, SOL_SOCKET, SO_REUSEPORT_LB, (void*)&on,
|
||||
(socklen_t)sizeof(on)) < 0) {
|
||||
#ifdef ENOPROTOOPT
|
||||
if(errno != ENOPROTOOPT || verbosity >= 3)
|
||||
log_warn("setsockopt(.. SO_REUSEPORT_LB ..) failed: %s",
|
||||
strerror(errno));
|
||||
#endif
|
||||
/* this option is not essential, we can continue */
|
||||
*reuseport = 0;
|
||||
}
|
||||
# else /* no SO_REUSEPORT_LB */
|
||||
|
||||
/* try to set SO_REUSEPORT so that incoming
|
||||
* queries are distributed evenly among the receiving threads.
|
||||
* Each thread must have its own socket bound to the same port,
|
||||
@@ -263,6 +283,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
/* this option is not essential, we can continue */
|
||||
*reuseport = 0;
|
||||
}
|
||||
# endif /* SO_REUSEPORT_LB */
|
||||
#else
|
||||
(void)reuseport;
|
||||
#endif /* defined(SO_REUSEPORT) */
|
||||
@@ -564,7 +585,12 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
/* detect freebsd jail with no ipv6 permission */
|
||||
if(family==AF_INET6 && errno==EINVAL)
|
||||
*noproto = 1;
|
||||
else if(errno != EADDRINUSE) {
|
||||
else if(errno != EADDRINUSE &&
|
||||
!(errno == EACCES && verbosity < 4 && !listen)
|
||||
#ifdef EADDRNOTAVAIL
|
||||
&& !(errno == EADDRNOTAVAIL && verbosity < 4 && !listen)
|
||||
#endif
|
||||
) {
|
||||
log_err_addr("can't bind socket", strerror(errno),
|
||||
(struct sockaddr_storage*)addr, addrlen);
|
||||
}
|
||||
@@ -572,7 +598,8 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
close(s);
|
||||
#else /* USE_WINSOCK */
|
||||
if(WSAGetLastError() != WSAEADDRINUSE &&
|
||||
WSAGetLastError() != WSAEADDRNOTAVAIL) {
|
||||
WSAGetLastError() != WSAEADDRNOTAVAIL &&
|
||||
!(WSAGetLastError() == WSAEACCES && verbosity < 4 && !listen)) {
|
||||
log_err_addr("can't bind socket",
|
||||
wsa_strerror(WSAGetLastError()),
|
||||
(struct sockaddr_storage*)addr, addrlen);
|
||||
@@ -1059,7 +1086,7 @@ set_recvpktinfo(int s, int family)
|
||||
/** see if interface is ssl, its port number == the ssl port number */
|
||||
static int
|
||||
if_is_ssl(const char* ifname, const char* port, int ssl_port,
|
||||
struct config_strlist* additional_tls_port)
|
||||
struct config_strlist* tls_additional_port)
|
||||
{
|
||||
struct config_strlist* s;
|
||||
char* p = strchr(ifname, '@');
|
||||
@@ -1067,7 +1094,7 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
|
||||
return 1;
|
||||
if(p && atoi(p+1) == ssl_port)
|
||||
return 1;
|
||||
for(s = additional_tls_port; s; s = s->next) {
|
||||
for(s = tls_additional_port; s; s = s->next) {
|
||||
if(p && atoi(p+1) == atoi(s->str))
|
||||
return 1;
|
||||
if(!p && atoi(port) == atoi(s->str))
|
||||
@@ -1089,7 +1116,7 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
|
||||
* @param rcv: receive buffer size for UDP
|
||||
* @param snd: send buffer size for UDP
|
||||
* @param ssl_port: ssl service port number
|
||||
* @param additional_tls_port: list of additional ssl service port numbers.
|
||||
* @param tls_additional_port: list of additional ssl service port numbers.
|
||||
* @param reuseport: try to set SO_REUSEPORT if nonNULL and true.
|
||||
* set to false on exit if reuseport failed due to no kernel support.
|
||||
* @param transparent: set IP_TRANSPARENT socket option.
|
||||
@@ -1103,7 +1130,7 @@ 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, int ssl_port,
|
||||
struct config_strlist* additional_tls_port, int* reuseport,
|
||||
struct config_strlist* tls_additional_port, int* reuseport,
|
||||
int transparent, int tcp_mss, int freebind, int use_systemd,
|
||||
int dnscrypt_port)
|
||||
{
|
||||
@@ -1170,7 +1197,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
}
|
||||
if(do_tcp) {
|
||||
int is_ssl = if_is_ssl(ifname, port, ssl_port,
|
||||
additional_tls_port);
|
||||
tls_additional_port);
|
||||
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
|
||||
&noip6, 0, 0, reuseport, transparent, tcp_mss,
|
||||
freebind, use_systemd)) == -1) {
|
||||
@@ -1216,7 +1243,8 @@ 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, void* sslctx,
|
||||
size_t bufsize, int tcp_accept_count, int tcp_idle_timeout,
|
||||
struct tcl_list* tcp_conn_limit, void* sslctx,
|
||||
struct dt_env* dtenv, comm_point_callback_type* cb, void *cb_arg)
|
||||
{
|
||||
struct listen_dnsport* front = (struct listen_dnsport*)
|
||||
@@ -1243,10 +1271,12 @@ listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
else if(ports->ftype == listen_type_tcp ||
|
||||
ports->ftype == listen_type_tcp_dnscrypt)
|
||||
cp = comm_point_create_tcp(base, ports->fd,
|
||||
tcp_accept_count, bufsize, cb, cb_arg);
|
||||
tcp_accept_count, tcp_idle_timeout,
|
||||
tcp_conn_limit, bufsize, cb, cb_arg);
|
||||
else if(ports->ftype == listen_type_ssl) {
|
||||
cp = comm_point_create_tcp(base, ports->fd,
|
||||
tcp_accept_count, bufsize, cb, cb_arg);
|
||||
tcp_accept_count, tcp_idle_timeout,
|
||||
tcp_conn_limit, bufsize, cb, cb_arg);
|
||||
cp->ssl = sslctx;
|
||||
} else if(ports->ftype == listen_type_udpancil ||
|
||||
ports->ftype == listen_type_udpancil_dnscrypt)
|
||||
@@ -1356,7 +1386,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
|
||||
do_auto, cfg->do_udp, do_tcp,
|
||||
&hints, portbuf, &list,
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port, cfg->additional_tls_port,
|
||||
cfg->ssl_port, cfg->tls_additional_port,
|
||||
reuseport, cfg->ip_transparent,
|
||||
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
|
||||
cfg->dnscrypt_port)) {
|
||||
@@ -1370,7 +1400,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
|
||||
do_auto, cfg->do_udp, do_tcp,
|
||||
&hints, portbuf, &list,
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port, cfg->additional_tls_port,
|
||||
cfg->ssl_port, cfg->tls_additional_port,
|
||||
reuseport, cfg->ip_transparent,
|
||||
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
|
||||
cfg->dnscrypt_port)) {
|
||||
@@ -1386,7 +1416,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
|
||||
if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
|
||||
do_tcp, &hints, portbuf, &list,
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port, cfg->additional_tls_port,
|
||||
cfg->ssl_port, cfg->tls_additional_port,
|
||||
reuseport, cfg->ip_transparent,
|
||||
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
|
||||
cfg->dnscrypt_port)) {
|
||||
@@ -1400,7 +1430,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
|
||||
if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
|
||||
do_tcp, &hints, portbuf, &list,
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port, cfg->additional_tls_port,
|
||||
cfg->ssl_port, cfg->tls_additional_port,
|
||||
reuseport, cfg->ip_transparent,
|
||||
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
|
||||
cfg->dnscrypt_port)) {
|
||||
|
||||
@@ -47,6 +47,7 @@ struct listen_list;
|
||||
struct config_file;
|
||||
struct addrinfo;
|
||||
struct sldns_buffer;
|
||||
struct tcl_list;
|
||||
|
||||
/**
|
||||
* Listening for queries structure.
|
||||
@@ -137,6 +138,8 @@ 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 tcp_idle_timeout: idle timeout for TCP connections in msec.
|
||||
* @param tcp_conn_limit: TCP connection limit info.
|
||||
* @param sslctx: nonNULL if ssl context.
|
||||
* @param dtenv: nonNULL if dnstap enabled.
|
||||
* @param cb: callback function when a request arrives. It is passed
|
||||
@@ -145,9 +148,10 @@ void listening_ports_free(struct listen_port* list);
|
||||
* @return: the malloced listening structure, ready for use. NULL on error.
|
||||
*/
|
||||
struct listen_dnsport* listen_create(struct comm_base* base,
|
||||
struct listen_port* ports, size_t bufsize, int tcp_accept_count,
|
||||
void* sslctx, struct dt_env *dtenv, comm_point_callback_type* cb,
|
||||
void* cb_arg);
|
||||
struct listen_port* ports, size_t bufsize,
|
||||
int tcp_accept_count, int tcp_idle_timeout,
|
||||
struct tcl_list* tcp_conn_limit, void* sslctx,
|
||||
struct dt_env *dtenv, comm_point_callback_type* cb, void* cb_arg);
|
||||
|
||||
/**
|
||||
* delete the listening structure
|
||||
|
||||
+88
-40
@@ -1146,8 +1146,9 @@ void local_zones_print(struct local_zones* zones)
|
||||
/** encode answer consisting of 1 rrset */
|
||||
static int
|
||||
local_encode(struct query_info* qinfo, struct module_env* env,
|
||||
struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
|
||||
struct ub_packed_rrset_key* rrset, int ansec, int rcode)
|
||||
struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
|
||||
struct regional* temp, struct ub_packed_rrset_key* rrset, int ansec,
|
||||
int rcode)
|
||||
{
|
||||
struct reply_info rep;
|
||||
uint16_t udpsize;
|
||||
@@ -1165,23 +1166,22 @@ local_encode(struct query_info* qinfo, struct module_env* env,
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns->ext_rcode = 0;
|
||||
edns->bits &= EDNS_DO;
|
||||
if(!inplace_cb_reply_local_call(env, qinfo, NULL, &rep, rcode, edns, temp)
|
||||
|| !reply_info_answer_encode(qinfo, &rep,
|
||||
*(uint16_t*)sldns_buffer_begin(buf),
|
||||
sldns_buffer_read_u16_at(buf, 2),
|
||||
buf, 0, 0, temp, udpsize, edns,
|
||||
(int)(edns->bits&EDNS_DO), 0))
|
||||
if(!inplace_cb_reply_local_call(env, qinfo, NULL, &rep, rcode, edns,
|
||||
repinfo, temp) || !reply_info_answer_encode(qinfo, &rep,
|
||||
*(uint16_t*)sldns_buffer_begin(buf), sldns_buffer_read_u16_at(buf, 2),
|
||||
buf, 0, 0, temp, udpsize, edns, (int)(edns->bits&EDNS_DO), 0)) {
|
||||
error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo,
|
||||
*(uint16_t*)sldns_buffer_begin(buf),
|
||||
sldns_buffer_read_u16_at(buf, 2), edns);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** encode local error answer */
|
||||
static void
|
||||
local_error_encode(struct query_info* qinfo, struct module_env* env,
|
||||
struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
|
||||
int rcode, int r)
|
||||
struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
|
||||
struct regional* temp, int rcode, int r)
|
||||
{
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
@@ -1189,7 +1189,7 @@ local_error_encode(struct query_info* qinfo, struct module_env* env,
|
||||
edns->bits &= EDNS_DO;
|
||||
|
||||
if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL,
|
||||
rcode, edns, temp))
|
||||
rcode, edns, repinfo, temp))
|
||||
edns->opt_list = NULL;
|
||||
error_encode(buf, r, qinfo, *(uint16_t*)sldns_buffer_begin(buf),
|
||||
sldns_buffer_read_u16_at(buf, 2), edns);
|
||||
@@ -1310,7 +1310,8 @@ find_tag_datas(struct query_info* qinfo, struct config_strlist* list,
|
||||
/** answer local data match */
|
||||
static int
|
||||
local_data_answer(struct local_zone* z, struct module_env* env,
|
||||
struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
|
||||
struct query_info* qinfo, struct edns_data* edns,
|
||||
struct comm_reply* repinfo, sldns_buffer* buf,
|
||||
struct regional* temp, int labs, struct local_data** ldp,
|
||||
enum localzone_type lz_type, int tag, struct config_strlist** tag_datas,
|
||||
size_t tag_datas_size, char** tagname, int num_tags)
|
||||
@@ -1339,7 +1340,7 @@ local_data_answer(struct local_zone* z, struct module_env* env,
|
||||
* chain. */
|
||||
if(qinfo->local_alias)
|
||||
return 1;
|
||||
return local_encode(qinfo, env, edns, buf, temp,
|
||||
return local_encode(qinfo, env, edns, repinfo, buf, temp,
|
||||
&r, 1, LDNS_RCODE_NOERROR);
|
||||
}
|
||||
}
|
||||
@@ -1374,29 +1375,60 @@ local_data_answer(struct local_zone* z, struct module_env* env,
|
||||
struct ub_packed_rrset_key r = *lr->rrset;
|
||||
r.rk.dname = qinfo->qname;
|
||||
r.rk.dname_len = qinfo->qname_len;
|
||||
return local_encode(qinfo, env, edns, buf, temp, &r, 1,
|
||||
return local_encode(qinfo, env, edns, repinfo, buf, temp, &r, 1,
|
||||
LDNS_RCODE_NOERROR);
|
||||
}
|
||||
return local_encode(qinfo, env, edns, buf, temp, lr->rrset, 1,
|
||||
return local_encode(qinfo, env, edns, repinfo, buf, temp, lr->rrset, 1,
|
||||
LDNS_RCODE_NOERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* See if the local zone does not cover the name, eg. the name is not
|
||||
* in the zone and the zone is transparent */
|
||||
static int
|
||||
local_zone_does_not_cover(struct local_zone* z, struct query_info* qinfo,
|
||||
int labs)
|
||||
{
|
||||
struct local_data key;
|
||||
struct local_data* ld = NULL;
|
||||
struct local_rrset* lr = NULL;
|
||||
if(z->type == local_zone_always_transparent)
|
||||
return 1;
|
||||
if(z->type != local_zone_transparent
|
||||
&& z->type != local_zone_typetransparent
|
||||
&& z->type != local_zone_inform)
|
||||
return 0;
|
||||
key.node.key = &key;
|
||||
key.name = qinfo->qname;
|
||||
key.namelen = qinfo->qname_len;
|
||||
key.namelabs = labs;
|
||||
ld = (struct local_data*)rbtree_search(&z->data, &key.node);
|
||||
if(z->type == local_zone_transparent || z->type == local_zone_inform)
|
||||
return (ld == NULL);
|
||||
if(ld)
|
||||
lr = local_data_find_type(ld, qinfo->qtype, 1);
|
||||
/* local_zone_typetransparent */
|
||||
return (lr == NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* answer in case where no exact match is found
|
||||
* @param z: zone for query
|
||||
* @param env: module environment
|
||||
* @param qinfo: query
|
||||
* @param edns: edns from query
|
||||
* Answer in case where no exact match is found.
|
||||
* @param z: zone for query.
|
||||
* @param env: module environment.
|
||||
* @param qinfo: query.
|
||||
* @param edns: edns from query.
|
||||
* @param repinfo: source address for checks. may be NULL.
|
||||
* @param buf: buffer for answer.
|
||||
* @param temp: temp region for encoding
|
||||
* @param temp: temp region for encoding.
|
||||
* @param ld: local data, if NULL, no such name exists in localdata.
|
||||
* @param lz_type: type of the local zone
|
||||
* @param lz_type: type of the local zone.
|
||||
* @return 1 if a reply is to be sent, 0 if not.
|
||||
*/
|
||||
static int
|
||||
lz_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
|
||||
struct regional* temp, struct local_data* ld, enum localzone_type lz_type)
|
||||
struct query_info* qinfo, struct edns_data* edns,
|
||||
struct comm_reply* repinfo, sldns_buffer* buf, struct regional* temp,
|
||||
struct local_data* ld, enum localzone_type lz_type)
|
||||
{
|
||||
if(lz_type == local_zone_deny || lz_type == local_zone_inform_deny) {
|
||||
/** no reply at all, signal caller by clearing buffer. */
|
||||
@@ -1405,7 +1437,7 @@ lz_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
return 1;
|
||||
} else if(lz_type == local_zone_refuse
|
||||
|| lz_type == local_zone_always_refuse) {
|
||||
local_error_encode(qinfo, env, edns, buf, temp,
|
||||
local_error_encode(qinfo, env, edns, repinfo, buf, temp,
|
||||
LDNS_RCODE_REFUSED, (LDNS_RCODE_REFUSED|BIT_AA));
|
||||
return 1;
|
||||
} else if(lz_type == local_zone_static ||
|
||||
@@ -1421,9 +1453,9 @@ lz_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
int rcode = (ld || lz_type == local_zone_redirect)?
|
||||
LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN;
|
||||
if(z->soa)
|
||||
return local_encode(qinfo, env, edns, buf, temp,
|
||||
return local_encode(qinfo, env, edns, repinfo, buf, temp,
|
||||
z->soa, 0, rcode);
|
||||
local_error_encode(qinfo, env, edns, buf, temp, rcode,
|
||||
local_error_encode(qinfo, env, edns, repinfo, buf, temp, rcode,
|
||||
(rcode|BIT_AA));
|
||||
return 1;
|
||||
} else if(lz_type == local_zone_typetransparent
|
||||
@@ -1438,9 +1470,9 @@ lz_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
if(ld && ld->rrsets) {
|
||||
int rcode = LDNS_RCODE_NOERROR;
|
||||
if(z->soa)
|
||||
return local_encode(qinfo, env, edns, buf, temp,
|
||||
return local_encode(qinfo, env, edns, repinfo, buf, temp,
|
||||
z->soa, 0, rcode);
|
||||
local_error_encode(qinfo, env, edns, buf, temp, rcode,
|
||||
local_error_encode(qinfo, env, edns, repinfo, buf, temp, rcode,
|
||||
(rcode|BIT_AA));
|
||||
return 1;
|
||||
}
|
||||
@@ -1459,7 +1491,7 @@ lz_inform_print(struct local_zone* z, struct query_info* qinfo,
|
||||
uint16_t port = ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port);
|
||||
dname_str(z->name, zname);
|
||||
addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
|
||||
snprintf(txt, sizeof(txt), "%s inform %s@%u", zname, ip,
|
||||
snprintf(txt, sizeof(txt), "%s %s %s@%u", zname, local_zone_type2str(z->type), ip,
|
||||
(unsigned)port);
|
||||
log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass);
|
||||
}
|
||||
@@ -1543,10 +1575,6 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||
(z = local_zones_lookup(view->local_zones,
|
||||
qinfo->qname, qinfo->qname_len, labs,
|
||||
qinfo->qclass, qinfo->qtype))) {
|
||||
if(z->type != local_zone_noview)
|
||||
verbose(VERB_ALGO,
|
||||
"using localzone from view: %s",
|
||||
view->name);
|
||||
lock_rw_rdlock(&z->lock);
|
||||
lzt = z->type;
|
||||
}
|
||||
@@ -1554,10 +1582,24 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||
lock_rw_unlock(&z->lock);
|
||||
z = NULL;
|
||||
}
|
||||
if(z && (lzt == local_zone_transparent ||
|
||||
lzt == local_zone_typetransparent ||
|
||||
lzt == local_zone_inform ||
|
||||
lzt == local_zone_always_transparent) &&
|
||||
local_zone_does_not_cover(z, qinfo, labs)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
z = NULL;
|
||||
}
|
||||
if(view->local_zones && !z && !view->isfirst){
|
||||
lock_rw_unlock(&view->lock);
|
||||
return 0;
|
||||
}
|
||||
if(z && verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
dname_str(z->name, zname);
|
||||
verbose(VERB_ALGO, "using localzone %s %s from view %s",
|
||||
zname, local_zone_type2str(lzt), view->name);
|
||||
}
|
||||
lock_rw_unlock(&view->lock);
|
||||
}
|
||||
if(!z) {
|
||||
@@ -1570,27 +1612,33 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||
return 0;
|
||||
}
|
||||
lock_rw_rdlock(&z->lock);
|
||||
|
||||
lzt = lz_type(taglist, taglen, z->taglist, z->taglen,
|
||||
tagactions, tagactionssize, z->type, repinfo,
|
||||
z->override_tree, &tag, tagname, num_tags);
|
||||
lock_rw_unlock(&zones->lock);
|
||||
if(z && verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
dname_str(z->name, zname);
|
||||
verbose(VERB_ALGO, "using localzone %s %s", zname,
|
||||
local_zone_type2str(lzt));
|
||||
}
|
||||
}
|
||||
if((lzt == local_zone_inform || lzt == local_zone_inform_deny)
|
||||
&& repinfo)
|
||||
if((env->cfg->log_local_actions ||
|
||||
lzt == local_zone_inform || lzt == local_zone_inform_deny)
|
||||
&& repinfo)
|
||||
lz_inform_print(z, qinfo, repinfo);
|
||||
|
||||
if(lzt != local_zone_always_refuse
|
||||
&& lzt != local_zone_always_transparent
|
||||
&& lzt != local_zone_always_nxdomain
|
||||
&& local_data_answer(z, env, qinfo, edns, buf, temp, labs, &ld, lzt,
|
||||
tag, tag_datas, tag_datas_size, tagname, num_tags)) {
|
||||
&& local_data_answer(z, env, qinfo, edns, repinfo, buf, temp, labs,
|
||||
&ld, lzt, tag, tag_datas, tag_datas_size, tagname, num_tags)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
/* We should tell the caller that encode is deferred if we found
|
||||
* a local alias. */
|
||||
return !qinfo->local_alias;
|
||||
}
|
||||
r = lz_zone_answer(z, env, qinfo, edns, buf, temp, ld, lzt);
|
||||
r = lz_zone_answer(z, env, qinfo, edns, repinfo, buf, temp, ld, lzt);
|
||||
lock_rw_unlock(&z->lock);
|
||||
return r && !qinfo->local_alias; /* see above */
|
||||
}
|
||||
|
||||
+40
-18
@@ -55,6 +55,7 @@
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "util/alloc.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/edns.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#include "services/localzone.h"
|
||||
@@ -385,7 +386,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
if(!s) {
|
||||
log_err("mesh_state_create: out of memory; SERVFAIL");
|
||||
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, NULL,
|
||||
LDNS_RCODE_SERVFAIL, edns, mesh->env->scratch))
|
||||
LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
|
||||
edns->opt_list = NULL;
|
||||
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, qid, qflags, edns);
|
||||
@@ -401,7 +402,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
if(!s->s.edns_opts_front_in) {
|
||||
log_err("mesh_state_create: out of memory; SERVFAIL");
|
||||
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL,
|
||||
NULL, LDNS_RCODE_SERVFAIL, edns, mesh->env->scratch))
|
||||
NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
|
||||
edns->opt_list = NULL;
|
||||
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, qid, qflags, edns);
|
||||
@@ -429,7 +430,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
if(!mesh_state_add_reply(s, edns, rep, qid, qflags, qinfo)) {
|
||||
log_err("mesh_new_client: out of memory; SERVFAIL");
|
||||
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, &s->s,
|
||||
NULL, LDNS_RCODE_SERVFAIL, edns, mesh->env->scratch))
|
||||
NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
|
||||
edns->opt_list = NULL;
|
||||
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, qid, qflags, edns);
|
||||
@@ -631,8 +632,8 @@ void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e,
|
||||
mesh_run(mesh, e->qstate->mesh_info, event, e);
|
||||
}
|
||||
|
||||
struct mesh_state*
|
||||
mesh_state_create(struct module_env* env, struct query_info* qinfo,
|
||||
struct mesh_state*
|
||||
mesh_state_create(struct module_env* env, struct query_info* qinfo,
|
||||
struct respip_client_info* cinfo, uint16_t qflags, int prime,
|
||||
int valrec)
|
||||
{
|
||||
@@ -693,6 +694,7 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
|
||||
mstate->s.no_cache_lookup = 0;
|
||||
mstate->s.no_cache_store = 0;
|
||||
mstate->s.need_refetch = 0;
|
||||
mstate->s.was_ratelimited = 0;
|
||||
|
||||
/* init modules */
|
||||
for(i=0; i<env->mesh->mods.num; i++) {
|
||||
@@ -740,7 +742,7 @@ mesh_state_cleanup(struct mesh_state* mstate)
|
||||
mstate->cb_list = cb->next;
|
||||
fptr_ok(fptr_whitelist_mesh_cb(cb->cb));
|
||||
(*cb->cb)(cb->cb_arg, LDNS_RCODE_SERVFAIL, NULL,
|
||||
sec_status_unchecked, NULL);
|
||||
sec_status_unchecked, NULL, 0);
|
||||
mesh->num_reply_addrs--;
|
||||
}
|
||||
}
|
||||
@@ -968,7 +970,8 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
{
|
||||
int secure;
|
||||
char* reason = NULL;
|
||||
/* bogus messages are not made into servfail, sec_status passed
|
||||
int was_ratelimited = m->s.was_ratelimited;
|
||||
/* bogus messages are not made into servfail, sec_status passed
|
||||
* to the callback function */
|
||||
if(rep && rep->security == sec_status_secure)
|
||||
secure = 1;
|
||||
@@ -977,22 +980,23 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
if(!rcode && (rep->security == sec_status_bogus ||
|
||||
rep->security == sec_status_secure_sentinel_fail)) {
|
||||
if(!(reason = errinf_to_str(&m->s)))
|
||||
if(!(reason = errinf_to_str_bogus(&m->s)))
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
}
|
||||
/* send the reply */
|
||||
if(rcode) {
|
||||
if(rcode == LDNS_RCODE_SERVFAIL) {
|
||||
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
|
||||
rep, rcode, &r->edns, m->s.region))
|
||||
rep, rcode, &r->edns, NULL, m->s.region))
|
||||
r->edns.opt_list = NULL;
|
||||
} else {
|
||||
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode,
|
||||
&r->edns, m->s.region))
|
||||
&r->edns, NULL, m->s.region))
|
||||
r->edns.opt_list = NULL;
|
||||
}
|
||||
fptr_ok(fptr_whitelist_mesh_cb(r->cb));
|
||||
(*r->cb)(r->cb_arg, rcode, r->buf, sec_status_unchecked, NULL);
|
||||
(*r->cb)(r->cb_arg, rcode, r->buf, sec_status_unchecked, NULL,
|
||||
was_ratelimited);
|
||||
} else {
|
||||
size_t udp_size = r->edns.udp_size;
|
||||
sldns_buffer_clear(r->buf);
|
||||
@@ -1002,7 +1006,7 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
r->edns.bits &= EDNS_DO;
|
||||
|
||||
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep,
|
||||
LDNS_RCODE_NOERROR, &r->edns, m->s.region) ||
|
||||
LDNS_RCODE_NOERROR, &r->edns, NULL, m->s.region) ||
|
||||
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
|
||||
r->qflags, r->buf, 0, 1,
|
||||
m->s.env->scratch, udp_size, &r->edns,
|
||||
@@ -1010,11 +1014,11 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
{
|
||||
fptr_ok(fptr_whitelist_mesh_cb(r->cb));
|
||||
(*r->cb)(r->cb_arg, LDNS_RCODE_SERVFAIL, r->buf,
|
||||
sec_status_unchecked, NULL);
|
||||
sec_status_unchecked, NULL, 0);
|
||||
} else {
|
||||
fptr_ok(fptr_whitelist_mesh_cb(r->cb));
|
||||
(*r->cb)(r->cb_arg, LDNS_RCODE_NOERROR, r->buf,
|
||||
rep->security, reason);
|
||||
rep->security, reason, was_ratelimited);
|
||||
}
|
||||
}
|
||||
free(reason);
|
||||
@@ -1080,11 +1084,11 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
m->s.qinfo.local_alias = r->local_alias;
|
||||
if(rcode == LDNS_RCODE_SERVFAIL) {
|
||||
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
|
||||
rep, rcode, &r->edns, m->s.region))
|
||||
rep, rcode, &r->edns, NULL, m->s.region))
|
||||
r->edns.opt_list = NULL;
|
||||
} else {
|
||||
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode,
|
||||
&r->edns, m->s.region))
|
||||
&r->edns, NULL, m->s.region))
|
||||
r->edns.opt_list = NULL;
|
||||
}
|
||||
error_encode(r->query_reply.c->buffer, rcode, &m->s.qinfo,
|
||||
@@ -1099,14 +1103,17 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
m->s.qinfo.qname = r->qname;
|
||||
m->s.qinfo.local_alias = r->local_alias;
|
||||
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep,
|
||||
LDNS_RCODE_NOERROR, &r->edns, m->s.region) ||
|
||||
LDNS_RCODE_NOERROR, &r->edns, NULL, m->s.region) ||
|
||||
!apply_edns_options(&r->edns, &edns_bak,
|
||||
m->s.env->cfg, r->query_reply.c,
|
||||
m->s.region) ||
|
||||
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
|
||||
r->qflags, r->query_reply.c->buffer, 0, 1,
|
||||
m->s.env->scratch, udp_size, &r->edns,
|
||||
(int)(r->edns.bits & EDNS_DO), secure))
|
||||
{
|
||||
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
|
||||
rep, LDNS_RCODE_SERVFAIL, &r->edns, m->s.region))
|
||||
rep, LDNS_RCODE_SERVFAIL, &r->edns, NULL, m->s.region))
|
||||
r->edns.opt_list = NULL;
|
||||
error_encode(r->query_reply.c->buffer,
|
||||
LDNS_RCODE_SERVFAIL, &m->s.qinfo, r->qid,
|
||||
@@ -1148,6 +1155,15 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
struct mesh_cb* c;
|
||||
struct reply_info* rep = (mstate->s.return_msg?
|
||||
mstate->s.return_msg->rep:NULL);
|
||||
if((mstate->s.return_rcode == LDNS_RCODE_SERVFAIL ||
|
||||
(rep && FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_SERVFAIL))
|
||||
&& mstate->s.env->cfg->log_servfail
|
||||
&& !mstate->s.env->cfg->val_log_squelch) {
|
||||
char* err = errinf_to_str_servfail(&mstate->s);
|
||||
if(err)
|
||||
log_err("%s", err);
|
||||
free(err);
|
||||
}
|
||||
for(r = mstate->reply_list; r; r = r->next) {
|
||||
/* if a response-ip address block has been stored the
|
||||
* information should be logged for each client. */
|
||||
@@ -1173,6 +1189,10 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
while((c = mstate->cb_list) != NULL) {
|
||||
/* take this cb off the list; so that the list can be
|
||||
* changed, eg. by adds from the callback routine */
|
||||
if(!mstate->reply_list && mstate->cb_list && !c->next) {
|
||||
/* was a reply state, not anymore */
|
||||
mstate->s.env->mesh->num_reply_states--;
|
||||
}
|
||||
mstate->cb_list = c->next;
|
||||
if(!mstate->reply_list && !mstate->cb_list &&
|
||||
mstate->super_set.count == 0)
|
||||
@@ -1193,6 +1213,8 @@ void mesh_walk_supers(struct mesh_area* mesh, struct mesh_state* mstate)
|
||||
mesh->mods.mod[ref->s->s.curmod]->inform_super));
|
||||
(*mesh->mods.mod[ref->s->s.curmod]->inform_super)(&mstate->s,
|
||||
ref->s->s.curmod, &ref->s->s);
|
||||
/* copy state that is always relevant to super */
|
||||
copy_state_to_super(&mstate->s, ref->s->s.curmod, &ref->s->s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -223,10 +223,11 @@ struct mesh_reply {
|
||||
|
||||
/**
|
||||
* Mesh result callback func.
|
||||
* called as func(cb_arg, rcode, buffer_with_reply, security, why_bogus);
|
||||
* called as func(cb_arg, rcode, buffer_with_reply, security, why_bogus,
|
||||
* was_ratelimited);
|
||||
*/
|
||||
typedef void (*mesh_cb_func_type)(void*, int, struct sldns_buffer*, enum sec_status,
|
||||
char*);
|
||||
typedef void (*mesh_cb_func_type)(void* cb_arg, int rcode, struct sldns_buffer*,
|
||||
enum sec_status, char* why_bogus, int was_ratelimited);
|
||||
|
||||
/**
|
||||
* Callback to result routine
|
||||
@@ -242,9 +243,8 @@ struct mesh_cb {
|
||||
uint16_t qflags;
|
||||
/** buffer for reply */
|
||||
struct sldns_buffer* buf;
|
||||
|
||||
/** callback routine for results. if rcode != 0 buf has message.
|
||||
* called as cb(cb_arg, rcode, buf, sec_state);
|
||||
* called as cb(cb_arg, rcode, buf, sec_state, why_bogus, was_ratelimited);
|
||||
*/
|
||||
mesh_cb_func_type cb;
|
||||
/** user arg for callback */
|
||||
|
||||
+73
-34
@@ -48,6 +48,7 @@
|
||||
#include "services/outside_network.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "util/data/msgparse.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/data/msgencode.h"
|
||||
@@ -364,6 +365,11 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
|
||||
comm_point_tcp_win_bio_cb(pend->c, pend->c->ssl);
|
||||
#endif
|
||||
pend->c->ssl_shake_state = comm_ssl_shake_write;
|
||||
if(w->tls_auth_name) {
|
||||
#ifdef HAVE_SSL
|
||||
(void)SSL_set_tlsext_host_name(pend->c->ssl, w->tls_auth_name);
|
||||
#endif
|
||||
}
|
||||
#ifdef HAVE_SSL_SET1_HOST
|
||||
if(w->tls_auth_name) {
|
||||
SSL_set_verify(pend->c->ssl, SSL_VERIFY_PEER, NULL);
|
||||
@@ -373,6 +379,8 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
|
||||
if(!SSL_set1_host(pend->c->ssl, w->tls_auth_name)) {
|
||||
log_err("SSL_set1_host failed");
|
||||
pend->c->fd = s;
|
||||
SSL_free(pend->c->ssl);
|
||||
pend->c->ssl = NULL;
|
||||
comm_point_close(pend->c);
|
||||
return 0;
|
||||
}
|
||||
@@ -1036,6 +1044,8 @@ udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int pfxlen,
|
||||
int freebind = 0;
|
||||
struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr;
|
||||
sa.sin6_port = (in_port_t)htons((uint16_t)port);
|
||||
sa.sin6_flowinfo = 0;
|
||||
sa.sin6_scope_id = 0;
|
||||
if(pfxlen != 0) {
|
||||
freebind = 1;
|
||||
sai6_putrandom(&sa, pfxlen, rnd);
|
||||
@@ -1258,6 +1268,13 @@ outnet_tcptimer(void* arg)
|
||||
} else {
|
||||
/* it was in use */
|
||||
struct pending_tcp* pend=(struct pending_tcp*)w->next_waiting;
|
||||
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->query = NULL;
|
||||
pend->next_free = outnet->tcp_free;
|
||||
@@ -1301,8 +1318,8 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet,
|
||||
w->ssl_upstream = sq->ssl_upstream;
|
||||
w->tls_auth_name = sq->tls_auth_name;
|
||||
#ifndef S_SPLINT_S
|
||||
tv.tv_sec = timeout;
|
||||
tv.tv_usec = 0;
|
||||
tv.tv_sec = timeout/1000;
|
||||
tv.tv_usec = (timeout%1000)*1000;
|
||||
#endif
|
||||
comm_timer_set(w->timer, &tv);
|
||||
if(pend) {
|
||||
@@ -1812,7 +1829,12 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
|
||||
}
|
||||
if(sq->tcp_upstream || sq->ssl_upstream) {
|
||||
struct timeval now = *sq->outnet->now_tv;
|
||||
if(now.tv_sec > sq->last_sent_time.tv_sec ||
|
||||
if(error!=NETEVENT_NOERROR) {
|
||||
if(!infra_rtt_update(sq->outnet->infra, &sq->addr,
|
||||
sq->addrlen, sq->zone, sq->zonelen, sq->qtype,
|
||||
-1, sq->last_rtt, (time_t)now.tv_sec))
|
||||
log_err("out of memory in TCP exponential backoff.");
|
||||
} else 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 */
|
||||
@@ -1822,7 +1844,7 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
|
||||
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(roundtime < 60000) {
|
||||
if(!infra_rtt_update(sq->outnet->infra, &sq->addr,
|
||||
sq->addrlen, sq->zone, sq->zonelen, sq->qtype,
|
||||
roundtime, sq->last_rtt, (time_t)now.tv_sec))
|
||||
@@ -1854,7 +1876,7 @@ serviced_tcp_initiate(struct serviced_query* sq, sldns_buffer* buff)
|
||||
if(!sq->pending) {
|
||||
/* delete from tree so that a retry by above layer does not
|
||||
* clash with this entry */
|
||||
log_err("serviced_tcp_initiate: failed to send tcp query");
|
||||
verbose(VERB_ALGO, "serviced_tcp_initiate: failed to send tcp query");
|
||||
serviced_callbacks(sq, NETEVENT_CLOSED, NULL, NULL);
|
||||
}
|
||||
}
|
||||
@@ -1863,18 +1885,26 @@ serviced_tcp_initiate(struct serviced_query* sq, sldns_buffer* buff)
|
||||
static int
|
||||
serviced_tcp_send(struct serviced_query* sq, sldns_buffer* buff)
|
||||
{
|
||||
int vs, rtt;
|
||||
int vs, rtt, timeout;
|
||||
uint8_t edns_lame_known;
|
||||
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;
|
||||
sq->last_rtt = rtt;
|
||||
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, buff, TCP_AUTH_QUERY_TIMEOUT,
|
||||
if(sq->tcp_upstream || sq->ssl_upstream) {
|
||||
timeout = rtt;
|
||||
if(rtt >= UNKNOWN_SERVER_NICENESS && rtt < TCP_AUTH_QUERY_TIMEOUT)
|
||||
timeout = TCP_AUTH_QUERY_TIMEOUT;
|
||||
} else {
|
||||
timeout = TCP_AUTH_QUERY_TIMEOUT;
|
||||
}
|
||||
sq->pending = pending_tcp_query(sq, buff, timeout,
|
||||
serviced_tcp_callback, sq);
|
||||
return sq->pending != NULL;
|
||||
}
|
||||
@@ -1963,7 +1993,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
return 0;
|
||||
}
|
||||
if(rto >= RTT_MAX_TIMEOUT) {
|
||||
fallback_tcp = 1;
|
||||
/* fallback_tcp = 1; */
|
||||
/* UDP does not work, fallback to TCP below */
|
||||
} else {
|
||||
serviced_callbacks(sq, NETEVENT_TIMEOUT, c, rep);
|
||||
@@ -2177,39 +2207,48 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
|
||||
{
|
||||
struct sockaddr_storage* addr;
|
||||
socklen_t addrlen;
|
||||
int i;
|
||||
int try;
|
||||
|
||||
/* select interface */
|
||||
if(addr_is_ip6(to_addr, to_addrlen)) {
|
||||
if(outnet->num_ip6 == 0) {
|
||||
char to[64];
|
||||
addr_to_str(to_addr, to_addrlen, to, sizeof(to));
|
||||
verbose(VERB_QUERY, "need ipv6 to send, but no ipv6 outgoing interfaces, for %s", to);
|
||||
return -1;
|
||||
}
|
||||
i = ub_random_max(outnet->rnd, outnet->num_ip6);
|
||||
addr = &outnet->ip6_ifs[i].addr;
|
||||
addrlen = outnet->ip6_ifs[i].addrlen;
|
||||
} else {
|
||||
if(outnet->num_ip4 == 0) {
|
||||
char to[64];
|
||||
addr_to_str(to_addr, to_addrlen, to, sizeof(to));
|
||||
verbose(VERB_QUERY, "need ipv4 to send, but no ipv4 outgoing interfaces, for %s", to);
|
||||
return -1;
|
||||
}
|
||||
i = ub_random_max(outnet->rnd, outnet->num_ip4);
|
||||
addr = &outnet->ip4_ifs[i].addr;
|
||||
addrlen = outnet->ip4_ifs[i].addrlen;
|
||||
}
|
||||
int i, try, pnum;
|
||||
struct port_if* pif;
|
||||
|
||||
/* create fd */
|
||||
for(try = 0; try<1000; try++) {
|
||||
int port = 0;
|
||||
int freebind = 0;
|
||||
int noproto = 0;
|
||||
int inuse = 0;
|
||||
int port = ub_random(outnet->rnd)&0xffff;
|
||||
int fd = -1;
|
||||
|
||||
/* select interface */
|
||||
if(addr_is_ip6(to_addr, to_addrlen)) {
|
||||
if(outnet->num_ip6 == 0) {
|
||||
char to[64];
|
||||
addr_to_str(to_addr, to_addrlen, to, sizeof(to));
|
||||
verbose(VERB_QUERY, "need ipv6 to send, but no ipv6 outgoing interfaces, for %s", to);
|
||||
return -1;
|
||||
}
|
||||
i = ub_random_max(outnet->rnd, outnet->num_ip6);
|
||||
pif = &outnet->ip6_ifs[i];
|
||||
} else {
|
||||
if(outnet->num_ip4 == 0) {
|
||||
char to[64];
|
||||
addr_to_str(to_addr, to_addrlen, to, sizeof(to));
|
||||
verbose(VERB_QUERY, "need ipv4 to send, but no ipv4 outgoing interfaces, for %s", to);
|
||||
return -1;
|
||||
}
|
||||
i = ub_random_max(outnet->rnd, outnet->num_ip4);
|
||||
pif = &outnet->ip4_ifs[i];
|
||||
}
|
||||
addr = &pif->addr;
|
||||
addrlen = pif->addrlen;
|
||||
pnum = ub_random_max(outnet->rnd, pif->avail_total);
|
||||
if(pnum < pif->inuse) {
|
||||
/* port already open */
|
||||
port = pif->out[pnum]->number;
|
||||
} else {
|
||||
/* unused ports in start part of array */
|
||||
port = pif->avail_ports[pnum - pif->inuse];
|
||||
}
|
||||
|
||||
if(addr_is_ip6(to_addr, to_addrlen)) {
|
||||
struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr;
|
||||
sa.sin6_port = (in_port_t)htons((uint16_t)port);
|
||||
|
||||
@@ -376,7 +376,7 @@ struct serviced_query {
|
||||
int retry;
|
||||
/** time last UDP was sent */
|
||||
struct timeval last_sent_time;
|
||||
/** rtt of last (UDP) message */
|
||||
/** rtt of last message */
|
||||
int last_rtt;
|
||||
/** do we know edns probe status already, for UDP_EDNS queries */
|
||||
int edns_lame_known;
|
||||
@@ -456,7 +456,7 @@ struct pending* pending_udp_query(struct serviced_query* sq,
|
||||
* checks id.
|
||||
* @param sq: serviced query.
|
||||
* @param packet: wireformat query to send to destination. copied from.
|
||||
* @param timeout: in seconds from now.
|
||||
* @param timeout: in milliseconds from now.
|
||||
* Timer starts running now. Timer may expire if all buffers are used,
|
||||
* without any query been sent to the server yet.
|
||||
* @param callback: function to call on error, timeout or reply.
|
||||
|
||||
+2
-5
@@ -341,12 +341,9 @@ static sldns_rr_descriptor rdata_field_descriptors[] = {
|
||||
{LDNS_RR_TYPE_NSEC3PARAM, "NSEC3PARAM", 4, 4, type_nsec3param_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
|
||||
/* 52 */
|
||||
{LDNS_RR_TYPE_TLSA, "TLSA", 4, 4, type_tlsa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
|
||||
/*53 */
|
||||
#ifdef DRAFT_RRTYPES
|
||||
/* 53 */
|
||||
{LDNS_RR_TYPE_SMIMEA, "SMIMEA", 4, 4, type_tlsa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
|
||||
#else
|
||||
{LDNS_RR_TYPE_NULL, "TYPE53", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
|
||||
#endif
|
||||
/* 54 */
|
||||
{LDNS_RR_TYPE_NULL, "TYPE54", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
|
||||
/* 55
|
||||
* Hip ends with 0 or more Rendezvous Servers represented as dname's.
|
||||
|
||||
+1
-3
@@ -182,9 +182,7 @@ enum sldns_enum_rr_type
|
||||
LDNS_RR_TYPE_NSEC3PARAM = 51, /* RFC 5155 */
|
||||
LDNS_RR_TYPE_NSEC3PARAMS = 51,
|
||||
LDNS_RR_TYPE_TLSA = 52, /* RFC 6698 */
|
||||
LDNS_RR_TYPE_SMIMEA = 53, /* draft-ietf-dane-smime, TLSA-like but may
|
||||
be extended */
|
||||
|
||||
LDNS_RR_TYPE_SMIMEA = 53, /* RFC 8162 */
|
||||
LDNS_RR_TYPE_HIP = 55, /* RFC 5205 */
|
||||
|
||||
/** draft-reid-dnsext-zs */
|
||||
|
||||
+2
-2
@@ -130,7 +130,7 @@ struct sldns_buffer
|
||||
/** If the buffer is fixed it cannot be resized */
|
||||
unsigned _fixed : 1;
|
||||
|
||||
/** If the buffer is vfixed, no more than capacity bytes willl be
|
||||
/** If the buffer is vfixed, no more than capacity bytes will be
|
||||
* written to _data, however the _position counter will be updated
|
||||
* with the amount that would have been written in consecutive
|
||||
* writes. This allows for a modus operandi in which a sequence is
|
||||
@@ -160,7 +160,7 @@ sldns_buffer_invariant(sldns_buffer *buffer)
|
||||
assert(buffer != NULL);
|
||||
assert(buffer->_position <= buffer->_limit || buffer->_vfixed);
|
||||
assert(buffer->_limit <= buffer->_capacity);
|
||||
assert(buffer->_data != NULL || (buffer->_vfixed && buffer->_capacity == 0));
|
||||
assert(buffer->_data != NULL || (buffer->_vfixed && buffer->_capacity == 0 && buffer->_limit == 0));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+58
-36
@@ -192,9 +192,10 @@ usage(void)
|
||||
printf("-n name signer's subject emailAddress, default %s\n", P7SIGNER);
|
||||
printf("-4 work using IPv4 only\n");
|
||||
printf("-6 work using IPv6 only\n");
|
||||
printf("-f resolv.conf use given resolv.conf to resolve -u name\n");
|
||||
printf("-r root.hints use given root.hints to resolve -u name\n"
|
||||
printf("-f resolv.conf use given resolv.conf\n");
|
||||
printf("-r root.hints use given root.hints\n"
|
||||
" builtin root hints are used by default\n");
|
||||
printf("-R fallback from -f to root query on error\n");
|
||||
printf("-v more verbose\n");
|
||||
printf("-C conf debug, read config\n");
|
||||
printf("-P port use port for https connect, default 443\n");
|
||||
@@ -1096,11 +1097,14 @@ read_http_result(SSL* ssl)
|
||||
}
|
||||
if(!data) return NULL;
|
||||
if(verb >= 4) print_data("read data", data, (int)len);
|
||||
m = BIO_new_mem_buf(data, (int)len);
|
||||
m = BIO_new(BIO_s_mem());
|
||||
if(!m) {
|
||||
if(verb) printf("out of memory\n");
|
||||
free(data);
|
||||
exit(0);
|
||||
}
|
||||
BIO_write(m, data, (int)len);
|
||||
free(data);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -1167,17 +1171,6 @@ https(struct ip_list* ip_list, const char* pathname, const char* urlname)
|
||||
return bio;
|
||||
}
|
||||
|
||||
/** free up a downloaded file BIO */
|
||||
static void
|
||||
free_file_bio(BIO* bio)
|
||||
{
|
||||
char* pp = NULL;
|
||||
(void)BIO_reset(bio);
|
||||
(void)BIO_get_mem_data(bio, &pp);
|
||||
free(pp);
|
||||
BIO_free(bio);
|
||||
}
|
||||
|
||||
/** XML parse private data during the parse */
|
||||
struct xml_data {
|
||||
/** the parser, reference */
|
||||
@@ -1602,7 +1595,7 @@ xml_parse(BIO* xml, time_t now)
|
||||
xml_parse_setup(parser, &data, now);
|
||||
|
||||
/* parse it */
|
||||
(void)BIO_reset(xml);
|
||||
(void)BIO_seek(xml, 0);
|
||||
len = (int)BIO_get_mem_data(xml, &pp);
|
||||
if(!len || !pp) {
|
||||
if(verb) printf("out of memory\n");
|
||||
@@ -1776,8 +1769,8 @@ verify_p7sig(BIO* data, BIO* p7s, STACK_OF(X509)* trust, const char* p7signer)
|
||||
X509_VERIFY_PARAM_free(param);
|
||||
#endif
|
||||
|
||||
(void)BIO_reset(p7s);
|
||||
(void)BIO_reset(data);
|
||||
(void)BIO_seek(p7s, 0);
|
||||
(void)BIO_seek(data, 0);
|
||||
|
||||
/* convert p7s to p7 (the signature) */
|
||||
p7 = d2i_PKCS7_bio(p7s, NULL);
|
||||
@@ -1920,8 +1913,7 @@ static int
|
||||
do_certupdate(const char* root_anchor_file, const char* root_cert_file,
|
||||
const char* urlname, const char* xmlname, const char* p7sname,
|
||||
const char* p7signer, const char* res_conf, const char* root_hints,
|
||||
const char* debugconf, int ip4only, int ip6only, int port,
|
||||
struct ub_result* dnskey)
|
||||
const char* debugconf, int ip4only, int ip6only, int port)
|
||||
{
|
||||
STACK_OF(X509)* cert;
|
||||
BIO *xml, *p7s;
|
||||
@@ -1956,12 +1948,11 @@ do_certupdate(const char* root_anchor_file, const char* root_cert_file,
|
||||
if(verb) printf("success: the anchor has been updated "
|
||||
"using the cert\n");
|
||||
|
||||
free_file_bio(xml);
|
||||
free_file_bio(p7s);
|
||||
BIO_free(xml);
|
||||
BIO_free(p7s);
|
||||
#ifndef S_SPLINT_S
|
||||
sk_X509_pop_free(cert, X509_free);
|
||||
#endif
|
||||
ub_resolve_free(dnskey);
|
||||
ip_list_free(ip_list);
|
||||
return 1;
|
||||
}
|
||||
@@ -2199,16 +2190,33 @@ probe_date_allows_certupdate(const char* root_anchor_file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ub_result *
|
||||
fetch_root_key(const char* root_anchor_file, const char* res_conf,
|
||||
const char* root_hints, const char* debugconf,
|
||||
int ip4only, int ip6only)
|
||||
{
|
||||
struct ub_ctx* ctx;
|
||||
struct ub_result* dnskey;
|
||||
|
||||
ctx = create_unbound_context(res_conf, root_hints, debugconf,
|
||||
ip4only, ip6only);
|
||||
add_5011_probe_root(ctx, root_anchor_file);
|
||||
dnskey = prime_root_key(ctx);
|
||||
ub_ctx_delete(ctx);
|
||||
return dnskey;
|
||||
}
|
||||
|
||||
/** perform the unbound-anchor work */
|
||||
static int
|
||||
do_root_update_work(const char* root_anchor_file, const char* root_cert_file,
|
||||
const char* urlname, const char* xmlname, const char* p7sname,
|
||||
const char* p7signer, const char* res_conf, const char* root_hints,
|
||||
const char* debugconf, int ip4only, int ip6only, int force, int port)
|
||||
const char* debugconf, int ip4only, int ip6only, int force,
|
||||
int res_conf_fallback, int port)
|
||||
{
|
||||
struct ub_ctx* ctx;
|
||||
struct ub_result* dnskey;
|
||||
int used_builtin = 0;
|
||||
int rcode;
|
||||
|
||||
/* see if builtin rootanchor needs to be provided, or if
|
||||
* rootanchor is 'revoked-trust-point' */
|
||||
@@ -2217,12 +2225,22 @@ do_root_update_work(const char* root_anchor_file, const char* root_cert_file,
|
||||
|
||||
/* make unbound context with 5011-probe for root anchor,
|
||||
* and probe . DNSKEY */
|
||||
ctx = create_unbound_context(res_conf, root_hints, debugconf,
|
||||
ip4only, ip6only);
|
||||
add_5011_probe_root(ctx, root_anchor_file);
|
||||
dnskey = prime_root_key(ctx);
|
||||
ub_ctx_delete(ctx);
|
||||
|
||||
dnskey = fetch_root_key(root_anchor_file, res_conf,
|
||||
root_hints, debugconf, ip4only, ip6only);
|
||||
rcode = dnskey->rcode;
|
||||
|
||||
if (res_conf_fallback && res_conf && !dnskey->secure) {
|
||||
if (verb) printf("%s failed, retrying direct\n", res_conf);
|
||||
ub_resolve_free(dnskey);
|
||||
/* try direct query without res_conf */
|
||||
dnskey = fetch_root_key(root_anchor_file, NULL,
|
||||
root_hints, debugconf, ip4only, ip6only);
|
||||
if (rcode != 0 && dnskey->rcode == 0) {
|
||||
res_conf = NULL;
|
||||
rcode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* if secure: exit */
|
||||
if(dnskey->secure && !force) {
|
||||
if(verb) printf("success: the anchor is ok\n");
|
||||
@@ -2230,18 +2248,18 @@ do_root_update_work(const char* root_anchor_file, const char* root_cert_file,
|
||||
return used_builtin;
|
||||
}
|
||||
if(force && verb) printf("debug cert update forced\n");
|
||||
ub_resolve_free(dnskey);
|
||||
|
||||
/* if not (and NOERROR): check date and do certupdate */
|
||||
if((dnskey->rcode == 0 &&
|
||||
if((rcode == 0 &&
|
||||
probe_date_allows_certupdate(root_anchor_file)) || force) {
|
||||
if(do_certupdate(root_anchor_file, root_cert_file, urlname,
|
||||
xmlname, p7sname, p7signer, res_conf, root_hints,
|
||||
debugconf, ip4only, ip6only, port, dnskey))
|
||||
debugconf, ip4only, ip6only, port))
|
||||
return 1;
|
||||
return used_builtin;
|
||||
}
|
||||
if(verb) printf("fail: the anchor is NOT ok and could not be fixed\n");
|
||||
ub_resolve_free(dnskey);
|
||||
return used_builtin;
|
||||
}
|
||||
|
||||
@@ -2264,8 +2282,9 @@ int main(int argc, char* argv[])
|
||||
const char* root_hints = NULL;
|
||||
const char* debugconf = NULL;
|
||||
int dolist=0, ip4only=0, ip6only=0, force=0, port = HTTPS_PORT;
|
||||
int res_conf_fallback = 0;
|
||||
/* parse the options */
|
||||
while( (c=getopt(argc, argv, "46C:FP:a:c:f:hln:r:s:u:vx:")) != -1) {
|
||||
while( (c=getopt(argc, argv, "46C:FRP:a:c:f:hln:r:s:u:vx:")) != -1) {
|
||||
switch(c) {
|
||||
case 'l':
|
||||
dolist = 1;
|
||||
@@ -2300,6 +2319,9 @@ int main(int argc, char* argv[])
|
||||
case 'r':
|
||||
root_hints = optarg;
|
||||
break;
|
||||
case 'R':
|
||||
res_conf_fallback = 1;
|
||||
break;
|
||||
case 'C':
|
||||
debugconf = optarg;
|
||||
break;
|
||||
@@ -2319,7 +2341,7 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
/* argv += optind; not using further arguments */
|
||||
if(argc != 0)
|
||||
usage();
|
||||
|
||||
@@ -2346,5 +2368,5 @@ int main(int argc, char* argv[])
|
||||
|
||||
return do_root_update_work(root_anchor_file, root_cert_file, urlname,
|
||||
xmlname, p7sname, p7signer, res_conf, root_hints, debugconf,
|
||||
ip4only, ip6only, force, port);
|
||||
ip4only, ip6only, force, res_conf_fallback, port);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <ctype.h>
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/module.h"
|
||||
@@ -252,6 +253,23 @@ aclchecks(struct config_file* cfg)
|
||||
}
|
||||
}
|
||||
|
||||
/** check tcp connection limit ips */
|
||||
static void
|
||||
tcpconnlimitchecks(struct config_file* cfg)
|
||||
{
|
||||
int d;
|
||||
struct sockaddr_storage a;
|
||||
socklen_t alen;
|
||||
struct config_str2list* tcl;
|
||||
for(tcl=cfg->tcp_connection_limits; tcl; tcl = tcl->next) {
|
||||
if(!netblockstrtoaddr(tcl->str, UNBOUND_DNS_PORT, &a, &alen,
|
||||
&d)) {
|
||||
fatal_exit("cannot parse tcp connection limit address %s %s",
|
||||
tcl->str, tcl->str2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** true if fname is a file */
|
||||
static int
|
||||
is_file(const char* fname)
|
||||
@@ -373,6 +391,44 @@ ecs_conf_checks(struct config_file* cfg)
|
||||
}
|
||||
#endif /* CLIENT_SUBNET */
|
||||
|
||||
/** check that the modules exist, are compiled in */
|
||||
static void
|
||||
check_modules_exist(const char* module_conf)
|
||||
{
|
||||
const char** names = module_list_avail();
|
||||
const char* s = module_conf;
|
||||
while(*s) {
|
||||
int i = 0;
|
||||
int is_ok = 0;
|
||||
while(*s && isspace((unsigned char)*s))
|
||||
s++;
|
||||
if(!*s) break;
|
||||
while(names[i]) {
|
||||
if(strncmp(names[i], s, strlen(names[i])) == 0) {
|
||||
is_ok = 1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if(is_ok == 0) {
|
||||
char n[64];
|
||||
size_t j;
|
||||
n[0]=0;
|
||||
n[sizeof(n)-1]=0;
|
||||
for(j=0; j<sizeof(n)-1; j++) {
|
||||
if(!s[j] || isspace((unsigned char)s[j])) {
|
||||
n[j] = 0;
|
||||
break;
|
||||
}
|
||||
n[j] = s[j];
|
||||
}
|
||||
fatal_exit("module_conf lists module '%s' but that "
|
||||
"module is not available.", n);
|
||||
}
|
||||
s += strlen(names[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/** check configuration for errors */
|
||||
static void
|
||||
morechecks(struct config_file* cfg, const char* fname)
|
||||
@@ -381,6 +437,7 @@ morechecks(struct config_file* cfg, const char* fname)
|
||||
warn_hosts("forward-host", cfg->forwards);
|
||||
interfacechecks(cfg);
|
||||
aclchecks(cfg);
|
||||
tcpconnlimitchecks(cfg);
|
||||
|
||||
if(cfg->verbosity < 0)
|
||||
fatal_exit("verbosity value < 0");
|
||||
@@ -465,6 +522,9 @@ morechecks(struct config_file* cfg, const char* fname)
|
||||
free(cfg->chrootdir);
|
||||
cfg->chrootdir = NULL;
|
||||
|
||||
/* check that the modules listed in module_conf exist */
|
||||
check_modules_exist(cfg->module_conf);
|
||||
|
||||
/* There should be no reason for 'respip' module not to work with
|
||||
* dns64, but it's not explicitly confirmed, so the combination is
|
||||
* excluded below. It's simply unknown yet for the combination of
|
||||
@@ -511,7 +571,6 @@ morechecks(struct config_file* cfg, const char* fname)
|
||||
#if defined(WITH_PYTHONMODULE) && defined(CLIENT_SUBNET)
|
||||
&& strcmp(cfg->module_conf, "python subnetcache iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "subnetcache python iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "subnetcache validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "python subnetcache validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "subnetcache python validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "subnetcache validator python iterator") != 0
|
||||
@@ -542,7 +601,8 @@ morechecks(struct config_file* cfg, const char* fname)
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
if(cfg->remote_control_enable && cfg->remote_control_use_cert) {
|
||||
if(cfg->remote_control_enable && options_remote_is_address(cfg)
|
||||
&& cfg->control_use_cert) {
|
||||
check_chroot_string("server-key-file", &cfg->server_key_file,
|
||||
cfg->chrootdir, cfg);
|
||||
check_chroot_string("server-cert-file", &cfg->server_cert_file,
|
||||
|
||||
@@ -148,8 +148,8 @@ test -f $CTL_BASE.pem || error "could not create $CTL_BASE.pem"
|
||||
# echo "empty password is used, simply click OK on the password dialog box."
|
||||
# openssl pkcs12 -export -in $CTL_BASE"_trust.pem" -inkey $CTL_BASE.key -name "unbound remote control client cert" -out $CTL_BASE"_browser.pfx" -password "pass:" || error "could not create browser certificate"
|
||||
|
||||
# remove unused permissions
|
||||
chmod o-rw $SVR_BASE.pem $SVR_BASE.key $CTL_BASE.pem $CTL_BASE.key
|
||||
# set desired permissions
|
||||
chmod 0640 $SVR_BASE.pem $SVR_BASE.key $CTL_BASE.pem $CTL_BASE.key
|
||||
|
||||
# remove crap
|
||||
rm -f request.cfg
|
||||
|
||||
+146
-83
@@ -73,6 +73,10 @@
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
||||
static void usage(void) ATTR_NORETURN;
|
||||
static void ssl_err(const char* s) ATTR_NORETURN;
|
||||
static void ssl_path_err(const char* s, const char *path) ATTR_NORETURN;
|
||||
|
||||
/** Give unbound-control usage, and exit (1). */
|
||||
static void
|
||||
usage(void)
|
||||
@@ -143,11 +147,15 @@ usage(void)
|
||||
printf(" ip_ratelimit_list [+a] list ratelimited ip addresses\n");
|
||||
printf(" +a list all, also not ratelimited\n");
|
||||
printf(" list_auth_zones list auth zones\n");
|
||||
printf(" auth_zone_reload zone reload auth zone from zonefile\n");
|
||||
printf(" auth_zone_transfer zone transfer auth zone from master\n");
|
||||
printf(" view_list_local_zones view list local-zones in view\n");
|
||||
printf(" view_list_local_data view list local-data RRs in view\n");
|
||||
printf(" view_local_zone view name type add local-zone in view\n");
|
||||
printf(" view_local_zone_remove view name remove local-zone in view\n");
|
||||
printf(" view_local_data view RR... add local-data in view\n");
|
||||
printf(" view_local_datas view add list of local-data to view\n");
|
||||
printf(" one entry per line read from stdin\n");
|
||||
printf(" view_local_data_remove view name remove local-data in view\n");
|
||||
printf("Version %s\n", PACKAGE_VERSION);
|
||||
printf("BSD licensed, see LICENSE in source package for details.\n");
|
||||
@@ -319,6 +327,7 @@ static void print_extended(struct ub_stats_info* s)
|
||||
/* transport */
|
||||
PR_UL("num.query.tcp", s->svr.qtcp);
|
||||
PR_UL("num.query.tcpout", s->svr.qtcp_outgoing);
|
||||
PR_UL("num.query.tls", s->svr.qtls);
|
||||
PR_UL("num.query.ipv6", s->svr.qipv6);
|
||||
|
||||
/* flags */
|
||||
@@ -371,6 +380,10 @@ static void print_extended(struct ub_stats_info* s)
|
||||
#endif /* USE_DNSCRYPT */
|
||||
PR_UL("num.query.authzone.up", s->svr.num_query_authzone_up);
|
||||
PR_UL("num.query.authzone.down", s->svr.num_query_authzone_down);
|
||||
#ifdef CLIENT_SUBNET
|
||||
PR_UL("num.query.subnet", s->svr.num_query_subnet);
|
||||
PR_UL("num.query.subnet_cache", s->svr.num_query_subnet_cache);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** print statistics out of memory structures */
|
||||
@@ -444,6 +457,22 @@ static void ssl_err(const char* s)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/** exit with ssl error related to a file path */
|
||||
static void ssl_path_err(const char* s, const char *path)
|
||||
{
|
||||
unsigned long err;
|
||||
err = ERR_peek_error();
|
||||
if (ERR_GET_LIB(err) == ERR_LIB_SYS &&
|
||||
(ERR_GET_FUNC(err) == SYS_F_FOPEN ||
|
||||
ERR_GET_FUNC(err) == SYS_F_FREAD) ) {
|
||||
fprintf(stderr, "error: %s\n%s: %s\n",
|
||||
s, path, ERR_reason_error_string(err));
|
||||
exit(1);
|
||||
} else {
|
||||
ssl_err(s);
|
||||
}
|
||||
}
|
||||
|
||||
/** setup SSL context */
|
||||
static SSL_CTX*
|
||||
setup_ctx(struct config_file* cfg)
|
||||
@@ -451,47 +480,36 @@ setup_ctx(struct config_file* cfg)
|
||||
char* s_cert=NULL, *c_key=NULL, *c_cert=NULL;
|
||||
SSL_CTX* ctx;
|
||||
|
||||
if(cfg->remote_control_use_cert) {
|
||||
s_cert = fname_after_chroot(cfg->server_cert_file, cfg, 1);
|
||||
c_key = fname_after_chroot(cfg->control_key_file, cfg, 1);
|
||||
c_cert = fname_after_chroot(cfg->control_cert_file, cfg, 1);
|
||||
if(!s_cert || !c_key || !c_cert)
|
||||
fatal_exit("out of memory");
|
||||
}
|
||||
if(!(options_remote_is_address(cfg) && cfg->control_use_cert))
|
||||
return NULL;
|
||||
s_cert = fname_after_chroot(cfg->server_cert_file, cfg, 1);
|
||||
c_key = fname_after_chroot(cfg->control_key_file, cfg, 1);
|
||||
c_cert = fname_after_chroot(cfg->control_cert_file, cfg, 1);
|
||||
if(!s_cert || !c_key || !c_cert)
|
||||
fatal_exit("out of memory");
|
||||
ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
if(!ctx)
|
||||
ssl_err("could not allocate SSL_CTX pointer");
|
||||
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
|
||||
!= SSL_OP_NO_SSLv2)
|
||||
ssl_err("could not set SSL_OP_NO_SSLv2");
|
||||
if(cfg->remote_control_use_cert) {
|
||||
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
|
||||
!= SSL_OP_NO_SSLv3)
|
||||
ssl_err("could not set SSL_OP_NO_SSLv3");
|
||||
if(!SSL_CTX_use_certificate_chain_file(ctx,c_cert) ||
|
||||
!SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM)
|
||||
|| !SSL_CTX_check_private_key(ctx))
|
||||
ssl_err("Error setting up SSL_CTX client key and cert");
|
||||
if (SSL_CTX_load_verify_locations(ctx, s_cert, NULL) != 1)
|
||||
ssl_err("Error setting up SSL_CTX verify, server cert");
|
||||
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
|
||||
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
|
||||
!= SSL_OP_NO_SSLv3)
|
||||
ssl_err("could not set SSL_OP_NO_SSLv3");
|
||||
if(!SSL_CTX_use_certificate_chain_file(ctx,c_cert))
|
||||
ssl_path_err("Error setting up SSL_CTX client cert", c_cert);
|
||||
if (!SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM))
|
||||
ssl_path_err("Error setting up SSL_CTX client key", c_key);
|
||||
if (!SSL_CTX_check_private_key(ctx))
|
||||
ssl_err("Error setting up SSL_CTX client key");
|
||||
if (SSL_CTX_load_verify_locations(ctx, s_cert, NULL) != 1)
|
||||
ssl_path_err("Error setting up SSL_CTX verify, server cert",
|
||||
s_cert);
|
||||
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
|
||||
|
||||
free(s_cert);
|
||||
free(c_key);
|
||||
free(c_cert);
|
||||
} else {
|
||||
/* Use ciphers that don't require authentication */
|
||||
#if defined(SSL_OP_NO_TLSv1_3)
|
||||
/* in openssl 1.1.1, negotiation code for tls 1.3 does
|
||||
* not allow the unauthenticated aNULL and eNULL ciphers */
|
||||
SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_3);
|
||||
#endif
|
||||
#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
|
||||
SSL_CTX_set_security_level(ctx, 0);
|
||||
#endif
|
||||
if(!SSL_CTX_set_cipher_list(ctx, "aNULL:eNULL"))
|
||||
ssl_err("Error setting NULL cipher!");
|
||||
}
|
||||
free(s_cert);
|
||||
free(c_key);
|
||||
free(c_cert);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
@@ -501,12 +519,12 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen;
|
||||
int addrfamily = 0;
|
||||
int fd;
|
||||
int addrfamily = 0, proto = IPPROTO_TCP;
|
||||
int fd, useport = 1;
|
||||
/* use svr or the first config entry */
|
||||
if(!svr) {
|
||||
if(cfg->control_ifs) {
|
||||
svr = cfg->control_ifs->str;
|
||||
if(cfg->control_ifs.first) {
|
||||
svr = cfg->control_ifs.first->str;
|
||||
} else if(cfg->do_ip4) {
|
||||
svr = "127.0.0.1";
|
||||
} else {
|
||||
@@ -534,6 +552,8 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
|
||||
(void)strlcpy(usock->sun_path, svr, sizeof(usock->sun_path));
|
||||
addrlen = (socklen_t)sizeof(struct sockaddr_un);
|
||||
addrfamily = AF_LOCAL;
|
||||
useport = 0;
|
||||
proto = 0;
|
||||
#endif
|
||||
} else {
|
||||
if(!ipstrtoaddr(svr, cfg->control_port, &addr, &addrlen))
|
||||
@@ -541,8 +561,8 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
|
||||
}
|
||||
|
||||
if(addrfamily == 0)
|
||||
addrfamily = addr_is_ip6(&addr, addrlen)?AF_INET6:AF_INET;
|
||||
fd = socket(addrfamily, SOCK_STREAM, 0);
|
||||
addrfamily = addr_is_ip6(&addr, addrlen)?PF_INET6:PF_INET;
|
||||
fd = socket(addrfamily, SOCK_STREAM, proto);
|
||||
if(fd == -1) {
|
||||
#ifndef USE_WINSOCK
|
||||
fatal_exit("socket: %s", strerror(errno));
|
||||
@@ -552,14 +572,18 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
|
||||
}
|
||||
if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) {
|
||||
#ifndef USE_WINSOCK
|
||||
log_err_addr("connect", strerror(errno), &addr, addrlen);
|
||||
if(errno == ECONNREFUSED && statuscmd) {
|
||||
int err = errno;
|
||||
if(!useport) log_err("connect: %s for %s", strerror(err), svr);
|
||||
else log_err_addr("connect", strerror(err), &addr, addrlen);
|
||||
if(err == ECONNREFUSED && statuscmd) {
|
||||
printf("unbound is stopped\n");
|
||||
exit(3);
|
||||
}
|
||||
#else
|
||||
log_err_addr("connect", wsa_strerror(WSAGetLastError()), &addr, addrlen);
|
||||
if(WSAGetLastError() == WSAECONNREFUSED && statuscmd) {
|
||||
int wsaerr = WSAGetLastError();
|
||||
if(!useport) log_err("connect: %s for %s", wsa_strerror(wsaerr), svr);
|
||||
else log_err_addr("connect", wsa_strerror(wsaerr), &addr, addrlen);
|
||||
if(wsaerr == WSAECONNREFUSED && statuscmd) {
|
||||
printf("unbound is stopped\n");
|
||||
exit(3);
|
||||
}
|
||||
@@ -571,12 +595,13 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
|
||||
|
||||
/** setup SSL on the connection */
|
||||
static SSL*
|
||||
setup_ssl(SSL_CTX* ctx, int fd, struct config_file* cfg)
|
||||
setup_ssl(SSL_CTX* ctx, int fd)
|
||||
{
|
||||
SSL* ssl;
|
||||
X509* x;
|
||||
int r;
|
||||
|
||||
if(!ctx) return NULL;
|
||||
ssl = SSL_new(ctx);
|
||||
if(!ssl)
|
||||
ssl_err("could not SSL_new");
|
||||
@@ -597,78 +622,116 @@ setup_ssl(SSL_CTX* ctx, int fd, struct config_file* cfg)
|
||||
/* check authenticity of server */
|
||||
if(SSL_get_verify_result(ssl) != X509_V_OK)
|
||||
ssl_err("SSL verification failed");
|
||||
if(cfg->remote_control_use_cert) {
|
||||
x = SSL_get_peer_certificate(ssl);
|
||||
if(!x)
|
||||
ssl_err("Server presented no peer certificate");
|
||||
X509_free(x);
|
||||
}
|
||||
x = SSL_get_peer_certificate(ssl);
|
||||
if(!x)
|
||||
ssl_err("Server presented no peer certificate");
|
||||
X509_free(x);
|
||||
|
||||
return ssl;
|
||||
}
|
||||
|
||||
/** read from ssl or fd, fatalexit on error, 0 EOF, 1 success */
|
||||
static int
|
||||
remote_read(SSL* ssl, int fd, char* buf, size_t len)
|
||||
{
|
||||
if(ssl) {
|
||||
int r;
|
||||
ERR_clear_error();
|
||||
if((r = SSL_read(ssl, buf, (int)len-1)) <= 0) {
|
||||
if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) {
|
||||
/* EOF */
|
||||
return 0;
|
||||
}
|
||||
ssl_err("could not SSL_read");
|
||||
}
|
||||
buf[r] = 0;
|
||||
} else {
|
||||
ssize_t rr = recv(fd, buf, len-1, 0);
|
||||
if(rr <= 0) {
|
||||
if(rr == 0) {
|
||||
/* EOF */
|
||||
return 0;
|
||||
}
|
||||
#ifndef USE_WINSOCK
|
||||
fatal_exit("could not recv: %s", strerror(errno));
|
||||
#else
|
||||
fatal_exit("could not recv: %s", wsa_strerror(WSAGetLastError()));
|
||||
#endif
|
||||
}
|
||||
buf[rr] = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** write to ssl or fd, fatalexit on error */
|
||||
static void
|
||||
remote_write(SSL* ssl, int fd, const char* buf, size_t len)
|
||||
{
|
||||
if(ssl) {
|
||||
if(SSL_write(ssl, buf, (int)len) <= 0)
|
||||
ssl_err("could not SSL_write");
|
||||
} else {
|
||||
if(send(fd, buf, len, 0) < (ssize_t)len) {
|
||||
#ifndef USE_WINSOCK
|
||||
fatal_exit("could not send: %s", strerror(errno));
|
||||
#else
|
||||
fatal_exit("could not send: %s", wsa_strerror(WSAGetLastError()));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** send stdin to server */
|
||||
static void
|
||||
send_file(SSL* ssl, FILE* in, char* buf, size_t sz)
|
||||
send_file(SSL* ssl, int fd, FILE* in, char* buf, size_t sz)
|
||||
{
|
||||
while(fgets(buf, (int)sz, in)) {
|
||||
if(SSL_write(ssl, buf, (int)strlen(buf)) <= 0)
|
||||
ssl_err("could not SSL_write contents");
|
||||
remote_write(ssl, fd, buf, strlen(buf));
|
||||
}
|
||||
}
|
||||
|
||||
/** send end-of-file marker to server */
|
||||
static void
|
||||
send_eof(SSL* ssl)
|
||||
send_eof(SSL* ssl, int fd)
|
||||
{
|
||||
char e[] = {0x04, 0x0a};
|
||||
if(SSL_write(ssl, e, (int)sizeof(e)) <= 0)
|
||||
ssl_err("could not SSL_write end-of-file marker");
|
||||
remote_write(ssl, fd, e, sizeof(e));
|
||||
}
|
||||
|
||||
/** send command and display result */
|
||||
static int
|
||||
go_cmd(SSL* ssl, int quiet, int argc, char* argv[])
|
||||
go_cmd(SSL* ssl, int fd, int quiet, int argc, char* argv[])
|
||||
{
|
||||
char pre[10];
|
||||
const char* space=" ";
|
||||
const char* newline="\n";
|
||||
int was_error = 0, first_line = 1;
|
||||
int r, i;
|
||||
int i;
|
||||
char buf[1024];
|
||||
snprintf(pre, sizeof(pre), "UBCT%d ", UNBOUND_CONTROL_VERSION);
|
||||
if(SSL_write(ssl, pre, (int)strlen(pre)) <= 0)
|
||||
ssl_err("could not SSL_write");
|
||||
remote_write(ssl, fd, pre, strlen(pre));
|
||||
for(i=0; i<argc; i++) {
|
||||
if(SSL_write(ssl, space, (int)strlen(space)) <= 0)
|
||||
ssl_err("could not SSL_write");
|
||||
if(SSL_write(ssl, argv[i], (int)strlen(argv[i])) <= 0)
|
||||
ssl_err("could not SSL_write");
|
||||
remote_write(ssl, fd, space, strlen(space));
|
||||
remote_write(ssl, fd, argv[i], strlen(argv[i]));
|
||||
}
|
||||
if(SSL_write(ssl, newline, (int)strlen(newline)) <= 0)
|
||||
ssl_err("could not SSL_write");
|
||||
remote_write(ssl, fd, newline, strlen(newline));
|
||||
|
||||
if(argc == 1 && strcmp(argv[0], "load_cache") == 0) {
|
||||
send_file(ssl, stdin, buf, sizeof(buf));
|
||||
send_file(ssl, fd, stdin, buf, sizeof(buf));
|
||||
}
|
||||
else if(argc == 1 && (strcmp(argv[0], "local_zones") == 0 ||
|
||||
else if(argc >= 1 && (strcmp(argv[0], "local_zones") == 0 ||
|
||||
strcmp(argv[0], "local_zones_remove") == 0 ||
|
||||
strcmp(argv[0], "local_datas") == 0 ||
|
||||
strcmp(argv[0], "view_local_datas") == 0 ||
|
||||
strcmp(argv[0], "local_datas_remove") == 0)) {
|
||||
send_file(ssl, stdin, buf, sizeof(buf));
|
||||
send_eof(ssl);
|
||||
send_file(ssl, fd, stdin, buf, sizeof(buf));
|
||||
send_eof(ssl, fd);
|
||||
}
|
||||
|
||||
while(1) {
|
||||
ERR_clear_error();
|
||||
if((r = SSL_read(ssl, buf, (int)sizeof(buf)-1)) <= 0) {
|
||||
if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) {
|
||||
/* EOF */
|
||||
break;
|
||||
}
|
||||
ssl_err("could not SSL_read");
|
||||
if(remote_read(ssl, fd, buf, sizeof(buf)) == 0) {
|
||||
break; /* EOF */
|
||||
}
|
||||
buf[r] = 0;
|
||||
if(first_line && strncmp(buf, "error", 5) == 0) {
|
||||
printf("%s", buf);
|
||||
was_error = 1;
|
||||
@@ -703,18 +766,18 @@ go(const char* cfgfile, char* svr, int quiet, int argc, char* argv[])
|
||||
|
||||
/* contact server */
|
||||
fd = contact_server(svr, cfg, argc>0&&strcmp(argv[0],"status")==0);
|
||||
ssl = setup_ssl(ctx, fd, cfg);
|
||||
ssl = setup_ssl(ctx, fd);
|
||||
|
||||
/* send command */
|
||||
ret = go_cmd(ssl, quiet, argc, argv);
|
||||
ret = go_cmd(ssl, fd, quiet, argc, argv);
|
||||
|
||||
SSL_free(ssl);
|
||||
if(ssl) SSL_free(ssl);
|
||||
#ifndef USE_WINSOCK
|
||||
close(fd);
|
||||
#else
|
||||
closesocket(fd);
|
||||
#endif
|
||||
SSL_CTX_free(ctx);
|
||||
if(ctx) SSL_CTX_free(ctx);
|
||||
config_delete(cfg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+33
-3
@@ -66,6 +66,14 @@
|
||||
/* nss3 */
|
||||
#include "nss.h"
|
||||
#endif
|
||||
#ifdef HAVE_SSL
|
||||
#ifdef HAVE_OPENSSL_SSL_H
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
/** verbosity for unbound-host app */
|
||||
static int verb = 0;
|
||||
@@ -74,9 +82,8 @@ static int verb = 0;
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage: unbound-host [-vdhr46] [-c class] [-t type] hostname\n");
|
||||
printf(" [-y key] [-f keyfile] [-F namedkeyfile]\n");
|
||||
printf(" [-C configfile]\n");
|
||||
printf("Usage: unbound-host [-C configfile] [-vdhr46] [-c class] [-t type]\n");
|
||||
printf(" [-y key] [-f keyfile] [-F namedkeyfile] hostname\n");
|
||||
printf(" Queries the DNS for information.\n");
|
||||
printf(" The hostname is looked up for IP4, IP6 and mail.\n");
|
||||
printf(" If an ip-address is given a reverse lookup is done.\n");
|
||||
@@ -90,6 +97,8 @@ usage(void)
|
||||
printf(" -f keyfile read trust anchors from file, with lines as -y.\n");
|
||||
printf(" -F keyfile read named.conf-style trust anchors.\n");
|
||||
printf(" -C config use the specified unbound.conf (none read by default)\n");
|
||||
printf(" pass as first argument if you want to override some\n");
|
||||
printf(" options with further arguments\n");
|
||||
printf(" -r read forwarder information from /etc/resolv.conf\n");
|
||||
printf(" breaks validation if the forwarder does not do DNSSEC.\n");
|
||||
printf(" -v be more verbose, shows nodata and security.\n");
|
||||
@@ -331,6 +340,7 @@ pretty_output(char* q, int t, int c, struct ub_result* result, int docname)
|
||||
exit(1);
|
||||
}
|
||||
printf("%s\n", s);
|
||||
free(s);
|
||||
} else printf(" has no %s record", tstr);
|
||||
printf(" %s\n", secstatus);
|
||||
}
|
||||
@@ -487,6 +497,26 @@ int main(int argc, char* argv[])
|
||||
if(argc != 1)
|
||||
usage();
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
#ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
|
||||
ERR_load_crypto_strings();
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
ERR_load_SSL_strings();
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
|
||||
OpenSSL_add_all_algorithms();
|
||||
#else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
#else
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||
#endif
|
||||
#endif /* HAVE_SSL */
|
||||
#ifdef HAVE_NSS
|
||||
if(NSS_NoDB_Init(".") != SECSuccess) {
|
||||
fprintf(stderr, "could not init NSS\n");
|
||||
|
||||
@@ -168,21 +168,21 @@ void libworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube),
|
||||
|
||||
void libworker_fg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
|
||||
struct sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s),
|
||||
char* ATTR_UNUSED(why_bogus))
|
||||
char* ATTR_UNUSED(why_bogus), int ATTR_UNUSED(was_ratelimited))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void libworker_bg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
|
||||
struct sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s),
|
||||
char* ATTR_UNUSED(why_bogus))
|
||||
char* ATTR_UNUSED(why_bogus), int ATTR_UNUSED(was_ratelimited))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void libworker_event_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
|
||||
struct sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s),
|
||||
char* ATTR_UNUSED(why_bogus))
|
||||
char* ATTR_UNUSED(why_bogus), int ATTR_UNUSED(was_ratelimited))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
+44
-8
@@ -56,6 +56,15 @@
|
||||
#undef free
|
||||
#undef strdup
|
||||
#endif
|
||||
#ifdef HAVE_SSL
|
||||
#ifdef HAVE_OPENSSL_SSL_H
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
|
||||
/** keeping track of the async ids */
|
||||
struct track_id {
|
||||
@@ -173,6 +182,8 @@ struct ext_thr_info {
|
||||
char** argv;
|
||||
/** number of queries to do */
|
||||
int numq;
|
||||
/** list of ids to free once threads are done */
|
||||
struct track_id* id_list;
|
||||
};
|
||||
|
||||
/** if true, we are testing against 'localhost' and extra checking is done */
|
||||
@@ -300,6 +311,7 @@ ext_thread(void* arg)
|
||||
for(i=0; i<inf->numq; i++) {
|
||||
lock_basic_init(&async_ids[i].lock);
|
||||
}
|
||||
inf->id_list = async_ids;
|
||||
}
|
||||
for(i=0; i<inf->numq; i++) {
|
||||
if(async_ids) {
|
||||
@@ -338,14 +350,6 @@ ext_thread(void* arg)
|
||||
/* if these locks are destroyed, or if the async_ids is freed, then
|
||||
a use-after-free happens in another thread.
|
||||
The allocation is only part of this test, though. */
|
||||
/*
|
||||
if(async_ids) {
|
||||
for(i=0; i<inf->numq; i++) {
|
||||
lock_basic_destroy(&async_ids[i].lock);
|
||||
}
|
||||
}
|
||||
free(async_ids);
|
||||
*/
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -366,6 +370,7 @@ ext_test(struct ub_ctx* ctx, int argc, char** argv)
|
||||
inf[i].argc = argc;
|
||||
inf[i].argv = argv;
|
||||
inf[i].numq = 100;
|
||||
inf[i].id_list = NULL;
|
||||
ub_thread_create(&inf[i].tid, ext_thread, &inf[i]);
|
||||
}
|
||||
/* the work happens here */
|
||||
@@ -373,6 +378,16 @@ ext_test(struct ub_ctx* ctx, int argc, char** argv)
|
||||
ub_thread_join(inf[i].tid);
|
||||
}
|
||||
printf("extended test end\n");
|
||||
/* free the id lists */
|
||||
for(i=0; i<NUMTHR; i++) {
|
||||
if(inf[i].id_list) {
|
||||
int j;
|
||||
for(j=0; j<inf[i].numq; j++) {
|
||||
lock_basic_destroy(&inf[i].id_list[j].lock);
|
||||
}
|
||||
free(inf[i].id_list);
|
||||
}
|
||||
}
|
||||
ub_ctx_delete(ctx);
|
||||
checklock_stop();
|
||||
return 0;
|
||||
@@ -459,6 +474,27 @@ int main(int argc, char** argv)
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
#ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
|
||||
ERR_load_crypto_strings();
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
ERR_load_SSL_strings();
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
|
||||
OpenSSL_add_all_algorithms();
|
||||
#else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
#else
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||
#endif
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
if(ext)
|
||||
return ext_test(ctx, argc, argv);
|
||||
|
||||
|
||||
@@ -71,6 +71,9 @@ static pid_t check_lock_pid;
|
||||
|
||||
/** print all possible debug info on the state of the system */
|
||||
static void total_debug_info(void);
|
||||
/** print pretty lock error and exit (decl for NORETURN attribute) */
|
||||
static void lock_error(struct checked_lock* lock, const char* func,
|
||||
const char* file, int line, const char* err) ATTR_NORETURN;
|
||||
|
||||
/** print pretty lock error and exit */
|
||||
static void lock_error(struct checked_lock* lock,
|
||||
|
||||
+1
-1
@@ -788,7 +788,7 @@ service_tcp_relay(struct tcp_proxy** tcp_proxies, struct timeval* now,
|
||||
if(!tcp_relay_write(p->server_s, &p->querylist,
|
||||
&p->querylast, now))
|
||||
delete_it = 1;
|
||||
if(p->querylist && p->server_s != -1 &&
|
||||
if(p->querylist &&
|
||||
dl_tv_smaller(&p->querylist->wait, now))
|
||||
FD_SET(FD_SET_T p->server_s, worig);
|
||||
else FD_CLR(FD_SET_T p->server_s, worig);
|
||||
|
||||
+20
-7
@@ -374,8 +374,11 @@ answer_callback_from_entry(struct replay_runtime* runtime,
|
||||
c.fd = -1;
|
||||
c.buffer = sldns_buffer_new(runtime->bufsize);
|
||||
c.type = comm_udp;
|
||||
if(pend->transport == transport_tcp)
|
||||
if(pend->transport == transport_tcp) {
|
||||
c.type = comm_tcp;
|
||||
c.tcp_timeout_msec = 30000;
|
||||
c.tcp_keepalive = runtime->tcp_seen_keepalive;
|
||||
}
|
||||
fill_buffer_with_reply(c.buffer, entry, pend->pkt, pend->pkt_len,
|
||||
pend->tcp_pkt_counter);
|
||||
repinfo.c = &c;
|
||||
@@ -423,6 +426,8 @@ answer_check_it(struct replay_runtime* runtime)
|
||||
else runtime->answer_list = ans->next;
|
||||
if(!ans->next)
|
||||
runtime->answer_last = prev;
|
||||
if(ans->repinfo.c->tcp_keepalive)
|
||||
runtime->tcp_seen_keepalive = 1;
|
||||
delete_replay_answer(ans);
|
||||
return;
|
||||
} else {
|
||||
@@ -452,9 +457,12 @@ fake_front_query(struct replay_runtime* runtime, struct replay_moment *todo)
|
||||
repinfo.c->fd = -1;
|
||||
repinfo.c->ev = (struct internal_event*)runtime;
|
||||
repinfo.c->buffer = sldns_buffer_new(runtime->bufsize);
|
||||
if(todo->match->match_transport == transport_tcp)
|
||||
if(todo->match->match_transport == transport_tcp) {
|
||||
repinfo.c->type = comm_tcp;
|
||||
else repinfo.c->type = comm_udp;
|
||||
repinfo.c->tcp_timeout_msec = 30000;
|
||||
repinfo.c->tcp_keepalive = runtime->tcp_seen_keepalive;
|
||||
} else
|
||||
repinfo.c->type = comm_udp;
|
||||
fill_buffer_with_reply(repinfo.c->buffer, todo->match, NULL, 0, 0);
|
||||
log_info("testbound: incoming QUERY");
|
||||
log_pkt("query pkt", todo->match->reply_list->reply_pkt,
|
||||
@@ -488,8 +496,11 @@ fake_pending_callback(struct replay_runtime* runtime,
|
||||
cb = p->callback;
|
||||
c.buffer = sldns_buffer_new(runtime->bufsize);
|
||||
c.type = comm_udp;
|
||||
if(p->transport == transport_tcp)
|
||||
if(p->transport == transport_tcp) {
|
||||
c.type = comm_tcp;
|
||||
c.tcp_timeout_msec = 30000;
|
||||
c.tcp_keepalive = runtime->tcp_seen_keepalive;
|
||||
}
|
||||
if(todo->evt_type == repevt_back_reply && todo->match) {
|
||||
fill_buffer_with_reply(c.buffer, todo->match, p->pkt,
|
||||
p->pkt_len, p->tcp_pkt_counter);
|
||||
@@ -856,6 +867,8 @@ 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),
|
||||
int ATTR_UNUSED(tcp_idle_timeout),
|
||||
struct tcl_list* ATTR_UNUSED(tcp_conn_limit),
|
||||
void* ATTR_UNUSED(sslctx), struct dt_env* ATTR_UNUSED(dtenv),
|
||||
comm_point_callback_type* cb, void* cb_arg)
|
||||
{
|
||||
@@ -1125,7 +1138,7 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet,
|
||||
pend->addrlen = sq->addrlen;
|
||||
pend->callback = callback;
|
||||
pend->cb_arg = callback_arg;
|
||||
pend->timeout = timeout;
|
||||
pend->timeout = timeout/1000;
|
||||
pend->transport = transport_tcp;
|
||||
pend->pkt = NULL;
|
||||
pend->zone = NULL;
|
||||
@@ -1218,7 +1231,7 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
log_assert(pend->zone);
|
||||
pend->callback = callback;
|
||||
pend->cb_arg = callback_arg;
|
||||
pend->timeout = UDP_AUTH_QUERY_TIMEOUT;
|
||||
pend->timeout = UDP_AUTH_QUERY_TIMEOUT/1000;
|
||||
pend->transport = transport_udp; /* pretend UDP */
|
||||
pend->pkt = NULL;
|
||||
pend->runtime = runtime;
|
||||
@@ -1757,7 +1770,7 @@ int comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
|
||||
}
|
||||
pend->callback = fc->cb;
|
||||
pend->cb_arg = fc->cb_arg;
|
||||
pend->timeout = UDP_AUTH_QUERY_TIMEOUT;
|
||||
pend->timeout = UDP_AUTH_QUERY_TIMEOUT/1000;
|
||||
pend->transport = transport_udp;
|
||||
pend->pkt = NULL;
|
||||
pend->runtime = runtime;
|
||||
|
||||
+3
-3
@@ -610,7 +610,7 @@ int main(int argc, char* argv[])
|
||||
case 'd':
|
||||
if(atoi(optarg)==0 && strcmp(optarg, "0")!=0) {
|
||||
printf("-d not a number %s", optarg);
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
info.duration = atoi(optarg);
|
||||
break;
|
||||
@@ -635,11 +635,11 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
if(!extstrtoaddr(argv[0], &info.dest, &info.destlen)) {
|
||||
printf("Could not parse ip: %s\n", argv[0]);
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
if(info.qlist_size == 0) {
|
||||
printf("No queries to make, use -f or -a.\n");
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* do the performance test */
|
||||
|
||||
+6
-4
@@ -417,7 +417,7 @@ provide_file_10(SSL* ssl, char* fname)
|
||||
}
|
||||
fclose(in);
|
||||
at += len;
|
||||
avail -= len;
|
||||
/* avail -= len; unused */
|
||||
if(SSL_write(ssl, buf, at-buf) <= 0) {
|
||||
/* write failure */
|
||||
}
|
||||
@@ -506,7 +506,7 @@ provide_file_chunked(SSL* ssl, char* fname)
|
||||
snprintf(at, avail, "\r\n");
|
||||
r = strlen(at);
|
||||
at += r;
|
||||
avail -= r;
|
||||
/* avail -= r; unused */
|
||||
}
|
||||
/* send chunk */
|
||||
if(SSL_write(ssl, buf, at-buf) <= 0) {
|
||||
@@ -569,7 +569,9 @@ do_service(char* addr, int port, char* key, char* cert)
|
||||
while(go) {
|
||||
struct sockaddr_storage from;
|
||||
socklen_t flen = (socklen_t)sizeof(from);
|
||||
int s = accept(fd, (struct sockaddr*)&from, &flen);
|
||||
int s;
|
||||
memset(&from, 0, sizeof(from));
|
||||
s = accept(fd, (struct sockaddr*)&from, &flen);
|
||||
if(verb) fflush(stdout);
|
||||
if(s != -1) {
|
||||
SSL* ssl = setup_ssl(s, sslctx);
|
||||
@@ -633,7 +635,7 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
/* argv += optind; not using further arguments */
|
||||
if(argc != 0)
|
||||
usage();
|
||||
|
||||
|
||||
+11
-4
@@ -458,6 +458,8 @@ replay_scenario_read(FILE* in, const char* name, int* lineno)
|
||||
if(parse_keyword(&parse, ";"))
|
||||
continue; /* comment */
|
||||
if(parse_keyword(&parse, "SCENARIO_BEGIN")) {
|
||||
if(scen)
|
||||
fatal_exit("%d: double SCENARIO_BEGIN", *lineno);
|
||||
scen = make_scenario(parse);
|
||||
if(!scen)
|
||||
fatal_exit("%d: could not make scen", *lineno);
|
||||
@@ -801,14 +803,19 @@ macro_expand(rbtree_type* store, struct replay_runtime* runtime, char** text)
|
||||
|
||||
/* check for functions */
|
||||
if(strcmp(buf, "time") == 0) {
|
||||
snprintf(buf, sizeof(buf), ARG_LL "d", (long long)runtime->now_secs);
|
||||
if(runtime)
|
||||
snprintf(buf, sizeof(buf), ARG_LL "d", (long long)runtime->now_secs);
|
||||
else
|
||||
snprintf(buf, sizeof(buf), ARG_LL "d", (long long)0);
|
||||
*text += len;
|
||||
return strdup(buf);
|
||||
} else if(strcmp(buf, "timeout") == 0) {
|
||||
time_t res = 0;
|
||||
struct fake_timer* t = first_timer(runtime);
|
||||
if(t && (time_t)t->tv.tv_sec >= runtime->now_secs)
|
||||
res = (time_t)t->tv.tv_sec - runtime->now_secs;
|
||||
if(runtime) {
|
||||
struct fake_timer* t = first_timer(runtime);
|
||||
if(t && (time_t)t->tv.tv_sec >= runtime->now_secs)
|
||||
res = (time_t)t->tv.tv_sec - runtime->now_secs;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), ARG_LL "d", (long long)res);
|
||||
*text += len;
|
||||
return strdup(buf);
|
||||
|
||||
@@ -303,6 +303,9 @@ struct replay_runtime {
|
||||
/** the current time in microseconds */
|
||||
struct timeval now_tv;
|
||||
|
||||
/** has TCP connection seen a keepalive? */
|
||||
int tcp_seen_keepalive;
|
||||
|
||||
/** signal handler callback */
|
||||
void (*sig_cb)(int, void*);
|
||||
/** signal handler user arg */
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
.RB [ \-unsh ]
|
||||
.RB [ \-f
|
||||
.IR ipaddr[@port] ]
|
||||
.RB [ \-d
|
||||
.IR secs ]
|
||||
.I name
|
||||
.I type
|
||||
.I class
|
||||
@@ -50,6 +52,10 @@ Print program usage.
|
||||
.TP
|
||||
.B \-f \fIipaddr[@port]
|
||||
Specify the server to send the queries to. If not specified localhost (127.0.0.1) is used.
|
||||
.TP
|
||||
.B \-d \fIsecs
|
||||
Delay after the connection before sending query. This tests the timeout
|
||||
on the other side, eg. if shorter the connection is closed.
|
||||
.SH "EXAMPLES"
|
||||
.LP
|
||||
Some examples of use.
|
||||
|
||||
+24
-4
@@ -44,6 +44,8 @@
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "util/locks.h"
|
||||
#include "util/log.h"
|
||||
#include "util/net_help.h"
|
||||
@@ -71,6 +73,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("-d secs delay after connection before sending query\n");
|
||||
printf("-s use ssl\n");
|
||||
printf("-h this help text\n");
|
||||
exit(1);
|
||||
@@ -275,7 +278,8 @@ static int get_random(void)
|
||||
|
||||
/** send the TCP queries and print answers */
|
||||
static void
|
||||
send_em(const char* svr, int udp, int usessl, int noanswer, int num, char** qs)
|
||||
send_em(const char* svr, int udp, int usessl, int noanswer, int delay,
|
||||
int num, char** qs)
|
||||
{
|
||||
sldns_buffer* buf = sldns_buffer_new(65553);
|
||||
int fd = open_svr(svr, udp);
|
||||
@@ -284,7 +288,7 @@ send_em(const char* svr, int udp, int usessl, int noanswer, int num, char** qs)
|
||||
SSL* ssl = NULL;
|
||||
if(!buf) fatal_exit("out of memory");
|
||||
if(usessl) {
|
||||
ctx = connect_sslctx_create(NULL, NULL, NULL);
|
||||
ctx = connect_sslctx_create(NULL, NULL, NULL, 0);
|
||||
if(!ctx) fatal_exit("cannot create ssl ctx");
|
||||
ssl = outgoing_ssl_fd(ctx, fd);
|
||||
if(!ssl) fatal_exit("cannot create ssl");
|
||||
@@ -310,6 +314,13 @@ send_em(const char* svr, int udp, int usessl, int noanswer, int num, char** qs)
|
||||
}
|
||||
}
|
||||
for(i=0; i<num; i+=3) {
|
||||
if (delay != 0) {
|
||||
#ifdef HAVE_SLEEP
|
||||
sleep((unsigned)delay);
|
||||
#else
|
||||
Sleep(delay*1000);
|
||||
#endif
|
||||
}
|
||||
printf("\nNext query is %s %s %s\n", qs[i], qs[i+1], qs[i+2]);
|
||||
write_q(fd, udp, ssl, buf, (uint16_t)get_random(), qs[i],
|
||||
qs[i+1], qs[i+2]);
|
||||
@@ -358,6 +369,7 @@ int main(int argc, char** argv)
|
||||
int udp = 0;
|
||||
int noanswer = 0;
|
||||
int usessl = 0;
|
||||
int delay = 0;
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
WSADATA wsa_data;
|
||||
@@ -382,7 +394,7 @@ int main(int argc, char** argv)
|
||||
if(argc == 1) {
|
||||
usage(argv);
|
||||
}
|
||||
while( (c=getopt(argc, argv, "f:hnsu")) != -1) {
|
||||
while( (c=getopt(argc, argv, "f:hnsud:")) != -1) {
|
||||
switch(c) {
|
||||
case 'f':
|
||||
svr = optarg;
|
||||
@@ -396,6 +408,14 @@ int main(int argc, char** argv)
|
||||
case 's':
|
||||
usessl = 1;
|
||||
break;
|
||||
case 'd':
|
||||
if(atoi(optarg)==0 && strcmp(optarg,"0")!=0) {
|
||||
printf("error parsing delay, "
|
||||
"number expected: %s\n", optarg);
|
||||
return 1;
|
||||
}
|
||||
delay = atoi(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
@@ -426,7 +446,7 @@ int main(int argc, char** argv)
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||
#endif
|
||||
}
|
||||
send_em(svr, udp, usessl, noanswer, argc, argv);
|
||||
send_em(svr, udp, usessl, noanswer, delay, argc, argv);
|
||||
checklock_stop();
|
||||
#ifdef USE_WINSOCK
|
||||
WSACleanup();
|
||||
|
||||
@@ -177,7 +177,8 @@ spool_temp_file(FILE* in, int* lineno, char* id)
|
||||
while(isspace((unsigned char)*parse))
|
||||
parse++;
|
||||
if(strncmp(parse, "$INCLUDE_TEMPFILE", 17) == 0) {
|
||||
char l2[MAX_LINE_LEN];
|
||||
char l2[MAX_LINE_LEN-30]; /* -30 makes it fit with
|
||||
a preceding $INCLUDE in the buf line[] */
|
||||
char* tid = parse+17;
|
||||
while(isspace((unsigned char)*tid))
|
||||
tid++;
|
||||
@@ -428,14 +429,14 @@ main(int argc, char* argv[])
|
||||
case 'h':
|
||||
default:
|
||||
testbound_usage();
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
/* argv += optind; not using further arguments */
|
||||
if(argc != 0) {
|
||||
testbound_usage();
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
log_info("Start of %s testbound program.", PACKAGE_STRING);
|
||||
if(atexit(&remove_configfile) != 0)
|
||||
|
||||
@@ -46,6 +46,7 @@ enum verbosity_value { NO_VERBOSE=0 };
|
||||
#endif
|
||||
/** logging routine, provided by caller */
|
||||
void verbose(enum verbosity_value lvl, const char* msg, ...) ATTR_FORMAT(printf, 2, 3);
|
||||
static void error(const char* msg, ...) ATTR_NORETURN;
|
||||
|
||||
/** print error and exit */
|
||||
static void error(const char* msg, ...)
|
||||
@@ -235,6 +236,8 @@ static void adjustline(char* line, struct entry* e,
|
||||
e->copy_query = 1;
|
||||
} else if(str_keyword(&parse, "copy_ednsdata_assume_clientsubnet")) {
|
||||
e->copy_ednsdata_assume_clientsubnet = 1;
|
||||
} else if(str_keyword(&parse, "increment_ecs_scope")) {
|
||||
e->increment_ecs_scope = 1;
|
||||
} else if(str_keyword(&parse, "sleep=")) {
|
||||
e->sleeptime = (unsigned int) strtol(parse, (char**)&parse, 10);
|
||||
while(isspace((unsigned char)*parse))
|
||||
@@ -273,6 +276,7 @@ static struct entry* new_entry(void)
|
||||
e->copy_id = 0;
|
||||
e->copy_query = 0;
|
||||
e->copy_ednsdata_assume_clientsubnet = 0;
|
||||
e->increment_ecs_scope = 0;
|
||||
e->sleeptime = 0;
|
||||
e->next = NULL;
|
||||
return e;
|
||||
@@ -1592,6 +1596,9 @@ adjust_packet(struct entry* match, uint8_t** answer_pkt, size_t *answer_len,
|
||||
if(walk_qlen >= 15 && walk_plen >= 15) {
|
||||
walk_p[15] = walk_q[14];
|
||||
}
|
||||
if(match->increment_ecs_scope) {
|
||||
walk_p[15]++;
|
||||
}
|
||||
}
|
||||
|
||||
if(match->sleeptime > 0) {
|
||||
|
||||
@@ -208,6 +208,8 @@ struct entry {
|
||||
/** copy ednsdata to reply, assume it is clientsubnet and
|
||||
* adjust scopemask to match sourcemask */
|
||||
uint8_t copy_ednsdata_assume_clientsubnet;
|
||||
/** increment the ECS scope copied from the sourcemask by one */
|
||||
uint8_t increment_ecs_scope;
|
||||
/** in seconds */
|
||||
unsigned int sleeptime;
|
||||
|
||||
|
||||
+21
-3
@@ -42,6 +42,7 @@
|
||||
#include "testcode/unitmain.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "sldns/str2wire.h"
|
||||
@@ -111,8 +112,9 @@ static const char* zone_example_com =
|
||||
/* just an RRSIG rrset with nothing else, 2 rrsigs */
|
||||
"z5.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
|
||||
"z5.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12345 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
|
||||
#if 0 /* comparison of file does not work on this part because duplicates */
|
||||
#if 1 /* comparison of file does not work on this part because duplicates */
|
||||
/* are removed and the rrsets are reordered */
|
||||
"end_of_check.z6.example.com. 3600 IN A 10.0.0.10\n"
|
||||
/* first rrsig, then A record */
|
||||
"z6.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
|
||||
"z6.example.com. 3600 IN A 10.0.0.10\n"
|
||||
@@ -131,6 +133,12 @@ static const char* zone_example_com =
|
||||
"z9.example.com. 3600 IN A 10.0.0.10\n"
|
||||
"z9.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
|
||||
"z9.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
|
||||
/* different covered types, first RRSIGs then, RRs, then another RRSIG */
|
||||
"zz10.example.com. 3600 IN RRSIG AAAA 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
|
||||
"zz10.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
|
||||
"zz10.example.com. 3600 IN A 10.0.0.10\n"
|
||||
"zz10.example.com. 3600 IN RRSIG CNAME 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
|
||||
"zz10.example.com. 3600 IN AAAA ::11\n"
|
||||
#endif /* if0 for duplicates and reordering */
|
||||
;
|
||||
|
||||
@@ -515,6 +523,7 @@ addzone(struct auth_zones* az, const char* name, char* fname)
|
||||
struct auth_zone* z;
|
||||
size_t nmlen;
|
||||
uint8_t* nm = sldns_str2wire_dname(name, &nmlen);
|
||||
struct config_file* cfg;
|
||||
if(!nm) fatal_exit("out of memory");
|
||||
lock_rw_wrlock(&az->lock);
|
||||
z = auth_zone_create(az, nm, nmlen, LDNS_RR_CLASS_IN);
|
||||
@@ -522,12 +531,16 @@ addzone(struct auth_zones* az, const char* name, char* fname)
|
||||
if(!z) fatal_exit("cannot find zone");
|
||||
auth_zone_set_zonefile(z, fname);
|
||||
z->for_upstream = 1;
|
||||
cfg = config_create();
|
||||
free(cfg->chrootdir);
|
||||
cfg->chrootdir = NULL;
|
||||
|
||||
if(!auth_zone_read_zonefile(z)) {
|
||||
if(!auth_zone_read_zonefile(z, cfg)) {
|
||||
fatal_exit("parse failure for auth zone %s", name);
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
free(nm);
|
||||
config_delete(cfg);
|
||||
return z;
|
||||
}
|
||||
|
||||
@@ -550,11 +563,16 @@ checkfile(char* f1, char *f2)
|
||||
cp2 = fgets(buf2, (int)sizeof(buf2), i2);
|
||||
if((!cp1 && !feof(i1)) || (!cp2 && !feof(i2)))
|
||||
fatal_exit("fgets failed: %s", strerror(errno));
|
||||
if(strncmp(buf1, "end_of_check", 12) == 0) {
|
||||
fclose(i1);
|
||||
fclose(i2);
|
||||
return;
|
||||
}
|
||||
if(strcmp(buf1, buf2) != 0) {
|
||||
log_info("in files %s and %s:%d", f1, f2, line);
|
||||
log_info("'%s'", buf1);
|
||||
log_info("'%s'", buf2);
|
||||
fatal_exit("files are not eqaul");
|
||||
fatal_exit("files are not equal");
|
||||
}
|
||||
}
|
||||
unit_assert(feof(i1) && feof(i2));
|
||||
|
||||
+1
-1
@@ -158,7 +158,7 @@ static void consistency_test(void)
|
||||
{
|
||||
addrlen_t l;
|
||||
time_t i;
|
||||
unsigned int count;
|
||||
uint32_t count;
|
||||
addrkey_t *k;
|
||||
struct addrtree* t;
|
||||
struct module_env env;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user