mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
Compare commits
473
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
081fd4fdae | ||
|
|
09a0e6ee30 | ||
|
|
a4f4d7b6ba | ||
|
|
e2a2dcdfd5 | ||
|
|
14b11384a4 | ||
|
|
a03f0a388e | ||
|
|
0b77c9d676 | ||
|
|
1c3ba0cef7 | ||
|
|
310396190b | ||
|
|
a08fe8ca60 | ||
|
|
a95f5fd5cb | ||
|
|
a922a19d70 | ||
|
|
a8d0177b36 | ||
|
|
779b86fb22 | ||
|
|
e3453711e5 | ||
|
|
73484d3b36 | ||
|
|
f1c23891ab | ||
|
|
9b7843f879 | ||
|
|
bd5eeff364 | ||
|
|
2fea5663bd | ||
|
|
f46c238552 | ||
|
|
7e300939c0 | ||
|
|
409bc229ef | ||
|
|
ee0087d5c7 | ||
|
|
d4f697f160 | ||
|
|
6e4bab2629 | ||
|
|
5c5ddbe859 | ||
|
|
ea506d0f68 | ||
|
|
27e334e813 | ||
|
|
8e48a5cf5f | ||
|
|
9bc81f31d8 | ||
|
|
c6db87d81d | ||
|
|
f90e80d3bc | ||
|
|
e60f92ea29 | ||
|
|
46b5e96c54 | ||
|
|
f5a197f96e | ||
|
|
196654efec | ||
|
|
a9c8d00d63 | ||
|
|
5e4cfcc665 | ||
|
|
193cb2fcc4 | ||
|
|
b57a2f15db | ||
|
|
8d2c08befd | ||
|
|
d9a9f73e82 | ||
|
|
e19da1b619 | ||
|
|
6ce60bcb61 | ||
|
|
ff026a1f3c | ||
|
|
a37730cee8 | ||
|
|
af11b54071 | ||
|
|
2a78803049 | ||
|
|
edf1ad369a | ||
|
|
52ea271a65 | ||
|
|
ae54e9013b | ||
|
|
8a3ae4d08a | ||
|
|
1cc54b080a | ||
|
|
63171a2522 | ||
|
|
2e023a5699 | ||
|
|
1c1fc36d76 | ||
|
|
42d7db578a | ||
|
|
d4a6380562 | ||
|
|
8133251662 | ||
|
|
5a8d314ce3 | ||
|
|
99f36a4e1e | ||
|
|
61a28c2ee5 | ||
|
|
2552a81b40 | ||
|
|
ab6f1d0fc7 | ||
|
|
c8a56bfa8f | ||
|
|
d1150541bb | ||
|
|
ead84a5a64 | ||
|
|
c6369e9ffa | ||
|
|
474afc9016 | ||
|
|
bd3c02bd59 | ||
|
|
32b1d900ff | ||
|
|
4eac399dfd | ||
|
|
c26fc84945 | ||
|
|
2b47ca080e | ||
|
|
348cbab016 | ||
|
|
a777329b7f | ||
|
|
92121f7878 | ||
|
|
ce8167a3bb | ||
|
|
937523285a | ||
|
|
8a0de6b519 | ||
|
|
e338143639 | ||
|
|
59570b0413 | ||
|
|
78adebf8ec | ||
|
|
b75c37252c | ||
|
|
48ad6477eb | ||
|
|
296f28e8d0 | ||
|
|
83e2cade5b | ||
|
|
ce0628ee55 | ||
|
|
bb5251da66 | ||
|
|
bfd0c5ec85 | ||
|
|
8092cd6331 | ||
|
|
7105ea9293 | ||
|
|
16cc196bf2 | ||
|
|
c79a99a577 | ||
|
|
a82c0eeece | ||
|
|
a62c1135fe | ||
|
|
ba0cad0bc3 | ||
|
|
7c1f9699d8 | ||
|
|
33a814683b | ||
|
|
beebe5ba0c | ||
|
|
225534e5ab | ||
|
|
3599fd9c60 | ||
|
|
5b162ead92 | ||
|
|
62428e17f6 | ||
|
|
079253670e | ||
|
|
91e863138b | ||
|
|
d1e92a0ebd | ||
|
|
3949bf2c82 | ||
|
|
a41375411e | ||
|
|
030832cf12 | ||
|
|
49a36d98bb | ||
|
|
ddae2885bd | ||
|
|
19193fd534 | ||
|
|
4e249c96e8 | ||
|
|
cae8361dcd | ||
|
|
429e130768 | ||
|
|
20d57ec58b | ||
|
|
e43c3daec2 | ||
|
|
64c4e69b07 | ||
|
|
a9e028564d | ||
|
|
99994a26b0 | ||
|
|
fe97f25b75 | ||
|
|
281030d576 | ||
|
|
8992e8c91f | ||
|
|
b34a6defc1 | ||
|
|
8cf5eae166 | ||
|
|
df8f236b62 | ||
|
|
273ff1201b | ||
|
|
91f585ed38 | ||
|
|
b9b226bdea | ||
|
|
8fffdca2a6 | ||
|
|
723845b350 | ||
|
|
31b677b35f | ||
|
|
c2e3baa81a | ||
|
|
7273b35243 | ||
|
|
dfe8e0dfa2 | ||
|
|
7ad8ffccf5 | ||
|
|
065c7c5dd8 | ||
|
|
71744b8bb2 | ||
|
|
3d2dfc4769 | ||
|
|
5e4f0d65ce | ||
|
|
aae44940c7 | ||
|
|
062c2cacfc | ||
|
|
ce65cdde71 | ||
|
|
b005fcd87b | ||
|
|
f11d6653d6 | ||
|
|
20d5e35576 | ||
|
|
3028fa50a8 | ||
|
|
e584933b2b | ||
|
|
d48abb9a84 | ||
|
|
37361a1d10 | ||
|
|
299cc0c689 | ||
|
|
707e5a915b | ||
|
|
649e265d6f | ||
|
|
9d4ca81959 | ||
|
|
68a57554a6 | ||
|
|
cc9fb69911 | ||
|
|
d3f397c686 | ||
|
|
ed8b859e31 | ||
|
|
011a7d8830 | ||
|
|
510606dd1c | ||
|
|
4e59c8344f | ||
|
|
4c8f334c15 | ||
|
|
2f52ecdd9c | ||
|
|
5d82b7c421 | ||
|
|
8ae9f26bce | ||
|
|
55f560a3ca | ||
|
|
51caffb454 | ||
|
|
ef1baf94f7 | ||
|
|
8b18d1a0a4 | ||
|
|
4481b9584c | ||
|
|
dec68aa9a9 | ||
|
|
c10712a82b | ||
|
|
d81e2c654f | ||
|
|
f5dcd84d27 | ||
|
|
7c4911c577 | ||
|
|
be4583ac84 | ||
|
|
068374740c | ||
|
|
f7d63b0927 | ||
|
|
9087b18234 | ||
|
|
19a3907657 | ||
|
|
762920232a | ||
|
|
f30fe71395 | ||
|
|
ec6f4bab46 | ||
|
|
0d2efc3f3f | ||
|
|
bb480068fa | ||
|
|
ae9fe1a10e | ||
|
|
dd19026e91 | ||
|
|
42d2c04ae1 | ||
|
|
db2557826a | ||
|
|
11d98df304 | ||
|
|
ec84fd2ca6 | ||
|
|
fe6eb5f665 | ||
|
|
90b00dfe57 | ||
|
|
023411f975 | ||
|
|
a97bfa08ec | ||
|
|
9c2a45c59e | ||
|
|
1b72e814e7 | ||
|
|
71b078611f | ||
|
|
1ef8cfcac5 | ||
|
|
6b8e316663 | ||
|
|
21d03697ca | ||
|
|
4c7f824e0a | ||
|
|
42244e1b4d | ||
|
|
2981adac66 | ||
|
|
91971db3d0 | ||
|
|
b4e8ab4254 | ||
|
|
198a7ce74d | ||
|
|
e103490376 | ||
|
|
f3658c210c | ||
|
|
1ba3682d9b | ||
|
|
39b7468bab | ||
|
|
a42e9aaaba | ||
|
|
a9b7194485 | ||
|
|
2ad55ba791 | ||
|
|
ac8dc59341 | ||
|
|
c1c1cd97e7 | ||
|
|
b23c373f4d | ||
|
|
e6da6c251c | ||
|
|
81ded6124d | ||
|
|
c417f733af | ||
|
|
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 |
+16
-1
@@ -4,6 +4,7 @@
|
||||
/Makefile
|
||||
/autom4te.cache/
|
||||
/config.h
|
||||
/config.h.in~
|
||||
/config.log
|
||||
/config.status
|
||||
/dnstap/dnstap_config.h
|
||||
@@ -18,6 +19,7 @@
|
||||
/doc/unbound.conf.5
|
||||
/libtool
|
||||
/libunbound.la
|
||||
/_unbound.la
|
||||
/smallapp/unbound-control-setup.sh
|
||||
/unbound
|
||||
/unbound-anchor
|
||||
@@ -36,4 +38,17 @@
|
||||
/streamtcp
|
||||
/testbound
|
||||
/unittest
|
||||
|
||||
/contrib/libunbound.pc
|
||||
/contrib/unbound.service
|
||||
/contrib/unbound.socket
|
||||
/dnstap/dnstap.pb-c.c
|
||||
/dnstap/dnstap.pb-c.h
|
||||
/libunbound/python/libunbound_wrap.c
|
||||
/libunbound/python/unbound.py
|
||||
/pythonmod/interface.h
|
||||
/pythonmod/unboundmodule.py
|
||||
/testdata/result.*
|
||||
/testdata/.done-*
|
||||
/testdata/.perfstats.txt
|
||||
/doc/html
|
||||
/doc/xml
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
sudo: false
|
||||
language: c
|
||||
compiler:
|
||||
- gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libssl-dev
|
||||
- libevent-dev
|
||||
- libexpat-dev
|
||||
- clang
|
||||
script:
|
||||
- ./configure --enable-debug --disable-flto
|
||||
- make
|
||||
- make test
|
||||
- (cd testdata/clang-analysis.tdir; bash clang-analysis.test)
|
||||
+482
-537
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
||||
# Unbound
|
||||
|
||||
[](https://travis-ci.org/NLnetLabs/unbound)
|
||||
[](https://repology.org/project/unbound/versions)
|
||||
|
||||
Unbound is a validating, recursive, caching DNS resolver. It is designed to be
|
||||
fast and lean and incorporates modern features based on open standards. If you
|
||||
have any feedback, we would love to hear from you. Don’t hesitate to
|
||||
[create an issue on Github](https://github.com/NLnetLabs/unbound/issues/new)
|
||||
or post a message on the [Unbound mailing list](https://nlnetlabs.nl/mailman/listinfo/unbound-users).
|
||||
You can lean more about Unbound by reading our
|
||||
[documentation](https://nlnetlabs.nl/documentation/unbound/).
|
||||
|
||||
## Compiling
|
||||
|
||||
Make sure you have the C toolchain, OpenSSL and its include files, and libexpat
|
||||
installed. Unbound can be compiled and installed using:
|
||||
|
||||
```
|
||||
./configure && make && make install
|
||||
```
|
||||
|
||||
You can use libevent if you want. libevent is useful when using many (10000)
|
||||
outgoing ports. By default max 256 ports are opened at the same time and the
|
||||
builtin alternative is equally capable and a little faster.
|
||||
|
||||
Use the `--with-libevent=dir` configure option to compile Unbound with libevent
|
||||
support.
|
||||
|
||||
## Unbound configuration
|
||||
|
||||
All of Unbound's configuration options are described in the man pages, which
|
||||
will be installed and are available on the Unbound
|
||||
[documentation page](https://nlnetlabs.nl/documentation/unbound/).
|
||||
|
||||
An example configuration file is located in
|
||||
[doc/example.conf](https://github.com/NLnetLabs/unbound/blob/master/doc/example.conf.in).
|
||||
Vendored
+4
-4
@@ -1,6 +1,6 @@
|
||||
# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
|
||||
# generated automatically by aclocal 1.16.1 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2018 Free Software Foundation, Inc.
|
||||
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@@ -9390,7 +9390,7 @@ AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"],
|
||||
|
||||
# AM_CONDITIONAL -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1997-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1997-2018 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@@ -9421,7 +9421,7 @@ AC_CONFIG_COMMANDS_PRE(
|
||||
Usually this means the macro was only invoked conditionally.]])
|
||||
fi])])
|
||||
|
||||
# Copyright (C) 2006-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2006-2018 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
||||
@@ -72,6 +72,19 @@
|
||||
# define be64toh(x) OSSwapBigToHostInt64(x)
|
||||
#endif
|
||||
|
||||
/* Some compilers do not define __BYTE_ORDER__, like IBM XLC on AIX */
|
||||
#ifndef be64toh
|
||||
#if defined(__sun) || defined(_AIX)
|
||||
# if __BIG_ENDIAN__
|
||||
# define be64toh(n) (n)
|
||||
# define htobe64(n) (n)
|
||||
# else
|
||||
# define be64toh(n) (((uint64_t)htonl((n) & 0xFFFFFFFF) << 32) | htonl((n) >> 32))
|
||||
# define htobe64(n) (((uint64_t)htonl((n) & 0xFFFFFFFF) << 32) | htonl((n) >> 32))
|
||||
# endif
|
||||
#endif
|
||||
#endif /* be64toh */
|
||||
|
||||
/** the unit test testframe for cachedb, its module state contains
|
||||
* a cache for a couple queries (in memory). */
|
||||
struct testframe_moddata {
|
||||
@@ -446,6 +459,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->
|
||||
|
||||
@@ -140,6 +140,7 @@ nodevrandom:
|
||||
static inline void
|
||||
_rs_init(u_char *buf, size_t n)
|
||||
{
|
||||
assert(buf);
|
||||
if (n < KEYSZ + IVSZ)
|
||||
return;
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
#! /bin/sh
|
||||
#!/usr/bin/sh
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright 1992-2016 Free Software Foundation, Inc.
|
||||
|
||||
|
||||
+55
-2
@@ -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
|
||||
|
||||
@@ -45,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
|
||||
|
||||
@@ -60,6 +69,9 @@
|
||||
/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
|
||||
#undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
|
||||
|
||||
/* Define to 1 if you have the `CRYPTO_THREADID_set_callback' function. */
|
||||
#undef HAVE_CRYPTO_THREADID_SET_CALLBACK
|
||||
|
||||
/* Define to 1 if you have the `ctime_r' function. */
|
||||
#undef HAVE_CTIME_R
|
||||
|
||||
@@ -74,6 +86,10 @@
|
||||
if you don't. */
|
||||
#undef HAVE_DECL_ARC4RANDOM_UNIFORM
|
||||
|
||||
/* Define to 1 if you have the declaration of `evsignal_assign', and to 0 if
|
||||
you don't. */
|
||||
#undef HAVE_DECL_EVSIGNAL_ASSIGN
|
||||
|
||||
/* Define to 1 if you have the declaration of `inet_ntop', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_INET_NTOP
|
||||
@@ -154,6 +170,9 @@
|
||||
/* Define to 1 if you have the `ERR_load_crypto_strings' function. */
|
||||
#undef HAVE_ERR_LOAD_CRYPTO_STRINGS
|
||||
|
||||
/* Define to 1 if you have the `event_assign' function. */
|
||||
#undef HAVE_EVENT_ASSIGN
|
||||
|
||||
/* Define to 1 if you have the `event_base_free' function. */
|
||||
#undef HAVE_EVENT_BASE_FREE
|
||||
|
||||
@@ -169,6 +188,9 @@
|
||||
/* Define to 1 if you have the <event.h> header file. */
|
||||
#undef HAVE_EVENT_H
|
||||
|
||||
/* Define to 1 if you have the `EVP_aes_256_cbc' function. */
|
||||
#undef HAVE_EVP_AES_256_CBC
|
||||
|
||||
/* Define to 1 if you have the `EVP_cleanup' function. */
|
||||
#undef HAVE_EVP_CLEANUP
|
||||
|
||||
@@ -178,6 +200,9 @@
|
||||
/* Define to 1 if you have the `EVP_dss1' function. */
|
||||
#undef HAVE_EVP_DSS1
|
||||
|
||||
/* Define to 1 if you have the `EVP_EncryptInit_ex' function. */
|
||||
#undef HAVE_EVP_ENCRYPTINIT_EX
|
||||
|
||||
/* Define to 1 if you have the `EVP_MD_CTX_new' function. */
|
||||
#undef HAVE_EVP_MD_CTX_NEW
|
||||
|
||||
@@ -199,6 +224,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
|
||||
|
||||
@@ -247,6 +275,9 @@
|
||||
/* Define to 1 if you have the <hiredis/hiredis.h> header file. */
|
||||
#undef HAVE_HIREDIS_HIREDIS_H
|
||||
|
||||
/* Define to 1 if you have the `HMAC_Init_ex' function. */
|
||||
#undef HAVE_HMAC_INIT_EX
|
||||
|
||||
/* If you have HMAC_Update */
|
||||
#undef HAVE_HMAC_UPDATE
|
||||
|
||||
@@ -382,7 +413,7 @@
|
||||
/* Define to 1 if you have the `RAND_cleanup' function. */
|
||||
#undef HAVE_RAND_CLEANUP
|
||||
|
||||
/* Define to 1 if you have the `reallocarray' function. */
|
||||
/* If we have reallocarray(3) */
|
||||
#undef HAVE_REALLOCARRAY
|
||||
|
||||
/* Define to 1 if you have the `recvmsg' function. */
|
||||
@@ -439,9 +470,15 @@
|
||||
/* Define if you have the SSL libraries installed. */
|
||||
#undef HAVE_SSL
|
||||
|
||||
/* Define to 1 if you have the `SSL_CTX_set_ciphersuites' function. */
|
||||
#undef HAVE_SSL_CTX_SET_CIPHERSUITES
|
||||
|
||||
/* Define to 1 if you have the `SSL_CTX_set_security_level' function. */
|
||||
#undef HAVE_SSL_CTX_SET_SECURITY_LEVEL
|
||||
|
||||
/* Define to 1 if you have the `SSL_CTX_set_tlsext_ticket_key_cb' function. */
|
||||
#undef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_CB
|
||||
|
||||
/* Define to 1 if you have the `SSL_get0_peername' function. */
|
||||
#undef HAVE_SSL_GET0_PEERNAME
|
||||
|
||||
@@ -574,6 +611,9 @@
|
||||
/* Define to 1 if you have the <ws2tcpip.h> header file. */
|
||||
#undef HAVE_WS2TCPIP_H
|
||||
|
||||
/* Define to 1 if you have the `X509_VERIFY_PARAM_set1_host' function. */
|
||||
#undef HAVE_X509_VERIFY_PARAM_SET1_HOST
|
||||
|
||||
/* Define to 1 if you have the `_beginthreadex' function. */
|
||||
#undef HAVE__BEGINTHREADEX
|
||||
|
||||
@@ -651,6 +691,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
|
||||
|
||||
@@ -929,8 +972,14 @@
|
||||
|
||||
|
||||
|
||||
#ifndef _OPENBSD_SOURCE
|
||||
#define _OPENBSD_SOURCE 1
|
||||
#endif
|
||||
|
||||
#ifndef UNBOUND_DEBUG
|
||||
# ifndef NDEBUG
|
||||
# define NDEBUG
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/** Use small-ldns codebase */
|
||||
@@ -1144,6 +1193,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
|
||||
@@ -1176,7 +1230,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);
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
#! /bin/sh
|
||||
#!/usr/bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright 1992-2016 Free Software Foundation, Inc.
|
||||
|
||||
|
||||
@@ -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.3.
|
||||
# Generated by GNU Autoconf 2.69 for unbound 1.9.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.3'
|
||||
PACKAGE_STRING='unbound 1.7.3'
|
||||
PACKAGE_VERSION='1.9.2'
|
||||
PACKAGE_STRING='unbound 1.9.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
|
||||
@@ -710,6 +707,9 @@ PTHREAD_CC
|
||||
ax_pthread_config
|
||||
RUNTIME_PATH
|
||||
LIBOBJS
|
||||
PKG_CONFIG_LIBDIR
|
||||
PKG_CONFIG_PATH
|
||||
PKG_CONFIG
|
||||
LT_SYS_LIBRARY_PATH
|
||||
OTOOL64
|
||||
OTOOL
|
||||
@@ -892,10 +892,10 @@ CPP
|
||||
YACC
|
||||
YFLAGS
|
||||
LT_SYS_LIBRARY_PATH
|
||||
PYTHON_VERSION
|
||||
PKG_CONFIG
|
||||
PKG_CONFIG_PATH
|
||||
PKG_CONFIG_LIBDIR
|
||||
PYTHON_VERSION
|
||||
SYSTEMD_CFLAGS
|
||||
SYSTEMD_LIBS
|
||||
SYSTEMD_DAEMON_CFLAGS
|
||||
@@ -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.3 to adapt to many kinds of systems.
|
||||
\`configure' configures unbound 1.9.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.3:";;
|
||||
short | recursive ) echo "Configuration of unbound 1.9.2:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1638,15 +1638,15 @@ Some influential environment variables:
|
||||
default value of `-d' given by some make applications.
|
||||
LT_SYS_LIBRARY_PATH
|
||||
User-defined run-time library search path.
|
||||
PYTHON_VERSION
|
||||
The installed Python version to use, for example '2.3'. This
|
||||
string will be appended to the Python interpreter canonical
|
||||
name.
|
||||
PKG_CONFIG path to pkg-config utility
|
||||
PKG_CONFIG_PATH
|
||||
directories to add to pkg-config's search path
|
||||
PKG_CONFIG_LIBDIR
|
||||
path overriding pkg-config's built-in search path
|
||||
PYTHON_VERSION
|
||||
The installed Python version to use, for example '2.3'. This
|
||||
string will be appended to the Python interpreter canonical
|
||||
name.
|
||||
SYSTEMD_CFLAGS
|
||||
C compiler flags for SYSTEMD, overriding pkg-config
|
||||
SYSTEMD_LIBS
|
||||
@@ -1722,7 +1722,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
unbound configure 1.7.3
|
||||
unbound configure 1.9.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.3, which was
|
||||
It was created by unbound $as_me 1.9.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=9
|
||||
|
||||
UNBOUND_VERSION_MICRO=3
|
||||
UNBOUND_VERSION_MICRO=2
|
||||
|
||||
|
||||
LIBUNBOUND_CURRENT=7
|
||||
LIBUNBOUND_REVISION=11
|
||||
LIBUNBOUND_AGE=5
|
||||
LIBUNBOUND_CURRENT=9
|
||||
LIBUNBOUND_REVISION=2
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
# 1.0.2 had 0:14:0
|
||||
@@ -2850,6 +2850,13 @@ LIBUNBOUND_AGE=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
|
||||
# 1.8.3 had 8:3:0
|
||||
# 1.9.0 had 9:0:1 # add ub_ctx_set_tls
|
||||
# 1.9.1 had 9:1:1
|
||||
# 1.9.2 had 9:2:1
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -6264,6 +6271,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
|
||||
|
||||
|
||||
@@ -6273,6 +6328,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.
|
||||
@@ -6432,6 +6489,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; }
|
||||
@@ -6442,8 +6500,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.
|
||||
@@ -14483,6 +14560,127 @@ CC=$lt_save_CC
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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
|
||||
|
||||
# Checks for header files.
|
||||
for ac_header in stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h
|
||||
do :
|
||||
@@ -15894,6 +16092,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 :
|
||||
@@ -16929,7 +17138,16 @@ $as_echo "#define HAVE_PYTHON 1" >>confdefs.h
|
||||
CPPFLAGS="$PYTHON_CPPFLAGS"
|
||||
fi
|
||||
ub_have_python=yes
|
||||
PC_PY_DEPENDENCY="python"
|
||||
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
|
||||
@@ -17778,7 +17996,7 @@ fi
|
||||
|
||||
done
|
||||
|
||||
for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify
|
||||
for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify SSL_CTX_set_tlsext_ticket_key_cb EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback
|
||||
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"
|
||||
@@ -17794,7 +18012,7 @@ done
|
||||
# these check_funcs need -lssl
|
||||
BAKLIBS="$LIBS"
|
||||
LIBS="-lssl $LIBS"
|
||||
for ac_func in OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername
|
||||
for ac_func in OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites
|
||||
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"
|
||||
@@ -18795,6 +19013,35 @@ _ACEOF
|
||||
fi
|
||||
done
|
||||
# only in libev. (tested on 4.00)
|
||||
for ac_func in event_assign
|
||||
do :
|
||||
ac_fn_c_check_func "$LINENO" "event_assign" "ac_cv_func_event_assign"
|
||||
if test "x$ac_cv_func_event_assign" = xyes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_EVENT_ASSIGN 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
done
|
||||
# in libevent, for thread-safety
|
||||
ac_fn_c_check_decl "$LINENO" "evsignal_assign" "ac_cv_have_decl_evsignal_assign" "$ac_includes_default
|
||||
#ifdef HAVE_EVENT_H
|
||||
# include <event.h>
|
||||
#else
|
||||
# include \"event2/event.h\"
|
||||
#endif
|
||||
|
||||
"
|
||||
if test "x$ac_cv_have_decl_evsignal_assign" = xyes; then :
|
||||
ac_have_decl=1
|
||||
else
|
||||
ac_have_decl=0
|
||||
fi
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_DECL_EVSIGNAL_ASSIGN $ac_have_decl
|
||||
_ACEOF
|
||||
|
||||
PC_LIBEVENT_DEPENDENCY="libevent"
|
||||
|
||||
if test -n "$BAK_LDFLAGS_SET"; then
|
||||
@@ -18870,10 +19117,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
|
||||
@@ -18959,126 +19206,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 :
|
||||
|
||||
|
||||
@@ -20001,22 +20128,60 @@ esac
|
||||
fi
|
||||
|
||||
|
||||
LIBOBJ_WITHOUT_CTIMEARC4="$LIBOBJS"
|
||||
|
||||
ac_fn_c_check_func "$LINENO" "reallocarray" "ac_cv_func_reallocarray"
|
||||
if test "x$ac_cv_func_reallocarray" = xyes; then :
|
||||
$as_echo "#define HAVE_REALLOCARRAY 1" >>confdefs.h
|
||||
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
|
||||
*" reallocarray.$ac_objext "* ) ;;
|
||||
*) LIBOBJS="$LIBOBJS reallocarray.$ac_objext"
|
||||
*" explicit_bzero.$ac_objext "* ) ;;
|
||||
*) LIBOBJS="$LIBOBJS explicit_bzero.$ac_objext"
|
||||
;;
|
||||
esac
|
||||
|
||||
fi
|
||||
|
||||
|
||||
LIBOBJ_WITHOUT_CTIMEARC4="$LIBOBJS"
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for reallocarray" >&5
|
||||
$as_echo_n "checking for reallocarray... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$ac_includes_default
|
||||
|
||||
#ifndef _OPENBSD_SOURCE
|
||||
#define _OPENBSD_SOURCE 1
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
int main(void) {
|
||||
void* p = reallocarray(NULL, 10, 100);
|
||||
free(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
|
||||
$as_echo "#define HAVE_REALLOCARRAY 1" >>confdefs.h
|
||||
|
||||
|
||||
else
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
case " $LIBOBJS " in
|
||||
*" reallocarray.$ac_objext "* ) ;;
|
||||
*) LIBOBJS="$LIBOBJS reallocarray.$ac_objext"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
if test "$USE_NSS" = "no"; then
|
||||
ac_fn_c_check_func "$LINENO" "arc4random" "ac_cv_func_arc4random"
|
||||
if test "x$ac_cv_func_arc4random" = xyes; then :
|
||||
@@ -20047,12 +20212,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"
|
||||
@@ -21045,7 +21204,7 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
version=1.7.3
|
||||
version=1.9.2
|
||||
|
||||
date=`date +'%b %e, %Y'`
|
||||
|
||||
@@ -21564,7 +21723,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.3, which was
|
||||
This file was extended by unbound $as_me 1.9.2, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -21630,7 +21789,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.3
|
||||
unbound config.status 1.9.2
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
+110
-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],[3])
|
||||
m4_define([VERSION_MINOR],[9])
|
||||
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=11
|
||||
LIBUNBOUND_AGE=5
|
||||
LIBUNBOUND_CURRENT=9
|
||||
LIBUNBOUND_REVISION=2
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
# 1.0.2 had 0:14:0
|
||||
@@ -81,6 +81,13 @@ LIBUNBOUND_AGE=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
|
||||
# 1.8.3 had 8:3:0
|
||||
# 1.9.0 had 9:0:1 # add ub_ctx_set_tls
|
||||
# 1.9.1 had 9:1:1
|
||||
# 1.9.2 had 9:2:1
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -309,11 +316,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
|
||||
@@ -323,16 +355,37 @@ 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)
|
||||
ACX_LIBTOOL_C_ONLY
|
||||
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
# Checks for header files.
|
||||
AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h],,, [AC_INCLUDES_DEFAULT])
|
||||
|
||||
@@ -415,6 +468,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 ]),
|
||||
@@ -585,7 +645,9 @@ if test x_$ub_test_python != x_no; then
|
||||
CPPFLAGS="$PYTHON_CPPFLAGS"
|
||||
fi
|
||||
ub_have_python=yes
|
||||
PC_PY_DEPENDENCY="python"
|
||||
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
|
||||
@@ -722,12 +784,12 @@ else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
AC_CHECK_HEADERS([openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify SSL_CTX_set_tlsext_ticket_key_cb EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback])
|
||||
|
||||
# these check_funcs need -lssl
|
||||
BAKLIBS="$LIBS"
|
||||
LIBS="-lssl $LIBS"
|
||||
AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername])
|
||||
AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites])
|
||||
LIBS="$BAKLIBS"
|
||||
|
||||
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
|
||||
@@ -1138,6 +1200,14 @@ large outgoing port ranges. ])
|
||||
AC_CHECK_FUNCS([event_base_get_method]) # only in libevent 1.4.3 and later
|
||||
AC_CHECK_FUNCS([ev_loop]) # only in libev. (tested on 3.51)
|
||||
AC_CHECK_FUNCS([ev_default_loop]) # only in libev. (tested on 4.00)
|
||||
AC_CHECK_FUNCS([event_assign]) # in libevent, for thread-safety
|
||||
AC_CHECK_DECLS([evsignal_assign], [], [], [AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_EVENT_H
|
||||
# include <event.h>
|
||||
#else
|
||||
# include "event2/event.h"
|
||||
#endif
|
||||
])
|
||||
PC_LIBEVENT_DEPENDENCY="libevent"
|
||||
AC_SUBST(PC_LIBEVENT_DEPENDENCY)
|
||||
if test -n "$BAK_LDFLAGS_SET"; then
|
||||
@@ -1177,9 +1247,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
|
||||
@@ -1373,15 +1443,32 @@ 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)
|
||||
AC_REPLACE_FUNCS(reallocarray)
|
||||
AC_MSG_CHECKING([for reallocarray])
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE(AC_INCLUDES_DEFAULT
|
||||
[[
|
||||
#ifndef _OPENBSD_SOURCE
|
||||
#define _OPENBSD_SOURCE 1
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
int main(void) {
|
||||
void* p = reallocarray(NULL, 10, 100);
|
||||
free(p);
|
||||
return 0;
|
||||
}
|
||||
]])], [AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_REALLOCARRAY, 1, [If we have reallocarray(3)])
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
AC_LIBOBJ(reallocarray)
|
||||
])
|
||||
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
|
||||
@@ -1590,8 +1677,14 @@ AHX_CONFIG_EXT_FLAGS
|
||||
|
||||
dnl includes
|
||||
[
|
||||
#ifndef _OPENBSD_SOURCE
|
||||
#define _OPENBSD_SOURCE 1
|
||||
#endif
|
||||
|
||||
#ifndef UNBOUND_DEBUG
|
||||
# ifndef NDEBUG
|
||||
# define NDEBUG
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/** Use small-ldns codebase */
|
||||
@@ -1706,6 +1799,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
|
||||
@@ -1738,7 +1836,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);
|
||||
|
||||
@@ -38,3 +38,5 @@ distribution but may be helpful.
|
||||
* unbound-querycachedb.py: utility to show data stored in cachedb backend
|
||||
for a particular query name and type. It requires dnspython and (for
|
||||
redis backend) redis Python modules.
|
||||
* unbound-fuzzme.patch: adds unbound-fuzzme program that parses a packet from
|
||||
stdin. Used with fuzzers, patch from Jacob Hoffman-Andrews.
|
||||
|
||||
+180
-186
@@ -1,14 +1,10 @@
|
||||
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/
|
||||
===================================================================
|
||||
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
|
||||
diff --git a/Makefile.in b/Makefile.in
|
||||
index 03a6347..6758bea 100644
|
||||
--- a/Makefile.in
|
||||
+++ b/Makefile.in
|
||||
@@ -23,6 +23,8 @@ CHECKLOCK_SRC=testcode/checklocks.c
|
||||
CHECKLOCK_OBJ=@CHECKLOCK_OBJ@
|
||||
DNSTAP_SRC=@DNSTAP_SRC@
|
||||
@@ -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 @@ validator/val_sigcrypt.c validator/val_utils.c dns64/dns64.c \
|
||||
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 @@ autotrust.lo val_anchor.lo \
|
||||
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 @@ dnscrypt.lo dnscrypt.o: $(srcdir)/dnscrypt/dnscrypt.c config.h \
|
||||
$(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
|
||||
===================================================================
|
||||
--- 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
|
||||
diff --git a/config.h.in b/config.h.in
|
||||
index 74c14d1..a18f4ff 100644
|
||||
--- a/config.h.in
|
||||
+++ b/config.h.in
|
||||
@@ -1305,4 +1305,11 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
||||
/** the version of unbound-control that this software implements */
|
||||
#define UNBOUND_CONTROL_VERSION 1
|
||||
|
||||
@@ -65,10 +61,10 @@ 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
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/configure.ac
|
||||
+++ unbound-1.7.0~rc1/configure.ac
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index abbecf0..6454274 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -6,6 +6,7 @@ sinclude(ax_pthread.m4)
|
||||
sinclude(acx_python.m4)
|
||||
sinclude(ac_pkg_swig.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
|
||||
@@ -1586,6 +1587,9 @@ case "$enable_ipsecmod" in
|
||||
;;
|
||||
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
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/daemon/daemon.c
|
||||
+++ unbound-1.7.0~rc1/daemon/daemon.c
|
||||
@@ -90,6 +90,9 @@
|
||||
diff --git a/daemon/daemon.c b/daemon/daemon.c
|
||||
index 7461a26..706f8f6 100644
|
||||
--- a/daemon/daemon.c
|
||||
+++ b/daemon/daemon.c
|
||||
@@ -91,6 +91,9 @@
|
||||
#include "sldns/keyraw.h"
|
||||
#include "respip/respip.h"
|
||||
#include <signal.h>
|
||||
@@ -101,36 +97,36 @@ 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
|
||||
@@ -460,6 +463,14 @@ daemon_create_workers(struct daemon* daemon)
|
||||
dt_apply_cfg(daemon->dtenv, daemon->cfg);
|
||||
#else
|
||||
fatal_exit("dnstap enabled in config but not built with dnstap support");
|
||||
#endif
|
||||
}
|
||||
+#endif
|
||||
+ }
|
||||
+ if(daemon->cfg->rpz_enable) {
|
||||
+#ifdef ENABLE_FASTRPZ
|
||||
+ rpz_init(&daemon->rpz_clist, &daemon->rpz_client, daemon->cfg);
|
||||
+#else
|
||||
+ fatal_exit("fastrpz enabled in config"
|
||||
+ " but not built with fastrpz");
|
||||
+#endif
|
||||
+ }
|
||||
#endif
|
||||
}
|
||||
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)
|
||||
@@ -718,6 +729,9 @@ daemon_cleanup(struct daemon* daemon)
|
||||
#ifdef USE_DNSCRYPT
|
||||
dnsc_delete(daemon->dnscenv);
|
||||
#endif
|
||||
daemon->dnscenv = NULL;
|
||||
+#endif
|
||||
+#ifdef ENABLE_FASTRPZ
|
||||
+ rpz_delete(&daemon->rpz_clist, &daemon->rpz_client);
|
||||
+#endif
|
||||
#endif
|
||||
daemon->cfg = NULL;
|
||||
}
|
||||
|
||||
Index: unbound-1.7.0~rc1/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 {
|
||||
diff --git a/daemon/daemon.h b/daemon/daemon.h
|
||||
index 5749dbe..64ce230 100644
|
||||
--- a/daemon/daemon.h
|
||||
+++ b/daemon/daemon.h
|
||||
@@ -136,6 +136,11 @@ struct daemon {
|
||||
/** 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
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/daemon/worker.c
|
||||
+++ unbound-1.7.0~rc1/daemon/worker.c
|
||||
@@ -74,6 +74,9 @@
|
||||
diff --git a/daemon/worker.c b/daemon/worker.c
|
||||
index fc93817..e435226 100644
|
||||
--- a/daemon/worker.c
|
||||
+++ b/daemon/worker.c
|
||||
@@ -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 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
/* 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,
|
||||
@@ -699,6 +721,23 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
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*
|
||||
@@ -1409,6 +1448,15 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
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:
|
||||
@@ -1457,12 +1505,21 @@ lookup_cache:
|
||||
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:
|
||||
@@ -1516,11 +1573,19 @@ lookup_cache:
|
||||
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
|
||||
===================================================================
|
||||
--- 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.
|
||||
diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in
|
||||
index c14ee27..0b71eaf 100644
|
||||
--- a/doc/unbound.conf.5.in
|
||||
+++ b/doc/unbound.conf.5.in
|
||||
@@ -1795,6 +1795,81 @@ 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 "Response Policy Zone Rewriting"
|
||||
+.LP
|
||||
+Response policy zone rewriting is controlled with the
|
||||
@@ -356,10 +352,11 @@ 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
|
||||
===================================================================
|
||||
diff --git a/fastrpz/librpz.h b/fastrpz/librpz.h
|
||||
new file mode 100644
|
||||
index 0000000..645279d
|
||||
--- /dev/null
|
||||
+++ unbound-1.7.0~rc1/fastrpz/librpz.h
|
||||
+++ b/fastrpz/librpz.h
|
||||
@@ -0,0 +1,957 @@
|
||||
+/*
|
||||
+ * Define the interface from a DNS resolver to the Response Policy Zone
|
||||
@@ -1318,11 +1315,12 @@ 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
|
||||
===================================================================
|
||||
diff --git a/fastrpz/rpz.c b/fastrpz/rpz.c
|
||||
new file mode 100644
|
||||
index 0000000..c5ab780
|
||||
--- /dev/null
|
||||
+++ unbound-1.7.0~rc1/fastrpz/rpz.c
|
||||
@@ -0,0 +1,1357 @@
|
||||
+++ b/fastrpz/rpz.c
|
||||
@@ -0,0 +1,1352 @@
|
||||
+/*
|
||||
+ * fastrpz/rpz.c - interface to the fastrpz response policy zone library
|
||||
+ *
|
||||
@@ -1438,8 +1436,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 +1945,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 +2673,11 @@ Index: unbound-1.7.0~rc1/fastrpz/rpz.c
|
||||
+}
|
||||
+
|
||||
+#endif /* ENABLE_FASTRPZ */
|
||||
Index: unbound-1.7.0~rc1/fastrpz/rpz.h
|
||||
===================================================================
|
||||
diff --git a/fastrpz/rpz.h b/fastrpz/rpz.h
|
||||
new file mode 100644
|
||||
index 0000000..5d7e31c
|
||||
--- /dev/null
|
||||
+++ unbound-1.7.0~rc1/fastrpz/rpz.h
|
||||
+++ b/fastrpz/rpz.h
|
||||
@@ -0,0 +1,138 @@
|
||||
+/*
|
||||
+ * fastrpz/rpz.h - interface to the fastrpz response policy zone library
|
||||
@@ -2823,10 +2817,11 @@ 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
|
||||
===================================================================
|
||||
diff --git a/fastrpz/rpz.m4 b/fastrpz/rpz.m4
|
||||
new file mode 100644
|
||||
index 0000000..2123535
|
||||
--- /dev/null
|
||||
+++ unbound-1.7.0~rc1/fastrpz/rpz.m4
|
||||
+++ b/fastrpz/rpz.m4
|
||||
@@ -0,0 +1,64 @@
|
||||
+# fastrpz/rpz.m4
|
||||
+
|
||||
@@ -2892,10 +2887,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
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/iterator/iterator.c
|
||||
+++ unbound-1.7.0~rc1/iterator/iterator.c
|
||||
diff --git a/iterator/iterator.c b/iterator/iterator.c
|
||||
index c906c27..55bf218 100644
|
||||
--- a/iterator/iterator.c
|
||||
+++ b/iterator/iterator.c
|
||||
@@ -68,6 +68,9 @@
|
||||
#include "sldns/str2wire.h"
|
||||
#include "sldns/parseutil.h"
|
||||
@@ -2904,9 +2899,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 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
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 +2925,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 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
|
||||
/* Other rrsets in the section are ignored. */
|
||||
}
|
||||
@@ -2940,7 +2935,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 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
uint8_t* delname;
|
||||
size_t delnamelen;
|
||||
struct dns_msg* msg = NULL;
|
||||
@@ -2948,7 +2943,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 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
if(msg) {
|
||||
/* handle positive cache response */
|
||||
@@ -2958,7 +2953,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 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
(int)msg->rep->ttl,
|
||||
(int)msg->rep->prefetch_ttl);
|
||||
}
|
||||
@@ -2981,7 +2976,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
|
||||
@@ -2714,6 +2752,62 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
sock_list_insert(&qstate->reply_origin,
|
||||
&qstate->reply->addr, qstate->reply->addrlen,
|
||||
qstate->region);
|
||||
@@ -3041,10 +3036,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
|
||||
@@ -3467,12 +3561,44 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* but only if we did recursion. The nonrecursion referral
|
||||
* from cache does not need to be stored in the msg cache. */
|
||||
if(!qstate->no_cache_store && qstate->query_flags&BIT_RD) {
|
||||
@@ -3089,11 +3084,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
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/iterator/iterator.h
|
||||
+++ unbound-1.7.0~rc1/iterator/iterator.h
|
||||
@@ -383,6 +383,16 @@ struct iter_qstate {
|
||||
diff --git a/iterator/iterator.h b/iterator/iterator.h
|
||||
index a2f1b57..e1e4a73 100644
|
||||
--- a/iterator/iterator.h
|
||||
+++ b/iterator/iterator.h
|
||||
@@ -386,6 +386,16 @@ struct iter_qstate {
|
||||
*/
|
||||
int minimise_count;
|
||||
|
||||
@@ -3110,11 +3105,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
|
||||
===================================================================
|
||||
--- 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,
|
||||
diff --git a/services/cache/dns.c b/services/cache/dns.c
|
||||
index aa4efec..5dd3412 100644
|
||||
--- a/services/cache/dns.c
|
||||
+++ b/services/cache/dns.c
|
||||
@@ -945,6 +945,14 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
struct regional* region, uint32_t flags)
|
||||
{
|
||||
struct reply_info* rep = NULL;
|
||||
@@ -3129,11 +3124,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
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/services/mesh.c
|
||||
+++ unbound-1.7.0~rc1/services/mesh.c
|
||||
@@ -59,6 +59,9 @@
|
||||
diff --git a/services/mesh.c b/services/mesh.c
|
||||
index d96289e..2e9f267 100644
|
||||
--- a/services/mesh.c
|
||||
+++ b/services/mesh.c
|
||||
@@ -60,6 +60,9 @@
|
||||
#include "sldns/wire2str.h"
|
||||
#include "services/localzone.h"
|
||||
#include "util/data/dname.h"
|
||||
@@ -3141,9 +3136,9 @@ Index: unbound-1.7.0~rc1/services/mesh.c
|
||||
+#include "fastrpz/rpz.h"
|
||||
+#endif
|
||||
#include "respip/respip.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
|
||||
/** subtract timers and the values do not overflow or become negative */
|
||||
@@ -1050,6 +1053,13 @@ mesh_send_reply(struct mesh_state* m, in
|
||||
@@ -1072,6 +1075,13 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
else secure = 0;
|
||||
if(!rep && rcode == LDNS_RCODE_NOERROR)
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
@@ -3157,7 +3152,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
|
||||
@@ -1247,6 +1257,7 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
|
||||
key.s.is_valrec = valrec;
|
||||
key.s.qinfo = *qinfo;
|
||||
key.s.query_flags = qflags;
|
||||
@@ -3165,7 +3160,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
|
||||
@@ -1293,6 +1304,10 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
|
||||
if(!r)
|
||||
return 0;
|
||||
r->query_reply = *rep;
|
||||
@@ -3176,11 +3171,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
|
||||
===================================================================
|
||||
--- 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)
|
||||
diff --git a/util/config_file.c b/util/config_file.c
|
||||
index 9b60254..d791f8f 100644
|
||||
--- a/util/config_file.c
|
||||
+++ b/util/config_file.c
|
||||
@@ -1418,6 +1418,8 @@ config_delete(struct config_file* cfg)
|
||||
free(cfg->dnstap_socket_path);
|
||||
free(cfg->dnstap_identity);
|
||||
free(cfg->dnstap_version);
|
||||
@@ -3189,11 +3184,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
|
||||
===================================================================
|
||||
--- 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 {
|
||||
diff --git a/util/config_file.h b/util/config_file.h
|
||||
index 3cffdbf..e0fa1c8 100644
|
||||
--- a/util/config_file.h
|
||||
+++ b/util/config_file.h
|
||||
@@ -490,6 +490,11 @@ struct config_file {
|
||||
/** true to disable DNSSEC lameness check in iterator */
|
||||
int disable_dnssec_lame_check;
|
||||
|
||||
@@ -3205,11 +3200,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
|
||||
===================================================================
|
||||
--- 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
|
||||
diff --git a/util/configlexer.lex b/util/configlexer.lex
|
||||
index 16b5bc5..038045d 100644
|
||||
--- a/util/configlexer.lex
|
||||
+++ b/util/configlexer.lex
|
||||
@@ -439,6 +439,10 @@ dnstap-log-forwarder-query-messages{COLON} {
|
||||
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES) }
|
||||
dnstap-log-forwarder-response-messages{COLON} {
|
||||
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES) }
|
||||
@@ -3220,11 +3215,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
|
||||
===================================================================
|
||||
--- 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
|
||||
diff --git a/util/configparser.y b/util/configparser.y
|
||||
index c7b9169..bef15b5 100644
|
||||
--- a/util/configparser.y
|
||||
+++ b/util/configparser.y
|
||||
@@ -125,6 +125,7 @@ extern struct config_parser_state* cfg_parser;
|
||||
%token VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES
|
||||
%token VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES
|
||||
%token VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES
|
||||
@@ -3232,7 +3227,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
|
||||
@@ -170,7 +171,7 @@ extern struct config_parser_state* cfg_parser;
|
||||
|
||||
%%
|
||||
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
|
||||
@@ -3241,8 +3236,8 @@ 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
|
||||
(strcmp($2, "yes")==0);
|
||||
@@ -2710,6 +2711,50 @@ dt_dnstap_log_forwarder_response_messages: VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MES
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
+rpzstart: VAR_RPZ
|
||||
@@ -3269,7 +3264,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 +3277,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 +3287,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
|
||||
===================================================================
|
||||
--- 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
|
||||
diff --git a/util/data/msgencode.c b/util/data/msgencode.c
|
||||
index 4c0a555..e51e9b8 100644
|
||||
--- a/util/data/msgencode.c
|
||||
+++ b/util/data/msgencode.c
|
||||
@@ -590,6 +590,35 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
|
||||
return RETVAL_OK;
|
||||
}
|
||||
|
||||
@@ -3332,7 +3327,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 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
|
||||
return 0;
|
||||
}
|
||||
sldns_buffer_write_u16_at(buffer, 10, arcount);
|
||||
@@ -3352,13 +3347,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
|
||||
===================================================================
|
||||
--- 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";
|
||||
diff --git a/util/data/packed_rrset.c b/util/data/packed_rrset.c
|
||||
index 7b9d549..e44b2ce 100644
|
||||
--- a/util/data/packed_rrset.c
|
||||
+++ b/util/data/packed_rrset.c
|
||||
@@ -255,6 +255,10 @@ sec_status_to_string(enum sec_status s)
|
||||
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 +3362,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
|
||||
===================================================================
|
||||
--- 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,
|
||||
diff --git a/util/data/packed_rrset.h b/util/data/packed_rrset.h
|
||||
index 3a5335d..2011321 100644
|
||||
--- a/util/data/packed_rrset.h
|
||||
+++ b/util/data/packed_rrset.h
|
||||
@@ -193,7 +193,15 @@ enum sec_status {
|
||||
sec_status_secure_sentinel_fail,
|
||||
/** SECURE means that the object (RRset or message) validated
|
||||
* according to local policy. */
|
||||
- sec_status_secure
|
||||
@@ -3388,11 +3383,11 @@ Index: unbound-1.7.0~rc1/util/data/packed_rrset.h
|
||||
};
|
||||
|
||||
/**
|
||||
Index: unbound-1.7.0~rc1/util/netevent.c
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/util/netevent.c
|
||||
+++ unbound-1.7.0~rc1/util/netevent.c
|
||||
@@ -54,6 +54,9 @@
|
||||
diff --git a/util/netevent.c b/util/netevent.c
|
||||
index b8b2a09..5ccc29a 100644
|
||||
--- a/util/netevent.c
|
||||
+++ b/util/netevent.c
|
||||
@@ -57,6 +57,9 @@
|
||||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
@@ -3402,7 +3397,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
|
||||
@@ -590,6 +593,9 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg)
|
||||
struct cmsghdr* cmsg;
|
||||
#endif /* S_SPLINT_S */
|
||||
|
||||
@@ -3412,7 +3407,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
|
||||
@@ -679,6 +685,9 @@ comm_point_udp_callback(int fd, short event, void* arg)
|
||||
int i;
|
||||
struct sldns_buffer *buffer;
|
||||
|
||||
@@ -3422,7 +3417,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
|
||||
@@ -722,6 +731,9 @@ comm_point_udp_callback(int fd, short event, void* arg)
|
||||
(void)comm_point_send_udp_msg(rep.c, buffer,
|
||||
(struct sockaddr*)&rep.addr, rep.addrlen);
|
||||
}
|
||||
@@ -3432,9 +3427,9 @@ 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
|
||||
comm_point_start_listening(repinfo->c, -1,
|
||||
repinfo->c->tcp_timeout_msec);
|
||||
@@ -3142,6 +3154,9 @@ comm_point_send_reply(struct comm_reply *repinfo)
|
||||
repinfo->c->tcp_timeout_msec);
|
||||
}
|
||||
}
|
||||
+#ifdef ENABLE_FASTRPZ
|
||||
+ rpz_end(repinfo);
|
||||
@@ -3442,7 +3437,7 @@ Index: unbound-1.7.0~rc1/util/netevent.c
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2965,6 +2980,9 @@ comm_point_drop_reply(struct comm_reply*
|
||||
@@ -3151,6 +3166,9 @@ comm_point_drop_reply(struct comm_reply* repinfo)
|
||||
return;
|
||||
log_assert(repinfo && repinfo->c);
|
||||
log_assert(repinfo->c->type != comm_tcp_accept);
|
||||
@@ -3451,22 +3446,22 @@ Index: unbound-1.7.0~rc1/util/netevent.c
|
||||
+#endif
|
||||
if(repinfo->c->type == comm_udp)
|
||||
return;
|
||||
reclaim_tcp_handler(repinfo->c);
|
||||
@@ -2984,6 +3002,9 @@ comm_point_start_listening(struct comm_p
|
||||
if(repinfo->c->tcp_req_info)
|
||||
@@ -3172,6 +3190,9 @@ comm_point_start_listening(struct comm_point* c, int newfd, int msec)
|
||||
{
|
||||
verbose(VERB_ALGO, "comm point start listening %d",
|
||||
c->fd==-1?newfd:c->fd);
|
||||
verbose(VERB_ALGO, "comm point start listening %d (%d msec)",
|
||||
c->fd==-1?newfd:c->fd, msec);
|
||||
+#ifdef ENABLE_FASTRPZ
|
||||
+ rpz_end(&c->repinfo);
|
||||
+#endif
|
||||
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
|
||||
===================================================================
|
||||
--- unbound-1.7.0~rc1.orig/util/netevent.h
|
||||
+++ unbound-1.7.0~rc1/util/netevent.h
|
||||
@@ -119,6 +119,10 @@ struct comm_reply {
|
||||
diff --git a/util/netevent.h b/util/netevent.h
|
||||
index d80c72b..0233292 100644
|
||||
--- a/util/netevent.h
|
||||
+++ b/util/netevent.h
|
||||
@@ -120,6 +120,10 @@ struct comm_reply {
|
||||
/** return type 0 (none), 4(IP4), 6(IP6) */
|
||||
int srctype;
|
||||
/* DnsCrypt context */
|
||||
@@ -3477,11 +3472,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
|
||||
===================================================================
|
||||
--- 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*
|
||||
diff --git a/validator/validator.c b/validator/validator.c
|
||||
index fa8d541..5628ef0 100644
|
||||
--- a/validator/validator.c
|
||||
+++ b/validator/validator.c
|
||||
@@ -2755,6 +2755,12 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
|
||||
default:
|
||||
/* NSEC proof did not work, try next */
|
||||
break;
|
||||
@@ -3494,7 +3489,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 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
|
||||
default:
|
||||
/* NSEC3 proof did not work */
|
||||
break;
|
||||
@@ -3507,4 +3502,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: @PC_LIBEVENT_DEPENDENCY@ @PC_PY_DEPENDENCY@
|
||||
Requires: libcrypto libssl @PC_LIBEVENT_DEPENDENCY@
|
||||
Requires.private: @PC_PY_DEPENDENCY@
|
||||
Libs: -L${libdir} -lunbound -lssl -lcrypto
|
||||
Libs.private: @SSLLIB@ @LIBS@
|
||||
Cflags: -I${includedir}
|
||||
|
||||
@@ -14,6 +14,7 @@ int ub_ctx_set_option(ub_ctx*, string, string);
|
||||
int ub_ctx_get_option(ub_ctx*, string, +string*);
|
||||
int ub_ctx_config(ub_ctx*, string);
|
||||
int ub_ctx_set_fwd(ub_ctx*, string);
|
||||
int ub_ctx_set_tls(ub_ctx*, bool(int));
|
||||
int ub_ctx_set_stub(ub_ctx*, string, string, bool(int));
|
||||
int ub_ctx_resolvconf(ub_ctx*, string);
|
||||
int ub_ctx_hosts(ub_ctx*, string);
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
>From cc9b927f8f29d989ddb8415fe6508a538546abca Mon Sep 17 00:00:00 2001
|
||||
From: Jacob Hoffman-Andrews <github@hoffman-andrews.com>
|
||||
Date: Wed, 2 Jan 2019 22:52:51 -0800
|
||||
Subject: [PATCH] Add unbound-fuzzme.
|
||||
|
||||
This is a small program that simply parses a packet provided on stdout,
|
||||
for the purposes of fuzzing.
|
||||
---
|
||||
.gitignore | 1 +
|
||||
Makefile.in | 22 ++++++++++++++++++++--
|
||||
smallapp/unbound-fuzzme.c | 38 ++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 59 insertions(+), 2 deletions(-)
|
||||
create mode 100644 smallapp/unbound-fuzzme.c
|
||||
|
||||
diff --git a/.gitignore b/.gitignore
|
||||
index f4527fd8..6163f905 100644
|
||||
--- a/.gitignore
|
||||
+++ b/.gitignore
|
||||
@@ -24,6 +24,7 @@
|
||||
/unbound-checkconf
|
||||
/unbound-control
|
||||
/unbound-control-setup
|
||||
+/unbound-fuzzme
|
||||
/unbound-host
|
||||
/unbound.h
|
||||
/asynclook
|
||||
diff --git a/Makefile.in b/Makefile.in
|
||||
index af5b10f6..dacf1ab5 100644
|
||||
--- a/Makefile.in
|
||||
+++ b/Makefile.in
|
||||
@@ -177,6 +177,10 @@ shm_main.lo remote.lo stats.lo unbound.lo \
|
||||
worker.lo @WIN_DAEMON_OBJ@
|
||||
DAEMON_OBJ_LINK=$(DAEMON_OBJ) $(COMMON_OBJ_ALL_SYMBOLS) $(SLDNS_OBJ) \
|
||||
$(COMPAT_OBJ) @WIN_DAEMON_OBJ_LINK@
|
||||
+FUZZME_SRC=smallapp/unbound-fuzzme.c
|
||||
+FUZZME_OBJ=unbound-fuzzme.lo
|
||||
+FUZZME_OBJ_LINK=$(FUZZME_OBJ) worker_cb.lo $(COMMON_OBJ_ALL_SYMBOLS) $(SLDNS_OBJ) \
|
||||
+$(COMPAT_OBJ)
|
||||
CHECKCONF_SRC=smallapp/unbound-checkconf.c smallapp/worker_cb.c
|
||||
CHECKCONF_OBJ=unbound-checkconf.lo worker_cb.lo
|
||||
CHECKCONF_OBJ_LINK=$(CHECKCONF_OBJ) $(COMMON_OBJ_ALL_SYMBOLS) $(SLDNS_OBJ) \
|
||||
@@ -252,6 +256,7 @@ RSRC_OBJ=rsrc_svcinst.o rsrc_svcuninst.o rsrc_anchorupd.o rsrc_unbound.o \
|
||||
rsrc_unbound_checkconf.o
|
||||
|
||||
ALL_SRC=$(COMMON_SRC) $(UNITTEST_SRC) $(DAEMON_SRC) \
|
||||
+ $(FUZZME_SRC) \
|
||||
$(TESTBOUND_SRC) $(LOCKVERIFY_SRC) $(PKTVIEW_SRC) \
|
||||
$(MEMSTATS_SRC) $(CHECKCONF_SRC) $(LIBUNBOUND_SRC) $(HOST_SRC) \
|
||||
$(ASYNCLOOK_SRC) $(STREAMTCP_SRC) $(PERF_SRC) $(DELAYER_SRC) \
|
||||
@@ -259,6 +264,7 @@ ALL_SRC=$(COMMON_SRC) $(UNITTEST_SRC) $(DAEMON_SRC) \
|
||||
$(PYTHONMOD_SRC) $(PYUNBOUND_SRC) $(WIN_DAEMON_THE_SRC)\
|
||||
$(SVCINST_SRC) $(SVCUNINST_SRC) $(ANCHORUPD_SRC) $(SLDNS_SRC)
|
||||
ALL_OBJ=$(COMMON_OBJ) $(UNITTEST_OBJ) $(DAEMON_OBJ) \
|
||||
+ $(FUZZME_OBJ) \
|
||||
$(TESTBOUND_OBJ) $(LOCKVERIFY_OBJ) $(PKTVIEW_OBJ) \
|
||||
$(MEMSTATS_OBJ) $(CHECKCONF_OBJ) $(LIBUNBOUND_OBJ) $(HOST_OBJ) \
|
||||
$(ASYNCLOOK_OBJ) $(STREAMTCP_OBJ) $(PERF_OBJ) $(DELAYER_OBJ) \
|
||||
@@ -274,7 +280,7 @@ LINK_LIB=$(LIBTOOL) --tag=CC --mode=link $(CC) $(RUNTIME_PATH) $(CPPFLAGS) $(CFL
|
||||
|
||||
all: $(COMMON_OBJ) $(ALLTARGET)
|
||||
|
||||
-alltargets: unbound$(EXEEXT) unbound-checkconf$(EXEEXT) lib unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup $(WINAPPS) $(PYUNBOUND_TARGET)
|
||||
+alltargets: unbound$(EXEEXT) unbound-checkconf$(EXEEXT) lib unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup unbound-fuzzme$(EXEEXT) $(WINAPPS) $(PYUNBOUND_TARGET)
|
||||
|
||||
# compat with BSD make, register suffix, and an implicit rule to actualise it.
|
||||
.SUFFIXES: .lo
|
||||
@@ -325,6 +331,9 @@ libunbound.la: $(LIBUNBOUND_OBJ_LINK)
|
||||
unbound$(EXEEXT): $(DAEMON_OBJ_LINK) libunbound.la
|
||||
$(LINK) -o $@ $(DAEMON_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS)
|
||||
|
||||
+unbound-fuzzme$(EXEEXT): $(FUZZME_OBJ_LINK) libunbound.la
|
||||
+ $(LINK) -o $@ $(FUZZME_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS)
|
||||
+
|
||||
unbound-checkconf$(EXEEXT): $(CHECKCONF_OBJ_LINK) libunbound.la
|
||||
$(LINK) -o $@ $(CHECKCONF_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS)
|
||||
|
||||
@@ -447,7 +456,7 @@ util/configparser.c util/configparser.h: $(srcdir)/util/configparser.y
|
||||
|
||||
clean:
|
||||
rm -f *.o *.d *.lo *~ tags
|
||||
- rm -f unbound$(EXEEXT) unbound-checkconf$(EXEEXT) unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup libunbound.la unbound.h
|
||||
+ rm -f unbound$(EXEEXT) unbound-checkconf$(EXEEXT) unbound-fuzzme$(EXEEXT) unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup libunbound.la unbound.h
|
||||
rm -f $(ALL_SRC:.c=.lint)
|
||||
rm -f _unbound.la libunbound/python/libunbound_wrap.c libunbound/python/unbound.py pythonmod/interface.h pythonmod/unboundmodule.py
|
||||
rm -rf autom4te.cache .libs build doc/html doc/xml
|
||||
@@ -1183,6 +1192,15 @@ stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(s
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
|
||||
$(srcdir)/util/rtt.h $(srcdir)/services/authzone.h $(srcdir)/validator/val_kcache.h \
|
||||
$(srcdir)/validator/val_neg.h
|
||||
+unbound-fuzzme.lo unbound-fuzzme.o: $(srcdir)/smallapp/unbound-fuzzme.c \
|
||||
+ $(srcdir)/util/locks.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
|
||||
+ $(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h \
|
||||
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h $(srcdir)/services/listen_dnsport.h \
|
||||
+ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/services/cache/rrset.h \
|
||||
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
|
||||
+ $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/fptr_wlist.h \
|
||||
+ $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
|
||||
+ $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/net_help.h $(srcdir)/util/ub_event.h
|
||||
unbound.lo unbound.o: $(srcdir)/daemon/unbound.c config.h $(srcdir)/util/log.h $(srcdir)/daemon/daemon.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/daemon/remote.h \
|
||||
diff --git a/smallapp/unbound-fuzzme.c b/smallapp/unbound-fuzzme.c
|
||||
new file mode 100644
|
||||
index 00000000..74ae5204
|
||||
--- /dev/null
|
||||
+++ b/smallapp/unbound-fuzzme.c
|
||||
@@ -0,0 +1,38 @@
|
||||
+/*
|
||||
+ * unbound-fuzzme.c - parse a packet provided on stdin (for fuzzing).
|
||||
+ *
|
||||
+ */
|
||||
+#include "config.h"
|
||||
+#include "util/regional.h"
|
||||
+#include "util/fptr_wlist.h"
|
||||
+#include "sldns/sbuffer.h"
|
||||
+
|
||||
+#define SZ 10000
|
||||
+
|
||||
+int main() {
|
||||
+ char buffer[SZ];
|
||||
+ size_t n_read = fread(buffer, 1, SZ, stdin);
|
||||
+ if (n_read == SZ) {
|
||||
+ printf("input too big\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ sldns_buffer *pkt = sldns_buffer_new(n_read);
|
||||
+ sldns_buffer_init_frm_data(pkt, buffer, n_read);
|
||||
+
|
||||
+ struct regional *region = regional_create();
|
||||
+
|
||||
+ struct msg_parse* prs;
|
||||
+ struct edns_data edns;
|
||||
+ prs = (struct msg_parse*)malloc(sizeof(struct msg_parse));
|
||||
+ if(!prs) {
|
||||
+ printf("out of memory on incoming message\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ memset(prs, 0, sizeof(*prs));
|
||||
+ memset(&edns, 0, sizeof(edns));
|
||||
+ sldns_buffer_set_position(pkt, 0);
|
||||
+ if(parse_packet(pkt, prs, region) != LDNS_RCODE_NOERROR) {
|
||||
+ printf("parse error\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@@ -39,13 +39,13 @@ start() {
|
||||
# setup root jail
|
||||
if [ -s /etc/localtime ]; then
|
||||
[ -d ${rootdir}/etc ] || mkdir -p ${rootdir}/etc ;
|
||||
if [ ! -e ${rootdir}/etc/localtime ] || /usr/bin/cmp -s /etc/localtime ${rootdir}/etc/localtime; then
|
||||
if [ ! -e ${rootdir}/etc/localtime ] || ! /usr/bin/cmp -s /etc/localtime ${rootdir}/etc/localtime; then
|
||||
cp -fp /etc/localtime ${rootdir}/etc/localtime
|
||||
fi;
|
||||
fi;
|
||||
if [ -s /etc/resolv.conf ]; then
|
||||
[ -d ${rootdir}/etc ] || mkdir -p ${rootdir}/etc ;
|
||||
if [ ! -e ${rootdir}/etc/resolv.conf ] || /usr/bin/cmp -s /etc/resolv.conf ${rootdir}/etc/resolv.conf; then
|
||||
if [ ! -e ${rootdir}/etc/resolv.conf ] || ! /usr/bin/cmp -s /etc/resolv.conf ${rootdir}/etc/resolv.conf; then
|
||||
cp -fp /etc/resolv.conf ${rootdir}/etc/resolv.conf
|
||||
fi;
|
||||
fi;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -653,6 +653,7 @@ load_msg(RES* 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");
|
||||
|
||||
+22
-17
@@ -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);
|
||||
|
||||
@@ -738,18 +744,18 @@ 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);
|
||||
#ifdef HAVE_SSL
|
||||
listen_sslctx_delete_ticket_keys();
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_sslctx);
|
||||
SSL_CTX_free((SSL_CTX*)daemon->connect_sslctx);
|
||||
#endif
|
||||
free(daemon);
|
||||
#ifdef LEX_HAS_YYLEX_DESTROY
|
||||
/* lex cleanup */
|
||||
ub_c_lex_destroy();
|
||||
#endif
|
||||
/* libcrypto cleanup */
|
||||
#ifdef HAVE_SSL
|
||||
# if defined(USE_GOST) && defined(HAVE_LDNS_KEY_EVP_UNLOAD_GOST)
|
||||
@@ -764,7 +770,7 @@ daemon_delete(struct daemon* daemon)
|
||||
# endif
|
||||
# ifdef HAVE_OPENSSL_CONFIG
|
||||
EVP_cleanup();
|
||||
# if OPENSSL_VERSION_NUMBER < 0x10100000
|
||||
# if (OPENSSL_VERSION_NUMBER < 0x10100000) && !defined(OPENSSL_NO_ENGINE)
|
||||
ENGINE_cleanup();
|
||||
# endif
|
||||
CONF_modules_free();
|
||||
@@ -800,9 +806,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 */
|
||||
|
||||
+132
-13
@@ -208,7 +208,7 @@ daemon_remote_create(struct config_file* cfg)
|
||||
rc->ctx = NULL;
|
||||
return rc;
|
||||
}
|
||||
if(options_remote_is_address(cfg)) {
|
||||
if(options_remote_is_address(cfg) && cfg->control_use_cert) {
|
||||
if(!remote_setup_ctx(rc, cfg)) {
|
||||
daemon_remote_delete(rc);
|
||||
return NULL;
|
||||
@@ -218,7 +218,8 @@ daemon_remote_create(struct config_file* cfg)
|
||||
struct config_strlist* p;
|
||||
rc->ctx = NULL;
|
||||
rc->use_cert = 0;
|
||||
for(p = cfg->control_ifs.first; p; p = p->next) {
|
||||
if(!options_remote_is_address(cfg))
|
||||
for(p = cfg->control_ifs.first; p; p = p->next) {
|
||||
if(p->str && p->str[0] != '/')
|
||||
log_warn("control-interface %s is not using TLS, but plain transfer, because first control-interface in config file is a local socket (starts with a /).", p->str);
|
||||
}
|
||||
@@ -274,12 +275,13 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
|
||||
struct addrinfo hints;
|
||||
struct addrinfo* res;
|
||||
struct listen_port* n;
|
||||
int noproto;
|
||||
int noproto = 0;
|
||||
int fd, r;
|
||||
char port[15];
|
||||
snprintf(port, sizeof(port), "%d", nr);
|
||||
port[sizeof(port)-1]=0;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
log_assert(ip);
|
||||
|
||||
if(ip[0] == '/') {
|
||||
/* This looks like a local socket */
|
||||
@@ -567,11 +569,15 @@ ssl_print_text(RES* res, const char* text)
|
||||
} else {
|
||||
size_t at = 0;
|
||||
while(at < strlen(text)) {
|
||||
ssize_t r = write(res->fd, text+at, strlen(text)-at);
|
||||
ssize_t r = send(res->fd, text+at, strlen(text)-at, 0);
|
||||
if(r == -1) {
|
||||
if(errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
log_err("could not write: %s", strerror(errno));
|
||||
#ifndef USE_WINSOCK
|
||||
log_err("could not send: %s", strerror(errno));
|
||||
#else
|
||||
log_err("could not send: %s", wsa_strerror(WSAGetLastError()));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
at += r;
|
||||
@@ -620,7 +626,7 @@ ssl_read_line(RES* res, char* buf, size_t max)
|
||||
}
|
||||
} else {
|
||||
while(1) {
|
||||
ssize_t rr = read(res->fd, buf+len, 1);
|
||||
ssize_t rr = recv(res->fd, buf+len, 1, 0);
|
||||
if(rr <= 0) {
|
||||
if(rr == 0) {
|
||||
buf[len] = 0;
|
||||
@@ -628,7 +634,11 @@ ssl_read_line(RES* res, char* buf, size_t max)
|
||||
}
|
||||
if(errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
log_err("could not read: %s", strerror(errno));
|
||||
#ifndef USE_WINSOCK
|
||||
log_err("could not recv: %s", strerror(errno));
|
||||
#else
|
||||
log_err("could not recv: %s", wsa_strerror(WSAGetLastError()));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
@@ -779,7 +789,8 @@ print_longnum(RES* ssl, const char* desc, size_t x)
|
||||
|
||||
/** print mem stats */
|
||||
static int
|
||||
print_mem(RES* ssl, struct worker* worker, struct daemon* daemon)
|
||||
print_mem(RES* ssl, struct worker* worker, struct daemon* daemon,
|
||||
struct ub_stats_info* s)
|
||||
{
|
||||
size_t msg, rrset, val, iter, respip;
|
||||
#ifdef CLIENT_SUBNET
|
||||
@@ -837,6 +848,9 @@ print_mem(RES* ssl, struct worker* worker, struct daemon* daemon)
|
||||
dnscrypt_nonce))
|
||||
return 0;
|
||||
#endif /* USE_DNSCRYPT */
|
||||
if(!print_longnum(ssl, "mem.streamwait"SQ,
|
||||
(size_t)s->svr.mem_stream_wait))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -957,6 +971,10 @@ print_ext(RES* ssl, struct ub_stats_info* s)
|
||||
(unsigned long)s->svr.qtcp)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.tcpout"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qtcp_outgoing)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.tls"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qtls)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.tls.resume"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qtls_resume)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.ipv6"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qipv6)) return 0;
|
||||
/* flags */
|
||||
@@ -1041,6 +1059,12 @@ print_ext(RES* ssl, struct ub_stats_info* s)
|
||||
(unsigned long)s->svr.num_query_authzone_up)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.authzone.down"SQ"%lu\n",
|
||||
(unsigned long)s->svr.num_query_authzone_down)) return 0;
|
||||
#ifdef CLIENT_SUBNET
|
||||
if(!ssl_printf(ssl, "num.query.subnet"SQ"%lu\n",
|
||||
(unsigned long)s->svr.num_query_subnet)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.subnet_cache"SQ"%lu\n",
|
||||
(unsigned long)s->svr.num_query_subnet_cache)) return 0;
|
||||
#endif /* CLIENT_SUBNET */
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1052,6 +1076,7 @@ do_stats(RES* ssl, struct daemon_remote* rc, int reset)
|
||||
struct ub_stats_info total;
|
||||
struct ub_stats_info s;
|
||||
int i;
|
||||
memset(&total, 0, sizeof(total));
|
||||
log_assert(daemon->num > 0);
|
||||
/* gather all thread statistics in one place */
|
||||
for(i=0; i<daemon->num; i++) {
|
||||
@@ -1069,7 +1094,7 @@ do_stats(RES* ssl, struct daemon_remote* rc, int reset)
|
||||
if(!print_uptime(ssl, rc->worker, reset))
|
||||
return;
|
||||
if(daemon->cfg->stat_extended) {
|
||||
if(!print_mem(ssl, rc->worker, daemon))
|
||||
if(!print_mem(ssl, rc->worker, daemon, &total))
|
||||
return;
|
||||
if(!print_hist(ssl, &total))
|
||||
return;
|
||||
@@ -1409,6 +1434,28 @@ do_view_data_add(RES* ssl, struct worker* worker, char* arg)
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
|
||||
/** Add new RR data from stdin to view */
|
||||
static void
|
||||
do_view_datas_add(RES* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
struct view* v;
|
||||
v = views_find_view(worker->daemon->views,
|
||||
arg, 1 /* get write lock*/);
|
||||
if(!v) {
|
||||
ssl_printf(ssl,"no view with name: %s\n", arg);
|
||||
return;
|
||||
}
|
||||
if(!v->local_zones) {
|
||||
if(!(v->local_zones = local_zones_create())){
|
||||
lock_rw_unlock(&v->lock);
|
||||
ssl_printf(ssl,"error out of memory\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
do_datas_add(ssl, v->local_zones);
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
|
||||
/** Remove RR data from view */
|
||||
static void
|
||||
do_view_data_remove(RES* ssl, struct worker* worker, char* arg)
|
||||
@@ -1616,6 +1663,7 @@ zone_del_msg(struct lruhash_entry* e, void* arg)
|
||||
if(d->ttl > inf->expired) {
|
||||
d->ttl = inf->expired;
|
||||
d->prefetch_ttl = inf->expired;
|
||||
d->serve_expired_ttl = inf->expired;
|
||||
inf->num_msgs++;
|
||||
}
|
||||
}
|
||||
@@ -1939,6 +1987,11 @@ parse_delegpt(RES* ssl, char* args, uint8_t* nm, int allow_names)
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
|
||||
if(auth_name)
|
||||
log_err("no name verification functionality in "
|
||||
"ssl library, ignored name for %s", todo);
|
||||
#endif
|
||||
/* add address */
|
||||
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
|
||||
auth_name)) {
|
||||
@@ -2207,9 +2260,12 @@ do_status(RES* ssl, struct worker* worker)
|
||||
uptime = (time_t)time(NULL) - (time_t)worker->daemon->time_boot.tv_sec;
|
||||
if(!ssl_printf(ssl, "uptime: " ARG_LL "d seconds\n", (long long)uptime))
|
||||
return;
|
||||
if(!ssl_printf(ssl, "options:%s%s\n" ,
|
||||
if(!ssl_printf(ssl, "options:%s%s%s%s\n" ,
|
||||
(worker->daemon->reuseport?" reuseport":""),
|
||||
(worker->daemon->rc->accept_list?(worker->daemon->rc->use_cert?" control(ssl)":" control(namedpipe)"):"")))
|
||||
(worker->daemon->rc->accept_list?" control":""),
|
||||
(worker->daemon->rc->accept_list && worker->daemon->rc->use_cert?"(ssl)":""),
|
||||
(worker->daemon->rc->accept_list && worker->daemon->cfg->control_ifs.first && worker->daemon->cfg->control_ifs.first->str && worker->daemon->cfg->control_ifs.first->str[0] == '/'?"(namedpipe)":"")
|
||||
))
|
||||
return;
|
||||
if(!ssl_printf(ssl, "unbound (pid %d) is running...\n",
|
||||
(int)getpid()))
|
||||
@@ -2404,6 +2460,57 @@ do_log_reopen(RES* ssl, struct worker* worker)
|
||||
log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
|
||||
}
|
||||
|
||||
/** do the auth_zone_reload command */
|
||||
static void
|
||||
do_auth_zone_reload(RES* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
size_t nmlen;
|
||||
int nmlabs;
|
||||
uint8_t* nm = NULL;
|
||||
struct auth_zones* az = worker->env.auth_zones;
|
||||
struct auth_zone* z = NULL;
|
||||
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
|
||||
return;
|
||||
if(az) {
|
||||
lock_rw_rdlock(&az->lock);
|
||||
z = auth_zone_find(az, nm, nmlen, LDNS_RR_CLASS_IN);
|
||||
if(z) {
|
||||
lock_rw_wrlock(&z->lock);
|
||||
}
|
||||
lock_rw_unlock(&az->lock);
|
||||
}
|
||||
free(nm);
|
||||
if(!z) {
|
||||
(void)ssl_printf(ssl, "error no auth-zone %s\n", arg);
|
||||
return;
|
||||
}
|
||||
if(!auth_zone_read_zonefile(z, worker->env.cfg)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
(void)ssl_printf(ssl, "error failed to read %s\n", arg);
|
||||
return;
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** do the auth_zone_transfer command */
|
||||
static void
|
||||
do_auth_zone_transfer(RES* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
size_t nmlen;
|
||||
int nmlabs;
|
||||
uint8_t* nm = NULL;
|
||||
struct auth_zones* az = worker->env.auth_zones;
|
||||
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
|
||||
return;
|
||||
if(!az || !auth_zones_startprobesequence(az, &worker->env, nm, nmlen,
|
||||
LDNS_RR_CLASS_IN)) {
|
||||
(void)ssl_printf(ssl, "error zone xfr task not found %s\n", arg);
|
||||
return;
|
||||
}
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** do the set_option command */
|
||||
static void
|
||||
do_set_option(RES* ssl, struct worker* worker, char* arg)
|
||||
@@ -2794,6 +2901,12 @@ execute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd,
|
||||
} else if(cmdcmp(p, "list_auth_zones", 15)) {
|
||||
do_list_auth_zones(ssl, worker->env.auth_zones);
|
||||
return;
|
||||
} else if(cmdcmp(p, "auth_zone_reload", 16)) {
|
||||
do_auth_zone_reload(ssl, worker, skipwhite(p+16));
|
||||
return;
|
||||
} else if(cmdcmp(p, "auth_zone_transfer", 18)) {
|
||||
do_auth_zone_transfer(ssl, worker, skipwhite(p+18));
|
||||
return;
|
||||
} else if(cmdcmp(p, "stub_add", 8)) {
|
||||
/* must always distribute this cmd */
|
||||
if(rc) distribute_cmd(rc, ssl, cmd);
|
||||
@@ -2878,6 +2991,8 @@ execute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd,
|
||||
do_view_data_remove(ssl, worker, skipwhite(p+22));
|
||||
} else if(cmdcmp(p, "view_local_data", 15)) {
|
||||
do_view_data_add(ssl, worker, skipwhite(p+15));
|
||||
} else if(cmdcmp(p, "view_local_datas", 16)) {
|
||||
do_view_datas_add(ssl, worker, skipwhite(p+16));
|
||||
} else if(cmdcmp(p, "flush_zone", 10)) {
|
||||
do_flush_zone(ssl, worker, skipwhite(p+10));
|
||||
} else if(cmdcmp(p, "flush_type", 10)) {
|
||||
@@ -2946,12 +3061,16 @@ handle_req(struct daemon_remote* rc, struct rc_state* s, RES* res)
|
||||
}
|
||||
} else {
|
||||
while(1) {
|
||||
ssize_t rr = read(res->fd, magic, sizeof(magic)-1);
|
||||
ssize_t rr = recv(res->fd, magic, sizeof(magic)-1, 0);
|
||||
if(rr <= 0) {
|
||||
if(rr == 0) return;
|
||||
if(errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
log_err("could not read: %s", strerror(errno));
|
||||
#ifndef USE_WINSOCK
|
||||
log_err("could not recv: %s", strerror(errno));
|
||||
#else
|
||||
log_err("could not recv: %s", wsa_strerror(WSAGetLastError()));
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
r = (int)rr;
|
||||
|
||||
+53
-1
@@ -63,6 +63,12 @@
|
||||
#include "services/authzone.h"
|
||||
#include "validator/val_kcache.h"
|
||||
#include "validator/val_neg.h"
|
||||
#ifdef CLIENT_SUBNET
|
||||
#include "edns-subnet/subnetmod.h"
|
||||
#endif
|
||||
#ifdef HAVE_SSL
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
|
||||
/** add timers and the values do not overflow or become negative */
|
||||
static void
|
||||
@@ -124,6 +130,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,
|
||||
@@ -298,9 +331,18 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
}
|
||||
lock_rw_unlock(&worker->env.auth_zones->lock);
|
||||
}
|
||||
s->svr.mem_stream_wait =
|
||||
(long long)tcp_req_info_get_stream_buffer_size();
|
||||
|
||||
/* 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 +416,8 @@ 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.qtls_resume += a->svr.qtls_resume;
|
||||
total->svr.qipv6 += a->svr.qipv6;
|
||||
total->svr.qbit_QR += a->svr.qbit_QR;
|
||||
total->svr.qbit_AA += a->svr.qbit_AA;
|
||||
@@ -428,8 +472,16 @@ 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++;
|
||||
#ifdef HAVE_SSL
|
||||
if(SSL_session_reused(c->ssl))
|
||||
stats->qtls_resume++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if(repinfo && addr_is_ip6(&repinfo->addr, repinfo->addrlen))
|
||||
stats->qipv6++;
|
||||
if( (flags&BIT_QR) )
|
||||
|
||||
+25
-3
@@ -67,6 +67,7 @@
|
||||
#ifdef HAVE_GRP_H
|
||||
#include <grp.h>
|
||||
#endif
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#ifndef S_SPLINT_S
|
||||
/* splint chokes on this system header file */
|
||||
@@ -101,6 +102,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");
|
||||
@@ -429,6 +431,24 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
if(!(daemon->listen_sslctx = listen_sslctx_create(
|
||||
cfg->ssl_service_key, cfg->ssl_service_pem, NULL)))
|
||||
fatal_exit("could not set up listen SSL_CTX");
|
||||
if(cfg->tls_ciphers && cfg->tls_ciphers[0]) {
|
||||
if (!SSL_CTX_set_cipher_list(daemon->listen_sslctx, cfg->tls_ciphers)) {
|
||||
fatal_exit("failed to set tls-cipher %s", cfg->tls_ciphers);
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
|
||||
if(cfg->tls_ciphersuites && cfg->tls_ciphersuites[0]) {
|
||||
if (!SSL_CTX_set_ciphersuites(daemon->listen_sslctx, cfg->tls_ciphersuites)) {
|
||||
fatal_exit("failed to set tls-ciphersuites %s", cfg->tls_ciphersuites);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(cfg->tls_session_ticket_keys.first &&
|
||||
cfg->tls_session_ticket_keys.first->str[0] != 0) {
|
||||
if(!listen_sslctx_setup_ticket_keys(daemon->listen_sslctx, cfg->tls_session_ticket_keys.first)) {
|
||||
fatal_exit("could not set session ticket SSL_CTX");
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL,
|
||||
cfg->tls_cert_bundle, cfg->tls_win_cert)))
|
||||
@@ -626,8 +646,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 +749,7 @@ main(int argc, char* argv[])
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
/* argv += optind; not using further arguments */
|
||||
|
||||
if(winopt) {
|
||||
#ifdef UB_ON_WINDOWS
|
||||
|
||||
+128
-78
@@ -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
|
||||
@@ -652,10 +660,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
if(!reply_check_cname_chain(qinfo, rep)) {
|
||||
/* cname chain invalid, redo iterator steps */
|
||||
verbose(VERB_ALGO, "Cache reply: cname chain broken");
|
||||
bail_out:
|
||||
rrset_array_unlock_touch(worker->env.rrset_cache,
|
||||
worker->scratchpad, rep->ref, rep->rrset_count);
|
||||
return 0;
|
||||
goto bail_out;
|
||||
}
|
||||
}
|
||||
/* check security status of the cached answer */
|
||||
@@ -667,7 +672,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 +700,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 +734,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);
|
||||
@@ -747,6 +755,11 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
}
|
||||
/* go and return this buffer to the client */
|
||||
return 1;
|
||||
|
||||
bail_out:
|
||||
rrset_array_unlock_touch(worker->env.rrset_cache,
|
||||
worker->scratchpad, rep->ref, rep->rrset_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Reply to client and perform prefetch to keep cache up to date.
|
||||
@@ -779,10 +792,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 +829,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 +839,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 +849,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 +864,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 +898,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 +907,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 +929,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 +946,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 +955,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;
|
||||
}
|
||||
|
||||
@@ -1073,7 +1090,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
struct ub_packed_rrset_key* alias_rrset = NULL;
|
||||
struct reply_info* partial_rep = NULL;
|
||||
struct query_info* lookup_qinfo = &qinfo;
|
||||
struct query_info qinfo_tmp; /* placeholdoer for lookup_qinfo */
|
||||
struct query_info qinfo_tmp; /* placeholder for lookup_qinfo */
|
||||
struct respip_client_info* cinfo = NULL, cinfo_tmp;
|
||||
memset(&qinfo, 0, sizeof(qinfo));
|
||||
|
||||
@@ -1156,16 +1173,16 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
|
||||
/* check if this query should be dropped based on source ip rate limiting */
|
||||
if(!infra_ip_ratelimit_inc(worker->env.infra_cache, repinfo,
|
||||
*worker->env.now)) {
|
||||
*worker->env.now, c->buffer)) {
|
||||
/* See if we are passed through with slip factor */
|
||||
if(worker->env.cfg->ip_ratelimit_factor != 0 &&
|
||||
ub_random_max(worker->env.rnd,
|
||||
worker->env.cfg->ip_ratelimit_factor) == 1) {
|
||||
worker->env.cfg->ip_ratelimit_factor) == 0) {
|
||||
|
||||
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++;
|
||||
@@ -1193,7 +1210,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
if(worker->env.cfg->log_queries) {
|
||||
char ip[128];
|
||||
addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
|
||||
log_nametypeclass(0, ip, qinfo.qname, qinfo.qtype, qinfo.qclass);
|
||||
log_query_in(ip, qinfo.qname, qinfo.qtype, qinfo.qclass);
|
||||
}
|
||||
if(qinfo.qtype == LDNS_RR_TYPE_AXFR ||
|
||||
qinfo.qtype == LDNS_RR_TYPE_IXFR) {
|
||||
@@ -1246,29 +1263,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 +1338,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 +1365,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);
|
||||
@@ -1521,8 +1561,17 @@ send_reply_rc:
|
||||
if(worker->env.cfg->log_replies)
|
||||
{
|
||||
struct timeval tv = {0, 0};
|
||||
log_reply_info(0, &qinfo, &repinfo->addr, repinfo->addrlen,
|
||||
tv, 1, c->buffer);
|
||||
if(qinfo.local_alias && qinfo.local_alias->rrset &&
|
||||
qinfo.local_alias->rrset->rk.dname) {
|
||||
/* log original qname, before the local alias was
|
||||
* used to resolve that CNAME to something else */
|
||||
qinfo.qname = qinfo.local_alias->rrset->rk.dname;
|
||||
log_reply_info(0, &qinfo, &repinfo->addr, repinfo->addrlen,
|
||||
tv, 1, c->buffer);
|
||||
} else {
|
||||
log_reply_info(0, &qinfo, &repinfo->addr, repinfo->addrlen,
|
||||
tv, 1, c->buffer);
|
||||
}
|
||||
}
|
||||
#ifdef USE_DNSCRYPT
|
||||
if(!dnsc_handle_uncurved_request(repinfo)) {
|
||||
@@ -1633,14 +1682,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);
|
||||
@@ -1708,9 +1757,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);
|
||||
@@ -1760,8 +1813,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;
|
||||
@@ -1867,7 +1918,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 */
|
||||
@@ -1972,22 +2022,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);
|
||||
}
|
||||
@@ -2000,13 +2050,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;
|
||||
}
|
||||
|
||||
|
||||
+177
-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,36 @@ 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) &&
|
||||
qstate->return_msg && qstate->return_msg->rep &&
|
||||
!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 +653,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 +663,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 +680,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 +811,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 +840,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 +897,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 +916,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 +925,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(super->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 +954,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)
|
||||
|
||||
+843
-1
@@ -1,5 +1,847 @@
|
||||
6 June 2019: Wouter
|
||||
- 1.9.2rc1 release candidate tag.
|
||||
|
||||
4 June 2019: Wouter
|
||||
- iana portlist updated.
|
||||
|
||||
29 May 2019: Wouter
|
||||
- Fix to guard _OPENBSD_SOURCE from redefinition.
|
||||
|
||||
28 May 2019: Wouter
|
||||
- Fix to define _OPENBSD_SOURCE to get reallocarray on NetBSD.
|
||||
- gitignore config.h.in~.
|
||||
|
||||
27 May 2019: Wouter
|
||||
- Fix double file close in tcp pipelined response code.
|
||||
|
||||
24 May 2019: Wouter
|
||||
- Fix that spoolbuf is not used to store tcp pipelined response
|
||||
between mesh send and callback end.
|
||||
|
||||
20 May 2019: Wouter
|
||||
- Note that so-reuseport at extreme load is better turned off,
|
||||
otherwise queries are not distributed evenly, on Linux 4.4.x.
|
||||
|
||||
16 May 2019: Wouter
|
||||
- Fix #31: swig 4.0 and python module.
|
||||
|
||||
13 May 2019: Wouter
|
||||
- Squelch log messages from tcp send about connection reset by peer.
|
||||
They can be enabled with verbosity at higher values for diagnosing
|
||||
network connectivity issues.
|
||||
- Attempt to fix malformed tcp response.
|
||||
|
||||
9 May 2019: Wouter
|
||||
- Revert fix for oss-fuzz, error is in that build script that
|
||||
unconditionally includes .o files detected by configure, also
|
||||
when the machine architecture uses different LIBOBJS files.
|
||||
|
||||
8 May 2019: Wouter
|
||||
- Attempt to fix build failure in oss-fuzz because of reallocarray.
|
||||
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=14648.
|
||||
Does not omit compile flags from commandline.
|
||||
|
||||
7 May 2019: Wouter
|
||||
- Fix edns-subnet locks, in error cases the lock was not unlocked.
|
||||
- Fix doxygen output error on readme markdown vignettes.
|
||||
|
||||
6 May 2019: Wouter
|
||||
- Fix #29: Solaris 11.3 and missing symbols be64toh, htobe64.
|
||||
- Fix #30: AddressSanitizer finding in lookup3.c. This sets the
|
||||
hash function to use a slower but better auditable code that does
|
||||
not read beyond array boundaries. This makes code better security
|
||||
checkable, and is better for security. It is fixed to be slower,
|
||||
but not read outside of the array.
|
||||
|
||||
2 May 2019: Wouter
|
||||
- contrib/fastrpz.patch updated for code changes, and with git diff.
|
||||
- Fix .gitignore, add pythonmod and dnstap generated files.
|
||||
And unit test generated files, and generated doc files.
|
||||
|
||||
1 May 2019: Wouter
|
||||
- Update makedist for git.
|
||||
- Nicer travis output for clang analysis.
|
||||
- PR #16: XoT support, AXFR over TLS, turn it on with
|
||||
master: <ip>#<authname> in unbound.conf. This uses TLS to
|
||||
download the AXFR (or IXFR).
|
||||
|
||||
25 April 2019: Wouter
|
||||
- Fix wrong query name in local zone redirect answers with a CNAME,
|
||||
the copy of the local alias is in unpacked form.
|
||||
|
||||
18 April 2019: Ralph
|
||||
- Scrub RRs from answer section when reusing NXDOMAIN message for
|
||||
subdomain answers.
|
||||
- For harden-below-nxdomain: do not consider a name to be non-exitent
|
||||
when message contains a CNAME record.
|
||||
|
||||
18 April 2019: Wouter
|
||||
- travis build file.
|
||||
|
||||
16 April 2019: Wouter
|
||||
- Better braces in if statement in TCP fastopen code.
|
||||
- iana portlist updated.
|
||||
|
||||
15 April 2019: Wouter
|
||||
- Fix tls write event for read state change to re-call SSL_write and
|
||||
not resume the TLS handshake.
|
||||
|
||||
11 April 2019: George
|
||||
- Update python documentation for init_standard().
|
||||
- Typos.
|
||||
|
||||
11 April 2019: Wouter
|
||||
- Fix that auth zone uses correct network type for sockets for
|
||||
SOA serial probes. This fixes that probes fail because earlier
|
||||
probe addresses are unreachable.
|
||||
- Fix that auth zone fails over to next master for timeout in tcp.
|
||||
- Squelch SSL read and write connection reset by peer and broken pipe
|
||||
messages. Verbosity 2 and higher enables them.
|
||||
|
||||
8 April 2019: Wouter
|
||||
- Fix to use event_assign with libevent for thread-safety.
|
||||
- verbose information about auth zone lookup process, also lookup
|
||||
start, timeout and fail.
|
||||
- Fix #17: Add python module example from Jan Janak, that is a
|
||||
plugin for the Unbound DNS resolver to resolve DNS records in
|
||||
multicast DNS [RFC 6762] via Avahi. The plugin communicates
|
||||
with Avahi via DBus. The comment section at the beginning of
|
||||
the file contains detailed documentation.
|
||||
- Fix to wipe ssl ticket keys from memory with explicit_bzero,
|
||||
if available.
|
||||
|
||||
5 April 2019: Wouter
|
||||
- Fix to reinit event structure for accepted TCP (and TLS) sockets.
|
||||
|
||||
4 April 2019: Wouter
|
||||
- Fix spelling error in log output for event method.
|
||||
|
||||
3 April 2019: Wouter
|
||||
- Move goto label in answer_from_cache to the end of the function
|
||||
where it is more visible.
|
||||
- Fix auth-zone NSEC3 response for wildcard nodata answers,
|
||||
include the closest encloser in the answer.
|
||||
|
||||
2 April 2019: Wouter
|
||||
- Fix auth-zone NSEC3 response for empty nonterminals with exact
|
||||
match nsec3 records.
|
||||
- Fix for out of bounds integers, thanks to OSTIF audit. It is in
|
||||
allocation debug code.
|
||||
- Fix for auth zone nsec3 ent fix for wildcard nodata.
|
||||
|
||||
25 March 2019: Wouter
|
||||
- Fix that tls-session-ticket-keys: "" on its own in unbound.conf
|
||||
disables the tls session ticker key calls into the OpenSSL API.
|
||||
- Fix crash if tls-servic-pem not filled in when necessary.
|
||||
|
||||
21 March 2019: Wouter
|
||||
- Fix #4240: Fix whitespace cleanup in example.conf.
|
||||
|
||||
19 March 2019: Wouter
|
||||
- add type CAA to libpyunbound (accessing libunbound from python).
|
||||
|
||||
18 March 2019: Wouter
|
||||
- Add log message, at verbosity 4, that says the query is encrypted
|
||||
with TLS, if that is enabled for the query.
|
||||
- Fix #4239: set NOTIMPL when deny-any is enabled, for RFC8482.
|
||||
|
||||
7 March 2019: Wouter
|
||||
- Fix for #4233: guard use of NDEBUG, so that it can be passed in
|
||||
CFLAGS into configure.
|
||||
|
||||
5 March 2019: Wouter
|
||||
- Tag release 1.9.1rc1. Which became 1.9.1 on 12 March 2019. Trunk
|
||||
has 1.9.2 in development.
|
||||
|
||||
1 March 2019: Wouter
|
||||
- output forwarder log in ssl_req_order test.
|
||||
|
||||
28 February 2019: Wouter
|
||||
- Remove memory leak on pythonmod python2 script file init.
|
||||
- Remove swig gcc8 python function cast warnings, they are ignored.
|
||||
- Print correct module that failed when module-config is wrong.
|
||||
|
||||
27 February 2019: Wouter
|
||||
- Fix #4229: Unbound man pages lack information, about access-control
|
||||
order and local zone tags, and elements in views.
|
||||
- Fix #14: contrib/unbound.init: Fix wrong comparison judgment
|
||||
before copying.
|
||||
- Fix for python module on Windows, fix fopen.
|
||||
|
||||
25 February 2019: Wouter
|
||||
- Fix #4227: pair event del and add for libevent for tcp_req_info.
|
||||
|
||||
21 February 2019: Wouter
|
||||
- Fix the error for unknown module in module-config is understandable,
|
||||
and explains it was not compiled in and where to see the list.
|
||||
- In example.conf explain where to put cachedb module in module-config.
|
||||
- In man page and example config explain that most modules have to
|
||||
be listed at the start of module-config.
|
||||
|
||||
20 February 2019: Wouter
|
||||
- Fix pythonmod include and sockaddr_un ifdefs for compile on
|
||||
Windows, and for libunbound.
|
||||
|
||||
18 February 2019: Wouter
|
||||
- Print query name with ip_ratelimit exceeded log lines.
|
||||
- Spaces instead of tabs in that log message.
|
||||
- Print query name and IP address when domain rate limit exceeded.
|
||||
|
||||
14 February 2019: Wouter
|
||||
- Fix capsforid canonical sort qsort callback.
|
||||
|
||||
11 February 2019: Wouter
|
||||
- Note default for module-config in man page.
|
||||
- Fix recursion lame test for qname minimisation asked queries,
|
||||
that were not present in the set of prepared answers.
|
||||
- Fix #13: Remove left-over requirements on OpenSSL >= 1.1.0 for
|
||||
cert name matching, from man page.
|
||||
- make depend, with newer gcc, nicer layout.
|
||||
|
||||
7 February 2019: Wouter
|
||||
- Fix #4206: OpenSSL 1.0.2 hostname verification for FreeBSD 11.2.
|
||||
- Fix that qname minimisation does not skip a label when missing
|
||||
nameserver targets need to be fetched.
|
||||
- Fix #4225: clients seem to erroneously receive no answer with
|
||||
DNS-over-TLS and qname-minimisation.
|
||||
|
||||
4 February 2019: Wouter
|
||||
- Fix that log-replies prints the correct name for local-alias
|
||||
names, for names that have a CNAME in local-data configuration.
|
||||
It logs the original query name, not the target of the CNAME.
|
||||
- Add local-zone type inform_redirect, which logs like type inform,
|
||||
and redirects like type redirect.
|
||||
- Perform canonical sort for 0x20 capsforid compare of replies,
|
||||
this sorts rrsets in the authority and additional section before
|
||||
comparison, so that out of order rrsets do not cause failure.
|
||||
|
||||
31 January 2019: Wouter
|
||||
- Set ub_ctx_set_tls call signature in ltrace config file for
|
||||
libunbound in contrib/libunbound.so.conf.
|
||||
- improve documentation for tls-service-key and forward-first.
|
||||
- #10: fixed pkg-config operations, PKG_PROG_PKG_CONFIG moved out of
|
||||
conditional section, fixes systemd builds, from Enrico Scholz.
|
||||
- #9: For openssl 1.0.2 use the CRYPTO_THREADID locking callbacks,
|
||||
still supports the set_id_callback previous API. And for 1.1.0
|
||||
no locking callbacks are needed.
|
||||
- #8: Fix OpenSSL without ENGINE support compilation.
|
||||
- Wipe TLS session key data from memory on exit.
|
||||
|
||||
30 January 2019: Ralph
|
||||
- Fix case in which query timeout can result in marking delegation
|
||||
as edns_lame_known.
|
||||
|
||||
29 January 2019: Wouter
|
||||
- Fix spelling of tls-ciphers in example.conf.in.
|
||||
- Fix #4224: auth_xfr_notify.rpl test broken due to typo
|
||||
- Fix locking for libunbound context setup with broken port config.
|
||||
|
||||
28 January 2019: Wouter
|
||||
- ub_ctx_set_tls call for libunbound that enables DoT for the machines
|
||||
set with ub_ctx_set_fwd. Patch from Florian Obser.
|
||||
- Set build system for added call in the libunbound API.
|
||||
- List example config for root zone copy locally hosted with auth-zone
|
||||
as suggested from draft-ietf-dnsop-7706-bis-02. But with updated
|
||||
B root address.
|
||||
- set version to 1.9.0 for release. And this was released with the
|
||||
spelling for tls-ciphers fix as 1.9.0 on Feb 5. Trunk has 1.9.1 in
|
||||
development.
|
||||
|
||||
25 January 2019: Wouter
|
||||
- Fix that tcp for auth zone and outgoing does not remove and
|
||||
then gets the ssl read again applied to the deleted commpoint.
|
||||
- updated contrib/fastrpz.patch to cleanly diff.
|
||||
- no lock when threads disabled in tcp request buffer count.
|
||||
- remove compile warnings from libnettle compile.
|
||||
- output of newer lex 2.6.1 and bison 3.0.5.
|
||||
|
||||
24 January 2019: Wouter
|
||||
- Newer aclocal and libtoolize used for generating configure scripts,
|
||||
aclocal 1.16.1 and libtoolize 2.4.6.
|
||||
- Fix unit test for python 3.7 new keyword 'async'.
|
||||
- clang analysis fixes, assert arc4random buffer in init,
|
||||
no check for already checked delegation pointer in iterator,
|
||||
in testcode check for NULL packet matches, in perf do not copy
|
||||
from NULL start list when growing capacity. Adjust host and file
|
||||
only when present in test header read to please checker. In
|
||||
testcode for unknown macro operand give zero result. Initialise the
|
||||
passed argv array in test code. In test code add EDNS data
|
||||
segment copy only when nonempty.
|
||||
- Patch from Florian Obser fixes some compiler warnings:
|
||||
include mini_event.h to have a prototype for mini_ev_cmp
|
||||
include edns.h to have a prototype for apply_edns_options
|
||||
sldns_wire2str_edns_keepalive_print is only called in the wire2str,
|
||||
module declare it static to get rid of compiler warning:
|
||||
no previous prototype for function
|
||||
infra_find_ip_ratedata() is only called in the infra module,
|
||||
declare it static to get rid of compiler warning:
|
||||
no previous prototype for function
|
||||
do not shadow local variable buf in authzone
|
||||
auth_chunks_delete and az_nsec3_findnode are only called in the
|
||||
authzone module, declare them static to get rid of compiler warning:
|
||||
no previous prototype for function...
|
||||
copy_rrset() is only called in the respip module, declare it
|
||||
static to get rid of compiler warning:
|
||||
no previous prototype for function 'copy_rrset'
|
||||
no need for another variable "r"; gets rid of compiler warning:
|
||||
declaration shadows a local variable in libunbound.c
|
||||
no need for another variable "ns"; gets rid of compiler warning:
|
||||
declaration shadows a local variable in iterator.c
|
||||
- Moved includes and make depend.
|
||||
|
||||
23 January 2019: Wouter
|
||||
- Patch from Manabu Sonoda with tls-ciphers and tls-ciphersuites
|
||||
options for unbound.conf.
|
||||
- Fixes for the patch, and man page entry.
|
||||
- Fix configure to detect SSL_CTX_set_ciphersuites, for better
|
||||
library compatibility when compiling.
|
||||
- Patch for TLS session resumption from Manabu Sonoda,
|
||||
enable with tls-session-ticket-keys in unbound.conf.
|
||||
- Fixes for patch (includes, declarations, warnings). Free at end
|
||||
and keep config options in order read from file to keep the first
|
||||
one as the first one.
|
||||
- Fix for IXFR fallback to reset counter when IXFR does not timeout.
|
||||
|
||||
22 January 2019: Wouter
|
||||
- Fix space calculation for tcp req buffer size.
|
||||
- Doc for stream-wait-size and unit test.
|
||||
- unbound-control stats has mem.streamwait that counts TCP and TLS
|
||||
waiting result buffers.
|
||||
- Fix for #4219: secondaries not updated after serial change, unbound
|
||||
falls back to AXFR after IXFR gives several timeout failures.
|
||||
- Fix that auth zone after IXFR fallback tries the same master.
|
||||
|
||||
21 January 2019: Wouter
|
||||
- Fix tcp idle timeout test, for difference in the tcp reply code.
|
||||
- Unit test for tcp request reorder and timeouts.
|
||||
- Unit tests for ssl out of order processing.
|
||||
- Fix that multiple dns fragments can be carried in one TLS frame.
|
||||
- Add stream-wait-size: 4m config option to limit the maximum
|
||||
memory used by waiting tcp and tls stream replies. This avoids
|
||||
a denial of service where these replies use up all of the memory.
|
||||
|
||||
17 January 2019: Wouter
|
||||
- For caps-for-id fallback, use the whitelist to avoid timeout
|
||||
starting a fallback sequence for it.
|
||||
- increase mesh max activation count for capsforid long fetches.
|
||||
|
||||
16 January 2019: Ralph
|
||||
- Get ready for the DNS flag day: remove EDNS lame procedure, do not
|
||||
re-query without EDNS after timeout.
|
||||
|
||||
15 January 2019: Wouter
|
||||
- In the out of order processing, reset byte count for (potential)
|
||||
partial read.
|
||||
- Review fixes in out of order processing.
|
||||
|
||||
14 January 2019: Wouter
|
||||
- streamtcp option -a send queries consecutively and prints answers
|
||||
as they arrive.
|
||||
- Fix for out of order processing administration quit cleanup.
|
||||
- unit test for tcp out of order processing.
|
||||
|
||||
11 January 2019: Wouter
|
||||
- Initial commit for out-of-order processing for TCP and TLS.
|
||||
|
||||
9 January 2019: Wouter
|
||||
- Log query name for looping module errors.
|
||||
|
||||
8 January 2019: Wouter
|
||||
- Fix syntax in comment of local alias processing.
|
||||
- Fix NSEC3 record that is returned in wildcard replies from
|
||||
auth-zone zones with NSEC3 and wildcards.
|
||||
|
||||
7 January 2019: Wouter
|
||||
- On FreeBSD warn if systcl settings do not allow server TCP FASTOPEN,
|
||||
and server tcp fastopen is enabled at compile time.
|
||||
- Document interaction between the tls-upstream option in the server
|
||||
section and forward-tls-upstream option in the forward-zone sections.
|
||||
- Add contrib/unbound-fuzzme.patch from Jacob Hoffman-Andrews,
|
||||
the patch adds a program used for fuzzing.
|
||||
|
||||
12 December 2018: Wouter
|
||||
- Fix for crash in dns64 module if response is null.
|
||||
|
||||
10 December 2018: Wouter
|
||||
- Fix config parser memory leaks.
|
||||
- ip-ratelimit-factor of 1 allows all traffic through, instead of the
|
||||
previous blocking everything.
|
||||
- Fix for FreeBSD port make with dnscrypt and dnstap enabled.
|
||||
- Fix #4206: support openssl 1.0.2 for TLS hostname verification,
|
||||
alongside the 1.1.0 and later support that is already there.
|
||||
- Fixup openssl 1.0.2 compile
|
||||
|
||||
6 December 2018: Wouter
|
||||
- Fix dns64 allocation in wrong region for returned internal queries.
|
||||
|
||||
3 December 2018: Wouter
|
||||
- Fix icon, no ragged edges and nicer resolutions available, for eg.
|
||||
Win 7 and Windows 10 display.
|
||||
- cache-max-ttl also defines upperbound of initial TTL in response.
|
||||
|
||||
30 November 2018: Wouter
|
||||
- Patch for typo in unbound.conf man page.
|
||||
- log-tag-queryreply: yes in unbound.conf tags the log-queries and
|
||||
log-replies in the log file for easier log filter maintenance.
|
||||
|
||||
29 November 2018: Wouter
|
||||
- iana portlist updated.
|
||||
- Fix chroot auth-zone fix to remove chroot prefix.
|
||||
- tag for 1.8.2rc1, which became 1.8.2 on 4 dec 2018, with icon
|
||||
updated. Trunk contains 1.8.3 in development.
|
||||
Which became 1.8.3 on 11 december with only the dns64 fix of 6 dec.
|
||||
Trunk then became 1.8.4 in development.
|
||||
- Fix that unbound-checkconf does not complains if the config file
|
||||
is not placed inside the chroot.
|
||||
- Refuse to start with no ports.
|
||||
- Remove clang analysis warnings.
|
||||
|
||||
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
|
||||
@@ -1598,7 +2440,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.
|
||||
|
||||
|
||||
+99
-17
@@ -103,7 +103,8 @@ server:
|
||||
# so-sndbuf: 0
|
||||
|
||||
# use SO_REUSEPORT to distribute queries over threads.
|
||||
# so-reuseport: no
|
||||
# at extreme load it could be better to turn it off to distribute even.
|
||||
# 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
|
||||
@@ -123,6 +124,9 @@ server:
|
||||
# Suggested values are 512 to 4096. Default is 4096. 65536 disables it.
|
||||
# max-udp-size: 4096
|
||||
|
||||
# max memory to use for stream(tcp and tls) waiting result buffers.
|
||||
# stream-wait-size: 4m
|
||||
|
||||
# buffer size for handling DNS data. No messages larger than this
|
||||
# size can be sent or received, by UDP or TCP. In bytes.
|
||||
# msg-buffer-size: 65552
|
||||
@@ -145,6 +149,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 +220,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
|
||||
|
||||
@@ -309,6 +326,17 @@ server:
|
||||
# timetoresolve, fromcache and responsesize.
|
||||
# log-replies: no
|
||||
|
||||
# log with tag 'query' and 'reply' instead of 'info' for
|
||||
# filtering log-queries and log-replies from the log.
|
||||
# log-tag-queryreply: 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@"
|
||||
|
||||
@@ -357,7 +385,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).
|
||||
@@ -433,18 +461,24 @@ 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
|
||||
|
||||
# module configuration of the server. A string with identifiers
|
||||
# separated by spaces. Syntax: "[dns64] [validator] iterator"
|
||||
# most modules have to be listed at the beginning of the line,
|
||||
# except cachedb(just before iterator), and python (at the beginning,
|
||||
# or, just before the iterator).
|
||||
# module-config: "validator iterator"
|
||||
|
||||
# File with trusted keys, kept uptodate using RFC5011 probes,
|
||||
@@ -459,7 +493,7 @@ server:
|
||||
|
||||
# trust anchor signaling sends a RFC8145 key tag query after priming.
|
||||
# trust-anchor-signaling: yes
|
||||
|
||||
|
||||
# Root key trust anchor sentinel (draft-ietf-dnsop-kskroll-sentinel)
|
||||
# root-key-sentinel: yes
|
||||
|
||||
@@ -527,6 +561,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.
|
||||
@@ -633,6 +677,7 @@ server:
|
||||
# o typetransparent resolves normally for other types and other names
|
||||
# o inform acts like transparent, but logs client IP address
|
||||
# o inform_deny drops queries and logs client IP address
|
||||
# o inform_redirect redirects queries and logs client IP address
|
||||
# o always_transparent, always_refuse, always_nxdomain, resolve in
|
||||
# that way but ignore local data for that name
|
||||
# o noview breaks out of that view towards global local-zones.
|
||||
@@ -675,6 +720,19 @@ server:
|
||||
# tls-service-pem: "path/to/publiccertfile.pem"
|
||||
# tls-port: 853
|
||||
|
||||
# cipher setting for TLSv1.2
|
||||
# tls-ciphers: "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256"
|
||||
# cipher setting for TLSv1.3
|
||||
# tls-ciphersuites: "TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256"
|
||||
|
||||
# Add the secret file for TLS Session Ticket.
|
||||
# Secret file must be 80 bytes of random data.
|
||||
# First key use to encrypt and decrypt TLS session tickets.
|
||||
# Other keys use to decrypt only.
|
||||
# requires restart to take effect.
|
||||
# tls-session-ticket-keys: "path/to/secret_file1"
|
||||
# tls-session-ticket-keys: "path/to/secret_file2"
|
||||
|
||||
# request upstream over TLS (with plain DNS inside the TLS stream).
|
||||
# Default is no. Can be turned on and off with unbound-control.
|
||||
# tls-upstream: no
|
||||
@@ -692,6 +750,9 @@ server:
|
||||
# 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.
|
||||
@@ -725,11 +786,14 @@ 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-permil: 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.
|
||||
@@ -763,6 +827,8 @@ server:
|
||||
# Python config section. To enable:
|
||||
# o use --with-pythonmodule to configure before compiling.
|
||||
# o list python in the module-config string (above) to enable.
|
||||
# It can be at the start, it gets validated results, or just before
|
||||
# the iterator and process before DNSSEC validation.
|
||||
# o and give a python-script to run.
|
||||
python:
|
||||
# Script file to load
|
||||
@@ -784,6 +850,10 @@ remote-control:
|
||||
# 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"
|
||||
|
||||
@@ -810,6 +880,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.
|
||||
@@ -826,6 +897,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
|
||||
@@ -841,15 +913,25 @@ remote-control:
|
||||
# notifies.
|
||||
# auth-zone:
|
||||
# name: "."
|
||||
# master: 199.9.14.201 # b.root-servers.net
|
||||
# master: 192.33.4.12 # c.root-servers.net
|
||||
# master: 199.7.91.13 # d.root-servers.net
|
||||
# master: 192.5.5.241 # f.root-servers.net
|
||||
# master: 192.112.36.4 # g.root-servers.net
|
||||
# master: 193.0.14.129 # k.root-servers.net
|
||||
# master: 192.0.47.132 # xfr.cjr.dns.icann.org
|
||||
# master: 192.0.32.132 # xfr.lax.dns.icann.org
|
||||
# master: 2001:500:200::b # b.root-servers.net
|
||||
# master: 2001:500:2::c # c.root-servers.net
|
||||
# master: 2001:500:2d::d # d.root-servers.net
|
||||
# master: 2001:500:2f::f # f.root-servers.net
|
||||
# master: 2001:500:12::d0d # g.root-servers.net
|
||||
# master: 2001:7fd::1 # k.root-servers.net
|
||||
# master: 2620:0:2830:202::132 # xfr.cjr.dns.icann.org
|
||||
# master: 2620:0:2d0:202::132 # xfr.lax.dns.icann.org
|
||||
# fallback-enabled: yes
|
||||
# for-downstream: no
|
||||
# for-upstream: yes
|
||||
# fallback-enabled: yes
|
||||
# master: b.root-servers.net
|
||||
# master: c.root-servers.net
|
||||
# master: e.root-servers.net
|
||||
# master: f.root-servers.net
|
||||
# master: g.root-servers.net
|
||||
# master: k.root-servers.net
|
||||
# auth-zone:
|
||||
# name: "example.org"
|
||||
# for-downstream: yes
|
||||
@@ -897,7 +979,7 @@ remote-control:
|
||||
# Enable external backend DB as auxiliary cache. Specify the backend name
|
||||
# (default is "testframe", which has no use other than for debugging and
|
||||
# testing) and backend-specific options. The 'cachedb' module must be
|
||||
# included in module-config.
|
||||
# included in module-config, just before the iterator module.
|
||||
# cachedb:
|
||||
# backend: "testframe"
|
||||
# # secret seed string to calculate hashed keys
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
.B ub_ctx_config,
|
||||
.B ub_ctx_set_fwd,
|
||||
.B ub_ctx_set_stub,
|
||||
.B ub_ctx_set_tls,
|
||||
.B ub_ctx_resolvconf,
|
||||
.B ub_ctx_hosts,
|
||||
.B ub_ctx_add_ta,
|
||||
@@ -72,6 +73,9 @@
|
||||
\fIint\fR isprime);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_set_tls\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR tls);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_resolvconf\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
|
||||
.LP
|
||||
\fIint\fR
|
||||
@@ -227,6 +231,12 @@ for different zones, or to add multiple addresses for a particular zone.
|
||||
At this time it is only possible to set configuration before the
|
||||
first resolve is done.
|
||||
.TP
|
||||
.B ub_ctx_set_tls
|
||||
Enable DNS over TLS (DoT) for machines set with
|
||||
.B ub_ctx_set_fwd.
|
||||
At this time it is only possible to set configuration before the
|
||||
first resolve is done.
|
||||
.TP
|
||||
.B ub_ctx_resolvconf
|
||||
By default the root servers are queried and full resolver mode is used, but
|
||||
you can use this call to read the list of nameservers to use from the
|
||||
|
||||
@@ -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"
|
||||
@@ -484,6 +499,10 @@ Memory in bytes in use by the iterator module.
|
||||
Memory in bytes in use by the validator module. Includes the key cache and
|
||||
negative cache.
|
||||
.TP
|
||||
.I mem.streamwait
|
||||
Memory in bytes in used by the TCP and TLS stream wait buffers. These are
|
||||
answers waiting to be written back to the clients.
|
||||
.TP
|
||||
.I histogram.<sec>.<usec>.to.<sec>.<usec>
|
||||
Shows a histogram, summed over all threads. Every element counts the
|
||||
recursive queries whose reply time fit between the lower and upper bound.
|
||||
@@ -515,6 +534,14 @@ 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.tls.resume
|
||||
Number of TLS session resumptions, these are queries over TLS towards
|
||||
the unbound server where the client negotiated a TLS session resumption key.
|
||||
.TP
|
||||
.I num.query.ipv6
|
||||
Number of queries that were made using IPv6 towards the unbound server.
|
||||
.TP
|
||||
@@ -625,6 +652,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
|
||||
|
||||
+217
-50
@@ -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
|
||||
@@ -207,6 +207,16 @@ Maximum UDP response size (not applied to TCP response). 65536 disables the
|
||||
udp response size maximum, and uses the choice from the client, always.
|
||||
Suggested values are 512 to 4096. Default is 4096.
|
||||
.TP
|
||||
.B stream\-wait\-size: \fI<number>
|
||||
Number of bytes size maximum to use for waiting stream buffers. Default is
|
||||
4 megabytes. A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes,
|
||||
megabytes or gigabytes (1024*1024 bytes in a megabyte). As TCP and TLS streams
|
||||
queue up multiple results, the amount of memory used for these buffers does
|
||||
not exceed this number, otherwise the responses are dropped. This manages
|
||||
the total memory usage of the server (under heavy use), the number of requests
|
||||
that can be queued up per connection is also limited, with further requests
|
||||
waiting in TCP buffers.
|
||||
.TP
|
||||
.B msg\-buffer\-size: \fI<number>
|
||||
Number of bytes size of the message buffers. Default is 65552 bytes, enough
|
||||
for 64 Kb packets, the maximum DNS message size. No message larger than this
|
||||
@@ -253,6 +263,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,12 +294,14 @@ 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.
|
||||
At extreme load it could be better to turn it off to distribute the queries
|
||||
evenly, reported for Linux systems (4.4.x).
|
||||
.TP
|
||||
.B ip\-transparent: \fI<yes or no>
|
||||
If yes, then use IP_TRANSPARENT socket option on sockets where unbound
|
||||
@@ -314,11 +332,9 @@ Must be set to a power of 2.
|
||||
.TP
|
||||
.B cache\-max\-ttl: \fI<seconds>
|
||||
Time to live maximum for RRsets and messages in the cache. Default is
|
||||
86400 seconds (1 day). If the maximum kicks in, responses to clients
|
||||
still get decrementing TTLs based on the original (larger) values.
|
||||
When the internal TTL expires, the cache item has expired.
|
||||
86400 seconds (1 day). When the TTL expires, the cache item has expired.
|
||||
Can be set lower to force the resolver to query for data often, and not
|
||||
trust (very large) TTL values.
|
||||
trust (very large) TTL values. Downstream clients also see the lower TTL.
|
||||
.TP
|
||||
.B cache\-min\-ttl: \fI<seconds>
|
||||
Time to live minimum for RRsets and messages in the cache. Default is 0.
|
||||
@@ -389,6 +405,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,22 +450,25 @@ 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
|
||||
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.
|
||||
This option enables TLS for all of them, but if you do not set this you can
|
||||
configure TLS specifically for some forward zones with forward\-tls\-upstream. And also with stub\-tls\-upstream.
|
||||
.TP
|
||||
.B ssl\-upstream: \fI<yes or no>
|
||||
Alternate syntax for \fBtls\-upstream\fR. If both are present in the config
|
||||
file the last is used.
|
||||
.TP
|
||||
.B tls\-service\-key: \fI<file>
|
||||
If enabled, the server provider TLS service on its TCP sockets. The clients
|
||||
have to use tls\-upstream: yes. The file is the private key for the TLS
|
||||
session. The public certificate is in the tls\-service\-pem file. Default
|
||||
is "", turned off. Requires a restart (a reload is not enough) if changed,
|
||||
because the private key is read while root permissions are held and before
|
||||
chroot (if any). Normal DNS TCP service is not provided and gives errors,
|
||||
this service is best run with a different \fBport:\fR config or \fI@port\fR
|
||||
suffixes in the \fBinterface\fR config.
|
||||
If enabled, the server provides TLS service on the TCP ports marked
|
||||
implicitly or explicitly for TLS service with tls\-port. The file must
|
||||
contain the private key for the TLS session, the public certificate is in
|
||||
the tls\-service\-pem file and it must also be specified if tls\-service\-key
|
||||
is specified. The default is "", turned off. Enabling or disabling
|
||||
this service requires a restart (a reload is not enough), because the
|
||||
key is read while root permissions are held and before chroot (if any).
|
||||
The ports enabled implicitly or explicitly via \fBtls\-port:\fR do not provide
|
||||
normal DNS TCP service.
|
||||
.TP
|
||||
.B ssl\-service\-key: \fI<file>
|
||||
Alternate syntax for \fBtls\-service\-key\fR.
|
||||
@@ -457,6 +507,27 @@ 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
|
||||
.B tls-session-ticket-keys: \fI<file>
|
||||
If not "", lists files with 80 bytes of random contents that are used to
|
||||
perform TLS session resumption for clients using the unbound server.
|
||||
These files contain the secret key for the TLS session tickets.
|
||||
First key use to encrypt and decrypt TLS session tickets.
|
||||
Other keys use to decrypt only. With this you can roll over to new keys,
|
||||
by generating a new first file and allowing decrypt of the old file by
|
||||
listing it after the first file for some time, after the wait clients are not
|
||||
using the old key any more and the old key can be removed.
|
||||
One way to create the file is dd if=/dev/random bs=1 count=80 of=ticket.dat
|
||||
The first 16 bytes should be different from the old one if you create a second key, that is the name used to identify the key. Then there is 32 bytes random
|
||||
data for an AES key and then 32 bytes random data for the HMAC key.
|
||||
.TP
|
||||
.B tls\-ciphers: \fI<string with cipher list>
|
||||
Set the list of ciphers to allow when serving TLS. Use "" for defaults,
|
||||
and that is the default.
|
||||
.TP
|
||||
.B tls\-ciphersuites: \fI<string with ciphersuites list>
|
||||
Set the list of ciphersuites to allow when serving TLS. This is for newer
|
||||
TLS 1.3 connections. Use "" for defaults, and that is the default.
|
||||
.TP
|
||||
.B use\-systemd: \fI<yes or no>
|
||||
Enable or disable systemd socket activation.
|
||||
Default is no.
|
||||
@@ -466,12 +537,18 @@ 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_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.
|
||||
The order of the access\-control statements therefore does not matter.
|
||||
.IP
|
||||
The action \fIdeny\fR stops queries from hosts from that netblock.
|
||||
.IP
|
||||
@@ -557,8 +634,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
|
||||
@@ -618,6 +696,21 @@ 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\-tag\-queryreply: \fI<yes or no>
|
||||
Prints the word 'query' and 'reply' with log\-queries and log\-replies.
|
||||
This makes filtering logs easier. The default is off (for backwards
|
||||
compatibility).
|
||||
.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,
|
||||
@@ -700,7 +793,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>
|
||||
@@ -737,7 +830,7 @@ Can be given multiple times, for different domains.
|
||||
.TP
|
||||
.B qname\-minimisation: \fI<yes or no>
|
||||
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
|
||||
Only send 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 yes.
|
||||
@@ -801,12 +894,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
|
||||
@@ -814,9 +913,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
|
||||
@@ -832,6 +933,12 @@ Setting this to "iterator" will result in a non\-validating server.
|
||||
Setting this to "validator iterator" will turn on DNSSEC validation.
|
||||
The ordering of the modules is important.
|
||||
You must also set trust\-anchors for validation to be useful.
|
||||
The default is "validator iterator". When the server is built with
|
||||
EDNS client subnet support the default is "subnetcache validator iterator".
|
||||
Most modules that need to be listed here have to be listed at the beginning
|
||||
of the line. The cachedb module has to be listed just before the iterator.
|
||||
The python module can be listed in different places, it then processes the
|
||||
output of the module it is just before.
|
||||
.TP
|
||||
.B trust\-anchor\-file: \fI<filename>
|
||||
File with trusted keys for validation. Both DS and DNSKEY entries can appear
|
||||
@@ -964,6 +1071,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
|
||||
@@ -1012,7 +1130,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,
|
||||
@@ -1023,7 +1141,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.
|
||||
@@ -1032,7 +1150,7 @@ address space are not validated. This is usually required whenever
|
||||
Configure a local zone. The type determines the answer to give if
|
||||
there is no match from local\-data. The types are deny, refuse, static,
|
||||
transparent, redirect, nodefault, typetransparent, inform, inform_deny,
|
||||
always_transparent, always_refuse, always_nxdomain, noview,
|
||||
inform_redirect, always_transparent, always_refuse, always_nxdomain, noview,
|
||||
and are explained below. After that the default settings are listed. Use
|
||||
local\-data: to enter data into the local zone. Answers for local zones
|
||||
are authoritative DNS answers. By default the zones are class IN.
|
||||
@@ -1093,6 +1211,10 @@ looking up infected names are logged, eg. to run antivirus on them.
|
||||
The query is dropped, like 'deny', and logged, like 'inform'. Ie. find
|
||||
infected machines without answering the queries.
|
||||
.TP 10
|
||||
\h'5'\fIinform_redirect\fR
|
||||
The query is redirected, like 'redirect', and logged, like 'inform'.
|
||||
Ie. answer queries with fixed data and also log the machines that ask.
|
||||
.TP 10
|
||||
\h'5'\fIalways_transparent\fR
|
||||
Like transparent, but ignores local data and resolves normally.
|
||||
.TP 10
|
||||
@@ -1248,7 +1370,8 @@ TTL can be inserted like this: "2001:DB8::4 7200 www.example.com"
|
||||
Assign tags to localzones. Tagged localzones will only be applied when the
|
||||
used access-control element has a matching tag. Tags must be defined in
|
||||
\fIdefine\-tags\fR. Enclose list of tags in quotes ("") and put spaces between
|
||||
tags.
|
||||
tags. When there are multiple tags it checks if the intersection of the
|
||||
list of tags for the query and local\-zone\-tag is non-empty.
|
||||
.TP 5
|
||||
.B local\-zone\-override: \fI<zone> <IP netblock> <type>
|
||||
Override the localzone type for queries from addresses matching netblock.
|
||||
@@ -1331,22 +1454,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\-permil 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\-permil: \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\-permil 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:
|
||||
@@ -1384,6 +1505,11 @@ default is 8953.
|
||||
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>
|
||||
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.
|
||||
This file is generated by the \fIunbound\-control\-setup\fR utility.
|
||||
@@ -1465,6 +1591,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
|
||||
@@ -1501,19 +1631,22 @@ 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.
|
||||
.TP
|
||||
.B forward\-first: \fI<yes or no>
|
||||
If enabled, a query is attempted without the forward clause if it fails.
|
||||
The data could not be retrieved and would have caused SERVFAIL because
|
||||
the servers are unreachable, instead it is tried without this clause.
|
||||
The default is no.
|
||||
If a forwarded query is met with a SERVFAIL error, and this option is
|
||||
enabled, unbound will fall back to normal recursive resolution for this
|
||||
query as if no query forwarding had been specified. The default is "no".
|
||||
.TP
|
||||
.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
|
||||
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
|
||||
@@ -1530,6 +1663,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.
|
||||
@@ -1537,6 +1677,7 @@ Name of the authority zone.
|
||||
.B master: \fI<IP address or host name>
|
||||
Where to download a copy of the zone from, with AXFR and IXFR. Multiple
|
||||
masters can be specified. They are all tried if one fails.
|
||||
With the "ip#name" notation a AXFR over TLS can be used.
|
||||
.TP
|
||||
.B url: \fI<url to zonefile>
|
||||
Where to download a zonefile for the zone. With http or https. An example
|
||||
@@ -1588,7 +1729,9 @@ data (eg. from the master servers).
|
||||
There may be multiple
|
||||
.B view:
|
||||
clauses. Each with a \fBname:\fR and zero or more \fBlocal\-zone\fR and
|
||||
\fBlocal\-data\fR elements. View can be mapped to requests by specifying the
|
||||
\fBlocal\-data\fR elements. Views can also contain view\-first,
|
||||
response\-ip, response\-ip\-data and local\-data\-ptr elements.
|
||||
View can be mapped to requests by specifying the
|
||||
view name in an \fBaccess\-control\-view\fR element. Options from matching
|
||||
views will override global options. Global options will be used if no matching
|
||||
view is found, or when the matching view does not have the option specified.
|
||||
@@ -1648,6 +1791,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
|
||||
@@ -1763,6 +1912,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
|
||||
|
||||
+9
-3
@@ -612,18 +612,24 @@ 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 \
|
||||
README.md \
|
||||
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.
|
||||
|
||||
+76
-25
@@ -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;
|
||||
@@ -323,33 +334,37 @@ update_cache(struct module_qstate *qstate, int id)
|
||||
/* Step 1, general qinfo lookup */
|
||||
struct lruhash_entry *lru_entry = slabhash_lookup(subnet_msg_cache, h,
|
||||
&qstate->qinfo, 1);
|
||||
int acquired_lock = (lru_entry != NULL);
|
||||
int need_to_insert = (lru_entry == NULL);
|
||||
if (!lru_entry) {
|
||||
void* data = calloc(1,
|
||||
sizeof(struct subnet_msg_cache_data));
|
||||
if(!data) {
|
||||
log_err("malloc failed");
|
||||
return;
|
||||
}
|
||||
qinf = qstate->qinfo;
|
||||
qinf.qname = memdup(qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len);
|
||||
if(!qinf.qname) {
|
||||
free(data);
|
||||
log_err("memdup failed");
|
||||
return;
|
||||
}
|
||||
mrep_entry = query_info_entrysetup(&qinf, NULL, h);
|
||||
mrep_entry = query_info_entrysetup(&qinf, data, h);
|
||||
free(qinf.qname); /* if qname 'consumed', it is set to NULL */
|
||||
if (!mrep_entry) {
|
||||
free(data);
|
||||
log_err("query_info_entrysetup failed");
|
||||
return;
|
||||
}
|
||||
lru_entry = &mrep_entry->entry;
|
||||
lock_rw_wrlock(&lru_entry->lock);
|
||||
lru_entry->data = calloc(1,
|
||||
sizeof(struct subnet_msg_cache_data));
|
||||
if (!lru_entry->data) {
|
||||
log_err("malloc failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* lru_entry->lock is locked regardless of how we got here,
|
||||
* either from the slabhash_lookup, or above in the new allocated */
|
||||
/* Step 2, find the correct tree */
|
||||
if (!(tree = get_tree(lru_entry->data, edns, sne, qstate->env->cfg))) {
|
||||
if (acquired_lock) lock_rw_unlock(&lru_entry->lock);
|
||||
lock_rw_unlock(&lru_entry->lock);
|
||||
log_err("Subnet cache insertion failed");
|
||||
return;
|
||||
}
|
||||
@@ -357,7 +372,7 @@ update_cache(struct module_qstate *qstate, int id)
|
||||
rep = reply_info_copy(qstate->return_msg->rep, &sne->alloc, NULL);
|
||||
lock_quick_unlock(&sne->alloc.lock);
|
||||
if (!rep) {
|
||||
if (acquired_lock) lock_rw_unlock(&lru_entry->lock);
|
||||
lock_rw_unlock(&lru_entry->lock);
|
||||
log_err("Subnet cache insertion failed");
|
||||
return;
|
||||
}
|
||||
@@ -374,10 +389,9 @@ update_cache(struct module_qstate *qstate, int id)
|
||||
edns->subnet_source_mask,
|
||||
sq->ecs_server_in.subnet_scope_mask, rep,
|
||||
rep->ttl, *qstate->env->now);
|
||||
if (acquired_lock) {
|
||||
lock_rw_unlock(&lru_entry->lock);
|
||||
} else {
|
||||
lock_rw_unlock(&lru_entry->lock);
|
||||
|
||||
lock_rw_unlock(&lru_entry->lock);
|
||||
if (need_to_insert) {
|
||||
slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data,
|
||||
NULL);
|
||||
}
|
||||
@@ -464,7 +478,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 +501,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 +531,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 +544,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 +728,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 +790,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 */
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
#!/usr/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2013-12-25.23; # UTC
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_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;
|
||||
}
|
||||
#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_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
|
||||
|
||||
+208
-14
@@ -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_permil != 0 && prefetch == 0 &&
|
||||
low_rtt < env->cfg->low_rtt &&
|
||||
ub_random_max(env->rnd, 1000) < env->cfg->low_rtt_permil) {
|
||||
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;
|
||||
@@ -800,10 +882,35 @@ rrset_equal(struct ub_packed_rrset_key* k1, struct ub_packed_rrset_key* k2)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** compare rrsets and sort canonically. Compares rrset name, type, class.
|
||||
* return 0 if equal, +1 if x > y, and -1 if x < y.
|
||||
*/
|
||||
static int
|
||||
rrset_canonical_sort_cmp(const void* x, const void* y)
|
||||
{
|
||||
struct ub_packed_rrset_key* rrx = *(struct ub_packed_rrset_key**)x;
|
||||
struct ub_packed_rrset_key* rry = *(struct ub_packed_rrset_key**)y;
|
||||
int r = dname_canonical_compare(rrx->rk.dname, rry->rk.dname);
|
||||
if(r != 0)
|
||||
return r;
|
||||
if(rrx->rk.type != rry->rk.type) {
|
||||
if(ntohs(rrx->rk.type) > ntohs(rry->rk.type))
|
||||
return 1;
|
||||
else return -1;
|
||||
}
|
||||
if(rrx->rk.rrset_class != rry->rk.rrset_class) {
|
||||
if(ntohs(rrx->rk.rrset_class) > ntohs(rry->rk.rrset_class))
|
||||
return 1;
|
||||
else return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
reply_equal(struct reply_info* p, struct reply_info* q, struct regional* region)
|
||||
{
|
||||
size_t i;
|
||||
struct ub_packed_rrset_key** sorted_p, **sorted_q;
|
||||
if(p->flags != q->flags ||
|
||||
p->qdcount != q->qdcount ||
|
||||
/* do not check TTL, this may differ */
|
||||
@@ -817,16 +924,43 @@ reply_equal(struct reply_info* p, struct reply_info* q, struct regional* region)
|
||||
p->ar_numrrsets != q->ar_numrrsets ||
|
||||
p->rrset_count != q->rrset_count)
|
||||
return 0;
|
||||
/* sort the rrsets in the authority and additional sections before
|
||||
* compare, the query and answer sections are ordered in the sequence
|
||||
* they should have (eg. one after the other for aliases). */
|
||||
sorted_p = (struct ub_packed_rrset_key**)regional_alloc_init(
|
||||
region, p->rrsets, sizeof(*sorted_p)*p->rrset_count);
|
||||
if(!sorted_p) return 0;
|
||||
log_assert(p->an_numrrsets + p->ns_numrrsets + p->ar_numrrsets <=
|
||||
p->rrset_count);
|
||||
qsort(sorted_p + p->an_numrrsets, p->ns_numrrsets,
|
||||
sizeof(*sorted_p), rrset_canonical_sort_cmp);
|
||||
qsort(sorted_p + p->an_numrrsets + p->ns_numrrsets, p->ar_numrrsets,
|
||||
sizeof(*sorted_p), rrset_canonical_sort_cmp);
|
||||
|
||||
sorted_q = (struct ub_packed_rrset_key**)regional_alloc_init(
|
||||
region, q->rrsets, sizeof(*sorted_q)*q->rrset_count);
|
||||
if(!sorted_q) {
|
||||
regional_free_all(region);
|
||||
return 0;
|
||||
}
|
||||
log_assert(q->an_numrrsets + q->ns_numrrsets + q->ar_numrrsets <=
|
||||
q->rrset_count);
|
||||
qsort(sorted_q + q->an_numrrsets, q->ns_numrrsets,
|
||||
sizeof(*sorted_q), rrset_canonical_sort_cmp);
|
||||
qsort(sorted_q + q->an_numrrsets + q->ns_numrrsets, q->ar_numrrsets,
|
||||
sizeof(*sorted_q), rrset_canonical_sort_cmp);
|
||||
|
||||
/* compare the rrsets */
|
||||
for(i=0; i<p->rrset_count; i++) {
|
||||
if(!rrset_equal(p->rrsets[i], q->rrsets[i])) {
|
||||
if(!rrset_canonical_equal(region, p->rrsets[i],
|
||||
q->rrsets[i])) {
|
||||
if(!rrset_equal(sorted_p[i], sorted_q[i])) {
|
||||
if(!rrset_canonical_equal(region, sorted_p[i],
|
||||
sorted_q[i])) {
|
||||
regional_free_all(region);
|
||||
return 0;
|
||||
}
|
||||
regional_free_all(region);
|
||||
}
|
||||
}
|
||||
regional_free_all(region);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1077,6 +1211,19 @@ iter_scrub_ds(struct dns_msg* msg, struct ub_packed_rrset_key* ns, uint8_t* z)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
iter_scrub_nxdomain(struct dns_msg* msg)
|
||||
{
|
||||
if(msg->rep->an_numrrsets == 0)
|
||||
return;
|
||||
|
||||
memmove(msg->rep->rrsets, msg->rep->rrsets+msg->rep->an_numrrsets,
|
||||
sizeof(struct ub_packed_rrset_key*) *
|
||||
(msg->rep->rrset_count-msg->rep->an_numrrsets));
|
||||
msg->rep->rrset_count -= msg->rep->an_numrrsets;
|
||||
msg->rep->an_numrrsets = 0;
|
||||
}
|
||||
|
||||
void iter_dec_attempts(struct delegpt* dp, int d)
|
||||
{
|
||||
struct delegpt_addr* a;
|
||||
@@ -1184,3 +1331,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;
|
||||
}
|
||||
|
||||
@@ -334,6 +334,13 @@ int iter_get_next_root(struct iter_hints* hints, struct iter_forwards* fwd,
|
||||
void iter_scrub_ds(struct dns_msg* msg, struct ub_packed_rrset_key* ns,
|
||||
uint8_t* z);
|
||||
|
||||
/**
|
||||
* Prepare an NXDOMAIN message to be used for a subdomain answer by removing all
|
||||
* RRs from the ANSWER section.
|
||||
* @param msg: the response to scrub.
|
||||
*/
|
||||
void iter_scrub_nxdomain(struct dns_msg* msg);
|
||||
|
||||
/**
|
||||
* Remove query attempts from all available ips. For 0x20.
|
||||
* @param dp: delegpt.
|
||||
@@ -369,4 +376,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 */
|
||||
|
||||
+201
-21
@@ -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");
|
||||
@@ -789,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 */
|
||||
}
|
||||
@@ -807,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 */
|
||||
}
|
||||
@@ -822,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 */
|
||||
}
|
||||
@@ -905,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,
|
||||
@@ -916,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;
|
||||
@@ -1106,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;
|
||||
}
|
||||
@@ -1159,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);
|
||||
}
|
||||
|
||||
@@ -1170,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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1382,7 +1448,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* now will also exceed the rate, keeping cache fresh */
|
||||
(void)infra_ratelimit_inc(qstate->env->infra_cache,
|
||||
iq->dp->name, iq->dp->namelen,
|
||||
*qstate->env->now);
|
||||
*qstate->env->now, &qstate->qinfo,
|
||||
qstate->reply);
|
||||
/* see if we are passed through with slip factor */
|
||||
if(qstate->env->cfg->ratelimit_factor != 0 &&
|
||||
ub_random_max(qstate->env->rnd,
|
||||
@@ -1398,6 +1465,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);
|
||||
}
|
||||
}
|
||||
@@ -1427,6 +1497,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
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);
|
||||
}
|
||||
@@ -1435,6 +1506,9 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
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);
|
||||
}
|
||||
@@ -1454,6 +1528,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);
|
||||
}
|
||||
@@ -1508,6 +1583,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
|
||||
@@ -1798,6 +1874,8 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
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);
|
||||
}
|
||||
@@ -1805,7 +1883,6 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
struct delegpt* p = hints_lookup_root(qstate->env->hints,
|
||||
iq->qchase.qclass);
|
||||
if(p) {
|
||||
struct delegpt_ns* ns;
|
||||
struct delegpt_addr* a;
|
||||
iq->chase_flags &= ~BIT_RD; /* go to authorities */
|
||||
for(ns = p->nslist; ns; ns=ns->next) {
|
||||
@@ -1857,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;
|
||||
@@ -1868,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 &&
|
||||
@@ -1876,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 */
|
||||
@@ -1901,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++;
|
||||
}
|
||||
@@ -1911,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++;
|
||||
}
|
||||
@@ -1934,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. */
|
||||
@@ -1967,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);
|
||||
}
|
||||
|
||||
@@ -1987,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);
|
||||
}
|
||||
|
||||
@@ -2017,6 +2106,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
struct delegpt_addr* target;
|
||||
struct outbound_entry* outq;
|
||||
int auth_fallback = 0;
|
||||
uint8_t* qout_orig = NULL;
|
||||
size_t qout_orig_len = 0;
|
||||
|
||||
/* NOTE: a request will encounter this state for each target it
|
||||
* needs to send a query to. That is, at least one per referral,
|
||||
@@ -2032,11 +2123,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);
|
||||
}
|
||||
|
||||
@@ -2044,6 +2137,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)
|
||||
@@ -2061,7 +2155,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
|
||||
@@ -2086,6 +2181,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
int labdiff = qchaselabs -
|
||||
dname_count_labels(iq->qinfo_out.qname);
|
||||
|
||||
qout_orig = iq->qinfo_out.qname;
|
||||
qout_orig_len = iq->qinfo_out.qname_len;
|
||||
iq->qinfo_out.qname = iq->qchase.qname;
|
||||
iq->qinfo_out.qname_len = iq->qchase.qname_len;
|
||||
iq->minimise_count++;
|
||||
@@ -2203,9 +2300,10 @@ 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) {
|
||||
if(iq->dp->auth_dp) {
|
||||
/* we wanted to fallback, but had no delegpt, only the
|
||||
* auth zone generated delegpt, create an actual one */
|
||||
iq->auth_zone_avoid = 1;
|
||||
@@ -2228,6 +2326,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;
|
||||
@@ -2236,6 +2335,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* wait to get all targets, we want to try em */
|
||||
verbose(VERB_ALGO, "wait for all targets for fallback");
|
||||
qstate->ext_state[id] = module_wait_reply;
|
||||
/* undo qname minimise step because we'll get back here
|
||||
* to do it again */
|
||||
if(qout_orig && iq->minimise_count > 0) {
|
||||
iq->minimise_count--;
|
||||
iq->qinfo_out.qname = qout_orig;
|
||||
iq->qinfo_out.qname_len = qout_orig_len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* did we do enough fallback queries already? */
|
||||
@@ -2308,6 +2414,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);
|
||||
}
|
||||
@@ -2367,17 +2475,28 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->num_current_queries);
|
||||
qstate->ext_state[id] = module_wait_reply;
|
||||
}
|
||||
/* undo qname minimise step because we'll get back here
|
||||
* to do it again */
|
||||
if(qout_orig && iq->minimise_count > 0) {
|
||||
iq->minimise_count--;
|
||||
iq->qinfo_out.qname = qout_orig;
|
||||
iq->qinfo_out.qname_len = qout_orig_len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if not forwarding, check ratelimits per delegationpoint name */
|
||||
if(!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok) {
|
||||
if(!infra_ratelimit_inc(qstate->env->infra_cache, iq->dp->name,
|
||||
iq->dp->namelen, *qstate->env->now)) {
|
||||
iq->dp->namelen, *qstate->env->now, &qstate->qinfo,
|
||||
qstate->reply)) {
|
||||
lock_basic_lock(&ie->queries_ratelimit_lock);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -2542,6 +2661,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 */
|
||||
@@ -2586,11 +2714,19 @@ 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)
|
||||
return final_state(iq);
|
||||
if(qstate->env->cfg->qname_minimisation_strict) {
|
||||
if(FLAGS_GET_RCODE(iq->response->rep->flags) ==
|
||||
LDNS_RCODE_NXDOMAIN) {
|
||||
iter_scrub_nxdomain(iq->response);
|
||||
return final_state(iq);
|
||||
}
|
||||
return error_response(qstate, id,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
/* Best effort qname-minimisation.
|
||||
* Stop minimising and send full query when
|
||||
* RCODE is not NOERROR. */
|
||||
@@ -2623,6 +2759,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);
|
||||
@@ -2690,11 +2832,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);
|
||||
@@ -2756,8 +2902,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). */
|
||||
@@ -2858,6 +3006,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, "
|
||||
@@ -2948,6 +3098,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;
|
||||
}
|
||||
@@ -3091,6 +3243,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) */
|
||||
@@ -3191,6 +3344,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 --;
|
||||
@@ -3229,6 +3384,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);
|
||||
}
|
||||
@@ -3275,6 +3432,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);
|
||||
}
|
||||
|
||||
@@ -3439,12 +3597,13 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if(event == module_event_noreply || event == module_event_error) {
|
||||
if(event == module_event_noreply && iq->sent_count >= 3 &&
|
||||
qstate->env->cfg->use_caps_bits_for_id &&
|
||||
!iq->caps_fallback) {
|
||||
!iq->caps_fallback && !is_caps_whitelisted(ie, iq)) {
|
||||
/* start fallback */
|
||||
iq->caps_fallback = 1;
|
||||
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
|
||||
@@ -3459,6 +3618,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;
|
||||
}
|
||||
@@ -3511,6 +3671,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");
|
||||
@@ -3530,15 +3691,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");
|
||||
@@ -3570,6 +3746,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;
|
||||
@@ -3608,6 +3785,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;
|
||||
}
|
||||
@@ -3625,11 +3803,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.
|
||||
|
||||
+21
-17
@@ -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,
|
||||
@@ -294,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;
|
||||
}
|
||||
@@ -322,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;
|
||||
@@ -345,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 */
|
||||
@@ -388,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)
|
||||
|
||||
+16
-10
@@ -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);
|
||||
@@ -728,7 +724,7 @@ ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
*async_id = 0;
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
if(!ctx->finalized) {
|
||||
int r = context_finalize(ctx);
|
||||
r = context_finalize(ctx);
|
||||
if(r) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
return r;
|
||||
@@ -962,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;
|
||||
@@ -971,6 +966,19 @@ ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr)
|
||||
return UB_NOERROR;
|
||||
}
|
||||
|
||||
int ub_ctx_set_tls(struct ub_ctx* ctx, int tls)
|
||||
{
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
if(ctx->finalized) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
errno=EINVAL;
|
||||
return UB_AFTERFINAL;
|
||||
}
|
||||
ctx->env->cfg->ssl_upstream = tls;
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
|
||||
int ub_ctx_set_stub(struct ub_ctx* ctx, const char* zone, const char* addr,
|
||||
int isprime)
|
||||
{
|
||||
@@ -1045,7 +1053,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;
|
||||
}
|
||||
@@ -1233,7 +1240,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;
|
||||
}
|
||||
|
||||
+37
-32
@@ -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);
|
||||
@@ -222,11 +222,10 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
|
||||
}
|
||||
numports = cfg_condense_ports(cfg, &ports);
|
||||
if(numports == 0) {
|
||||
int locked = !w->is_bg || w->is_bg_thread;
|
||||
libworker_delete(w);
|
||||
if(locked) {
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
}
|
||||
libworker_delete(w);
|
||||
return NULL;
|
||||
}
|
||||
w->back = outside_network_create(w->base, cfg->msg_buffer_size,
|
||||
@@ -521,8 +520,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 +546,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 +603,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,7 +634,7 @@ 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 = q->cb_event;
|
||||
@@ -656,8 +656,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 +684,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 +710,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 +724,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 +759,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 +777,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 +808,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 +821,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 +837,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")
|
||||
|
||||
@@ -33,12 +33,26 @@
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
%begin %{
|
||||
/* store state of warning output, restored at later pop */
|
||||
#pragma GCC diagnostic push
|
||||
/* ignore gcc8 METH_NOARGS function cast warnings for swig function pointers */
|
||||
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||
%}
|
||||
%module unbound
|
||||
%{
|
||||
/* restore state of warning output, remove the functioncast ignore */
|
||||
#pragma GCC diagnostic pop
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#include "libunbound/unbound.h"
|
||||
%}
|
||||
|
||||
@@ -108,7 +122,7 @@
|
||||
|
||||
%inline %{
|
||||
void ub_ctx_free_dbg (struct ub_ctx* c) {
|
||||
printf("******** UB_CTX free 0x%lX ************\n", (long unsigned int)c);
|
||||
printf("******** UB_CTX free 0x%p ************\n", c);
|
||||
ub_ctx_delete(c);
|
||||
}
|
||||
|
||||
@@ -228,6 +242,7 @@
|
||||
RR_TYPE_MAILA = 254,
|
||||
/** any type (wildcard) */
|
||||
RR_TYPE_ANY = 255,
|
||||
RR_TYPE_CAA = 257,
|
||||
|
||||
/* RFC 4431, 5074, DNSSEC Lookaside Validation */
|
||||
RR_TYPE_DLV = 32769,
|
||||
@@ -648,7 +663,7 @@ Result: ['74.125.43.147', '74.125.43.99', '74.125.43.103', '74.125.43.104']
|
||||
|
||||
%inline %{
|
||||
void ub_resolve_free_dbg (struct ub_result* r) {
|
||||
printf("******** UB_RESOLVE free 0x%lX ************\n", (long unsigned int)r);
|
||||
printf("******** UB_RESOLVE free 0x%p ************\n", r);
|
||||
ub_resolve_free(r);
|
||||
}
|
||||
%}
|
||||
@@ -809,8 +824,7 @@ Result: ['74.125.43.147', '74.125.43.99', '74.125.43.103', '74.125.43.104']
|
||||
"""
|
||||
return self.rcode2str[self.rcode]
|
||||
|
||||
__swig_getmethods__["rcode_str"] = _get_rcode_str
|
||||
if _newclass:rcode_str = _swig_property(_get_rcode_str)
|
||||
rcode_str = property(_get_rcode_str)
|
||||
|
||||
def _get_raw_data(self):
|
||||
"""Result data, a list of network order DNS rdata items.
|
||||
@@ -819,15 +833,13 @@ Result: ['74.125.43.147', '74.125.43.99', '74.125.43.103', '74.125.43.104']
|
||||
"""
|
||||
return self._ub_result_data(self)
|
||||
|
||||
__swig_getmethods__["rawdata"] = _get_raw_data
|
||||
rawdata = property(_get_raw_data, doc="Returns raw data, a list of rdata items. To decode RAW data use the :attr:`data` attribute which returns an instance of :class:`ub_data` containing the conversion functions.")
|
||||
|
||||
def _get_data(self):
|
||||
if not self.havedata: return None
|
||||
return ub_data(self._ub_result_data(self))
|
||||
|
||||
__swig_getmethods__["data"] = _get_data
|
||||
__swig_getmethods__["packet"] = _packet
|
||||
packet = property(_packet)
|
||||
data = property(_get_data, doc="Returns :class:`ub_data` instance containing various decoding functions or None")
|
||||
|
||||
%}
|
||||
|
||||
@@ -20,6 +20,7 @@ ub_ctx_set_event
|
||||
ub_ctx_set_fwd
|
||||
ub_ctx_set_option
|
||||
ub_ctx_set_stub
|
||||
ub_ctx_set_tls
|
||||
ub_ctx_trustedkeys
|
||||
ub_ctx_zone_add
|
||||
ub_ctx_zone_remove
|
||||
|
||||
@@ -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.
|
||||
@@ -303,6 +309,17 @@ int ub_ctx_config(struct ub_ctx* ctx, const char* fname);
|
||||
*/
|
||||
int ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr);
|
||||
|
||||
/**
|
||||
* Use DNS over TLS to send queries to machines set with ub_ctx_set_fwd().
|
||||
*
|
||||
* @param ctx: context.
|
||||
* At this time it is only possible to set configuration before the
|
||||
* first resolve is done.
|
||||
* @param tls: enable or disable DNS over TLS
|
||||
* @return 0 if OK, else error.
|
||||
*/
|
||||
int ub_ctx_set_tls(struct ub_ctx* ctx, int tls);
|
||||
|
||||
/**
|
||||
* Add a stub zone, with given address to send to. This is for custom
|
||||
* root hints or pointing to a local authoritative dns server.
|
||||
@@ -674,6 +691,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 +776,15 @@ 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;
|
||||
/** number of bytes in the stream wait buffers */
|
||||
long long mem_stream_wait;
|
||||
/** number of TLS connection resume */
|
||||
long long qtls_resume;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+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.
|
||||
|
||||
@@ -2124,7 +2124,7 @@ fi
|
||||
# a configuration failure hint, and exit.
|
||||
func_fatal_configuration ()
|
||||
{
|
||||
func__fatal_error ${1+"$@"} \
|
||||
func_fatal_error ${1+"$@"} \
|
||||
"See the $PACKAGE documentation for more information." \
|
||||
"Fatal configuration error."
|
||||
}
|
||||
@@ -7272,10 +7272,12 @@ func_mode_link ()
|
||||
# -tp=* Portland pgcc target processor selection
|
||||
# --sysroot=* for sysroot support
|
||||
# -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization
|
||||
# -specs=* GCC specs files
|
||||
# -stdlib=* select c++ std lib with clang
|
||||
-64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
|
||||
-t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
|
||||
-O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*)
|
||||
-O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \
|
||||
-specs=*)
|
||||
func_quote_for_eval "$arg"
|
||||
arg=$func_quote_for_eval_result
|
||||
func_append compile_command " $arg"
|
||||
|
||||
+93
-37
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Build unbound distribution tar from the SVN repository.
|
||||
# Build unbound distribution tar from the git repository.
|
||||
#
|
||||
# Copyright (c) 2007, NLnet Labs. All rights reserved.
|
||||
#
|
||||
@@ -42,7 +42,7 @@ cwd=`pwd`
|
||||
# Utility functions.
|
||||
usage () {
|
||||
cat >&2 <<EOF
|
||||
Usage $0: [-h] [-s] [-d SVN_root] [-w ...args...]
|
||||
Usage $0: [-h] [-s] [-u git_url] [-b git_branch] [-w ...args...]
|
||||
Generate a distribution tar file for unbound.
|
||||
|
||||
-h This usage information.
|
||||
@@ -51,8 +51,10 @@ Generate a distribution tar file for unbound.
|
||||
-rc <nr> Build a release candidate, the given string will be added
|
||||
to the version number
|
||||
(which will then be unbound-<version>rc<number>)
|
||||
-d SVN_root Retrieve the unbound source from the specified repository.
|
||||
Detected from svn working copy if not specified.
|
||||
-u git_url Retrieve the source from the specified repository url.
|
||||
Detected from the working copy if not specified.
|
||||
-b git_branch Retrieve the the specified branch or tag.
|
||||
Detected from the working copy if not specified.
|
||||
-wssl openssl.xx.tar.gz Also build openssl from tarball for windows dist.
|
||||
-wxp expat.xx.tar.gz Also build expat from tarball for windows dist.
|
||||
-w32 32bit windows compile.
|
||||
@@ -115,16 +117,20 @@ replace_version () {
|
||||
replace_text "$1" "VERSION_MICRO\],\[$v1" "VERSION_MICRO\],\[$v2"
|
||||
}
|
||||
|
||||
check_svn_root () {
|
||||
# Check if SVNROOT is specified.
|
||||
if [ -z "$SVNROOT" ]; then
|
||||
if svn info 2>&1 | grep "not a working copy" >/dev/null; then
|
||||
if test -z "$SVNROOT"; then
|
||||
error "SVNROOT must be specified (using -d)"
|
||||
fi
|
||||
check_git_repo () {
|
||||
# Check if git repo and branch are specified.
|
||||
if [ -z "$GITREPO" ]; then
|
||||
if git status 2>&1 | grep "not a git repository" >/dev/null; then
|
||||
error "specify repo (using -u) or use settings detected by starting from working copy directory"
|
||||
else
|
||||
eval `svn info | grep 'URL:' | sed -e 's/URL: /url=/' | head -1`
|
||||
SVNROOT="$url"
|
||||
GITREPO="`git config --get remote.origin.url`"
|
||||
fi
|
||||
fi
|
||||
if [ -z "$GITBRANCH" ]; then
|
||||
if git status 2>&1 | grep "not a git repository" >/dev/null; then
|
||||
error "specify branch (using -b) or use settings detected by starting from working copy directory"
|
||||
else
|
||||
GITBRANCH="`git branch | grep '^\*' | sed -e 's/^\* //'`"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
@@ -181,6 +187,7 @@ DOWIN="no"
|
||||
W64="yes"
|
||||
WINSSL=""
|
||||
WINEXPAT=""
|
||||
MINJ=""
|
||||
|
||||
# Parse the command line arguments.
|
||||
while [ "$1" ]; do
|
||||
@@ -188,8 +195,12 @@ while [ "$1" ]; do
|
||||
"-h")
|
||||
usage
|
||||
;;
|
||||
"-d")
|
||||
SVNROOT="$2"
|
||||
"-u")
|
||||
GITREPO="$2"
|
||||
shift
|
||||
;;
|
||||
"-b")
|
||||
GITBRANCH="$2"
|
||||
shift
|
||||
;;
|
||||
"-s")
|
||||
@@ -239,8 +250,9 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
makensis="makensis" # from mingw32-nsis package
|
||||
# flags for crosscompiled dependency libraries
|
||||
cross_flag=""
|
||||
shared_cross_flag=""
|
||||
|
||||
check_svn_root
|
||||
check_git_repo
|
||||
create_temp_dir
|
||||
|
||||
# crosscompile openssl for windows.
|
||||
@@ -249,24 +261,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,18 +302,22 @@ 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
|
||||
|
||||
info "SVNROOT is $SVNROOT"
|
||||
info "Exporting source from SVN."
|
||||
svn export "$SVNROOT" unbound || error_cleanup "SVN command failed"
|
||||
cd unbound || error_cleanup "Unbound not exported correctly from SVN"
|
||||
info "GITREPO is $GITREPO"
|
||||
info "GITBRANCH is $GITBRANCH"
|
||||
info "Exporting source from git."
|
||||
info "git clone --depth=1 --no-tags -b $GITBRANCH $GITREPO unbound"
|
||||
git clone --depth=1 --no-tags -b $GITBRANCH $GITREPO unbound || error_cleanup "git clone failed"
|
||||
cd unbound || error_cleanup "Unbound not exported correctly from git"
|
||||
rm -rf .git || error_cleanup "Failed to remove .git tracking information"
|
||||
|
||||
# on a re-configure the cache may no longer be valid...
|
||||
if test -f mingw32-config.cache; then rm mingw32-config.cache; fi
|
||||
@@ -320,6 +349,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 +371,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 +410,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"
|
||||
@@ -390,20 +442,24 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
check_svn_root
|
||||
check_git_repo
|
||||
|
||||
# Start the packaging process.
|
||||
info "SVNROOT is $SVNROOT"
|
||||
info "SNAPSHOT is $SNAPSHOT"
|
||||
info "GITREPO is $GITREPO"
|
||||
info "GITBRANCH is $GITBRANCH"
|
||||
info "SNAPSHOT is $SNAPSHOT"
|
||||
|
||||
#question "Do you wish to continue with these settings?" || error "User abort."
|
||||
|
||||
create_temp_dir
|
||||
|
||||
info "Exporting source from SVN."
|
||||
svn export "$SVNROOT" unbound || error_cleanup "SVN command failed"
|
||||
info "Exporting source from git."
|
||||
# --depth=1 and --no-tags reduce the download size.
|
||||
info "git clone --depth=1 --no-tags -b $GITBRANCH $GITREPO unbound"
|
||||
git clone --depth=1 --no-tags -b $GITBRANCH $GITREPO unbound || error_cleanup "git clone failed"
|
||||
|
||||
cd unbound || error_cleanup "Unbound not exported correctly from SVN"
|
||||
cd unbound || error_cleanup "Unbound not exported correctly from git"
|
||||
rm -rf .git || error_cleanup "Failed to remove .git tracking information"
|
||||
|
||||
info "Adding libtool utils (libtoolize)."
|
||||
libtoolize -c --install || libtoolize -c || error_cleanup "Libtoolize failed."
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
|
||||
def init(id, cfg):
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
|
||||
return True
|
||||
|
||||
def init_standard(id, env):
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, env.cfg.port, env.cfg.python_script))
|
||||
return True
|
||||
|
||||
def deinit(id):
|
||||
log_info("pythonmod: deinit called, module id is %d" % id)
|
||||
return True
|
||||
|
||||
@@ -54,6 +54,25 @@ Script file must contain four compulsory functions:
|
||||
return True
|
||||
|
||||
|
||||
.. function:: init_standard(id, env)
|
||||
|
||||
Initialize module internals, like database etc.
|
||||
Called just once on module load.
|
||||
|
||||
*Preferred* over the init() function above as this function's signature is the
|
||||
same as the C counterpart and allows for extra functionality during init.
|
||||
The previously accessible configuration options can now be found in env.cfg.
|
||||
|
||||
:param id: module identifier (integer)
|
||||
:param env: :class:`module_env` module environment
|
||||
|
||||
::
|
||||
|
||||
def init_standard(id, env):
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, env.cfg.port, env.cfg.python_script))
|
||||
return True
|
||||
|
||||
|
||||
.. function:: deinit(id)
|
||||
|
||||
Deinitialize module internals.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -0,0 +1,567 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# A plugin for the Unbound DNS resolver to resolve DNS records in
|
||||
# multicast DNS [RFC 6762] via Avahi.
|
||||
#
|
||||
# Copyright (C) 2018-2019 Internet Real-Time Lab, Columbia University
|
||||
# http://www.cs.columbia.edu/irt/
|
||||
#
|
||||
# Written by Jan Janak <janakj@cs.columbia.edu>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
#
|
||||
# Dependendies:
|
||||
# Unbound with pythonmodule configured for Python 3
|
||||
# dnspython [http://www.dnspython.org]
|
||||
# pydbus [https://github.com/LEW21/pydbus]
|
||||
#
|
||||
# To enable Python 3 support, configure Unbound as follows:
|
||||
# PYTHON_VERSION=3 ./configure --with-pythonmodule
|
||||
#
|
||||
# The plugin in meant to be used as a fallback resolver that resolves
|
||||
# records in multicast DNS if the upstream server cannot be reached or
|
||||
# provides no answer (NXDOMAIN).
|
||||
#
|
||||
# mDNS requests for negative records, i.e., records for which Avahi
|
||||
# returns no answer (NXDOMAIN), are expensive. Since there is no
|
||||
# single authoritative server in mDNS, such requests terminate only
|
||||
# via a timeout. The timeout is about a second (if MDNS_TIMEOUT is not
|
||||
# configured), or the value configured via MDNS_TIMEOUT. The
|
||||
# corresponding Unbound thread will be blocked for this amount of
|
||||
# time. For this reason, it is important to configure an appropriate
|
||||
# number of threads in unbound.conf and limit the RR types and names
|
||||
# that will be resolved via Avahi via the environment variables
|
||||
# described later.
|
||||
#
|
||||
# An example unbound.conf with the plugin enabled:
|
||||
#
|
||||
# | server:
|
||||
# | module-config: "validator python iterator"
|
||||
# | num-threads: 32
|
||||
# | cache-max-negative-ttl: 60
|
||||
# | cache-max-ttl: 60
|
||||
#
|
||||
#
|
||||
# The plugin can also be run interactively. Provide the name and
|
||||
# record type to be resolved as command line arguments and the
|
||||
# resolved record will be printed to standard output:
|
||||
#
|
||||
# $ ./avahi-resolver.py voip-phx4.phxnet.org A
|
||||
# voip-phx4.phxnet.org. 120 IN A 10.4.3.2
|
||||
#
|
||||
#
|
||||
# The behavior of the plugin can be controlled via the following
|
||||
# environment variables:
|
||||
#
|
||||
# DBUS_SYSTEM_BUS_ADDRESS
|
||||
#
|
||||
# The address of the system DBus bus, in the format expected by DBus,
|
||||
# e.g., unix:path=/run/avahi/system-bus.sock
|
||||
#
|
||||
#
|
||||
# DEBUG
|
||||
#
|
||||
# Set this environment variable to "yes", "true", "on", or "1" to
|
||||
# enable debugging. In debugging mode, the plugin will output a lot
|
||||
# more information about what it is doing either to the standard
|
||||
# output (when run interactively) or to Unbound via log_info and
|
||||
# log_error.
|
||||
#
|
||||
# By default debugging is disabled.
|
||||
#
|
||||
#
|
||||
# MDNS_TTL
|
||||
#
|
||||
# Avahi does not provide the TTL value for the records it returns.
|
||||
# This environment variable can be used to configure the TTL value for
|
||||
# such records.
|
||||
#
|
||||
# The default value is 120 seconds.
|
||||
#
|
||||
#
|
||||
# MDNS_TIMEOUT
|
||||
#
|
||||
# The maximum amount of time (in milliseconds) an Avahi request is
|
||||
# allowed to run. This value sets the time it takes to resolve
|
||||
# negative (non-existent) records in Avahi. If unset, the request
|
||||
# terminates when Avahi sends the "AllForNow" signal, telling the
|
||||
# client that more records are unlikely to arrive. This takes roughly
|
||||
# about one second. You may need to configure a longer value here on
|
||||
# slower networks, e.g., networks that relay mDNS packets such as
|
||||
# MANETs.
|
||||
#
|
||||
#
|
||||
# MDNS_GETONE
|
||||
#
|
||||
# If set to "true", "1", or "on", an Avahi request will terminate as
|
||||
# soon as at least one record has been found. If there are multiple
|
||||
# nodes in the mDNS network publishing the same record, only one (or
|
||||
# subset) will be returned.
|
||||
#
|
||||
# If set to "false", "0", or "off", the plugin will gather records for
|
||||
# MDNS_TIMEOUT and return all records found. This is only useful in
|
||||
# networks where multiple nodes are known to publish different records
|
||||
# under the same name and the client needs to be able to obtain them
|
||||
# all. When configured this way, all Avahi requests will always take
|
||||
# MDNS_TIMEOUT to complete!
|
||||
#
|
||||
# This option is set to true by default.
|
||||
#
|
||||
#
|
||||
# MDNS_REJECT_TYPES
|
||||
#
|
||||
# A comma-separated list of record types that will NOT be resolved in
|
||||
# mDNS via Avahi. Use this environment variable to prevent specific
|
||||
# record types from being resolved via Avahi. For example, if your
|
||||
# network does not support IPv6, you can put AAAA on this list.
|
||||
#
|
||||
# The default value is an empty list.
|
||||
#
|
||||
# Example: MDNS_REJECT_TYPES=aaaa,mx,soa
|
||||
#
|
||||
#
|
||||
# MDNS_ACCEPT_TYPES
|
||||
#
|
||||
# If set, a record type will be resolved via Avahi if and only if it
|
||||
# is present on this comma-separated list. In other words, this is a
|
||||
# whitelist.
|
||||
#
|
||||
# The default value is an empty list which means all record types will
|
||||
# be resolved via Avahi.
|
||||
#
|
||||
# Example: MDNS_ACCEPT_TYPES=a,ptr,txt,srv,aaaa,cname
|
||||
#
|
||||
#
|
||||
# MDNS_REJECT_NAMES
|
||||
#
|
||||
# If the name being resolved matches the regular expression in this
|
||||
# environment variable, the name will NOT be resolved via Avahi. In
|
||||
# other words, this environment variable provides a blacklist.
|
||||
#
|
||||
# The default value is empty--no names will be reject.
|
||||
#
|
||||
# Example: MDNS_REJECT_NAMES=(^|\.)example\.com\.$
|
||||
#
|
||||
#
|
||||
# MDNS_ACCEPT_NAMES
|
||||
#
|
||||
# If set to a regular expression, a name will be resolved via Avahi if
|
||||
# and only if it matches the regular expression. In other words, this
|
||||
# variable provides a whitelist.
|
||||
#
|
||||
# The default value is empty--all names will be resolved via Avahi.
|
||||
#
|
||||
# Example: MDNS_ACCEPT_NAMES=^.*\.example\.com\.$
|
||||
#
|
||||
|
||||
import os
|
||||
import re
|
||||
import array
|
||||
import threading
|
||||
import traceback
|
||||
import dns.rdata
|
||||
import dns.rdatatype
|
||||
import dns.rdataclass
|
||||
from queue import Queue
|
||||
from gi.repository import GLib
|
||||
from pydbus import SystemBus
|
||||
|
||||
|
||||
IF_UNSPEC = -1
|
||||
PROTO_UNSPEC = -1
|
||||
|
||||
sysbus = None
|
||||
avahi = None
|
||||
trampoline = dict()
|
||||
thread_local = threading.local()
|
||||
dbus_thread = None
|
||||
dbus_loop = None
|
||||
|
||||
|
||||
def str2bool(v):
|
||||
if v.lower() in ['false', 'no', '0', 'off', '']:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def dbg(msg):
|
||||
if DEBUG != False:
|
||||
log_info('avahi-resolver: %s' % msg)
|
||||
|
||||
|
||||
#
|
||||
# Although pydbus has an internal facility for handling signals, we
|
||||
# cannot use that with Avahi. When responding from an internal cache,
|
||||
# Avahi sends the first signal very quickly, before pydbus has had a
|
||||
# chance to subscribe for the signal. This will result in lost signal
|
||||
# and missed data:
|
||||
#
|
||||
# https://github.com/LEW21/pydbus/issues/87
|
||||
#
|
||||
# As a workaround, we subscribe to all signals before creating a
|
||||
# record browser and do our own signal matching and dispatching via
|
||||
# the following function.
|
||||
#
|
||||
def signal_dispatcher(connection, sender, path, interface, name, args):
|
||||
o = trampoline.get(path, None)
|
||||
if o is None:
|
||||
return
|
||||
|
||||
if name == 'ItemNew': o.itemNew(*args)
|
||||
elif name == 'ItemRemove': o.itemRemove(*args)
|
||||
elif name == 'AllForNow': o.allForNow(*args)
|
||||
elif name == 'Failure': o.failure(*args)
|
||||
|
||||
|
||||
class RecordBrowser:
|
||||
def __init__(self, callback, name, type_, timeout=None, getone=True):
|
||||
self.callback = callback
|
||||
self.records = []
|
||||
self.error = None
|
||||
self.getone = getone
|
||||
|
||||
self.timer = None if timeout is None else GLib.timeout_add(timeout, self.timedOut)
|
||||
|
||||
self.browser_path = avahi.RecordBrowserNew(IF_UNSPEC, PROTO_UNSPEC, name, dns.rdataclass.IN, type_, 0)
|
||||
trampoline[self.browser_path] = self
|
||||
self.browser = sysbus.get('.Avahi', self.browser_path)
|
||||
self.dbg('Created RecordBrowser(name=%s, type=%s, getone=%s, timeout=%s)'
|
||||
% (name, dns.rdatatype.to_text(type_), getone, timeout))
|
||||
|
||||
def dbg(self, msg):
|
||||
dbg('[%s] %s' % (self.browser_path, msg))
|
||||
|
||||
def _done(self):
|
||||
del trampoline[self.browser_path]
|
||||
self.dbg('Freeing')
|
||||
self.browser.Free()
|
||||
|
||||
if self.timer is not None:
|
||||
self.dbg('Removing timer')
|
||||
GLib.source_remove(self.timer)
|
||||
|
||||
self.callback(self.records, self.error)
|
||||
|
||||
def itemNew(self, interface, protocol, name, class_, type_, rdata, flags):
|
||||
self.dbg('Got signal ItemNew')
|
||||
self.records.append((name, class_, type_, rdata))
|
||||
if self.getone:
|
||||
self._done()
|
||||
|
||||
def itemRemove(self, interface, protocol, name, class_, type_, rdata, flags):
|
||||
self.dbg('Got signal ItemRemove')
|
||||
self.records.remove((name, class_, type_, rdata))
|
||||
|
||||
def failure(self, error):
|
||||
self.dbg('Got signal Failure')
|
||||
self.error = Exception(error)
|
||||
self._done()
|
||||
|
||||
def allForNow(self):
|
||||
self.dbg('Got signal AllForNow')
|
||||
if self.timer is None:
|
||||
self._done()
|
||||
|
||||
def timedOut(self):
|
||||
self.dbg('Timed out')
|
||||
self._done()
|
||||
return False
|
||||
|
||||
|
||||
#
|
||||
# This function runs the main event loop for DBus (GLib). This
|
||||
# function must be run in a dedicated worker thread.
|
||||
#
|
||||
def dbus_main():
|
||||
global sysbus, avahi, dbus_loop
|
||||
|
||||
dbg('Connecting to system DBus')
|
||||
sysbus = SystemBus()
|
||||
|
||||
dbg('Subscribing to .Avahi.RecordBrowser signals')
|
||||
sysbus.con.signal_subscribe('org.freedesktop.Avahi',
|
||||
'org.freedesktop.Avahi.RecordBrowser',
|
||||
None, None, None, 0, signal_dispatcher)
|
||||
|
||||
avahi = sysbus.get('.Avahi', '/')
|
||||
|
||||
dbg("Connected to Avahi Daemon: %s (API %s) [%s]"
|
||||
% (avahi.GetVersionString(), avahi.GetAPIVersion(), avahi.GetHostNameFqdn()))
|
||||
|
||||
dbg('Starting DBus main loop')
|
||||
dbus_loop = GLib.MainLoop()
|
||||
dbus_loop.run()
|
||||
|
||||
|
||||
#
|
||||
# This function must be run in the DBus worker thread. It creates a
|
||||
# new RecordBrowser instance and once it has finished doing it thing,
|
||||
# it will send the result back to the original thread via the queue.
|
||||
#
|
||||
def start_resolver(queue, *args, **kwargs):
|
||||
try:
|
||||
RecordBrowser(lambda *v: queue.put_nowait(v), *args, **kwargs)
|
||||
except Exception as e:
|
||||
queue.put_nowait((None, e))
|
||||
|
||||
return False
|
||||
|
||||
|
||||
#
|
||||
# To resolve a request, we setup a queue, post a task to the DBus
|
||||
# worker thread, and wait for the result (or error) to arrive over the
|
||||
# queue. If the worker thread reports an error, raise the error as an
|
||||
# exception.
|
||||
#
|
||||
def resolve(*args, **kwargs):
|
||||
try:
|
||||
queue = thread_local.queue
|
||||
except AttributeError:
|
||||
dbg('Creating new per-thread queue')
|
||||
queue = Queue()
|
||||
thread_local.queue = queue
|
||||
|
||||
GLib.idle_add(lambda: start_resolver(queue, *args, **kwargs))
|
||||
|
||||
records, error = queue.get()
|
||||
queue.task_done()
|
||||
|
||||
if error is not None:
|
||||
raise error
|
||||
|
||||
return records
|
||||
|
||||
|
||||
def parse_type_list(lst):
|
||||
return list(map(dns.rdatatype.from_text, [v.strip() for v in lst.split(',') if len(v)]))
|
||||
|
||||
|
||||
def init(*args, **kwargs):
|
||||
global dbus_thread, DEBUG
|
||||
global MDNS_TTL, MDNS_GETONE, MDNS_TIMEOUT
|
||||
global MDNS_REJECT_TYPES, MDNS_ACCEPT_TYPES
|
||||
global MDNS_REJECT_NAMES, MDNS_ACCEPT_NAMES
|
||||
|
||||
DEBUG = str2bool(os.environ.get('DEBUG', str(False)))
|
||||
|
||||
MDNS_TTL = int(os.environ.get('MDNS_TTL', 120))
|
||||
dbg("TTL for records from Avahi: %d" % MDNS_TTL)
|
||||
|
||||
MDNS_REJECT_TYPES = parse_type_list(os.environ.get('MDNS_REJECT_TYPES', ''))
|
||||
if MDNS_REJECT_TYPES:
|
||||
dbg('Types NOT resolved via Avahi: %s' % MDNS_REJECT_TYPES)
|
||||
|
||||
MDNS_ACCEPT_TYPES = parse_type_list(os.environ.get('MDNS_ACCEPT_TYPES', ''))
|
||||
if MDNS_ACCEPT_TYPES:
|
||||
dbg('ONLY resolving the following types via Avahi: %s' % MDNS_ACCEPT_TYPES)
|
||||
|
||||
v = os.environ.get('MDNS_REJECT_NAMES', None)
|
||||
MDNS_REJECT_NAMES = re.compile(v, flags=re.I | re.S) if v is not None else None
|
||||
if MDNS_REJECT_NAMES is not None:
|
||||
dbg('Names NOT resolved via Avahi: %s' % MDNS_REJECT_NAMES.pattern)
|
||||
|
||||
v = os.environ.get('MDNS_ACCEPT_NAMES', None)
|
||||
MDNS_ACCEPT_NAMES = re.compile(v, flags=re.I | re.S) if v is not None else None
|
||||
if MDNS_ACCEPT_NAMES is not None:
|
||||
dbg('ONLY resolving the following names via Avahi: %s' % MDNS_ACCEPT_NAMES.pattern)
|
||||
|
||||
v = os.environ.get('MDNS_TIMEOUT', None)
|
||||
MDNS_TIMEOUT = int(v) if v is not None else None
|
||||
if MDNS_TIMEOUT is not None:
|
||||
dbg('Avahi request timeout: %s' % MDNS_TIMEOUT)
|
||||
|
||||
MDNS_GETONE = str2bool(os.environ.get('MDNS_GETONE', str(True)))
|
||||
dbg('Terminate Avahi requests on first record: %s' % MDNS_GETONE)
|
||||
|
||||
dbus_thread = threading.Thread(target=dbus_main)
|
||||
dbus_thread.daemon = True
|
||||
dbus_thread.start()
|
||||
|
||||
|
||||
def deinit(*args, **kwargs):
|
||||
dbus_loop.quit()
|
||||
dbus_thread.join()
|
||||
return True
|
||||
|
||||
|
||||
def inform_super(id, qstate, superqstate, qdata):
|
||||
return True
|
||||
|
||||
|
||||
def get_rcode(msg):
|
||||
if not msg:
|
||||
return RCODE_SERVFAIL
|
||||
|
||||
return msg.rep.flags & 0xf
|
||||
|
||||
|
||||
def rr2text(rec, ttl):
|
||||
name, class_, type_, rdata = rec
|
||||
wire = array.array('B', rdata).tostring()
|
||||
return '%s. %d %s %s %s' % (
|
||||
name,
|
||||
ttl,
|
||||
dns.rdataclass.to_text(class_),
|
||||
dns.rdatatype.to_text(type_),
|
||||
dns.rdata.from_wire(class_, type_, wire, 0, len(wire), None))
|
||||
|
||||
|
||||
def operate(id, event, qstate, qdata):
|
||||
qi = qstate.qinfo
|
||||
name = qi.qname_str
|
||||
type_ = qi.qtype
|
||||
type_str = dns.rdatatype.to_text(type_)
|
||||
class_ = qi.qclass
|
||||
class_str = dns.rdataclass.to_text(class_)
|
||||
rc = get_rcode(qstate.return_msg)
|
||||
|
||||
if event == MODULE_EVENT_NEW or event == MODULE_EVENT_PASS:
|
||||
qstate.ext_state[id] = MODULE_WAIT_MODULE
|
||||
return True
|
||||
|
||||
if event != MODULE_EVENT_MODDONE:
|
||||
log_err("avahi-resolver: Unexpected event %d" % event)
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
||||
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
|
||||
# Only resolve via Avahi if we got NXDOMAIn from the upstream DNS
|
||||
# server, or if we could not reach the upstream DNS server. If we
|
||||
# got some records for the name from the upstream DNS server
|
||||
# already, do not resolve the record in Avahi.
|
||||
if rc != RCODE_NXDOMAIN and rc != RCODE_SERVFAIL:
|
||||
return True
|
||||
|
||||
dbg("Got request for '%s %s %s'" % (name, class_str, type_str))
|
||||
|
||||
# Avahi only supports the IN class
|
||||
if class_ != RR_CLASS_IN:
|
||||
dbg('Rejected, Avahi only supports the IN class')
|
||||
return True
|
||||
|
||||
# Avahi does not support meta queries (e.g., ANY)
|
||||
if dns.rdatatype.is_metatype(type_):
|
||||
dbg('Rejected, Avahi does not support the type %s' % type_str)
|
||||
return True
|
||||
|
||||
# If we have a type blacklist and the requested type is on the
|
||||
# list, reject it.
|
||||
if MDNS_REJECT_TYPES and type_ in MDNS_REJECT_TYPES:
|
||||
dbg('Rejected, type %s is on the blacklist' % type_str)
|
||||
return True
|
||||
|
||||
# If we have a type whitelist and if the requested type is not on
|
||||
# the list, reject it.
|
||||
if MDNS_ACCEPT_TYPES and type_ not in MDNS_ACCEPT_TYPES:
|
||||
dbg('Rejected, type %s is not on the whitelist' % type_str)
|
||||
return True
|
||||
|
||||
# If we have a name blacklist and if the requested name matches
|
||||
# the blacklist, reject it.
|
||||
if MDNS_REJECT_NAMES is not None:
|
||||
if MDNS_REJECT_NAMES.search(name):
|
||||
dbg('Rejected, name %s is on the blacklist' % name)
|
||||
return True
|
||||
|
||||
# If we have a name whitelist and if the requested name does not
|
||||
# match the whitelist, reject it.
|
||||
if MDNS_ACCEPT_NAMES is not None:
|
||||
if not MDNS_ACCEPT_NAMES.search(name):
|
||||
dbg('Rejected, name %s is not on the whitelist' % name)
|
||||
return True
|
||||
|
||||
dbg("Resolving '%s %s %s' via Avahi" % (name, class_str, type_str))
|
||||
|
||||
recs = resolve(name, type_, getone=MDNS_GETONE, timeout=MDNS_TIMEOUT)
|
||||
|
||||
if not recs:
|
||||
dbg('Result: Not found (NXDOMAIN)')
|
||||
qstate.return_rcode = RCODE_NXDOMAIN
|
||||
return True
|
||||
|
||||
m = DNSMessage(name, type_, class_, PKT_QR | PKT_RD | PKT_RA)
|
||||
for r in recs:
|
||||
s = rr2text(r, MDNS_TTL)
|
||||
dbg('Result: %s' % s)
|
||||
m.answer.append(s)
|
||||
|
||||
if not m.set_return_msg(qstate):
|
||||
raise Exception("Error in set_return_msg")
|
||||
|
||||
if not storeQueryInCache(qstate, qstate.return_msg.qinfo, qstate.return_msg.rep, 0):
|
||||
raise Exception("Error in storeQueryInCache")
|
||||
|
||||
qstate.return_msg.rep.security = 2
|
||||
qstate.return_rcode = RCODE_NOERROR
|
||||
return True
|
||||
|
||||
|
||||
#
|
||||
# It does not appear to be sufficient to check __name__ to determine
|
||||
# whether we are being run in interactive mode. As a workaround, try
|
||||
# to import module unboundmodule and if that fails, assume we're being
|
||||
# run in interactive mode.
|
||||
#
|
||||
try:
|
||||
import unboundmodule
|
||||
embedded = True
|
||||
except ImportError:
|
||||
embedded = False
|
||||
|
||||
if __name__ == '__main__' and not embedded:
|
||||
import sys
|
||||
|
||||
def log_info(msg):
|
||||
print(msg)
|
||||
|
||||
def log_err(msg):
|
||||
print('ERROR: %s' % msg, file=sys.stderr)
|
||||
|
||||
if len(sys.argv) != 3:
|
||||
print('Usage: %s <name> <rr_type>' % sys.argv[0])
|
||||
sys.exit(2)
|
||||
|
||||
name = sys.argv[1]
|
||||
type_str = sys.argv[2]
|
||||
|
||||
try:
|
||||
type_ = dns.rdatatype.from_text(type_str)
|
||||
except dns.rdatatype.UnknownRdatatype:
|
||||
log_err('Unsupported DNS record type "%s"' % type_str)
|
||||
sys.exit(2)
|
||||
|
||||
if dns.rdatatype.is_metatype(type_):
|
||||
log_err('Meta record type "%s" cannot be resolved via Avahi' % type_str)
|
||||
sys.exit(2)
|
||||
|
||||
init()
|
||||
try:
|
||||
recs = resolve(name, type_, getone=MDNS_GETONE, timeout=MDNS_TIMEOUT)
|
||||
if not len(recs):
|
||||
print('%s not found (NXDOMAIN)' % name)
|
||||
sys.exit(1)
|
||||
|
||||
for r in recs:
|
||||
print(rr2text(r, MDNS_TTL))
|
||||
finally:
|
||||
deinit()
|
||||
@@ -78,7 +78,7 @@ def init_standard(id, env):
|
||||
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.
|
||||
env.cfg.
|
||||
"""
|
||||
log_info("python: inited script {}".format(env.cfg.python_script))
|
||||
|
||||
|
||||
@@ -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.
|
||||
env.cfg.
|
||||
|
||||
"""
|
||||
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
|
||||
|
||||
+315
-127
@@ -1,17 +1,37 @@
|
||||
/*
|
||||
* interface.i: unbound python module
|
||||
*/
|
||||
%begin %{
|
||||
/* store state of warning output, restored at later pop */
|
||||
#pragma GCC diagnostic push
|
||||
/* ignore gcc8 METH_NOARGS function cast warnings for swig function pointers */
|
||||
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||
%}
|
||||
%module unboundmodule
|
||||
%{
|
||||
/* restore state of warning output, remove the functioncast ignore */
|
||||
#pragma GCC diagnostic pop
|
||||
/**
|
||||
* \file
|
||||
* This is the interface between the unbound server and a python module
|
||||
* called to perform operations on queries.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
#include "config.h"
|
||||
#include "util/log.h"
|
||||
@@ -43,15 +63,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,33 +185,28 @@ 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);
|
||||
}
|
||||
%}
|
||||
|
||||
%extend query_info {
|
||||
%pythoncode %{
|
||||
def _get_qtype_str(self): return sldns_wire2str_type(self.qtype)
|
||||
__swig_getmethods__["qtype_str"] = _get_qtype_str
|
||||
if _newclass:qtype_str = _swig_property(_get_qtype_str)
|
||||
qtype_str = property(_get_qtype_str)
|
||||
|
||||
def _get_qclass_str(self): return sldns_wire2str_class(self.qclass)
|
||||
__swig_getmethods__["qclass_str"] = _get_qclass_str
|
||||
if _newclass:qclass_str = _swig_property(_get_qclass_str)
|
||||
qclass_str = property(_get_qclass_str)
|
||||
|
||||
__swig_getmethods__["qname"] = _unboundmodule._get_qname
|
||||
if _newclass:qname = _swig_property(_unboundmodule._get_qname)
|
||||
qname = property(_unboundmodule._get_qname)
|
||||
|
||||
__swig_getmethods__["qname_list"] = _unboundmodule._get_qname_components
|
||||
if _newclass:qname_list = _swig_property(_unboundmodule._get_qname_components)
|
||||
qname_list = property(_unboundmodule._get_qname_components)
|
||||
|
||||
def _get_qname_str(self): return dnameAsStr(self.qname)
|
||||
__swig_getmethods__["qname_str"] = _get_qname_str
|
||||
if _newclass:qname_str = _swig_property(_get_qname_str)
|
||||
qname_str = property(_get_qname_str)
|
||||
%}
|
||||
}
|
||||
|
||||
@@ -225,22 +246,17 @@ uint16_t ntohs(uint16_t netshort);
|
||||
%extend packed_rrset_key {
|
||||
%pythoncode %{
|
||||
def _get_type_str(self): return sldns_wire2str_type(_unboundmodule.ntohs(self.type))
|
||||
__swig_getmethods__["type_str"] = _get_type_str
|
||||
if _newclass:type_str = _swig_property(_get_type_str)
|
||||
type_str = property(_get_type_str)
|
||||
|
||||
def _get_class_str(self): return sldns_wire2str_class(_unboundmodule.ntohs(self.rrset_class))
|
||||
__swig_getmethods__["rrset_class_str"] = _get_class_str
|
||||
if _newclass:rrset_class_str = _swig_property(_get_class_str)
|
||||
rrset_class_str = property(_get_class_str)
|
||||
|
||||
__swig_getmethods__["dname"] = _unboundmodule._get_dname
|
||||
if _newclass:dname = _swig_property(_unboundmodule._get_dname)
|
||||
dname = property(_unboundmodule._get_dname)
|
||||
|
||||
__swig_getmethods__["dname_list"] = _unboundmodule._get_dname_components
|
||||
if _newclass:dname_list = _swig_property(_unboundmodule._get_dname_components)
|
||||
dname_list = property(_unboundmodule._get_dname_components)
|
||||
|
||||
def _get_dname_str(self): return dnameAsStr(self.dname)
|
||||
__swig_getmethods__["dname_str"] = _get_dname_str
|
||||
if _newclass:dname_str = _swig_property(_get_dname_str)
|
||||
dname_str = property(_get_dname_str)
|
||||
%}
|
||||
}
|
||||
|
||||
@@ -338,14 +354,11 @@ struct packed_rrset_data {
|
||||
%extend packed_rrset_data {
|
||||
%pythoncode %{
|
||||
def _get_data_rr_len(self): return RRSetData_RRLen(self)
|
||||
__swig_getmethods__["rr_len"] = _get_data_rr_len
|
||||
if _newclass:rr_len = _swig_property(_get_data_rr_len)
|
||||
rr_len = property(_get_data_rr_len)
|
||||
def _get_data_rr_ttl(self): return RRSetData_RRTTL(self)
|
||||
__swig_getmethods__["rr_ttl"] =_get_data_rr_ttl
|
||||
if _newclass:rr_len = _swig_property(_get_data_rr_ttl)
|
||||
rr_ttl = property(_get_data_rr_ttl)
|
||||
def _get_data_rr_data(self): return RRSetData_RRData(self)
|
||||
__swig_getmethods__["rr_data"] = _get_data_rr_data
|
||||
if _newclass:rr_len = _swig_property(_get_data_rr_data)
|
||||
rr_data = property(_get_data_rr_data)
|
||||
%}
|
||||
}
|
||||
|
||||
@@ -417,12 +430,166 @@ struct dns_msg {
|
||||
%extend reply_info {
|
||||
%pythoncode %{
|
||||
def _rrset_ref_get(self): return ReplyInfo_Ref(self)
|
||||
__swig_getmethods__["ref"] = _rrset_ref_get
|
||||
if _newclass:ref = _swig_property(_rrset_ref_get)
|
||||
ref = property(_rrset_ref_get)
|
||||
|
||||
def _rrset_rrsets_get(self): return ReplyInfo_RRSet(self)
|
||||
__swig_getmethods__["rrsets"] = _rrset_rrsets_get
|
||||
if _newclass:rrsets = _swig_property(_rrset_rrsets_get)
|
||||
rrsets = property(_rrset_rrsets_get)
|
||||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
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);
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
case AF_UNIX: return sizeof(struct sockaddr_un);
|
||||
#endif
|
||||
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));
|
||||
}
|
||||
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
if (ss->ss_family == AF_UNIX) {
|
||||
const struct sockaddr_un *sa = (struct sockaddr_un *)ss;
|
||||
return PyBytes_FromString(sa->sun_path);
|
||||
}
|
||||
#endif
|
||||
|
||||
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)
|
||||
family = property(_family_get)
|
||||
|
||||
def _addr_get(self): return _sockaddr_storage_addr(self)
|
||||
addr = property(_addr_get)
|
||||
|
||||
def _raw_addr_get(self): return _sockaddr_storage_raw_addr(self)
|
||||
raw_addr = property(_raw_addr_get)
|
||||
|
||||
def _port_get(self): return _sockaddr_storage_port(self)
|
||||
port = property(_port_get)
|
||||
|
||||
def _flowinfo_get(self): return _sockaddr_storage_flowinfo(self)
|
||||
flowinfo = property(_flowinfo_get)
|
||||
|
||||
def _scope_id_get(self): return _sockaddr_storage_scope_id(self)
|
||||
scope_id = property(_scope_id_get)
|
||||
%}
|
||||
}
|
||||
|
||||
@@ -438,54 +605,21 @@ 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)
|
||||
__swig_getmethods__["addr"] = _addr_get
|
||||
if _newclass:addr = _swig_property(_addr_get)
|
||||
def _addr_get(self): return _sockaddr_storage_addr(self._addr)
|
||||
addr = property(_addr_get)
|
||||
|
||||
def _port_get(self): return _comm_reply_port_get(self)
|
||||
__swig_getmethods__["port"] = _port_get
|
||||
if _newclass:port = _swig_property(_port_get)
|
||||
def _port_get(self): return _sockaddr_storage_port(self._addr)
|
||||
port = property(_port_get)
|
||||
|
||||
def _family_get(self): return _comm_reply_family_get(self)
|
||||
__swig_getmethods__["family"] = _family_get
|
||||
if _newclass:family = _swig_property(_family_get)
|
||||
def _family_get(self): return _sockaddr_storage_family(self._addr)
|
||||
family = property(_family_get)
|
||||
%}
|
||||
}
|
||||
|
||||
@@ -520,12 +654,10 @@ struct edns_option {
|
||||
%extend edns_option {
|
||||
%pythoncode %{
|
||||
def _opt_code_get(self): return _edns_option_opt_code_get(self)
|
||||
__swig_getmethods__["code"] = _opt_code_get
|
||||
if _newclass: opt_code = _swig_property(_opt_code_get)
|
||||
code = property(_opt_code_get)
|
||||
|
||||
def _opt_data_get(self): return _edns_option_opt_data_get(self)
|
||||
__swig_getmethods__["data"] = _opt_data_get
|
||||
if _newclass: opt_data = _swig_property(_opt_data_get)
|
||||
data = property(_opt_data_get)
|
||||
%}
|
||||
}
|
||||
|
||||
@@ -552,11 +684,9 @@ struct edns_data {
|
||||
%extend edns_data {
|
||||
%pythoncode %{
|
||||
def _opt_list_iter(self): return EdnsOptsListIter(self.opt_list)
|
||||
__swig_getmethods__["opt_list_iter"] = _opt_list_iter
|
||||
if _newclass:opt_list_iter = _swig_property(_opt_list_iter)
|
||||
opt_list_iter = property(_opt_list_iter)
|
||||
def _opt_list(self): return _edns_data_opt_list_get(self)
|
||||
__swig_getmethods__["opt_list"] = _opt_list
|
||||
if _newclass:opt_list = _swig_property(_opt_list)
|
||||
opt_list = property(_opt_list)
|
||||
%}
|
||||
}
|
||||
|
||||
@@ -757,34 +887,25 @@ struct module_qstate {
|
||||
_unboundmodule._ext_state_set(self, id, state)
|
||||
|
||||
def __ext_state_get(self): return ExtState(self)
|
||||
__swig_getmethods__["ext_state"] = __ext_state_get
|
||||
if _newclass:ext_state = _swig_property(__ext_state_get)#, __ext_state_set)
|
||||
ext_state = property(__ext_state_get) #, __ext_state_set
|
||||
|
||||
def _edns_opts_front_in_iter(self): return EdnsOptsListIter(self.edns_opts_front_in)
|
||||
__swig_getmethods__["edns_opts_front_in_iter"] = _edns_opts_front_in_iter
|
||||
if _newclass:edns_opts_front_in_iter = _swig_property(_edns_opts_front_in_iter)
|
||||
edns_opts_front_in_iter = property(_edns_opts_front_in_iter)
|
||||
def _edns_opts_back_out_iter(self): return EdnsOptsListIter(self.edns_opts_back_out)
|
||||
__swig_getmethods__["edns_opts_back_out_iter"] = _edns_opts_back_out_iter
|
||||
if _newclass:edns_opts_back_out_iter = _swig_property(_edns_opts_back_out_iter)
|
||||
edns_opts_back_out_iter = property(_edns_opts_back_out_iter)
|
||||
def _edns_opts_back_in_iter(self): return EdnsOptsListIter(self.edns_opts_back_in)
|
||||
__swig_getmethods__["edns_opts_back_in_iter"] = _edns_opts_back_in_iter
|
||||
if _newclass:edns_opts_back_in_iter = _swig_property(_edns_opts_back_in_iter)
|
||||
edns_opts_back_in_iter = property(_edns_opts_back_in_iter)
|
||||
def _edns_opts_front_out_iter(self): return EdnsOptsListIter(self.edns_opts_front_out)
|
||||
__swig_getmethods__["edns_opts_front_out_iter"] = _edns_opts_front_out_iter
|
||||
if _newclass:edns_opts_front_out_iter = _swig_property(_edns_opts_front_out_iter)
|
||||
edns_opts_front_out_iter = property(_edns_opts_front_out_iter)
|
||||
|
||||
def _edns_opts_front_in(self): return _edns_opts_front_in_get(self)
|
||||
__swig_getmethods__["edns_opts_front_in"] = _edns_opts_front_in
|
||||
if _newclass:edns_opts_front_in = _swig_property(_edns_opts_front_in)
|
||||
edns_opts_front_in = property(_edns_opts_front_in)
|
||||
def _edns_opts_back_out(self): return _edns_opts_back_out_get(self)
|
||||
__swig_getmethods__["edns_opts_back_out"] = _edns_opts_back_out
|
||||
if _newclass:edns_opts_back_out = _swig_property(_edns_opts_back_out)
|
||||
edns_opts_back_out = property(_edns_opts_back_out)
|
||||
def _edns_opts_back_in(self): return _edns_opts_back_in_get(self)
|
||||
__swig_getmethods__["edns_opts_back_in"] = _edns_opts_back_in
|
||||
if _newclass:edns_opts_back_in = _swig_property(_edns_opts_back_in)
|
||||
edns_opts_back_in = property(_edns_opts_back_in)
|
||||
def _edns_opts_front_out(self): return _edns_opts_front_out_get(self)
|
||||
__swig_getmethods__["edns_opts_front_out"] = _edns_opts_front_out
|
||||
if _newclass:edns_opts_front_out = _swig_property(_edns_opts_front_out)
|
||||
edns_opts_front_out = property(_edns_opts_front_out)
|
||||
%}
|
||||
}
|
||||
|
||||
@@ -954,35 +1075,28 @@ struct delegpt {
|
||||
|
||||
%extend delegpt {
|
||||
%pythoncode %{
|
||||
__swig_getmethods__["dname"] = _unboundmodule._get_dp_dname
|
||||
if _newclass:dname = _swig_property(_unboundmodule._get_dp_dname)
|
||||
dname = property(_unboundmodule._get_dp_dname)
|
||||
|
||||
__swig_getmethods__["dname_list"] = _unboundmodule._get_dp_dname_components
|
||||
if _newclass:dname_list = _swig_property(_unboundmodule._get_dp_dname_components)
|
||||
dname_list = property(_unboundmodule._get_dp_dname_components)
|
||||
|
||||
def _get_dname_str(self): return dnameAsStr(self.dname)
|
||||
__swig_getmethods__["dname_str"] = _get_dname_str
|
||||
if _newclass:dname_str = _swig_property(_get_dname_str)
|
||||
dname_str = property(_get_dname_str)
|
||||
%}
|
||||
}
|
||||
%extend delegpt_ns {
|
||||
%pythoncode %{
|
||||
__swig_getmethods__["dname"] = _unboundmodule._get_dpns_dname
|
||||
if _newclass:dname = _swig_property(_unboundmodule._get_dpns_dname)
|
||||
dname = property(_unboundmodule._get_dpns_dname)
|
||||
|
||||
__swig_getmethods__["dname_list"] = _unboundmodule._get_dpns_dname_components
|
||||
if _newclass:dname_list = _swig_property(_unboundmodule._get_dpns_dname_components)
|
||||
dname_list = property(_unboundmodule._get_dpns_dname_components)
|
||||
|
||||
def _get_dname_str(self): return dnameAsStr(self.dname)
|
||||
__swig_getmethods__["dname_str"] = _get_dname_str
|
||||
if _newclass:dname_str = _swig_property(_get_dname_str)
|
||||
dname_str = property(_get_dname_str)
|
||||
%}
|
||||
}
|
||||
%extend delegpt_addr {
|
||||
%pythoncode %{
|
||||
def _addr_get(self): return _delegpt_addr_addr_get(self)
|
||||
__swig_getmethods__["addr"] = _addr_get
|
||||
if _newclass:addr = _swig_property(_addr_get)
|
||||
addr = property(_addr_get)
|
||||
%}
|
||||
}
|
||||
|
||||
@@ -1081,7 +1195,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 +1210,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 +1496,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 +1513,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 +1568,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 +1630,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);
|
||||
|
||||
+168
-12
@@ -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 */
|
||||
@@ -117,6 +247,9 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
PyObject* py_init_arg, *res;
|
||||
PyGILState_STATE gil;
|
||||
int init_standard = 1;
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
PyObject* PyFileObject = NULL;
|
||||
#endif
|
||||
|
||||
struct pythonmod_env* pe = (struct pythonmod_env*)calloc(1, sizeof(struct pythonmod_env));
|
||||
if (!pe)
|
||||
@@ -177,7 +310,15 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
}
|
||||
|
||||
/* Check Python file load */
|
||||
if ((script_py = fopen(pe->fname, "r")) == NULL)
|
||||
/* uses python to open the file, this works on other platforms,
|
||||
* eg. Windows, to open the file in the correct mode for python */
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
PyFileObject = PyFile_FromString((char*)pe->fname, "r");
|
||||
script_py = PyFile_AsFile(PyFileObject);
|
||||
#else
|
||||
script_py = _Py_fopen(pe->fname, "r");
|
||||
#endif
|
||||
if (script_py == NULL)
|
||||
{
|
||||
log_err("pythonmod: can't open file %s for reading", pe->fname);
|
||||
PyGILState_Release(gil);
|
||||
@@ -193,14 +334,31 @@ 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;
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
Py_XDECREF(PyFileObject);
|
||||
#else
|
||||
fclose(script_py);
|
||||
#endif
|
||||
|
||||
if ((pe->func_init = PyDict_GetItemString(pe->dict, "init_standard")) == NULL)
|
||||
{
|
||||
@@ -244,7 +402,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 +432,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 +470,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 +511,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)))
|
||||
@@ -374,8 +532,7 @@ void pythonmod_clear(struct module_qstate* qstate, int id)
|
||||
return;
|
||||
|
||||
pq = (struct pythonmod_qstate*)qstate->minfo[id];
|
||||
verbose(VERB_ALGO, "pythonmod: clear, id: %d, pq:%lX", id,
|
||||
(unsigned long int)pq);
|
||||
verbose(VERB_ALGO, "pythonmod: clear, id: %d, pq:%p", id, pq);
|
||||
if(pq != NULL)
|
||||
{
|
||||
PyGILState_STATE gil = PyGILState_Ensure();
|
||||
@@ -391,8 +548,7 @@ void pythonmod_clear(struct module_qstate* qstate, int id)
|
||||
size_t pythonmod_get_mem(struct module_env* env, int id)
|
||||
{
|
||||
struct pythonmod_env* pe = (struct pythonmod_env*)env->modinfo[id];
|
||||
verbose(VERB_ALGO, "pythonmod: get_mem, id: %d, pe:%lX", id,
|
||||
(unsigned long int)pe);
|
||||
verbose(VERB_ALGO, "pythonmod: get_mem, id: %d, pe:%p", id, pe);
|
||||
if(!pe)
|
||||
return 0;
|
||||
return sizeof(*pe);
|
||||
|
||||
+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 */
|
||||
|
||||
+11
-6
@@ -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)
|
||||
@@ -183,6 +183,8 @@ respip_action_cfg(struct respip_set* set, const char* ipstr,
|
||||
action = respip_inform;
|
||||
else if(strcmp(actnstr, "inform_deny") == 0)
|
||||
action = respip_inform_deny;
|
||||
else if(strcmp(actnstr, "inform_redirect") == 0)
|
||||
action = respip_inform_redirect;
|
||||
else if(strcmp(actnstr, "always_transparent") == 0)
|
||||
action = respip_always_transparent;
|
||||
else if(strcmp(actnstr, "always_refuse") == 0)
|
||||
@@ -245,7 +247,8 @@ respip_enter_rr(struct regional* region, struct resp_addr* raddr,
|
||||
struct packed_rrset_data* pd;
|
||||
struct sockaddr* sa;
|
||||
int ret;
|
||||
if(raddr->action != respip_redirect) {
|
||||
if(raddr->action != respip_redirect
|
||||
&& raddr->action != respip_inform_redirect) {
|
||||
log_err("cannot parse response-ip-data %s: response-ip "
|
||||
"action for %s is not redirect", rrstr, netblock);
|
||||
return 0;
|
||||
@@ -451,7 +454,7 @@ respip_views_apply_cfg(struct views* vs, struct config_file* cfg,
|
||||
* This function returns the copied rrset key on success, and NULL on memory
|
||||
* allocation failure.
|
||||
*/
|
||||
struct ub_packed_rrset_key*
|
||||
static struct ub_packed_rrset_key*
|
||||
copy_rrset(const struct ub_packed_rrset_key* key, struct regional* region)
|
||||
{
|
||||
struct ub_packed_rrset_key* ck = regional_alloc(region,
|
||||
@@ -611,8 +614,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))
|
||||
@@ -749,7 +753,8 @@ respip_nodata_answer(uint16_t qtype, enum respip_action action,
|
||||
*new_repp = new_rep;
|
||||
return 1;
|
||||
} else if(action == respip_static || action == respip_redirect ||
|
||||
action == respip_always_nxdomain) {
|
||||
action == respip_always_nxdomain ||
|
||||
action == respip_inform_redirect) {
|
||||
/* Since we don't know about other types of the owner name,
|
||||
* we generally return NOERROR/NODATA unless an NXDOMAIN action
|
||||
* is explicitly specified. */
|
||||
|
||||
+419
-98
File diff suppressed because it is too large
Load Diff
+26
-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 */
|
||||
@@ -324,6 +327,8 @@ struct auth_probe {
|
||||
/** the SOA probe udp event.
|
||||
* on the workers event base. */
|
||||
struct comm_point* cp;
|
||||
/** is the cp for ip6 or ip4 */
|
||||
int cp_is_ip6;
|
||||
/** timeout for packets.
|
||||
* on the workers event base. */
|
||||
struct comm_timer* timer;
|
||||
@@ -375,6 +380,8 @@ struct auth_transfer {
|
||||
* data or add of duplicate data). Flag is cleared once the retry
|
||||
* with axfr is done. */
|
||||
int ixfr_fail;
|
||||
/** we saw an ixfr-indicating timeout, count of them */
|
||||
int ixfr_possible_timeout_count;
|
||||
/** we are doing IXFR right now */
|
||||
int on_ixfr;
|
||||
/** did we detect the current AXFR/IXFR serial number yet, 0 not yet,
|
||||
@@ -393,6 +400,9 @@ struct auth_transfer {
|
||||
/** the transfer (TCP) to the master.
|
||||
* on the workers event base. */
|
||||
struct comm_point* cp;
|
||||
/** timeout for the transfer.
|
||||
* on the workers event base. */
|
||||
struct comm_timer* timer;
|
||||
};
|
||||
|
||||
/** list of addresses */
|
||||
@@ -509,12 +519,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 +599,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);
|
||||
@@ -635,12 +652,16 @@ int auth_xfer_transfer_http_callback(struct comm_point* c, void* arg, int err,
|
||||
struct comm_reply* repinfo);
|
||||
/** xfer probe timeout callback, part of task_probe */
|
||||
void auth_xfer_probe_timer_callback(void* arg);
|
||||
/** xfer transfer timeout callback, part of task_transfer */
|
||||
void auth_xfer_transfer_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
+22
-1
@@ -40,6 +40,7 @@
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "iterator/iter_delegpt.h"
|
||||
#include "iterator/iter_utils.h"
|
||||
#include "validator/val_nsec.h"
|
||||
#include "validator/val_utils.h"
|
||||
#include "services/cache/dns.h"
|
||||
@@ -109,7 +110,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 +548,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 +603,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 +641,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 +700,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 +722,19 @@ 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;
|
||||
}
|
||||
/* set NOTIMPL for RFC 8482 */
|
||||
msg->rep->flags |= LDNS_RCODE_NOTIMPL;
|
||||
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(
|
||||
@@ -897,12 +915,15 @@ dns_cache_lookup(struct module_env* env,
|
||||
struct dns_msg* msg;
|
||||
if(FLAGS_GET_RCODE(data->flags) == LDNS_RCODE_NXDOMAIN
|
||||
&& data->security == sec_status_secure
|
||||
&& (data->an_numrrsets == 0 ||
|
||||
ntohs(data->rrsets[0]->rk.type) != LDNS_RR_TYPE_CNAME)
|
||||
&& (msg=tomsg(env, &k, data, region, now, scratch))){
|
||||
lock_rw_unlock(&e->lock);
|
||||
msg->qinfo.qname=qname;
|
||||
msg->qinfo.qname_len=qnamelen;
|
||||
/* check that DNSSEC really works out */
|
||||
msg->rep->security = sec_status_unchecked;
|
||||
iter_scrub_nxdomain(msg);
|
||||
return msg;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
|
||||
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
+69
-13
@@ -41,6 +41,8 @@
|
||||
#include "config.h"
|
||||
#include "sldns/rrdef.h"
|
||||
#include "sldns/str2wire.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/storage/lookup3.h"
|
||||
@@ -215,6 +217,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,7 +244,6 @@ 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;
|
||||
infra->domain_rates = slabhash_create(cfg->ratelimit_slabs,
|
||||
INFRA_HOST_STARTSIZE, cfg->ratelimit_size,
|
||||
@@ -241,11 +254,10 @@ infra_create(struct config_file* cfg)
|
||||
return NULL;
|
||||
}
|
||||
/* insert config data into ratelimits */
|
||||
if(!infra_ratelimit_cfg_insert(infra, cfg)) {
|
||||
if(!setup_domain_limits(infra, cfg)) {
|
||||
infra_delete(infra);
|
||||
return NULL;
|
||||
}
|
||||
name_tree_init_parents(&infra->domain_limits);
|
||||
infra_ip_ratelimit = cfg->ip_ratelimit;
|
||||
infra->client_ip_rates = slabhash_create(cfg->ip_ratelimit_slabs,
|
||||
INFRA_HOST_STARTSIZE, cfg->ip_ratelimit_size, &ip_rate_sizefunc,
|
||||
@@ -285,12 +297,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;
|
||||
}
|
||||
@@ -782,7 +810,7 @@ static struct lruhash_entry* infra_find_ratedata(struct infra_cache* infra,
|
||||
}
|
||||
|
||||
/** find data item in array for ip addresses */
|
||||
struct lruhash_entry* infra_find_ip_ratedata(struct infra_cache* infra,
|
||||
static struct lruhash_entry* infra_find_ip_ratedata(struct infra_cache* infra,
|
||||
struct comm_reply* repinfo, int wr)
|
||||
{
|
||||
struct ip_rate_key key;
|
||||
@@ -881,7 +909,8 @@ int infra_rate_max(void* data, time_t now)
|
||||
}
|
||||
|
||||
int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name,
|
||||
size_t namelen, time_t timenow)
|
||||
size_t namelen, time_t timenow, struct query_info* qinfo,
|
||||
struct comm_reply* replylist)
|
||||
{
|
||||
int lim, max;
|
||||
struct lruhash_entry* entry;
|
||||
@@ -904,9 +933,19 @@ int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name,
|
||||
lock_rw_unlock(&entry->lock);
|
||||
|
||||
if(premax < lim && max >= lim) {
|
||||
char buf[257];
|
||||
char buf[257], qnm[257], ts[12], cs[12], ip[128];
|
||||
dname_str(name, buf);
|
||||
verbose(VERB_OPS, "ratelimit exceeded %s %d", buf, lim);
|
||||
dname_str(qinfo->qname, qnm);
|
||||
sldns_wire2str_type_buf(qinfo->qtype, ts, sizeof(ts));
|
||||
sldns_wire2str_class_buf(qinfo->qclass, cs, sizeof(cs));
|
||||
ip[0]=0;
|
||||
if(replylist) {
|
||||
addr_to_str((struct sockaddr_storage *)&replylist->addr,
|
||||
replylist->addrlen, ip, sizeof(ip));
|
||||
verbose(VERB_OPS, "ratelimit exceeded %s %d query %s %s %s from %s", buf, lim, qnm, cs, ts, ip);
|
||||
} else {
|
||||
verbose(VERB_OPS, "ratelimit exceeded %s %d query %s %s %s", buf, lim, qnm, cs, ts);
|
||||
}
|
||||
}
|
||||
return (max < lim);
|
||||
}
|
||||
@@ -965,7 +1004,7 @@ infra_get_mem(struct infra_cache* infra)
|
||||
}
|
||||
|
||||
int infra_ip_ratelimit_inc(struct infra_cache* infra,
|
||||
struct comm_reply* repinfo, time_t timenow)
|
||||
struct comm_reply* repinfo, time_t timenow, struct sldns_buffer* buffer)
|
||||
{
|
||||
int max;
|
||||
struct lruhash_entry* entry;
|
||||
@@ -984,11 +1023,28 @@ int infra_ip_ratelimit_inc(struct infra_cache* infra,
|
||||
lock_rw_unlock(&entry->lock);
|
||||
|
||||
if(premax < infra_ip_ratelimit && max >= infra_ip_ratelimit) {
|
||||
char client_ip[128];
|
||||
char client_ip[128], qnm[LDNS_MAX_DOMAINLEN+1+12+12];
|
||||
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);
|
||||
qnm[0]=0;
|
||||
if(sldns_buffer_limit(buffer)>LDNS_HEADER_SIZE &&
|
||||
LDNS_QDCOUNT(sldns_buffer_begin(buffer))!=0) {
|
||||
(void)sldns_wire2str_rrquestion_buf(
|
||||
sldns_buffer_at(buffer, LDNS_HEADER_SIZE),
|
||||
sldns_buffer_limit(buffer)-LDNS_HEADER_SIZE,
|
||||
qnm, sizeof(qnm));
|
||||
if(strlen(qnm)>0 && qnm[strlen(qnm)-1]=='\n')
|
||||
qnm[strlen(qnm)-1] = 0; /*remove newline*/
|
||||
if(strchr(qnm, '\t'))
|
||||
*strchr(qnm, '\t') = ' ';
|
||||
if(strchr(qnm, '\t'))
|
||||
*strchr(qnm, '\t') = ' ';
|
||||
verbose(VERB_OPS, "ip_ratelimit exceeded %s %d %s",
|
||||
client_ip, infra_ip_ratelimit, qnm);
|
||||
} else {
|
||||
verbose(VERB_OPS, "ip_ratelimit exceeded %s %d (no query name)",
|
||||
client_ip, infra_ip_ratelimit);
|
||||
}
|
||||
}
|
||||
return (max <= infra_ip_ratelimit);
|
||||
}
|
||||
|
||||
Vendored
+7
-2
@@ -366,12 +366,15 @@ long long infra_get_host_rto(struct infra_cache* infra,
|
||||
* @param name: zone name
|
||||
* @param namelen: zone name length
|
||||
* @param timenow: what time it is now.
|
||||
* @param qinfo: for logging, query name.
|
||||
* @param replylist: for logging, querier's address (if any).
|
||||
* @return 1 if it could be incremented. 0 if the increment overshot the
|
||||
* ratelimit or if in the previous second the ratelimit was exceeded.
|
||||
* Failures like alloc failures are not returned (probably as 1).
|
||||
*/
|
||||
int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name,
|
||||
size_t namelen, time_t timenow);
|
||||
size_t namelen, time_t timenow, struct query_info* qinfo,
|
||||
struct comm_reply* replylist);
|
||||
|
||||
/**
|
||||
* Decrement the query rate counter for a delegation point.
|
||||
@@ -410,10 +413,12 @@ int infra_find_ratelimit(struct infra_cache* infra, uint8_t* name,
|
||||
* @param infra: infra cache
|
||||
* @param repinfo: information about client
|
||||
* @param timenow: what time it is now.
|
||||
* @param buffer: with query for logging.
|
||||
* @return 1 if it could be incremented. 0 if the increment overshot the
|
||||
* ratelimit and the query should be dropped. */
|
||||
int infra_ip_ratelimit_inc(struct infra_cache* infra,
|
||||
struct comm_reply* repinfo, time_t timenow);
|
||||
struct comm_reply* repinfo, time_t timenow,
|
||||
struct sldns_buffer* buffer);
|
||||
|
||||
/**
|
||||
* Get memory used by the infra cache.
|
||||
|
||||
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);
|
||||
|
||||
+438
-7
@@ -53,6 +53,9 @@
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "services/mesh.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "util/locks.h"
|
||||
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
@@ -70,6 +73,18 @@
|
||||
/** number of queued TCP connections for listen() */
|
||||
#define TCP_BACKLOG 256
|
||||
|
||||
/** number of simultaneous requests a client can have */
|
||||
#define TCP_MAX_REQ_SIMULTANEOUS 32
|
||||
|
||||
#ifndef THREADS_DISABLED
|
||||
/** lock on the counter of stream buffer memory */
|
||||
static lock_basic_type stream_wait_count_lock;
|
||||
#endif
|
||||
/** size (in bytes) of stream wait buffers */
|
||||
static size_t stream_wait_count = 0;
|
||||
/** is the lock initialised for stream wait buffers */
|
||||
static int stream_wait_lock_inited = 0;
|
||||
|
||||
/**
|
||||
* Debug print of the getaddrinfo returned address.
|
||||
* @param addr: the address returned.
|
||||
@@ -247,6 +262,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 +298,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 +600,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 +613,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);
|
||||
@@ -809,9 +851,16 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
|
||||
#ifdef ENOPROTOOPT
|
||||
/* squelch ENOPROTOOPT: freebsd server mode with kernel support
|
||||
disabled, except when verbosity enabled for debugging */
|
||||
if(errno != ENOPROTOOPT || verbosity >= 3)
|
||||
if(errno != ENOPROTOOPT || verbosity >= 3) {
|
||||
#endif
|
||||
if(errno == EPERM) {
|
||||
log_warn("Setting TCP Fast Open as server failed: %s ; this could likely be because sysctl net.inet.tcp.fastopen.enabled, net.inet.tcp.fastopen.server_enable, or net.ipv4.tcp_fastopen is disabled", strerror(errno));
|
||||
} else {
|
||||
log_err("Setting TCP Fast Open as server failed: %s", strerror(errno));
|
||||
}
|
||||
#ifdef ENOPROTOOPT
|
||||
}
|
||||
#endif
|
||||
log_err("Setting TCP Fast Open as server failed: %s", strerror(errno));
|
||||
}
|
||||
#endif
|
||||
return s;
|
||||
@@ -1216,7 +1265,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*)
|
||||
@@ -1232,6 +1282,10 @@ listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
free(front);
|
||||
return NULL;
|
||||
}
|
||||
if(!stream_wait_lock_inited) {
|
||||
lock_basic_init(&stream_wait_count_lock);
|
||||
stream_wait_lock_inited = 1;
|
||||
}
|
||||
|
||||
/* create comm points as needed */
|
||||
while(ports) {
|
||||
@@ -1243,10 +1297,14 @@ 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, front->udp_buff,
|
||||
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, front->udp_buff,
|
||||
cb, cb_arg);
|
||||
cp->ssl = sslctx;
|
||||
} else if(ports->ftype == listen_type_udpancil ||
|
||||
ports->ftype == listen_type_udpancil_dnscrypt)
|
||||
@@ -1317,6 +1375,10 @@ listen_delete(struct listen_dnsport* front)
|
||||
#endif
|
||||
sldns_buffer_free(front->udp_buff);
|
||||
free(front);
|
||||
if(stream_wait_lock_inited) {
|
||||
stream_wait_lock_inited = 0;
|
||||
lock_basic_destroy(&stream_wait_count_lock);
|
||||
}
|
||||
}
|
||||
|
||||
struct listen_port*
|
||||
@@ -1474,3 +1536,372 @@ void listen_start_accept(struct listen_dnsport* listen)
|
||||
}
|
||||
}
|
||||
|
||||
struct tcp_req_info*
|
||||
tcp_req_info_create(struct sldns_buffer* spoolbuf)
|
||||
{
|
||||
struct tcp_req_info* req = (struct tcp_req_info*)malloc(sizeof(*req));
|
||||
if(!req) {
|
||||
log_err("malloc failure for new stream outoforder processing structure");
|
||||
return NULL;
|
||||
}
|
||||
memset(req, 0, sizeof(*req));
|
||||
req->spool_buffer = spoolbuf;
|
||||
return req;
|
||||
}
|
||||
|
||||
void
|
||||
tcp_req_info_delete(struct tcp_req_info* req)
|
||||
{
|
||||
if(!req) return;
|
||||
tcp_req_info_clear(req);
|
||||
/* cp is pointer back to commpoint that owns this struct and
|
||||
* called delete on us */
|
||||
/* spool_buffer is shared udp buffer, not deleted here */
|
||||
free(req);
|
||||
}
|
||||
|
||||
void tcp_req_info_clear(struct tcp_req_info* req)
|
||||
{
|
||||
struct tcp_req_open_item* open, *nopen;
|
||||
struct tcp_req_done_item* item, *nitem;
|
||||
if(!req) return;
|
||||
|
||||
/* free outstanding request mesh reply entries */
|
||||
open = req->open_req_list;
|
||||
while(open) {
|
||||
nopen = open->next;
|
||||
mesh_state_remove_reply(open->mesh, open->mesh_state, req->cp);
|
||||
free(open);
|
||||
open = nopen;
|
||||
}
|
||||
req->open_req_list = NULL;
|
||||
req->num_open_req = 0;
|
||||
|
||||
/* free pending writable result packets */
|
||||
item = req->done_req_list;
|
||||
while(item) {
|
||||
nitem = item->next;
|
||||
lock_basic_lock(&stream_wait_count_lock);
|
||||
stream_wait_count -= (sizeof(struct tcp_req_done_item)
|
||||
+item->len);
|
||||
lock_basic_unlock(&stream_wait_count_lock);
|
||||
free(item->buf);
|
||||
free(item);
|
||||
item = nitem;
|
||||
}
|
||||
req->done_req_list = NULL;
|
||||
req->num_done_req = 0;
|
||||
req->read_is_closed = 0;
|
||||
}
|
||||
|
||||
void
|
||||
tcp_req_info_remove_mesh_state(struct tcp_req_info* req, struct mesh_state* m)
|
||||
{
|
||||
struct tcp_req_open_item* open, *prev = NULL;
|
||||
if(!req || !m) return;
|
||||
open = req->open_req_list;
|
||||
while(open) {
|
||||
if(open->mesh_state == m) {
|
||||
struct tcp_req_open_item* next;
|
||||
if(prev) prev->next = open->next;
|
||||
else req->open_req_list = open->next;
|
||||
/* caller has to manage the mesh state reply entry */
|
||||
next = open->next;
|
||||
free(open);
|
||||
req->num_open_req --;
|
||||
|
||||
/* prev = prev; */
|
||||
open = next;
|
||||
continue;
|
||||
}
|
||||
prev = open;
|
||||
open = open->next;
|
||||
}
|
||||
}
|
||||
|
||||
/** setup listening for read or write */
|
||||
static void
|
||||
tcp_req_info_setup_listen(struct tcp_req_info* req)
|
||||
{
|
||||
int wr = 0;
|
||||
int rd = 0;
|
||||
|
||||
if(req->cp->tcp_byte_count != 0) {
|
||||
/* cannot change, halfway through */
|
||||
return;
|
||||
}
|
||||
|
||||
if(!req->cp->tcp_is_reading)
|
||||
wr = 1;
|
||||
if(req->num_open_req + req->num_done_req < TCP_MAX_REQ_SIMULTANEOUS &&
|
||||
!req->read_is_closed)
|
||||
rd = 1;
|
||||
|
||||
if(wr) {
|
||||
req->cp->tcp_is_reading = 0;
|
||||
comm_point_stop_listening(req->cp);
|
||||
comm_point_start_listening(req->cp, -1,
|
||||
req->cp->tcp_timeout_msec);
|
||||
} else if(rd) {
|
||||
req->cp->tcp_is_reading = 1;
|
||||
comm_point_stop_listening(req->cp);
|
||||
comm_point_start_listening(req->cp, -1,
|
||||
req->cp->tcp_timeout_msec);
|
||||
/* and also read it (from SSL stack buffers), so
|
||||
* no event read event is expected since the remainder of
|
||||
* the TLS frame is sitting in the buffers. */
|
||||
req->read_again = 1;
|
||||
} else {
|
||||
comm_point_stop_listening(req->cp);
|
||||
comm_point_start_listening(req->cp, -1,
|
||||
req->cp->tcp_timeout_msec);
|
||||
comm_point_listen_for_rw(req->cp, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/** remove first item from list of pending results */
|
||||
static struct tcp_req_done_item*
|
||||
tcp_req_info_pop_done(struct tcp_req_info* req)
|
||||
{
|
||||
struct tcp_req_done_item* item;
|
||||
log_assert(req->num_done_req > 0 && req->done_req_list);
|
||||
item = req->done_req_list;
|
||||
lock_basic_lock(&stream_wait_count_lock);
|
||||
stream_wait_count -= (sizeof(struct tcp_req_done_item)+item->len);
|
||||
lock_basic_unlock(&stream_wait_count_lock);
|
||||
req->done_req_list = req->done_req_list->next;
|
||||
req->num_done_req --;
|
||||
return item;
|
||||
}
|
||||
|
||||
/** Send given buffer and setup to write */
|
||||
static void
|
||||
tcp_req_info_start_write_buf(struct tcp_req_info* req, uint8_t* buf,
|
||||
size_t len)
|
||||
{
|
||||
sldns_buffer_clear(req->cp->buffer);
|
||||
sldns_buffer_write(req->cp->buffer, buf, len);
|
||||
sldns_buffer_flip(req->cp->buffer);
|
||||
|
||||
req->cp->tcp_is_reading = 0; /* we are now writing */
|
||||
}
|
||||
|
||||
/** pick up the next result and start writing it to the channel */
|
||||
static void
|
||||
tcp_req_pickup_next_result(struct tcp_req_info* req)
|
||||
{
|
||||
if(req->num_done_req > 0) {
|
||||
/* unlist the done item from the list of pending results */
|
||||
struct tcp_req_done_item* item = tcp_req_info_pop_done(req);
|
||||
tcp_req_info_start_write_buf(req, item->buf, item->len);
|
||||
free(item->buf);
|
||||
free(item);
|
||||
}
|
||||
}
|
||||
|
||||
/** the read channel has closed */
|
||||
int
|
||||
tcp_req_info_handle_read_close(struct tcp_req_info* req)
|
||||
{
|
||||
verbose(VERB_ALGO, "tcp channel read side closed %d", req->cp->fd);
|
||||
/* reset byte count for (potential) partial read */
|
||||
req->cp->tcp_byte_count = 0;
|
||||
/* if we still have results to write, pick up next and write it */
|
||||
if(req->num_done_req != 0) {
|
||||
tcp_req_pickup_next_result(req);
|
||||
tcp_req_info_setup_listen(req);
|
||||
return 1;
|
||||
}
|
||||
/* if nothing to do, this closes the connection */
|
||||
if(req->num_open_req == 0 && req->num_done_req == 0)
|
||||
return 0;
|
||||
/* otherwise, we must be waiting for dns resolve, wait with timeout */
|
||||
req->read_is_closed = 1;
|
||||
tcp_req_info_setup_listen(req);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
tcp_req_info_handle_writedone(struct tcp_req_info* req)
|
||||
{
|
||||
/* back to reading state, we finished this write event */
|
||||
sldns_buffer_clear(req->cp->buffer);
|
||||
if(req->num_done_req == 0 && req->read_is_closed) {
|
||||
/* no more to write and nothing to read, close it */
|
||||
comm_point_drop_reply(&req->cp->repinfo);
|
||||
return;
|
||||
}
|
||||
req->cp->tcp_is_reading = 1;
|
||||
/* see if another result needs writing */
|
||||
tcp_req_pickup_next_result(req);
|
||||
|
||||
/* see if there is more to write, if not stop_listening for writing */
|
||||
/* see if new requests are allowed, if so, start_listening
|
||||
* for reading */
|
||||
tcp_req_info_setup_listen(req);
|
||||
}
|
||||
|
||||
void
|
||||
tcp_req_info_handle_readdone(struct tcp_req_info* req)
|
||||
{
|
||||
struct comm_point* c = req->cp;
|
||||
|
||||
/* we want to read up several requests, unless there are
|
||||
* pending answers */
|
||||
|
||||
req->is_drop = 0;
|
||||
req->is_reply = 0;
|
||||
req->in_worker_handle = 1;
|
||||
/* handle the current request */
|
||||
/* this calls the worker handle request routine that could give
|
||||
* a cache response, or localdata response, or drop the reply,
|
||||
* or schedule a mesh entry for later */
|
||||
fptr_ok(fptr_whitelist_comm_point(c->callback));
|
||||
if( (*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &c->repinfo) ) {
|
||||
req->in_worker_handle = 0;
|
||||
/* there is an answer, put it up. It is already in the
|
||||
* c->buffer, just send it. */
|
||||
/* since we were just reading a query, the channel is
|
||||
* clear to write to */
|
||||
send_it:
|
||||
c->tcp_is_reading = 0;
|
||||
comm_point_stop_listening(c);
|
||||
comm_point_start_listening(c, -1, c->tcp_timeout_msec);
|
||||
return;
|
||||
}
|
||||
req->in_worker_handle = 0;
|
||||
/* it should be waiting in the mesh for recursion.
|
||||
* If mesh failed to add a new entry and called commpoint_drop_reply.
|
||||
* Then the mesh state has been cleared. */
|
||||
if(req->is_drop) {
|
||||
/* the reply has been dropped, stream has been closed. */
|
||||
return;
|
||||
}
|
||||
/* If mesh failed(mallocfail) and called commpoint_send_reply with
|
||||
* something like servfail then we pick up that reply below. */
|
||||
if(req->is_reply) {
|
||||
goto send_it;
|
||||
}
|
||||
|
||||
sldns_buffer_clear(c->buffer);
|
||||
/* if pending answers, pick up an answer and start sending it */
|
||||
tcp_req_pickup_next_result(req);
|
||||
|
||||
/* if answers pending, start sending answers */
|
||||
/* read more requests if we can have more requests */
|
||||
tcp_req_info_setup_listen(req);
|
||||
}
|
||||
|
||||
int
|
||||
tcp_req_info_add_meshstate(struct tcp_req_info* req,
|
||||
struct mesh_area* mesh, struct mesh_state* m)
|
||||
{
|
||||
struct tcp_req_open_item* item;
|
||||
log_assert(req && mesh && m);
|
||||
item = (struct tcp_req_open_item*)malloc(sizeof(*item));
|
||||
if(!item) return 0;
|
||||
item->next = req->open_req_list;
|
||||
item->mesh = mesh;
|
||||
item->mesh_state = m;
|
||||
req->open_req_list = item;
|
||||
req->num_open_req++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Add a result to the result list. At the end. */
|
||||
static int
|
||||
tcp_req_info_add_result(struct tcp_req_info* req, uint8_t* buf, size_t len)
|
||||
{
|
||||
struct tcp_req_done_item* last = NULL;
|
||||
struct tcp_req_done_item* item;
|
||||
size_t space;
|
||||
|
||||
/* see if we have space */
|
||||
space = sizeof(struct tcp_req_done_item) + len;
|
||||
lock_basic_lock(&stream_wait_count_lock);
|
||||
if(stream_wait_count + space > stream_wait_max) {
|
||||
lock_basic_unlock(&stream_wait_count_lock);
|
||||
verbose(VERB_ALGO, "drop stream reply, no space left, in stream-wait-size");
|
||||
return 0;
|
||||
}
|
||||
stream_wait_count += space;
|
||||
lock_basic_unlock(&stream_wait_count_lock);
|
||||
|
||||
/* find last element */
|
||||
last = req->done_req_list;
|
||||
while(last && last->next)
|
||||
last = last->next;
|
||||
|
||||
/* create new element */
|
||||
item = (struct tcp_req_done_item*)malloc(sizeof(*item));
|
||||
if(!item) {
|
||||
log_err("malloc failure, for stream result list");
|
||||
return 0;
|
||||
}
|
||||
item->next = NULL;
|
||||
item->len = len;
|
||||
item->buf = memdup(buf, len);
|
||||
if(!item->buf) {
|
||||
free(item);
|
||||
log_err("malloc failure, adding reply to stream result list");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* link in */
|
||||
if(last) last->next = item;
|
||||
else req->done_req_list = item;
|
||||
req->num_done_req++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
tcp_req_info_send_reply(struct tcp_req_info* req)
|
||||
{
|
||||
if(req->in_worker_handle) {
|
||||
/* reply from mesh is in the spool_buffer */
|
||||
/* copy now, so that the spool buffer is free for other tasks
|
||||
* before the callback is done */
|
||||
sldns_buffer_clear(req->cp->buffer);
|
||||
sldns_buffer_write(req->cp->buffer,
|
||||
sldns_buffer_begin(req->spool_buffer),
|
||||
sldns_buffer_limit(req->spool_buffer));
|
||||
sldns_buffer_flip(req->cp->buffer);
|
||||
req->is_reply = 1;
|
||||
return;
|
||||
}
|
||||
/* now that the query has been handled, that mesh_reply entry
|
||||
* should be removed, from the tcp_req_info list,
|
||||
* the mesh state cleanup removes then with region_cleanup and
|
||||
* replies_sent true. */
|
||||
/* see if we can send it straight away (we are not doing
|
||||
* anything else). If so, copy to buffer and start */
|
||||
if(req->cp->tcp_is_reading && req->cp->tcp_byte_count == 0) {
|
||||
/* buffer is free, and was ready to read new query into,
|
||||
* but we are now going to use it to send this answer */
|
||||
tcp_req_info_start_write_buf(req,
|
||||
sldns_buffer_begin(req->spool_buffer),
|
||||
sldns_buffer_limit(req->spool_buffer));
|
||||
/* switch to listen to write events */
|
||||
comm_point_stop_listening(req->cp);
|
||||
comm_point_start_listening(req->cp, -1,
|
||||
req->cp->tcp_timeout_msec);
|
||||
return;
|
||||
}
|
||||
/* queue up the answer behind the others already pending */
|
||||
if(!tcp_req_info_add_result(req, sldns_buffer_begin(req->spool_buffer),
|
||||
sldns_buffer_limit(req->spool_buffer))) {
|
||||
/* drop the connection, we are out of resources */
|
||||
comm_point_drop_reply(&req->cp->repinfo);
|
||||
}
|
||||
}
|
||||
|
||||
size_t tcp_req_info_get_stream_buffer_size(void)
|
||||
{
|
||||
size_t s;
|
||||
if(!stream_wait_lock_inited)
|
||||
return stream_wait_count;
|
||||
lock_basic_lock(&stream_wait_count_lock);
|
||||
s = stream_wait_count;
|
||||
lock_basic_unlock(&stream_wait_count_lock);
|
||||
return s;
|
||||
}
|
||||
|
||||
+137
-3
@@ -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
|
||||
@@ -233,4 +237,134 @@ int create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
|
||||
*/
|
||||
int create_local_accept_sock(const char* path, int* noproto, int use_systemd);
|
||||
|
||||
/**
|
||||
* TCP request info. List of requests outstanding on the channel, that
|
||||
* are asked for but not yet answered back.
|
||||
*/
|
||||
struct tcp_req_info {
|
||||
/** the TCP comm point for this. Its buffer is used for read/write */
|
||||
struct comm_point* cp;
|
||||
/** the buffer to use to spool reply from mesh into,
|
||||
* it can then be copied to the result list and written.
|
||||
* it is a pointer to the shared udp buffer. */
|
||||
struct sldns_buffer* spool_buffer;
|
||||
/** are we in worker_handle function call (for recursion callback)*/
|
||||
int in_worker_handle;
|
||||
/** is the comm point dropped (by worker handle).
|
||||
* That means we have to disconnect the channel. */
|
||||
int is_drop;
|
||||
/** is the comm point set to send_reply (by mesh new client in worker
|
||||
* handle), if so answer is available in c.buffer */
|
||||
int is_reply;
|
||||
/** read channel has closed, just write pending results */
|
||||
int read_is_closed;
|
||||
/** read again */
|
||||
int read_again;
|
||||
/** number of outstanding requests */
|
||||
int num_open_req;
|
||||
/** list of outstanding requests */
|
||||
struct tcp_req_open_item* open_req_list;
|
||||
/** number of pending writeable results */
|
||||
int num_done_req;
|
||||
/** list of pending writable result packets, malloced one at a time */
|
||||
struct tcp_req_done_item* done_req_list;
|
||||
};
|
||||
|
||||
/**
|
||||
* List of open items in TCP channel
|
||||
*/
|
||||
struct tcp_req_open_item {
|
||||
/** next in list */
|
||||
struct tcp_req_open_item* next;
|
||||
/** the mesh area of the mesh_state */
|
||||
struct mesh_area* mesh;
|
||||
/** the mesh state */
|
||||
struct mesh_state* mesh_state;
|
||||
};
|
||||
|
||||
/**
|
||||
* List of done items in TCP channel
|
||||
*/
|
||||
struct tcp_req_done_item {
|
||||
/** next in list */
|
||||
struct tcp_req_done_item* next;
|
||||
/** the buffer with packet contents */
|
||||
uint8_t* buf;
|
||||
/** length of the buffer */
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create tcp request info structure that keeps track of open
|
||||
* requests on the TCP channel that are resolved at the same time,
|
||||
* and the pending results that have to get written back to that client.
|
||||
* @param spoolbuf: shared buffer
|
||||
* @return new structure or NULL on alloc failure.
|
||||
*/
|
||||
struct tcp_req_info* tcp_req_info_create(struct sldns_buffer* spoolbuf);
|
||||
|
||||
/**
|
||||
* Delete tcp request structure. Called by owning commpoint.
|
||||
* Removes mesh entry references and stored results from the lists.
|
||||
* @param req: the tcp request info
|
||||
*/
|
||||
void tcp_req_info_delete(struct tcp_req_info* req);
|
||||
|
||||
/**
|
||||
* Clear tcp request structure. Removes list entries, sets it up ready
|
||||
* for the next connection.
|
||||
* @param req: tcp request info structure.
|
||||
*/
|
||||
void tcp_req_info_clear(struct tcp_req_info* req);
|
||||
|
||||
/**
|
||||
* Remove mesh state entry from list in tcp_req_info.
|
||||
* caller has to manage the mesh state reply entry in the mesh state.
|
||||
* @param req: the tcp req info that has the entry removed from the list.
|
||||
* @param m: the state removed from the list.
|
||||
*/
|
||||
void tcp_req_info_remove_mesh_state(struct tcp_req_info* req,
|
||||
struct mesh_state* m);
|
||||
|
||||
/**
|
||||
* Handle write done of the last result packet
|
||||
* @param req: the tcp req info.
|
||||
*/
|
||||
void tcp_req_info_handle_writedone(struct tcp_req_info* req);
|
||||
|
||||
/**
|
||||
* Handle read done of a new request from the client
|
||||
* @param req: the tcp req info.
|
||||
*/
|
||||
void tcp_req_info_handle_readdone(struct tcp_req_info* req);
|
||||
|
||||
/**
|
||||
* Add mesh state to the tcp req list of open requests.
|
||||
* So the comm_reply can be removed off the mesh reply list when
|
||||
* the tcp channel has to be closed (for other reasons then that that
|
||||
* request was done, eg. channel closed by client or some format error).
|
||||
* @param req: tcp req info structure. It keeps track of the simultaneous
|
||||
* requests and results on a tcp (or TLS) channel.
|
||||
* @param mesh: mesh area for the state.
|
||||
* @param m: mesh state to add.
|
||||
* @return 0 on failure (malloc failure).
|
||||
*/
|
||||
int tcp_req_info_add_meshstate(struct tcp_req_info* req,
|
||||
struct mesh_area* mesh, struct mesh_state* m);
|
||||
|
||||
/**
|
||||
* Send reply on tcp simultaneous answer channel. May queue it up.
|
||||
* @param req: request info structure.
|
||||
*/
|
||||
void tcp_req_info_send_reply(struct tcp_req_info* req);
|
||||
|
||||
/** the read channel has closed
|
||||
* @param req: request. remaining queries are looked up and answered.
|
||||
* @return zero if nothing to do, just close the tcp.
|
||||
*/
|
||||
int tcp_req_info_handle_read_close(struct tcp_req_info* req);
|
||||
|
||||
/** get the size of currently used tcp stream wait buffers (in bytes) */
|
||||
size_t tcp_req_info_get_stream_buffer_size(void);
|
||||
|
||||
#endif /* LISTEN_DNSPORT_H */
|
||||
|
||||
+106
-46
@@ -464,7 +464,8 @@ lz_enter_rr_into_zone(struct local_zone* z, const char* rrstr)
|
||||
return 0;
|
||||
}
|
||||
log_assert(z->dclass == rrclass);
|
||||
if(z->type == local_zone_redirect &&
|
||||
if((z->type == local_zone_redirect ||
|
||||
z->type == local_zone_inform_redirect) &&
|
||||
query_dname_compare(z->name, nm) != 0) {
|
||||
log_err("local-data in redirect zone must reside at top of zone"
|
||||
", not at %s", rrstr);
|
||||
@@ -481,7 +482,8 @@ lz_enter_rr_into_zone(struct local_zone* z, const char* rrstr)
|
||||
|
||||
/* Reject it if we would end up having CNAME and other data (including
|
||||
* another CNAME) for a redirect zone. */
|
||||
if(z->type == local_zone_redirect && node->rrsets) {
|
||||
if((z->type == local_zone_redirect ||
|
||||
z->type == local_zone_inform_redirect) && node->rrsets) {
|
||||
const char* othertype = NULL;
|
||||
if (rrtype == LDNS_RR_TYPE_CNAME)
|
||||
othertype = "other";
|
||||
@@ -1146,8 +1148,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 +1168,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 +1191,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 +1312,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)
|
||||
@@ -1322,7 +1325,8 @@ local_data_answer(struct local_zone* z, struct module_env* env,
|
||||
key.name = qinfo->qname;
|
||||
key.namelen = qinfo->qname_len;
|
||||
key.namelabs = labs;
|
||||
if(lz_type == local_zone_redirect) {
|
||||
if(lz_type == local_zone_redirect ||
|
||||
lz_type == local_zone_inform_redirect) {
|
||||
key.name = z->name;
|
||||
key.namelen = z->namelen;
|
||||
key.namelabs = z->namelabs;
|
||||
@@ -1339,7 +1343,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);
|
||||
}
|
||||
}
|
||||
@@ -1354,7 +1358,8 @@ local_data_answer(struct local_zone* z, struct module_env* env,
|
||||
return 0;
|
||||
|
||||
/* Special case for alias matching. See local_data_answer(). */
|
||||
if(lz_type == local_zone_redirect &&
|
||||
if((lz_type == local_zone_redirect ||
|
||||
lz_type == local_zone_inform_redirect) &&
|
||||
qinfo->qtype != LDNS_RR_TYPE_CNAME &&
|
||||
lr->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME)) {
|
||||
qinfo->local_alias =
|
||||
@@ -1369,34 +1374,66 @@ local_data_answer(struct local_zone* z, struct module_env* env,
|
||||
qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
|
||||
return 1;
|
||||
}
|
||||
if(lz_type == local_zone_redirect) {
|
||||
if(lz_type == local_zone_redirect ||
|
||||
lz_type == local_zone_inform_redirect) {
|
||||
/* convert rrset name to query name; like a wildcard */
|
||||
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,11 +1442,12 @@ 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 ||
|
||||
lz_type == local_zone_redirect ||
|
||||
lz_type == local_zone_inform_redirect ||
|
||||
lz_type == local_zone_always_nxdomain) {
|
||||
/* for static, reply nodata or nxdomain
|
||||
* for redirect, reply nodata */
|
||||
@@ -1418,12 +1456,13 @@ lz_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
* or using closest match for NSEC.
|
||||
* or using closest match for returning delegation downwards
|
||||
*/
|
||||
int rcode = (ld || lz_type == local_zone_redirect)?
|
||||
int rcode = (ld || lz_type == local_zone_redirect ||
|
||||
lz_type == local_zone_inform_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 +1477,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 +1498,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 +1582,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 +1589,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 +1619,35 @@ 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 ||
|
||||
lzt == local_zone_inform_redirect)
|
||||
&& 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 */
|
||||
}
|
||||
@@ -1608,6 +1665,7 @@ const char* local_zone_type2str(enum localzone_type t)
|
||||
case local_zone_nodefault: return "nodefault";
|
||||
case local_zone_inform: return "inform";
|
||||
case local_zone_inform_deny: return "inform_deny";
|
||||
case local_zone_inform_redirect: return "inform_redirect";
|
||||
case local_zone_always_transparent: return "always_transparent";
|
||||
case local_zone_always_refuse: return "always_refuse";
|
||||
case local_zone_always_nxdomain: return "always_nxdomain";
|
||||
@@ -1634,6 +1692,8 @@ int local_zone_str2type(const char* type, enum localzone_type* t)
|
||||
*t = local_zone_inform;
|
||||
else if(strcmp(type, "inform_deny") == 0)
|
||||
*t = local_zone_inform_deny;
|
||||
else if(strcmp(type, "inform_redirect") == 0)
|
||||
*t = local_zone_inform_redirect;
|
||||
else if(strcmp(type, "always_transparent") == 0)
|
||||
*t = local_zone_always_transparent;
|
||||
else if(strcmp(type, "always_refuse") == 0)
|
||||
|
||||
@@ -83,6 +83,8 @@ enum localzone_type {
|
||||
local_zone_inform,
|
||||
/** log client address, and block (drop) */
|
||||
local_zone_inform_deny,
|
||||
/** log client address, and direct */
|
||||
local_zone_inform_redirect,
|
||||
/** resolve normally, even when there is local data */
|
||||
local_zone_always_transparent,
|
||||
/** answer with error, even when there is local data */
|
||||
@@ -491,6 +493,8 @@ enum respip_action {
|
||||
respip_inform = local_zone_inform,
|
||||
/** log query source and don't answer query */
|
||||
respip_inform_deny = local_zone_inform_deny,
|
||||
/** log query source and redirect */
|
||||
respip_inform_redirect = local_zone_inform_redirect,
|
||||
/** resolve normally, even when there is response-ip data */
|
||||
respip_always_transparent = local_zone_always_transparent,
|
||||
/** answer with 'refused' response */
|
||||
|
||||
+124
-57
@@ -55,11 +55,13 @@
|
||||
#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"
|
||||
#include "util/data/dname.h"
|
||||
#include "respip/respip.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
|
||||
/** subtract timers and the values do not overflow or become negative */
|
||||
static void
|
||||
@@ -385,7 +387,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 +403,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);
|
||||
@@ -428,8 +430,9 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
/* add reply to s */
|
||||
if(!mesh_state_add_reply(s, edns, rep, qid, qflags, qinfo)) {
|
||||
log_err("mesh_new_client: out of memory; SERVFAIL");
|
||||
servfail_mem:
|
||||
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);
|
||||
@@ -438,6 +441,12 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
mesh_state_delete(&s->s);
|
||||
return;
|
||||
}
|
||||
if(rep->c->tcp_req_info) {
|
||||
if(!tcp_req_info_add_meshstate(rep->c->tcp_req_info, mesh, s)) {
|
||||
log_err("mesh_new_client: out of memory add tcpreqinfo");
|
||||
goto servfail_mem;
|
||||
}
|
||||
}
|
||||
/* update statistics */
|
||||
if(was_detached) {
|
||||
log_assert(mesh->num_detached_states > 0);
|
||||
@@ -631,8 +640,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 +702,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++) {
|
||||
@@ -730,9 +740,13 @@ mesh_state_cleanup(struct mesh_state* mstate)
|
||||
mesh = mstate->s.env->mesh;
|
||||
/* drop unsent replies */
|
||||
if(!mstate->replies_sent) {
|
||||
struct mesh_reply* rep;
|
||||
struct mesh_reply* rep = mstate->reply_list;
|
||||
struct mesh_cb* cb;
|
||||
for(rep=mstate->reply_list; rep; rep=rep->next) {
|
||||
/* in tcp_req_info, the mstates linked are removed, but
|
||||
* the reply_list is now NULL, so the remove-from-empty-list
|
||||
* takes no time and also it does not do the mesh accounting */
|
||||
mstate->reply_list = NULL;
|
||||
for(; rep; rep=rep->next) {
|
||||
comm_point_drop_reply(&rep->query_reply);
|
||||
mesh->num_reply_addrs--;
|
||||
}
|
||||
@@ -740,7 +754,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 +982,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 +992,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 +1018,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 +1026,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);
|
||||
@@ -1027,11 +1043,14 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
* @param rcode: if not 0, error code.
|
||||
* @param rep: reply to send (or NULL if rcode is set).
|
||||
* @param r: reply entry
|
||||
* @param r_buffer: buffer to use for reply entry.
|
||||
* @param prev: previous reply, already has its answer encoded in buffer.
|
||||
* @param prev_buffer: buffer for previous reply.
|
||||
*/
|
||||
static void
|
||||
mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
struct mesh_reply* r, struct mesh_reply* prev)
|
||||
struct mesh_reply* r, struct sldns_buffer* r_buffer,
|
||||
struct mesh_reply* prev, struct sldns_buffer* prev_buffer)
|
||||
{
|
||||
struct timeval end_time;
|
||||
struct timeval duration;
|
||||
@@ -1059,7 +1078,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
* and still reuse the previous answer if they are the same, but that
|
||||
* would be complicated and error prone for the relatively minor case.
|
||||
* So we err on the side of safety. */
|
||||
if(prev && prev->qflags == r->qflags &&
|
||||
if(prev && prev_buffer && prev->qflags == r->qflags &&
|
||||
!prev->local_alias && !r->local_alias &&
|
||||
prev->edns.edns_present == r->edns.edns_present &&
|
||||
prev->edns.bits == r->edns.bits &&
|
||||
@@ -1067,28 +1086,26 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
edns_opt_list_compare(prev->edns.opt_list, r->edns.opt_list)
|
||||
== 0) {
|
||||
/* if the previous reply is identical to this one, fix ID */
|
||||
if(prev->query_reply.c->buffer != r->query_reply.c->buffer)
|
||||
sldns_buffer_copy(r->query_reply.c->buffer,
|
||||
prev->query_reply.c->buffer);
|
||||
sldns_buffer_write_at(r->query_reply.c->buffer, 0,
|
||||
&r->qid, sizeof(uint16_t));
|
||||
sldns_buffer_write_at(r->query_reply.c->buffer, 12,
|
||||
r->qname, m->s.qinfo.qname_len);
|
||||
if(prev_buffer != r_buffer)
|
||||
sldns_buffer_copy(r_buffer, prev_buffer);
|
||||
sldns_buffer_write_at(r_buffer, 0, &r->qid, sizeof(uint16_t));
|
||||
sldns_buffer_write_at(r_buffer, 12, r->qname,
|
||||
m->s.qinfo.qname_len);
|
||||
comm_point_send_reply(&r->query_reply);
|
||||
} else if(rcode) {
|
||||
m->s.qinfo.qname = r->qname;
|
||||
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,
|
||||
r->qid, r->qflags, &r->edns);
|
||||
error_encode(r_buffer, rcode, &m->s.qinfo, r->qid,
|
||||
r->qflags, &r->edns);
|
||||
comm_point_send_reply(&r->query_reply);
|
||||
} else {
|
||||
size_t udp_size = r->edns.udp_size;
|
||||
@@ -1099,18 +1116,20 @@ 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))
|
||||
r->qflags, r_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,
|
||||
r->qflags, &r->edns);
|
||||
error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
|
||||
&m->s.qinfo, r->qid, r->qflags, &r->edns);
|
||||
}
|
||||
r->edns = edns_bak;
|
||||
comm_point_send_reply(&r->query_reply);
|
||||
@@ -1125,19 +1144,17 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
timeval_add(&m->s.env->mesh->replies_sum_wait, &duration);
|
||||
timehist_insert(m->s.env->mesh->histogram, &duration);
|
||||
if(m->s.env->cfg->stat_extended) {
|
||||
uint16_t rc = FLAGS_GET_RCODE(sldns_buffer_read_u16_at(r->
|
||||
query_reply.c->buffer, 2));
|
||||
uint16_t rc = FLAGS_GET_RCODE(sldns_buffer_read_u16_at(
|
||||
r_buffer, 2));
|
||||
if(secure) m->s.env->mesh->ans_secure++;
|
||||
m->s.env->mesh->ans_rcode[ rc ] ++;
|
||||
if(rc == 0 && LDNS_ANCOUNT(sldns_buffer_begin(r->
|
||||
query_reply.c->buffer)) == 0)
|
||||
if(rc == 0 && LDNS_ANCOUNT(sldns_buffer_begin(r_buffer)) == 0)
|
||||
m->s.env->mesh->ans_nodata++;
|
||||
}
|
||||
/* Log reply sent */
|
||||
if(m->s.env->cfg->log_replies) {
|
||||
log_reply_info(0, &m->s.qinfo, &r->query_reply.addr,
|
||||
r->query_reply.addrlen, duration, 0,
|
||||
r->query_reply.c->buffer);
|
||||
r->query_reply.addrlen, duration, 0, r_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1145,9 +1162,19 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
{
|
||||
struct mesh_reply* r;
|
||||
struct mesh_reply* prev = NULL;
|
||||
struct sldns_buffer* prev_buffer = NULL;
|
||||
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. */
|
||||
@@ -1164,9 +1191,19 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
if(mstate->s.is_drop)
|
||||
comm_point_drop_reply(&r->query_reply);
|
||||
else {
|
||||
struct sldns_buffer* r_buffer = r->query_reply.c->buffer;
|
||||
if(r->query_reply.c->tcp_req_info) {
|
||||
r_buffer = r->query_reply.c->tcp_req_info->spool_buffer;
|
||||
prev_buffer = NULL;
|
||||
}
|
||||
mesh_send_reply(mstate, mstate->s.return_rcode, rep,
|
||||
r, prev);
|
||||
r, r_buffer, prev, prev_buffer);
|
||||
if(r->query_reply.c->tcp_req_info) {
|
||||
tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate);
|
||||
r_buffer = NULL;
|
||||
}
|
||||
prev = r;
|
||||
prev_buffer = r_buffer;
|
||||
}
|
||||
}
|
||||
mstate->replies_sent = 1;
|
||||
@@ -1197,6 +1234,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1306,21 +1345,14 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
|
||||
log_assert(qinfo->local_alias->rrset->rk.dname ==
|
||||
sldns_buffer_at(rep->c->buffer, LDNS_HEADER_SIZE));
|
||||
|
||||
d = regional_alloc_init(s->s.region, dsrc,
|
||||
sizeof(struct packed_rrset_data)
|
||||
+ sizeof(size_t) + sizeof(uint8_t*) + sizeof(time_t));
|
||||
/* the rrset is not packed, like in the cache, but it is
|
||||
* individualy allocated with an allocator from localzone. */
|
||||
d = regional_alloc_zero(s->s.region, sizeof(*d));
|
||||
if(!d)
|
||||
return 0;
|
||||
r->local_alias->rrset->entry.data = d;
|
||||
d->rr_len = (size_t*)((uint8_t*)d +
|
||||
sizeof(struct packed_rrset_data));
|
||||
d->rr_data = (uint8_t**)&(d->rr_len[1]);
|
||||
d->rr_ttl = (time_t*)&(d->rr_data[1]);
|
||||
d->rr_len[0] = dsrc->rr_len[0];
|
||||
d->rr_ttl[0] = dsrc->rr_ttl[0];
|
||||
d->rr_data[0] = regional_alloc_init(s->s.region,
|
||||
dsrc->rr_data[0], d->rr_len[0]);
|
||||
if(!d->rr_data[0])
|
||||
if(!rrset_insert_rr(s->s.region, d, dsrc->rr_data[0],
|
||||
dsrc->rr_len[0], dsrc->rr_ttl[0], "CNAME local alias"))
|
||||
return 0;
|
||||
} else
|
||||
r->local_alias = NULL;
|
||||
@@ -1374,7 +1406,7 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
|
||||
/* module is looping. Stop it. */
|
||||
log_err("internal error: looping module (%s) stopped",
|
||||
mesh->mods.mod[mstate->s.curmod]->name);
|
||||
log_query_info(VERB_QUERY, "pass error for qstate",
|
||||
log_query_info(0, "pass error for qstate",
|
||||
&mstate->s.qinfo);
|
||||
s = module_error;
|
||||
}
|
||||
@@ -1595,3 +1627,38 @@ void mesh_list_remove(struct mesh_state* m, struct mesh_state** fp,
|
||||
m->prev->next = m->next;
|
||||
else *fp = m->next;
|
||||
}
|
||||
|
||||
void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
|
||||
struct comm_point* cp)
|
||||
{
|
||||
struct mesh_reply* n, *prev = NULL;
|
||||
n = m->reply_list;
|
||||
/* when in mesh_cleanup, it sets the reply_list to NULL, so that
|
||||
* there is no accounting twice */
|
||||
if(!n) return; /* nothing to remove, also no accounting needed */
|
||||
while(n) {
|
||||
if(n->query_reply.c == cp) {
|
||||
/* unlink it */
|
||||
if(prev) prev->next = n->next;
|
||||
else m->reply_list = n->next;
|
||||
/* delete it, but allocated in m region */
|
||||
mesh->num_reply_addrs--;
|
||||
|
||||
/* prev = prev; */
|
||||
n = n->next;
|
||||
continue;
|
||||
}
|
||||
prev = n;
|
||||
n = n->next;
|
||||
}
|
||||
/* it was not detached (because it had a reply list), could be now */
|
||||
if(!m->reply_list && !m->cb_list
|
||||
&& m->super_set.count == 0) {
|
||||
mesh->num_detached_states++;
|
||||
}
|
||||
/* if not replies any more in mstate, it is no longer a reply_state */
|
||||
if(!m->reply_list && !m->cb_list) {
|
||||
log_assert(mesh->num_reply_states > 0);
|
||||
mesh->num_reply_states--;
|
||||
}
|
||||
}
|
||||
|
||||
+16
-6
@@ -65,7 +65,7 @@ struct respip_client_info;
|
||||
* Maximum number of mesh state activations. Any more is likely an
|
||||
* infinite loop in the module. It is then terminated.
|
||||
*/
|
||||
#define MESH_MAX_ACTIVATION 3000
|
||||
#define MESH_MAX_ACTIVATION 10000
|
||||
|
||||
/**
|
||||
* Max number of references-to-references-to-references.. search size.
|
||||
@@ -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 */
|
||||
@@ -633,4 +633,14 @@ void mesh_list_insert(struct mesh_state* m, struct mesh_state** fp,
|
||||
void mesh_list_remove(struct mesh_state* m, struct mesh_state** fp,
|
||||
struct mesh_state** lp);
|
||||
|
||||
/**
|
||||
* Remove mesh reply entry from the reply entry list. Searches for
|
||||
* the comm_point pointer.
|
||||
* @param mesh: to update the counters.
|
||||
* @param m: the mesh state.
|
||||
* @param cp: the comm_point to remove from the list.
|
||||
*/
|
||||
void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
|
||||
struct comm_point* cp);
|
||||
|
||||
#endif /* SERVICES_MESH_H */
|
||||
|
||||
+8
-2
@@ -113,8 +113,14 @@ modstack_config(struct module_stack* stack, const char* module_conf)
|
||||
for(i=0; i<stack->num; i++) {
|
||||
stack->mod[i] = module_factory(&module_conf);
|
||||
if(!stack->mod[i]) {
|
||||
log_err("Unknown value for next module: '%s'",
|
||||
module_conf);
|
||||
char md[256];
|
||||
snprintf(md, sizeof(md), "%s", module_conf);
|
||||
if(strchr(md, ' ')) *(strchr(md, ' ')) = 0;
|
||||
if(strchr(md, '\t')) *(strchr(md, '\t')) = 0;
|
||||
log_err("Unknown value in module-config, module: '%s'."
|
||||
" This module is not present (not compiled in),"
|
||||
" See the list of linked modules with unbound -h",
|
||||
md);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
+151
-105
@@ -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"
|
||||
@@ -62,6 +63,9 @@
|
||||
#ifdef HAVE_OPENSSL_SSL_H
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
#ifdef HAVE_X509_VERIFY_PARAM_SET1_HOST
|
||||
#include <openssl/x509v3.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
@@ -360,10 +364,17 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
|
||||
comm_point_close(pend->c);
|
||||
return 0;
|
||||
}
|
||||
verbose(VERB_ALGO, "the query is using TLS encryption, for %s",
|
||||
(w->tls_auth_name?w->tls_auth_name:"an unauthenticated connection"));
|
||||
#ifdef USE_WINSOCK
|
||||
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,10 +384,30 @@ 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;
|
||||
}
|
||||
}
|
||||
#elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
|
||||
/* openssl 1.0.2 has this function that can be used for
|
||||
* set1_host like verification */
|
||||
if(w->tls_auth_name) {
|
||||
X509_VERIFY_PARAM* param = SSL_get0_param(pend->c->ssl);
|
||||
X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
|
||||
if(!X509_VERIFY_PARAM_set1_host(param, w->tls_auth_name, strlen(w->tls_auth_name))) {
|
||||
log_err("X509_VERIFY_PARAM_set1_host failed");
|
||||
pend->c->fd = s;
|
||||
SSL_free(pend->c->ssl);
|
||||
pend->c->ssl = NULL;
|
||||
comm_point_close(pend->c);
|
||||
return 0;
|
||||
}
|
||||
SSL_set_verify(pend->c->ssl, SSL_VERIFY_PEER, NULL);
|
||||
}
|
||||
#else
|
||||
verbose(VERB_ALGO, "the query has an auth_name, but libssl has no call to perform TLS authentication");
|
||||
#endif /* HAVE_SSL_SET1_HOST */
|
||||
}
|
||||
w->pkt = NULL;
|
||||
@@ -751,7 +782,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
|
||||
outnet->delay_tv.tv_usec = (delayclose%1000)*1000;
|
||||
}
|
||||
#endif
|
||||
if(numavailports == 0) {
|
||||
if(numavailports == 0 || num_ports == 0) {
|
||||
log_err("no outgoing ports available");
|
||||
outside_network_delete(outnet);
|
||||
return NULL;
|
||||
@@ -1036,6 +1067,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 +1291,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;
|
||||
@@ -1470,7 +1510,6 @@ serviced_delete(struct serviced_query* sq)
|
||||
/* clear up the pending query */
|
||||
if(sq->status == serviced_query_UDP_EDNS ||
|
||||
sq->status == serviced_query_UDP ||
|
||||
sq->status == serviced_query_PROBE_EDNS ||
|
||||
sq->status == serviced_query_UDP_EDNS_FRAG ||
|
||||
sq->status == serviced_query_UDP_EDNS_fallback) {
|
||||
struct pending* p = (struct pending*)sq->pending;
|
||||
@@ -1597,15 +1636,7 @@ serviced_udp_send(struct serviced_query* sq, sldns_buffer* buff)
|
||||
sq->last_rtt = rtt;
|
||||
verbose(VERB_ALGO, "EDNS lookup known=%d vs=%d", edns_lame_known, vs);
|
||||
if(sq->status == serviced_initial) {
|
||||
if(edns_lame_known == 0 && rtt > 5000 && rtt < 10001) {
|
||||
/* perform EDNS lame probe - check if server is
|
||||
* EDNS lame (EDNS queries to it are dropped) */
|
||||
verbose(VERB_ALGO, "serviced query: send probe to see "
|
||||
" if use of EDNS causes timeouts");
|
||||
/* even 700 msec may be too small */
|
||||
rtt = 1000;
|
||||
sq->status = serviced_query_PROBE_EDNS;
|
||||
} else if(vs != -1) {
|
||||
if(vs != -1) {
|
||||
sq->status = serviced_query_UDP_EDNS;
|
||||
} else {
|
||||
sq->status = serviced_query_UDP;
|
||||
@@ -1859,7 +1890,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);
|
||||
}
|
||||
}
|
||||
@@ -1882,7 +1913,7 @@ serviced_tcp_send(struct serviced_query* sq, sldns_buffer* buff)
|
||||
sq->last_sent_time = *sq->outnet->now_tv;
|
||||
if(sq->tcp_upstream || sq->ssl_upstream) {
|
||||
timeout = rtt;
|
||||
if(rtt >= 376 && rtt < TCP_AUTH_QUERY_TIMEOUT)
|
||||
if(rtt >= UNKNOWN_SERVER_NICENESS && rtt < TCP_AUTH_QUERY_TIMEOUT)
|
||||
timeout = TCP_AUTH_QUERY_TIMEOUT;
|
||||
} else {
|
||||
timeout = TCP_AUTH_QUERY_TIMEOUT;
|
||||
@@ -1937,17 +1968,10 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
struct serviced_query* sq = (struct serviced_query*)arg;
|
||||
struct outside_network* outnet = sq->outnet;
|
||||
struct timeval now = *sq->outnet->now_tv;
|
||||
int fallback_tcp = 0;
|
||||
|
||||
sq->pending = NULL; /* removed after callback */
|
||||
if(error == NETEVENT_TIMEOUT) {
|
||||
int rto = 0;
|
||||
if(sq->status == serviced_query_PROBE_EDNS) {
|
||||
/* non-EDNS probe failed; we do not know its status,
|
||||
* keep trying with EDNS, timeout may not be caused
|
||||
* by EDNS. */
|
||||
sq->status = serviced_query_UDP_EDNS;
|
||||
}
|
||||
if(sq->status == serviced_query_UDP_EDNS && sq->last_rtt < 5000) {
|
||||
/* fallback to 1480/1280 */
|
||||
sq->status = serviced_query_UDP_EDNS_FRAG;
|
||||
@@ -1975,14 +1999,8 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if(rto >= RTT_MAX_TIMEOUT) {
|
||||
fallback_tcp = 1;
|
||||
/* UDP does not work, fallback to TCP below */
|
||||
} else {
|
||||
serviced_callbacks(sq, NETEVENT_TIMEOUT, c, rep);
|
||||
return 0;
|
||||
}
|
||||
} else if(error != NETEVENT_NOERROR) {
|
||||
}
|
||||
if(error != NETEVENT_NOERROR) {
|
||||
/* udp returns error (due to no ID or interface available) */
|
||||
serviced_callbacks(sq, error, c, rep);
|
||||
return 0;
|
||||
@@ -1995,9 +2013,8 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
sq->zone, sq->zonelen, sq->qbuf, sq->qbuflen,
|
||||
&sq->last_sent_time, sq->outnet->now_tv, c->buffer);
|
||||
#endif
|
||||
if(!fallback_tcp) {
|
||||
if( (sq->status == serviced_query_UDP_EDNS
|
||||
||sq->status == serviced_query_UDP_EDNS_FRAG)
|
||||
if( (sq->status == serviced_query_UDP_EDNS
|
||||
||sq->status == serviced_query_UDP_EDNS_FRAG)
|
||||
&& (LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer))
|
||||
== LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE(
|
||||
sldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOTIMPL
|
||||
@@ -2011,19 +2028,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
serviced_callbacks(sq, NETEVENT_CLOSED, c, rep);
|
||||
}
|
||||
return 0;
|
||||
} else if(sq->status == serviced_query_PROBE_EDNS) {
|
||||
/* probe without EDNS succeeds, so we conclude that this
|
||||
* host likely has EDNS packets dropped */
|
||||
log_addr(VERB_DETAIL, "timeouts, concluded that connection to "
|
||||
"host drops EDNS packets", &sq->addr, sq->addrlen);
|
||||
/* only store noEDNS in cache if domain is noDNSSEC */
|
||||
if(!sq->want_dnssec)
|
||||
if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
sq->zone, sq->zonelen, -1, (time_t)now.tv_sec)) {
|
||||
log_err("Out of memory caching no edns for host");
|
||||
}
|
||||
sq->status = serviced_query_UDP;
|
||||
} else if(sq->status == serviced_query_UDP_EDNS &&
|
||||
} else if(sq->status == serviced_query_UDP_EDNS &&
|
||||
!sq->edns_lame_known) {
|
||||
/* now we know that edns queries received answers store that */
|
||||
log_addr(VERB_ALGO, "serviced query: EDNS works for",
|
||||
@@ -2033,7 +2038,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
log_err("Out of memory caching edns works");
|
||||
}
|
||||
sq->edns_lame_known = 1;
|
||||
} else if(sq->status == serviced_query_UDP_EDNS_fallback &&
|
||||
} else if(sq->status == serviced_query_UDP_EDNS_fallback &&
|
||||
!sq->edns_lame_known && (LDNS_RCODE_WIRE(
|
||||
sldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOERROR ||
|
||||
LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) ==
|
||||
@@ -2051,12 +2056,12 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
}
|
||||
} else {
|
||||
log_addr(VERB_ALGO, "serviced query: EDNS fails, but "
|
||||
"not stored because need DNSSEC for", &sq->addr,
|
||||
"not stored because need DNSSEC for", &sq->addr,
|
||||
sq->addrlen);
|
||||
}
|
||||
sq->status = serviced_query_UDP;
|
||||
}
|
||||
if(now.tv_sec > sq->last_sent_time.tv_sec ||
|
||||
}
|
||||
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 */
|
||||
@@ -2072,11 +2077,10 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
sq->last_rtt, (time_t)now.tv_sec))
|
||||
log_err("out of memory noting rtt.");
|
||||
}
|
||||
}
|
||||
} /* end of if_!fallback_tcp */
|
||||
}
|
||||
/* perform TC flag check and TCP fallback after updating our
|
||||
* cache entries for EDNS status and RTT times */
|
||||
if(LDNS_TC_WIRE(sldns_buffer_begin(c->buffer)) || fallback_tcp) {
|
||||
if(LDNS_TC_WIRE(sldns_buffer_begin(c->buffer))) {
|
||||
/* fallback to TCP */
|
||||
/* this discards partial UDP contents */
|
||||
if(sq->status == serviced_query_UDP_EDNS ||
|
||||
@@ -2190,39 +2194,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);
|
||||
@@ -2268,11 +2281,60 @@ outnet_comm_point_for_udp(struct outside_network* outnet,
|
||||
return cp;
|
||||
}
|
||||
|
||||
/** setup SSL for comm point */
|
||||
static int
|
||||
setup_comm_ssl(struct comm_point* cp, struct outside_network* outnet,
|
||||
int fd, char* host)
|
||||
{
|
||||
cp->ssl = outgoing_ssl_fd(outnet->sslctx, fd);
|
||||
if(!cp->ssl) {
|
||||
log_err("cannot create SSL object");
|
||||
return 0;
|
||||
}
|
||||
#ifdef USE_WINSOCK
|
||||
comm_point_tcp_win_bio_cb(cp, cp->ssl);
|
||||
#endif
|
||||
cp->ssl_shake_state = comm_ssl_shake_write;
|
||||
/* https verification */
|
||||
#ifdef HAVE_SSL_SET1_HOST
|
||||
if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
|
||||
/* because we set SSL_VERIFY_PEER, in netevent in
|
||||
* ssl_handshake, it'll check if the certificate
|
||||
* verification has succeeded */
|
||||
/* SSL_VERIFY_PEER is set on the sslctx */
|
||||
/* and the certificates to verify with are loaded into
|
||||
* it with SSL_load_verify_locations or
|
||||
* SSL_CTX_set_default_verify_paths */
|
||||
/* setting the hostname makes openssl verify the
|
||||
* host name in the x509 certificate in the
|
||||
* SSL connection*/
|
||||
if(!SSL_set1_host(cp->ssl, host)) {
|
||||
log_err("SSL_set1_host failed");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
|
||||
/* openssl 1.0.2 has this function that can be used for
|
||||
* set1_host like verification */
|
||||
if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
|
||||
X509_VERIFY_PARAM* param = SSL_get0_param(cp->ssl);
|
||||
X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
|
||||
if(!X509_VERIFY_PARAM_set1_host(param, host, strlen(host))) {
|
||||
log_err("X509_VERIFY_PARAM_set1_host failed");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)host;
|
||||
#endif /* HAVE_SSL_SET1_HOST */
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct comm_point*
|
||||
outnet_comm_point_for_tcp(struct outside_network* outnet,
|
||||
comm_point_callback_type* cb, void* cb_arg,
|
||||
struct sockaddr_storage* to_addr, socklen_t to_addrlen,
|
||||
sldns_buffer* query, int timeout)
|
||||
sldns_buffer* query, int timeout, int ssl, char* host)
|
||||
{
|
||||
struct comm_point* cp;
|
||||
int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss);
|
||||
@@ -2292,6 +2354,16 @@ outnet_comm_point_for_tcp(struct outside_network* outnet,
|
||||
}
|
||||
cp->repinfo.addrlen = to_addrlen;
|
||||
memcpy(&cp->repinfo.addr, to_addr, to_addrlen);
|
||||
|
||||
/* setup for SSL (if needed) */
|
||||
if(ssl) {
|
||||
if(!setup_comm_ssl(cp, outnet, fd, host)) {
|
||||
log_err("cannot setup XoT");
|
||||
comm_point_delete(cp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* set timeout on TCP connection */
|
||||
comm_point_start_listening(cp, fd, timeout);
|
||||
/* copy scratch buffer to cp->buffer */
|
||||
@@ -2348,36 +2420,11 @@ outnet_comm_point_for_http(struct outside_network* outnet,
|
||||
|
||||
/* setup for SSL (if needed) */
|
||||
if(ssl) {
|
||||
cp->ssl = outgoing_ssl_fd(outnet->sslctx, fd);
|
||||
if(!cp->ssl) {
|
||||
if(!setup_comm_ssl(cp, outnet, fd, host)) {
|
||||
log_err("cannot setup https");
|
||||
comm_point_delete(cp);
|
||||
return NULL;
|
||||
}
|
||||
#ifdef USE_WINSOCK
|
||||
comm_point_tcp_win_bio_cb(cp, cp->ssl);
|
||||
#endif
|
||||
cp->ssl_shake_state = comm_ssl_shake_write;
|
||||
/* https verification */
|
||||
#ifdef HAVE_SSL_SET1_HOST
|
||||
if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
|
||||
/* because we set SSL_VERIFY_PEER, in netevent in
|
||||
* ssl_handshake, it'll check if the certificate
|
||||
* verification has succeeded */
|
||||
/* SSL_VERIFY_PEER is set on the sslctx */
|
||||
/* and the certificates to verify with are loaded into
|
||||
* it with SSL_load_verify_locations or
|
||||
* SSL_CTX_set_default_verify_paths */
|
||||
/* setting the hostname makes openssl verify the
|
||||
* host name in the x509 certificate in the
|
||||
* SSL connection*/
|
||||
if(!SSL_set1_host(cp->ssl, host)) {
|
||||
log_err("SSL_set1_host failed");
|
||||
comm_point_delete(cp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_SSL_SET1_HOST */
|
||||
}
|
||||
|
||||
/* set timeout on TCP connection */
|
||||
@@ -2482,7 +2529,6 @@ serviced_get_mem(struct serviced_query* sq)
|
||||
s += sizeof(*sb);
|
||||
if(sq->status == serviced_query_UDP_EDNS ||
|
||||
sq->status == serviced_query_UDP ||
|
||||
sq->status == serviced_query_PROBE_EDNS ||
|
||||
sq->status == serviced_query_UDP_EDNS_FRAG ||
|
||||
sq->status == serviced_query_UDP_EDNS_fallback) {
|
||||
s += sizeof(struct pending);
|
||||
|
||||
@@ -359,8 +359,6 @@ struct serviced_query {
|
||||
serviced_query_TCP_EDNS,
|
||||
/** TCP without EDNS sent */
|
||||
serviced_query_TCP,
|
||||
/** probe to test EDNS lameness (EDNS is dropped) */
|
||||
serviced_query_PROBE_EDNS,
|
||||
/** probe to test noEDNS0 (EDNS gives FORMERRorNOTIMP) */
|
||||
serviced_query_UDP_EDNS_fallback,
|
||||
/** probe to test TCP noEDNS0 (EDNS gives FORMERRorNOTIMP) */
|
||||
@@ -572,12 +570,14 @@ struct comm_point* outnet_comm_point_for_udp(struct outside_network* outnet,
|
||||
* @param timeout: timeout for the TCP connection.
|
||||
* timeout in milliseconds, or -1 for no (change to the) timeout.
|
||||
* So seconds*1000.
|
||||
* @param ssl: set to true for TLS.
|
||||
* @param host: hostname for host name verification of TLS (or NULL if no TLS).
|
||||
* @return tcp_out commpoint, or NULL.
|
||||
*/
|
||||
struct comm_point* outnet_comm_point_for_tcp(struct outside_network* outnet,
|
||||
comm_point_callback_type* cb, void* cb_arg,
|
||||
struct sockaddr_storage* to_addr, socklen_t to_addrlen,
|
||||
struct sldns_buffer* query, int timeout);
|
||||
struct sldns_buffer* query, int timeout, int ssl, char* host);
|
||||
|
||||
/**
|
||||
* Create http commpoint suitable for communication to the destination.
|
||||
|
||||
+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
|
||||
|
||||
|
||||
+2
-2
@@ -1908,8 +1908,8 @@ int sldns_wire2str_edns_subnet_print(char** s, size_t* sl, uint8_t* data,
|
||||
return w;
|
||||
}
|
||||
|
||||
int sldns_wire2str_edns_keepalive_print(char** s, size_t* sl, uint8_t* data,
|
||||
size_t len)
|
||||
static int sldns_wire2str_edns_keepalive_print(char** s, size_t* sl,
|
||||
uint8_t* data, size_t len)
|
||||
{
|
||||
int w = 0;
|
||||
uint16_t timeout;
|
||||
|
||||
+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,14 +391,53 @@ 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)
|
||||
morechecks(struct config_file* cfg)
|
||||
{
|
||||
warn_hosts("stub-host", cfg->stubs);
|
||||
warn_hosts("forward-host", cfg->forwards);
|
||||
interfacechecks(cfg);
|
||||
aclchecks(cfg);
|
||||
tcpconnlimitchecks(cfg);
|
||||
|
||||
if(cfg->verbosity < 0)
|
||||
fatal_exit("verbosity value < 0");
|
||||
@@ -406,19 +463,6 @@ morechecks(struct config_file* cfg, const char* fname)
|
||||
!is_dir(cfg->chrootdir)) {
|
||||
fatal_exit("bad chroot directory");
|
||||
}
|
||||
if(cfg->chrootdir && cfg->chrootdir[0]) {
|
||||
char buf[10240];
|
||||
buf[0] = 0;
|
||||
if(fname[0] != '/') {
|
||||
if(getcwd(buf, sizeof(buf)) == NULL)
|
||||
fatal_exit("getcwd: %s", strerror(errno));
|
||||
(void)strlcat(buf, "/", sizeof(buf));
|
||||
}
|
||||
(void)strlcat(buf, fname, sizeof(buf));
|
||||
if(strncmp(buf, cfg->chrootdir, strlen(cfg->chrootdir)) != 0)
|
||||
fatal_exit("config file %s is not inside chroot %s",
|
||||
buf, cfg->chrootdir);
|
||||
}
|
||||
if(cfg->directory && cfg->directory[0]) {
|
||||
char* ad = fname_after_chroot(cfg->directory, cfg, 0);
|
||||
if(!ad) fatal_exit("out of memory");
|
||||
@@ -465,6 +509,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 +558,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 +588,8 @@ morechecks(struct config_file* cfg, const char* fname)
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
if(cfg->remote_control_enable && options_remote_is_address(cfg)) {
|
||||
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,
|
||||
@@ -620,7 +667,7 @@ checkconf(const char* cfgfile, const char* opt, int final)
|
||||
config_delete(cfg);
|
||||
return;
|
||||
}
|
||||
morechecks(cfg, cfgfile);
|
||||
morechecks(cfg);
|
||||
check_mod(cfg, iter_get_funcblock());
|
||||
check_mod(cfg, val_get_funcblock());
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
|
||||
@@ -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
|
||||
|
||||
+62
-16
@@ -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");
|
||||
@@ -239,7 +247,8 @@ static void print_uptime(struct ub_shm_stat_info* shm_stat)
|
||||
}
|
||||
|
||||
/** print memory usage */
|
||||
static void print_mem(struct ub_shm_stat_info* shm_stat)
|
||||
static void print_mem(struct ub_shm_stat_info* shm_stat,
|
||||
struct ub_stats_info* s)
|
||||
{
|
||||
PR_LL("mem.cache.rrset", shm_stat->mem.rrset);
|
||||
PR_LL("mem.cache.message", shm_stat->mem.msg);
|
||||
@@ -258,6 +267,7 @@ static void print_mem(struct ub_shm_stat_info* shm_stat)
|
||||
PR_LL("mem.cache.dnscrypt_nonce",
|
||||
shm_stat->mem.dnscrypt_nonce);
|
||||
#endif
|
||||
PR_LL("mem.streamwait", s->svr.mem_stream_wait);
|
||||
}
|
||||
|
||||
/** print histogram */
|
||||
@@ -319,6 +329,8 @@ 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.tls_resume", s->svr.qtls_resume);
|
||||
PR_UL("num.query.ipv6", s->svr.qipv6);
|
||||
|
||||
/* flags */
|
||||
@@ -371,6 +383,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 */
|
||||
@@ -386,7 +402,7 @@ static void do_stats_shm(struct config_file* cfg, struct ub_stats_info* stats,
|
||||
pr_stats("total", &stats[0]);
|
||||
print_uptime(shm_stat);
|
||||
if(cfg->stat_extended) {
|
||||
print_mem(shm_stat);
|
||||
print_mem(shm_stat, &stats[0]);
|
||||
print_hist(stats);
|
||||
print_extended(stats);
|
||||
}
|
||||
@@ -444,6 +460,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,7 +483,7 @@ setup_ctx(struct config_file* cfg)
|
||||
char* s_cert=NULL, *c_key=NULL, *c_cert=NULL;
|
||||
SSL_CTX* ctx;
|
||||
|
||||
if(!options_remote_is_address(cfg))
|
||||
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);
|
||||
@@ -467,12 +499,15 @@ setup_ctx(struct config_file* cfg)
|
||||
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_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_err("Error setting up SSL_CTX verify, server cert");
|
||||
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);
|
||||
@@ -487,7 +522,7 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen;
|
||||
int addrfamily = 0;
|
||||
int addrfamily = 0, proto = IPPROTO_TCP;
|
||||
int fd, useport = 1;
|
||||
/* use svr or the first config entry */
|
||||
if(!svr) {
|
||||
@@ -521,6 +556,7 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
|
||||
addrlen = (socklen_t)sizeof(struct sockaddr_un);
|
||||
addrfamily = AF_LOCAL;
|
||||
useport = 0;
|
||||
proto = 0;
|
||||
#endif
|
||||
} else {
|
||||
if(!ipstrtoaddr(svr, cfg->control_port, &addr, &addrlen))
|
||||
@@ -528,8 +564,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));
|
||||
@@ -613,13 +649,17 @@ remote_read(SSL* ssl, int fd, char* buf, size_t len)
|
||||
}
|
||||
buf[r] = 0;
|
||||
} else {
|
||||
ssize_t rr = read(fd, buf, len-1);
|
||||
ssize_t rr = recv(fd, buf, len-1, 0);
|
||||
if(rr <= 0) {
|
||||
if(rr == 0) {
|
||||
/* EOF */
|
||||
return 0;
|
||||
}
|
||||
fatal_exit("could not read: %s", strerror(errno));
|
||||
#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;
|
||||
}
|
||||
@@ -634,8 +674,13 @@ remote_write(SSL* ssl, int fd, const char* buf, size_t len)
|
||||
if(SSL_write(ssl, buf, (int)len) <= 0)
|
||||
ssl_err("could not SSL_write");
|
||||
} else {
|
||||
if(write(fd, buf, len) < (ssize_t)len)
|
||||
fatal_exit("could not write: %s", strerror(errno));
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -677,9 +722,10 @@ go_cmd(SSL* ssl, int fd, int quiet, int argc, char* argv[])
|
||||
if(argc == 1 && strcmp(argv[0], "load_cache") == 0) {
|
||||
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, fd, stdin, buf, sizeof(buf));
|
||||
send_eof(ssl, fd);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user