mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
Compare commits
593
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b06fed6378 | ||
|
|
95ee34bd2b | ||
|
|
5fe503c864 | ||
|
|
b25332e1f4 | ||
|
|
a6ec2c6fc7 | ||
|
|
9cb404ba5f | ||
|
|
12251022ec | ||
|
|
00a0cabf7f | ||
|
|
d6ed0e868f | ||
|
|
700ad78f10 | ||
|
|
d65accbb23 | ||
|
|
78767f2014 | ||
|
|
21af42a281 | ||
|
|
0b0ece9db0 | ||
|
|
23edc18cac | ||
|
|
7153c94bd7 | ||
|
|
4df697b4b7 | ||
|
|
7fd32916e8 | ||
|
|
3f837bc440 | ||
|
|
f0769bed93 | ||
|
|
a1bfc07105 | ||
|
|
beba72d6db | ||
|
|
a4a5bfaa2f | ||
|
|
62ea384d19 | ||
|
|
53b1e11eba | ||
|
|
7fae96eb1e | ||
|
|
d386641820 | ||
|
|
7c5e38294a | ||
|
|
1cadc5d677 | ||
|
|
7509bf208e | ||
|
|
ec34bc9af1 | ||
|
|
8d1af17449 | ||
|
|
0db1573d34 | ||
|
|
b3c45a8edb | ||
|
|
1a0bd1a150 | ||
|
|
5a726fb61f | ||
|
|
6792d2d036 | ||
|
|
d32fb26adb | ||
|
|
d4ba7731ad | ||
|
|
b9607297e9 | ||
|
|
9ed59fdf34 | ||
|
|
8bcb44a019 | ||
|
|
6b28c8ace2 | ||
|
|
55088951c0 | ||
|
|
55a0d89f0d | ||
|
|
d532c9913c | ||
|
|
261bf354b7 | ||
|
|
50b6dc4b81 | ||
|
|
ba29a4a078 | ||
|
|
676644d8e8 | ||
|
|
f64a897cbc | ||
|
|
8b209f8f68 | ||
|
|
16b6619dfa | ||
|
|
a8c8fa6bc6 | ||
|
|
6d7e5df98f | ||
|
|
1d5d95c8cb | ||
|
|
8f886fc6dd | ||
|
|
581f975b38 | ||
|
|
d2c8bcf318 | ||
|
|
ef1ed6365c | ||
|
|
82418e2bf7 | ||
|
|
6fefbb4115 | ||
|
|
85bf0bd994 | ||
|
|
913d4537f4 | ||
|
|
4e2bafafef | ||
|
|
bffb7c52d5 | ||
|
|
38c4d3d09d | ||
|
|
2951f21dab | ||
|
|
d97a635084 | ||
|
|
2c9d9fe211 | ||
|
|
583411768d | ||
|
|
a55df65bc9 | ||
|
|
d6de848e29 | ||
|
|
649a98d855 | ||
|
|
127759b160 | ||
|
|
5b29f1b3ac | ||
|
|
755177fb4c | ||
|
|
ee9c42bee5 | ||
|
|
4d06c36342 | ||
|
|
1508d3708c | ||
|
|
ea6266f736 | ||
|
|
406a9d8350 | ||
|
|
2be0263dfa | ||
|
|
deea985a20 | ||
|
|
0d18256828 | ||
|
|
abe18e41bc | ||
|
|
716282cc1a | ||
|
|
f5a59fea5d | ||
|
|
2e70e3a0d3 | ||
|
|
7ff459af13 | ||
|
|
5bee11a6d3 | ||
|
|
0b21483b17 | ||
|
|
7444b3a8bf | ||
|
|
f39e39ed47 | ||
|
|
1989c52ca0 | ||
|
|
d8df0ddef8 | ||
|
|
7f6e3852b8 | ||
|
|
23656b2b0e | ||
|
|
c16a32d2be | ||
|
|
9d28279475 | ||
|
|
913de80cbc | ||
|
|
e4c8085408 | ||
|
|
1b055c6ca7 | ||
|
|
630600e70d | ||
|
|
4809fe1b95 | ||
|
|
2d6715878d | ||
|
|
4691979679 | ||
|
|
4e5af01354 | ||
|
|
b23b39bcfd | ||
|
|
4f974e3465 | ||
|
|
85994fb61c | ||
|
|
ad9784c5e8 | ||
|
|
c239c3f395 | ||
|
|
8d22d3c13d | ||
|
|
6ef9cafc0e | ||
|
|
471ed1befe | ||
|
|
e822adf725 | ||
|
|
d91f09896d | ||
|
|
d41cdb6ce8 | ||
|
|
fbee729c5b | ||
|
|
89ad258515 | ||
|
|
0e5abca6b7 | ||
|
|
9cd2f836bd | ||
|
|
1f9caf5805 | ||
|
|
c515215eea | ||
|
|
100cc496de | ||
|
|
0a06c5bfa2 | ||
|
|
6f4451b761 | ||
|
|
55b5227431 | ||
|
|
2be98b581a | ||
|
|
4e0128f16a | ||
|
|
3d1f9ae9d3 | ||
|
|
5fabe62e70 | ||
|
|
39f6488471 | ||
|
|
170c03f7db | ||
|
|
e5c14bfd16 | ||
|
|
4a0d32ec53 | ||
|
|
9f0d521b88 | ||
|
|
78031b37fc | ||
|
|
e1e629e592 | ||
|
|
554b8b35ae | ||
|
|
874165904f | ||
|
|
1d2d33d01a | ||
|
|
59935375a3 | ||
|
|
e784758a21 | ||
|
|
f7fe1a1093 | ||
|
|
3a287a70cd | ||
|
|
d111aaf64f | ||
|
|
cc617eadc9 | ||
|
|
54e15f5ace | ||
|
|
d1a76b55bc | ||
|
|
a48abc2f8b | ||
|
|
3a7d4d7c8d | ||
|
|
5e6c2e37ca | ||
|
|
b8c60d092f | ||
|
|
b57c76ed05 | ||
|
|
8da3f91a1d | ||
|
|
fdedd3aa38 | ||
|
|
a5fbb38fe2 | ||
|
|
3b25c475f5 | ||
|
|
babe659a64 | ||
|
|
980711e658 | ||
|
|
3a69cf5c69 | ||
|
|
5c8819f1ac | ||
|
|
f6f2ab1e4a | ||
|
|
1a7540c80a | ||
|
|
5919273709 | ||
|
|
4a3a6d1294 | ||
|
|
9407439587 | ||
|
|
d754cd3de4 | ||
|
|
9f88892190 | ||
|
|
1df2544e07 | ||
|
|
0e390bca00 | ||
|
|
8de66ab4b8 | ||
|
|
8148308cff | ||
|
|
24fc3242fc | ||
|
|
cd955fa34d | ||
|
|
28e9561a94 | ||
|
|
6905e41b57 | ||
|
|
075f470778 | ||
|
|
b8c72d7cbc | ||
|
|
b89db70821 | ||
|
|
a92e9692c1 | ||
|
|
3d57bf0a3b | ||
|
|
ec21a197ac | ||
|
|
ccf1ff8f02 | ||
|
|
76eee77b08 | ||
|
|
5b7942d197 | ||
|
|
a5df3a131e | ||
|
|
a901fc5fe7 | ||
|
|
a554c14f18 | ||
|
|
da06b1c76c | ||
|
|
b32284af57 | ||
|
|
54bd1fdd62 | ||
|
|
da961fd840 | ||
|
|
8449dc1b9d | ||
|
|
0648475a66 | ||
|
|
eff62cecac | ||
|
|
e63a4cd0fd | ||
|
|
dd2ba08f7c | ||
|
|
d19f3c8c07 | ||
|
|
427836884e | ||
|
|
1ad34fe7ae | ||
|
|
77f78152ee | ||
|
|
ad89368b4e | ||
|
|
5b41e86d51 | ||
|
|
48bd83f3b4 | ||
|
|
db766ce064 | ||
|
|
75eb720ab5 | ||
|
|
88c43a1b45 | ||
|
|
0ab8edd170 | ||
|
|
10e165c574 | ||
|
|
18aed94e0c | ||
|
|
3b87862c8a | ||
|
|
6fc79a70a3 | ||
|
|
a1b7abfb9f | ||
|
|
ff6ab04ecd | ||
|
|
bf6f33ceaf | ||
|
|
324d6e7c36 | ||
|
|
7edf4a3e75 | ||
|
|
e6b770b686 | ||
|
|
172b84f7ce | ||
|
|
dfb8fb2986 | ||
|
|
b5739f66a3 | ||
|
|
862b0b568c | ||
|
|
237e796955 | ||
|
|
1931d6e9cf | ||
|
|
b02f855df8 | ||
|
|
632ea0d02e | ||
|
|
a66fd181e5 | ||
|
|
cb28d35bd2 | ||
|
|
004609b5a7 | ||
|
|
fdd1199cb1 | ||
|
|
e95a9ac466 | ||
|
|
30891d6fff | ||
|
|
8605797002 | ||
|
|
cc9a0671f3 | ||
|
|
0b5e37dcee | ||
|
|
abeb60d511 | ||
|
|
4b9df2bae1 | ||
|
|
61d431e44f | ||
|
|
6a0b5aa8e3 | ||
|
|
392be1e787 | ||
|
|
84e819dc31 | ||
|
|
c1047e6a6c | ||
|
|
ca60143bdf | ||
|
|
c834b5eecd | ||
|
|
10cd092a78 | ||
|
|
0c4a702a39 | ||
|
|
ed002df8f5 | ||
|
|
bbcea9d913 | ||
|
|
657753aac2 | ||
|
|
7de2b4e047 | ||
|
|
f6946b9412 | ||
|
|
70f3d25173 | ||
|
|
fdd1a602d5 | ||
|
|
bea3b6b72d | ||
|
|
7d5dc75dc5 | ||
|
|
2e1f4420a8 | ||
|
|
0362614f94 | ||
|
|
208d045cf5 | ||
|
|
47909a6f2d | ||
|
|
f4ff97c297 | ||
|
|
0121427ef1 | ||
|
|
a1e63e8118 | ||
|
|
b9f4ff6e9f | ||
|
|
942ced78ed | ||
|
|
9ae592209f | ||
|
|
dc2e0ec3b6 | ||
|
|
dd77a1fb9a | ||
|
|
2ef71d6def | ||
|
|
414ed74526 | ||
|
|
01eab08c1c | ||
|
|
5fd83a85e8 | ||
|
|
093131438d | ||
|
|
603b62fdb5 | ||
|
|
ec179380f4 | ||
|
|
7eddb38162 | ||
|
|
c54dfcade9 | ||
|
|
859ca7db68 | ||
|
|
df6fbb82be | ||
|
|
4b4b1eec8b | ||
|
|
d759fdd457 | ||
|
|
fa57a0fbac | ||
|
|
2a6250e3fb | ||
|
|
be26349e37 | ||
|
|
b2943670ca | ||
|
|
7e8d3423cd | ||
|
|
0df528cc9e | ||
|
|
21d1989e05 | ||
|
|
fa90bbc07a | ||
|
|
44eb7bfd25 | ||
|
|
6cb75924d9 | ||
|
|
cb98f5896f | ||
|
|
dfba6bf690 | ||
|
|
06b80629bc | ||
|
|
87edf6497d | ||
|
|
6bae276ecb | ||
|
|
b1abc813fc | ||
|
|
1264f8cff8 | ||
|
|
3b393e0e2d | ||
|
|
a7d55a5ad8 | ||
|
|
30da6bde6f | ||
|
|
d918602521 | ||
|
|
e2aef3fa43 | ||
|
|
1ed537dc52 | ||
|
|
072347e594 | ||
|
|
743ea6815b | ||
|
|
2f69cd1765 | ||
|
|
c1e91553b9 | ||
|
|
36a54a9c9d | ||
|
|
d88bb99957 | ||
|
|
6030306d9c | ||
|
|
aeeb123b1e | ||
|
|
019d363dcd | ||
|
|
038303e6a5 | ||
|
|
635c4b5b89 | ||
|
|
975a7b1fc0 | ||
|
|
52aeaf4924 | ||
|
|
6c2fa12f10 | ||
|
|
f3304d408c | ||
|
|
05e3539856 | ||
|
|
ff384cd658 | ||
|
|
62fff935da | ||
|
|
35bd34f8e6 | ||
|
|
02fdb4c879 | ||
|
|
621b1c57a3 | ||
|
|
d905317682 | ||
|
|
9e59d5eb52 | ||
|
|
10b8997cc5 | ||
|
|
d41209512e | ||
|
|
8cf7e424e2 | ||
|
|
cba64aaaa4 | ||
|
|
31b331ca67 | ||
|
|
e13088d911 | ||
|
|
d016f85110 | ||
|
|
bcadc2b45c | ||
|
|
afb2d5f105 | ||
|
|
15d892c62d | ||
|
|
eb0f3256d9 | ||
|
|
f9add77d7b | ||
|
|
4863f45f7e | ||
|
|
6f88df1fc8 | ||
|
|
aa76ed9baf | ||
|
|
bdb6a5501a | ||
|
|
7bf7524d22 | ||
|
|
b37bc47eaa | ||
|
|
c5c2cb13d4 | ||
|
|
8752326d8c | ||
|
|
52e2331dd4 | ||
|
|
5ad3bbb27f | ||
|
|
a253d276d7 | ||
|
|
effb5c4203 | ||
|
|
64f4a0d800 | ||
|
|
5ef3663385 | ||
|
|
9a727c3c1a | ||
|
|
3e1e982625 | ||
|
|
d506659635 | ||
|
|
9247e8522b | ||
|
|
ef740d0cca | ||
|
|
ac9b95ca0c | ||
|
|
bbe5c6acf0 | ||
|
|
5e4faec554 | ||
|
|
207beff489 | ||
|
|
60beab1e8d | ||
|
|
7afdc695fe | ||
|
|
3264fa8a6f | ||
|
|
55d8fe2837 | ||
|
|
3427b992f7 | ||
|
|
ee8f07a686 | ||
|
|
a37e562079 | ||
|
|
c49226613b | ||
|
|
3ede03449c | ||
|
|
60318b18f7 | ||
|
|
32a4e9bfe6 | ||
|
|
7d17a926ac | ||
|
|
ce1f757ce0 | ||
|
|
b01f0db381 | ||
|
|
0b7d3bfd30 | ||
|
|
0042a5c5fc | ||
|
|
edd22eb36c | ||
|
|
eb25148123 | ||
|
|
0fcc88689d | ||
|
|
03d62b2e43 | ||
|
|
93b07b3526 | ||
|
|
08ceb2a737 | ||
|
|
4194c613bf | ||
|
|
6a5e7be380 | ||
|
|
e583448a6d | ||
|
|
a17400b45e | ||
|
|
a1153ba1f7 | ||
|
|
425dec3037 | ||
|
|
a270aa3c53 | ||
|
|
8a6d68e5d2 | ||
|
|
79c45131d1 | ||
|
|
fe18bbcb1f | ||
|
|
7a322130d6 | ||
|
|
41e555aadf | ||
|
|
2f270e6fbb | ||
|
|
cfcf5437f4 | ||
|
|
f5a2cb3593 | ||
|
|
1624efa939 | ||
|
|
6a8a202b71 | ||
|
|
3c3f1b42bb | ||
|
|
9a44fc5142 | ||
|
|
e3cc298ffd | ||
|
|
cd46a535cd | ||
|
|
80f310e2a4 | ||
|
|
ffc2f687cf | ||
|
|
e5b8a37a20 | ||
|
|
3dc206c721 | ||
|
|
d8960d2c55 | ||
|
|
64a5e6af4a | ||
|
|
b320c7ebd5 | ||
|
|
293e94d0ed | ||
|
|
8d1e4b3648 | ||
|
|
6e23e40a2f | ||
|
|
61605c1dfa | ||
|
|
c8cdd542dd | ||
|
|
5797c77f55 | ||
|
|
ae67923bab | ||
|
|
1159e53618 | ||
|
|
3de694be05 | ||
|
|
7b18274d7e | ||
|
|
9f49585a63 | ||
|
|
de731edc0d | ||
|
|
4f9236ae55 | ||
|
|
ff6a1cee12 | ||
|
|
6d8a924889 | ||
|
|
e396684a54 | ||
|
|
8abb85e4b2 | ||
|
|
6f4b0c4fa6 | ||
|
|
cb0e3980d8 | ||
|
|
36eeb92391 | ||
|
|
b7d9b59aa9 | ||
|
|
62e88b46cc | ||
|
|
7f6827aaae | ||
|
|
abb6cfdebd | ||
|
|
feb890564b | ||
|
|
1d3e6758b2 | ||
|
|
c52c07c086 | ||
|
|
554ff98fd5 | ||
|
|
160b70f417 | ||
|
|
c8189d1018 | ||
|
|
316f594fa5 | ||
|
|
bedac6bc28 | ||
|
|
40a4688400 | ||
|
|
399b0dd686 | ||
|
|
ecfe84702b | ||
|
|
0f4fdb6669 | ||
|
|
71788cf43a | ||
|
|
5165e14802 | ||
|
|
ead37db595 | ||
|
|
522bff52fe | ||
|
|
d514a9c709 | ||
|
|
67f54eea66 | ||
|
|
1a0bb5ad5a | ||
|
|
7e8e85459c | ||
|
|
5fba7e4339 | ||
|
|
962fea87d3 | ||
|
|
08a3461810 | ||
|
|
60d4c9bd54 | ||
|
|
7a9d8f49f4 | ||
|
|
50b7b2113e | ||
|
|
0b8117df2f | ||
|
|
0393f598d5 | ||
|
|
5573d7508b | ||
|
|
542162b4e0 | ||
|
|
e7260518ea | ||
|
|
82258dff59 | ||
|
|
a2f8946764 | ||
|
|
171a7a107e | ||
|
|
6195229d76 | ||
|
|
062515d9bc | ||
|
|
311264b960 | ||
|
|
bdd2cd248d | ||
|
|
1f6a7da0b0 | ||
|
|
71d2d60b85 | ||
|
|
4e66465e22 | ||
|
|
2288777334 | ||
|
|
cf0429f3e1 | ||
|
|
dff6c5ff7a | ||
|
|
df78cb7ccb | ||
|
|
acada5a8f6 | ||
|
|
20f8dafcd4 | ||
|
|
7bb1d8a8d1 | ||
|
|
39b5f5bbc6 | ||
|
|
7ebe1fe115 | ||
|
|
843bd4156e | ||
|
|
ca8d0a0e92 | ||
|
|
5989d675ce | ||
|
|
c4869780d1 | ||
|
|
998793998d | ||
|
|
e2459be7e1 | ||
|
|
33de42e729 | ||
|
|
b3b854072b | ||
|
|
54eabdde58 | ||
|
|
6e6ff89972 | ||
|
|
0992621839 | ||
|
|
7e9d37acae | ||
|
|
bfddc0dc64 | ||
|
|
b9196d48d2 | ||
|
|
75cb40edd1 | ||
|
|
124f8d57ab | ||
|
|
f78e04a12c | ||
|
|
b93fd4e0c9 | ||
|
|
401e456a17 | ||
|
|
69828ed94b | ||
|
|
627299f5e4 | ||
|
|
e4c60435d2 | ||
|
|
486edb10db | ||
|
|
8c4e7ffb14 | ||
|
|
dd0da65da9 | ||
|
|
75395a12e5 | ||
|
|
8b2397542e | ||
|
|
6132c9f8d5 | ||
|
|
ca57014bf2 | ||
|
|
3304a4f622 | ||
|
|
6538b82928 | ||
|
|
aa1b0fca72 | ||
|
|
aa9365446b | ||
|
|
632c1e83f8 | ||
|
|
115c8f8dd5 | ||
|
|
b8f4099e55 | ||
|
|
6c899d8947 | ||
|
|
3b5b21d29f | ||
|
|
65dde0c965 | ||
|
|
eb3144bacb | ||
|
|
efd19f766f | ||
|
|
4c8fb76a72 | ||
|
|
37c1739483 | ||
|
|
71fba3d221 | ||
|
|
1a44a8402e | ||
|
|
f8000b355e | ||
|
|
1329ff5f36 | ||
|
|
658c759b3d | ||
|
|
6e0ba733f3 | ||
|
|
0b10c8da28 | ||
|
|
0d271cbb09 | ||
|
|
a40e8ae321 | ||
|
|
95544096bf | ||
|
|
58fc4b8ea8 | ||
|
|
cf2da96a28 | ||
|
|
e1b6145e5c | ||
|
|
903fe8db7e | ||
|
|
39be1377e2 | ||
|
|
de4c7bd317 | ||
|
|
f78acf53fb | ||
|
|
92d625b648 | ||
|
|
305f6f0295 | ||
|
|
7641f23f87 | ||
|
|
491b0a26e4 | ||
|
|
5febdd39a1 | ||
|
|
c5cfa6c09c | ||
|
|
d0d6e34746 | ||
|
|
1db056b19c | ||
|
|
893159454f | ||
|
|
ce54c45394 | ||
|
|
4e502fd624 | ||
|
|
ad2e157763 | ||
|
|
d42090d63b | ||
|
|
1d181f0ade | ||
|
|
93d1d33f3f | ||
|
|
9649cc8c50 | ||
|
|
cb26ca2ce7 | ||
|
|
657948dd0c | ||
|
|
7e8d548d24 | ||
|
|
4770bfbb5b | ||
|
|
3018dc636a | ||
|
|
f610f40558 | ||
|
|
eb67febcc4 | ||
|
|
3676f20923 | ||
|
|
7940e854e6 | ||
|
|
cb253fafe7 | ||
|
|
33001c8c4b | ||
|
|
a511d5d95e | ||
|
|
619b808b31 | ||
|
|
56bde1ceca | ||
|
|
7925a98141 | ||
|
|
461c8c97db | ||
|
|
593949c88e | ||
|
|
73873da0c0 | ||
|
|
dae84a96fb | ||
|
|
89c2383c71 | ||
|
|
582a7f449e | ||
|
|
8d853b7eb6 | ||
|
|
a482b5cf12 | ||
|
|
0f8b560bd5 | ||
|
|
8466ee1c62 | ||
|
|
d4e0116ba8 | ||
|
|
16f2e53d5f | ||
|
|
17dd3370fc | ||
|
|
710778dfdd |
+615
-456
File diff suppressed because it is too large
Load Diff
Vendored
+75
-7
@@ -1,6 +1,6 @@
|
||||
# generated automatically by aclocal 1.15 -*- Autoconf -*-
|
||||
# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||||
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@@ -9044,9 +9044,9 @@ m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
|
||||
m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
|
||||
m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
|
||||
|
||||
dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
||||
dnl serial 11 (pkg-config-0.29.1)
|
||||
dnl
|
||||
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
||||
# serial 11 (pkg-config-0.29.1)
|
||||
|
||||
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
||||
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
|
||||
dnl
|
||||
@@ -9320,9 +9320,77 @@ AS_VAR_COPY([$1], [pkg_cv_][$1])
|
||||
AS_VAR_IF([$1], [""], [$5], [$4])dnl
|
||||
])dnl PKG_CHECK_VAR
|
||||
|
||||
dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES,
|
||||
dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND],
|
||||
dnl [DESCRIPTION], [DEFAULT])
|
||||
dnl ------------------------------------------
|
||||
dnl
|
||||
dnl Prepare a "--with-" configure option using the lowercase
|
||||
dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and
|
||||
dnl PKG_CHECK_MODULES in a single macro.
|
||||
AC_DEFUN([PKG_WITH_MODULES],
|
||||
[
|
||||
m4_pushdef([with_arg], m4_tolower([$1]))
|
||||
|
||||
m4_pushdef([description],
|
||||
[m4_default([$5], [build with ]with_arg[ support])])
|
||||
|
||||
m4_pushdef([def_arg], [m4_default([$6], [auto])])
|
||||
m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes])
|
||||
m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no])
|
||||
|
||||
m4_case(def_arg,
|
||||
[yes],[m4_pushdef([with_without], [--without-]with_arg)],
|
||||
[m4_pushdef([with_without],[--with-]with_arg)])
|
||||
|
||||
AC_ARG_WITH(with_arg,
|
||||
AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),,
|
||||
[AS_TR_SH([with_]with_arg)=def_arg])
|
||||
|
||||
AS_CASE([$AS_TR_SH([with_]with_arg)],
|
||||
[yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)],
|
||||
[auto],[PKG_CHECK_MODULES([$1],[$2],
|
||||
[m4_n([def_action_if_found]) $3],
|
||||
[m4_n([def_action_if_not_found]) $4])])
|
||||
|
||||
m4_popdef([with_arg])
|
||||
m4_popdef([description])
|
||||
m4_popdef([def_arg])
|
||||
|
||||
])dnl PKG_WITH_MODULES
|
||||
|
||||
dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
|
||||
dnl [DESCRIPTION], [DEFAULT])
|
||||
dnl -----------------------------------------------
|
||||
dnl
|
||||
dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES
|
||||
dnl check._[VARIABLE-PREFIX] is exported as make variable.
|
||||
AC_DEFUN([PKG_HAVE_WITH_MODULES],
|
||||
[
|
||||
PKG_WITH_MODULES([$1],[$2],,,[$3],[$4])
|
||||
|
||||
AM_CONDITIONAL([HAVE_][$1],
|
||||
[test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"])
|
||||
])dnl PKG_HAVE_WITH_MODULES
|
||||
|
||||
dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
|
||||
dnl [DESCRIPTION], [DEFAULT])
|
||||
dnl ------------------------------------------------------
|
||||
dnl
|
||||
dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after
|
||||
dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make
|
||||
dnl and preprocessor variable.
|
||||
AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES],
|
||||
[
|
||||
PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4])
|
||||
|
||||
AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"],
|
||||
[AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])])
|
||||
])dnl PKG_HAVE_DEFINE_WITH_MODULES
|
||||
|
||||
# AM_CONDITIONAL -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1997-2014 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1997-2017 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@@ -9353,7 +9421,7 @@ AC_CONFIG_COMMANDS_PRE(
|
||||
Usually this means the macro was only invoked conditionally.]])
|
||||
fi])])
|
||||
|
||||
# Copyright (C) 2006-2014 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2006-2017 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
||||
+7
-3
@@ -688,8 +688,8 @@ AC_DEFUN([ACX_SSL_CHECKS], [
|
||||
# check if -lwsock32 or -lgdi32 are needed.
|
||||
BAKLIBS="$LIBS"
|
||||
BAKSSLLIBS="$LIBSSL_LIBS"
|
||||
LIBS="$LIBS -lgdi32"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32"
|
||||
LIBS="$LIBS -lgdi32 -lws2_32"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32 -lws2_32"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -lgdi32])
|
||||
AC_TRY_LINK([], [
|
||||
int HMAC_Update(void);
|
||||
@@ -839,7 +839,11 @@ dnl see if on windows
|
||||
if test "$ac_cv_header_windows_h" = "yes"; then
|
||||
AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
|
||||
USE_WINSOCK="1"
|
||||
LIBS="$LIBS -lws2_32"
|
||||
if echo $LIBS | grep 'lws2_32' >/dev/null; then
|
||||
:
|
||||
else
|
||||
LIBS="$LIBS -lws2_32"
|
||||
fi
|
||||
fi
|
||||
],
|
||||
dnl no quick getaddrinfo, try mingw32 and winsock2 library.
|
||||
|
||||
+130
-33
@@ -43,6 +43,7 @@
|
||||
#include "config.h"
|
||||
#ifdef USE_CACHEDB
|
||||
#include "cachedb/cachedb.h"
|
||||
#include "cachedb/redis.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/config_file.h"
|
||||
@@ -56,11 +57,26 @@
|
||||
#include "sldns/wire2str.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
|
||||
#define CACHEDB_HASHSIZE 256 /* bit hash */
|
||||
/* header file for htobe64 */
|
||||
#ifdef HAVE_ENDIAN_H
|
||||
# include <endian.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_ENDIAN_H
|
||||
# include <sys/endian.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIBKERN_OSBYTEORDER_H
|
||||
/* In practice this is specific to MacOS X. We assume it doesn't have
|
||||
* htobe64/be64toh but has alternatives with a different name. */
|
||||
# include <libkern/OSByteOrder.h>
|
||||
# define htobe64(x) OSSwapHostToBigInt64(x)
|
||||
# define be64toh(x) OSSwapBigToHostInt64(x)
|
||||
#endif
|
||||
|
||||
/** the unit test testframe for cachedb, its module state contains
|
||||
* a cache for a couple queries (in memory). */
|
||||
struct testframe_moddata {
|
||||
/** lock for mutex */
|
||||
lock_basic_type lock;
|
||||
/** key for single stored data element, NULL if none */
|
||||
char* stored_key;
|
||||
/** data for single stored data element, NULL if none */
|
||||
@@ -72,14 +88,18 @@ struct testframe_moddata {
|
||||
static int
|
||||
testframe_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
{
|
||||
struct testframe_moddata* d;
|
||||
(void)env;
|
||||
verbose(VERB_ALGO, "testframe_init");
|
||||
cachedb_env->backend_data = (void*)calloc(1,
|
||||
d = (struct testframe_moddata*)calloc(1,
|
||||
sizeof(struct testframe_moddata));
|
||||
cachedb_env->backend_data = (void*)d;
|
||||
if(!cachedb_env->backend_data) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
lock_basic_init(&d->lock);
|
||||
lock_protect(&d->lock, d, sizeof(*d));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -92,6 +112,7 @@ testframe_deinit(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
verbose(VERB_ALGO, "testframe_deinit");
|
||||
if(!d)
|
||||
return;
|
||||
lock_basic_destroy(&d->lock);
|
||||
free(d->stored_key);
|
||||
free(d->stored_data);
|
||||
free(d);
|
||||
@@ -105,17 +126,22 @@ testframe_lookup(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
cachedb_env->backend_data;
|
||||
(void)env;
|
||||
verbose(VERB_ALGO, "testframe_lookup of %s", key);
|
||||
lock_basic_lock(&d->lock);
|
||||
if(d->stored_key && strcmp(d->stored_key, key) == 0) {
|
||||
if(d->stored_datalen > sldns_buffer_capacity(result_buffer))
|
||||
if(d->stored_datalen > sldns_buffer_capacity(result_buffer)) {
|
||||
lock_basic_unlock(&d->lock);
|
||||
return 0; /* too large */
|
||||
}
|
||||
verbose(VERB_ALGO, "testframe_lookup found %d bytes",
|
||||
(int)d->stored_datalen);
|
||||
sldns_buffer_clear(result_buffer);
|
||||
sldns_buffer_write(result_buffer, d->stored_data,
|
||||
d->stored_datalen);
|
||||
sldns_buffer_flip(result_buffer);
|
||||
lock_basic_unlock(&d->lock);
|
||||
return 1;
|
||||
}
|
||||
lock_basic_unlock(&d->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -126,6 +152,7 @@ testframe_store(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
struct testframe_moddata* d = (struct testframe_moddata*)
|
||||
cachedb_env->backend_data;
|
||||
(void)env;
|
||||
lock_basic_lock(&d->lock);
|
||||
verbose(VERB_ALGO, "testframe_store %s (%d bytes)", key, (int)data_len);
|
||||
|
||||
/* free old data element (if any) */
|
||||
@@ -137,6 +164,7 @@ testframe_store(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
|
||||
d->stored_data = memdup(data, data_len);
|
||||
if(!d->stored_data) {
|
||||
lock_basic_unlock(&d->lock);
|
||||
log_err("out of memory");
|
||||
return;
|
||||
}
|
||||
@@ -146,8 +174,10 @@ testframe_store(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
free(d->stored_data);
|
||||
d->stored_data = NULL;
|
||||
d->stored_datalen = 0;
|
||||
lock_basic_unlock(&d->lock);
|
||||
return;
|
||||
}
|
||||
lock_basic_unlock(&d->lock);
|
||||
/* (key,data) successfully stored */
|
||||
}
|
||||
|
||||
@@ -160,6 +190,10 @@ static struct cachedb_backend testframe_backend = { "testframe",
|
||||
static struct cachedb_backend*
|
||||
cachedb_find_backend(const char* str)
|
||||
{
|
||||
#ifdef USE_REDIS
|
||||
if(strcmp(str, redis_backend.name) == 0)
|
||||
return &redis_backend;
|
||||
#endif
|
||||
if(strcmp(str, testframe_backend.name) == 0)
|
||||
return &testframe_backend;
|
||||
/* TODO add more backends here */
|
||||
@@ -170,15 +204,17 @@ cachedb_find_backend(const char* str)
|
||||
static int
|
||||
cachedb_apply_cfg(struct cachedb_env* cachedb_env, struct config_file* cfg)
|
||||
{
|
||||
const char* backend_str = "testframe"; /* TODO get from cfg */
|
||||
if(backend_str && backend_str[0]) {
|
||||
cachedb_env->backend = cachedb_find_backend(backend_str);
|
||||
if(!cachedb_env->backend) {
|
||||
log_err("cachedb: cannot find backend name '%s",
|
||||
backend_str);
|
||||
return NULL;
|
||||
}
|
||||
const char* backend_str = cfg->cachedb_backend;
|
||||
|
||||
/* If unspecified we use the in-memory test DB. */
|
||||
if(!backend_str)
|
||||
backend_str = "testframe";
|
||||
cachedb_env->backend = cachedb_find_backend(backend_str);
|
||||
if(!cachedb_env->backend) {
|
||||
log_err("cachedb: cannot find backend name '%s'", backend_str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO see if more configuration needs to be applied or not */
|
||||
return 1;
|
||||
}
|
||||
@@ -276,9 +312,10 @@ calc_hash(struct module_qstate* qstate, char* buf, size_t len)
|
||||
size_t clen = 0;
|
||||
uint8_t hash[CACHEDB_HASHSIZE/8];
|
||||
const char* hex = "0123456789ABCDEF";
|
||||
const char* secret = "default"; /* TODO: from qstate->env->cfg */
|
||||
const char* secret = qstate->env->cfg->cachedb_secret ?
|
||||
qstate->env->cfg->cachedb_secret : "default";
|
||||
size_t i;
|
||||
|
||||
|
||||
/* copy the hash info into the clear buffer */
|
||||
if(clen + qstate->qinfo.qname_len < sizeof(clear)) {
|
||||
memmove(clear+clen, qstate->qinfo.qname,
|
||||
@@ -328,6 +365,13 @@ prep_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
|
||||
if(!qstate->return_msg || !qstate->return_msg->rep)
|
||||
return 0;
|
||||
/* We don't store the reply if its TTL is 0 unless serve-expired is
|
||||
* enabled. Such a reply won't be reusable and simply be a waste for
|
||||
* the backend. It's also compatible with the default behavior of
|
||||
* dns_cache_store_msg(). */
|
||||
if(qstate->return_msg->rep->ttl == 0 &&
|
||||
!qstate->env->cfg->serve_expired)
|
||||
return 0;
|
||||
if(verbosity >= VERB_ALGO)
|
||||
log_dns_msg("cachedb encoding", &qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
@@ -368,12 +412,47 @@ good_expiry_and_qinfo(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
&expiry, sizeof(expiry));
|
||||
expiry = be64toh(expiry);
|
||||
|
||||
if((time_t)expiry < *qstate->env->now)
|
||||
if((time_t)expiry < *qstate->env->now &&
|
||||
!qstate->env->cfg->serve_expired)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Adjust the TTL of the given RRset by 'subtract'. If 'subtract' is
|
||||
* negative, set the TTL to 0. */
|
||||
static void
|
||||
packed_rrset_ttl_subtract(struct packed_rrset_data* data, time_t subtract)
|
||||
{
|
||||
size_t i;
|
||||
size_t total = data->count + data->rrsig_count;
|
||||
if(subtract >= 0 && data->ttl > subtract)
|
||||
data->ttl -= subtract;
|
||||
else data->ttl = 0;
|
||||
for(i=0; i<total; i++) {
|
||||
if(subtract >= 0 && data->rr_ttl[i] > subtract)
|
||||
data->rr_ttl[i] -= subtract;
|
||||
else data->rr_ttl[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust the TTL of a DNS message and its RRs by 'adjust'. If 'adjust' is
|
||||
* negative, set the TTLs to 0. */
|
||||
static void
|
||||
adjust_msg_ttl(struct dns_msg* msg, time_t adjust)
|
||||
{
|
||||
size_t i;
|
||||
if(adjust >= 0 && msg->rep->ttl > adjust)
|
||||
msg->rep->ttl -= adjust;
|
||||
else msg->rep->ttl = 0;
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
|
||||
for(i=0; i<msg->rep->rrset_count; i++) {
|
||||
packed_rrset_ttl_subtract((struct packed_rrset_data*)msg->
|
||||
rep->rrsets[i]->entry.data, adjust);
|
||||
}
|
||||
}
|
||||
|
||||
/** convert dns message in buffer to return_msg */
|
||||
static int
|
||||
parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
@@ -420,24 +499,34 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
|
||||
/* see how much of the TTL expired, and remove it */
|
||||
if(*qstate->env->now <= (time_t)timestamp) {
|
||||
verbose(VERB_ALGO, "cachedb msg adjust by zero");
|
||||
return 1; /* message from the future (clock skew?) */
|
||||
}
|
||||
adjust = *qstate->env->now - (time_t)timestamp;
|
||||
if(qstate->return_msg->rep->ttl < adjust) {
|
||||
verbose(VERB_ALGO, "cachedb msg expired");
|
||||
/* If serve-expired is enabled, we still use an expired message
|
||||
* setting the TTL to 0. */
|
||||
if(qstate->env->cfg->serve_expired)
|
||||
adjust = -1;
|
||||
else
|
||||
return 0; /* message expired */
|
||||
}
|
||||
verbose(VERB_ALGO, "cachedb msg adjusted down by %d", (int)adjust);
|
||||
/*adjust_msg(qstate->return_msg, adjust);*/
|
||||
/* TODO:
|
||||
msg->rep->ttl = r->ttl - adjust;
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
for(i=0; i<d->count + d->rrsig_count; i++) {
|
||||
if(d->rr_ttl[i] < adjust)
|
||||
d->rr_ttl[i] = 0;
|
||||
else d->rr_ttl[i] -= adjust;
|
||||
}
|
||||
if(d->ttl < adjust)
|
||||
d->ttl = 0;
|
||||
else d->ttl -= adjust;
|
||||
*/
|
||||
/* TODO */
|
||||
adjust_msg_ttl(qstate->return_msg, adjust);
|
||||
|
||||
return 0;
|
||||
/* Similar to the unbound worker, if serve-expired is enabled and
|
||||
* the msg would be considered to be expired, mark the state so a
|
||||
* refetch will be scheduled. The comparison between 'expiry' and
|
||||
* 'now' should be redundant given how these values were calculated,
|
||||
* but we check it just in case as does good_expiry_and_qinfo(). */
|
||||
if(qstate->env->cfg->serve_expired &&
|
||||
(adjust == -1 || (time_t)expiry < *qstate->env->now)) {
|
||||
qstate->need_refetch = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -497,14 +586,18 @@ cachedb_intcache_lookup(struct module_qstate* qstate)
|
||||
msg = dns_cache_lookup(qstate->env, qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len, qstate->qinfo.qtype,
|
||||
qstate->qinfo.qclass, qstate->query_flags,
|
||||
qstate->region, qstate->env->scratch);
|
||||
if(!msg && qstate->env->neg_cache) {
|
||||
qstate->region, qstate->env->scratch,
|
||||
1 /* no partial messages with only a CNAME */
|
||||
);
|
||||
if(!msg && qstate->env->neg_cache &&
|
||||
iter_qname_indicates_dnssec(qstate->env, &qstate->qinfo)) {
|
||||
/* lookup in negative cache; may result in
|
||||
* NOERROR/NODATA or NXDOMAIN answers that need validation */
|
||||
msg = val_neg_getmsg(qstate->env->neg_cache, &qstate->qinfo,
|
||||
qstate->region, qstate->env->rrset_cache,
|
||||
qstate->env->scratch_buffer,
|
||||
*qstate->env->now, 1/*add SOA*/, NULL);
|
||||
*qstate->env->now, 1/*add SOA*/, NULL,
|
||||
qstate->env->cfg);
|
||||
}
|
||||
if(!msg)
|
||||
return 0;
|
||||
@@ -520,11 +613,15 @@ cachedb_intcache_lookup(struct module_qstate* qstate)
|
||||
static void
|
||||
cachedb_intcache_store(struct module_qstate* qstate)
|
||||
{
|
||||
uint32_t store_flags = qstate->query_flags;
|
||||
|
||||
if(qstate->env->cfg->serve_expired)
|
||||
store_flags |= DNSCACHE_STORE_ZEROTTL;
|
||||
if(!qstate->return_msg)
|
||||
return;
|
||||
(void)dns_cache_store(qstate->env, &qstate->qinfo,
|
||||
qstate->return_msg->rep, 0, qstate->prefetch_leeway, 0,
|
||||
qstate->region, qstate->query_flags);
|
||||
qstate->region, store_flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -87,6 +87,8 @@ struct cachedb_backend {
|
||||
uint8_t*, size_t);
|
||||
};
|
||||
|
||||
#define CACHEDB_HASHSIZE 256 /* bit hash */
|
||||
|
||||
/** Init the cachedb module */
|
||||
int cachedb_init(struct module_env* env, int id);
|
||||
/** Deinit the cachedb module */
|
||||
|
||||
+283
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* cachedb/redis.c - cachedb redis module
|
||||
*
|
||||
* Copyright (c) 2018, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* 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 NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains a module that uses the redis database to cache
|
||||
* dns responses.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#ifdef USE_CACHEDB
|
||||
#include "cachedb/redis.h"
|
||||
#include "cachedb/cachedb.h"
|
||||
#include "util/alloc.h"
|
||||
#include "util/config_file.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
|
||||
#ifdef USE_REDIS
|
||||
#include "hiredis/hiredis.h"
|
||||
|
||||
struct redis_moddata {
|
||||
redisContext** ctxs; /* thread-specific redis contexts */
|
||||
int numctxs; /* number of ctx entries */
|
||||
const char* server_host; /* server's IP address or host name */
|
||||
int server_port; /* server's TCP port */
|
||||
struct timeval timeout; /* timeout for connection setup and commands */
|
||||
};
|
||||
|
||||
static redisContext*
|
||||
redis_connect(const struct redis_moddata* moddata)
|
||||
{
|
||||
redisContext* ctx;
|
||||
|
||||
ctx = redisConnectWithTimeout(moddata->server_host,
|
||||
moddata->server_port, moddata->timeout);
|
||||
if(!ctx || ctx->err) {
|
||||
const char *errstr = "out of memory";
|
||||
if(ctx)
|
||||
errstr = ctx->errstr;
|
||||
log_err("failed to connect to redis server: %s", errstr);
|
||||
goto fail;
|
||||
}
|
||||
if(redisSetTimeout(ctx, moddata->timeout) != REDIS_OK) {
|
||||
log_err("failed to set redis timeout");
|
||||
goto fail;
|
||||
}
|
||||
return ctx;
|
||||
|
||||
fail:
|
||||
if(ctx)
|
||||
redisFree(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
{
|
||||
int i;
|
||||
struct redis_moddata* moddata = NULL;
|
||||
|
||||
verbose(VERB_ALGO, "redis_init");
|
||||
|
||||
moddata = calloc(1, sizeof(struct redis_moddata));
|
||||
if(!moddata) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
moddata->numctxs = env->cfg->num_threads;
|
||||
moddata->ctxs = calloc(env->cfg->num_threads, sizeof(redisContext*));
|
||||
if(!moddata->ctxs) {
|
||||
log_err("out of memory");
|
||||
free(moddata);
|
||||
return 0;
|
||||
}
|
||||
/* note: server_host is a shallow reference to configured string.
|
||||
* we don't have to free it in this module. */
|
||||
moddata->server_host = env->cfg->redis_server_host;
|
||||
moddata->server_port = env->cfg->redis_server_port;
|
||||
moddata->timeout.tv_sec = env->cfg->redis_timeout / 1000;
|
||||
moddata->timeout.tv_usec = (env->cfg->redis_timeout % 1000) * 1000;
|
||||
for(i = 0; i < moddata->numctxs; i++)
|
||||
moddata->ctxs[i] = redis_connect(moddata);
|
||||
cachedb_env->backend_data = moddata;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
redis_deinit(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
{
|
||||
struct redis_moddata* moddata = (struct redis_moddata*)
|
||||
cachedb_env->backend_data;
|
||||
(void)env;
|
||||
|
||||
verbose(VERB_ALGO, "redis_deinit");
|
||||
|
||||
if(!moddata)
|
||||
return;
|
||||
if(moddata->ctxs) {
|
||||
int i;
|
||||
for(i = 0; i < moddata->numctxs; i++) {
|
||||
if(moddata->ctxs[i])
|
||||
redisFree(moddata->ctxs[i]);
|
||||
}
|
||||
free(moddata->ctxs);
|
||||
}
|
||||
free(moddata);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a redis command and get a reply. Unified so that it can be used for
|
||||
* both SET and GET. If 'data' is non-NULL the command is supposed to be
|
||||
* SET and GET otherwise, but the implementation of this function is agnostic
|
||||
* about the semantics (except for logging): 'command', 'data', and 'data_len'
|
||||
* are opaquely passed to redisCommand().
|
||||
* This function first checks whether a connection with a redis server has
|
||||
* been established; if not it tries to set up a new one.
|
||||
* It returns redisReply returned from redisCommand() or NULL if some low
|
||||
* level error happens. The caller is responsible to check the return value,
|
||||
* if it's non-NULL, it has to free it with freeReplyObject().
|
||||
*/
|
||||
static redisReply*
|
||||
redis_command(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
const char* command, const uint8_t* data, size_t data_len)
|
||||
{
|
||||
redisContext* ctx;
|
||||
redisReply* rep;
|
||||
struct redis_moddata* d = (struct redis_moddata*)
|
||||
cachedb_env->backend_data;
|
||||
|
||||
/* We assume env->alloc->thread_num is a unique ID for each thread
|
||||
* in [0, num-of-threads). We could treat it as an error condition
|
||||
* if the assumption didn't hold, but it seems to be a fundamental
|
||||
* assumption throughout the unbound architecture, so we simply assert
|
||||
* it. */
|
||||
log_assert(env->alloc->thread_num < d->numctxs);
|
||||
ctx = d->ctxs[env->alloc->thread_num];
|
||||
|
||||
/* If we've not established a connection to the server or we've closed
|
||||
* it on a failure, try to re-establish a new one. Failures will be
|
||||
* logged in redis_connect(). */
|
||||
if(!ctx) {
|
||||
ctx = redis_connect(d);
|
||||
d->ctxs[env->alloc->thread_num] = ctx;
|
||||
}
|
||||
if(!ctx)
|
||||
return NULL;
|
||||
|
||||
/* Send the command and get a reply, synchronously. */
|
||||
rep = (redisReply*)redisCommand(ctx, command, data, data_len);
|
||||
if(!rep) {
|
||||
/* Once an error as a NULL-reply is returned the context cannot
|
||||
* be reused and we'll need to set up a new connection. */
|
||||
log_err("redis_command: failed to receive a reply, "
|
||||
"closing connection: %s", ctx->errstr);
|
||||
redisFree(ctx);
|
||||
d->ctxs[env->alloc->thread_num] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check error in reply to unify logging in that case.
|
||||
* The caller may perform context-dependent checks and logging. */
|
||||
if(rep->type == REDIS_REPLY_ERROR)
|
||||
log_err("redis: %s resulted in an error: %s",
|
||||
data ? "set" : "get", rep->str);
|
||||
|
||||
return rep;
|
||||
}
|
||||
|
||||
static int
|
||||
redis_lookup(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
char* key, struct sldns_buffer* result_buffer)
|
||||
{
|
||||
redisReply* rep;
|
||||
char cmdbuf[4+(CACHEDB_HASHSIZE/8)*2+1]; /* "GET " + key */
|
||||
int n;
|
||||
int ret = 0;
|
||||
|
||||
verbose(VERB_ALGO, "redis_lookup of %s", key);
|
||||
|
||||
n = snprintf(cmdbuf, sizeof(cmdbuf), "GET %s", key);
|
||||
if(n < 0 || n >= (int)sizeof(cmdbuf)) {
|
||||
log_err("redis_lookup: unexpected failure to build command");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rep = redis_command(env, cachedb_env, cmdbuf, NULL, 0);
|
||||
if(!rep)
|
||||
return 0;
|
||||
switch (rep->type) {
|
||||
case REDIS_REPLY_NIL:
|
||||
verbose(VERB_ALGO, "redis_lookup: no data cached");
|
||||
break;
|
||||
case REDIS_REPLY_STRING:
|
||||
verbose(VERB_ALGO, "redis_lookup found %d bytes",
|
||||
(int)rep->len);
|
||||
if((size_t)rep->len > sldns_buffer_capacity(result_buffer)) {
|
||||
log_err("redis_lookup: replied data too long: %lu",
|
||||
(size_t)rep->len);
|
||||
break;
|
||||
}
|
||||
sldns_buffer_clear(result_buffer);
|
||||
sldns_buffer_write(result_buffer, rep->str, rep->len);
|
||||
sldns_buffer_flip(result_buffer);
|
||||
ret = 1;
|
||||
break;
|
||||
case REDIS_REPLY_ERROR:
|
||||
break; /* already logged */
|
||||
default:
|
||||
log_err("redis_lookup: unexpected type of reply for (%d)",
|
||||
rep->type);
|
||||
break;
|
||||
}
|
||||
freeReplyObject(rep);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
char* key, uint8_t* data, size_t data_len)
|
||||
{
|
||||
redisReply* rep;
|
||||
char cmdbuf[4+(CACHEDB_HASHSIZE/8)*2+3+1]; /* "SET " + key + " %b" */
|
||||
int n;
|
||||
|
||||
verbose(VERB_ALGO, "redis_store %s (%d bytes)", key, (int)data_len);
|
||||
|
||||
/* build command to set to a binary safe string */
|
||||
n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b", key);
|
||||
if(n < 0 || n >= (int)sizeof(cmdbuf)) {
|
||||
log_err("redis_store: unexpected failure to build command");
|
||||
return;
|
||||
}
|
||||
|
||||
rep = redis_command(env, cachedb_env, cmdbuf, data, data_len);
|
||||
if(rep) {
|
||||
verbose(VERB_ALGO, "redis_store set completed");
|
||||
if(rep->type != REDIS_REPLY_STATUS &&
|
||||
rep->type != REDIS_REPLY_ERROR) {
|
||||
log_err("redis_store: unexpected type of reply (%d)",
|
||||
rep->type);
|
||||
}
|
||||
freeReplyObject(rep);
|
||||
}
|
||||
}
|
||||
|
||||
struct cachedb_backend redis_backend = { "redis",
|
||||
redis_init, redis_deinit, redis_lookup, redis_store
|
||||
};
|
||||
#endif /* USE_REDIS */
|
||||
#endif /* USE_CACHEDB */
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* cachedb/redis.h - cachedb redis module
|
||||
*
|
||||
* Copyright (c) 2018, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* 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 NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains a module that uses the redis database to cache
|
||||
* dns responses.
|
||||
*/
|
||||
|
||||
/** the redis backend definition, contains callable functions
|
||||
* and name string */
|
||||
extern struct cachedb_backend redis_backend;
|
||||
@@ -33,6 +33,9 @@
|
||||
*/
|
||||
#include "config.h"
|
||||
#define LOCKRET(func) func
|
||||
#ifdef ENABLE_LOCK_CHECKS
|
||||
#undef ENABLE_LOCK_CHECKS
|
||||
#endif
|
||||
#include "util/locks.h"
|
||||
|
||||
void _ARC4_LOCK(void);
|
||||
@@ -46,6 +49,10 @@ void _ARC4_LOCK(void)
|
||||
void _ARC4_UNLOCK(void)
|
||||
{
|
||||
}
|
||||
|
||||
void _ARC4_LOCK_DESTROY(void)
|
||||
{
|
||||
}
|
||||
#else /* !THREADS_DISABLED */
|
||||
|
||||
static lock_quick_type arc4lock;
|
||||
@@ -64,4 +71,12 @@ void _ARC4_UNLOCK(void)
|
||||
{
|
||||
lock_quick_unlock(&arc4lock);
|
||||
}
|
||||
|
||||
void _ARC4_LOCK_DESTROY(void)
|
||||
{
|
||||
if(arc4lockinit) {
|
||||
arc4lockinit = 0;
|
||||
lock_quick_destroy(&arc4lock);
|
||||
}
|
||||
}
|
||||
#endif /* THREADS_DISABLED */
|
||||
|
||||
+71
-2
@@ -71,6 +71,72 @@ static struct {
|
||||
|
||||
static inline void _rs_rekey(u_char *dat, size_t datlen);
|
||||
|
||||
/*
|
||||
* Basic sanity checking; wish we could do better.
|
||||
*/
|
||||
static int
|
||||
fallback_gotdata(char *buf, size_t len)
|
||||
{
|
||||
char any_set = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
any_set |= buf[i];
|
||||
if (any_set == 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fallback for getentropy in case libc returns failure */
|
||||
static int
|
||||
fallback_getentropy_urandom(void *buf, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
int fd, flags;
|
||||
int save_errno = errno;
|
||||
|
||||
start:
|
||||
|
||||
flags = O_RDONLY;
|
||||
#ifdef O_NOFOLLOW
|
||||
flags |= O_NOFOLLOW;
|
||||
#endif
|
||||
#ifdef O_CLOEXEC
|
||||
flags |= O_CLOEXEC;
|
||||
#endif
|
||||
fd = open("/dev/urandom", flags, 0);
|
||||
if (fd == -1) {
|
||||
if (errno == EINTR)
|
||||
goto start;
|
||||
goto nodevrandom;
|
||||
}
|
||||
#ifndef O_CLOEXEC
|
||||
# ifdef HAVE_FCNTL
|
||||
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
|
||||
# endif
|
||||
#endif
|
||||
for (i = 0; i < len; ) {
|
||||
size_t wanted = len - i;
|
||||
ssize_t ret = read(fd, (char*)buf + i, wanted);
|
||||
|
||||
if (ret == -1) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
close(fd);
|
||||
goto nodevrandom;
|
||||
}
|
||||
i += ret;
|
||||
}
|
||||
close(fd);
|
||||
if (fallback_gotdata(buf, len) == 0) {
|
||||
errno = save_errno;
|
||||
return 0; /* satisfied */
|
||||
}
|
||||
nodevrandom:
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_rs_init(u_char *buf, size_t n)
|
||||
{
|
||||
@@ -114,11 +180,14 @@ _rs_stir(void)
|
||||
u_char rnd[KEYSZ + IVSZ];
|
||||
|
||||
if (getentropy(rnd, sizeof rnd) == -1) {
|
||||
if(errno != ENOSYS ||
|
||||
fallback_getentropy_urandom(rnd, sizeof rnd) == -1) {
|
||||
#ifdef SIGKILL
|
||||
raise(SIGKILL);
|
||||
raise(SIGKILL);
|
||||
#else
|
||||
exit(9); /* windows */
|
||||
exit(9); /* windows */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (!rs)
|
||||
|
||||
Vendored
+129
-225
@@ -1,8 +1,8 @@
|
||||
#! /bin/sh
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright 1992-2013 Free Software Foundation, Inc.
|
||||
# Copyright 1992-2016 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2013-06-10'
|
||||
timestamp='2016-10-02'
|
||||
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
@@ -24,12 +24,12 @@ timestamp='2013-06-10'
|
||||
# program. This Exception is an additional permission under section 7
|
||||
# of the GNU General Public License, version 3 ("GPLv3").
|
||||
#
|
||||
# Originally written by Per Bothner.
|
||||
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
|
||||
#
|
||||
# You can get the latest version of this script from:
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
|
||||
#
|
||||
# Please send patches with a ChangeLog entry to config-patches@gnu.org.
|
||||
# Please send patches to <config-patches@gnu.org>.
|
||||
|
||||
|
||||
me=`echo "$0" | sed -e 's,.*/,,'`
|
||||
@@ -50,7 +50,7 @@ version="\
|
||||
GNU config.guess ($timestamp)
|
||||
|
||||
Originally written by Per Bothner.
|
||||
Copyright 1992-2013 Free Software Foundation, Inc.
|
||||
Copyright 1992-2016 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@@ -149,7 +149,7 @@ Linux|GNU|GNU/*)
|
||||
LIBC=gnu
|
||||
#endif
|
||||
EOF
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -168,19 +168,29 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
# Note: NetBSD doesn't particularly care about the vendor
|
||||
# portion of the name. We always set it to "unknown".
|
||||
sysctl="sysctl -n hw.machine_arch"
|
||||
UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
|
||||
/usr/sbin/$sysctl 2>/dev/null || echo unknown)`
|
||||
UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
|
||||
/sbin/$sysctl 2>/dev/null || \
|
||||
/usr/sbin/$sysctl 2>/dev/null || \
|
||||
echo unknown)`
|
||||
case "${UNAME_MACHINE_ARCH}" in
|
||||
armeb) machine=armeb-unknown ;;
|
||||
arm*) machine=arm-unknown ;;
|
||||
sh3el) machine=shl-unknown ;;
|
||||
sh3eb) machine=sh-unknown ;;
|
||||
sh5el) machine=sh5le-unknown ;;
|
||||
earmv*)
|
||||
arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
|
||||
endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
|
||||
machine=${arch}${endian}-unknown
|
||||
;;
|
||||
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
|
||||
esac
|
||||
# The Operating System including object format, if it has switched
|
||||
# to ELF recently, or will in the future.
|
||||
# to ELF recently (or will in the future) and ABI.
|
||||
case "${UNAME_MACHINE_ARCH}" in
|
||||
earm*)
|
||||
os=netbsdelf
|
||||
;;
|
||||
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
|
||||
eval $set_cc_for_build
|
||||
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
@@ -197,6 +207,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
os=netbsd
|
||||
;;
|
||||
esac
|
||||
# Determine ABI tags.
|
||||
case "${UNAME_MACHINE_ARCH}" in
|
||||
earm*)
|
||||
expr='s/^earmv[0-9]/-eabi/;s/eb$//'
|
||||
abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
|
||||
;;
|
||||
esac
|
||||
# The OS release
|
||||
# Debian GNU/NetBSD machines have a different userland, and
|
||||
# thus, need a distinct triplet. However, they do not need
|
||||
@@ -207,13 +224,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
release='-gnu'
|
||||
;;
|
||||
*)
|
||||
release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
||||
release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
|
||||
;;
|
||||
esac
|
||||
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
|
||||
# contains redundant information, the shorter form:
|
||||
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
|
||||
echo "${machine}-${os}${release}"
|
||||
echo "${machine}-${os}${release}${abi}"
|
||||
exit ;;
|
||||
*:Bitrig:*:*)
|
||||
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
|
||||
@@ -223,6 +240,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
|
||||
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:LibertyBSD:*:*)
|
||||
UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
|
||||
echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:ekkoBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
|
||||
exit ;;
|
||||
@@ -235,6 +256,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
*:MirBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:Sortix:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-sortix
|
||||
exit ;;
|
||||
alpha:OSF1:*:*)
|
||||
case $UNAME_RELEASE in
|
||||
*4.0)
|
||||
@@ -251,42 +275,42 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
|
||||
case "$ALPHA_CPU_TYPE" in
|
||||
"EV4 (21064)")
|
||||
UNAME_MACHINE="alpha" ;;
|
||||
UNAME_MACHINE=alpha ;;
|
||||
"EV4.5 (21064)")
|
||||
UNAME_MACHINE="alpha" ;;
|
||||
UNAME_MACHINE=alpha ;;
|
||||
"LCA4 (21066/21068)")
|
||||
UNAME_MACHINE="alpha" ;;
|
||||
UNAME_MACHINE=alpha ;;
|
||||
"EV5 (21164)")
|
||||
UNAME_MACHINE="alphaev5" ;;
|
||||
UNAME_MACHINE=alphaev5 ;;
|
||||
"EV5.6 (21164A)")
|
||||
UNAME_MACHINE="alphaev56" ;;
|
||||
UNAME_MACHINE=alphaev56 ;;
|
||||
"EV5.6 (21164PC)")
|
||||
UNAME_MACHINE="alphapca56" ;;
|
||||
UNAME_MACHINE=alphapca56 ;;
|
||||
"EV5.7 (21164PC)")
|
||||
UNAME_MACHINE="alphapca57" ;;
|
||||
UNAME_MACHINE=alphapca57 ;;
|
||||
"EV6 (21264)")
|
||||
UNAME_MACHINE="alphaev6" ;;
|
||||
UNAME_MACHINE=alphaev6 ;;
|
||||
"EV6.7 (21264A)")
|
||||
UNAME_MACHINE="alphaev67" ;;
|
||||
UNAME_MACHINE=alphaev67 ;;
|
||||
"EV6.8CB (21264C)")
|
||||
UNAME_MACHINE="alphaev68" ;;
|
||||
UNAME_MACHINE=alphaev68 ;;
|
||||
"EV6.8AL (21264B)")
|
||||
UNAME_MACHINE="alphaev68" ;;
|
||||
UNAME_MACHINE=alphaev68 ;;
|
||||
"EV6.8CX (21264D)")
|
||||
UNAME_MACHINE="alphaev68" ;;
|
||||
UNAME_MACHINE=alphaev68 ;;
|
||||
"EV6.9A (21264/EV69A)")
|
||||
UNAME_MACHINE="alphaev69" ;;
|
||||
UNAME_MACHINE=alphaev69 ;;
|
||||
"EV7 (21364)")
|
||||
UNAME_MACHINE="alphaev7" ;;
|
||||
UNAME_MACHINE=alphaev7 ;;
|
||||
"EV7.9 (21364A)")
|
||||
UNAME_MACHINE="alphaev79" ;;
|
||||
UNAME_MACHINE=alphaev79 ;;
|
||||
esac
|
||||
# A Pn.n version is a patched version.
|
||||
# A Vn.n version is a released version.
|
||||
# A Tn.n version is a released field test version.
|
||||
# A Xn.n version is an unreleased experimental baselevel.
|
||||
# 1.2 uses "1.2" for uname -r.
|
||||
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
||||
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
|
||||
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
|
||||
exitcode=$?
|
||||
trap '' 0
|
||||
@@ -359,16 +383,16 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
exit ;;
|
||||
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
|
||||
eval $set_cc_for_build
|
||||
SUN_ARCH="i386"
|
||||
SUN_ARCH=i386
|
||||
# If there is a compiler, see if it is configured for 64-bit objects.
|
||||
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
|
||||
# This test works for both compilers.
|
||||
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
|
||||
if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
|
||||
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_64BIT_ARCH >/dev/null
|
||||
then
|
||||
SUN_ARCH="x86_64"
|
||||
SUN_ARCH=x86_64
|
||||
fi
|
||||
fi
|
||||
echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
@@ -393,7 +417,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
exit ;;
|
||||
sun*:*:4.2BSD:*)
|
||||
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
|
||||
test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
|
||||
test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3
|
||||
case "`/bin/arch`" in
|
||||
sun3)
|
||||
echo m68k-sun-sunos${UNAME_RELEASE}
|
||||
@@ -579,8 +603,9 @@ EOF
|
||||
else
|
||||
IBM_ARCH=powerpc
|
||||
fi
|
||||
if [ -x /usr/bin/oslevel ] ; then
|
||||
IBM_REV=`/usr/bin/oslevel`
|
||||
if [ -x /usr/bin/lslpp ] ; then
|
||||
IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
|
||||
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
|
||||
else
|
||||
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
|
||||
fi
|
||||
@@ -617,13 +642,13 @@ EOF
|
||||
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
|
||||
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
|
||||
case "${sc_cpu_version}" in
|
||||
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
|
||||
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
|
||||
523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
|
||||
528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
|
||||
532) # CPU_PA_RISC2_0
|
||||
case "${sc_kernel_bits}" in
|
||||
32) HP_ARCH="hppa2.0n" ;;
|
||||
64) HP_ARCH="hppa2.0w" ;;
|
||||
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
|
||||
32) HP_ARCH=hppa2.0n ;;
|
||||
64) HP_ARCH=hppa2.0w ;;
|
||||
'') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
|
||||
esac ;;
|
||||
esac
|
||||
fi
|
||||
@@ -662,11 +687,11 @@ EOF
|
||||
exit (0);
|
||||
}
|
||||
EOF
|
||||
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
|
||||
(CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
|
||||
test -z "$HP_ARCH" && HP_ARCH=hppa
|
||||
fi ;;
|
||||
esac
|
||||
if [ ${HP_ARCH} = "hppa2.0w" ]
|
||||
if [ ${HP_ARCH} = hppa2.0w ]
|
||||
then
|
||||
eval $set_cc_for_build
|
||||
|
||||
@@ -679,12 +704,12 @@ EOF
|
||||
# $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
|
||||
# => hppa64-hp-hpux11.23
|
||||
|
||||
if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
|
||||
if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
|
||||
grep -q __LP64__
|
||||
then
|
||||
HP_ARCH="hppa2.0w"
|
||||
HP_ARCH=hppa2.0w
|
||||
else
|
||||
HP_ARCH="hppa64"
|
||||
HP_ARCH=hppa64
|
||||
fi
|
||||
fi
|
||||
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
|
||||
@@ -789,14 +814,14 @@ EOF
|
||||
echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
||||
exit ;;
|
||||
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
|
||||
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
||||
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
|
||||
FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
|
||||
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
|
||||
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||
exit ;;
|
||||
5000:UNIX_System_V:4.*:*)
|
||||
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
|
||||
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
|
||||
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||
exit ;;
|
||||
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
|
||||
@@ -826,7 +851,7 @@ EOF
|
||||
*:MINGW*:*)
|
||||
echo ${UNAME_MACHINE}-pc-mingw32
|
||||
exit ;;
|
||||
i*:MSYS*:*)
|
||||
*:MSYS*:*)
|
||||
echo ${UNAME_MACHINE}-pc-msys
|
||||
exit ;;
|
||||
i*:windows32*:*)
|
||||
@@ -878,7 +903,7 @@ EOF
|
||||
exit ;;
|
||||
*:GNU/*:*:*)
|
||||
# other systems with GNU libc and userland
|
||||
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
|
||||
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
|
||||
exit ;;
|
||||
i*86:Minix:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-minix
|
||||
@@ -901,7 +926,7 @@ EOF
|
||||
EV68*) UNAME_MACHINE=alphaev68 ;;
|
||||
esac
|
||||
objdump --private-headers /bin/sh | grep -q ld.so.1
|
||||
if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
|
||||
if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
arc:Linux:*:* | arceb:Linux:*:*)
|
||||
@@ -932,6 +957,9 @@ EOF
|
||||
crisv32:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
|
||||
exit ;;
|
||||
e2k:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
frv:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
@@ -944,6 +972,9 @@ EOF
|
||||
ia64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
k1om:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
m32r*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
@@ -969,10 +1000,13 @@ EOF
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
|
||||
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
|
||||
;;
|
||||
or1k:Linux:*:*)
|
||||
mips64el:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
or32:Linux:*:*)
|
||||
openrisc*:Linux:*:*)
|
||||
echo or1k-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
or32:Linux:*:* | or1k*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
padre:Linux:*:*)
|
||||
@@ -1001,6 +1035,9 @@ EOF
|
||||
ppcle:Linux:*:*)
|
||||
echo powerpcle-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
riscv32:Linux:*:* | riscv64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
s390:Linux:*:* | s390x:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
|
||||
exit ;;
|
||||
@@ -1020,7 +1057,7 @@ EOF
|
||||
echo ${UNAME_MACHINE}-dec-linux-${LIBC}
|
||||
exit ;;
|
||||
x86_64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
echo ${UNAME_MACHINE}-pc-linux-${LIBC}
|
||||
exit ;;
|
||||
xtensa*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
@@ -1099,7 +1136,7 @@ EOF
|
||||
# uname -m prints for DJGPP always 'pc', but it prints nothing about
|
||||
# the processor, so we play safe by assuming i586.
|
||||
# Note: whatever this is, it MUST be the same as what config.sub
|
||||
# prints for the "djgpp" host, or else GDB configury will decide that
|
||||
# prints for the "djgpp" host, or else GDB configure will decide that
|
||||
# this is a cross-build.
|
||||
echo i586-pc-msdosdjgpp
|
||||
exit ;;
|
||||
@@ -1248,6 +1285,9 @@ EOF
|
||||
SX-8R:SUPER-UX:*:*)
|
||||
echo sx8r-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
SX-ACE:SUPER-UX:*:*)
|
||||
echo sxace-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
Power*:Rhapsody:*:*)
|
||||
echo powerpc-apple-rhapsody${UNAME_RELEASE}
|
||||
exit ;;
|
||||
@@ -1260,22 +1300,32 @@ EOF
|
||||
if test "$UNAME_PROCESSOR" = unknown ; then
|
||||
UNAME_PROCESSOR=powerpc
|
||||
fi
|
||||
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
|
||||
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_64BIT_ARCH >/dev/null
|
||||
then
|
||||
case $UNAME_PROCESSOR in
|
||||
i386) UNAME_PROCESSOR=x86_64 ;;
|
||||
powerpc) UNAME_PROCESSOR=powerpc64 ;;
|
||||
esac
|
||||
if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
|
||||
if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
|
||||
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_64BIT_ARCH >/dev/null
|
||||
then
|
||||
case $UNAME_PROCESSOR in
|
||||
i386) UNAME_PROCESSOR=x86_64 ;;
|
||||
powerpc) UNAME_PROCESSOR=powerpc64 ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
elif test "$UNAME_PROCESSOR" = i386 ; then
|
||||
# Avoid executing cc on OS X 10.9, as it ships with a stub
|
||||
# that puts up a graphical alert prompting to install
|
||||
# developer tools. Any system running Mac OS X 10.7 or
|
||||
# later (Darwin 11 and later) is required to have a 64-bit
|
||||
# processor. This is not true of the ARM version of Darwin
|
||||
# that Apple uses in portable devices.
|
||||
UNAME_PROCESSOR=x86_64
|
||||
fi
|
||||
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:procnto*:*:* | *:QNX:[0123456789]*:*)
|
||||
UNAME_PROCESSOR=`uname -p`
|
||||
if test "$UNAME_PROCESSOR" = "x86"; then
|
||||
if test "$UNAME_PROCESSOR" = x86; then
|
||||
UNAME_PROCESSOR=i386
|
||||
UNAME_MACHINE=pc
|
||||
fi
|
||||
@@ -1306,7 +1356,7 @@ EOF
|
||||
# "uname -m" is not consistent, so use $cputype instead. 386
|
||||
# is converted to i386 for consistency with other x86
|
||||
# operating systems.
|
||||
if test "$cputype" = "386"; then
|
||||
if test "$cputype" = 386; then
|
||||
UNAME_MACHINE=i386
|
||||
else
|
||||
UNAME_MACHINE="$cputype"
|
||||
@@ -1348,7 +1398,7 @@ EOF
|
||||
echo i386-pc-xenix
|
||||
exit ;;
|
||||
i*86:skyos:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
|
||||
echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'`
|
||||
exit ;;
|
||||
i*86:rdos:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-rdos
|
||||
@@ -1359,171 +1409,25 @@ EOF
|
||||
x86_64:VMkernel:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-esx
|
||||
exit ;;
|
||||
amd64:Isilon\ OneFS:*:*)
|
||||
echo x86_64-unknown-onefs
|
||||
exit ;;
|
||||
esac
|
||||
|
||||
eval $set_cc_for_build
|
||||
cat >$dummy.c <<EOF
|
||||
#ifdef _SEQUENT_
|
||||
# include <sys/types.h>
|
||||
# include <sys/utsname.h>
|
||||
#endif
|
||||
main ()
|
||||
{
|
||||
#if defined (sony)
|
||||
#if defined (MIPSEB)
|
||||
/* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
|
||||
I don't know.... */
|
||||
printf ("mips-sony-bsd\n"); exit (0);
|
||||
#else
|
||||
#include <sys/param.h>
|
||||
printf ("m68k-sony-newsos%s\n",
|
||||
#ifdef NEWSOS4
|
||||
"4"
|
||||
#else
|
||||
""
|
||||
#endif
|
||||
); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (__arm) && defined (__acorn) && defined (__unix)
|
||||
printf ("arm-acorn-riscix\n"); exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (hp300) && !defined (hpux)
|
||||
printf ("m68k-hp-bsd\n"); exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (NeXT)
|
||||
#if !defined (__ARCHITECTURE__)
|
||||
#define __ARCHITECTURE__ "m68k"
|
||||
#endif
|
||||
int version;
|
||||
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
|
||||
if (version < 4)
|
||||
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
|
||||
else
|
||||
printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
|
||||
exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (MULTIMAX) || defined (n16)
|
||||
#if defined (UMAXV)
|
||||
printf ("ns32k-encore-sysv\n"); exit (0);
|
||||
#else
|
||||
#if defined (CMU)
|
||||
printf ("ns32k-encore-mach\n"); exit (0);
|
||||
#else
|
||||
printf ("ns32k-encore-bsd\n"); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (__386BSD__)
|
||||
printf ("i386-pc-bsd\n"); exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (sequent)
|
||||
#if defined (i386)
|
||||
printf ("i386-sequent-dynix\n"); exit (0);
|
||||
#endif
|
||||
#if defined (ns32000)
|
||||
printf ("ns32k-sequent-dynix\n"); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (_SEQUENT_)
|
||||
struct utsname un;
|
||||
|
||||
uname(&un);
|
||||
|
||||
if (strncmp(un.version, "V2", 2) == 0) {
|
||||
printf ("i386-sequent-ptx2\n"); exit (0);
|
||||
}
|
||||
if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
|
||||
printf ("i386-sequent-ptx1\n"); exit (0);
|
||||
}
|
||||
printf ("i386-sequent-ptx\n"); exit (0);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (vax)
|
||||
# if !defined (ultrix)
|
||||
# include <sys/param.h>
|
||||
# if defined (BSD)
|
||||
# if BSD == 43
|
||||
printf ("vax-dec-bsd4.3\n"); exit (0);
|
||||
# else
|
||||
# if BSD == 199006
|
||||
printf ("vax-dec-bsd4.3reno\n"); exit (0);
|
||||
# else
|
||||
printf ("vax-dec-bsd\n"); exit (0);
|
||||
# endif
|
||||
# endif
|
||||
# else
|
||||
printf ("vax-dec-bsd\n"); exit (0);
|
||||
# endif
|
||||
# else
|
||||
printf ("vax-dec-ultrix\n"); exit (0);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (alliant) && defined (i860)
|
||||
printf ("i860-alliant-bsd\n"); exit (0);
|
||||
#endif
|
||||
|
||||
exit (1);
|
||||
}
|
||||
EOF
|
||||
|
||||
$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
|
||||
{ echo "$SYSTEM_NAME"; exit; }
|
||||
|
||||
# Apollos put the system type in the environment.
|
||||
|
||||
test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
|
||||
|
||||
# Convex versions that predate uname can use getsysinfo(1)
|
||||
|
||||
if [ -x /usr/convex/getsysinfo ]
|
||||
then
|
||||
case `getsysinfo -f cpu_type` in
|
||||
c1*)
|
||||
echo c1-convex-bsd
|
||||
exit ;;
|
||||
c2*)
|
||||
if getsysinfo -f scalar_acc
|
||||
then echo c32-convex-bsd
|
||||
else echo c2-convex-bsd
|
||||
fi
|
||||
exit ;;
|
||||
c34*)
|
||||
echo c34-convex-bsd
|
||||
exit ;;
|
||||
c38*)
|
||||
echo c38-convex-bsd
|
||||
exit ;;
|
||||
c4*)
|
||||
echo c4-convex-bsd
|
||||
exit ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
cat >&2 <<EOF
|
||||
$0: unable to guess system type
|
||||
|
||||
This script, last modified $timestamp, has failed to recognize
|
||||
the operating system you are using. It is advised that you
|
||||
download the most up to date version of the config scripts from
|
||||
This script (version $timestamp), has failed to recognize the
|
||||
operating system you are using. If your script is old, overwrite
|
||||
config.guess and config.sub with the latest versions from:
|
||||
|
||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
|
||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
|
||||
and
|
||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
|
||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
|
||||
|
||||
If the version you run ($0) is already up to date, please
|
||||
send the following data and any information you think might be
|
||||
pertinent to <config-patches@gnu.org> in order to provide the needed
|
||||
information to handle your system.
|
||||
If $0 has already been updated, send the following data and any
|
||||
information you think might be pertinent to config-patches@gnu.org to
|
||||
provide the necessary information to handle your system.
|
||||
|
||||
config.guess timestamp = $timestamp
|
||||
|
||||
|
||||
+57
@@ -30,6 +30,9 @@
|
||||
internal symbols */
|
||||
#undef EXPORT_ALL_SYMBOLS
|
||||
|
||||
/* Define to 1 if you have the `accept4' function. */
|
||||
#undef HAVE_ACCEPT4
|
||||
|
||||
/* Define to 1 if you have the `arc4random' function. */
|
||||
#undef HAVE_ARC4RANDOM
|
||||
|
||||
@@ -79,6 +82,14 @@
|
||||
don't. */
|
||||
#undef HAVE_DECL_INET_PTON
|
||||
|
||||
/* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_NID_ED25519
|
||||
|
||||
/* Define to 1 if you have the declaration of `NID_ED448', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_NID_ED448
|
||||
|
||||
/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_NID_SECP384R1
|
||||
@@ -91,6 +102,10 @@
|
||||
don't. */
|
||||
#undef HAVE_DECL_REALLOCARRAY
|
||||
|
||||
/* Define to 1 if you have the declaration of `redisConnect', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_REDISCONNECT
|
||||
|
||||
/* Define to 1 if you have the declaration of `sk_SSL_COMP_pop_free', and to 0
|
||||
if you don't. */
|
||||
#undef HAVE_DECL_SK_SSL_COMP_POP_FREE
|
||||
@@ -157,6 +172,9 @@
|
||||
/* Define to 1 if you have the `EVP_cleanup' function. */
|
||||
#undef HAVE_EVP_CLEANUP
|
||||
|
||||
/* Define to 1 if you have the `EVP_DigestVerify' function. */
|
||||
#undef HAVE_EVP_DIGESTVERIFY
|
||||
|
||||
/* Define to 1 if you have the `EVP_dss1' function. */
|
||||
#undef HAVE_EVP_DSS1
|
||||
|
||||
@@ -226,6 +244,9 @@
|
||||
/* Define to 1 if you have the <grp.h> header file. */
|
||||
#undef HAVE_GRP_H
|
||||
|
||||
/* Define to 1 if you have the <hiredis/hiredis.h> header file. */
|
||||
#undef HAVE_HIREDIS_HIREDIS_H
|
||||
|
||||
/* If you have HMAC_Update */
|
||||
#undef HAVE_HMAC_UPDATE
|
||||
|
||||
@@ -256,6 +277,9 @@
|
||||
/* Define to 1 if you have the `kill' function. */
|
||||
#undef HAVE_KILL
|
||||
|
||||
/* Define to 1 if you have the <libkern/OSByteOrder.h> header file. */
|
||||
#undef HAVE_LIBKERN_OSBYTEORDER_H
|
||||
|
||||
/* Define if we have LibreSSL */
|
||||
#undef HAVE_LIBRESSL
|
||||
|
||||
@@ -289,6 +313,9 @@
|
||||
/* Define to 1 if you have the <nettle/dsa-compat.h> header file. */
|
||||
#undef HAVE_NETTLE_DSA_COMPAT_H
|
||||
|
||||
/* Define to 1 if you have the <nettle/eddsa.h> header file. */
|
||||
#undef HAVE_NETTLE_EDDSA_H
|
||||
|
||||
/* Use libnss for crypto */
|
||||
#undef HAVE_NSS
|
||||
|
||||
@@ -415,6 +442,12 @@
|
||||
/* 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_get0_peername' function. */
|
||||
#undef HAVE_SSL_GET0_PEERNAME
|
||||
|
||||
/* Define to 1 if you have the `SSL_set1_host' function. */
|
||||
#undef HAVE_SSL_SET1_HOST
|
||||
|
||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||
#undef HAVE_STDARG_H
|
||||
|
||||
@@ -463,6 +496,9 @@
|
||||
/* Define to 1 if systemd should be used */
|
||||
#undef HAVE_SYSTEMD
|
||||
|
||||
/* Define to 1 if you have the <sys/endian.h> header file. */
|
||||
#undef HAVE_SYS_ENDIAN_H
|
||||
|
||||
/* Define to 1 if you have the <sys/ipc.h> header file. */
|
||||
#undef HAVE_SYS_IPC_H
|
||||
|
||||
@@ -636,6 +672,9 @@
|
||||
/* define if (v)snprintf does not return length needed, (but length used) */
|
||||
#undef SNPRINTF_RET_BROKEN
|
||||
|
||||
/* Define to 1 if libsodium supports sodium_set_misuse_handler */
|
||||
#undef SODIUM_MISUSE_HANDLER
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
@@ -666,6 +705,9 @@
|
||||
/* Define to 1 to enable dnscrypt support */
|
||||
#undef USE_DNSCRYPT
|
||||
|
||||
/* Define to 1 to enable dnscrypt with xchacha20 support */
|
||||
#undef USE_DNSCRYPT_XCHACHA20
|
||||
|
||||
/* Define to 1 to enable dnstap support */
|
||||
#undef USE_DNSTAP
|
||||
|
||||
@@ -678,9 +720,18 @@
|
||||
/* Define this to enable an EVP workaround for older openssl */
|
||||
#undef USE_ECDSA_EVP_WORKAROUND
|
||||
|
||||
/* Define this to enable ED25519 support. */
|
||||
#undef USE_ED25519
|
||||
|
||||
/* Define this to enable ED448 support. */
|
||||
#undef USE_ED448
|
||||
|
||||
/* Define this to enable GOST support. */
|
||||
#undef USE_GOST
|
||||
|
||||
/* Define to 1 to use ipsecmod support. */
|
||||
#undef USE_IPSECMOD
|
||||
|
||||
/* Define if you want to use internal select based events */
|
||||
#undef USE_MINI_EVENT
|
||||
|
||||
@@ -690,6 +741,9 @@
|
||||
/* Define this to enable client TCP Fast Open. */
|
||||
#undef USE_OSX_MSG_FASTOPEN
|
||||
|
||||
/* Define this to use hiredis client. */
|
||||
#undef USE_REDIS
|
||||
|
||||
/* Define this to enable SHA1 support. */
|
||||
#undef USE_SHA1
|
||||
|
||||
@@ -1128,6 +1182,7 @@ uint32_t arc4random(void);
|
||||
void arc4random_buf(void* buf, size_t n);
|
||||
void _ARC4_LOCK(void);
|
||||
void _ARC4_UNLOCK(void);
|
||||
void _ARC4_LOCK_DESTROY(void);
|
||||
#endif
|
||||
#ifndef HAVE_ARC4RANDOM_UNIFORM
|
||||
uint32_t arc4random_uniform(uint32_t upper_bound);
|
||||
@@ -1193,6 +1248,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
||||
|
||||
/** default port for DNS traffic. */
|
||||
#define UNBOUND_DNS_PORT 53
|
||||
/** default port for DNS over TLS traffic. */
|
||||
#define UNBOUND_DNS_OVER_TLS_PORT 853
|
||||
/** default port for unbound control traffic, registered port with IANA,
|
||||
ub-dns-control 8953/tcp unbound dns nameserver control */
|
||||
#define UNBOUND_CONTROL_PORT 8953
|
||||
|
||||
Vendored
+60
-28
@@ -1,8 +1,8 @@
|
||||
#! /bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright 1992-2013 Free Software Foundation, Inc.
|
||||
# Copyright 1992-2016 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2013-08-10'
|
||||
timestamp='2016-09-05'
|
||||
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
@@ -25,7 +25,7 @@ timestamp='2013-08-10'
|
||||
# of the GNU General Public License, version 3 ("GPLv3").
|
||||
|
||||
|
||||
# Please send patches with a ChangeLog entry to config-patches@gnu.org.
|
||||
# Please send patches to <config-patches@gnu.org>.
|
||||
#
|
||||
# Configuration subroutine to validate and canonicalize a configuration type.
|
||||
# Supply the specified configuration type as an argument.
|
||||
@@ -33,7 +33,7 @@ timestamp='2013-08-10'
|
||||
# Otherwise, we print the canonical config type on stdout and succeed.
|
||||
|
||||
# You can get the latest version of this script from:
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
|
||||
|
||||
# This file is supposed to be the same for all GNU packages
|
||||
# and recognize all the CPU types, system types and aliases
|
||||
@@ -53,8 +53,7 @@ timestamp='2013-08-10'
|
||||
me=`echo "$0" | sed -e 's,.*/,,'`
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION] CPU-MFR-OPSYS
|
||||
$0 [OPTION] ALIAS
|
||||
Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
|
||||
|
||||
Canonicalize a configuration name.
|
||||
|
||||
@@ -68,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>."
|
||||
version="\
|
||||
GNU config.sub ($timestamp)
|
||||
|
||||
Copyright 1992-2013 Free Software Foundation, Inc.
|
||||
Copyright 1992-2016 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@@ -117,8 +116,8 @@ maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
|
||||
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
|
||||
knetbsd*-gnu* | netbsd*-gnu* | \
|
||||
kopensolaris*-gnu* | \
|
||||
knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
|
||||
kopensolaris*-gnu* | cloudabi*-eabi* | \
|
||||
storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
os=-$maybe_os
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
@@ -255,16 +254,18 @@ case $basic_machine in
|
||||
| arc | arceb \
|
||||
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
|
||||
| avr | avr32 \
|
||||
| ba \
|
||||
| be32 | be64 \
|
||||
| bfin \
|
||||
| c4x | c8051 | clipper \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
| epiphany \
|
||||
| fido | fr30 | frv \
|
||||
| e2k | epiphany \
|
||||
| fido | fr30 | frv | ft32 \
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| hexagon \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k | iq2000 \
|
||||
| k1om \
|
||||
| le32 | le64 \
|
||||
| lm32 \
|
||||
| m32c | m32r | m32rle | m68000 | m68k | m88k \
|
||||
@@ -282,8 +283,10 @@ case $basic_machine in
|
||||
| mips64vr5900 | mips64vr5900el \
|
||||
| mipsisa32 | mipsisa32el \
|
||||
| mipsisa32r2 | mipsisa32r2el \
|
||||
| mipsisa32r6 | mipsisa32r6el \
|
||||
| mipsisa64 | mipsisa64el \
|
||||
| mipsisa64r2 | mipsisa64r2el \
|
||||
| mipsisa64r6 | mipsisa64r6el \
|
||||
| mipsisa64sb1 | mipsisa64sb1el \
|
||||
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||
| mipsr5900 | mipsr5900el \
|
||||
@@ -295,14 +298,14 @@ case $basic_machine in
|
||||
| nds32 | nds32le | nds32be \
|
||||
| nios | nios2 | nios2eb | nios2el \
|
||||
| ns16k | ns32k \
|
||||
| open8 \
|
||||
| or1k | or32 \
|
||||
| open8 | or1k | or1knd | or32 \
|
||||
| pdp10 | pdp11 | pj | pjl \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle \
|
||||
| pyramid \
|
||||
| riscv32 | riscv64 \
|
||||
| rl78 | rx \
|
||||
| score \
|
||||
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh64 | sh64le \
|
||||
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
|
||||
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
|
||||
@@ -310,6 +313,7 @@ case $basic_machine in
|
||||
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
|
||||
| ubicom32 \
|
||||
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
|
||||
| visium \
|
||||
| we32k \
|
||||
| x86 | xc16x | xstormy16 | xtensa \
|
||||
| z8k | z80)
|
||||
@@ -324,7 +328,10 @@ case $basic_machine in
|
||||
c6x)
|
||||
basic_machine=tic6x-unknown
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
|
||||
leon|leon[3-9])
|
||||
basic_machine=sparc-$basic_machine
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-none
|
||||
;;
|
||||
@@ -369,18 +376,20 @@ case $basic_machine in
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
|
||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||
| avr-* | avr32-* \
|
||||
| ba-* \
|
||||
| be32-* | be64-* \
|
||||
| bfin-* | bs2000-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* \
|
||||
| c8051-* | clipper-* | craynv-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
| e2k-* | elxsi-* \
|
||||
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
||||
| h8300-* | h8500-* \
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| hexagon-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
| ip2k-* | iq2000-* \
|
||||
| k1om-* \
|
||||
| le32-* | le64-* \
|
||||
| lm32-* \
|
||||
| m32c-* | m32r-* | m32rle-* \
|
||||
@@ -400,8 +409,10 @@ case $basic_machine in
|
||||
| mips64vr5900-* | mips64vr5900el-* \
|
||||
| mipsisa32-* | mipsisa32el-* \
|
||||
| mipsisa32r2-* | mipsisa32r2el-* \
|
||||
| mipsisa32r6-* | mipsisa32r6el-* \
|
||||
| mipsisa64-* | mipsisa64el-* \
|
||||
| mipsisa64r2-* | mipsisa64r2el-* \
|
||||
| mipsisa64r6-* | mipsisa64r6el-* \
|
||||
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
||||
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
||||
| mipsr5900-* | mipsr5900el-* \
|
||||
@@ -413,16 +424,18 @@ case $basic_machine in
|
||||
| nios-* | nios2-* | nios2eb-* | nios2el-* \
|
||||
| none-* | np1-* | ns16k-* | ns32k-* \
|
||||
| open8-* \
|
||||
| or1k*-* \
|
||||
| orion-* \
|
||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
|
||||
| pyramid-* \
|
||||
| riscv32-* | riscv64-* \
|
||||
| rl78-* | romp-* | rs6000-* | rx-* \
|
||||
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
||||
| sparclite-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
|
||||
| tahoe-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||
| tile*-* \
|
||||
@@ -430,6 +443,7 @@ case $basic_machine in
|
||||
| ubicom32-* \
|
||||
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
|
||||
| vax-* \
|
||||
| visium-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* \
|
||||
| xstormy16-* | xtensa*-* \
|
||||
@@ -506,6 +520,9 @@ case $basic_machine in
|
||||
basic_machine=i386-pc
|
||||
os=-aros
|
||||
;;
|
||||
asmjs)
|
||||
basic_machine=asmjs-unknown
|
||||
;;
|
||||
aux)
|
||||
basic_machine=m68k-apple
|
||||
os=-aux
|
||||
@@ -626,6 +643,14 @@ case $basic_machine in
|
||||
basic_machine=m68k-bull
|
||||
os=-sysv3
|
||||
;;
|
||||
e500v[12])
|
||||
basic_machine=powerpc-unknown
|
||||
os=$os"spe"
|
||||
;;
|
||||
e500v[12]-*)
|
||||
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=$os"spe"
|
||||
;;
|
||||
ebmon29k)
|
||||
basic_machine=a29k-amd
|
||||
os=-ebmon
|
||||
@@ -767,6 +792,9 @@ case $basic_machine in
|
||||
basic_machine=m68k-isi
|
||||
os=-sysv
|
||||
;;
|
||||
leon-*|leon[3-9]-*)
|
||||
basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
|
||||
;;
|
||||
m68knommu)
|
||||
basic_machine=m68k-unknown
|
||||
os=-linux
|
||||
@@ -822,6 +850,10 @@ case $basic_machine in
|
||||
basic_machine=powerpc-unknown
|
||||
os=-morphos
|
||||
;;
|
||||
moxiebox)
|
||||
basic_machine=moxie-unknown
|
||||
os=-moxiebox
|
||||
;;
|
||||
msdos)
|
||||
basic_machine=i386-pc
|
||||
os=-msdos
|
||||
@@ -998,7 +1030,7 @@ case $basic_machine in
|
||||
ppc-* | ppcbe-*)
|
||||
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppcle | powerpclittle | ppc-le | powerpc-little)
|
||||
ppcle | powerpclittle)
|
||||
basic_machine=powerpcle-unknown
|
||||
;;
|
||||
ppcle-* | powerpclittle-*)
|
||||
@@ -1006,9 +1038,9 @@ case $basic_machine in
|
||||
;;
|
||||
ppc64) basic_machine=powerpc64-unknown
|
||||
;;
|
||||
ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
|
||||
ppc64le | powerpc64little)
|
||||
basic_machine=powerpc64le-unknown
|
||||
;;
|
||||
ppc64le-* | powerpc64little-*)
|
||||
@@ -1354,27 +1386,28 @@ case $os in
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
|
||||
| -sym* | -kopensolaris* | -plan9* \
|
||||
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
||||
| -aos* | -aros* \
|
||||
| -aos* | -aros* | -cloudabi* | -sortix* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
|
||||
| -bitrig* | -openbsd* | -solidbsd* \
|
||||
| -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
|
||||
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
|
||||
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -chorusos* | -chorusrdb* | -cegcc* \
|
||||
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
|
||||
| -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
|
||||
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
|
||||
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
|
||||
| -onefs* | -tirtos* | -phoenix*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
@@ -1506,6 +1539,8 @@ case $os in
|
||||
;;
|
||||
-nacl*)
|
||||
;;
|
||||
-ios)
|
||||
;;
|
||||
-none)
|
||||
;;
|
||||
*)
|
||||
@@ -1592,9 +1627,6 @@ case $basic_machine in
|
||||
mips*-*)
|
||||
os=-elf
|
||||
;;
|
||||
or1k-*)
|
||||
os=-elf
|
||||
;;
|
||||
or32-*)
|
||||
os=-coff
|
||||
;;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for unbound 1.6.2.
|
||||
# Generated by GNU Autoconf 2.69 for unbound 1.7.3.
|
||||
#
|
||||
# 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.6.2'
|
||||
PACKAGE_STRING='unbound 1.6.2'
|
||||
PACKAGE_VERSION='1.7.3'
|
||||
PACKAGE_STRING='unbound 1.7.3'
|
||||
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl'
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -638,9 +638,12 @@ INSTALLTARGET
|
||||
ALLTARGET
|
||||
SOURCEFILE
|
||||
SOURCEDETERMINE
|
||||
IPSECMOD_HEADER
|
||||
IPSECMOD_OBJ
|
||||
DNSCRYPT_OBJ
|
||||
DNSCRYPT_SRC
|
||||
ENABLE_DNSCRYPT
|
||||
ENABLE_DNSCRYPT_XCHACHA20
|
||||
DNSTAP_OBJ
|
||||
DNSTAP_SRC
|
||||
opt_dnstap_socket_path
|
||||
@@ -755,6 +758,9 @@ UNBOUND_CHROOT_DIR
|
||||
UNBOUND_RUN_DIR
|
||||
ub_conf_dir
|
||||
ub_conf_file
|
||||
UNBOUND_LOCALSTATE_DIR
|
||||
UNBOUND_SYSCONF_DIR
|
||||
UNBOUND_SBIN_DIR
|
||||
EGREP
|
||||
GREP
|
||||
CPP
|
||||
@@ -842,6 +848,7 @@ with_pthreads
|
||||
with_solaris_threads
|
||||
with_pyunbound
|
||||
with_pythonmodule
|
||||
enable_swig_version_check
|
||||
with_nss
|
||||
with_nettle
|
||||
with_ssl
|
||||
@@ -851,11 +858,14 @@ enable_subnet
|
||||
enable_gost
|
||||
enable_ecdsa
|
||||
enable_dsa
|
||||
enable_ed25519
|
||||
enable_ed448
|
||||
enable_event_api
|
||||
enable_tfo_client
|
||||
enable_tfo_server
|
||||
with_libevent
|
||||
with_libexpat
|
||||
with_libhiredis
|
||||
enable_static_exe
|
||||
enable_systemd
|
||||
enable_lock_checks
|
||||
@@ -867,6 +877,7 @@ with_libfstrm
|
||||
enable_dnscrypt
|
||||
with_libsodium
|
||||
enable_cachedb
|
||||
enable_ipsecmod
|
||||
with_libunbound_only
|
||||
'
|
||||
ac_precious_vars='build_alias
|
||||
@@ -1429,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.6.2 to adapt to many kinds of systems.
|
||||
\`configure' configures unbound 1.7.3 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1494,7 +1505,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of unbound 1.6.2:";;
|
||||
short | recursive ) echo "Configuration of unbound 1.7.3:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1524,6 +1535,9 @@ Optional Features:
|
||||
enable nonregional allocs, slow but exposes regional
|
||||
allocations to other memory purifiers, for debug
|
||||
purposes
|
||||
--disable-swig-version-check
|
||||
Disable swig version check to build python modules
|
||||
with older swig even though that is unreliable
|
||||
--disable-sha1 Disable SHA1 RRSIG support, does not disable nsec3
|
||||
support
|
||||
--disable-sha2 Disable SHA256 and SHA512 RRSIG support
|
||||
@@ -1531,6 +1545,8 @@ Optional Features:
|
||||
--disable-gost Disable GOST support
|
||||
--disable-ecdsa Disable ECDSA support
|
||||
--disable-dsa Disable DSA support
|
||||
--disable-ed25519 Disable ED25519 support
|
||||
--disable-ed448 Disable ED448 support
|
||||
--enable-event-api Enable (experimental) pluggable event base
|
||||
libunbound API installed to unbound-event.h
|
||||
--enable-tfo-client Enable TCP Fast Open for client mode
|
||||
@@ -1547,6 +1563,8 @@ Optional Features:
|
||||
--enable-dnscrypt Enable dnscrypt support (requires libsodium)
|
||||
--enable-cachedb enable cachedb module that can use external cache
|
||||
storage
|
||||
--enable-ipsecmod Enable ipsecmod module that facilitates
|
||||
opportunistic IPsec
|
||||
|
||||
Optional Packages:
|
||||
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
||||
@@ -1595,6 +1613,7 @@ Optional Packages:
|
||||
an explicit path). Slower, but allows use of large
|
||||
outgoing port ranges.
|
||||
--with-libexpat=path specify explicit path for libexpat.
|
||||
--with-libhiredis=path specify explicit path for libhiredis.
|
||||
--with-dnstap-socket-path=pathname
|
||||
set default dnstap socket path
|
||||
--with-protobuf-c=path Path where protobuf-c is installed, for dnstap
|
||||
@@ -1703,7 +1722,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
unbound configure 1.6.2
|
||||
unbound configure 1.7.3
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2412,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.6.2, which was
|
||||
It was created by unbound $as_me 1.7.3, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -2762,13 +2781,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
UNBOUND_VERSION_MAJOR=1
|
||||
|
||||
UNBOUND_VERSION_MINOR=6
|
||||
UNBOUND_VERSION_MINOR=7
|
||||
|
||||
UNBOUND_VERSION_MICRO=2
|
||||
UNBOUND_VERSION_MICRO=3
|
||||
|
||||
|
||||
LIBUNBOUND_CURRENT=7
|
||||
LIBUNBOUND_REVISION=1
|
||||
LIBUNBOUND_REVISION=11
|
||||
LIBUNBOUND_AGE=5
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@@ -2821,6 +2840,16 @@ LIBUNBOUND_AGE=5
|
||||
# 1.6.0 had 6:3:4
|
||||
# 1.6.1 had 7:0:5 # ub_callback_t typedef renamed to ub_callback_type
|
||||
# 1.6.2 had 7:1:5
|
||||
# 1.6.3 had 7:2:5
|
||||
# 1.6.4 had 7:3:5
|
||||
# 1.6.5 had 7:4:5
|
||||
# 1.6.6 had 7:5:5
|
||||
# 1.6.7 had 7:6:5
|
||||
# 1.6.8 had 7:7:5
|
||||
# 1.7.0 had 7:8:5
|
||||
# 1.7.1 had 7:9:5
|
||||
# 1.7.2 had 7:10:5
|
||||
# 1.7.3 had 7:11:5
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -2836,7 +2865,7 @@ LIBUNBOUND_AGE=5
|
||||
# Current and Age. Set Revision to 0, since this is the first
|
||||
# implementation of the new API.
|
||||
#
|
||||
# Otherwise, we're changing the binary API and breaking bakward
|
||||
# Otherwise, we're changing the binary API and breaking backward
|
||||
# compatibility with old binaries. Increment Current. Set Age to 0,
|
||||
# since we're backward compatible with no previous APIs. Set Revision
|
||||
# to 0 too.
|
||||
@@ -4105,6 +4134,11 @@ case "$prefix" in
|
||||
prefix="/usr/local"
|
||||
;;
|
||||
esac
|
||||
case "$exec_prefix" in
|
||||
NONE)
|
||||
exec_prefix="$prefix"
|
||||
;;
|
||||
esac
|
||||
|
||||
# are we on MinGW?
|
||||
if uname -s 2>&1 | grep MINGW32 >/dev/null; then on_mingw="yes"
|
||||
@@ -4116,6 +4150,12 @@ fi
|
||||
#
|
||||
# Determine configuration file
|
||||
# the eval is to evaluate shell expansion twice
|
||||
UNBOUND_SBIN_DIR=`eval echo "${sbindir}"`
|
||||
|
||||
UNBOUND_SYSCONF_DIR=`eval echo "${sysconfdir}"`
|
||||
|
||||
UNBOUND_LOCALSTATE_DIR=`eval echo "${localstatedir}"`
|
||||
|
||||
if test $on_mingw = "no"; then
|
||||
ub_conf_file=`eval echo "${sysconfdir}/unbound/unbound.conf"`
|
||||
else
|
||||
@@ -4401,6 +4441,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
|
||||
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
# allow user to override the -g -O2 flags.
|
||||
default_cflags=no
|
||||
if test "x$CFLAGS" = "x" ; then
|
||||
|
||||
|
||||
@@ -4464,6 +4505,7 @@ $as_echo "no" >&6; }
|
||||
|
||||
fi
|
||||
|
||||
default_cflags=yes
|
||||
fi
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
@@ -5917,6 +5959,10 @@ $as_echo "#define UNBOUND_DEBUG /**/" >>confdefs.h
|
||||
# nothing to do.
|
||||
;;
|
||||
esac
|
||||
if test "$default_cflags" = "yes"; then
|
||||
# only when CFLAGS was "" at the start, if the users wants to
|
||||
# override we shouldn't add default cflags, because they wouldn't
|
||||
# be able to turn off these options and set the CFLAGS wanted.
|
||||
|
||||
# Check whether --enable-flto was given.
|
||||
if test "${enable_flto+set}" = set; then :
|
||||
@@ -6051,6 +6097,7 @@ rm -f core conftest.err conftest.$ac_objext \
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
|
||||
$as_echo_n "checking for inline... " >&6; }
|
||||
@@ -14437,7 +14484,7 @@ CC=$lt_save_CC
|
||||
|
||||
|
||||
# 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/ipc.h sys/shm.h
|
||||
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 :
|
||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
|
||||
@@ -16439,7 +16486,9 @@ if test x"$ax_pthread_ok" = xyes; then
|
||||
|
||||
$as_echo "#define HAVE_PTHREAD 1" >>confdefs.h
|
||||
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
if test -n "$PTHREAD_LIBS"; then
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
fi
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
CC="$PTHREAD_CC"
|
||||
ub_have_pthreads=yes
|
||||
@@ -16869,14 +16918,28 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
$as_echo "#define HAVE_PYTHON 1" >>confdefs.h
|
||||
|
||||
LIBS="$PYTHON_LDFLAGS $LIBS"
|
||||
CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS"
|
||||
if test -n "$LIBS"; then
|
||||
LIBS="$PYTHON_LDFLAGS $LIBS"
|
||||
else
|
||||
LIBS="$PYTHON_LDFLAGS"
|
||||
fi
|
||||
if test -n "$CPPFLAGS"; then
|
||||
CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS"
|
||||
else
|
||||
CPPFLAGS="$PYTHON_CPPFLAGS"
|
||||
fi
|
||||
ub_have_python=yes
|
||||
PC_PY_DEPENDENCY="python"
|
||||
|
||||
|
||||
# Check for SWIG
|
||||
ub_have_swig=no
|
||||
# Check whether --enable-swig-version-check was given.
|
||||
if test "${enable_swig_version_check+set}" = set; then :
|
||||
enableval=$enable_swig_version_check;
|
||||
fi
|
||||
|
||||
if test "$enable_swig_version_check" = "yes"; then
|
||||
|
||||
# Extract the first word of "swig", so it can be a program name with args.
|
||||
set dummy swig; ac_word=$2
|
||||
@@ -16993,6 +17056,124 @@ $as_echo "$as_me: WARNING: cannot determine SWIG version" >&2;}
|
||||
fi
|
||||
|
||||
|
||||
else
|
||||
|
||||
# Extract the first word of "swig", so it can be a program name with args.
|
||||
set dummy swig; 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_SWIG+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
case $SWIG in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
ac_cv_path_SWIG="$SWIG" # 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_SWIG="$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
|
||||
SWIG=$ac_cv_path_SWIG
|
||||
if test -n "$SWIG"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG" >&5
|
||||
$as_echo "$SWIG" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
if test -z "$SWIG" ; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot find 'swig' program. You should look at http://www.swig.org" >&5
|
||||
$as_echo "$as_me: WARNING: cannot find 'swig' program. You should look at http://www.swig.org" >&2;}
|
||||
SWIG='echo "Error: SWIG is not installed. You should look at http://www.swig.org" ; false'
|
||||
elif test -n "" ; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SWIG version" >&5
|
||||
$as_echo_n "checking for SWIG version... " >&6; }
|
||||
swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $swig_version" >&5
|
||||
$as_echo "$swig_version" >&6; }
|
||||
if test -n "$swig_version" ; then
|
||||
# Calculate the required version number components
|
||||
required=
|
||||
required_major=`echo $required | sed 's/[^0-9].*//'`
|
||||
if test -z "$required_major" ; then
|
||||
required_major=0
|
||||
fi
|
||||
required=`echo $required | sed 's/[0-9]*[^0-9]//'`
|
||||
required_minor=`echo $required | sed 's/[^0-9].*//'`
|
||||
if test -z "$required_minor" ; then
|
||||
required_minor=0
|
||||
fi
|
||||
required=`echo $required | sed 's/[0-9]*[^0-9]//'`
|
||||
required_patch=`echo $required | sed 's/[^0-9].*//'`
|
||||
if test -z "$required_patch" ; then
|
||||
required_patch=0
|
||||
fi
|
||||
# Calculate the available version number components
|
||||
available=$swig_version
|
||||
available_major=`echo $available | sed 's/[^0-9].*//'`
|
||||
if test -z "$available_major" ; then
|
||||
available_major=0
|
||||
fi
|
||||
available=`echo $available | sed 's/[0-9]*[^0-9]//'`
|
||||
available_minor=`echo $available | sed 's/[^0-9].*//'`
|
||||
if test -z "$available_minor" ; then
|
||||
available_minor=0
|
||||
fi
|
||||
available=`echo $available | sed 's/[0-9]*[^0-9]//'`
|
||||
available_patch=`echo $available | sed 's/[^0-9].*//'`
|
||||
if test -z "$available_patch" ; then
|
||||
available_patch=0
|
||||
fi
|
||||
badversion=0
|
||||
if test $available_major -lt $required_major ; then
|
||||
badversion=1
|
||||
fi
|
||||
if test $available_major -eq $required_major \
|
||||
-a $available_minor -lt $required_minor ; then
|
||||
badversion=1
|
||||
fi
|
||||
if test $available_major -eq $required_major \
|
||||
-a $available_minor -eq $required_minor \
|
||||
-a $available_patch -lt $required_patch ; then
|
||||
badversion=1
|
||||
fi
|
||||
if test $badversion -eq 1 ; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: SWIG version >= is required. You have $swig_version. You should look at http://www.swig.org" >&5
|
||||
$as_echo "$as_me: WARNING: SWIG version >= is required. You have $swig_version. You should look at http://www.swig.org" >&2;}
|
||||
SWIG='echo "Error: SWIG version >= is required. You have '"$swig_version"'. You should look at http://www.swig.org" ; false'
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: SWIG executable is '$SWIG'" >&5
|
||||
$as_echo "$as_me: SWIG executable is '$SWIG'" >&6;}
|
||||
SWIG_LIB=`$SWIG -swiglib`
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: SWIG library directory is '$SWIG_LIB'" >&5
|
||||
$as_echo "$as_me: SWIG library directory is '$SWIG_LIB'" >&6;}
|
||||
fi
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot determine SWIG version" >&5
|
||||
$as_echo "$as_me: WARNING: cannot determine SWIG version" >&2;}
|
||||
SWIG='echo "Error: Cannot determine SWIG version. You should look at http://www.swig.org" ; false'
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking SWIG" >&5
|
||||
$as_echo_n "checking SWIG... " >&6; }
|
||||
if test ! -x "$SWIG"; then
|
||||
@@ -17225,8 +17406,8 @@ $as_echo "no" >&6; }
|
||||
# check if -lwsock32 or -lgdi32 are needed.
|
||||
BAKLIBS="$LIBS"
|
||||
BAKSSLLIBS="$LIBSSL_LIBS"
|
||||
LIBS="$LIBS -lgdi32"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32"
|
||||
LIBS="$LIBS -lgdi32 -lws2_32"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32 -lws2_32"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -lgdi32" >&5
|
||||
$as_echo_n "checking if -lcrypto needs -lgdi32... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
@@ -17597,7 +17778,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
|
||||
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
|
||||
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"
|
||||
@@ -17613,7 +17794,7 @@ done
|
||||
# these check_funcs need -lssl
|
||||
BAKLIBS="$LIBS"
|
||||
LIBS="-lssl $LIBS"
|
||||
for ac_func in OPENSSL_init_ssl SSL_CTX_set_security_level
|
||||
for ac_func in OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername
|
||||
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"
|
||||
@@ -18028,9 +18209,32 @@ case "$enable_dsa" in
|
||||
;;
|
||||
*)
|
||||
# detect if DSA is supported, and turn it off if not.
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
ac_fn_c_check_func "$LINENO" "DSA_SIG_new" "ac_cv_func_DSA_SIG_new"
|
||||
if test "x$ac_cv_func_DSA_SIG_new" = xyes; then :
|
||||
|
||||
as_ac_Type=`$as_echo "ac_cv_type_DSA_SIG*" | $as_tr_sh`
|
||||
ac_fn_c_check_type "$LINENO" "DSA_SIG*" "$as_ac_Type" "
|
||||
$ac_includes_default
|
||||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_RAND_H
|
||||
#include <openssl/rand.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_CONF_H
|
||||
#include <openssl/conf.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_ENGINE_H
|
||||
#include <openssl/engine.h>
|
||||
#endif
|
||||
|
||||
"
|
||||
if eval test \"x\$"$as_ac_Type"\" = x"yes"; then :
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define USE_DSA 1
|
||||
@@ -18042,9 +18246,124 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
else
|
||||
if test "x$enable_dsa" = "xyes"; then as_fn_error $? "OpenSSL does not support DSA and you used --enable-dsa." "$LINENO" 5
|
||||
fi
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define USE_DSA 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check whether --enable-ed25519 was given.
|
||||
if test "${enable_ed25519+set}" = set; then :
|
||||
enableval=$enable_ed25519;
|
||||
fi
|
||||
|
||||
use_ed25519="no"
|
||||
case "$enable_ed25519" in
|
||||
no)
|
||||
;;
|
||||
*)
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
ac_fn_c_check_decl "$LINENO" "NID_ED25519" "ac_cv_have_decl_NID_ED25519" "$ac_includes_default
|
||||
#include <openssl/evp.h>
|
||||
|
||||
"
|
||||
if test "x$ac_cv_have_decl_NID_ED25519" = xyes; then :
|
||||
ac_have_decl=1
|
||||
else
|
||||
ac_have_decl=0
|
||||
fi
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_DECL_NID_ED25519 $ac_have_decl
|
||||
_ACEOF
|
||||
if test $ac_have_decl = 1; then :
|
||||
|
||||
use_ed25519="yes"
|
||||
|
||||
else
|
||||
if test "x$enable_ed25519" = "xyes"; then as_fn_error $? "OpenSSL does not support ED25519 and you used --enable-ed25519." "$LINENO" 5
|
||||
fi
|
||||
fi
|
||||
|
||||
fi
|
||||
if test $USE_NETTLE = "yes"; then
|
||||
for ac_header in nettle/eddsa.h
|
||||
do :
|
||||
ac_fn_c_check_header_compile "$LINENO" "nettle/eddsa.h" "ac_cv_header_nettle_eddsa_h" "$ac_includes_default
|
||||
"
|
||||
if test "x$ac_cv_header_nettle_eddsa_h" = xyes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_NETTLE_EDDSA_H 1
|
||||
_ACEOF
|
||||
use_ed25519="yes"
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
fi
|
||||
if test $use_ed25519 = "yes"; then
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define USE_ED25519 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check whether --enable-ed448 was given.
|
||||
if test "${enable_ed448+set}" = set; then :
|
||||
enableval=$enable_ed448;
|
||||
fi
|
||||
|
||||
use_ed448="no"
|
||||
case "$enable_ed448" in
|
||||
no)
|
||||
;;
|
||||
*)
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
ac_fn_c_check_decl "$LINENO" "NID_ED448" "ac_cv_have_decl_NID_ED448" "$ac_includes_default
|
||||
#include <openssl/evp.h>
|
||||
|
||||
"
|
||||
if test "x$ac_cv_have_decl_NID_ED448" = xyes; then :
|
||||
ac_have_decl=1
|
||||
else
|
||||
ac_have_decl=0
|
||||
fi
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_DECL_NID_ED448 $ac_have_decl
|
||||
_ACEOF
|
||||
if test $ac_have_decl = 1; then :
|
||||
|
||||
use_ed448="yes"
|
||||
|
||||
else
|
||||
if test "x$enable_ed448" = "xyes"; then as_fn_error $? "OpenSSL does not support ED448 and you used --enable-ed448." "$LINENO" 5
|
||||
fi
|
||||
fi
|
||||
|
||||
fi
|
||||
if test $use_ed448 = "yes"; then
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define USE_ED448 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check whether --enable-event-api was given.
|
||||
if test "${enable_event_api+set}" = set; then :
|
||||
@@ -18542,6 +18861,70 @@ cat >>confdefs.h <<_ACEOF
|
||||
_ACEOF
|
||||
|
||||
|
||||
# hiredis (redis C client for cachedb)
|
||||
|
||||
# Check whether --with-libhiredis was given.
|
||||
if test "${with_libhiredis+set}" = set; then :
|
||||
withval=$with_libhiredis;
|
||||
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
|
||||
if test x_$withval = x_ -o x_$withval = x_yes; then
|
||||
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
|
||||
fi
|
||||
for dir in $withval ; do
|
||||
if test -f "$dir/include/hiredis/hiredis.h"; then
|
||||
found_libhiredis="yes"
|
||||
if test "$dir" != "/usr"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$dir/include"
|
||||
LDFLAGS="$LDFLAGS -L$dir/lib"
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $dir" >&5
|
||||
$as_echo "found in $dir" >&6; }
|
||||
|
||||
$as_echo "#define USE_REDIS 1" >>confdefs.h
|
||||
|
||||
LIBS="$LIBS -lhiredis"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
if test x_$found_libhiredis != x_yes; then
|
||||
as_fn_error $? "Could not find libhiredis, hiredis.h" "$LINENO" 5
|
||||
fi
|
||||
for ac_header in hiredis/hiredis.h
|
||||
do :
|
||||
ac_fn_c_check_header_compile "$LINENO" "hiredis/hiredis.h" "ac_cv_header_hiredis_hiredis_h" "$ac_includes_default
|
||||
"
|
||||
if test "x$ac_cv_header_hiredis_hiredis_h" = xyes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_HIREDIS_HIREDIS_H 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
ac_fn_c_check_decl "$LINENO" "redisConnect" "ac_cv_have_decl_redisConnect" "$ac_includes_default
|
||||
#include <hiredis/hiredis.h>
|
||||
|
||||
"
|
||||
if test "x$ac_cv_have_decl_redisConnect" = xyes; then :
|
||||
ac_have_decl=1
|
||||
else
|
||||
ac_have_decl=0
|
||||
fi
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_DECL_REDISCONNECT $ac_have_decl
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
# set static linking if requested
|
||||
|
||||
staticexe=""
|
||||
@@ -18555,7 +18938,12 @@ if test x_$enable_static_exe = x_yes; then
|
||||
if test "$on_mingw" = yes; then
|
||||
staticexe="-all-static"
|
||||
# for static compile, include gdi32 and zlib here.
|
||||
LIBS="$LIBS -lgdi32 -lz"
|
||||
if echo $LIBS | grep 'lgdi32' >/dev/null; then
|
||||
:
|
||||
else
|
||||
LIBS="$LIBS -lgdi32"
|
||||
fi
|
||||
LIBS="$LIBS -lz"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -18913,7 +19301,11 @@ if test "$ac_cv_header_windows_h" = "yes"; then
|
||||
$as_echo "#define USE_WINSOCK 1" >>confdefs.h
|
||||
|
||||
USE_WINSOCK="1"
|
||||
LIBS="$LIBS -lws2_32"
|
||||
if echo $LIBS | grep 'lws2_32' >/dev/null; then
|
||||
:
|
||||
else
|
||||
LIBS="$LIBS -lws2_32"
|
||||
fi
|
||||
fi
|
||||
|
||||
else
|
||||
@@ -19077,7 +19469,7 @@ else
|
||||
WINDRES="$ac_cv_prog_WINDRES"
|
||||
fi
|
||||
|
||||
LIBS="$LIBS -liphlpapi"
|
||||
LIBS="$LIBS -liphlpapi -lcrypt32"
|
||||
WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe"
|
||||
|
||||
WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c"
|
||||
@@ -19311,7 +19703,7 @@ if test "$ac_res" != no; then :
|
||||
|
||||
fi
|
||||
|
||||
for ac_func in tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget
|
||||
for ac_func in tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4
|
||||
do :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
@@ -19371,7 +19763,7 @@ done
|
||||
|
||||
|
||||
# check if setreuid en setregid fail, on MacOSX10.4(darwin8).
|
||||
if echo $build_os | grep darwin8 > /dev/null; then
|
||||
if echo $target_os | grep darwin8 > /dev/null; then
|
||||
|
||||
$as_echo "#define DARWIN_BROKEN_SETREUID 1" >>confdefs.h
|
||||
|
||||
@@ -20308,6 +20700,133 @@ else
|
||||
as_fn_error $? "The sodium library was not found. Please install sodium!" "$LINENO" 5
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing crypto_box_curve25519xchacha20poly1305_beforenm" >&5
|
||||
$as_echo_n "checking for library containing crypto_box_curve25519xchacha20poly1305_beforenm... " >&6; }
|
||||
if ${ac_cv_search_crypto_box_curve25519xchacha20poly1305_beforenm+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_func_search_save_LIBS=$LIBS
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char crypto_box_curve25519xchacha20poly1305_beforenm ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return crypto_box_curve25519xchacha20poly1305_beforenm ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
for ac_lib in '' sodium; do
|
||||
if test -z "$ac_lib"; then
|
||||
ac_res="none required"
|
||||
else
|
||||
ac_res=-l$ac_lib
|
||||
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
|
||||
fi
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_search_crypto_box_curve25519xchacha20poly1305_beforenm=$ac_res
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext
|
||||
if ${ac_cv_search_crypto_box_curve25519xchacha20poly1305_beforenm+:} false; then :
|
||||
break
|
||||
fi
|
||||
done
|
||||
if ${ac_cv_search_crypto_box_curve25519xchacha20poly1305_beforenm+:} false; then :
|
||||
|
||||
else
|
||||
ac_cv_search_crypto_box_curve25519xchacha20poly1305_beforenm=no
|
||||
fi
|
||||
rm conftest.$ac_ext
|
||||
LIBS=$ac_func_search_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_crypto_box_curve25519xchacha20poly1305_beforenm" >&5
|
||||
$as_echo "$ac_cv_search_crypto_box_curve25519xchacha20poly1305_beforenm" >&6; }
|
||||
ac_res=$ac_cv_search_crypto_box_curve25519xchacha20poly1305_beforenm
|
||||
if test "$ac_res" != no; then :
|
||||
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
|
||||
|
||||
ENABLE_DNSCRYPT_XCHACHA20=1
|
||||
|
||||
|
||||
$as_echo "#define USE_DNSCRYPT_XCHACHA20 1" >>confdefs.h
|
||||
|
||||
|
||||
else
|
||||
|
||||
ENABLE_DNSCRYPT_XCHACHA20=0
|
||||
|
||||
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sodium_set_misuse_handler" >&5
|
||||
$as_echo_n "checking for library containing sodium_set_misuse_handler... " >&6; }
|
||||
if ${ac_cv_search_sodium_set_misuse_handler+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_func_search_save_LIBS=$LIBS
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char sodium_set_misuse_handler ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return sodium_set_misuse_handler ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
for ac_lib in '' sodium; do
|
||||
if test -z "$ac_lib"; then
|
||||
ac_res="none required"
|
||||
else
|
||||
ac_res=-l$ac_lib
|
||||
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
|
||||
fi
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_search_sodium_set_misuse_handler=$ac_res
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext
|
||||
if ${ac_cv_search_sodium_set_misuse_handler+:} false; then :
|
||||
break
|
||||
fi
|
||||
done
|
||||
if ${ac_cv_search_sodium_set_misuse_handler+:} false; then :
|
||||
|
||||
else
|
||||
ac_cv_search_sodium_set_misuse_handler=no
|
||||
fi
|
||||
rm conftest.$ac_ext
|
||||
LIBS=$ac_func_search_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sodium_set_misuse_handler" >&5
|
||||
$as_echo "$ac_cv_search_sodium_set_misuse_handler" >&6; }
|
||||
ac_res=$ac_cv_search_sodium_set_misuse_handler
|
||||
if test "$ac_res" != no; then :
|
||||
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
|
||||
|
||||
|
||||
$as_echo "#define SODIUM_MISUSE_HANDLER 1" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
$as_echo "#define USE_DNSCRYPT 1" >>confdefs.h
|
||||
@@ -20321,6 +20840,8 @@ $as_echo "#define USE_DNSCRYPT 1" >>confdefs.h
|
||||
|
||||
|
||||
else
|
||||
ENABLE_DNSCRYPT_XCHACHA20=0
|
||||
|
||||
|
||||
ENABLE_DNSCRYPT=0
|
||||
|
||||
@@ -20335,6 +20856,8 @@ if test "${enable_cachedb+set}" = set; then :
|
||||
enableval=$enable_cachedb;
|
||||
fi
|
||||
|
||||
# turn on cachedb when hiredis support is enabled.
|
||||
if test "$found_libhiredis" = "yes"; then enable_cachedb="yes"; fi
|
||||
case "$enable_cachedb" in
|
||||
yes)
|
||||
|
||||
@@ -20346,6 +20869,27 @@ $as_echo "#define USE_CACHEDB 1" >>confdefs.h
|
||||
;;
|
||||
esac
|
||||
|
||||
# check for ipsecmod if requested
|
||||
# Check whether --enable-ipsecmod was given.
|
||||
if test "${enable_ipsecmod+set}" = set; then :
|
||||
enableval=$enable_ipsecmod;
|
||||
fi
|
||||
|
||||
case "$enable_ipsecmod" in
|
||||
yes)
|
||||
|
||||
$as_echo "#define USE_IPSECMOD 1" >>confdefs.h
|
||||
|
||||
IPSECMOD_OBJ="ipsecmod.lo ipsecmod-whitelist.lo"
|
||||
|
||||
IPSECMOD_HEADER='$(srcdir)/ipsecmod/ipsecmod.h $(srcdir)/ipsecmod/ipsecmod-whitelist.h'
|
||||
|
||||
;;
|
||||
no|*)
|
||||
# nothing
|
||||
;;
|
||||
esac
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if ${MAKE:-make} supports $< with implicit rule in scope" >&5
|
||||
$as_echo_n "checking if ${MAKE:-make} supports $< with implicit rule in scope... " >&6; }
|
||||
# on openBSD, the implicit rule make $< work.
|
||||
@@ -20398,6 +20942,15 @@ if test "${with_libunbound_only+set}" = set; then :
|
||||
|
||||
fi
|
||||
|
||||
if test $ALLTARGET = "alltargets"; then
|
||||
if test $USE_NSS = "yes"; then
|
||||
as_fn_error $? "--with-nss can only be used in combination with --with-libunbound-only." "$LINENO" 5
|
||||
fi
|
||||
if test $USE_NETTLE = "yes"; then
|
||||
as_fn_error $? "--with-nettle can only be used in combination with --with-libunbound-only." "$LINENO" 5
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -20477,7 +21030,12 @@ $as_echo "#define OMITTED__D_LARGEFILE_SOURCE_1 1" >>confdefs.h
|
||||
fi
|
||||
|
||||
|
||||
LDFLAGS="$LATE_LDFLAGS $LDFLAGS"
|
||||
if test -n "$LATE_LDFLAGS"; then
|
||||
LDFLAGS="$LATE_LDFLAGS $LDFLAGS"
|
||||
fi
|
||||
# remove start spaces
|
||||
LDFLAGS=`echo "$LDFLAGS"|sed -e 's/^ *//'`
|
||||
LIBS=`echo "$LIBS"|sed -e 's/^ *//'`
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
@@ -20487,7 +21045,7 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
version=1.6.2
|
||||
version=1.7.3
|
||||
|
||||
date=`date +'%b %e, %Y'`
|
||||
|
||||
@@ -21006,7 +21564,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.6.2, which was
|
||||
This file was extended by unbound $as_me 1.7.3, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -21072,7 +21630,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.6.2
|
||||
unbound config.status 1.7.3
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
+200
-19
@@ -10,15 +10,15 @@ sinclude(dnscrypt/dnscrypt.m4)
|
||||
|
||||
# must be numbers. ac_defun because of later processing
|
||||
m4_define([VERSION_MAJOR],[1])
|
||||
m4_define([VERSION_MINOR],[6])
|
||||
m4_define([VERSION_MICRO],[2])
|
||||
m4_define([VERSION_MINOR],[7])
|
||||
m4_define([VERSION_MICRO],[3])
|
||||
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=1
|
||||
LIBUNBOUND_REVISION=11
|
||||
LIBUNBOUND_AGE=5
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@@ -71,6 +71,16 @@ LIBUNBOUND_AGE=5
|
||||
# 1.6.0 had 6:3:4
|
||||
# 1.6.1 had 7:0:5 # ub_callback_t typedef renamed to ub_callback_type
|
||||
# 1.6.2 had 7:1:5
|
||||
# 1.6.3 had 7:2:5
|
||||
# 1.6.4 had 7:3:5
|
||||
# 1.6.5 had 7:4:5
|
||||
# 1.6.6 had 7:5:5
|
||||
# 1.6.7 had 7:6:5
|
||||
# 1.6.8 had 7:7:5
|
||||
# 1.7.0 had 7:8:5
|
||||
# 1.7.1 had 7:9:5
|
||||
# 1.7.2 had 7:10:5
|
||||
# 1.7.3 had 7:11:5
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -86,7 +96,7 @@ LIBUNBOUND_AGE=5
|
||||
# Current and Age. Set Revision to 0, since this is the first
|
||||
# implementation of the new API.
|
||||
#
|
||||
# Otherwise, we're changing the binary API and breaking bakward
|
||||
# Otherwise, we're changing the binary API and breaking backward
|
||||
# compatibility with old binaries. Increment Current. Set Age to 0,
|
||||
# since we're backward compatible with no previous APIs. Set Revision
|
||||
# to 0 too.
|
||||
@@ -108,6 +118,11 @@ case "$prefix" in
|
||||
prefix="/usr/local"
|
||||
;;
|
||||
esac
|
||||
case "$exec_prefix" in
|
||||
NONE)
|
||||
exec_prefix="$prefix"
|
||||
;;
|
||||
esac
|
||||
|
||||
# are we on MinGW?
|
||||
if uname -s 2>&1 | grep MINGW32 >/dev/null; then on_mingw="yes"
|
||||
@@ -119,6 +134,12 @@ fi
|
||||
#
|
||||
# Determine configuration file
|
||||
# the eval is to evaluate shell expansion twice
|
||||
UNBOUND_SBIN_DIR=`eval echo "${sbindir}"`
|
||||
AC_SUBST(UNBOUND_SBIN_DIR)
|
||||
UNBOUND_SYSCONF_DIR=`eval echo "${sysconfdir}"`
|
||||
AC_SUBST(UNBOUND_SYSCONF_DIR)
|
||||
UNBOUND_LOCALSTATE_DIR=`eval echo "${localstatedir}"`
|
||||
AC_SUBST(UNBOUND_LOCALSTATE_DIR)
|
||||
if test $on_mingw = "no"; then
|
||||
ub_conf_file=`eval echo "${sysconfdir}/unbound/unbound.conf"`
|
||||
else
|
||||
@@ -229,9 +250,11 @@ AC_DEFINE_UNQUOTED(RSRC_PACKAGE_VERSION, [$wnvs], [version number for resource f
|
||||
AC_C_CONST
|
||||
AC_LANG_C
|
||||
# allow user to override the -g -O2 flags.
|
||||
default_cflags=no
|
||||
if test "x$CFLAGS" = "x" ; then
|
||||
ACX_CHECK_COMPILER_FLAG(g, [CFLAGS="$CFLAGS -g"])
|
||||
ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"])
|
||||
default_cflags=yes
|
||||
fi
|
||||
AC_PROG_CC
|
||||
ACX_DEPFLAG
|
||||
@@ -255,9 +278,14 @@ case "$debug_enabled" in
|
||||
# nothing to do.
|
||||
;;
|
||||
esac
|
||||
ACX_CHECK_FLTO
|
||||
ACX_CHECK_PIE
|
||||
ACX_CHECK_RELRO_NOW
|
||||
if test "$default_cflags" = "yes"; then
|
||||
# only when CFLAGS was "" at the start, if the users wants to
|
||||
# override we shouldn't add default cflags, because they wouldn't
|
||||
# be able to turn off these options and set the CFLAGS wanted.
|
||||
ACX_CHECK_FLTO
|
||||
ACX_CHECK_PIE
|
||||
ACX_CHECK_RELRO_NOW
|
||||
fi
|
||||
|
||||
AC_C_INLINE
|
||||
ACX_CHECK_FORMAT_ATTRIBUTE
|
||||
@@ -306,7 +334,7 @@ AC_CHECK_TOOL(STRIP, strip)
|
||||
ACX_LIBTOOL_C_ONLY
|
||||
|
||||
# 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/ipc.h sys/shm.h],,, [AC_INCLUDES_DEFAULT])
|
||||
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])
|
||||
|
||||
# check for types.
|
||||
# Using own tests for int64* because autoconf builtin only give 32bit.
|
||||
@@ -442,7 +470,9 @@ ub_have_pthreads=no
|
||||
if test x_$withval != x_no; then
|
||||
AX_PTHREAD([
|
||||
AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.])
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
if test -n "$PTHREAD_LIBS"; then
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
fi
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
CC="$PTHREAD_CC"
|
||||
ub_have_pthreads=yes
|
||||
@@ -544,15 +574,28 @@ if test x_$ub_test_python != x_no; then
|
||||
AC_SUBST(PY_MAJOR_VERSION)
|
||||
# Have Python
|
||||
AC_DEFINE(HAVE_PYTHON,1,[Define if you have Python libraries and header files.])
|
||||
LIBS="$PYTHON_LDFLAGS $LIBS"
|
||||
CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS"
|
||||
if test -n "$LIBS"; then
|
||||
LIBS="$PYTHON_LDFLAGS $LIBS"
|
||||
else
|
||||
LIBS="$PYTHON_LDFLAGS"
|
||||
fi
|
||||
if test -n "$CPPFLAGS"; then
|
||||
CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS"
|
||||
else
|
||||
CPPFLAGS="$PYTHON_CPPFLAGS"
|
||||
fi
|
||||
ub_have_python=yes
|
||||
PC_PY_DEPENDENCY="python"
|
||||
AC_SUBST(PC_PY_DEPENDENCY)
|
||||
|
||||
# Check for SWIG
|
||||
ub_have_swig=no
|
||||
AC_PROG_SWIG(2.0.1)
|
||||
AC_ARG_ENABLE(swig-version-check, AC_HELP_STRING([--disable-swig-version-check], [Disable swig version check to build python modules with older swig even though that is unreliable]))
|
||||
if test "$enable_swig_version_check" = "yes"; then
|
||||
AC_PROG_SWIG(2.0.1)
|
||||
else
|
||||
AC_PROG_SWIG
|
||||
fi
|
||||
AC_MSG_CHECKING(SWIG)
|
||||
if test ! -x "$SWIG"; then
|
||||
AC_ERROR([failed to find swig tool, install it, or do not build Python module and PyUnbound])
|
||||
@@ -679,12 +722,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])
|
||||
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])
|
||||
|
||||
# these check_funcs need -lssl
|
||||
BAKLIBS="$LIBS"
|
||||
LIBS="-lssl $LIBS"
|
||||
AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level])
|
||||
AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername])
|
||||
LIBS="$BAKLIBS"
|
||||
|
||||
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
|
||||
@@ -898,13 +941,79 @@ case "$enable_dsa" in
|
||||
;;
|
||||
*)
|
||||
# detect if DSA is supported, and turn it off if not.
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
AC_CHECK_FUNC(DSA_SIG_new, [
|
||||
AC_CHECK_TYPE(DSA_SIG*, [
|
||||
AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.])
|
||||
], [if test "x$enable_dsa" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support DSA and you used --enable-dsa.])
|
||||
fi ], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_RAND_H
|
||||
#include <openssl/rand.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_CONF_H
|
||||
#include <openssl/conf.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_ENGINE_H
|
||||
#include <openssl/engine.h>
|
||||
#endif
|
||||
])
|
||||
], [if test "x$enable_dsa" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support DSA and you used --enable-dsa.])
|
||||
fi ])
|
||||
else
|
||||
AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(ed25519, AC_HELP_STRING([--disable-ed25519], [Disable ED25519 support]))
|
||||
use_ed25519="no"
|
||||
case "$enable_ed25519" in
|
||||
no)
|
||||
;;
|
||||
*)
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
AC_CHECK_DECLS([NID_ED25519], [
|
||||
use_ed25519="yes"
|
||||
], [ if test "x$enable_ed25519" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support ED25519 and you used --enable-ed25519.])
|
||||
fi ], [AC_INCLUDES_DEFAULT
|
||||
#include <openssl/evp.h>
|
||||
])
|
||||
fi
|
||||
if test $USE_NETTLE = "yes"; then
|
||||
AC_CHECK_HEADERS([nettle/eddsa.h], use_ed25519="yes",, [AC_INCLUDES_DEFAULT])
|
||||
fi
|
||||
if test $use_ed25519 = "yes"; then
|
||||
AC_DEFINE_UNQUOTED([USE_ED25519], [1], [Define this to enable ED25519 support.])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(ed448, AC_HELP_STRING([--disable-ed448], [Disable ED448 support]))
|
||||
use_ed448="no"
|
||||
case "$enable_ed448" in
|
||||
no)
|
||||
;;
|
||||
*)
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
AC_CHECK_DECLS([NID_ED448], [
|
||||
use_ed448="yes"
|
||||
], [ if test "x$enable_ed448" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support ED448 and you used --enable-ed448.])
|
||||
fi ], [AC_INCLUDES_DEFAULT
|
||||
#include <openssl/evp.h>
|
||||
])
|
||||
fi
|
||||
if test $use_ed448 = "yes"; then
|
||||
AC_DEFINE_UNQUOTED([USE_ED448], [1], [Define this to enable ED448 support.])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(event-api, AC_HELP_STRING([--enable-event-api], [Enable (experimental) pluggable event base libunbound API installed to unbound-event.h]))
|
||||
case "$enable_event_api" in
|
||||
@@ -1064,6 +1173,39 @@ AC_CHECK_DECLS([XML_StopParser], [], [], [AC_INCLUDES_DEFAULT
|
||||
#include <expat.h>
|
||||
])
|
||||
|
||||
# hiredis (redis C client for cachedb)
|
||||
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
|
||||
if test x_$withval = x_ -o x_$withval = x_yes; then
|
||||
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
|
||||
fi
|
||||
for dir in $withval ; do
|
||||
if test -f "$dir/include/hiredis/hiredis.h"; then
|
||||
found_libhiredis="yes"
|
||||
dnl assume /usr is in default path.
|
||||
if test "$dir" != "/usr"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$dir/include"
|
||||
LDFLAGS="$LDFLAGS -L$dir/lib"
|
||||
fi
|
||||
AC_MSG_RESULT(found in $dir)
|
||||
AC_DEFINE([USE_REDIS], [1], [Define this to use hiredis client.])
|
||||
LIBS="$LIBS -lhiredis"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
if test x_$found_libhiredis != x_yes; then
|
||||
AC_ERROR([Could not find libhiredis, hiredis.h])
|
||||
fi
|
||||
AC_CHECK_HEADERS([hiredis/hiredis.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_DECLS([redisConnect], [], [], [AC_INCLUDES_DEFAULT
|
||||
#include <hiredis/hiredis.h>
|
||||
])
|
||||
fi
|
||||
|
||||
# set static linking if requested
|
||||
AC_SUBST(staticexe)
|
||||
staticexe=""
|
||||
@@ -1075,7 +1217,12 @@ if test x_$enable_static_exe = x_yes; then
|
||||
if test "$on_mingw" = yes; then
|
||||
staticexe="-all-static"
|
||||
# for static compile, include gdi32 and zlib here.
|
||||
LIBS="$LIBS -lgdi32 -lz"
|
||||
if echo $LIBS | grep 'lgdi32' >/dev/null; then
|
||||
:
|
||||
else
|
||||
LIBS="$LIBS -lgdi32"
|
||||
fi
|
||||
LIBS="$LIBS -lz"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1100,7 +1247,7 @@ if test "$USE_WINSOCK" = 1; then
|
||||
#include <windows.h>
|
||||
])
|
||||
AC_CHECK_TOOL(WINDRES, windres)
|
||||
LIBS="$LIBS -liphlpapi"
|
||||
LIBS="$LIBS -liphlpapi -lcrypt32"
|
||||
WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe"
|
||||
AC_SUBST(WINAPPS)
|
||||
WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c"
|
||||
@@ -1173,12 +1320,12 @@ AC_INCLUDES_DEFAULT
|
||||
#endif
|
||||
])
|
||||
AC_SEARCH_LIBS([setusercontext], [util])
|
||||
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget])
|
||||
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4])
|
||||
AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])])
|
||||
AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
|
||||
|
||||
# check if setreuid en setregid fail, on MacOSX10.4(darwin8).
|
||||
if echo $build_os | grep darwin8 > /dev/null; then
|
||||
if echo $target_os | grep darwin8 > /dev/null; then
|
||||
AC_DEFINE(DARWIN_BROKEN_SETREUID, 1, [Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work])
|
||||
fi
|
||||
AC_CHECK_DECLS([inet_pton,inet_ntop], [], [], [
|
||||
@@ -1343,6 +1490,8 @@ dnsc_DNSCRYPT([
|
||||
|
||||
# check for cachedb if requested
|
||||
AC_ARG_ENABLE(cachedb, AC_HELP_STRING([--enable-cachedb], [enable cachedb module that can use external cache storage]))
|
||||
# turn on cachedb when hiredis support is enabled.
|
||||
if test "$found_libhiredis" = "yes"; then enable_cachedb="yes"; fi
|
||||
case "$enable_cachedb" in
|
||||
yes)
|
||||
AC_DEFINE([USE_CACHEDB], [1], [Define to 1 to use cachedb support])
|
||||
@@ -1352,6 +1501,21 @@ case "$enable_cachedb" in
|
||||
;;
|
||||
esac
|
||||
|
||||
# check for ipsecmod if requested
|
||||
AC_ARG_ENABLE(ipsecmod, AC_HELP_STRING([--enable-ipsecmod], [Enable ipsecmod module that facilitates opportunistic IPsec]))
|
||||
case "$enable_ipsecmod" in
|
||||
yes)
|
||||
AC_DEFINE([USE_IPSECMOD], [1], [Define to 1 to use ipsecmod support.])
|
||||
IPSECMOD_OBJ="ipsecmod.lo ipsecmod-whitelist.lo"
|
||||
AC_SUBST(IPSECMOD_OBJ)
|
||||
IPSECMOD_HEADER='$(srcdir)/ipsecmod/ipsecmod.h $(srcdir)/ipsecmod/ipsecmod-whitelist.h'
|
||||
AC_SUBST(IPSECMOD_HEADER)
|
||||
;;
|
||||
no|*)
|
||||
# nothing
|
||||
;;
|
||||
esac
|
||||
|
||||
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).
|
||||
@@ -1398,11 +1562,25 @@ AC_ARG_WITH(libunbound-only, AC_HELP_STRING([--with-libunbound-only],
|
||||
INSTALLTARGET="install-lib"
|
||||
fi
|
||||
])
|
||||
if test $ALLTARGET = "alltargets"; then
|
||||
if test $USE_NSS = "yes"; then
|
||||
AC_ERROR([--with-nss can only be used in combination with --with-libunbound-only.])
|
||||
fi
|
||||
if test $USE_NETTLE = "yes"; then
|
||||
AC_ERROR([--with-nettle can only be used in combination with --with-libunbound-only.])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(ALLTARGET)
|
||||
AC_SUBST(INSTALLTARGET)
|
||||
|
||||
ACX_STRIP_EXT_FLAGS
|
||||
LDFLAGS="$LATE_LDFLAGS $LDFLAGS"
|
||||
if test -n "$LATE_LDFLAGS"; then
|
||||
LDFLAGS="$LATE_LDFLAGS $LDFLAGS"
|
||||
fi
|
||||
# remove start spaces
|
||||
LDFLAGS=`echo "$LDFLAGS"|sed -e 's/^ *//'`
|
||||
LIBS=`echo "$LIBS"|sed -e 's/^ *//'`
|
||||
|
||||
AC_DEFINE_UNQUOTED([MAXSYSLOGMSGLEN], [10240], [Define to the maximum message length to pass to syslog.])
|
||||
|
||||
@@ -1566,6 +1744,7 @@ uint32_t arc4random(void);
|
||||
void arc4random_buf(void* buf, size_t n);
|
||||
void _ARC4_LOCK(void);
|
||||
void _ARC4_UNLOCK(void);
|
||||
void _ARC4_LOCK_DESTROY(void);
|
||||
#endif
|
||||
#ifndef HAVE_ARC4RANDOM_UNIFORM
|
||||
uint32_t arc4random_uniform(uint32_t upper_bound);
|
||||
@@ -1631,6 +1810,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
||||
|
||||
/** default port for DNS traffic. */
|
||||
#define UNBOUND_DNS_PORT 53
|
||||
/** default port for DNS over TLS traffic. */
|
||||
#define UNBOUND_DNS_OVER_TLS_PORT 853
|
||||
/** default port for unbound control traffic, registered port with IANA,
|
||||
ub-dns-control 8953/tcp unbound dns nameserver control */
|
||||
#define UNBOUND_CONTROL_PORT 8953
|
||||
|
||||
@@ -31,3 +31,10 @@ distribution but may be helpful.
|
||||
Contributed by Yuri Voinov.
|
||||
* unbound.socket and unbound.service: systemd files for unbound, install them
|
||||
in /usr/lib/systemd/system. Contributed by Sami Kerola and Pavel Odintsov.
|
||||
* redirect-bogus.patch: Return configured address for bogus A and AAAA answers,
|
||||
instead of SERVFAIL. Contributed by SIDN.
|
||||
* fastrpz.patch: fastrpz support from Farsight Security.
|
||||
* libunbound.so.conf: ltrace.conf file, see ltrace.conf(5), for libunbound.
|
||||
* 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.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
Index: trunk/doc/unbound.conf.5.in
|
||||
===================================================================
|
||||
--- trunk/doc/unbound.conf.5.in (revision 3587)
|
||||
--- trunk/doc/unbound.conf.5.in (revision 4357)
|
||||
+++ trunk/doc/unbound.conf.5.in (working copy)
|
||||
@@ -593,6 +593,13 @@
|
||||
possible. Best effort approach, full QNAME and original QTYPE will be sent when
|
||||
upstream replies with a RCODE other than NOERROR. Default is off.
|
||||
@@ -701,6 +701,13 @@
|
||||
this option in enabled. Only use if you know what you are doing.
|
||||
This option only has effect when qname-minimisation is enabled. Default is off.
|
||||
.TP
|
||||
+.B aaaa\-filter: \fI<yes or no>
|
||||
+Activate behavior similar to BIND's AAAA-filter.
|
||||
@@ -18,7 +18,7 @@ Index: trunk/doc/unbound.conf.5.in
|
||||
on your private network, and are not allowed to be returned for
|
||||
Index: trunk/iterator/iter_scrub.c
|
||||
===================================================================
|
||||
--- trunk/iterator/iter_scrub.c (revision 3587)
|
||||
--- trunk/iterator/iter_scrub.c (revision 4357)
|
||||
+++ trunk/iterator/iter_scrub.c (working copy)
|
||||
@@ -617,6 +617,32 @@
|
||||
}
|
||||
@@ -75,10 +75,11 @@ Index: trunk/iterator/iter_scrub.c
|
||||
/* At this point, we brutally remove ALL rrsets that aren't
|
||||
* children of the originating zone. The idea here is that,
|
||||
* as far as we know, the server that we contacted is ONLY
|
||||
@@ -681,6 +715,24 @@
|
||||
@@ -680,6 +714,24 @@
|
||||
prev = NULL;
|
||||
rrset = msg->rrset_first;
|
||||
while(rrset) {
|
||||
|
||||
+
|
||||
+ /* ASN: For AAAA records only... */
|
||||
+ if((ie->aaaa_filter) && (rrset->type == LDNS_RR_TYPE_AAAA)) {
|
||||
+ /* ASN: If this is not a AAAA query, then remove AAAA
|
||||
@@ -96,13 +97,12 @@ Index: trunk/iterator/iter_scrub.c
|
||||
+ LDNS_RR_TYPE_AAAA, qinfo->qclass);
|
||||
+ }
|
||||
+ /* ASN: End of added code */
|
||||
+
|
||||
|
||||
/* remove private addresses */
|
||||
if( (rrset->type == LDNS_RR_TYPE_A ||
|
||||
rrset->type == LDNS_RR_TYPE_AAAA)) {
|
||||
Index: trunk/iterator/iter_utils.c
|
||||
===================================================================
|
||||
--- trunk/iterator/iter_utils.c (revision 3587)
|
||||
--- trunk/iterator/iter_utils.c (revision 4357)
|
||||
+++ trunk/iterator/iter_utils.c (working copy)
|
||||
@@ -175,6 +175,7 @@
|
||||
}
|
||||
@@ -114,9 +114,9 @@ Index: trunk/iterator/iter_utils.c
|
||||
|
||||
Index: trunk/iterator/iterator.c
|
||||
===================================================================
|
||||
--- trunk/iterator/iterator.c (revision 3587)
|
||||
--- trunk/iterator/iterator.c (revision 4357)
|
||||
+++ trunk/iterator/iterator.c (working copy)
|
||||
@@ -1776,6 +1776,53 @@
|
||||
@@ -1847,6 +1847,53 @@
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -170,7 +170,7 @@ Index: trunk/iterator/iterator.c
|
||||
|
||||
/**
|
||||
* This is the request event state where the request will be sent to one of
|
||||
@@ -1823,6 +1870,13 @@
|
||||
@@ -1894,6 +1941,13 @@
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ Index: trunk/iterator/iterator.c
|
||||
/* Make sure we have a delegation point, otherwise priming failed
|
||||
* or another failure occurred */
|
||||
if(!iq->dp) {
|
||||
@@ -2922,6 +2976,61 @@
|
||||
@@ -3095,6 +3149,61 @@
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -244,9 +244,9 @@ Index: trunk/iterator/iterator.c
|
||||
+/* ASN: End of added code */
|
||||
+
|
||||
/*
|
||||
* Return priming query results to interestes super querystates.
|
||||
* Return priming query results to interested super querystates.
|
||||
*
|
||||
@@ -2941,6 +3050,9 @@
|
||||
@@ -3114,6 +3223,9 @@
|
||||
else if(super->qinfo.qtype == LDNS_RR_TYPE_DS && ((struct iter_qstate*)
|
||||
super->minfo[id])->state == DSNS_FIND_STATE)
|
||||
processDSNSResponse(qstate, id, super);
|
||||
@@ -256,7 +256,7 @@ Index: trunk/iterator/iterator.c
|
||||
else if(qstate->return_rcode != LDNS_RCODE_NOERROR)
|
||||
error_supers(qstate, id, super);
|
||||
else if(qstate->is_priming)
|
||||
@@ -2978,6 +3090,9 @@
|
||||
@@ -3151,6 +3263,9 @@
|
||||
case INIT_REQUEST_3_STATE:
|
||||
cont = processInitRequest3(qstate, iq, id);
|
||||
break;
|
||||
@@ -266,7 +266,7 @@ Index: trunk/iterator/iterator.c
|
||||
case QUERYTARGETS_STATE:
|
||||
cont = processQueryTargets(qstate, iq, ie, id);
|
||||
break;
|
||||
@@ -3270,6 +3385,8 @@
|
||||
@@ -3460,6 +3575,8 @@
|
||||
return "INIT REQUEST STATE (stage 2)";
|
||||
case INIT_REQUEST_3_STATE:
|
||||
return "INIT REQUEST STATE (stage 3)";
|
||||
@@ -275,7 +275,7 @@ Index: trunk/iterator/iterator.c
|
||||
case QUERYTARGETS_STATE :
|
||||
return "QUERY TARGETS STATE";
|
||||
case PRIME_RESP_STATE :
|
||||
@@ -3294,6 +3411,7 @@
|
||||
@@ -3484,6 +3601,7 @@
|
||||
case INIT_REQUEST_STATE :
|
||||
case INIT_REQUEST_2_STATE :
|
||||
case INIT_REQUEST_3_STATE :
|
||||
@@ -285,19 +285,19 @@ Index: trunk/iterator/iterator.c
|
||||
return 0;
|
||||
Index: trunk/iterator/iterator.h
|
||||
===================================================================
|
||||
--- trunk/iterator/iterator.h (revision 3587)
|
||||
--- trunk/iterator/iterator.h (revision 4357)
|
||||
+++ trunk/iterator/iterator.h (working copy)
|
||||
@@ -113,6 +113,9 @@
|
||||
@@ -130,6 +130,9 @@
|
||||
*/
|
||||
int* target_fetch_policy;
|
||||
|
||||
+ /** ASN: AAAA-filter flag */
|
||||
+ int aaaa_filter;
|
||||
+
|
||||
/** ip6.arpa dname in wireformat, used for qname-minimisation */
|
||||
uint8_t* ip6arpa_dname;
|
||||
};
|
||||
@@ -163,6 +166,14 @@
|
||||
/** lock on ratelimit counter */
|
||||
lock_basic_type queries_ratelimit_lock;
|
||||
/** number of queries that have been ratelimited */
|
||||
@@ -182,6 +185,14 @@
|
||||
INIT_REQUEST_3_STATE,
|
||||
|
||||
/**
|
||||
@@ -311,26 +311,26 @@ Index: trunk/iterator/iterator.h
|
||||
+ /**
|
||||
* Each time a delegation point changes for a given query or a
|
||||
* query times out and/or wakes up, this state is (re)visited.
|
||||
* This state is reponsible for iterating through a list of
|
||||
@@ -346,6 +357,13 @@
|
||||
* This state is responsible for iterating through a list of
|
||||
@@ -364,6 +375,13 @@
|
||||
* be used when creating the state. A higher one will be attempted.
|
||||
*/
|
||||
int refetch_glue;
|
||||
|
||||
+
|
||||
+ /**
|
||||
+ * ASN: This is a flag that, if true, means that this query is
|
||||
+ * for fetching A records to populate cache and determine if we must
|
||||
+ * return AAAA records or not.
|
||||
+ */
|
||||
+ int fetch_a_for_aaaa;
|
||||
+
|
||||
|
||||
/** list of pending queries to authoritative servers. */
|
||||
struct outbound_list outlist;
|
||||
|
||||
Index: trunk/pythonmod/interface.i
|
||||
===================================================================
|
||||
--- trunk/pythonmod/interface.i (revision 3587)
|
||||
--- trunk/pythonmod/interface.i (revision 4357)
|
||||
+++ trunk/pythonmod/interface.i (working copy)
|
||||
@@ -632,6 +632,7 @@
|
||||
@@ -851,6 +851,7 @@
|
||||
int harden_dnssec_stripped;
|
||||
int harden_referral_path;
|
||||
int use_caps_bits_for_id;
|
||||
@@ -340,9 +340,9 @@ Index: trunk/pythonmod/interface.i
|
||||
size_t unwanted_threshold;
|
||||
Index: trunk/util/config_file.c
|
||||
===================================================================
|
||||
--- trunk/util/config_file.c (revision 3587)
|
||||
--- trunk/util/config_file.c (revision 4357)
|
||||
+++ trunk/util/config_file.c (working copy)
|
||||
@@ -176,6 +176,7 @@
|
||||
@@ -195,6 +195,7 @@
|
||||
cfg->harden_referral_path = 0;
|
||||
cfg->harden_algo_downgrade = 0;
|
||||
cfg->use_caps_bits_for_id = 0;
|
||||
@@ -352,9 +352,9 @@ Index: trunk/util/config_file.c
|
||||
cfg->private_domain = NULL;
|
||||
Index: trunk/util/config_file.h
|
||||
===================================================================
|
||||
--- trunk/util/config_file.h (revision 3587)
|
||||
--- trunk/util/config_file.h (revision 4357)
|
||||
+++ trunk/util/config_file.h (working copy)
|
||||
@@ -179,6 +179,8 @@
|
||||
@@ -209,6 +209,8 @@
|
||||
int harden_algo_downgrade;
|
||||
/** use 0x20 bits in query as random ID bits */
|
||||
int use_caps_bits_for_id;
|
||||
@@ -365,9 +365,9 @@ Index: trunk/util/config_file.h
|
||||
/** strip away these private addrs from answers, no DNS Rebinding */
|
||||
Index: trunk/util/configlexer.lex
|
||||
===================================================================
|
||||
--- trunk/util/configlexer.lex (revision 3587)
|
||||
--- trunk/util/configlexer.lex (revision 4357)
|
||||
+++ trunk/util/configlexer.lex (working copy)
|
||||
@@ -267,6 +267,7 @@
|
||||
@@ -279,6 +279,7 @@
|
||||
use-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) }
|
||||
caps-whitelist{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
|
||||
unwanted-reply-threshold{COLON} { YDVAR(1, VAR_UNWANTED_REPLY_THRESHOLD) }
|
||||
@@ -377,9 +377,9 @@ Index: trunk/util/configlexer.lex
|
||||
prefetch-key{COLON} { YDVAR(1, VAR_PREFETCH_KEY) }
|
||||
Index: trunk/util/configparser.y
|
||||
===================================================================
|
||||
--- trunk/util/configparser.y (revision 3587)
|
||||
--- trunk/util/configparser.y (revision 4357)
|
||||
+++ trunk/util/configparser.y (working copy)
|
||||
@@ -92,6 +92,7 @@
|
||||
@@ -95,6 +95,7 @@
|
||||
%token VAR_STATISTICS_CUMULATIVE VAR_OUTGOING_PORT_PERMIT
|
||||
%token VAR_OUTGOING_PORT_AVOID VAR_DLV_ANCHOR_FILE VAR_DLV_ANCHOR
|
||||
%token VAR_NEG_CACHE_SIZE VAR_HARDEN_REFERRAL_PATH VAR_PRIVATE_ADDRESS
|
||||
@@ -387,7 +387,7 @@ Index: trunk/util/configparser.y
|
||||
%token VAR_PRIVATE_DOMAIN VAR_REMOTE_CONTROL VAR_CONTROL_ENABLE
|
||||
%token VAR_CONTROL_INTERFACE VAR_CONTROL_PORT VAR_SERVER_KEY_FILE
|
||||
%token VAR_SERVER_CERT_FILE VAR_CONTROL_KEY_FILE VAR_CONTROL_CERT_FILE
|
||||
@@ -169,6 +170,7 @@
|
||||
@@ -203,6 +204,7 @@
|
||||
server_dlv_anchor_file | server_dlv_anchor | server_neg_cache_size |
|
||||
server_harden_referral_path | server_private_address |
|
||||
server_private_domain | server_extended_statistics |
|
||||
@@ -395,10 +395,12 @@ Index: trunk/util/configparser.y
|
||||
server_local_data_ptr | server_jostle_timeout |
|
||||
server_unwanted_reply_threshold | server_log_time_ascii |
|
||||
server_domain_insecure | server_val_sig_skew_min |
|
||||
@@ -893,6 +895,15 @@
|
||||
@@ -1183,6 +1185,15 @@
|
||||
OUTYY(("P(server_caps_whitelist:%s)\n", $2));
|
||||
if(!cfg_strlist_insert(&cfg_parser->cfg->caps_whitelist, $2))
|
||||
yyerror("out of memory");
|
||||
}
|
||||
;
|
||||
+ }
|
||||
+ ;
|
||||
+server_aaaa_filter: VAR_AAAA_FILTER STRING_ARG
|
||||
+ {
|
||||
+ OUTYY(("P(server_aaaa_filter:%s)\n", $2));
|
||||
@@ -406,8 +408,6 @@ Index: trunk/util/configparser.y
|
||||
+ yyerror("expected yes or no.");
|
||||
+ else cfg_parser->cfg->aaaa_filter = (strcmp($2, "yes")==0);
|
||||
+ free($2);
|
||||
+ }
|
||||
+ ;
|
||||
}
|
||||
;
|
||||
server_private_address: VAR_PRIVATE_ADDRESS STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_private_address:%s)\n", $2));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ Name: unbound
|
||||
Description: Library with validating, recursive, and caching DNS resolver
|
||||
URL: http://www.unbound.net
|
||||
Version: @PACKAGE_VERSION@
|
||||
Requires: libcrypto libssl @PC_LIBEVENT_DEPENDENCY@ @PC_PY_DEPENDENCY@
|
||||
Libs: -L${libdir} -lunbound
|
||||
Requires: @PC_LIBEVENT_DEPENDENCY@ @PC_PY_DEPENDENCY@
|
||||
Libs: -L${libdir} -lunbound -lssl -lcrypto
|
||||
Libs.private: @SSLLIB@ @LIBS@
|
||||
Cflags: -I${includedir}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# See ltrace.conf(5) for description of syntax of this file.
|
||||
typedef ub_type = enum(TYPE_A=1,TYPE_NS=2,TYPE_SOA=6,TYPE_MX=15,TYPE_TXT=16,TYPE_AAAA=28,TYPE_DS=43,TYPE_DNSKEY=48,TYPE_TLSA=52,TYPE_ANY=255);
|
||||
typedef ub_class = enum(CLASS_IN=1,CLASS_CH=3,CLASS_NONE=254,CLASS_ANY=255);
|
||||
typedef ub_rcode = enum(RCODE_NOERROR,RCODE_FORMERR,RCODE_SERVFAIL,RCODE_NXDOMAIN,RCODE_NOTIMPL,RCODE_REFUSED,RCODE_YXDOMAIN,RCODE_YXRRSET,RCODE_NXRRSET,RCODE_NOTAUTH,RCODE_NOTZONE);
|
||||
typedef ub_havedata = enum(no_data, have_data);
|
||||
typedef ub_nxdomain = enum(name_exists, nxdomain);
|
||||
typedef ub_secure = enum(not_secure, secure);
|
||||
typedef ub_bogus = enum(not_bogus, bogus);
|
||||
typedef ub_result = struct(string, ub_type, ub_class, array(void*,zero)*, array(int,zero)*, string, ub_rcode, void*, int, ub_havedata, ub_nxdomain, ub_secure, ub_bogus, string, int);
|
||||
typedef ub_ctx = void;
|
||||
ub_ctx* ub_ctx_create(void);
|
||||
void ub_ctx_delete(ub_ctx*);
|
||||
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_stub(ub_ctx*, string, string, bool(int));
|
||||
int ub_ctx_resolvconf(ub_ctx*, string);
|
||||
int ub_ctx_hosts(ub_ctx*, string);
|
||||
int ub_ctx_add_ta(ub_ctx*, string);
|
||||
int ub_ctx_add_ta_file(ub_ctx*, string);
|
||||
int ub_ctx_add_ta_autr(ub_ctx*, string);
|
||||
int ub_ctx_trustedkeys(ub_ctx*, string);
|
||||
int ub_ctx_debugout(ub_ctx*, void*);
|
||||
int ub_ctx_debuglevel(ub_ctx*, int);
|
||||
int ub_ctx_async(ub_ctx*, bool(int));
|
||||
int ub_poll(ub_ctx*);
|
||||
int ub_wait(ub_ctx*);
|
||||
int ub_fd(ub_ctx*);
|
||||
int ub_process(ub_ctx*);
|
||||
int ub_resolve(ub_ctx*, string, ub_type, ub_class, +ub_result**);
|
||||
int ub_resolve_async(ub_ctx*, string, ub_type, ub_class, void*, void*, +int*);
|
||||
int ub_cancel(ub_ctx*, int);
|
||||
void ub_resolve_free(ub_result*);
|
||||
string ub_strerror(int);
|
||||
int ub_ctx_print_local_zones(ub_ctx*);
|
||||
int ub_ctx_zone_add(ub_ctx*, string, string);
|
||||
int ub_ctx_zone_remove(ub_ctx*, string);
|
||||
int ub_ctx_data_add(ub_ctx*, string);
|
||||
int ub_ctx_data_remove(ub_ctx*, string);
|
||||
string ub_version(void);
|
||||
@@ -91,7 +91,7 @@ while ( scalar keys %startstats < $numthreads || scalar keys %donestats < $numth
|
||||
$allstats{$inthread}->{outstandingexc} = $4;
|
||||
}
|
||||
elsif ( $line =~ m/info: average recursion processing time ([0-9\.]+) sec/ ) {
|
||||
$allstats{$inthread}->{recursionavg} = int($1 * 1000); # change sec to milisec.
|
||||
$allstats{$inthread}->{recursionavg} = int($1 * 1000); # change sec to millisec.
|
||||
}
|
||||
elsif ( $line =~ m/info: histogram of recursion processing times/ ) {
|
||||
next;
|
||||
@@ -103,7 +103,7 @@ while ( scalar keys %startstats < $numthreads || scalar keys %donestats < $numth
|
||||
}
|
||||
elsif ( $line =~ m/info: lower\(secs\) upper\(secs\) recursions/ ) {
|
||||
# since after this line we're unsure if we get these numbers
|
||||
# at all, we sould consider this marker as the end of the
|
||||
# at all, we should consider this marker as the end of the
|
||||
# block. Chances that we're parsing a file halfway written
|
||||
# at this stage are small. Bold statement.
|
||||
$donestats{$inthread} = 1;
|
||||
|
||||
@@ -0,0 +1,344 @@
|
||||
Index: daemon/worker.c
|
||||
===================================================================
|
||||
--- daemon/worker.c (revision 4191)
|
||||
+++ daemon/worker.c (working copy)
|
||||
@@ -663,8 +663,21 @@
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, rep,
|
||||
LDNS_RCODE_SERVFAIL, edns, worker->scratchpad))
|
||||
goto bail_out;
|
||||
- error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
- qinfo, id, flags, edns);
|
||||
+ if (qinfo->qtype == LDNS_RR_TYPE_A &&
|
||||
+ worker->env.cfg->redirect_bogus_ipv4) {
|
||||
+ /* BAD cached */
|
||||
+ fixed_address_encode(repinfo->c->buffer,
|
||||
+ LDNS_RCODE_NOERROR, qinfo, id, flags, edns,
|
||||
+ worker->env.cfg->redirect_bogus_ipv4);
|
||||
+ } else if (qinfo->qtype == LDNS_RR_TYPE_AAAA &&
|
||||
+ worker->env.cfg->redirect_bogus_ipv6) {
|
||||
+ fixed_address_encode(repinfo->c->buffer,
|
||||
+ LDNS_RCODE_NOERROR, qinfo, id, flags, edns,
|
||||
+ worker->env.cfg->redirect_bogus_ipv6);
|
||||
+ } else {
|
||||
+ error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
+ qinfo, id, flags, edns);
|
||||
+ }
|
||||
rrset_array_unlock_touch(worker->env.rrset_cache,
|
||||
worker->scratchpad, rep->ref, rep->rrset_count);
|
||||
if(worker->stats.extended) {
|
||||
Index: doc/unbound.conf.5.in
|
||||
===================================================================
|
||||
--- doc/unbound.conf.5.in (revision 4191)
|
||||
+++ doc/unbound.conf.5.in (working copy)
|
||||
@@ -1244,6 +1244,18 @@
|
||||
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 redirect-bogus-ipv4: \fI<IPv4 address>
|
||||
+Set a fixed address for DNSSEC failures that are cached
|
||||
+Instead of responding to A queries with SERVFAIL, respond
|
||||
+with NOERROR and the address specified here
|
||||
+The TTL of the response will be 5 seconds
|
||||
+.TP 5
|
||||
+.B redirect-bogus-ipv6: \fI<IPv4 address>
|
||||
+Set a fixed address for DNSSEC failures that are cached
|
||||
+Instead of responding to AAAA queries with SERVFAIL, respond
|
||||
+with NOERROR and the address specified here
|
||||
+The TTL of the response will be 5 seconds
|
||||
.SS "Remote Control Options"
|
||||
In the
|
||||
.B remote\-control:
|
||||
Index: services/mesh.c
|
||||
===================================================================
|
||||
--- services/mesh.c (revision 4191)
|
||||
+++ services/mesh.c (working copy)
|
||||
@@ -1006,6 +1006,7 @@
|
||||
struct timeval end_time;
|
||||
struct timeval duration;
|
||||
int secure;
|
||||
+ int bogus_override = 0;
|
||||
/* Copy the client's EDNS for later restore, to make sure the edns
|
||||
* compare is with the correct edns options. */
|
||||
struct edns_data edns_bak = r->edns;
|
||||
@@ -1016,6 +1017,7 @@
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
if(m->s.env->cfg->stat_extended)
|
||||
m->s.env->mesh->ans_bogus++;
|
||||
+ bogus_override = 1;
|
||||
}
|
||||
if(rep && rep->security == sec_status_secure)
|
||||
secure = 1;
|
||||
@@ -1047,17 +1049,34 @@
|
||||
} 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))
|
||||
- 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.opt_list = NULL;
|
||||
+ if(bogus_override && m->s.qinfo.qtype == LDNS_RR_TYPE_A &&
|
||||
+ m->s.env->cfg->redirect_bogus_ipv4) {
|
||||
+ fixed_address_encode(r->query_reply.c->buffer,
|
||||
+ LDNS_RCODE_NOERROR, &m->s.qinfo, r->qid,
|
||||
+ r->qflags, &r->edns,
|
||||
+ m->s.env->cfg->redirect_bogus_ipv4);
|
||||
+ } else if(bogus_override &&
|
||||
+ m->s.qinfo.qtype == LDNS_RR_TYPE_AAAA &&
|
||||
+ m->s.env->cfg->redirect_bogus_ipv6) {
|
||||
+ fixed_address_encode(r->query_reply.c->buffer,
|
||||
+ LDNS_RCODE_NOERROR, &m->s.qinfo, r->qid,
|
||||
+ r->qflags, &r->edns,
|
||||
+ m->s.env->cfg->redirect_bogus_ipv6);
|
||||
+ } else {
|
||||
+ 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))
|
||||
+ 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.opt_list = NULL;
|
||||
+ }
|
||||
+ error_encode(r->query_reply.c->buffer, rcode,
|
||||
+ &m->s.qinfo, r->qid, r->qflags, &r->edns);
|
||||
}
|
||||
- error_encode(r->query_reply.c->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;
|
||||
Index: util/config_file.c
|
||||
===================================================================
|
||||
--- util/config_file.c (revision 4191)
|
||||
+++ util/config_file.c (working copy)
|
||||
@@ -273,6 +273,8 @@
|
||||
cfg->ratelimit_factor = 10;
|
||||
cfg->qname_minimisation = 0;
|
||||
cfg->qname_minimisation_strict = 0;
|
||||
+ cfg->redirect_bogus_ipv4 = NULL;
|
||||
+ cfg->redirect_bogus_ipv6 = NULL;
|
||||
cfg->shm_enable = 0;
|
||||
cfg->shm_key = 11777;
|
||||
cfg->dnscrypt = 0;
|
||||
@@ -602,6 +604,10 @@
|
||||
}
|
||||
oi[cfg->num_out_ifs++] = d;
|
||||
cfg->out_ifs = oi;
|
||||
+ } else if (strcmp(opt, "redirect-bogus-ipv4:") == 0) {
|
||||
+ cfg->redirect_bogus_ipv4 = strdup(val);
|
||||
+ } else if (strcmp(opt, "redirect-bogus-ipv6:") == 0) {
|
||||
+ cfg->redirect_bogus_ipv6 = strdup(val);
|
||||
} else {
|
||||
/* unknown or unsupported (from the set_option interface):
|
||||
* interface, outgoing-interface, access-control,
|
||||
@@ -1250,6 +1256,12 @@
|
||||
free(cfg->dnstap_version);
|
||||
config_deldblstrlist(cfg->ratelimit_for_domain);
|
||||
config_deldblstrlist(cfg->ratelimit_below_domain);
|
||||
+ if (cfg->redirect_bogus_ipv4) {
|
||||
+ free(cfg->redirect_bogus_ipv4);
|
||||
+ }
|
||||
+ if (cfg->redirect_bogus_ipv6) {
|
||||
+ free(cfg->redirect_bogus_ipv6);
|
||||
+ }
|
||||
#ifdef USE_IPSECMOD
|
||||
free(cfg->ipsecmod_hook);
|
||||
config_delstrlist(cfg->ipsecmod_whitelist);
|
||||
Index: util/config_file.h
|
||||
===================================================================
|
||||
--- util/config_file.h (revision 4191)
|
||||
+++ util/config_file.h (working copy)
|
||||
@@ -444,6 +444,9 @@
|
||||
/** minimise QNAME in strict mode, minimise according to RFC.
|
||||
* Do not apply fallback */
|
||||
int qname_minimisation_strict;
|
||||
+ /** construct fake responses for DNSSEC failures */
|
||||
+ char *redirect_bogus_ipv4;
|
||||
+ char *redirect_bogus_ipv6;
|
||||
/** SHM data - true if shm is enabled */
|
||||
int shm_enable;
|
||||
/** SHM data - key for the shm */
|
||||
Index: util/configlexer.lex
|
||||
===================================================================
|
||||
--- util/configlexer.lex (revision 4191)
|
||||
+++ util/configlexer.lex (working copy)
|
||||
@@ -410,6 +410,8 @@
|
||||
response-ip-tag{COLON} { YDVAR(2, VAR_RESPONSE_IP_TAG) }
|
||||
response-ip{COLON} { YDVAR(2, VAR_RESPONSE_IP) }
|
||||
response-ip-data{COLON} { YDVAR(2, VAR_RESPONSE_IP_DATA) }
|
||||
+redirect-bogus-ipv4{COLON} { YDVAR(1, VAR_REDIRECT_BOGUS_IPV4) }
|
||||
+redirect-bogus-ipv6{COLON} { YDVAR(1, VAR_REDIRECT_BOGUS_IPV6) }
|
||||
dnscrypt{COLON} { YDVAR(0, VAR_DNSCRYPT) }
|
||||
dnscrypt-enable{COLON} { YDVAR(1, VAR_DNSCRYPT_ENABLE) }
|
||||
dnscrypt-port{COLON} { YDVAR(1, VAR_DNSCRYPT_PORT) }
|
||||
Index: util/configparser.y
|
||||
===================================================================
|
||||
--- util/configparser.y (revision 4191)
|
||||
+++ util/configparser.y (working copy)
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
+#include "sldns/str2wire.h"
|
||||
#include "util/configyyrename.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
@@ -141,6 +142,7 @@
|
||||
%token VAR_ACCESS_CONTROL_TAG_DATA VAR_VIEW VAR_ACCESS_CONTROL_VIEW
|
||||
%token VAR_VIEW_FIRST VAR_SERVE_EXPIRED VAR_FAKE_DSA VAR_FAKE_SHA1
|
||||
%token VAR_LOG_IDENTITY VAR_HIDE_TRUSTANCHOR VAR_TRUST_ANCHOR_SIGNALING
|
||||
+%token VAR_REDIRECT_BOGUS_IPV4 VAR_REDIRECT_BOGUS_IPV6
|
||||
%token VAR_USE_SYSTEMD VAR_SHM_ENABLE VAR_SHM_KEY
|
||||
%token VAR_DNSCRYPT VAR_DNSCRYPT_ENABLE VAR_DNSCRYPT_PORT VAR_DNSCRYPT_PROVIDER
|
||||
%token VAR_DNSCRYPT_SECRET_KEY VAR_DNSCRYPT_PROVIDER_CERT
|
||||
@@ -228,6 +230,7 @@
|
||||
server_access_control_tag_data | server_access_control_view |
|
||||
server_qname_minimisation_strict | server_serve_expired |
|
||||
server_fake_dsa | server_log_identity | server_use_systemd |
|
||||
+ server_redirect_bogus_ipv4 | server_redirect_bogus_ipv6 |
|
||||
server_response_ip_tag | server_response_ip | server_response_ip_data |
|
||||
server_shm_enable | server_shm_key | server_fake_sha1 |
|
||||
server_hide_trustanchor | server_trust_anchor_signaling |
|
||||
@@ -1873,6 +1876,34 @@
|
||||
#endif
|
||||
}
|
||||
;
|
||||
+server_redirect_bogus_ipv4: VAR_REDIRECT_BOGUS_IPV4 STRING_ARG
|
||||
+ {
|
||||
+ uint8_t data[4];
|
||||
+ size_t data_len = 4;
|
||||
+ OUTYY(("P(name:%s)\n", $2));
|
||||
+ if(cfg_parser->cfg->redirect_bogus_ipv4) {
|
||||
+ yyerror("redirect-bogus-ipv4, can only use one address");
|
||||
+ }
|
||||
+ if(sldns_str2wire_a_buf($2, data, &data_len) != LDNS_WIREPARSE_ERR_OK) {
|
||||
+ yyerror("redirect-bogus-ipv4, not a valid IPv4 address");
|
||||
+ }
|
||||
+ free(cfg_parser->cfg->redirect_bogus_ipv4);
|
||||
+ cfg_parser->cfg->redirect_bogus_ipv4 = $2;
|
||||
+ }
|
||||
+server_redirect_bogus_ipv6: VAR_REDIRECT_BOGUS_IPV6 STRING_ARG
|
||||
+ {
|
||||
+ uint8_t data[16];
|
||||
+ size_t data_len = 16;
|
||||
+ OUTYY(("P(name:%s)\n", $2));
|
||||
+ if(cfg_parser->cfg->redirect_bogus_ipv6) {
|
||||
+ yyerror("redirect-bogus-ipv6, can only use one address");
|
||||
+ }
|
||||
+ if(sldns_str2wire_aaaa_buf($2, data, &data_len) != LDNS_WIREPARSE_ERR_OK) {
|
||||
+ yyerror("redirect-bogus-ipv6, not a valid IPv6 address");
|
||||
+ }
|
||||
+ free(cfg_parser->cfg->redirect_bogus_ipv6);
|
||||
+ cfg_parser->cfg->redirect_bogus_ipv6 = $2;
|
||||
+ }
|
||||
stub_name: VAR_NAME STRING_ARG
|
||||
{
|
||||
OUTYY(("P(name:%s)\n", $2));
|
||||
Index: util/data/msgencode.c
|
||||
===================================================================
|
||||
--- util/data/msgencode.c (revision 4191)
|
||||
+++ util/data/msgencode.c (working copy)
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "util/regional.h"
|
||||
#include "util/net_help.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
+#include "sldns/str2wire.h"
|
||||
#include "services/localzone.h"
|
||||
|
||||
/** return code that means the function ran out of memory. negative so it does
|
||||
@@ -914,3 +915,63 @@
|
||||
attach_edns_record(buf, &es);
|
||||
}
|
||||
}
|
||||
+
|
||||
+void
|
||||
+fixed_address_encode(sldns_buffer* buf, int r, struct query_info* qinfo,
|
||||
+ uint16_t qid, uint16_t qflags, struct edns_data* edns, char* data)
|
||||
+{
|
||||
+ uint16_t flags;
|
||||
+ uint8_t addr_data[16];
|
||||
+ size_t addr_len = 16;
|
||||
+ if (qinfo->qtype == LDNS_RR_TYPE_A) {
|
||||
+ sldns_str2wire_a_buf(data, addr_data, &addr_len);
|
||||
+ } else if (qinfo->qtype == LDNS_RR_TYPE_AAAA) {
|
||||
+ sldns_str2wire_aaaa_buf(data, addr_data, &addr_len);
|
||||
+ } else {
|
||||
+ return error_encode(buf, LDNS_RCODE_NOERROR, qinfo, qid, qflags, edns);
|
||||
+ }
|
||||
+ sldns_buffer_clear(buf);
|
||||
+ sldns_buffer_write(buf, &qid, sizeof(uint16_t));
|
||||
+ flags = (uint16_t)(BIT_QR | BIT_RA | r); /* QR and retcode*/
|
||||
+ flags |= (qflags & (BIT_RD|BIT_CD)); /* copy RD and CD bit */
|
||||
+ sldns_buffer_write_u16(buf, flags);
|
||||
+ if(qinfo) flags = 1;
|
||||
+ else flags = 0;
|
||||
+ sldns_buffer_write_u16(buf, flags);
|
||||
+ sldns_buffer_write_u16(buf, 1);
|
||||
+ flags = 0;
|
||||
+ sldns_buffer_write(buf, &flags, sizeof(uint16_t));
|
||||
+ sldns_buffer_write(buf, &flags, sizeof(uint16_t));
|
||||
+ if(qinfo) {
|
||||
+ // query
|
||||
+ if(sldns_buffer_current(buf) == qinfo->qname)
|
||||
+ sldns_buffer_skip(buf, (ssize_t)qinfo->qname_len);
|
||||
+ else sldns_buffer_write(buf, qinfo->qname, qinfo->qname_len);
|
||||
+ sldns_buffer_write_u16(buf, qinfo->qtype);
|
||||
+ sldns_buffer_write_u16(buf, qinfo->qclass);
|
||||
+ // faked answer
|
||||
+ if(sldns_buffer_current(buf) == qinfo->qname)
|
||||
+ sldns_buffer_skip(buf, (ssize_t)qinfo->qname_len);
|
||||
+ else sldns_buffer_write(buf, qinfo->qname, qinfo->qname_len);
|
||||
+ sldns_buffer_write_u16(buf, qinfo->qtype);
|
||||
+ sldns_buffer_write_u16(buf, qinfo->qclass);
|
||||
+ sldns_buffer_write_u16(buf, 0);
|
||||
+ // TTL. Should we make this configurable too?
|
||||
+ sldns_buffer_write_u16(buf, 5);
|
||||
+ sldns_buffer_write_u16(buf, addr_len);
|
||||
+ sldns_buffer_write(buf, addr_data, addr_len);
|
||||
+ fflush(stderr);
|
||||
+ }
|
||||
+ sldns_buffer_flip(buf);
|
||||
+ if(edns) {
|
||||
+ struct edns_data es = *edns;
|
||||
+ es.edns_version = EDNS_ADVERTISED_VERSION;
|
||||
+ es.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
+ es.ext_rcode = 0;
|
||||
+ es.bits &= EDNS_DO;
|
||||
+ if(sldns_buffer_limit(buf) + calc_edns_field_size(&es) >
|
||||
+ edns->udp_size)
|
||||
+ return;
|
||||
+ attach_edns_record(buf, &es);
|
||||
+ }
|
||||
+}
|
||||
Index: util/data/msgencode.h
|
||||
===================================================================
|
||||
--- util/data/msgencode.h (revision 4191)
|
||||
+++ util/data/msgencode.h (working copy)
|
||||
@@ -128,4 +128,20 @@
|
||||
void error_encode(struct sldns_buffer* pkt, int r, struct query_info* qinfo,
|
||||
uint16_t qid, uint16_t qflags, struct edns_data* edns);
|
||||
|
||||
+/**
|
||||
+ * Encode a fixed address response.
|
||||
+ * This is a fake answer to either an A or AAA query
|
||||
+ *
|
||||
+ * It will answer with that address
|
||||
+ *
|
||||
+ * @param pkt: where to store the packet.
|
||||
+ * @param r: RCODE value to encode.
|
||||
+ * @param qinfo: if not NULL, the query is included.
|
||||
+ * @param qid: query ID to set in packet. network order.
|
||||
+ * @param qflags: original query flags (to copy RD and CD bits). host order.
|
||||
+ * @param edns: if not NULL, this is the query edns info,
|
||||
+ * and an edns reply is attached. Only attached if EDNS record fits reply.
|
||||
+ */
|
||||
+void fixed_address_encode(struct sldns_buffer* pkt, int r, struct query_info* qinfo,
|
||||
+ uint16_t qid, uint16_t qflags, struct edns_data* edns, char* address);
|
||||
#endif /* UTIL_DATA_MSGENCODE_H */
|
||||
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import hashlib
|
||||
import sys
|
||||
import struct
|
||||
import socket
|
||||
import time
|
||||
from optparse import OptionParser
|
||||
|
||||
import dns.message
|
||||
import dns.name
|
||||
import dns.rdataclass
|
||||
import dns.rdatatype
|
||||
|
||||
def _calc_hashkey(qname, secret, qtype):
|
||||
qclass = 'IN' # CLASS is fixed for simplicity
|
||||
hobj = hashlib.sha256()
|
||||
hobj.update(dns.name.from_text(qname).to_wire())
|
||||
hobj.update(struct.pack('HH',
|
||||
socket.htons(dns.rdatatype.from_text(qtype)),
|
||||
socket.htons(dns.rdataclass.from_text(qclass))))
|
||||
hobj.update(secret)
|
||||
return hobj.hexdigest().upper()
|
||||
|
||||
def _redis_get(options, key):
|
||||
import redis
|
||||
return redis.Redis(options.address, int(options.port)).get(key)
|
||||
|
||||
def _dump_value(options, qname, key, value):
|
||||
print(';; query=%s/IN/%s' % (qname, options.qtype))
|
||||
print(';; key=%s' % key)
|
||||
if value is None:
|
||||
print(';; no value')
|
||||
return
|
||||
if len(value) < 16:
|
||||
print(';; broken value, short length: %d' % len(value))
|
||||
return
|
||||
now = int(time.time())
|
||||
timestamp = struct.unpack('!Q', value[-16:-8])[0]
|
||||
expire = struct.unpack('!Q', value[-8:])[0]
|
||||
print(';; Now=%d, TimeStamp=%d, Expire=%d, TTL=%d' %
|
||||
(now, timestamp, expire, max(expire - now, 0)))
|
||||
print(dns.message.from_wire(value[:-16]))
|
||||
|
||||
def main():
|
||||
parser = OptionParser(usage='usage: %prog [options] query_name')
|
||||
parser.add_option("-a", "--address", dest="address", action="store",
|
||||
default='127.0.0.1', help="backend-server address",
|
||||
metavar='ADDRESS')
|
||||
parser.add_option("-b", "--backend", dest="backend", action="store",
|
||||
default='redis', help="backend name",
|
||||
metavar='BACKEND')
|
||||
parser.add_option("-p", "--port", dest="port", action="store",
|
||||
default='6379', help="backend-server port",
|
||||
metavar='PORT')
|
||||
parser.add_option("-s", "--secret", dest="secret", action="store",
|
||||
default='default', help="secret seed", metavar='SECRET')
|
||||
parser.add_option("-t", "--qtype", dest="qtype", action="store",
|
||||
default='A', help="query RR type", metavar='QTYPE')
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
if len(args) < 1:
|
||||
parser.error('qname is missing')
|
||||
if options.backend == 'redis':
|
||||
get_func = _redis_get
|
||||
else:
|
||||
raise Exception('unknown backend name: %s\n' % options.backend)
|
||||
key = _calc_hashkey(args[0], options.secret, options.qtype)
|
||||
value = get_func(options, key)
|
||||
_dump_value(options, args[0], key, value)
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main()
|
||||
except Exception as e:
|
||||
sys.stderr.write('%s\n' % e)
|
||||
exit(1)
|
||||
@@ -7,7 +7,7 @@ WantedBy=multi-user.target
|
||||
|
||||
[Service]
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
ExecStart=/home/vagrant/unbound_systemd/unbound
|
||||
ExecStart=@UNBOUND_SBIN_DIR@/unbound
|
||||
NotifyAccess=main
|
||||
Type=notify
|
||||
CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT
|
||||
@@ -20,7 +20,7 @@ ProtectControlGroups=true
|
||||
ProtectKernelModules=true
|
||||
ProtectKernelTunables=true
|
||||
ProtectSystem=strict
|
||||
ReadWritePaths=/etc/unbound /run
|
||||
ReadWritePaths=@UNBOUND_SYSCONF_DIR@ @UNBOUND_LOCALSTATE_DIR@ /run @UNBOUND_RUN_DIR@
|
||||
RestrictAddressFamilies=AF_INET AF_UNIX
|
||||
RestrictRealtime=true
|
||||
SystemCallArchitectures=native
|
||||
|
||||
@@ -111,6 +111,8 @@ acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
|
||||
control = acl_refuse_non_local;
|
||||
else if(strcmp(s2, "allow_snoop") == 0)
|
||||
control = acl_allow_snoop;
|
||||
else if(strcmp(s2, "allow_setrd") == 0)
|
||||
control = acl_allow_setrd;
|
||||
else {
|
||||
log_err("access control type %s unknown", str);
|
||||
return 0;
|
||||
|
||||
+3
-1
@@ -63,7 +63,9 @@ enum acl_access {
|
||||
/** allow full access for recursion (+RD) queries */
|
||||
acl_allow,
|
||||
/** allow full access for all queries, recursion and cache snooping */
|
||||
acl_allow_snoop
|
||||
acl_allow_snoop,
|
||||
/** allow full access for recursion queries and set RD flag regardless of request */
|
||||
acl_allow_setrd
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+22
-21
@@ -62,7 +62,7 @@
|
||||
|
||||
/** dump one rrset zonefile line */
|
||||
static int
|
||||
dump_rrset_line(SSL* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i)
|
||||
dump_rrset_line(RES* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i)
|
||||
{
|
||||
char s[65535];
|
||||
if(!packed_rr_to_string(k, i, now, s, sizeof(s))) {
|
||||
@@ -73,12 +73,13 @@ dump_rrset_line(SSL* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i)
|
||||
|
||||
/** dump rrset key and data info */
|
||||
static int
|
||||
dump_rrset(SSL* ssl, struct ub_packed_rrset_key* k,
|
||||
dump_rrset(RES* ssl, struct ub_packed_rrset_key* k,
|
||||
struct packed_rrset_data* d, time_t now)
|
||||
{
|
||||
size_t i;
|
||||
/* rd lock held by caller */
|
||||
if(!k || !d) return 1;
|
||||
if(k->id == 0) return 1; /* deleted */
|
||||
if(d->ttl < now) return 1; /* expired */
|
||||
|
||||
/* meta line */
|
||||
@@ -98,7 +99,7 @@ dump_rrset(SSL* ssl, struct ub_packed_rrset_key* k,
|
||||
|
||||
/** dump lruhash rrset cache */
|
||||
static int
|
||||
dump_rrset_lruhash(SSL* ssl, struct lruhash* h, time_t now)
|
||||
dump_rrset_lruhash(RES* ssl, struct lruhash* h, time_t now)
|
||||
{
|
||||
struct lruhash_entry* e;
|
||||
/* lruhash already locked by caller */
|
||||
@@ -117,7 +118,7 @@ dump_rrset_lruhash(SSL* ssl, struct lruhash* h, time_t now)
|
||||
|
||||
/** dump rrset cache */
|
||||
static int
|
||||
dump_rrset_cache(SSL* ssl, struct worker* worker)
|
||||
dump_rrset_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
struct rrset_cache* r = worker->env.rrset_cache;
|
||||
size_t slab;
|
||||
@@ -136,7 +137,7 @@ dump_rrset_cache(SSL* ssl, struct worker* worker)
|
||||
|
||||
/** dump message to rrset reference */
|
||||
static int
|
||||
dump_msg_ref(SSL* ssl, struct ub_packed_rrset_key* k)
|
||||
dump_msg_ref(RES* ssl, struct ub_packed_rrset_key* k)
|
||||
{
|
||||
char* nm, *tp, *cl;
|
||||
nm = sldns_wire2str_dname(k->rk.dname, k->rk.dname_len);
|
||||
@@ -163,7 +164,7 @@ dump_msg_ref(SSL* ssl, struct ub_packed_rrset_key* k)
|
||||
|
||||
/** dump message entry */
|
||||
static int
|
||||
dump_msg(SSL* ssl, struct query_info* k, struct reply_info* d,
|
||||
dump_msg(RES* ssl, struct query_info* k, struct reply_info* d,
|
||||
time_t now)
|
||||
{
|
||||
size_t i;
|
||||
@@ -245,7 +246,7 @@ copy_msg(struct regional* region, struct lruhash_entry* e,
|
||||
|
||||
/** dump lruhash msg cache */
|
||||
static int
|
||||
dump_msg_lruhash(SSL* ssl, struct worker* worker, struct lruhash* h)
|
||||
dump_msg_lruhash(RES* ssl, struct worker* worker, struct lruhash* h)
|
||||
{
|
||||
struct lruhash_entry* e;
|
||||
struct query_info* k;
|
||||
@@ -273,7 +274,7 @@ dump_msg_lruhash(SSL* ssl, struct worker* worker, struct lruhash* h)
|
||||
|
||||
/** dump msg cache */
|
||||
static int
|
||||
dump_msg_cache(SSL* ssl, struct worker* worker)
|
||||
dump_msg_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
struct slabhash* sh = worker->env.msg_cache;
|
||||
size_t slab;
|
||||
@@ -290,7 +291,7 @@ dump_msg_cache(SSL* ssl, struct worker* worker)
|
||||
}
|
||||
|
||||
int
|
||||
dump_cache(SSL* ssl, struct worker* worker)
|
||||
dump_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
if(!dump_rrset_cache(ssl, worker))
|
||||
return 0;
|
||||
@@ -301,7 +302,7 @@ dump_cache(SSL* ssl, struct worker* worker)
|
||||
|
||||
/** read a line from ssl into buffer */
|
||||
static int
|
||||
ssl_read_buf(SSL* ssl, sldns_buffer* buf)
|
||||
ssl_read_buf(RES* ssl, sldns_buffer* buf)
|
||||
{
|
||||
return ssl_read_line(ssl, (char*)sldns_buffer_begin(buf),
|
||||
sldns_buffer_capacity(buf));
|
||||
@@ -309,7 +310,7 @@ ssl_read_buf(SSL* ssl, sldns_buffer* buf)
|
||||
|
||||
/** check fixed text on line */
|
||||
static int
|
||||
read_fixed(SSL* ssl, sldns_buffer* buf, const char* str)
|
||||
read_fixed(RES* ssl, sldns_buffer* buf, const char* str)
|
||||
{
|
||||
if(!ssl_read_buf(ssl, buf)) return 0;
|
||||
return (strcmp((char*)sldns_buffer_begin(buf), str) == 0);
|
||||
@@ -317,7 +318,7 @@ read_fixed(SSL* ssl, sldns_buffer* buf, const char* str)
|
||||
|
||||
/** load an RR into rrset */
|
||||
static int
|
||||
load_rr(SSL* ssl, sldns_buffer* buf, struct regional* region,
|
||||
load_rr(RES* ssl, sldns_buffer* buf, struct regional* region,
|
||||
struct ub_packed_rrset_key* rk, struct packed_rrset_data* d,
|
||||
unsigned int i, int is_rrsig, int* go_on, time_t now)
|
||||
{
|
||||
@@ -434,7 +435,7 @@ move_into_cache(struct ub_packed_rrset_key* k,
|
||||
|
||||
/** load an rrset entry */
|
||||
static int
|
||||
load_rrset(SSL* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
load_rrset(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
{
|
||||
char* s = (char*)sldns_buffer_begin(buf);
|
||||
struct regional* region = worker->scratchpad;
|
||||
@@ -518,7 +519,7 @@ load_rrset(SSL* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
|
||||
/** load rrset cache */
|
||||
static int
|
||||
load_rrset_cache(SSL* ssl, struct worker* worker)
|
||||
load_rrset_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
sldns_buffer* buf = worker->env.scratch_buffer;
|
||||
if(!read_fixed(ssl, buf, "START_RRSET_CACHE")) return 0;
|
||||
@@ -574,7 +575,7 @@ load_qinfo(char* str, struct query_info* qinfo, struct regional* region)
|
||||
|
||||
/** load a msg rrset reference */
|
||||
static int
|
||||
load_ref(SSL* ssl, sldns_buffer* buf, struct worker* worker,
|
||||
load_ref(RES* ssl, sldns_buffer* buf, struct worker* worker,
|
||||
struct regional *region, struct ub_packed_rrset_key** rrset,
|
||||
int* go_on)
|
||||
{
|
||||
@@ -619,7 +620,7 @@ load_ref(SSL* ssl, sldns_buffer* buf, struct worker* worker,
|
||||
|
||||
/** load a msg entry */
|
||||
static int
|
||||
load_msg(SSL* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
{
|
||||
struct regional* region = worker->scratchpad;
|
||||
struct query_info qinf;
|
||||
@@ -684,7 +685,7 @@ load_msg(SSL* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
|
||||
/** load msg cache */
|
||||
static int
|
||||
load_msg_cache(SSL* ssl, struct worker* worker)
|
||||
load_msg_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
sldns_buffer* buf = worker->env.scratch_buffer;
|
||||
if(!read_fixed(ssl, buf, "START_MSG_CACHE")) return 0;
|
||||
@@ -697,7 +698,7 @@ load_msg_cache(SSL* ssl, struct worker* worker)
|
||||
}
|
||||
|
||||
int
|
||||
load_cache(SSL* ssl, struct worker* worker)
|
||||
load_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
if(!load_rrset_cache(ssl, worker))
|
||||
return 0;
|
||||
@@ -708,7 +709,7 @@ load_cache(SSL* ssl, struct worker* worker)
|
||||
|
||||
/** print details on a delegation point */
|
||||
static void
|
||||
print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp)
|
||||
print_dp_details(RES* ssl, struct worker* worker, struct delegpt* dp)
|
||||
{
|
||||
char buf[257];
|
||||
struct delegpt_addr* a;
|
||||
@@ -784,7 +785,7 @@ print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp)
|
||||
|
||||
/** print main dp info */
|
||||
static void
|
||||
print_dp_main(SSL* ssl, struct delegpt* dp, struct dns_msg* msg)
|
||||
print_dp_main(RES* ssl, struct delegpt* dp, struct dns_msg* msg)
|
||||
{
|
||||
size_t i, n_ns, n_miss, n_addr, n_res, n_avail;
|
||||
|
||||
@@ -812,7 +813,7 @@ print_dp_main(SSL* ssl, struct delegpt* dp, struct dns_msg* msg)
|
||||
return;
|
||||
}
|
||||
|
||||
int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
|
||||
int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
||||
size_t nmlen, int ATTR_UNUSED(nmlabs))
|
||||
{
|
||||
/* deep links into the iterator module */
|
||||
|
||||
+4
-3
@@ -72,6 +72,7 @@
|
||||
#ifndef DAEMON_DUMPCACHE_H
|
||||
#define DAEMON_DUMPCACHE_H
|
||||
struct worker;
|
||||
#include "daemon/remote.h"
|
||||
|
||||
/**
|
||||
* Dump cache(s) to text
|
||||
@@ -80,7 +81,7 @@ struct worker;
|
||||
* ptrs to the caches.
|
||||
* @return false on ssl print error.
|
||||
*/
|
||||
int dump_cache(SSL* ssl, struct worker* worker);
|
||||
int dump_cache(RES* ssl, struct worker* worker);
|
||||
|
||||
/**
|
||||
* Load cache(s) from text
|
||||
@@ -89,7 +90,7 @@ int dump_cache(SSL* ssl, struct worker* worker);
|
||||
* ptrs to the caches.
|
||||
* @return false on ssl error.
|
||||
*/
|
||||
int load_cache(SSL* ssl, struct worker* worker);
|
||||
int load_cache(RES* ssl, struct worker* worker);
|
||||
|
||||
/**
|
||||
* Print the delegation used to lookup for this name.
|
||||
@@ -101,7 +102,7 @@ int load_cache(SSL* ssl, struct worker* worker);
|
||||
* @param nmlabs: labels in name.
|
||||
* @return false on ssl error.
|
||||
*/
|
||||
int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
|
||||
int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
||||
size_t nmlen, int nmlabs);
|
||||
|
||||
#endif /* DAEMON_DUMPCACHE_H */
|
||||
|
||||
+28
-2
@@ -82,6 +82,7 @@
|
||||
#include "services/localzone.h"
|
||||
#include "services/view.h"
|
||||
#include "services/modstack.h"
|
||||
#include "services/authzone.h"
|
||||
#include "util/module.h"
|
||||
#include "util/random.h"
|
||||
#include "util/tube.h"
|
||||
@@ -221,7 +222,9 @@ daemon_init(void)
|
||||
# ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
|
||||
ERR_load_crypto_strings();
|
||||
# endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
ERR_load_SSL_strings();
|
||||
#endif
|
||||
# ifdef USE_GOST
|
||||
(void)sldns_key_EVP_load_gost_id();
|
||||
# endif
|
||||
@@ -239,7 +242,7 @@ daemon_init(void)
|
||||
# if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
# else
|
||||
(void)OPENSSL_init_ssl(0, NULL);
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||
# endif
|
||||
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
|
||||
if(!ub_openssl_lock_init())
|
||||
@@ -279,6 +282,13 @@ daemon_init(void)
|
||||
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);
|
||||
edns_known_options_delete(daemon->env);
|
||||
free(daemon->env);
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
return daemon;
|
||||
}
|
||||
|
||||
@@ -421,8 +431,8 @@ daemon_create_workers(struct daemon* daemon)
|
||||
daemon->rand = ub_initstate(seed, NULL);
|
||||
if(!daemon->rand)
|
||||
fatal_exit("could not init random generator");
|
||||
hash_set_raninit((uint32_t)ub_random(daemon->rand));
|
||||
}
|
||||
hash_set_raninit((uint32_t)ub_random(daemon->rand));
|
||||
shufport = (int*)calloc(65536, sizeof(int));
|
||||
if(!shufport)
|
||||
fatal_exit("out of memory during daemon init");
|
||||
@@ -601,6 +611,10 @@ daemon_fork(struct daemon* daemon)
|
||||
fatal_exit("Could not set up per-view response IP sets");
|
||||
daemon->use_response_ip = !respip_set_is_empty(daemon->respip_set) ||
|
||||
have_view_respip_cfg;
|
||||
|
||||
/* read auth zonefiles */
|
||||
if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1))
|
||||
fatal_exit("auth_zones could not be setup");
|
||||
|
||||
/* setup modules */
|
||||
daemon_setup_modules(daemon);
|
||||
@@ -681,6 +695,8 @@ daemon_cleanup(struct daemon* daemon)
|
||||
daemon->respip_set = NULL;
|
||||
views_delete(daemon->views);
|
||||
daemon->views = NULL;
|
||||
if(daemon->env->auth_zones)
|
||||
auth_zones_cleanup(daemon->env->auth_zones);
|
||||
/* key cache is cleared by module desetup during next daemon_fork() */
|
||||
daemon_remote_clear(daemon->rc);
|
||||
for(i=0; i<daemon->num; i++)
|
||||
@@ -688,8 +704,14 @@ daemon_cleanup(struct daemon* daemon)
|
||||
free(daemon->workers);
|
||||
daemon->workers = NULL;
|
||||
daemon->num = 0;
|
||||
alloc_clear_special(&daemon->superalloc);
|
||||
#ifdef USE_DNSTAP
|
||||
dt_delete(daemon->dtenv);
|
||||
daemon->dtenv = NULL;
|
||||
#endif
|
||||
#ifdef USE_DNSCRYPT
|
||||
dnsc_delete(daemon->dnscenv);
|
||||
daemon->dnscenv = NULL;
|
||||
#endif
|
||||
daemon->cfg = NULL;
|
||||
}
|
||||
@@ -711,6 +733,7 @@ daemon_delete(struct daemon* daemon)
|
||||
rrset_cache_delete(daemon->env->rrset_cache);
|
||||
infra_delete(daemon->env->infra_cache);
|
||||
edns_known_options_delete(daemon->env);
|
||||
auth_zones_delete(daemon->env->auth_zones);
|
||||
}
|
||||
ub_randfree(daemon->rand);
|
||||
alloc_clear(&daemon->superalloc);
|
||||
@@ -758,6 +781,9 @@ daemon_delete(struct daemon* daemon)
|
||||
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
|
||||
ub_openssl_lock_delete();
|
||||
# endif
|
||||
#ifndef HAVE_ARC4RANDOM
|
||||
_ARC4_LOCK_DESTROY();
|
||||
#endif
|
||||
#elif defined(HAVE_NSS)
|
||||
NSS_Shutdown();
|
||||
#endif /* HAVE_SSL or HAVE_NSS */
|
||||
|
||||
+389
-366
File diff suppressed because it is too large
Load Diff
+21
-6
@@ -73,6 +73,8 @@ struct rc_state {
|
||||
/** the ssl state */
|
||||
SSL* ssl;
|
||||
#endif
|
||||
/** file descriptor */
|
||||
int fd;
|
||||
/** the rc this is part of */
|
||||
struct daemon_remote* rc;
|
||||
};
|
||||
@@ -103,6 +105,19 @@ struct daemon_remote {
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Connection to print to, either SSL or plain over fd
|
||||
*/
|
||||
struct remote_stream {
|
||||
#ifdef HAVE_SSL
|
||||
/** SSL structure, nonNULL if using SSL */
|
||||
SSL* ssl;
|
||||
#endif
|
||||
/** file descriptor for plain transfer */
|
||||
int fd;
|
||||
};
|
||||
typedef struct remote_stream RES;
|
||||
|
||||
/**
|
||||
* Create new remote control state for the daemon.
|
||||
* @param cfg: config file with key file settings.
|
||||
@@ -166,26 +181,26 @@ void daemon_remote_exec(struct worker* worker);
|
||||
* @param text: the text.
|
||||
* @return false on connection failure.
|
||||
*/
|
||||
int ssl_print_text(SSL* ssl, const char* text);
|
||||
int ssl_print_text(RES* ssl, const char* text);
|
||||
|
||||
/**
|
||||
* printf style printing to the ssl connection
|
||||
* @param ssl: the SSL connection to print to. Blocking.
|
||||
* @param ssl: the RES connection to print to. Blocking.
|
||||
* @param format: printf style format string.
|
||||
* @return success or false on a network failure.
|
||||
*/
|
||||
int ssl_printf(SSL* ssl, const char* format, ...)
|
||||
int ssl_printf(RES* ssl, const char* format, ...)
|
||||
ATTR_FORMAT(printf, 2, 3);
|
||||
|
||||
/**
|
||||
* Read until \n is encountered
|
||||
* If SSL signals EOF, the string up to then is returned (without \n).
|
||||
* @param ssl: the SSL connection to read from. blocking.
|
||||
* If stream signals EOF, the string up to then is returned (without \n).
|
||||
* @param ssl: the RES connection to read from. blocking.
|
||||
* @param buf: buffer to read to.
|
||||
* @param max: size of buffer.
|
||||
* @return false on connection failure.
|
||||
*/
|
||||
int ssl_read_line(SSL* ssl, char* buf, size_t max);
|
||||
int ssl_read_line(RES* ssl, char* buf, size_t max);
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
#endif /* DAEMON_REMOTE_H */
|
||||
|
||||
+179
-56
@@ -56,49 +56,52 @@
|
||||
#include "util/timehist.h"
|
||||
#include "util/net_help.h"
|
||||
#include "validator/validator.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/authzone.h"
|
||||
#include "validator/val_kcache.h"
|
||||
#include "validator/val_neg.h"
|
||||
|
||||
/** add timers and the values do not overflow or become negative */
|
||||
static void
|
||||
timeval_add(struct timeval* d, const struct timeval* add)
|
||||
stats_timeval_add(long long* d_sec, long long* d_usec, long long add_sec, long long add_usec)
|
||||
{
|
||||
#ifndef S_SPLINT_S
|
||||
d->tv_sec += add->tv_sec;
|
||||
d->tv_usec += add->tv_usec;
|
||||
if(d->tv_usec > 1000000) {
|
||||
d->tv_usec -= 1000000;
|
||||
d->tv_sec++;
|
||||
(*d_sec) += add_sec;
|
||||
(*d_usec) += add_usec;
|
||||
if((*d_usec) > 1000000) {
|
||||
(*d_usec) -= 1000000;
|
||||
(*d_sec)++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void server_stats_init(struct server_stats* stats, struct config_file* cfg)
|
||||
void server_stats_init(struct ub_server_stats* stats, struct config_file* cfg)
|
||||
{
|
||||
memset(stats, 0, sizeof(*stats));
|
||||
stats->extended = cfg->stat_extended;
|
||||
}
|
||||
|
||||
void server_stats_querymiss(struct server_stats* stats, struct worker* worker)
|
||||
void server_stats_querymiss(struct ub_server_stats* stats, struct worker* worker)
|
||||
{
|
||||
stats->num_queries_missed_cache++;
|
||||
stats->sum_query_list_size += worker->env.mesh->all.count;
|
||||
if(worker->env.mesh->all.count > stats->max_query_list_size)
|
||||
stats->max_query_list_size = worker->env.mesh->all.count;
|
||||
if((long long)worker->env.mesh->all.count > stats->max_query_list_size)
|
||||
stats->max_query_list_size = (long long)worker->env.mesh->all.count;
|
||||
}
|
||||
|
||||
void server_stats_prefetch(struct server_stats* stats, struct worker* worker)
|
||||
void server_stats_prefetch(struct ub_server_stats* stats, struct worker* worker)
|
||||
{
|
||||
stats->num_queries_prefetch++;
|
||||
/* changes the query list size so account that, like a querymiss */
|
||||
stats->sum_query_list_size += worker->env.mesh->all.count;
|
||||
if(worker->env.mesh->all.count > stats->max_query_list_size)
|
||||
stats->max_query_list_size = worker->env.mesh->all.count;
|
||||
if((long long)worker->env.mesh->all.count > stats->max_query_list_size)
|
||||
stats->max_query_list_size = (long long)worker->env.mesh->all.count;
|
||||
}
|
||||
|
||||
void server_stats_log(struct server_stats* stats, struct worker* worker,
|
||||
void server_stats_log(struct ub_server_stats* stats, struct worker* worker,
|
||||
int threadnum)
|
||||
{
|
||||
log_info("server stats for thread %d: %u queries, "
|
||||
@@ -115,15 +118,39 @@ void server_stats_log(struct server_stats* stats, struct worker* worker,
|
||||
(unsigned)stats->max_query_list_size,
|
||||
(stats->num_queries_missed_cache+stats->num_queries_prefetch)?
|
||||
(double)stats->sum_query_list_size/
|
||||
(stats->num_queries_missed_cache+
|
||||
(double)(stats->num_queries_missed_cache+
|
||||
stats->num_queries_prefetch) : 0.0,
|
||||
(unsigned)worker->env.mesh->stats_dropped,
|
||||
(unsigned)worker->env.mesh->stats_jostled);
|
||||
}
|
||||
|
||||
/** Set the neg cache stats. */
|
||||
static void
|
||||
set_neg_cache_stats(struct worker* worker, struct ub_server_stats* svr,
|
||||
int reset)
|
||||
{
|
||||
int m = modstack_find(&worker->env.mesh->mods, "validator");
|
||||
struct val_env* ve;
|
||||
struct val_neg_cache* neg;
|
||||
if(m == -1)
|
||||
return;
|
||||
ve = (struct val_env*)worker->env.modinfo[m];
|
||||
if(!ve->neg_cache)
|
||||
return;
|
||||
neg = ve->neg_cache;
|
||||
lock_basic_lock(&neg->lock);
|
||||
svr->num_neg_cache_noerror = (long long)neg->num_neg_cache_noerror;
|
||||
svr->num_neg_cache_nxdomain = (long long)neg->num_neg_cache_nxdomain;
|
||||
if(reset && !worker->env.cfg->stat_cumulative) {
|
||||
neg->num_neg_cache_noerror = 0;
|
||||
neg->num_neg_cache_nxdomain = 0;
|
||||
}
|
||||
lock_basic_unlock(&neg->lock);
|
||||
}
|
||||
|
||||
/** get rrsets bogus number from validator */
|
||||
static size_t
|
||||
get_rrset_bogus(struct worker* worker)
|
||||
get_rrset_bogus(struct worker* worker, int reset)
|
||||
{
|
||||
int m = modstack_find(&worker->env.mesh->mods, "validator");
|
||||
struct val_env* ve;
|
||||
@@ -133,56 +160,153 @@ get_rrset_bogus(struct worker* worker)
|
||||
ve = (struct val_env*)worker->env.modinfo[m];
|
||||
lock_basic_lock(&ve->bogus_lock);
|
||||
r = ve->num_rrset_bogus;
|
||||
if(!worker->env.cfg->stat_cumulative)
|
||||
if(reset && !worker->env.cfg->stat_cumulative)
|
||||
ve->num_rrset_bogus = 0;
|
||||
lock_basic_unlock(&ve->bogus_lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
/** get number of ratelimited queries from iterator */
|
||||
static size_t
|
||||
get_queries_ratelimit(struct worker* worker, int reset)
|
||||
{
|
||||
int m = modstack_find(&worker->env.mesh->mods, "iterator");
|
||||
struct iter_env* ie;
|
||||
size_t r;
|
||||
if(m == -1)
|
||||
return 0;
|
||||
ie = (struct iter_env*)worker->env.modinfo[m];
|
||||
lock_basic_lock(&ie->queries_ratelimit_lock);
|
||||
r = ie->num_queries_ratelimited;
|
||||
if(reset && !worker->env.cfg->stat_cumulative)
|
||||
ie->num_queries_ratelimited = 0;
|
||||
lock_basic_unlock(&ie->queries_ratelimit_lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef USE_DNSCRYPT
|
||||
/** get the number of shared secret cache miss */
|
||||
static size_t
|
||||
get_dnscrypt_cache_miss(struct worker* worker, int reset)
|
||||
{
|
||||
size_t r;
|
||||
struct dnsc_env* de = worker->daemon->dnscenv;
|
||||
if(!de) return 0;
|
||||
|
||||
lock_basic_lock(&de->shared_secrets_cache_lock);
|
||||
r = de->num_query_dnscrypt_secret_missed_cache;
|
||||
if(reset && !worker->env.cfg->stat_cumulative)
|
||||
de->num_query_dnscrypt_secret_missed_cache = 0;
|
||||
lock_basic_unlock(&de->shared_secrets_cache_lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
/** get the number of replayed queries */
|
||||
static size_t
|
||||
get_dnscrypt_replay(struct worker* worker, int reset)
|
||||
{
|
||||
size_t r;
|
||||
struct dnsc_env* de = worker->daemon->dnscenv;
|
||||
|
||||
lock_basic_lock(&de->nonces_cache_lock);
|
||||
r = de->num_query_dnscrypt_replay;
|
||||
if(reset && !worker->env.cfg->stat_cumulative)
|
||||
de->num_query_dnscrypt_replay = 0;
|
||||
lock_basic_unlock(&de->nonces_cache_lock);
|
||||
return r;
|
||||
}
|
||||
#endif /* USE_DNSCRYPT */
|
||||
|
||||
void
|
||||
server_stats_compile(struct worker* worker, struct stats_info* s, int reset)
|
||||
server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
{
|
||||
int i;
|
||||
struct listen_list* lp;
|
||||
|
||||
s->svr = worker->stats;
|
||||
s->mesh_num_states = worker->env.mesh->all.count;
|
||||
s->mesh_num_reply_states = worker->env.mesh->num_reply_states;
|
||||
s->mesh_jostled = worker->env.mesh->stats_jostled;
|
||||
s->mesh_dropped = worker->env.mesh->stats_dropped;
|
||||
s->mesh_replies_sent = worker->env.mesh->replies_sent;
|
||||
s->mesh_replies_sum_wait = worker->env.mesh->replies_sum_wait;
|
||||
s->mesh_num_states = (long long)worker->env.mesh->all.count;
|
||||
s->mesh_num_reply_states = (long long)worker->env.mesh->num_reply_states;
|
||||
s->mesh_jostled = (long long)worker->env.mesh->stats_jostled;
|
||||
s->mesh_dropped = (long long)worker->env.mesh->stats_dropped;
|
||||
s->mesh_replies_sent = (long long)worker->env.mesh->replies_sent;
|
||||
s->mesh_replies_sum_wait_sec = (long long)worker->env.mesh->replies_sum_wait.tv_sec;
|
||||
s->mesh_replies_sum_wait_usec = (long long)worker->env.mesh->replies_sum_wait.tv_usec;
|
||||
s->mesh_time_median = timehist_quartile(worker->env.mesh->histogram,
|
||||
0.50);
|
||||
|
||||
/* add in the values from the mesh */
|
||||
s->svr.ans_secure += worker->env.mesh->ans_secure;
|
||||
s->svr.ans_bogus += worker->env.mesh->ans_bogus;
|
||||
s->svr.ans_rcode_nodata += worker->env.mesh->ans_nodata;
|
||||
s->svr.ans_secure += (long long)worker->env.mesh->ans_secure;
|
||||
s->svr.ans_bogus += (long long)worker->env.mesh->ans_bogus;
|
||||
s->svr.ans_rcode_nodata += (long long)worker->env.mesh->ans_nodata;
|
||||
for(i=0; i<16; i++)
|
||||
s->svr.ans_rcode[i] += worker->env.mesh->ans_rcode[i];
|
||||
s->svr.ans_rcode[i] += (long long)worker->env.mesh->ans_rcode[i];
|
||||
timehist_export(worker->env.mesh->histogram, s->svr.hist,
|
||||
NUM_BUCKETS_HIST);
|
||||
/* values from outside network */
|
||||
s->svr.unwanted_replies = worker->back->unwanted_replies;
|
||||
s->svr.qtcp_outgoing = worker->back->num_tcp_outgoing;
|
||||
s->svr.unwanted_replies = (long long)worker->back->unwanted_replies;
|
||||
s->svr.qtcp_outgoing = (long long)worker->back->num_tcp_outgoing;
|
||||
|
||||
/* get and reset validator rrset bogus number */
|
||||
s->svr.rrset_bogus = get_rrset_bogus(worker);
|
||||
s->svr.rrset_bogus = (long long)get_rrset_bogus(worker, reset);
|
||||
|
||||
/* get and reset iterator query ratelimit number */
|
||||
s->svr.queries_ratelimited = (long long)get_queries_ratelimit(worker, reset);
|
||||
|
||||
/* get cache sizes */
|
||||
s->svr.msg_cache_count = count_slabhash_entries(worker->env.msg_cache);
|
||||
s->svr.rrset_cache_count = count_slabhash_entries(&worker->env.rrset_cache->table);
|
||||
s->svr.infra_cache_count = count_slabhash_entries(worker->env.infra_cache->hosts);
|
||||
s->svr.msg_cache_count = (long long)count_slabhash_entries(worker->env.msg_cache);
|
||||
s->svr.rrset_cache_count = (long long)count_slabhash_entries(&worker->env.rrset_cache->table);
|
||||
s->svr.infra_cache_count = (long long)count_slabhash_entries(worker->env.infra_cache->hosts);
|
||||
if(worker->env.key_cache)
|
||||
s->svr.key_cache_count = count_slabhash_entries(worker->env.key_cache->slab);
|
||||
s->svr.key_cache_count = (long long)count_slabhash_entries(worker->env.key_cache->slab);
|
||||
else s->svr.key_cache_count = 0;
|
||||
|
||||
#ifdef USE_DNSCRYPT
|
||||
if(worker->daemon->dnscenv) {
|
||||
s->svr.num_query_dnscrypt_secret_missed_cache =
|
||||
(long long)get_dnscrypt_cache_miss(worker, reset);
|
||||
s->svr.shared_secret_cache_count = (long long)count_slabhash_entries(
|
||||
worker->daemon->dnscenv->shared_secrets_cache);
|
||||
s->svr.nonce_cache_count = (long long)count_slabhash_entries(
|
||||
worker->daemon->dnscenv->nonces_cache);
|
||||
s->svr.num_query_dnscrypt_replay =
|
||||
(long long)get_dnscrypt_replay(worker, reset);
|
||||
} else {
|
||||
s->svr.num_query_dnscrypt_secret_missed_cache = 0;
|
||||
s->svr.shared_secret_cache_count = 0;
|
||||
s->svr.nonce_cache_count = 0;
|
||||
s->svr.num_query_dnscrypt_replay = 0;
|
||||
}
|
||||
#else
|
||||
s->svr.num_query_dnscrypt_secret_missed_cache = 0;
|
||||
s->svr.shared_secret_cache_count = 0;
|
||||
s->svr.nonce_cache_count = 0;
|
||||
s->svr.num_query_dnscrypt_replay = 0;
|
||||
#endif /* USE_DNSCRYPT */
|
||||
if(worker->env.auth_zones) {
|
||||
if(reset && !worker->env.cfg->stat_cumulative) {
|
||||
lock_rw_wrlock(&worker->env.auth_zones->lock);
|
||||
} else {
|
||||
lock_rw_rdlock(&worker->env.auth_zones->lock);
|
||||
}
|
||||
s->svr.num_query_authzone_up = (long long)worker->env.
|
||||
auth_zones->num_query_up;
|
||||
s->svr.num_query_authzone_down = (long long)worker->env.
|
||||
auth_zones->num_query_down;
|
||||
if(reset && !worker->env.cfg->stat_cumulative) {
|
||||
worker->env.auth_zones->num_query_up = 0;
|
||||
worker->env.auth_zones->num_query_down = 0;
|
||||
}
|
||||
lock_rw_unlock(&worker->env.auth_zones->lock);
|
||||
}
|
||||
|
||||
/* Set neg cache usage numbers */
|
||||
set_neg_cache_stats(worker, &s->svr, reset);
|
||||
|
||||
/* get tcp accept usage */
|
||||
s->svr.tcp_accept_usage = 0;
|
||||
for(lp = worker->front->cps; lp; lp = lp->next) {
|
||||
if(lp->com->type == comm_tcp_accept)
|
||||
s->svr.tcp_accept_usage += lp->com->cur_tcp_count;
|
||||
s->svr.tcp_accept_usage += (long long)lp->com->cur_tcp_count;
|
||||
}
|
||||
|
||||
if(reset && !worker->env.cfg->stat_cumulative) {
|
||||
@@ -191,7 +315,7 @@ server_stats_compile(struct worker* worker, struct stats_info* s, int reset)
|
||||
}
|
||||
|
||||
void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
struct stats_info* s, int reset)
|
||||
struct ub_stats_info* s, int reset)
|
||||
{
|
||||
uint8_t *reply = NULL;
|
||||
uint32_t len = 0;
|
||||
@@ -217,7 +341,7 @@ void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
|
||||
void server_stats_reply(struct worker* worker, int reset)
|
||||
{
|
||||
struct stats_info s;
|
||||
struct ub_stats_info s;
|
||||
server_stats_compile(worker, &s, reset);
|
||||
verbose(VERB_ALGO, "write stats replymsg");
|
||||
if(!tube_write_msg(worker->daemon->workers[0]->cmd,
|
||||
@@ -225,7 +349,7 @@ void server_stats_reply(struct worker* worker, int reset)
|
||||
fatal_exit("could not write stat values over cmd channel");
|
||||
}
|
||||
|
||||
void server_stats_add(struct stats_info* total, struct stats_info* a)
|
||||
void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
||||
{
|
||||
total->svr.num_queries += a->svr.num_queries;
|
||||
total->svr.num_queries_ip_ratelimited += a->svr.num_queries_ip_ratelimited;
|
||||
@@ -233,13 +357,13 @@ void server_stats_add(struct stats_info* total, struct stats_info* a)
|
||||
total->svr.num_queries_prefetch += a->svr.num_queries_prefetch;
|
||||
total->svr.sum_query_list_size += a->svr.sum_query_list_size;
|
||||
#ifdef USE_DNSCRYPT
|
||||
total->svr.num_query_dnscrypt_crypted += a->svr.num_query_dnscrypt_crypted;
|
||||
total->svr.num_query_dnscrypt_cert += a->svr.num_query_dnscrypt_cert;
|
||||
total->svr.num_query_dnscrypt_cleartext += \
|
||||
a->svr.num_query_dnscrypt_cleartext;
|
||||
total->svr.num_query_dnscrypt_crypted_malformed += \
|
||||
a->svr.num_query_dnscrypt_crypted_malformed;
|
||||
#endif
|
||||
total->svr.num_query_dnscrypt_crypted += a->svr.num_query_dnscrypt_crypted;
|
||||
total->svr.num_query_dnscrypt_cert += a->svr.num_query_dnscrypt_cert;
|
||||
total->svr.num_query_dnscrypt_cleartext += \
|
||||
a->svr.num_query_dnscrypt_cleartext;
|
||||
total->svr.num_query_dnscrypt_crypted_malformed += \
|
||||
a->svr.num_query_dnscrypt_crypted_malformed;
|
||||
#endif /* USE_DNSCRYPT */
|
||||
/* the max size reached is upped to higher of both */
|
||||
if(a->svr.max_query_list_size > total->svr.max_query_list_size)
|
||||
total->svr.max_query_list_size = a->svr.max_query_list_size;
|
||||
@@ -265,17 +389,16 @@ void server_stats_add(struct stats_info* total, struct stats_info* a)
|
||||
total->svr.zero_ttl_responses += a->svr.zero_ttl_responses;
|
||||
total->svr.ans_secure += a->svr.ans_secure;
|
||||
total->svr.ans_bogus += a->svr.ans_bogus;
|
||||
total->svr.rrset_bogus += a->svr.rrset_bogus;
|
||||
total->svr.unwanted_replies += a->svr.unwanted_replies;
|
||||
total->svr.unwanted_queries += a->svr.unwanted_queries;
|
||||
total->svr.tcp_accept_usage += a->svr.tcp_accept_usage;
|
||||
for(i=0; i<STATS_QTYPE_NUM; i++)
|
||||
for(i=0; i<UB_STATS_QTYPE_NUM; i++)
|
||||
total->svr.qtype[i] += a->svr.qtype[i];
|
||||
for(i=0; i<STATS_QCLASS_NUM; i++)
|
||||
for(i=0; i<UB_STATS_QCLASS_NUM; i++)
|
||||
total->svr.qclass[i] += a->svr.qclass[i];
|
||||
for(i=0; i<STATS_OPCODE_NUM; i++)
|
||||
for(i=0; i<UB_STATS_OPCODE_NUM; i++)
|
||||
total->svr.qopcode[i] += a->svr.qopcode[i];
|
||||
for(i=0; i<STATS_RCODE_NUM; i++)
|
||||
for(i=0; i<UB_STATS_RCODE_NUM; i++)
|
||||
total->svr.ans_rcode[i] += a->svr.ans_rcode[i];
|
||||
for(i=0; i<NUM_BUCKETS_HIST; i++)
|
||||
total->svr.hist[i] += a->svr.hist[i];
|
||||
@@ -286,22 +409,22 @@ void server_stats_add(struct stats_info* total, struct stats_info* a)
|
||||
total->mesh_jostled += a->mesh_jostled;
|
||||
total->mesh_dropped += a->mesh_dropped;
|
||||
total->mesh_replies_sent += a->mesh_replies_sent;
|
||||
timeval_add(&total->mesh_replies_sum_wait, &a->mesh_replies_sum_wait);
|
||||
stats_timeval_add(&total->mesh_replies_sum_wait_sec, &total->mesh_replies_sum_wait_usec, a->mesh_replies_sum_wait_sec, a->mesh_replies_sum_wait_usec);
|
||||
/* the medians are averaged together, this is not as accurate as
|
||||
* taking the median over all of the data, but is good and fast
|
||||
* added up here, division later*/
|
||||
total->mesh_time_median += a->mesh_time_median;
|
||||
}
|
||||
|
||||
void server_stats_insquery(struct server_stats* stats, struct comm_point* c,
|
||||
void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
|
||||
uint16_t qtype, uint16_t qclass, struct edns_data* edns,
|
||||
struct comm_reply* repinfo)
|
||||
{
|
||||
uint16_t flags = sldns_buffer_read_u16_at(c->buffer, 2);
|
||||
if(qtype < STATS_QTYPE_NUM)
|
||||
if(qtype < UB_STATS_QTYPE_NUM)
|
||||
stats->qtype[qtype]++;
|
||||
else stats->qtype_big++;
|
||||
if(qclass < STATS_QCLASS_NUM)
|
||||
if(qclass < UB_STATS_QCLASS_NUM)
|
||||
stats->qclass[qclass]++;
|
||||
else stats->qclass_big++;
|
||||
stats->qopcode[ LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) ]++;
|
||||
@@ -332,7 +455,7 @@ void server_stats_insquery(struct server_stats* stats, struct comm_point* c,
|
||||
}
|
||||
}
|
||||
|
||||
void server_stats_insrcode(struct server_stats* stats, sldns_buffer* buf)
|
||||
void server_stats_insrcode(struct ub_server_stats* stats, sldns_buffer* buf)
|
||||
{
|
||||
if(stats->extended && sldns_buffer_limit(buf) != 0) {
|
||||
int r = (int)LDNS_RCODE_WIRE( sldns_buffer_begin(buf) );
|
||||
|
||||
+11
-144
@@ -43,7 +43,6 @@
|
||||
#ifndef DAEMON_STATS_H
|
||||
#define DAEMON_STATS_H
|
||||
#include "util/timehist.h"
|
||||
#include "dnscrypt/dnscrypt_config.h"
|
||||
struct worker;
|
||||
struct config_file;
|
||||
struct comm_point;
|
||||
@@ -51,156 +50,24 @@ struct comm_reply;
|
||||
struct edns_data;
|
||||
struct sldns_buffer;
|
||||
|
||||
/** number of qtype that is stored for in array */
|
||||
#define STATS_QTYPE_NUM 256
|
||||
/** number of qclass that is stored for in array */
|
||||
#define STATS_QCLASS_NUM 256
|
||||
/** number of rcodes in stats */
|
||||
#define STATS_RCODE_NUM 16
|
||||
/** number of opcodes in stats */
|
||||
#define STATS_OPCODE_NUM 16
|
||||
|
||||
/** per worker statistics */
|
||||
struct server_stats {
|
||||
/** number of queries from clients received. */
|
||||
size_t num_queries;
|
||||
/** number of queries that have been dropped/ratelimited by ip. */
|
||||
size_t num_queries_ip_ratelimited;
|
||||
/** number of queries that had a cache-miss. */
|
||||
size_t num_queries_missed_cache;
|
||||
/** number of prefetch queries - cachehits with prefetch */
|
||||
size_t num_queries_prefetch;
|
||||
|
||||
/**
|
||||
* Sum of the querylistsize of the worker for
|
||||
* every query that missed cache. To calculate average.
|
||||
*/
|
||||
size_t sum_query_list_size;
|
||||
/** max value of query list size reached. */
|
||||
size_t max_query_list_size;
|
||||
|
||||
/** Extended stats below (bool) */
|
||||
int extended;
|
||||
|
||||
/** qtype stats */
|
||||
size_t qtype[STATS_QTYPE_NUM];
|
||||
/** bigger qtype values not in array */
|
||||
size_t qtype_big;
|
||||
/** qclass stats */
|
||||
size_t qclass[STATS_QCLASS_NUM];
|
||||
/** bigger qclass values not in array */
|
||||
size_t qclass_big;
|
||||
/** query opcodes */
|
||||
size_t qopcode[STATS_OPCODE_NUM];
|
||||
/** number of queries over TCP */
|
||||
size_t qtcp;
|
||||
/** number of outgoing queries over TCP */
|
||||
size_t qtcp_outgoing;
|
||||
/** number of queries over IPv6 */
|
||||
size_t qipv6;
|
||||
/** number of queries with QR bit */
|
||||
size_t qbit_QR;
|
||||
/** number of queries with AA bit */
|
||||
size_t qbit_AA;
|
||||
/** number of queries with TC bit */
|
||||
size_t qbit_TC;
|
||||
/** number of queries with RD bit */
|
||||
size_t qbit_RD;
|
||||
/** number of queries with RA bit */
|
||||
size_t qbit_RA;
|
||||
/** number of queries with Z bit */
|
||||
size_t qbit_Z;
|
||||
/** number of queries with AD bit */
|
||||
size_t qbit_AD;
|
||||
/** number of queries with CD bit */
|
||||
size_t qbit_CD;
|
||||
/** number of queries with EDNS OPT record */
|
||||
size_t qEDNS;
|
||||
/** number of queries with EDNS with DO flag */
|
||||
size_t qEDNS_DO;
|
||||
/** answer rcodes */
|
||||
size_t ans_rcode[STATS_RCODE_NUM];
|
||||
/** answers with pseudo rcode 'nodata' */
|
||||
size_t ans_rcode_nodata;
|
||||
/** answers that were secure (AD) */
|
||||
size_t ans_secure;
|
||||
/** answers that were bogus (withheld as SERVFAIL) */
|
||||
size_t ans_bogus;
|
||||
/** rrsets marked bogus by validator */
|
||||
size_t rrset_bogus;
|
||||
/** unwanted traffic received on server-facing ports */
|
||||
size_t unwanted_replies;
|
||||
/** unwanted traffic received on client-facing ports */
|
||||
size_t unwanted_queries;
|
||||
/** usage of tcp accept list */
|
||||
size_t tcp_accept_usage;
|
||||
/** answers served from expired cache */
|
||||
size_t zero_ttl_responses;
|
||||
/** histogram data exported to array
|
||||
* if the array is the same size, no data is lost, and
|
||||
* if all histograms are same size (is so by default) then
|
||||
* adding up works well. */
|
||||
size_t hist[NUM_BUCKETS_HIST];
|
||||
|
||||
/** number of message cache entries */
|
||||
size_t msg_cache_count;
|
||||
/** number of rrset cache entries */
|
||||
size_t rrset_cache_count;
|
||||
/** number of infra cache entries */
|
||||
size_t infra_cache_count;
|
||||
/** number of key cache entries */
|
||||
size_t key_cache_count;
|
||||
#ifdef USE_DNSCRYPT
|
||||
/** number of queries that used dnscrypt */
|
||||
size_t num_query_dnscrypt_crypted;
|
||||
/** number of queries that queried dnscrypt certificates */
|
||||
size_t num_query_dnscrypt_cert;
|
||||
/** number of queries in clear text and not asking for the certificates */
|
||||
size_t num_query_dnscrypt_cleartext;
|
||||
/** number of malformed encrypted queries */
|
||||
size_t num_query_dnscrypt_crypted_malformed;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Statistics to send over the control pipe when asked
|
||||
* This struct is made to be memcpied, sent in binary.
|
||||
*/
|
||||
struct stats_info {
|
||||
/** the thread stats */
|
||||
struct server_stats svr;
|
||||
|
||||
/** mesh stats: current number of states */
|
||||
size_t mesh_num_states;
|
||||
/** mesh stats: current number of reply (user) states */
|
||||
size_t mesh_num_reply_states;
|
||||
/** mesh stats: number of reply states overwritten with a new one */
|
||||
size_t mesh_jostled;
|
||||
/** mesh stats: number of incoming queries dropped */
|
||||
size_t mesh_dropped;
|
||||
/** mesh stats: replies sent */
|
||||
size_t mesh_replies_sent;
|
||||
/** mesh stats: sum of waiting times for the replies */
|
||||
struct timeval mesh_replies_sum_wait;
|
||||
/** mesh stats: median of waiting times for replies (in sec) */
|
||||
double mesh_time_median;
|
||||
};
|
||||
/* stats struct */
|
||||
#include "libunbound/unbound.h"
|
||||
|
||||
/**
|
||||
* Initialize server stats to 0.
|
||||
* @param stats: what to init (this is alloced by the caller).
|
||||
* @param cfg: with extended statistics option.
|
||||
*/
|
||||
void server_stats_init(struct server_stats* stats, struct config_file* cfg);
|
||||
void server_stats_init(struct ub_server_stats* stats, struct config_file* cfg);
|
||||
|
||||
/** add query if it missed the cache */
|
||||
void server_stats_querymiss(struct server_stats* stats, struct worker* worker);
|
||||
void server_stats_querymiss(struct ub_server_stats* stats, struct worker* worker);
|
||||
|
||||
/** add query if was cached and also resulted in a prefetch */
|
||||
void server_stats_prefetch(struct server_stats* stats, struct worker* worker);
|
||||
void server_stats_prefetch(struct ub_server_stats* stats, struct worker* worker);
|
||||
|
||||
/** display the stats to the log */
|
||||
void server_stats_log(struct server_stats* stats, struct worker* worker,
|
||||
void server_stats_log(struct ub_server_stats* stats, struct worker* worker,
|
||||
int threadnum);
|
||||
|
||||
/**
|
||||
@@ -211,7 +78,7 @@ void server_stats_log(struct server_stats* stats, struct worker* worker,
|
||||
* @param reset: if stats can be reset.
|
||||
*/
|
||||
void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
struct stats_info* s, int reset);
|
||||
struct ub_stats_info* s, int reset);
|
||||
|
||||
/**
|
||||
* Compile stats into structure for this thread worker.
|
||||
@@ -221,7 +88,7 @@ void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
* @param reset: if true, depending on config stats are reset.
|
||||
* if false, statistics are not reset.
|
||||
*/
|
||||
void server_stats_compile(struct worker* worker, struct stats_info* s,
|
||||
void server_stats_compile(struct worker* worker, struct ub_stats_info* s,
|
||||
int reset);
|
||||
|
||||
/**
|
||||
@@ -237,7 +104,7 @@ void server_stats_reply(struct worker* worker, int reset);
|
||||
* @param total: sum of the two entries.
|
||||
* @param a: to add to it.
|
||||
*/
|
||||
void server_stats_add(struct stats_info* total, struct stats_info* a);
|
||||
void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a);
|
||||
|
||||
/**
|
||||
* Add stats for this query
|
||||
@@ -248,7 +115,7 @@ void server_stats_add(struct stats_info* total, struct stats_info* a);
|
||||
* @param edns: edns record
|
||||
* @param repinfo: reply info with remote address
|
||||
*/
|
||||
void server_stats_insquery(struct server_stats* stats, struct comm_point* c,
|
||||
void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
|
||||
uint16_t qtype, uint16_t qclass, struct edns_data* edns,
|
||||
struct comm_reply* repinfo);
|
||||
|
||||
@@ -257,6 +124,6 @@ void server_stats_insquery(struct server_stats* stats, struct comm_point* c,
|
||||
* @param stats: the stats
|
||||
* @param buf: buffer with rcode. If buffer is length0: not counted.
|
||||
*/
|
||||
void server_stats_insrcode(struct server_stats* stats, struct sldns_buffer* buf);
|
||||
void server_stats_insrcode(struct ub_server_stats* stats, struct sldns_buffer* buf);
|
||||
|
||||
#endif /* DAEMON_STATS_H */
|
||||
|
||||
+39
-23
@@ -128,6 +128,9 @@ static void usage(void)
|
||||
for(m = module_list_avail(); *m; m++)
|
||||
printf(" %s", *m);
|
||||
printf("\n");
|
||||
#ifdef USE_DNSCRYPT
|
||||
printf("DNSCrypt feature available\n");
|
||||
#endif
|
||||
printf("BSD licensed, see LICENSE in source package for details.\n");
|
||||
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
|
||||
ub_event_base_free(base);
|
||||
@@ -397,10 +400,10 @@ detach(void)
|
||||
#endif /* HAVE_DAEMON */
|
||||
}
|
||||
|
||||
/** daemonize, drop user priviliges and chroot if needed */
|
||||
/** daemonize, drop user privileges and chroot if needed */
|
||||
static void
|
||||
perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
const char** cfgfile)
|
||||
const char** cfgfile, int need_pidfile)
|
||||
{
|
||||
#ifdef HAVE_KILL
|
||||
int pidinchroot;
|
||||
@@ -418,6 +421,20 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
w_config_adjust_directory(cfg);
|
||||
#endif
|
||||
|
||||
/* read ssl keys while superuser and outside chroot */
|
||||
#ifdef HAVE_SSL
|
||||
if(!(daemon->rc = daemon_remote_create(cfg)))
|
||||
fatal_exit("could not set up remote-control");
|
||||
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
|
||||
if(!(daemon->listen_sslctx = listen_sslctx_create(
|
||||
cfg->ssl_service_key, cfg->ssl_service_pem, NULL)))
|
||||
fatal_exit("could not set up listen SSL_CTX");
|
||||
}
|
||||
if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL,
|
||||
cfg->tls_cert_bundle, cfg->tls_win_cert)))
|
||||
fatal_exit("could not set up connect SSL_CTX");
|
||||
#endif
|
||||
|
||||
/* init syslog (as root) if needed, before daemonize, otherwise
|
||||
* a fork error could not be printed since daemonize closed stderr.*/
|
||||
if(cfg->use_syslog) {
|
||||
@@ -429,28 +446,15 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
* So, using a logfile, the user does not see errors unless -d is
|
||||
* given to unbound on the commandline. */
|
||||
|
||||
/* read ssl keys while superuser and outside chroot */
|
||||
#ifdef HAVE_SSL
|
||||
if(!(daemon->rc = daemon_remote_create(cfg)))
|
||||
fatal_exit("could not set up remote-control");
|
||||
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
|
||||
if(!(daemon->listen_sslctx = listen_sslctx_create(
|
||||
cfg->ssl_service_key, cfg->ssl_service_pem, NULL)))
|
||||
fatal_exit("could not set up listen SSL_CTX");
|
||||
}
|
||||
if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL, NULL)))
|
||||
fatal_exit("could not set up connect SSL_CTX");
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_KILL
|
||||
/* true if pidfile is inside chrootdir, or nochroot */
|
||||
pidinchroot = !(cfg->chrootdir && cfg->chrootdir[0]) ||
|
||||
pidinchroot = need_pidfile && (!(cfg->chrootdir && cfg->chrootdir[0]) ||
|
||||
(cfg->chrootdir && cfg->chrootdir[0] &&
|
||||
strncmp(cfg->pidfile, cfg->chrootdir,
|
||||
strlen(cfg->chrootdir))==0);
|
||||
strlen(cfg->chrootdir))==0));
|
||||
|
||||
/* check old pid file before forking */
|
||||
if(cfg->pidfile && cfg->pidfile[0]) {
|
||||
if(cfg->pidfile && cfg->pidfile[0] && need_pidfile) {
|
||||
/* calculate position of pidfile */
|
||||
if(cfg->pidfile[0] == '/')
|
||||
daemon->pidfile = strdup(cfg->pidfile);
|
||||
@@ -469,7 +473,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
|
||||
/* write new pidfile (while still root, so can be outside chroot) */
|
||||
#ifdef HAVE_KILL
|
||||
if(cfg->pidfile && cfg->pidfile[0]) {
|
||||
if(cfg->pidfile && cfg->pidfile[0] && need_pidfile) {
|
||||
writepid(daemon->pidfile, getpid());
|
||||
if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1 &&
|
||||
pidinchroot) {
|
||||
@@ -484,6 +488,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
}
|
||||
#else
|
||||
(void)daemon;
|
||||
(void)need_pidfile;
|
||||
#endif /* HAVE_KILL */
|
||||
|
||||
/* Set user context */
|
||||
@@ -600,9 +605,10 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
* These increase verbosity as specified in the config file.
|
||||
* @param debug_mode: if set, do not daemonize.
|
||||
* @param log_default_identity: Default identity to report in logs
|
||||
* @param need_pidfile: if false, no pidfile is checked or created.
|
||||
*/
|
||||
static void
|
||||
run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char* log_default_identity)
|
||||
run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char* log_default_identity, int need_pidfile)
|
||||
{
|
||||
struct config_file* cfg = NULL;
|
||||
struct daemon* daemon = NULL;
|
||||
@@ -632,7 +638,7 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char*
|
||||
if(!daemon_open_shared_ports(daemon))
|
||||
fatal_exit("could not open ports");
|
||||
if(!done_setup) {
|
||||
perform_setup(daemon, cfg, debug_mode, &cfgfile);
|
||||
perform_setup(daemon, cfg, debug_mode, &cfgfile, need_pidfile);
|
||||
done_setup = 1;
|
||||
} else {
|
||||
/* reopen log after HUP to facilitate log rotation */
|
||||
@@ -682,6 +688,8 @@ main(int argc, char* argv[])
|
||||
const char* log_ident_default;
|
||||
int cmdline_verbose = 0;
|
||||
int debug_mode = 0;
|
||||
int need_pidfile = 1;
|
||||
|
||||
#ifdef UB_ON_WINDOWS
|
||||
int cmdline_cfg = 0;
|
||||
#endif
|
||||
@@ -690,7 +698,7 @@ main(int argc, char* argv[])
|
||||
log_ident_default = strrchr(argv[0],'/')?strrchr(argv[0],'/')+1:argv[0];
|
||||
log_ident_set(log_ident_default);
|
||||
/* parse the options */
|
||||
while( (c=getopt(argc, argv, "c:dhvw:")) != -1) {
|
||||
while( (c=getopt(argc, argv, "c:dhpvw:")) != -1) {
|
||||
switch(c) {
|
||||
case 'c':
|
||||
cfgfile = optarg;
|
||||
@@ -702,6 +710,9 @@ main(int argc, char* argv[])
|
||||
cmdline_verbose++;
|
||||
verbosity++;
|
||||
break;
|
||||
case 'p':
|
||||
need_pidfile = 0;
|
||||
break;
|
||||
case 'd':
|
||||
debug_mode++;
|
||||
break;
|
||||
@@ -732,7 +743,12 @@ main(int argc, char* argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
run_daemon(cfgfile, cmdline_verbose, debug_mode, log_ident_default);
|
||||
run_daemon(cfgfile, cmdline_verbose, debug_mode, log_ident_default, need_pidfile);
|
||||
log_init(NULL, 0, NULL); /* close logfile */
|
||||
#ifndef unbound_testbound
|
||||
if(log_get_lock()) {
|
||||
lock_quick_destroy((lock_quick_type*)log_get_lock());
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
+191
-62
@@ -58,6 +58,7 @@
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/authzone.h"
|
||||
#include "services/mesh.h"
|
||||
#include "services/localzone.h"
|
||||
#include "util/data/msgparse.h"
|
||||
@@ -341,7 +342,8 @@ worker_check_request(sldns_buffer* pkt, struct worker* worker)
|
||||
verbose(VERB_QUERY, "request bad, has TC bit on");
|
||||
return worker_err_ratelimit(worker, LDNS_RCODE_FORMERR);
|
||||
}
|
||||
if(LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_QUERY) {
|
||||
if(LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_QUERY &&
|
||||
LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_NOTIFY) {
|
||||
verbose(VERB_QUERY, "request unknown opcode %d",
|
||||
LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)));
|
||||
return worker_err_ratelimit(worker, LDNS_RCODE_NOTIMPL);
|
||||
@@ -351,7 +353,9 @@ worker_check_request(sldns_buffer* pkt, struct worker* worker)
|
||||
LDNS_QDCOUNT(sldns_buffer_begin(pkt)));
|
||||
return worker_err_ratelimit(worker, LDNS_RCODE_FORMERR);
|
||||
}
|
||||
if(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) != 0) {
|
||||
if(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) != 0 &&
|
||||
(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) != 1 ||
|
||||
LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_NOTIFY)) {
|
||||
verbose(VERB_QUERY, "request wrong nr an=%d",
|
||||
LDNS_ANCOUNT(sldns_buffer_begin(pkt)));
|
||||
return worker_err_ratelimit(worker, LDNS_RCODE_FORMERR);
|
||||
@@ -498,6 +502,7 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
* let validator do that */
|
||||
return 0;
|
||||
case sec_status_bogus:
|
||||
case sec_status_secure_sentinel_fail:
|
||||
/* some rrsets are bogus, reply servfail */
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
@@ -654,7 +659,8 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
}
|
||||
}
|
||||
/* check security status of the cached answer */
|
||||
if( rep->security == sec_status_bogus && must_validate) {
|
||||
if(must_validate && (rep->security == sec_status_bogus ||
|
||||
rep->security == sec_status_secure_sentinel_fail)) {
|
||||
/* BAD cached */
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
@@ -811,7 +817,9 @@ chaos_replystr(sldns_buffer* pkt, char** str, int num, struct edns_data* edns,
|
||||
if(!inplace_cb_reply_local_call(&worker->env, NULL, NULL, NULL,
|
||||
LDNS_RCODE_NOERROR, edns, worker->scratchpad))
|
||||
edns->opt_list = NULL;
|
||||
attach_edns_record(pkt, edns);
|
||||
if(sldns_buffer_capacity(pkt) >=
|
||||
sldns_buffer_limit(pkt)+calc_edns_field_size(edns))
|
||||
attach_edns_record(pkt, edns);
|
||||
}
|
||||
|
||||
/** Reply with one string */
|
||||
@@ -937,6 +945,66 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Answer notify queries. These are notifies for authoritative zones,
|
||||
* the reply is an ack that the notify has been received. We need to check
|
||||
* access permission here.
|
||||
* @param w: worker
|
||||
* @param qinfo: query info. Pointer into packet buffer.
|
||||
* @param edns: edns info from query.
|
||||
* @param repinfo: reply info with source address.
|
||||
* @param pkt: packet buffer.
|
||||
*/
|
||||
static void
|
||||
answer_notify(struct worker* w, struct query_info* qinfo,
|
||||
struct edns_data* edns, sldns_buffer* pkt, struct comm_reply* repinfo)
|
||||
{
|
||||
int refused = 0;
|
||||
int rcode = LDNS_RCODE_NOERROR;
|
||||
uint32_t serial = 0;
|
||||
int has_serial;
|
||||
if(!w->env.auth_zones) return;
|
||||
has_serial = auth_zone_parse_notify_serial(pkt, &serial);
|
||||
if(auth_zones_notify(w->env.auth_zones, &w->env, qinfo->qname,
|
||||
qinfo->qname_len, qinfo->qclass, &repinfo->addr,
|
||||
repinfo->addrlen, has_serial, serial, &refused)) {
|
||||
rcode = LDNS_RCODE_NOERROR;
|
||||
} else {
|
||||
if(refused)
|
||||
rcode = LDNS_RCODE_REFUSED;
|
||||
else rcode = LDNS_RCODE_SERVFAIL;
|
||||
}
|
||||
|
||||
if(verbosity >= VERB_DETAIL) {
|
||||
char buf[380];
|
||||
char zname[255+1];
|
||||
char sr[25];
|
||||
dname_str(qinfo->qname, zname);
|
||||
sr[0]=0;
|
||||
if(has_serial)
|
||||
snprintf(sr, sizeof(sr), "serial %u ",
|
||||
(unsigned)serial);
|
||||
if(rcode == LDNS_RCODE_REFUSED)
|
||||
snprintf(buf, sizeof(buf),
|
||||
"refused NOTIFY %sfor %s from", sr, zname);
|
||||
else if(rcode == LDNS_RCODE_SERVFAIL)
|
||||
snprintf(buf, sizeof(buf),
|
||||
"servfail for NOTIFY %sfor %s from", sr, zname);
|
||||
else snprintf(buf, sizeof(buf),
|
||||
"received NOTIFY %sfor %s from", sr, zname);
|
||||
log_addr(VERB_DETAIL, buf, &repinfo->addr, repinfo->addrlen);
|
||||
}
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns->ext_rcode = 0;
|
||||
edns->bits &= EDNS_DO;
|
||||
edns->opt_list = NULL;
|
||||
error_encode(pkt, rcode, qinfo,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(pkt),
|
||||
sldns_buffer_read_u16_at(pkt, 2), edns);
|
||||
LDNS_OPCODE_SET(sldns_buffer_begin(pkt), LDNS_PACKET_NOTIFY);
|
||||
}
|
||||
|
||||
static int
|
||||
deny_refuse(struct comm_point* c, enum acl_access acl,
|
||||
enum acl_access deny, enum acl_access refuse,
|
||||
@@ -1007,6 +1075,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
struct query_info* lookup_qinfo = &qinfo;
|
||||
struct query_info qinfo_tmp; /* placeholdoer for lookup_qinfo */
|
||||
struct respip_client_info* cinfo = NULL, cinfo_tmp;
|
||||
memset(&qinfo, 0, sizeof(qinfo));
|
||||
|
||||
if(error != NETEVENT_NOERROR) {
|
||||
/* some bad tcp query DNS formats give these error calls */
|
||||
@@ -1014,43 +1083,48 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
return 0;
|
||||
}
|
||||
#ifdef USE_DNSCRYPT
|
||||
repinfo->max_udp_size = worker->daemon->cfg->max_udp_size;
|
||||
if(!dnsc_handle_curved_request(worker->daemon->dnscenv, repinfo)) {
|
||||
worker->stats.num_query_dnscrypt_crypted_malformed++;
|
||||
return 0;
|
||||
}
|
||||
if(c->dnscrypt && !repinfo->is_dnscrypted) {
|
||||
char buf[LDNS_MAX_DOMAINLEN+1];
|
||||
// Check if this is unencrypted and asking for certs
|
||||
if(worker_check_request(c->buffer, worker) != 0) {
|
||||
verbose(VERB_ALGO, "dnscrypt: worker check request: bad query.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
if(!query_info_parse(&qinfo, c->buffer)) {
|
||||
verbose(VERB_ALGO, "dnscrypt: worker parse request: formerror.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
dname_str(qinfo.qname, buf);
|
||||
if(!(qinfo.qtype == LDNS_RR_TYPE_TXT &&
|
||||
strcasecmp(buf, worker->daemon->dnscenv->provider_name) == 0)) {
|
||||
verbose(VERB_ALGO,
|
||||
"dnscrypt: not TXT %s. Receive: %s %s",
|
||||
worker->daemon->dnscenv->provider_name,
|
||||
sldns_rr_descript(qinfo.qtype)->_name,
|
||||
buf);
|
||||
comm_point_drop_reply(repinfo);
|
||||
worker->stats.num_query_dnscrypt_cleartext++;
|
||||
return 0;
|
||||
}
|
||||
worker->stats.num_query_dnscrypt_cert++;
|
||||
sldns_buffer_rewind(c->buffer);
|
||||
} else if(c->dnscrypt && repinfo->is_dnscrypted) {
|
||||
worker->stats.num_query_dnscrypt_crypted++;
|
||||
}
|
||||
repinfo->max_udp_size = worker->daemon->cfg->max_udp_size;
|
||||
if(!dnsc_handle_curved_request(worker->daemon->dnscenv, repinfo)) {
|
||||
worker->stats.num_query_dnscrypt_crypted_malformed++;
|
||||
return 0;
|
||||
}
|
||||
if(c->dnscrypt && !repinfo->is_dnscrypted) {
|
||||
char buf[LDNS_MAX_DOMAINLEN+1];
|
||||
/* Check if this is unencrypted and asking for certs */
|
||||
if(worker_check_request(c->buffer, worker) != 0) {
|
||||
verbose(VERB_ALGO,
|
||||
"dnscrypt: worker check request: bad query.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr,
|
||||
repinfo->addrlen);
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
if(!query_info_parse(&qinfo, c->buffer)) {
|
||||
verbose(VERB_ALGO,
|
||||
"dnscrypt: worker parse request: formerror.");
|
||||
log_addr(VERB_CLIENT, "from", &repinfo->addr,
|
||||
repinfo->addrlen);
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
dname_str(qinfo.qname, buf);
|
||||
if(!(qinfo.qtype == LDNS_RR_TYPE_TXT &&
|
||||
strcasecmp(buf,
|
||||
worker->daemon->dnscenv->provider_name) == 0)) {
|
||||
verbose(VERB_ALGO,
|
||||
"dnscrypt: not TXT \"%s\". Received: %s \"%s\"",
|
||||
worker->daemon->dnscenv->provider_name,
|
||||
sldns_rr_descript(qinfo.qtype)->_name,
|
||||
buf);
|
||||
comm_point_drop_reply(repinfo);
|
||||
worker->stats.num_query_dnscrypt_cleartext++;
|
||||
return 0;
|
||||
}
|
||||
worker->stats.num_query_dnscrypt_cert++;
|
||||
sldns_buffer_rewind(c->buffer);
|
||||
} else if(c->dnscrypt && repinfo->is_dnscrypted) {
|
||||
worker->stats.num_query_dnscrypt_crypted++;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_DNSTAP
|
||||
if(worker->dtenv.log_client_query_messages)
|
||||
@@ -1104,6 +1178,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
if(!query_info_parse(&qinfo, c->buffer)) {
|
||||
verbose(VERB_ALGO, "worker parse request: formerror.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
memset(&qinfo, 0, sizeof(qinfo)); /* zero qinfo.qname */
|
||||
if(worker_err_ratelimit(worker, LDNS_RCODE_FORMERR) == -1) {
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
@@ -1182,7 +1257,9 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
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);
|
||||
attach_edns_record(c->buffer, &edns);
|
||||
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;
|
||||
}
|
||||
@@ -1226,6 +1303,12 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply;
|
||||
}
|
||||
if(LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) ==
|
||||
LDNS_PACKET_NOTIFY) {
|
||||
answer_notify(worker, &qinfo, &edns, c->buffer, repinfo);
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply;
|
||||
}
|
||||
if(local_zones_answer(worker->daemon->local_zones, &worker->env, &qinfo,
|
||||
&edns, c->buffer, worker->scratchpad, repinfo, acladdr->taglist,
|
||||
acladdr->taglen, acladdr->tag_actions,
|
||||
@@ -1240,6 +1323,22 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
server_stats_insrcode(&worker->stats, c->buffer);
|
||||
goto send_reply;
|
||||
}
|
||||
if(worker->env.auth_zones &&
|
||||
auth_zones_answer(worker->env.auth_zones, &worker->env,
|
||||
&qinfo, &edns, c->buffer, worker->scratchpad)) {
|
||||
regional_free_all(worker->scratchpad);
|
||||
if(sldns_buffer_limit(c->buffer) == 0) {
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
/* set RA for everyone that can have recursion (based on
|
||||
* access control list) */
|
||||
if(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer)) &&
|
||||
acl != acl_deny_non_local && acl != acl_refuse_non_local)
|
||||
LDNS_RA_SET(sldns_buffer_begin(c->buffer));
|
||||
server_stats_insrcode(&worker->stats, c->buffer);
|
||||
goto send_reply;
|
||||
}
|
||||
|
||||
/* We've looked in our local zones. If the answer isn't there, we
|
||||
* might need to bail out based on ACLs now. */
|
||||
@@ -1251,17 +1350,20 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If this request does not have the recursion bit set, verify
|
||||
* ACLs allow the recursion bit to be treated as set. */
|
||||
if(!(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) &&
|
||||
acl == acl_allow_setrd ) {
|
||||
LDNS_RD_SET(sldns_buffer_begin(c->buffer));
|
||||
}
|
||||
|
||||
/* If this request does not have the recursion bit set, verify
|
||||
* ACLs allow the snooping. */
|
||||
if(!(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) &&
|
||||
acl != acl_allow_snoop ) {
|
||||
sldns_buffer_set_limit(c->buffer, LDNS_HEADER_SIZE);
|
||||
sldns_buffer_write_at(c->buffer, 4,
|
||||
(uint8_t*)"\0\0\0\0\0\0\0\0", 8);
|
||||
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
|
||||
LDNS_RCODE_REFUSED);
|
||||
sldns_buffer_flip(c->buffer);
|
||||
error_encode(c->buffer, LDNS_RCODE_REFUSED, &qinfo,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), NULL);
|
||||
regional_free_all(worker->scratchpad);
|
||||
server_stats_insrcode(&worker->stats, c->buffer);
|
||||
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
|
||||
@@ -1315,11 +1417,11 @@ 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 */
|
||||
if(answer_from_cache(worker, &qinfo,
|
||||
if(answer_from_cache(worker, &qinfo,
|
||||
cinfo, &need_drop, &alias_rrset, &partial_rep,
|
||||
(struct reply_info*)e->data,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), repinfo,
|
||||
(struct reply_info*)e->data,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), repinfo,
|
||||
&edns)) {
|
||||
/* prefetch it if the prefetch TTL expired.
|
||||
* Note that if there is more than one pass
|
||||
@@ -1346,6 +1448,10 @@ lookup_cache:
|
||||
lock_rw_unlock(&e->lock);
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply;
|
||||
} else {
|
||||
/* Note that we've already released the
|
||||
* lock if we're here after prefetch. */
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
/* We've found a partial reply ending with an
|
||||
* alias. Replace the lookup qinfo for the
|
||||
@@ -1353,7 +1459,6 @@ lookup_cache:
|
||||
* (possibly) complete the reply. As we're
|
||||
* passing the "base" reply, there will be no
|
||||
* more alias chasing. */
|
||||
lock_rw_unlock(&e->lock);
|
||||
memset(&qinfo_tmp, 0, sizeof(qinfo_tmp));
|
||||
get_cname_target(alias_rrset, &qinfo_tmp.qname,
|
||||
&qinfo_tmp.qname_len);
|
||||
@@ -1420,9 +1525,9 @@ send_reply_rc:
|
||||
tv, 1, c->buffer);
|
||||
}
|
||||
#ifdef USE_DNSCRYPT
|
||||
if(!dnsc_handle_uncurved_request(repinfo)) {
|
||||
return 0;
|
||||
}
|
||||
if(!dnsc_handle_uncurved_request(repinfo)) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
@@ -1619,7 +1724,8 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
cfg->use_caps_bits_for_id, worker->ports, worker->numports,
|
||||
cfg->unwanted_threshold, cfg->outgoing_tcp_mss,
|
||||
&worker_alloc_cleanup, worker,
|
||||
cfg->do_udp, worker->daemon->connect_sslctx, cfg->delay_close,
|
||||
cfg->do_udp || cfg->udp_upstream_without_downstream,
|
||||
worker->daemon->connect_sslctx, cfg->delay_close,
|
||||
dtenv);
|
||||
if(!worker->back) {
|
||||
log_err("could not create outgoing sockets");
|
||||
@@ -1657,13 +1763,26 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
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;
|
||||
worker->env.alloc = &worker->alloc;
|
||||
worker->env.outnet = worker->back;
|
||||
worker->env.rnd = worker->rndstate;
|
||||
worker->env.scratch = worker->scratchpad;
|
||||
/* If case prefetch is triggered, the corresponding mesh will clear
|
||||
* the scratchpad for the module env in the middle of request handling.
|
||||
* It would be prone to a use-after-free kind of bug, so we avoid
|
||||
* sharing it with worker's own scratchpad at the cost of having
|
||||
* one more pad per worker. */
|
||||
worker->env.scratch = regional_create_custom(cfg->msg_buffer_size);
|
||||
if(!worker->env.scratch) {
|
||||
log_err("malloc failure");
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
worker->env.mesh = mesh_create(&worker->daemon->mods, &worker->env);
|
||||
worker->env.detach_subs = &mesh_detach_subs;
|
||||
worker->env.attach_sub = &mesh_attach_sub;
|
||||
worker->env.add_sub = &mesh_add_sub;
|
||||
worker->env.kill_sub = &mesh_state_delete;
|
||||
worker->env.detect_cycle = &mesh_detect_cycle;
|
||||
worker->env.scratch_buffer = sldns_buffer_new(cfg->msg_buffer_size);
|
||||
@@ -1697,6 +1816,14 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
comm_timer_set(worker->env.probe_timer, &tv);
|
||||
}
|
||||
}
|
||||
/* zone transfer tasks, setup once per process, if any */
|
||||
if(worker->env.auth_zones
|
||||
#ifndef THREADS_DISABLED
|
||||
&& worker->thread_num == 0
|
||||
#endif
|
||||
) {
|
||||
auth_xfer_pickup_initial(worker->env.auth_zones, &worker->env);
|
||||
}
|
||||
if(!worker->env.mesh || !worker->env.scratch_buffer) {
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
@@ -1748,6 +1875,7 @@ worker_delete(struct worker* worker)
|
||||
comm_base_delete(worker->base);
|
||||
ub_randfree(worker->rndstate);
|
||||
alloc_clear(&worker->alloc);
|
||||
regional_destroy(worker->env.scratch);
|
||||
regional_destroy(worker->scratchpad);
|
||||
free(worker);
|
||||
}
|
||||
@@ -1756,7 +1884,7 @@ struct outbound_entry*
|
||||
worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec,
|
||||
int want_dnssec, int nocaps, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* zone, size_t zonelen, int ssl_upstream,
|
||||
struct module_qstate* q)
|
||||
char* tls_auth_name, struct module_qstate* q)
|
||||
{
|
||||
struct worker* worker = q->env->worker;
|
||||
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
|
||||
@@ -1766,7 +1894,7 @@ worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec,
|
||||
e->qstate = q;
|
||||
e->qsent = outnet_serviced_query(worker->back, qinfo, flags, dnssec,
|
||||
want_dnssec, nocaps, q->env->cfg->tcp_upstream,
|
||||
ssl_upstream, addr, addrlen, zone, zonelen, q,
|
||||
ssl_upstream, tls_auth_name, addr, addrlen, zone, zonelen, q,
|
||||
worker_handle_service_reply, e, worker->back->udp_buff, q->env);
|
||||
if(!e->qsent) {
|
||||
return NULL;
|
||||
@@ -1813,7 +1941,8 @@ struct outbound_entry* libworker_send_query(
|
||||
int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen),
|
||||
uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
|
||||
int ATTR_UNUSED(ssl_upstream), struct module_qstate* ATTR_UNUSED(q))
|
||||
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
|
||||
struct module_qstate* ATTR_UNUSED(q))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
|
||||
+1
-1
@@ -116,7 +116,7 @@ struct worker {
|
||||
/** allocation cache for this thread */
|
||||
struct alloc_cache alloc;
|
||||
/** per thread statistics */
|
||||
struct server_stats stats;
|
||||
struct ub_server_stats stats;
|
||||
/** thread scratch regional */
|
||||
struct regional* scratchpad;
|
||||
|
||||
|
||||
@@ -540,6 +540,7 @@ dns64_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
case module_event_new:
|
||||
/* Tag this query as being new and fall through. */
|
||||
qstate->minfo[id] = (void*)DNS64_NEW_QUERY;
|
||||
/* fallthrough */
|
||||
case module_event_pass:
|
||||
qstate->ext_state[id] = handle_event_pass(qstate, id);
|
||||
break;
|
||||
@@ -791,6 +792,10 @@ dns64_inform_super(struct module_qstate* qstate, int id,
|
||||
qstate->return_msg->rep))
|
||||
return;
|
||||
|
||||
/* Use return code from A query in response to client. */
|
||||
if (super->return_rcode != LDNS_RCODE_NOERROR)
|
||||
super->return_rcode = qstate->return_rcode;
|
||||
|
||||
/* Generate a response suitable for the original query. */
|
||||
if (qstate->qinfo.qtype == LDNS_RR_TYPE_A) {
|
||||
dns64_adjust_a(id, super, qstate);
|
||||
|
||||
+1
-1
@@ -20,12 +20,12 @@ struct SignedCert {
|
||||
uint8_t version_minor[2];
|
||||
|
||||
// Signed Content
|
||||
uint8_t signed_content[64];
|
||||
uint8_t server_publickey[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t magic_query[8];
|
||||
uint8_t serial[4];
|
||||
uint8_t ts_begin[4];
|
||||
uint8_t ts_end[4];
|
||||
uint8_t end[64];
|
||||
};
|
||||
|
||||
|
||||
|
||||
+667
-83
@@ -5,6 +5,7 @@
|
||||
#ifdef HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <inttypes.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include "sldns/sbuffer.h"
|
||||
@@ -12,19 +13,24 @@
|
||||
#include "util/net_help.h"
|
||||
#include "util/netevent.h"
|
||||
#include "util/log.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/storage/lookup3.h"
|
||||
|
||||
#include "dnscrypt/cert.h"
|
||||
#include "dnscrypt/dnscrypt.h"
|
||||
#include "dnscrypt/dnscrypt_config.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
/**
|
||||
* \file
|
||||
* dnscrypt functions for encrypting DNS packets.
|
||||
*/
|
||||
|
||||
#define DNSCRYPT_QUERY_BOX_OFFSET \
|
||||
(DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_PUBLICKEYBYTES + crypto_box_HALF_NONCEBYTES)
|
||||
(DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_PUBLICKEYBYTES + \
|
||||
crypto_box_HALF_NONCEBYTES)
|
||||
|
||||
// 8 bytes: magic header (CERT_MAGIC_HEADER)
|
||||
// 12 bytes: the client's nonce
|
||||
@@ -32,21 +38,211 @@
|
||||
// 16 bytes: Poly1305 MAC (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
|
||||
|
||||
#define DNSCRYPT_REPLY_BOX_OFFSET \
|
||||
(DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_HALF_NONCEBYTES + crypto_box_HALF_NONCEBYTES)
|
||||
(DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_HALF_NONCEBYTES + \
|
||||
crypto_box_HALF_NONCEBYTES)
|
||||
|
||||
|
||||
/**
|
||||
* Decrypt a query using the keypair that was found using dnsc_find_keypair.
|
||||
* Shared secret cache key length.
|
||||
* secret key.
|
||||
* 1 byte: ES_VERSION[1]
|
||||
* 32 bytes: client crypto_box_PUBLICKEYBYTES
|
||||
* 32 bytes: server crypto_box_SECRETKEYBYTES
|
||||
*/
|
||||
#define DNSCRYPT_SHARED_SECRET_KEY_LENGTH \
|
||||
(1 + crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES)
|
||||
|
||||
|
||||
struct shared_secret_cache_key {
|
||||
/** the hash table key */
|
||||
uint8_t key[DNSCRYPT_SHARED_SECRET_KEY_LENGTH];
|
||||
/** the hash table entry, data is uint8_t pointer of size crypto_box_BEFORENMBYTES which contains the shared secret. */
|
||||
struct lruhash_entry entry;
|
||||
};
|
||||
|
||||
|
||||
struct nonce_cache_key {
|
||||
/** the nonce used by the client */
|
||||
uint8_t nonce[crypto_box_HALF_NONCEBYTES];
|
||||
/** the client_magic used by the client, this is associated to 1 cert only */
|
||||
uint8_t magic_query[DNSCRYPT_MAGIC_HEADER_LEN];
|
||||
/** the client public key */
|
||||
uint8_t client_publickey[crypto_box_PUBLICKEYBYTES];
|
||||
/** the hash table entry, data is uint8_t */
|
||||
struct lruhash_entry entry;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a key suitable to find shared secret in slabhash.
|
||||
* \param[in] key: a uint8_t pointer of size DNSCRYPT_SHARED_SECRET_KEY_LENGTH
|
||||
* \param[in] esversion: The es version least significant byte.
|
||||
* \param[in] pk: The public key of the client. uint8_t pointer of size
|
||||
* crypto_box_PUBLICKEYBYTES.
|
||||
* \param[in] sk: The secret key of the server matching the magic query number.
|
||||
* uint8_t pointer of size crypto_box_SECRETKEYBYTES.
|
||||
* \return the hash of the key.
|
||||
*/
|
||||
static uint32_t
|
||||
dnsc_shared_secrets_cache_key(uint8_t* key,
|
||||
uint8_t esversion,
|
||||
uint8_t* pk,
|
||||
uint8_t* sk)
|
||||
{
|
||||
key[0] = esversion;
|
||||
memcpy(key + 1, pk, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(key + 1 + crypto_box_PUBLICKEYBYTES, sk, crypto_box_SECRETKEYBYTES);
|
||||
return hashlittle(key, DNSCRYPT_SHARED_SECRET_KEY_LENGTH, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a shared secret into the shared_secrets_cache slabhash.
|
||||
* The shared secret is copied so the caller can use it freely without caring
|
||||
* about the cache entry being evicted or not.
|
||||
* \param[in] cache: the slabhash in which to look for the key.
|
||||
* \param[in] key: a uint8_t pointer of size DNSCRYPT_SHARED_SECRET_KEY_LENGTH
|
||||
* which contains the key of the shared secret.
|
||||
* \param[in] hash: the hash of the key.
|
||||
* \param[in] nmkey: a uint8_t pointer of size crypto_box_BEFORENMBYTES which
|
||||
* contains the shared secret.
|
||||
*/
|
||||
static void
|
||||
dnsc_shared_secret_cache_insert(struct slabhash *cache,
|
||||
uint8_t key[DNSCRYPT_SHARED_SECRET_KEY_LENGTH],
|
||||
uint32_t hash,
|
||||
uint8_t nmkey[crypto_box_BEFORENMBYTES])
|
||||
{
|
||||
struct shared_secret_cache_key* k =
|
||||
(struct shared_secret_cache_key*)calloc(1, sizeof(*k));
|
||||
uint8_t* d = malloc(crypto_box_BEFORENMBYTES);
|
||||
if(!k || !d) {
|
||||
free(k);
|
||||
free(d);
|
||||
return;
|
||||
}
|
||||
memcpy(d, nmkey, crypto_box_BEFORENMBYTES);
|
||||
lock_rw_init(&k->entry.lock);
|
||||
memcpy(k->key, key, DNSCRYPT_SHARED_SECRET_KEY_LENGTH);
|
||||
k->entry.hash = hash;
|
||||
k->entry.key = k;
|
||||
k->entry.data = d;
|
||||
slabhash_insert(cache,
|
||||
hash, &k->entry,
|
||||
d,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a record in shared_secrets_cache.
|
||||
* \param[in] cache: a pointer to shared_secrets_cache slabhash.
|
||||
* \param[in] key: a uint8_t pointer of size DNSCRYPT_SHARED_SECRET_KEY_LENGTH
|
||||
* containing the key to look for.
|
||||
* \param[in] hash: a hash of the key.
|
||||
* \return a pointer to the locked cache entry or NULL on failure.
|
||||
*/
|
||||
static struct lruhash_entry*
|
||||
dnsc_shared_secrets_lookup(struct slabhash* cache,
|
||||
uint8_t key[DNSCRYPT_SHARED_SECRET_KEY_LENGTH],
|
||||
uint32_t hash)
|
||||
{
|
||||
return slabhash_lookup(cache, hash, key, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a key hash suitable to find a nonce in slabhash.
|
||||
* \param[in] nonce: a uint8_t pointer of size crypto_box_HALF_NONCEBYTES
|
||||
* \param[in] magic_query: a uint8_t pointer of size DNSCRYPT_MAGIC_HEADER_LEN
|
||||
* \param[in] pk: The public key of the client. uint8_t pointer of size
|
||||
* crypto_box_PUBLICKEYBYTES.
|
||||
* \return the hash of the key.
|
||||
*/
|
||||
static uint32_t
|
||||
dnsc_nonce_cache_key_hash(const uint8_t nonce[crypto_box_HALF_NONCEBYTES],
|
||||
const uint8_t magic_query[DNSCRYPT_MAGIC_HEADER_LEN],
|
||||
const uint8_t pk[crypto_box_PUBLICKEYBYTES])
|
||||
{
|
||||
uint32_t h = 0;
|
||||
h = hashlittle(nonce, crypto_box_HALF_NONCEBYTES, h);
|
||||
h = hashlittle(magic_query, DNSCRYPT_MAGIC_HEADER_LEN, h);
|
||||
return hashlittle(pk, crypto_box_PUBLICKEYBYTES, h);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a nonce, magic_query, pk tuple into the nonces_cache slabhash.
|
||||
* \param[in] cache: the slabhash in which to look for the key.
|
||||
* \param[in] nonce: a uint8_t pointer of size crypto_box_HALF_NONCEBYTES
|
||||
* \param[in] magic_query: a uint8_t pointer of size DNSCRYPT_MAGIC_HEADER_LEN
|
||||
* \param[in] pk: The public key of the client. uint8_t pointer of size
|
||||
* crypto_box_PUBLICKEYBYTES.
|
||||
* \param[in] hash: the hash of the key.
|
||||
*/
|
||||
static void
|
||||
dnsc_nonce_cache_insert(struct slabhash *cache,
|
||||
const uint8_t nonce[crypto_box_HALF_NONCEBYTES],
|
||||
const uint8_t magic_query[DNSCRYPT_MAGIC_HEADER_LEN],
|
||||
const uint8_t pk[crypto_box_PUBLICKEYBYTES],
|
||||
uint32_t hash)
|
||||
{
|
||||
struct nonce_cache_key* k =
|
||||
(struct nonce_cache_key*)calloc(1, sizeof(*k));
|
||||
if(!k) {
|
||||
free(k);
|
||||
return;
|
||||
}
|
||||
lock_rw_init(&k->entry.lock);
|
||||
memcpy(k->nonce, nonce, crypto_box_HALF_NONCEBYTES);
|
||||
memcpy(k->magic_query, magic_query, DNSCRYPT_MAGIC_HEADER_LEN);
|
||||
memcpy(k->client_publickey, pk, crypto_box_PUBLICKEYBYTES);
|
||||
k->entry.hash = hash;
|
||||
k->entry.key = k;
|
||||
k->entry.data = NULL;
|
||||
slabhash_insert(cache,
|
||||
hash, &k->entry,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a record in nonces_cache.
|
||||
* \param[in] cache: the slabhash in which to look for the key.
|
||||
* \param[in] nonce: a uint8_t pointer of size crypto_box_HALF_NONCEBYTES
|
||||
* \param[in] magic_query: a uint8_t pointer of size DNSCRYPT_MAGIC_HEADER_LEN
|
||||
* \param[in] pk: The public key of the client. uint8_t pointer of size
|
||||
* crypto_box_PUBLICKEYBYTES.
|
||||
* \param[in] hash: the hash of the key.
|
||||
* \return a pointer to the locked cache entry or NULL on failure.
|
||||
*/
|
||||
static struct lruhash_entry*
|
||||
dnsc_nonces_lookup(struct slabhash* cache,
|
||||
const uint8_t nonce[crypto_box_HALF_NONCEBYTES],
|
||||
const uint8_t magic_query[DNSCRYPT_MAGIC_HEADER_LEN],
|
||||
const uint8_t pk[crypto_box_PUBLICKEYBYTES],
|
||||
uint32_t hash)
|
||||
{
|
||||
struct nonce_cache_key k;
|
||||
memset(&k, 0, sizeof(k));
|
||||
k.entry.hash = hash;
|
||||
memcpy(k.nonce, nonce, crypto_box_HALF_NONCEBYTES);
|
||||
memcpy(k.magic_query, magic_query, DNSCRYPT_MAGIC_HEADER_LEN);
|
||||
memcpy(k.client_publickey, pk, crypto_box_PUBLICKEYBYTES);
|
||||
|
||||
return slabhash_lookup(cache, hash, &k, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt a query using the dnsccert that was found using dnsc_find_cert.
|
||||
* The client nonce will be extracted from the encrypted query and stored in
|
||||
* client_nonce, a shared secret will be computed and stored in nmkey and the
|
||||
* buffer will be decrypted inplace.
|
||||
* \param[in] keypair the keypair that matches this encrypted query.
|
||||
* \param[in] env the dnscrypt environment.
|
||||
* \param[in] cert the cert that matches this encrypted query.
|
||||
* \param[in] client_nonce where the client nonce will be stored.
|
||||
* \param[in] nmkey where the shared secret key will be written.
|
||||
* \param[in] buffer the encrypted buffer.
|
||||
* \return 0 on success.
|
||||
*/
|
||||
static int
|
||||
dnscrypt_server_uncurve(const KeyPair *keypair,
|
||||
dnscrypt_server_uncurve(struct dnsc_env* env,
|
||||
const dnsccert *cert,
|
||||
uint8_t client_nonce[crypto_box_HALF_NONCEBYTES],
|
||||
uint8_t nmkey[crypto_box_BEFORENMBYTES],
|
||||
struct sldns_buffer* buffer)
|
||||
@@ -55,46 +251,127 @@ dnscrypt_server_uncurve(const KeyPair *keypair,
|
||||
uint8_t *const buf = sldns_buffer_begin(buffer);
|
||||
uint8_t nonce[crypto_box_NONCEBYTES];
|
||||
struct dnscrypt_query_header *query_header;
|
||||
// shared secret cache
|
||||
uint8_t key[DNSCRYPT_SHARED_SECRET_KEY_LENGTH];
|
||||
struct lruhash_entry* entry;
|
||||
uint32_t hash;
|
||||
|
||||
uint32_t nonce_hash;
|
||||
|
||||
if (len <= DNSCRYPT_QUERY_HEADER_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
query_header = (struct dnscrypt_query_header *)buf;
|
||||
memcpy(nmkey, query_header->publickey, crypto_box_PUBLICKEYBYTES);
|
||||
if (crypto_box_beforenm(nmkey, nmkey, keypair->crypt_secretkey) != 0) {
|
||||
|
||||
/* Detect replay attacks */
|
||||
nonce_hash = dnsc_nonce_cache_key_hash(
|
||||
query_header->nonce,
|
||||
cert->magic_query,
|
||||
query_header->publickey);
|
||||
|
||||
lock_basic_lock(&env->nonces_cache_lock);
|
||||
entry = dnsc_nonces_lookup(
|
||||
env->nonces_cache,
|
||||
query_header->nonce,
|
||||
cert->magic_query,
|
||||
query_header->publickey,
|
||||
nonce_hash);
|
||||
|
||||
if(entry) {
|
||||
lock_rw_unlock(&entry->lock);
|
||||
env->num_query_dnscrypt_replay++;
|
||||
lock_basic_unlock(&env->nonces_cache_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dnsc_nonce_cache_insert(
|
||||
env->nonces_cache,
|
||||
query_header->nonce,
|
||||
cert->magic_query,
|
||||
query_header->publickey,
|
||||
nonce_hash);
|
||||
lock_basic_unlock(&env->nonces_cache_lock);
|
||||
|
||||
/* Find existing shared secret */
|
||||
hash = dnsc_shared_secrets_cache_key(key,
|
||||
cert->es_version[1],
|
||||
query_header->publickey,
|
||||
cert->keypair->crypt_secretkey);
|
||||
entry = dnsc_shared_secrets_lookup(env->shared_secrets_cache,
|
||||
key,
|
||||
hash);
|
||||
|
||||
if(!entry) {
|
||||
lock_basic_lock(&env->shared_secrets_cache_lock);
|
||||
env->num_query_dnscrypt_secret_missed_cache++;
|
||||
lock_basic_unlock(&env->shared_secrets_cache_lock);
|
||||
if(cert->es_version[1] == 2) {
|
||||
#ifdef USE_DNSCRYPT_XCHACHA20
|
||||
if (crypto_box_curve25519xchacha20poly1305_beforenm(
|
||||
nmkey, query_header->publickey,
|
||||
cert->keypair->crypt_secretkey) != 0) {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
} else {
|
||||
if (crypto_box_beforenm(nmkey,
|
||||
query_header->publickey,
|
||||
cert->keypair->crypt_secretkey) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// Cache the shared secret we just computed.
|
||||
dnsc_shared_secret_cache_insert(env->shared_secrets_cache,
|
||||
key,
|
||||
hash,
|
||||
nmkey);
|
||||
} else {
|
||||
/* copy shared secret and unlock entry */
|
||||
memcpy(nmkey, entry->data, crypto_box_BEFORENMBYTES);
|
||||
lock_rw_unlock(&entry->lock);
|
||||
}
|
||||
|
||||
memcpy(nonce, query_header->nonce, crypto_box_HALF_NONCEBYTES);
|
||||
memset(nonce + crypto_box_HALF_NONCEBYTES, 0, crypto_box_HALF_NONCEBYTES);
|
||||
|
||||
sldns_buffer_set_at(buffer,
|
||||
DNSCRYPT_QUERY_BOX_OFFSET - crypto_box_BOXZEROBYTES,
|
||||
0, crypto_box_BOXZEROBYTES);
|
||||
|
||||
if (crypto_box_open_afternm
|
||||
(buf + DNSCRYPT_QUERY_BOX_OFFSET - crypto_box_BOXZEROBYTES,
|
||||
buf + DNSCRYPT_QUERY_BOX_OFFSET - crypto_box_BOXZEROBYTES,
|
||||
len - DNSCRYPT_QUERY_BOX_OFFSET + crypto_box_BOXZEROBYTES, nonce,
|
||||
nmkey) != 0) {
|
||||
if(cert->es_version[1] == 2) {
|
||||
#ifdef USE_DNSCRYPT_XCHACHA20
|
||||
if (crypto_box_curve25519xchacha20poly1305_open_easy_afternm
|
||||
(buf,
|
||||
buf + DNSCRYPT_QUERY_BOX_OFFSET,
|
||||
len - DNSCRYPT_QUERY_BOX_OFFSET, nonce,
|
||||
nmkey) != 0) {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
} else {
|
||||
if (crypto_box_open_easy_afternm
|
||||
(buf,
|
||||
buf + DNSCRYPT_QUERY_BOX_OFFSET,
|
||||
len - DNSCRYPT_QUERY_BOX_OFFSET, nonce,
|
||||
nmkey) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
len -= DNSCRYPT_QUERY_HEADER_SIZE;
|
||||
|
||||
while (*sldns_buffer_at(buffer, --len) == 0)
|
||||
;
|
||||
;
|
||||
|
||||
if (*sldns_buffer_at(buffer, len) != 0x80) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(client_nonce, nonce, crypto_box_HALF_NONCEBYTES);
|
||||
memmove(sldns_buffer_begin(buffer),
|
||||
sldns_buffer_at(buffer, DNSCRYPT_QUERY_HEADER_SIZE),
|
||||
len - DNSCRYPT_QUERY_HEADER_SIZE);
|
||||
|
||||
sldns_buffer_set_position(buffer, 0);
|
||||
sldns_buffer_set_limit(buffer, len - DNSCRYPT_QUERY_HEADER_SIZE);
|
||||
sldns_buffer_set_limit(buffer, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -151,7 +428,7 @@ dnscrypt_hrtime(void)
|
||||
if (ret == 0) {
|
||||
ts = (uint64_t)tv.tv_sec * 1000000U + (uint64_t)tv.tv_usec;
|
||||
} else {
|
||||
log_err("gettimeofday: %s", strerror(errno));
|
||||
log_err("gettimeofday: %s", strerror(errno));
|
||||
}
|
||||
return ts;
|
||||
}
|
||||
@@ -182,10 +459,10 @@ add_server_nonce(uint8_t *nonce)
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt a reply using the keypair that was used with the query.
|
||||
* Encrypt a reply using the dnsccert that was used with the query.
|
||||
* The client nonce will be extracted from the encrypted query and stored in
|
||||
* The buffer will be encrypted inplace.
|
||||
* \param[in] keypair the keypair that matches this encrypted query.
|
||||
* \param[in] cert the dnsccert that matches this encrypted query.
|
||||
* \param[in] client_nonce client nonce used during the query
|
||||
* \param[in] nmkey shared secret key used during the query.
|
||||
* \param[in] buffer the buffer where to encrypt the reply.
|
||||
@@ -194,7 +471,7 @@ add_server_nonce(uint8_t *nonce)
|
||||
* \return 0 on success.
|
||||
*/
|
||||
static int
|
||||
dnscrypt_server_curve(const KeyPair *keypair,
|
||||
dnscrypt_server_curve(const dnsccert *cert,
|
||||
uint8_t client_nonce[crypto_box_HALF_NONCEBYTES],
|
||||
uint8_t nmkey[crypto_box_BEFORENMBYTES],
|
||||
struct sldns_buffer* buffer,
|
||||
@@ -202,7 +479,8 @@ dnscrypt_server_curve(const KeyPair *keypair,
|
||||
size_t max_udp_size)
|
||||
{
|
||||
size_t dns_reply_len = sldns_buffer_limit(buffer);
|
||||
size_t max_len = dns_reply_len + DNSCRYPT_MAX_PADDING + DNSCRYPT_REPLY_HEADER_SIZE;
|
||||
size_t max_len = dns_reply_len + DNSCRYPT_MAX_PADDING \
|
||||
+ DNSCRYPT_REPLY_HEADER_SIZE;
|
||||
size_t max_reply_size = max_udp_size - 20U - 8U;
|
||||
uint8_t nonce[crypto_box_NONCEBYTES];
|
||||
uint8_t *boxed;
|
||||
@@ -223,7 +501,7 @@ dnscrypt_server_curve(const KeyPair *keypair,
|
||||
memmove(boxed + crypto_box_MACBYTES, buf, len);
|
||||
len = dnscrypt_pad(boxed + crypto_box_MACBYTES, len,
|
||||
max_len - DNSCRYPT_REPLY_HEADER_SIZE, nonce,
|
||||
keypair->crypt_secretkey);
|
||||
cert->keypair->crypt_secretkey);
|
||||
sldns_buffer_set_at(buffer,
|
||||
DNSCRYPT_REPLY_BOX_OFFSET - crypto_box_BOXZEROBYTES,
|
||||
0, crypto_box_ZEROBYTES);
|
||||
@@ -231,14 +509,30 @@ dnscrypt_server_curve(const KeyPair *keypair,
|
||||
// add server nonce extension
|
||||
add_server_nonce(nonce);
|
||||
|
||||
if (crypto_box_afternm
|
||||
(boxed - crypto_box_BOXZEROBYTES, boxed - crypto_box_BOXZEROBYTES,
|
||||
len + crypto_box_ZEROBYTES, nonce, nmkey) != 0) {
|
||||
if(cert->es_version[1] == 2) {
|
||||
#ifdef USE_DNSCRYPT_XCHACHA20
|
||||
if (crypto_box_curve25519xchacha20poly1305_easy_afternm
|
||||
(boxed, boxed + crypto_box_MACBYTES, len, nonce, nmkey) != 0) {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
} else {
|
||||
if (crypto_box_easy_afternm
|
||||
(boxed, boxed + crypto_box_MACBYTES, len, nonce, nmkey) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
sldns_buffer_write_at(buffer, 0, DNSCRYPT_MAGIC_RESPONSE, DNSCRYPT_MAGIC_HEADER_LEN);
|
||||
sldns_buffer_write_at(buffer, DNSCRYPT_MAGIC_HEADER_LEN, nonce, crypto_box_NONCEBYTES);
|
||||
sldns_buffer_write_at(buffer,
|
||||
0,
|
||||
DNSCRYPT_MAGIC_RESPONSE,
|
||||
DNSCRYPT_MAGIC_HEADER_LEN);
|
||||
sldns_buffer_write_at(buffer,
|
||||
DNSCRYPT_MAGIC_HEADER_LEN,
|
||||
nonce,
|
||||
crypto_box_NONCEBYTES);
|
||||
sldns_buffer_set_limit(buffer, len + DNSCRYPT_REPLY_HEADER_SIZE);
|
||||
return 0;
|
||||
}
|
||||
@@ -253,17 +547,36 @@ dnscrypt_server_curve(const KeyPair *keypair,
|
||||
static int
|
||||
dnsc_read_from_file(char *fname, char *buf, size_t count)
|
||||
{
|
||||
int fd;
|
||||
fd = open(fname, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (read(fd, buf, count) != (ssize_t)count) {
|
||||
close(fd);
|
||||
return -2;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
int fd;
|
||||
fd = open(fname, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (read(fd, buf, count) != (ssize_t)count) {
|
||||
close(fd);
|
||||
return -2;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an absolute path on the original root, returns the absolute path
|
||||
* within the chroot. If chroot is disabled, the path is not modified.
|
||||
* No char * is malloced so there is no need to free this.
|
||||
* \param[in] cfg the configuration.
|
||||
* \param[in] path the path from the original root.
|
||||
* \return the path from inside the chroot.
|
||||
*/
|
||||
static char *
|
||||
dnsc_chroot_path(struct config_file *cfg, char *path)
|
||||
{
|
||||
char *nm;
|
||||
nm = path;
|
||||
if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm,
|
||||
cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
|
||||
nm += strlen(cfg->chrootdir);
|
||||
return nm;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -276,24 +589,42 @@ dnsc_read_from_file(char *fname, char *buf, size_t count)
|
||||
static int
|
||||
dnsc_parse_certs(struct dnsc_env *env, struct config_file *cfg)
|
||||
{
|
||||
struct config_strlist *head;
|
||||
struct config_strlist *head, *head2;
|
||||
size_t signed_cert_id;
|
||||
size_t rotated_cert_id;
|
||||
char *nm;
|
||||
|
||||
env->signed_certs_count = 0U;
|
||||
env->rotated_certs_count = 0U;
|
||||
for (head = cfg->dnscrypt_provider_cert; head; head = head->next) {
|
||||
env->signed_certs_count++;
|
||||
}
|
||||
for (head = cfg->dnscrypt_provider_cert_rotated; head; head = head->next) {
|
||||
env->rotated_certs_count++;
|
||||
}
|
||||
env->signed_certs = sodium_allocarray(env->signed_certs_count,
|
||||
sizeof *env->signed_certs);
|
||||
|
||||
env->rotated_certs = sodium_allocarray(env->rotated_certs_count,
|
||||
sizeof env->signed_certs);
|
||||
signed_cert_id = 0U;
|
||||
rotated_cert_id = 0U;
|
||||
for(head = cfg->dnscrypt_provider_cert; head; head = head->next, signed_cert_id++) {
|
||||
nm = dnsc_chroot_path(cfg, head->str);
|
||||
if(dnsc_read_from_file(
|
||||
head->str,
|
||||
nm,
|
||||
(char *)(env->signed_certs + signed_cert_id),
|
||||
sizeof(struct SignedCert)) != 0) {
|
||||
fatal_exit("dnsc_parse_certs: failed to load %s: %s", head->str, strerror(errno));
|
||||
}
|
||||
for(head2 = cfg->dnscrypt_provider_cert_rotated; head2; head2 = head2->next) {
|
||||
if(strcmp(head->str, head2->str) == 0) {
|
||||
*(env->rotated_certs + rotated_cert_id) = env->signed_certs + signed_cert_id;
|
||||
rotated_cert_id++;
|
||||
verbose(VERB_OPS, "Cert %s is rotated and will not be distributed via DNS", head->str);
|
||||
break;
|
||||
}
|
||||
}
|
||||
verbose(VERB_OPS, "Loaded cert %s", head->str);
|
||||
}
|
||||
return signed_cert_id;
|
||||
@@ -326,16 +657,17 @@ dnsc_key_to_fingerprint(char fingerprint[80U], const uint8_t * const key)
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the keypair matching a DNSCrypt query.
|
||||
* \param[in] dnscenv The DNSCrypt enviroment, which contains the list of keys
|
||||
* Find the cert matching a DNSCrypt query.
|
||||
* \param[in] dnscenv The DNSCrypt environment, which contains the list of certs
|
||||
* supported by the server.
|
||||
* \param[in] buffer The encrypted DNS query.
|
||||
* \return a KeyPair * if we found a key pair matching the query, NULL otherwise.
|
||||
* \return a dnsccert * if we found a cert matching the magic_number of the
|
||||
* query, NULL otherwise.
|
||||
*/
|
||||
static const KeyPair *
|
||||
dnsc_find_keypair(struct dnsc_env* dnscenv, struct sldns_buffer* buffer)
|
||||
static const dnsccert *
|
||||
dnsc_find_cert(struct dnsc_env* dnscenv, struct sldns_buffer* buffer)
|
||||
{
|
||||
const KeyPair *keypairs = dnscenv->keypairs;
|
||||
const dnsccert *certs = dnscenv->certs;
|
||||
struct dnscrypt_query_header *dnscrypt_header;
|
||||
size_t i;
|
||||
|
||||
@@ -343,10 +675,10 @@ dnsc_find_keypair(struct dnsc_env* dnscenv, struct sldns_buffer* buffer)
|
||||
return NULL;
|
||||
}
|
||||
dnscrypt_header = (struct dnscrypt_query_header *)sldns_buffer_begin(buffer);
|
||||
for (i = 0U; i < dnscenv->keypairs_count; i++) {
|
||||
if (memcmp(keypairs[i].crypt_publickey, dnscrypt_header->magic_query,
|
||||
for (i = 0U; i < dnscenv->signed_certs_count; i++) {
|
||||
if (memcmp(certs[i].magic_query, dnscrypt_header->magic_query,
|
||||
DNSCRYPT_MAGIC_HEADER_LEN) == 0) {
|
||||
return &keypairs[i];
|
||||
return &certs[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@@ -357,7 +689,7 @@ dnsc_find_keypair(struct dnsc_env* dnscenv, struct sldns_buffer* buffer)
|
||||
* In order to be able to serve certs over TXT, we can reuse the local-zone and
|
||||
* local-data config option. The zone and qname are infered from the
|
||||
* provider_name and the content of the TXT record from the certificate content.
|
||||
* returns the number of certtificate TXT record that were loaded.
|
||||
* returns the number of certificate TXT record that were loaded.
|
||||
* < 0 in case of error.
|
||||
*/
|
||||
static int
|
||||
@@ -377,26 +709,54 @@ dnsc_load_local_data(struct dnsc_env* dnscenv, struct config_file *cfg)
|
||||
// 2.dnscrypt-cert.example.com 86400 IN TXT "DNSC......"
|
||||
for(i=0; i<dnscenv->signed_certs_count; i++) {
|
||||
const char *ttl_class_type = " 86400 IN TXT \"";
|
||||
int rotated_cert = 0;
|
||||
uint32_t serial;
|
||||
uint16_t rrlen;
|
||||
char* rr;
|
||||
struct SignedCert *cert = dnscenv->signed_certs + i;
|
||||
uint16_t rrlen = strlen(dnscenv->provider_name) +
|
||||
// Check if the certificate is being rotated and should not be published
|
||||
for(j=0; j<dnscenv->rotated_certs_count; j++){
|
||||
if(cert == dnscenv->rotated_certs[j]) {
|
||||
rotated_cert = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
memcpy(&serial, cert->serial, sizeof serial);
|
||||
serial = htonl(serial);
|
||||
if(rotated_cert) {
|
||||
verbose(VERB_OPS,
|
||||
"DNSCrypt: not adding cert with serial #%"
|
||||
PRIu32
|
||||
" to local-data as it is rotated",
|
||||
serial
|
||||
);
|
||||
continue;
|
||||
}
|
||||
rrlen = strlen(dnscenv->provider_name) +
|
||||
strlen(ttl_class_type) +
|
||||
4 * sizeof(struct SignedCert) + // worst case scenario
|
||||
1 + // trailing double quote
|
||||
1;
|
||||
char *rr = malloc(rrlen);
|
||||
rr = malloc(rrlen);
|
||||
if(!rr) {
|
||||
log_err("Could not allocate memory");
|
||||
return -2;
|
||||
}
|
||||
snprintf(rr, rrlen - 1, "%s 86400 IN TXT \"", dnscenv->provider_name);
|
||||
for(j=0; j<sizeof(struct SignedCert); j++) {
|
||||
int c = (int)*((const uint8_t *) cert + j);
|
||||
int c = (int)*((const uint8_t *) cert + j);
|
||||
if (isprint(c) && c != '"' && c != '\\') {
|
||||
snprintf(rr + strlen(rr), rrlen - 1 - strlen(rr), "%c", c);
|
||||
} else {
|
||||
snprintf(rr + strlen(rr), rrlen - 1 - strlen(rr), "\\%03d", c);
|
||||
}
|
||||
}
|
||||
verbose(VERB_OPS,
|
||||
"DNSCrypt: adding cert with serial #%"
|
||||
PRIu32
|
||||
" to local-data to config: %s",
|
||||
serial, rr
|
||||
);
|
||||
snprintf(rr + strlen(rr), rrlen - 1 - strlen(rr), "\"");
|
||||
cfg_strlist_insert(&cfg->local_data, strdup(rr));
|
||||
free(rr);
|
||||
@@ -404,9 +764,33 @@ dnsc_load_local_data(struct dnsc_env* dnscenv, struct config_file *cfg)
|
||||
return dnscenv->signed_certs_count;
|
||||
}
|
||||
|
||||
static const char *
|
||||
key_get_es_version(uint8_t version[2])
|
||||
{
|
||||
struct es_version {
|
||||
uint8_t es_version[2];
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct es_version es_versions[] = {
|
||||
{{0x00, 0x01}, "X25519-XSalsa20Poly1305"},
|
||||
{{0x00, 0x02}, "X25519-XChacha20Poly1305"},
|
||||
};
|
||||
int i;
|
||||
for(i=0; i < (int)sizeof(es_versions); i++){
|
||||
if(es_versions[i].es_version[0] == version[0] &&
|
||||
es_versions[i].es_version[1] == version[1]){
|
||||
return es_versions[i].name;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse the secret key files from `dnscrypt-secret-key` config and populates
|
||||
* a list of secret/public keys supported by dnscrypt listener.
|
||||
* a list of dnsccert with es_version, magic number and secret/public keys
|
||||
* supported by dnscrypt listener.
|
||||
* \param[in] env The dnsc_env structure which will hold the keypairs.
|
||||
* \param[in] cfg The config with the secret key file paths.
|
||||
*/
|
||||
@@ -414,33 +798,86 @@ static int
|
||||
dnsc_parse_keys(struct dnsc_env *env, struct config_file *cfg)
|
||||
{
|
||||
struct config_strlist *head;
|
||||
size_t keypair_id;
|
||||
size_t cert_id, keypair_id;
|
||||
size_t c;
|
||||
char *nm;
|
||||
|
||||
env->keypairs_count = 0U;
|
||||
for (head = cfg->dnscrypt_secret_key; head; head = head->next) {
|
||||
env->keypairs_count++;
|
||||
}
|
||||
env->keypairs = sodium_allocarray(env->keypairs_count,
|
||||
sizeof *env->keypairs);
|
||||
|
||||
env->keypairs = sodium_allocarray(env->keypairs_count,
|
||||
sizeof *env->keypairs);
|
||||
env->certs = sodium_allocarray(env->signed_certs_count,
|
||||
sizeof *env->certs);
|
||||
|
||||
cert_id = 0U;
|
||||
keypair_id = 0U;
|
||||
for(head = cfg->dnscrypt_secret_key; head; head = head->next, keypair_id++) {
|
||||
char fingerprint[80];
|
||||
int found_cert = 0;
|
||||
KeyPair *current_keypair = &env->keypairs[keypair_id];
|
||||
nm = dnsc_chroot_path(cfg, head->str);
|
||||
if(dnsc_read_from_file(
|
||||
head->str,
|
||||
(char *)(env->keypairs[keypair_id].crypt_secretkey),
|
||||
nm,
|
||||
(char *)(current_keypair->crypt_secretkey),
|
||||
crypto_box_SECRETKEYBYTES) != 0) {
|
||||
fatal_exit("dnsc_parse_keys: failed to load %s: %s", head->str, strerror(errno));
|
||||
}
|
||||
verbose(VERB_OPS, "Loaded key %s", head->str);
|
||||
if (crypto_scalarmult_base(env->keypairs[keypair_id].crypt_publickey,
|
||||
env->keypairs[keypair_id].crypt_secretkey) != 0) {
|
||||
if (crypto_scalarmult_base(current_keypair->crypt_publickey,
|
||||
current_keypair->crypt_secretkey) != 0) {
|
||||
fatal_exit("dnsc_parse_keys: could not generate public key from %s", head->str);
|
||||
}
|
||||
dnsc_key_to_fingerprint(fingerprint, env->keypairs[keypair_id].crypt_publickey);
|
||||
dnsc_key_to_fingerprint(fingerprint, current_keypair->crypt_publickey);
|
||||
verbose(VERB_OPS, "Crypt public key fingerprint for %s: %s", head->str, fingerprint);
|
||||
// find the cert matching this key
|
||||
for(c = 0; c < env->signed_certs_count; c++) {
|
||||
if(memcmp(current_keypair->crypt_publickey,
|
||||
env->signed_certs[c].server_publickey,
|
||||
crypto_box_PUBLICKEYBYTES) == 0) {
|
||||
dnsccert *current_cert = &env->certs[cert_id++];
|
||||
found_cert = 1;
|
||||
current_cert->keypair = current_keypair;
|
||||
memcpy(current_cert->magic_query,
|
||||
env->signed_certs[c].magic_query,
|
||||
sizeof env->signed_certs[c].magic_query);
|
||||
memcpy(current_cert->es_version,
|
||||
env->signed_certs[c].version_major,
|
||||
sizeof env->signed_certs[c].version_major
|
||||
);
|
||||
dnsc_key_to_fingerprint(fingerprint,
|
||||
current_cert->keypair->crypt_publickey);
|
||||
verbose(VERB_OPS, "Crypt public key fingerprint for %s: %s",
|
||||
head->str, fingerprint);
|
||||
verbose(VERB_OPS, "Using %s",
|
||||
key_get_es_version(current_cert->es_version));
|
||||
#ifndef USE_DNSCRYPT_XCHACHA20
|
||||
if (current_cert->es_version[1] == 0x02) {
|
||||
fatal_exit("Certificate for XChacha20 but libsodium does not support it.");
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
if (!found_cert) {
|
||||
fatal_exit("dnsc_parse_keys: could not match certificate for key "
|
||||
"%s. Unable to determine ES version.",
|
||||
head->str);
|
||||
}
|
||||
}
|
||||
return keypair_id;
|
||||
return cert_id;
|
||||
}
|
||||
|
||||
static void
|
||||
sodium_misuse_handler(void)
|
||||
{
|
||||
fatal_exit(
|
||||
"dnscrypt: libsodium could not be initialized, this typically"
|
||||
" happens when no good source of entropy is found. If you run"
|
||||
" unbound in a chroot, make sure /dev/random is available. See"
|
||||
" https://www.unbound.net/documentation/unbound.conf.html");
|
||||
}
|
||||
|
||||
|
||||
@@ -463,8 +900,9 @@ dnsc_handle_curved_request(struct dnsc_env* dnscenv,
|
||||
// Attempt to decrypt the query. If it is not crypted, we may still need
|
||||
// to serve the certificate.
|
||||
verbose(VERB_ALGO, "handle request called on DNSCrypt socket");
|
||||
if ((repinfo->keypair = dnsc_find_keypair(dnscenv, c->buffer)) != NULL) {
|
||||
if(dnscrypt_server_uncurve(repinfo->keypair,
|
||||
if ((repinfo->dnsc_cert = dnsc_find_cert(dnscenv, c->buffer)) != NULL) {
|
||||
if(dnscrypt_server_uncurve(dnscenv,
|
||||
repinfo->dnsc_cert,
|
||||
repinfo->client_nonce,
|
||||
repinfo->nmkey,
|
||||
c->buffer) != 0){
|
||||
@@ -488,7 +926,7 @@ dnsc_handle_uncurved_request(struct comm_reply *repinfo)
|
||||
if(!repinfo->is_dnscrypted) {
|
||||
return 1;
|
||||
}
|
||||
if(dnscrypt_server_curve(repinfo->keypair,
|
||||
if(dnscrypt_server_curve(repinfo->dnsc_cert,
|
||||
repinfo->client_nonce,
|
||||
repinfo->nmkey,
|
||||
repinfo->c->dnscrypt_buffer,
|
||||
@@ -505,27 +943,173 @@ struct dnsc_env *
|
||||
dnsc_create(void)
|
||||
{
|
||||
struct dnsc_env *env;
|
||||
#ifdef SODIUM_MISUSE_HANDLER
|
||||
sodium_set_misuse_handler(sodium_misuse_handler);
|
||||
#endif
|
||||
if (sodium_init() == -1) {
|
||||
fatal_exit("dnsc_create: could not initialize libsodium.");
|
||||
}
|
||||
env = (struct dnsc_env *) calloc(1, sizeof(struct dnsc_env));
|
||||
lock_basic_init(&env->shared_secrets_cache_lock);
|
||||
lock_protect(&env->shared_secrets_cache_lock,
|
||||
&env->num_query_dnscrypt_secret_missed_cache,
|
||||
sizeof(env->num_query_dnscrypt_secret_missed_cache));
|
||||
lock_basic_init(&env->nonces_cache_lock);
|
||||
lock_protect(&env->nonces_cache_lock,
|
||||
&env->nonces_cache,
|
||||
sizeof(env->nonces_cache));
|
||||
lock_protect(&env->nonces_cache_lock,
|
||||
&env->num_query_dnscrypt_replay,
|
||||
sizeof(env->num_query_dnscrypt_replay));
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
int
|
||||
dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg)
|
||||
{
|
||||
if(dnsc_parse_certs(env, cfg) <= 0) {
|
||||
fatal_exit("dnsc_apply_cfg: no cert file loaded");
|
||||
}
|
||||
if(dnsc_parse_keys(env, cfg) <= 0) {
|
||||
fatal_exit("dnsc_apply_cfg: no key file loaded");
|
||||
}
|
||||
randombytes_buf(env->hash_key, sizeof env->hash_key);
|
||||
env->provider_name = cfg->dnscrypt_provider;
|
||||
if(dnsc_parse_certs(env, cfg) <= 0) {
|
||||
fatal_exit("dnsc_apply_cfg: no cert file loaded");
|
||||
}
|
||||
if(dnsc_parse_keys(env, cfg) <= 0) {
|
||||
fatal_exit("dnsc_apply_cfg: no key file loaded");
|
||||
}
|
||||
randombytes_buf(env->hash_key, sizeof env->hash_key);
|
||||
env->provider_name = cfg->dnscrypt_provider;
|
||||
|
||||
if(dnsc_load_local_data(env, cfg) <= 0) {
|
||||
fatal_exit("dnsc_apply_cfg: could not load local data");
|
||||
}
|
||||
return 0;
|
||||
if(dnsc_load_local_data(env, cfg) <= 0) {
|
||||
fatal_exit("dnsc_apply_cfg: could not load local data");
|
||||
}
|
||||
lock_basic_lock(&env->shared_secrets_cache_lock);
|
||||
env->shared_secrets_cache = slabhash_create(
|
||||
cfg->dnscrypt_shared_secret_cache_slabs,
|
||||
HASH_DEFAULT_STARTARRAY,
|
||||
cfg->dnscrypt_shared_secret_cache_size,
|
||||
dnsc_shared_secrets_sizefunc,
|
||||
dnsc_shared_secrets_compfunc,
|
||||
dnsc_shared_secrets_delkeyfunc,
|
||||
dnsc_shared_secrets_deldatafunc,
|
||||
NULL
|
||||
);
|
||||
lock_basic_unlock(&env->shared_secrets_cache_lock);
|
||||
if(!env->shared_secrets_cache){
|
||||
fatal_exit("dnsc_apply_cfg: could not create shared secrets cache.");
|
||||
}
|
||||
lock_basic_lock(&env->nonces_cache_lock);
|
||||
env->nonces_cache = slabhash_create(
|
||||
cfg->dnscrypt_nonce_cache_slabs,
|
||||
HASH_DEFAULT_STARTARRAY,
|
||||
cfg->dnscrypt_nonce_cache_size,
|
||||
dnsc_nonces_sizefunc,
|
||||
dnsc_nonces_compfunc,
|
||||
dnsc_nonces_delkeyfunc,
|
||||
dnsc_nonces_deldatafunc,
|
||||
NULL
|
||||
);
|
||||
lock_basic_unlock(&env->nonces_cache_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
dnsc_delete(struct dnsc_env *env)
|
||||
{
|
||||
if(!env) {
|
||||
return;
|
||||
}
|
||||
verbose(VERB_OPS, "DNSCrypt: Freeing environment.");
|
||||
sodium_free(env->signed_certs);
|
||||
sodium_free(env->rotated_certs);
|
||||
sodium_free(env->certs);
|
||||
sodium_free(env->keypairs);
|
||||
lock_basic_destroy(&env->shared_secrets_cache_lock);
|
||||
lock_basic_destroy(&env->nonces_cache_lock);
|
||||
slabhash_delete(env->shared_secrets_cache);
|
||||
slabhash_delete(env->nonces_cache);
|
||||
free(env);
|
||||
}
|
||||
|
||||
/**
|
||||
* #########################################################
|
||||
* ############# Shared secrets cache functions ############
|
||||
* #########################################################
|
||||
*/
|
||||
|
||||
size_t
|
||||
dnsc_shared_secrets_sizefunc(void *k, void* ATTR_UNUSED(d))
|
||||
{
|
||||
struct shared_secret_cache_key* ssk = (struct shared_secret_cache_key*)k;
|
||||
size_t key_size = sizeof(struct shared_secret_cache_key)
|
||||
+ lock_get_mem(&ssk->entry.lock);
|
||||
size_t data_size = crypto_box_BEFORENMBYTES;
|
||||
(void)ssk; /* otherwise ssk is unused if no threading, or fixed locksize */
|
||||
return key_size + data_size;
|
||||
}
|
||||
|
||||
int
|
||||
dnsc_shared_secrets_compfunc(void *m1, void *m2)
|
||||
{
|
||||
return sodium_memcmp(m1, m2, DNSCRYPT_SHARED_SECRET_KEY_LENGTH);
|
||||
}
|
||||
|
||||
void
|
||||
dnsc_shared_secrets_delkeyfunc(void *k, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct shared_secret_cache_key* ssk = (struct shared_secret_cache_key*)k;
|
||||
lock_rw_destroy(&ssk->entry.lock);
|
||||
free(ssk);
|
||||
}
|
||||
|
||||
void
|
||||
dnsc_shared_secrets_deldatafunc(void* d, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
uint8_t* data = (uint8_t*)d;
|
||||
free(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* #########################################################
|
||||
* ############### Nonces cache functions ##################
|
||||
* #########################################################
|
||||
*/
|
||||
|
||||
size_t
|
||||
dnsc_nonces_sizefunc(void *k, void* ATTR_UNUSED(d))
|
||||
{
|
||||
struct nonce_cache_key* nk = (struct nonce_cache_key*)k;
|
||||
size_t key_size = sizeof(struct nonce_cache_key)
|
||||
+ lock_get_mem(&nk->entry.lock);
|
||||
(void)nk; /* otherwise ssk is unused if no threading, or fixed locksize */
|
||||
return key_size;
|
||||
}
|
||||
|
||||
int
|
||||
dnsc_nonces_compfunc(void *m1, void *m2)
|
||||
{
|
||||
struct nonce_cache_key *k1 = m1, *k2 = m2;
|
||||
return
|
||||
sodium_memcmp(
|
||||
k1->nonce,
|
||||
k2->nonce,
|
||||
crypto_box_HALF_NONCEBYTES) != 0 ||
|
||||
sodium_memcmp(
|
||||
k1->magic_query,
|
||||
k2->magic_query,
|
||||
DNSCRYPT_MAGIC_HEADER_LEN) != 0 ||
|
||||
sodium_memcmp(
|
||||
k1->client_publickey, k2->client_publickey,
|
||||
crypto_box_PUBLICKEYBYTES) != 0;
|
||||
}
|
||||
|
||||
void
|
||||
dnsc_nonces_delkeyfunc(void *k, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct nonce_cache_key* nk = (struct nonce_cache_key*)k;
|
||||
lock_rw_destroy(&nk->entry.lock);
|
||||
free(nk);
|
||||
}
|
||||
|
||||
void
|
||||
dnsc_nonces_deldatafunc(void* ATTR_UNUSED(d), void* ATTR_UNUSED(arg))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
+74
-1
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "dnscrypt/cert.h"
|
||||
#include "util/locks.h"
|
||||
|
||||
#define DNSCRYPT_QUERY_HEADER_SIZE \
|
||||
(DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_PUBLICKEYBYTES + crypto_box_HALF_NONCEBYTES + crypto_box_MACBYTES)
|
||||
@@ -38,15 +39,25 @@
|
||||
struct sldns_buffer;
|
||||
struct config_file;
|
||||
struct comm_reply;
|
||||
struct slabhash;
|
||||
|
||||
typedef struct KeyPair_ {
|
||||
uint8_t crypt_publickey[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t crypt_secretkey[crypto_box_SECRETKEYBYTES];
|
||||
} KeyPair;
|
||||
|
||||
typedef struct cert_ {
|
||||
uint8_t magic_query[DNSCRYPT_MAGIC_HEADER_LEN];
|
||||
uint8_t es_version[2];
|
||||
KeyPair *keypair;
|
||||
} dnsccert;
|
||||
|
||||
struct dnsc_env {
|
||||
struct SignedCert *signed_certs;
|
||||
struct SignedCert **rotated_certs;
|
||||
dnsccert *certs;
|
||||
size_t signed_certs_count;
|
||||
size_t rotated_certs_count;
|
||||
uint8_t provider_publickey[crypto_sign_ed25519_PUBLICKEYBYTES];
|
||||
uint8_t provider_secretkey[crypto_sign_ed25519_SECRETKEYBYTES];
|
||||
KeyPair *keypairs;
|
||||
@@ -54,6 +65,20 @@ struct dnsc_env {
|
||||
uint64_t nonce_ts_last;
|
||||
unsigned char hash_key[crypto_shorthash_KEYBYTES];
|
||||
char * provider_name;
|
||||
|
||||
/** Caches */
|
||||
struct slabhash *shared_secrets_cache;
|
||||
/** lock on shared secret cache counters */
|
||||
lock_basic_type shared_secrets_cache_lock;
|
||||
/** number of misses from shared_secrets_cache */
|
||||
size_t num_query_dnscrypt_secret_missed_cache;
|
||||
|
||||
/** slabhash keeping track of nonce/cient pk/server sk pairs. */
|
||||
struct slabhash *nonces_cache;
|
||||
/** lock on nonces_cache, used to avoid race condition in updating the hash */
|
||||
lock_basic_type nonces_cache_lock;
|
||||
/** number of replayed queries */
|
||||
size_t num_query_dnscrypt_replay;
|
||||
};
|
||||
|
||||
struct dnscrypt_query_header {
|
||||
@@ -64,7 +89,7 @@ struct dnscrypt_query_header {
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize DNSCrypt enviroment.
|
||||
* Initialize DNSCrypt environment.
|
||||
* Initialize sodium library and allocate the dnsc_env structure.
|
||||
* \return an uninitialized struct dnsc_env.
|
||||
*/
|
||||
@@ -81,6 +106,12 @@ struct dnsc_env * dnsc_create(void);
|
||||
*/
|
||||
int dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg);
|
||||
|
||||
/**
|
||||
* Delete DNSCrypt environment
|
||||
*
|
||||
*/
|
||||
void dnsc_delete(struct dnsc_env *env);
|
||||
|
||||
/**
|
||||
* handle a crypted dnscrypt request.
|
||||
* Determine wether or not a query is coming over the dnscrypt listener and
|
||||
@@ -98,5 +129,47 @@ int dnsc_handle_curved_request(struct dnsc_env* dnscenv,
|
||||
*/
|
||||
|
||||
int dnsc_handle_uncurved_request(struct comm_reply *repinfo);
|
||||
|
||||
/**
|
||||
* Computes the size of the shared secret cache entry.
|
||||
*/
|
||||
size_t dnsc_shared_secrets_sizefunc(void *k, void *d);
|
||||
|
||||
/**
|
||||
* Compares two shared secret cache keys.
|
||||
*/
|
||||
int dnsc_shared_secrets_compfunc(void *m1, void *m2);
|
||||
|
||||
/**
|
||||
* Function to delete a shared secret cache key.
|
||||
*/
|
||||
void dnsc_shared_secrets_delkeyfunc(void *k, void* arg);
|
||||
|
||||
/**
|
||||
* Function to delete a share secret cache value.
|
||||
*/
|
||||
void dnsc_shared_secrets_deldatafunc(void* d, void* arg);
|
||||
|
||||
/**
|
||||
* Computes the size of the nonce cache entry.
|
||||
*/
|
||||
size_t dnsc_nonces_sizefunc(void *k, void *d);
|
||||
|
||||
/**
|
||||
* Compares two nonce cache keys.
|
||||
*/
|
||||
int dnsc_nonces_compfunc(void *m1, void *m2);
|
||||
|
||||
/**
|
||||
* Function to delete a nonce cache key.
|
||||
*/
|
||||
void dnsc_nonces_delkeyfunc(void *k, void* arg);
|
||||
|
||||
/**
|
||||
* Function to delete a nonce cache value.
|
||||
*/
|
||||
void dnsc_nonces_deldatafunc(void* d, void* arg);
|
||||
|
||||
|
||||
#endif /* USE_DNSCRYPT */
|
||||
#endif
|
||||
|
||||
@@ -18,8 +18,27 @@ AC_DEFUN([dnsc_DNSCRYPT],
|
||||
])
|
||||
AC_SEARCH_LIBS([sodium_init], [sodium], [],
|
||||
AC_MSG_ERROR([The sodium library was not found. Please install sodium!]))
|
||||
AC_SEARCH_LIBS([crypto_box_curve25519xchacha20poly1305_beforenm], [sodium],
|
||||
[
|
||||
AC_SUBST([ENABLE_DNSCRYPT_XCHACHA20], [1])
|
||||
AC_DEFINE(
|
||||
[USE_DNSCRYPT_XCHACHA20], [1],
|
||||
[Define to 1 to enable dnscrypt with xchacha20 support])
|
||||
],
|
||||
[
|
||||
AC_SUBST([ENABLE_DNSCRYPT_XCHACHA20], [0])
|
||||
])
|
||||
AC_SEARCH_LIBS([sodium_set_misuse_handler], [sodium],
|
||||
[
|
||||
AC_DEFINE(
|
||||
[SODIUM_MISUSE_HANDLER], [1],
|
||||
[Define to 1 if libsodium supports sodium_set_misuse_handler])
|
||||
],
|
||||
[
|
||||
])
|
||||
$1
|
||||
else
|
||||
AC_SUBST([ENABLE_DNSCRYPT_XCHACHA20], [0])
|
||||
$2
|
||||
fi
|
||||
])
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
CERT_EXPIRE_DAYS="$(( 365 * 15 ))"
|
||||
DIR="$(dirname "$0")"
|
||||
|
||||
|
||||
if [[ "$PWD" != *tdir ]]
|
||||
then
|
||||
echo "You should run this script with a .tdir directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for i in 1 2
|
||||
do
|
||||
# Ephemeral key
|
||||
rm -f "${i}.key"
|
||||
dnscrypt-wrapper --gen-crypt-keypair \
|
||||
--crypt-secretkey-file="${i}.key" \
|
||||
--provider-publickey-file="${DIR}/keys${i}/public.key" \
|
||||
--provider-secretkey-file="${DIR}/keys${i}/secret.key"
|
||||
# Cert file
|
||||
for cipher in salsa chacha
|
||||
do
|
||||
rm -f "${i}_${cipher}.cert"
|
||||
extraarg=""
|
||||
if [ "${cipher}" == "chacha" ]
|
||||
then
|
||||
extraarg="-x"
|
||||
fi
|
||||
|
||||
dnscrypt-wrapper ${extraarg} --gen-cert-file \
|
||||
--provider-cert-file="${i}_${cipher}.cert" \
|
||||
--crypt-secretkey-file="${i}.key" \
|
||||
--provider-publickey-file="${DIR}/keys${i}/public.key" \
|
||||
--provider-secretkey-file="${DIR}/keys${i}/secret.key" \
|
||||
--cert-file-expire-days="${CERT_EXPIRE_DAYS}"
|
||||
done
|
||||
done
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
¸_A¡O#÷ÛÈfó—ÌoD¶_�eŶ)|'T¦éÜòO�
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
-&ç6\Uùõñh`^"…ºz/C9‚
óˆ¸_A¡O#÷ÛÈfó—ÌoD¶_�eŶ)|'T¦éÜòO�
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
ΓR ς�ύeµτ{φl�ΑKΛ€Ξ:5r\±}KΣηƒ
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
ηi%‚ 5fΝ™–νΙϋ�νBnκΝ―.Ί“ΓR ς�ύeµτ{φl�ΑKΛ€Ξ:5r\±}KΣηƒ
|
||||
@@ -13,6 +13,7 @@
|
||||
// with this file. If not, see:
|
||||
//
|
||||
// <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
syntax = "proto2";
|
||||
|
||||
package dnstap;
|
||||
|
||||
|
||||
+875
-1
@@ -1,6 +1,880 @@
|
||||
18 June 2018: Wouter
|
||||
- Fix that control-use-cert: no works for 127.0.0.1 to disable certs.
|
||||
|
||||
15 June 2018: Wouter
|
||||
- tag for 1.7.3rc1.
|
||||
|
||||
14 June 2018: Wouter
|
||||
- #4103: Fix that auth-zone does not insist on SOA record first in
|
||||
file for url downloads.
|
||||
- Fix that first control-interface determines if TLS is used. Warn
|
||||
when IP address interfaces are used without TLS.
|
||||
- Fix nettle compile.
|
||||
|
||||
12 June 2018: Ralph
|
||||
- Don't count CNAME response types received during qname minimisation as
|
||||
query restart.
|
||||
|
||||
12 June 2018: Wouter
|
||||
- #4102 for NSD, but for Unbound. Named unix pipes do not use
|
||||
certificate and key files, access can be restricted with file and
|
||||
directory permissions. The option control-use-cert is no longer
|
||||
used, and ignored if found in unbound.conf.
|
||||
- Rename tls-additional-ports to tls-additional-port, because every
|
||||
line adds one port.
|
||||
- Fix buffer size warning in unit test.
|
||||
- remade dependencies in the Makefile.
|
||||
|
||||
6 June 2018: Wouter
|
||||
- Patch to fix openwrt for mac os build darwin detection in configure.
|
||||
|
||||
5 June 2018: Wouter
|
||||
- Fix crash if ratelimit taken into use with unbound-control
|
||||
instead of with unbound.conf.
|
||||
|
||||
4 June 2018: Wouter
|
||||
- Fix deadlock caused by incoming notify for auth-zone.
|
||||
- tag for 1.7.2rc1, became 1.7.2 release on 11 June 2018,
|
||||
trunk is 1.7.3 in development from this point.
|
||||
- #4100: Fix stub reprime when it becomes useless.
|
||||
|
||||
1 June 2018: Wouter
|
||||
- Rename additional-tls-port to tls-additional-ports.
|
||||
The older name is accepted for backwards compatibility.
|
||||
|
||||
30 May 2018: Wouter
|
||||
- Patch from Syzdek: Add ability to ignore RD bit and treat all
|
||||
requests as if the RD bit is set.
|
||||
|
||||
29 May 2018: Wouter
|
||||
- in compat/arc4random call getentropy_urandom when getentropy fails
|
||||
with ENOSYS.
|
||||
- Fix that fallback for windows port.
|
||||
|
||||
28 May 2018: Wouter
|
||||
- Fix windows tcp and tls spin on events.
|
||||
- Add routine from getdns to add windows cert store to the SSL_CTX.
|
||||
- tls-win-cert option that adds the system certificate store for
|
||||
authenticating DNS-over-TLS connections. It can be used instead
|
||||
of the tls-cert-bundle option, or with it to add certificates.
|
||||
|
||||
25 May 2018: Wouter
|
||||
- For TCP and TLS connections that don't establish, perform address
|
||||
update in infra cache, so future selections can exclude them.
|
||||
- Fix that tcp sticky events are removed for closed fd on windows.
|
||||
- Fix close events for tcp only.
|
||||
|
||||
24 May 2018: Wouter
|
||||
- Fix that libunbound can do DNS-over-TLS, when configured.
|
||||
- Fix that windows unbound service can use DNS-over-TLS.
|
||||
- unbound-host initializes ssl (for potential DNS-over-TLS usage
|
||||
inside libunbound), when ssl upstream or a cert-bundle is configured.
|
||||
|
||||
23 May 2018: Wouter
|
||||
- Use accept4 to speed up incoming TCP (and TLS) connections,
|
||||
available on Linux, FreeBSD and OpenBSD.
|
||||
|
||||
17 May 2018: Ralph
|
||||
- Qname minimisation default changed to yes.
|
||||
|
||||
15 May 2018: Wouter
|
||||
- Fix low-rtt-pct to low-rtt-permil, as it is parts in one thousand.
|
||||
|
||||
11 May 2018: Wouter
|
||||
- Fix contrib/libunbound.pc for libssl libcrypto references,
|
||||
from https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=226914
|
||||
|
||||
7 May 2018: Wouter
|
||||
- Fix windows to not have sticky TLS events for TCP.
|
||||
- Fix read of DNS over TLS length and data in one read call.
|
||||
- Fix mesh state assertion failure due to callback removal.
|
||||
|
||||
3 May 2018: Wouter
|
||||
- Fix that configure --with-libhiredis also turns on cachedb.
|
||||
- Fix gcc 8 buffer warning in testcode.
|
||||
- Fix function type cast warning in libunbound context callback type.
|
||||
|
||||
2 May 2018: Wouter
|
||||
- Fix fail to reject dead peers in forward-zone, with ssl-upstream.
|
||||
|
||||
1 May 2018: Wouter
|
||||
- Fix that unbound-control reload frees the rrset keys and returns
|
||||
the memory pages to the system.
|
||||
|
||||
30 April 2018: Wouter
|
||||
- Fix spelling error in man page and note defaults as no instead of
|
||||
off.
|
||||
|
||||
26 April 2018: Wouter
|
||||
- Fix for crash in daemon_cleanup with dnstap during reload,
|
||||
from Saksham Manchanda.
|
||||
- Also that for dnscrypt.
|
||||
- tag for 1.7.1rc1 release. Became 1.7.1 release on 3 May, trunk
|
||||
is from here 1.7.2 in development.
|
||||
|
||||
25 April 2018: Ralph
|
||||
- Fix memory leak when caching wildcard records for aggressive NSEC use
|
||||
|
||||
24 April 2018: Wouter
|
||||
- Fix contrib/fastrpz.patch for this release.
|
||||
- Fix auth https for libev.
|
||||
|
||||
24 April 2018: Ralph
|
||||
- Added root-key-sentinel support
|
||||
|
||||
23 April 2018: Wouter
|
||||
- makedist uses bz2 for expat code, instead of tar.gz.
|
||||
- Fix #4092: libunbound: use-caps-for-id lacks colon in
|
||||
config_set_option.
|
||||
- auth zone http download stores exact copy of downloaded file,
|
||||
including comments in the file.
|
||||
- Fix sldns parse failure for CDS alternate delete syntax empty hex.
|
||||
- Attempt for auth zone fix; add of callback in mesh gets from
|
||||
callback does not skip callback of result.
|
||||
- Fix cname classification with qname minimisation enabled.
|
||||
- list_auth_zones unbound-control command.
|
||||
|
||||
20 April 2018: Wouter
|
||||
- man page documentation for dns-over-tls forward-addr '#' notation.
|
||||
- removed free from failed parse case.
|
||||
- Fix #4091: Fix that reload of auth-zone does not merge the zonefile
|
||||
with the previous contents.
|
||||
- Delete auth zone when removed from config.
|
||||
|
||||
19 April 2018: Wouter
|
||||
- Can set tls authentication with forward-addr: IP#tls.auth.name
|
||||
And put the public cert bundle in tls-cert-bundle: "ca-bundle.pem".
|
||||
such as forward-addr: 9.9.9.9@853#dns.quad9.net or
|
||||
1.1.1.1@853#cloudflare-dns.com
|
||||
- Fix #658: unbound using TLS in a forwarding configuration does not
|
||||
verify the server's certificate (RFC 8310 support).
|
||||
- For addr with #authname and no @port notation, the default is 853.
|
||||
|
||||
18 April 2018: Wouter
|
||||
- Fix auth-zone retry timer to be on schedule with retry timeout,
|
||||
with backoff. Also time a refresh at the zone expiry.
|
||||
|
||||
17 April 2018: Wouter
|
||||
- auth zone notify work.
|
||||
- allow-notify: config statement for auth-zones.
|
||||
- unit test for allow-notify
|
||||
|
||||
16 April 2018: Wouter
|
||||
- Fix auth zone target lookup iterator.
|
||||
- auth zone notify with prefix
|
||||
- auth zone notify work.
|
||||
|
||||
13 April 2018: Wouter
|
||||
- Fix for max include depth for authzones.
|
||||
- Fix memory free on fail for $INCLUDE in authzone.
|
||||
- Fix that an internal error to look up the wrong rr type for
|
||||
auth zone gets stopped, before trying to send there.
|
||||
- auth zone notify work.
|
||||
|
||||
10 April 2018: Ralph
|
||||
- num.query.aggressive.NOERROR and num.query.aggressive.NXDOMAIN
|
||||
statistics counters.
|
||||
|
||||
10 April 2018: Wouter
|
||||
- documentation for low-rtt and low-rtt-pct.
|
||||
- auth zone notify work.
|
||||
|
||||
9 April 2018: Wouter
|
||||
- Fix that flush_zone sets prefetch ttl expired, so that with
|
||||
serve-expired enabled it'll start prefetching those entries.
|
||||
- num.query.authzone.up and num.query.authzone.down statistics counters.
|
||||
- Fix downstream auth zone, only fallback when auth zone fails to
|
||||
answer and fallback is enabled.
|
||||
- Accept both option names with and without colon for get_option
|
||||
and set_option.
|
||||
- low-rtt and low-rtt-pct in unbound.conf enable the server selection
|
||||
of fast servers for some percentage of the time.
|
||||
|
||||
5 April 2018: Wouter
|
||||
- Combine write of tcp length and tcp query for dns over tls.
|
||||
- nitpick fixes in example.conf.
|
||||
- Fix above stub queries for type NS and useless delegation point.
|
||||
- Fix unbound-control over pipe with openssl 1.1.1, the TLSv1.3
|
||||
tls_choose_sigalg routine does not allow the ciphers for the pipe,
|
||||
so use TLSv1.2.
|
||||
- ED448 support.
|
||||
|
||||
3 April 2018: Wouter
|
||||
- Fix #4043: make test fails due to v6 presentation issue in macOS.
|
||||
- Fix unable to resolve after new WLAN connection, due to auth-zone
|
||||
failing with a forwarder set. Now, auth-zone is only used for
|
||||
answers (not referrals) when a forwarder is set.
|
||||
|
||||
29 March 2018: Ralph
|
||||
- Check "result" in dup_all(), by Florian Obser.
|
||||
|
||||
23 March 2018: Ralph
|
||||
- Fix unbound-control get_option aggressive-nsec
|
||||
|
||||
21 March 2018: Ralph
|
||||
- Do not use cached NSEC records to generate negative answers for
|
||||
domains under DNSSEC Negative Trust Anchors.
|
||||
|
||||
19 March 2018: Wouter
|
||||
- iana port update.
|
||||
|
||||
16 March 2018: Wouter
|
||||
- corrected a minor typo in the changelog.
|
||||
- move htobe64/be64toh portability code to cachedb.c.
|
||||
|
||||
15 March 2018: Wouter
|
||||
- Add --with-libhiredis, unbound support for a new cachedb backend
|
||||
that uses a Redis server as the storage. This implementation
|
||||
depends on the hiredis client library (https://redislabs.com/lp/hiredis/).
|
||||
And unbound should be built with both --enable-cachedb and
|
||||
--with-libhiredis[=PATH] (where $PATH/include/hiredis/hiredis.h
|
||||
should exist). Patch from Jinmei Tatuya (Infoblox).
|
||||
- Fix #3817: core dump happens in libunbound delete, when queued
|
||||
servfail hits deleted message queue.
|
||||
- Create additional tls service interfaces by opening them on other
|
||||
portnumbers and listing the portnumbers as additional-tls-port: nr.
|
||||
|
||||
13 March 2018: Wouter
|
||||
- Fix typo in documentation.
|
||||
- Fix #3736: Fix 0 TTL domains stuck on SERVFAIL unless manually
|
||||
flushed with serve-expired on.
|
||||
|
||||
12 March 2018: Wouter
|
||||
- Added documentation for aggressive-nsec: yes.
|
||||
- tag 1.7.0rc3. That became the 1.7.0 release on 15 Mar, trunk
|
||||
now has 1.7.1 in development.
|
||||
- Fix #3727: Protocol name is TLS, options have been renamed but
|
||||
documentation is not consistent.
|
||||
- Check IXFR start serial.
|
||||
|
||||
9 March 2018: Wouter
|
||||
- Fix #3598: Fix swig build issue on rhel6 based system.
|
||||
configure --disable-swig-version-check stops the swig version check.
|
||||
|
||||
8 March 2018: Wouter
|
||||
- tag 1.7.0rc2.
|
||||
|
||||
7 March 2018: Wouter
|
||||
- Fixed contrib/fastrpz.patch, even though this already applied
|
||||
cleanly for me, now also for others.
|
||||
- patch to log creates keytag queries, from A. Schulze.
|
||||
- patch suggested by Debian lintian: allow to -> allow one to, from
|
||||
A. Schulze.
|
||||
- Attempt to remove warning about trailing whitespace.
|
||||
|
||||
6 March 2018: Wouter
|
||||
- Reverted fix for #3512, this may not be the best way forward;
|
||||
although it could be changed at a later time, to stay similar to
|
||||
other implementations.
|
||||
- svn trunk contains 1.7.0, this is the number for the next release.
|
||||
- Fix for windows compile.
|
||||
- tag 1.7.0rc1.
|
||||
|
||||
5 March 2018: Wouter
|
||||
- Fix to check define of DSA for when openssl is without deprecated.
|
||||
- iana port update.
|
||||
- Fix #3582: Squelch address already in use log when reuseaddr option
|
||||
causes same port to be used twice for tcp connections.
|
||||
|
||||
27 February 2018: Wouter
|
||||
- Fixup contrib/fastrpz.patch so that it applies.
|
||||
- Fix compile without threads, and remove unused variable.
|
||||
- Fix compile with staticexe and python module.
|
||||
- Fix nettle compile.
|
||||
|
||||
22 February 2018: Ralph
|
||||
- Save wildcard RRset from answer with original owner for use in
|
||||
aggressive NSEC.
|
||||
|
||||
21 February 2018: Wouter
|
||||
- Fix #3512: unbound incorrectly reports SERVFAIL for CAA query
|
||||
when there is a CNAME loop.
|
||||
- Fix validation for CNAME loops. When it detects a cname loop,
|
||||
by finding the cname, cname in the existing list, it returns
|
||||
the partial result with the validation result up to then.
|
||||
- more robust cachedump rrset routine.
|
||||
|
||||
19 February 2018: Wouter
|
||||
- Fix #3505: Documentation for default local zones references
|
||||
wrong RFC.
|
||||
- Fix #3494: local-zone noview can be used to break out of the view
|
||||
to the global local zone contents, for queries for that zone.
|
||||
- Fix for more maintainable code in localzone.
|
||||
|
||||
16 February 2018: Wouter
|
||||
- Fixes for clang static analyzer, the missing ; in
|
||||
edns-subnet/addrtree.c after the assert made clang analyzer
|
||||
produce a failure to analyze it.
|
||||
|
||||
13 February 2018: Ralph
|
||||
- Aggressive NSEC tests
|
||||
|
||||
13 February 2018: Wouter
|
||||
- tls-cert-bundle option in unbound.conf enables TLS authentication.
|
||||
- iana port update.
|
||||
|
||||
12 February 2018: Wouter
|
||||
- Unit test for auth zone https url download.
|
||||
|
||||
12 February 2018: Ralph
|
||||
- Added tests with wildcard expanded NSEC records (CVE-2017-15105 test)
|
||||
- Processed aggressive NSEC code review remarks Wouter
|
||||
|
||||
8 February 2018: Ralph
|
||||
- Aggressive use of NSEC implementation. Use cached NSEC records to
|
||||
generate NXDOMAIN, NODATA and positive wildcard answers.
|
||||
|
||||
8 February 2018: Wouter
|
||||
- iana port update.
|
||||
- auth zone url config.
|
||||
|
||||
5 February 2018: Wouter
|
||||
- Fix #3451: dnstap not building when you have a separate build dir.
|
||||
And removed protoc warning, set dnstap.proto syntax to proto2.
|
||||
- auth-zone provides a way to configure RFC7706 from unbound.conf,
|
||||
eg. with auth-zone: name: "." for-downstream: no for-upstream: yes
|
||||
fallback-enabled: yes and masters or a zonefile with data.
|
||||
|
||||
2 February 2018: Wouter
|
||||
- Fix unfreed locks in log and arc4random at exit of unbound.
|
||||
- unit test with valgrind
|
||||
- Fix lock race condition in dns cache dname synthesis.
|
||||
- lock subnet new item before insertion to please checklocks,
|
||||
no modification of critical regions outside of lock region.
|
||||
|
||||
1 February 2018: Wouter
|
||||
- fix unaligned structure making a false positive in checklock
|
||||
unitialised memory.
|
||||
|
||||
29 January 2018: Ralph
|
||||
- Use NSEC with longest ce to prove wildcard absence.
|
||||
- Only use *.ce to prove wildcard absence, no longer names.
|
||||
|
||||
25 January 2018: Wouter
|
||||
- ltrace.conf file for libunbound in contrib.
|
||||
|
||||
23 January 2018: Wouter
|
||||
- Fix that unbound-checkconf -f flag works with auto-trust-anchor-file
|
||||
for startup scripts to get the full pathname(s) of anchor file(s).
|
||||
- Print fatal errors about remote control setup before log init,
|
||||
so that it is printed to console.
|
||||
|
||||
22 January 2018: Wouter
|
||||
- Accept tls-upstream in unbound.conf, the ssl-upstream keyword is
|
||||
also recognized and means the same. Also for tls-port,
|
||||
tls-service-key, tls-service-pem, stub-tls-upstream and
|
||||
forward-tls-upstream.
|
||||
- Fix #3397: Fix that cachedb could return a partial CNAME chain.
|
||||
- Fix #3397: Fix that when the cache contains an unsigned DNAME in
|
||||
the middle of a cname chain, a result without the DNAME could
|
||||
be returned.
|
||||
|
||||
19 January 2018: Wouter
|
||||
- tag 1.6.8 for release with CVE fix.
|
||||
- trunk has 1.6.9 with fix and previous commits.
|
||||
- patch for CVE-2017-15105: vulnerability in the processing of
|
||||
wildcard synthesized NSEC records.
|
||||
- iana port update.
|
||||
- make depend: code dependencies updated in Makefile.
|
||||
|
||||
4 January 2018: Ralph
|
||||
- Copy query and correctly set flags on REFUSED answers when cache
|
||||
snooping is not allowed.
|
||||
|
||||
3 January 2018: Ralph
|
||||
- Fix queries being leaked above stub when refetching glue.
|
||||
|
||||
2 January 2017: Wouter
|
||||
- Fix that DS queries with referral replies are answered straight
|
||||
away, without a repeat query picking the DS from cache.
|
||||
The correct reply should have been an answer, the reply is fixed
|
||||
by the scrubber to have the answer in the answer section.
|
||||
- Remove clang optimizer disable,
|
||||
Fix that expiration date checks don't fail with clang -O2.
|
||||
|
||||
15 December 2017: Wouter
|
||||
- Fix timestamp failure because of clang optimizer failure, by
|
||||
disabling -O2 when the compiler --version is clang.
|
||||
- iana port update.
|
||||
- Also disable -flto for clang, to make incep-expi signature check
|
||||
work.
|
||||
|
||||
12 December 2017: Ralph
|
||||
- Fix qname-minimisation documentation (A QTYPE, not NS)
|
||||
|
||||
12 December 2017: Wouter
|
||||
- authzone work, transfer connect.
|
||||
|
||||
7 December 2017: Ralph
|
||||
- Check whether --with-libunbound-only is set when using --with-nettle
|
||||
or --with-nss.
|
||||
|
||||
4 December 2017: Wouter
|
||||
- Fix link failure on OmniOS.
|
||||
|
||||
1 December 2017: Wouter
|
||||
- auth zone work.
|
||||
|
||||
30 November 2017: Wouter
|
||||
- Fix #3299 - forward CNAME daisy chain is not working
|
||||
|
||||
14 November 2017: Wouter
|
||||
- Fix #2882: Unbound behaviour changes (wrong) when domain-insecure is
|
||||
set for stub zone. It no longer searches for DNSSEC information.
|
||||
- auth xfer work on probe timer and lookup.
|
||||
|
||||
13 November 2017: Wouter
|
||||
- Fix #2801: Install libunbound.pc.
|
||||
- Fix qname minimisation to send AAAA queries at zonecut like type A.
|
||||
- reverted AAAA change.
|
||||
|
||||
7 November 2017: Wouter
|
||||
- Fix #2492: Documentation libunbound.
|
||||
|
||||
3 November 2017: Wouter
|
||||
- Fix #2362: TLS1.3/openssl-1.1.1 not working.
|
||||
- Fix #2034 - Autoconf and -flto.
|
||||
- Fix #2141 - for libsodium detect lack of entropy in chroot, print
|
||||
a message and exit.
|
||||
|
||||
2 November 2017: Wouter
|
||||
- Fix #1913: ub_ctx_config is under circumstances thread-safe.
|
||||
- make ip-transparent option work on OpenBSD.
|
||||
|
||||
31 October 2017: Wouter
|
||||
- Document that errno is left informative on libunbound config read
|
||||
fail.
|
||||
- lexer output.
|
||||
- iana port update.
|
||||
|
||||
25 October 2017: Ralph
|
||||
- Fixed libunbound manual typo.
|
||||
- Fix #1949: [dnscrypt] make provider name mismatch more obvious.
|
||||
- Fix #2031: Double included headers
|
||||
|
||||
24 October 2017: Ralph
|
||||
- Update B root ipv4 address.
|
||||
|
||||
19 October 2017: Wouter
|
||||
- authzone work, probe timer setup.
|
||||
|
||||
18 October 2017: Wouter
|
||||
- lint for recent authzone commit.
|
||||
|
||||
17 October 2017: Wouter
|
||||
- Fix #1749: With harden-referral-path: performance drops, due to
|
||||
circular dependency in NS and DS lookups.
|
||||
- [dnscrypt] prevent dnscrypt-secret-key, dnscrypt-provider-cert
|
||||
duplicates
|
||||
- [dnscrypt] introduce dnscrypt-provider-cert-rotated option,
|
||||
from Manu Bretelle.
|
||||
This option allows handling multiple cert/key pairs while only
|
||||
distributing some of them.
|
||||
In order to reliably match a client magic with a given key without
|
||||
strong assumption as to how those were generated, we need both key and
|
||||
cert. Likewise, in order to know which ES version should be used.
|
||||
On the other hand, when rotating a cert, it can be desirable to only
|
||||
serve the new cert but still be able to handle clients that are still
|
||||
using the old certs's public key.
|
||||
The `dnscrypt-provider-cert-rotated` allow to instruct unbound to not
|
||||
publish the cert as part of the DNS's provider_name's TXT answer.
|
||||
- Better documentation for cache-max-negative-ttl.
|
||||
- Work on local root zone code.
|
||||
|
||||
10 October 2017: Wouter
|
||||
- tag 1.6.7
|
||||
- trunk has version 1.6.8.
|
||||
|
||||
6 October 2017: Wouter
|
||||
- Fix spelling in unbound-control man page.
|
||||
|
||||
5 October 2017: Wouter
|
||||
- Fix trust-anchor-signaling works in libunbound.
|
||||
- Fix some more crpls in testdata for different signaling default.
|
||||
- tag 1.6.7rc1
|
||||
|
||||
5 October 2017: Ralph
|
||||
- Set trust-anchor-signaling default to yes
|
||||
- Use RCODE from A query on DNS64 synthesized answer.
|
||||
|
||||
2 October 2017: Wouter
|
||||
- Fix param unused warning for windows exportsymbol compile.
|
||||
|
||||
25 September 2017: Ralph
|
||||
- Fix #1450: Generate again patch contrib/aaaa-filter-iterator.patch
|
||||
(by Danilo G. Baio).
|
||||
|
||||
21 September 2017: Ralph
|
||||
- Log name of looping module
|
||||
|
||||
19 September 2017: Wouter
|
||||
- use a cachedb answer even if it's "expired" when serve-expired is yes
|
||||
(patch from Jinmei Tatuya).
|
||||
- trigger refetching of the answer in that case (this will bypass
|
||||
cachedb lookup)
|
||||
- allow storing a 0-TTL answer from cachedb in the in-memory message
|
||||
cache when serve-expired is yes
|
||||
- Fix DNSCACHE_STORE_ZEROTTL to be bigger than 0xffff.
|
||||
|
||||
18 September 2017: Ralph
|
||||
- Fix #1400: allowing use of global cache on ECS-forwarding unless
|
||||
always-forward.
|
||||
|
||||
18 September 2017: Wouter
|
||||
- tag 1.6.6 (is 1.6.6rc2)
|
||||
- Fix that looping modules always stop the query, and don't pass
|
||||
control.
|
||||
- Fix #1435: Please allow UDP to be disabled separately upstream and
|
||||
downstream.
|
||||
- Fix #1440: [dnscrypt] client nonce cache.
|
||||
|
||||
15 September 2017: Wouter
|
||||
- Fix unbound-host to report error for DNSSEC state of failed lookups.
|
||||
- Spelling fixes, from Josh Soref.
|
||||
|
||||
13 September 2017: Wouter
|
||||
- tag 1.6.6rc2, became 1.6.6 on 18 sep. trunk 1.6.7 in development.
|
||||
|
||||
12 September 2017: Wouter
|
||||
- Add dns64 for client-subnet in unbound-checkconf.
|
||||
|
||||
4 September 2017: Ralph
|
||||
- Fix #1412: QNAME minimisation strict mode not honored
|
||||
- Fix #1434: Fix windows openssl 1.1.0 linking.
|
||||
|
||||
4 September 2017: Wouter
|
||||
- tag 1.6.6rc1
|
||||
- makedist fix for windows binaries, with openssl 1.1.0 windres fix,
|
||||
and expat 2.2.4 install target fix.
|
||||
|
||||
1 September 2017: Wouter
|
||||
- Recommend 1472 buffer size in unbound.conf
|
||||
|
||||
31 August 2017: Wouter
|
||||
- Fix #1424: cachedb:testframe is not thread safe.
|
||||
- For #1417: escape ; in dnscrypt tests.
|
||||
- but reverted that, tests fails with that escape.
|
||||
- Fix #1417: [dnscrypt] shared secret cache counters, and works when
|
||||
dnscrypt is not enabled. And cache size configuration option.
|
||||
- make depend
|
||||
- Fix #1418: [ip ratelimit] initialize slabhash using
|
||||
ip-ratelimit-slabs.
|
||||
|
||||
30 August 2017: Wouter
|
||||
- updated contrib/fastrpz.patch to apply with configparser changes.
|
||||
- Fix 1416: qname-minimisation breaks TLSA lookups with CNAMEs.
|
||||
|
||||
29 August 2017: Wouter
|
||||
- Fix #1414: fix segfault on parse failure and log_replies.
|
||||
- zero qinfo in handle_request, this zeroes local_alias and also the
|
||||
qname member.
|
||||
- new keys and certs for dnscrypt tests.
|
||||
- fixup WKS test on buildhost without servicebyname.
|
||||
|
||||
28 August 2017: Wouter
|
||||
- Fix #1415: patch to free dnscrypt environment on reload.
|
||||
- iana portlist update
|
||||
- Fix #1415: [dnscrypt] shared secret cache, patch from
|
||||
Manu Bretelle.
|
||||
- Small fixes for the shared secret cache patch.
|
||||
- Fix WKS records on kvm autobuild host, with default protobyname
|
||||
entries for udp and tcp.
|
||||
|
||||
23 August 2017: Wouter
|
||||
- Fix #1407: Add ECS options check to unbound-checkconf.
|
||||
- make depend
|
||||
- Fix to reclaim tcp handler when it is closed due to dnscrypt buffer
|
||||
allocation failure.
|
||||
|
||||
22 August 2017: Wouter
|
||||
- Fix install of trust anchor when two anchors are present, makes both
|
||||
valid. Checks hash of DS but not signature of new key. This fixes
|
||||
the root.key file if created when unbound is installed between
|
||||
sep11 and oct11 2017.
|
||||
- tag 1.6.5 with pointrelease 1.6.5 (1.6.4 plus 5011 fix).
|
||||
- trunk version 1.6.6 in development.
|
||||
- Fix issue on macOX 10.10 where TCP fast open is detected but not
|
||||
implemented causing TCP to fail. The fix allows fallback to regular
|
||||
TCP in this case and is also more robust for cases where connectx()
|
||||
fails for some reason.
|
||||
- Fix #1402: squelch invalid argument error for fd_set_block on windows.
|
||||
|
||||
10 August 2017: Wouter
|
||||
- Patch to show DNSCrypt status in help output, from Carsten
|
||||
Strotmann.
|
||||
|
||||
8 August 2017: Wouter
|
||||
- Fix #1398: make cachedb secret configurable.
|
||||
- Remove spaces from Makefile.
|
||||
|
||||
7 August 2017: Wouter
|
||||
- Fix #1397: Recursive DS lookups for AS112 zones names should recurse.
|
||||
|
||||
3 August 2017: Ralph
|
||||
- Remove unused iter_env member (ip6arpa_dname)
|
||||
- Do not reset rrset.bogus stats when called using stats_noreset.
|
||||
- Added stats for queries that have been ratelimited by domain
|
||||
recursion.
|
||||
- Do not add rrset_bogus and query ratelimiting stats per thread, these
|
||||
module stats are global.
|
||||
|
||||
3 August 2017: Wouter
|
||||
- Fix #1394: mix of serve-expired and response-ip could cause a crash.
|
||||
|
||||
24 July 2017: Wouter
|
||||
- upgrade aclocal(pkg.m4 0.29.1), config.guess(2016-10-02),
|
||||
config.sub(2016-09-05).
|
||||
- annotate case statement fallthrough for gcc 7.1.1.
|
||||
- flex output from flex 2.6.1.
|
||||
- snprintf of thread number does not warn about truncated string.
|
||||
- squelch TCP fast open error on FreeBSD when kernel has it disabled,
|
||||
unless verbosity is high.
|
||||
- remove warning from windows compile.
|
||||
- Fix compile with libnettle
|
||||
- Fix DSA configure switch (--disable dsa) for libnettle and libnss.
|
||||
- Fix #1365: Add Ed25519 support using libnettle.
|
||||
- iana portlist update
|
||||
|
||||
17 July 2017: Wouter
|
||||
- Fix #1350: make cachedb backend configurable (from JINMEI Tatuya).
|
||||
- Fix #1349: allow suppression of pidfiles (from Daniel Kahn Gillmor).
|
||||
With the -p option unbound does not create a pidfile.
|
||||
|
||||
11 July 2017: Wouter
|
||||
- Fix #1344: RFC6761-reserved domains: test. and invalid.
|
||||
- Redirect all localhost names to localhost address for RFC6761.
|
||||
|
||||
6 July 2017: Wouter
|
||||
- Fix tests to use .tdir (from Manu Bretelle) instead of .tpkg.
|
||||
- Fix svn hooks for tdir (selected if testcode/mini_tdir.sh exists)..
|
||||
|
||||
4 July 2017: Wouter
|
||||
- Fix 1332: Bump verbosity of failed chown'ing of the control socket.
|
||||
|
||||
3 July 2017: Wouter
|
||||
- Fix for unbound-checkconf, check ipsecmod-hook if ipsecmod is turned
|
||||
on.
|
||||
- Fix #1331: libunbound segfault in threaded mode when context is
|
||||
deleted.
|
||||
- Fix pythonmod link line option flag.
|
||||
- Fix openssl 1.1.0 load of ssl error strings from ssl init.
|
||||
|
||||
29 June 2017: Wouter
|
||||
- Fix python example0 return module wait instead of error for pass.
|
||||
- iana portlist update
|
||||
- enhancement for hardened-tls for DNS over TLS. Removed duplicated
|
||||
security settings.
|
||||
|
||||
27 June 2017: Wouter
|
||||
- Tag 1.6.4 is created with the 1.6.4rc2 contents.
|
||||
- Trunk contains 1.6.5, with changes from 26, 27 june.
|
||||
- Remove signed unsigned warning from authzone.
|
||||
- Fix that infra cache host hash does not change after reconfig.
|
||||
|
||||
26 June 2017: Wouter
|
||||
- (for 1.6.5)
|
||||
Better fixup of dnscrypt_cert_chacha test for different escapes.
|
||||
- First fix for zero b64 and hex text zone format in sldns.
|
||||
- unbound-control dump_infra prints port number for address if not 53.
|
||||
|
||||
23 June 2017: Wouter
|
||||
- (for 1.6.5): fixup of dnscrypt_cert_chacha test (from Manu Bretelle).
|
||||
|
||||
22 June 2017: Wouter
|
||||
- Tag 1.6.4rc2
|
||||
|
||||
22 June 2017: Ralph
|
||||
- Added fastrpz patch to contrib
|
||||
|
||||
21 June 2017: Wouter
|
||||
- Fix #1316: heap read buffer overflow in parse_edns_options.
|
||||
|
||||
20 June 2017: Wouter
|
||||
- Fix warning in pythonmod under clang compiler.
|
||||
- Tag 1.6.4rc1
|
||||
- Fix lintian typo.
|
||||
|
||||
16 June 2017: Ralph
|
||||
- Fix #1277: disable domain ratelimit by setting value to 0.
|
||||
|
||||
16 June 2017: Wouter
|
||||
- Fix #1301: memory leak in respip and tests.
|
||||
- Free callback in edns-subnetmod on exit and restart.
|
||||
- Fix memory leak in sldns_buffer_new_frm_data.
|
||||
- Fix memory leak in dnscrypt config read.
|
||||
- Fix dnscrypt chacha cert support ifdefs.
|
||||
- Fix dnscrypt chacha cert unit test escapes in grep.
|
||||
- Remove asynclook tests that cause test and purifier problems.
|
||||
- Fix to unlock view in view test.
|
||||
|
||||
15 June 2017: Wouter
|
||||
- Fix stub zone queries leaking to the internet for
|
||||
harden-referral-path ns checks.
|
||||
- Fix query for refetch_glue of stub leaking to internet.
|
||||
|
||||
13 June 2017: Wouter
|
||||
- Fix #1279: Memory leak on reload when python module is enabled.
|
||||
- Fix #1280: Unbound fails assert when response from authoritative
|
||||
contains malformed qname. When 0x20 caps-for-id is enabled, when
|
||||
assertions are not enabled the malformed qname is handled correctly.
|
||||
- 1.6.3 tag created, with only #1280 fix, trunk is 1.6.4 development.
|
||||
- More fixes in depth for buffer checks in 0x20 qname checks.
|
||||
|
||||
12 June 2017: Wouter
|
||||
- Fix #1278: Incomplete wildcard proof.
|
||||
|
||||
8 June 2017: Ralph
|
||||
- Added domain name based ECS whitelist.
|
||||
|
||||
8 June 2017: Wouter
|
||||
- Detect chacha for dnscrypt at configure time.
|
||||
- dnscrypt unit tests with chacha.
|
||||
|
||||
7 June 2017: Wouter
|
||||
- Fix that unbound-control can set val_clean_additional and val_permissive_mode.
|
||||
- Add dnscrypt XChaCha20 tests.
|
||||
|
||||
6 June 2017: Wouter
|
||||
- Add an explicit type cast for TCP FASTOPEN fix.
|
||||
- renumbering B-Root's IPv6 address to 2001:500:200::b.
|
||||
- Fix #1275: cached data in cachedb is never used.
|
||||
- Fix #1276: [dnscrypt] add XChaCha20-Poly1305 cipher.
|
||||
|
||||
1 June 2017: Ralph
|
||||
- Fix #1274: automatically trim chroot path from dnscrypt key/cert paths
|
||||
(from Manu Bretelle).
|
||||
|
||||
1 June 2017: Wouter
|
||||
- Fix fastopen EPIPE fallthrough to perform connect.
|
||||
|
||||
31 May 2017: Ralph
|
||||
- Also use global local-zones when there is a matching view that does
|
||||
not have any local-zone specified.
|
||||
|
||||
31 May 2017: Wouter
|
||||
- Fix #1273: cachedb.c doesn't compile with -Wextra.
|
||||
- If MSG_FASTOPEN gives EPIPE fallthrough to try normal tcp write.
|
||||
|
||||
30 May 2017: Ralph
|
||||
- Fix #1269: inconsistent use of built-in local zones with views.
|
||||
- Add defaults for new local-zone trees added to views using
|
||||
unbound-control.
|
||||
|
||||
30 May 2017: Wouter
|
||||
- Support for openssl EVP_DigestVerify.
|
||||
- Support for the ED25519 algorithm with openssl (from openssl 1.1.1).
|
||||
|
||||
29 May 2017: Wouter
|
||||
- Fix assertion for low buffer size and big edns payload when worker
|
||||
overrides udpsize.
|
||||
|
||||
26 May 2017: Ralph
|
||||
- Added redirect-bogus.patch to contrib directory.
|
||||
|
||||
26 May 2017: Wouter
|
||||
- Fix #1270: unitauth.c doesn't compile with higher warning level
|
||||
and optimization
|
||||
- exec_prefix is by default equal to prefix.
|
||||
- printout localzone for duplicate local-zone warnings.
|
||||
|
||||
24 May 2017: Wouter
|
||||
- authzone cname chain, no rrset duplicates, wildcard doesn't change
|
||||
rrsets added for cname chain.
|
||||
|
||||
23 May 2017: Wouter
|
||||
- first services/authzone check in, it compiles and reads and writes
|
||||
zonefiles.
|
||||
- iana portlist update
|
||||
|
||||
22 May 2017: Wouter
|
||||
- Fix #1268: SIGSEGV after log_reopen.
|
||||
|
||||
18 May 2017: Wouter
|
||||
- Fix #1265 to use /bin/kill.
|
||||
- Fix #1267: Libunbound validator/val_secalgo.c uses obsolete APIs,
|
||||
and compatibility with BoringSSL.
|
||||
|
||||
17 May 2017: Wouter
|
||||
- Fix #1265: contrib/unbound.service contains hardcoded path.
|
||||
|
||||
17 May 2017: George
|
||||
- Use qstate's region for IPSECKEY rrset (ipsecmod).
|
||||
|
||||
16 May 2017: George
|
||||
- Implemented opportunistic IPsec support module (ipsecmod).
|
||||
- Some whitespace fixup.
|
||||
|
||||
16 May 2017: Wouter
|
||||
- updated dependencies in the makefile.
|
||||
- document trust-anchor-signaling in example config file.
|
||||
- updated configure, dependencies and flex output.
|
||||
- better module memory lookup, fix of unbound-control shm names for
|
||||
module memory printout of statistics.
|
||||
- Fix type AVC sldns rrdef.
|
||||
|
||||
12 May 2017: Wouter
|
||||
- Adjust servfail by iterator to not store in cache when serve-expired
|
||||
is enabled, to avoid overwriting useful information there.
|
||||
- Fix queries for nameservers under a stub leaking to the internet.
|
||||
|
||||
9 May 2017: Ralph
|
||||
- Add 'c' to getopt() in testbound.
|
||||
- iana portlist update
|
||||
|
||||
8 May 2017: Wouter
|
||||
- Fix tcp-mss failure printout text.
|
||||
- Set SO_REUSEADDR on outgoing tcp connections to fix the bind before
|
||||
connect limited tcp connections. With the option tcp connections
|
||||
can share the same source port (for different destinations).
|
||||
|
||||
2 May 2017: Ralph
|
||||
- Added mesh_add_sub to add detached mesh entries.
|
||||
- Use mesh_add_sub for key tag signaling query.
|
||||
|
||||
2 May 2017: Wouter
|
||||
- Added test for leak of stub information.
|
||||
- Fix sldns wire2str printout of RR type CAA tags.
|
||||
- Fix sldns int16_data parse.
|
||||
- Fix sldns parse and printout of TSIG RRs.
|
||||
- sldns SMIMEA and AVC definitions, same as getdns definitions.
|
||||
|
||||
1 May 2017: Wouter
|
||||
- Fix #1259: "--disable-ecdsa" argument overwritten
|
||||
by "#ifdef SHA256_DIGEST_LENGTH@daemon/remote.c".
|
||||
- iana portlist update
|
||||
- Fix #1258: Windows 10 X64 unbound 1.6.2 service will not start.
|
||||
and fix that 64bit getting installed in C:\Program Files (x86).
|
||||
|
||||
26 April 2017: Ralph
|
||||
- Implemented trust anchor signaling using key tag query.
|
||||
|
||||
26 April 2017: Wouter
|
||||
- Based on #1257: check parse limit before t increment in sldns RR
|
||||
string parse routine.
|
||||
|
||||
24 April 2017: Wouter
|
||||
- unbound-checkconf -o allows query of dnstap config variables.
|
||||
Also unbound-control get_option. Also for dnscrypt.
|
||||
- trunk contains 1.6.3 version number (changes from 1.6.2 back from
|
||||
when the 1.6.2rc1 tag has been created).
|
||||
|
||||
21 April 2017: Ralph
|
||||
- Fix #1254: clarify ratelimit-{for,below}-domain (from Manu Bretelle).
|
||||
- iana portlist update
|
||||
|
||||
18 April 2017: Ralph
|
||||
- Fix #1252: more indentation inconsistencies.
|
||||
- Fix #1253: unused variable in edns-subnet/addrtree.c:getbit().
|
||||
|
||||
13 April 2017: Ralph
|
||||
- Added ECS unit test (from Manu Bretelle).
|
||||
- ECS documentation fix (from Manu Bretelle).
|
||||
|
||||
13 April 2017: Wouter
|
||||
- Fix #1250: inconsistent indentation in services/listen_dnsport.c.
|
||||
- tag for 1.6.2rc1
|
||||
- (for 1.6.3:) unbound.h exports the shm stats structures. They use
|
||||
type long long and no ifdefs, and ub_ before the typenames.
|
||||
|
||||
12 April 2017: Wouter
|
||||
- subnet mem value is available in shm, also when not enabled,
|
||||
@@ -237,7 +1111,7 @@
|
||||
- Fix #1184: Log DNS replies. This includes the same logging
|
||||
information that DNS queries and response code and response size,
|
||||
patch from Larissa Feng.
|
||||
- Fix #1185: Source IP rate limiting, patch from Larissa Feng.
|
||||
- Fix #1187: Source IP rate limiting, patch from Larissa Feng.
|
||||
|
||||
3 January 2017: Wouter
|
||||
- configure --enable-systemd and lets unbound use systemd sockets if
|
||||
|
||||
+128
-21
@@ -116,7 +116,7 @@ server:
|
||||
# ip-freebind: no
|
||||
|
||||
# EDNS reassembly buffer to advertise to UDP peers (the actual buffer
|
||||
# is set with msg-buffer-size). 1480 can solve fragmentation (timeouts).
|
||||
# is set with msg-buffer-size). 1472 can solve fragmentation (timeouts)
|
||||
# edns-buffer-size: 4096
|
||||
|
||||
# Maximum UDP response size (not applied to TCP response).
|
||||
@@ -200,6 +200,10 @@ server:
|
||||
# useful for tunneling scenarios, default no.
|
||||
# tcp-upstream: no
|
||||
|
||||
# upstream connections also use UDP (even if do-udp is no).
|
||||
# useful if if you want UDP upstream, but don't provide UDP downstream.
|
||||
# udp-upstream-without-downstream: no
|
||||
|
||||
# Maximum segment size (MSS) of TCP socket on which the server
|
||||
# responds to queries. Default is 0, system default MSS.
|
||||
# tcp-mss: 0
|
||||
@@ -219,7 +223,8 @@ server:
|
||||
# to this server. Specify classless netblocks with /size and action.
|
||||
# By default everything is refused, except for localhost.
|
||||
# Choose deny (drop message), refuse (polite error reply),
|
||||
# allow (recursive ok), allow_snoop (recursive and nonrecursive ok)
|
||||
# allow (recursive ok), allow_setrd (recursive ok, rd bit is forced on),
|
||||
# allow_snoop (recursive and nonrecursive ok)
|
||||
# deny_non_local (drop queries unless can be answered from local-data)
|
||||
# refuse_non_local (like deny_non_local but polite error reply).
|
||||
# access-control: 0.0.0.0/0 refuse
|
||||
@@ -316,7 +321,7 @@ server:
|
||||
|
||||
# enable to not answer version.server and version.bind queries.
|
||||
# hide-version: no
|
||||
|
||||
|
||||
# enable to not answer trustanchor.unbound queries.
|
||||
# hide-trustanchor: no
|
||||
|
||||
@@ -367,8 +372,8 @@ server:
|
||||
|
||||
# Sent minimum amount of information to upstream servers to enhance
|
||||
# privacy. Only sent minimum required labels of the QNAME and set QTYPE
|
||||
# to NS when possible.
|
||||
# qname-minimisation: no
|
||||
# to A when possible.
|
||||
# qname-minimisation: yes
|
||||
|
||||
# QNAME minimisation in strict mode. Do not fall-back to sending full
|
||||
# QNAME to potentially broken nameservers. A lot of domains will not be
|
||||
@@ -376,6 +381,10 @@ server:
|
||||
# This option only has effect when qname-minimisation is enabled.
|
||||
# qname-minimisation-strict: no
|
||||
|
||||
# Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN
|
||||
# and other denials, using information from previous NXDOMAINs answers.
|
||||
# aggressive-nsec: no
|
||||
|
||||
# Use 0x20-encoded random bits in the query to foil spoof attempts.
|
||||
# This feature is an experimental implementation of draft dns-0x20.
|
||||
# use-caps-for-id: no
|
||||
@@ -448,6 +457,12 @@ server:
|
||||
# and under the terms of our LICENSE (see that file in the source).
|
||||
# auto-trust-anchor-file: "@UNBOUND_ROOTKEY_FILE@"
|
||||
|
||||
# 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
|
||||
|
||||
# File with DLV trusted keys. Same format as trust-anchor-file.
|
||||
# There can be only one DLV configured, it is trusted from root down.
|
||||
# DLV is going to be decommissioned. Please do not use it any more.
|
||||
@@ -509,7 +524,7 @@ server:
|
||||
# that set CD but cannot validate themselves.
|
||||
# ignore-cd-flag: no
|
||||
|
||||
# Serve expired reponses from cache, with TTL 0 in the response,
|
||||
# Serve expired responses from cache, with TTL 0 in the response,
|
||||
# and then attempt to fetch the data afresh.
|
||||
# serve-expired: no
|
||||
|
||||
@@ -560,6 +575,8 @@ server:
|
||||
# local-zone: "127.in-addr.arpa." nodefault
|
||||
# local-zone: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." nodefault
|
||||
# local-zone: "onion." nodefault
|
||||
# local-zone: "test." nodefault
|
||||
# local-zone: "invalid." nodefault
|
||||
# local-zone: "10.in-addr.arpa." nodefault
|
||||
# local-zone: "16.172.in-addr.arpa." nodefault
|
||||
# local-zone: "17.172.in-addr.arpa." nodefault
|
||||
@@ -617,7 +634,8 @@ server:
|
||||
# o inform acts like transparent, but logs client IP address
|
||||
# o inform_deny drops queries and logs client IP address
|
||||
# o always_transparent, always_refuse, always_nxdomain, resolve in
|
||||
# that way but ignore local data for that name.
|
||||
# that way but ignore local data for that name
|
||||
# o noview breaks out of that view towards global local-zones.
|
||||
#
|
||||
# defaults are localhost address, reverse for 127.0.0.1 and ::1
|
||||
# and nxdomain for AS112 zones. If you configure one of these zones
|
||||
@@ -650,16 +668,25 @@ server:
|
||||
# add a netblock specific override to a localzone, with zone type
|
||||
# local-zone-override: "example.com" 192.0.2.0/24 refuse
|
||||
|
||||
# service clients over SSL (on the TCP sockets), with plain DNS inside
|
||||
# the SSL stream. Give the certificate to use and private key.
|
||||
# service clients over TLS (on the TCP sockets), with plain DNS inside
|
||||
# the TLS stream. Give the certificate to use and private key.
|
||||
# default is "" (disabled). requires restart to take effect.
|
||||
# ssl-service-key: "path/to/privatekeyfile.key"
|
||||
# ssl-service-pem: "path/to/publiccertfile.pem"
|
||||
# ssl-port: 853
|
||||
# tls-service-key: "path/to/privatekeyfile.key"
|
||||
# tls-service-pem: "path/to/publiccertfile.pem"
|
||||
# tls-port: 853
|
||||
|
||||
# request upstream over SSL (with plain DNS inside the SSL stream).
|
||||
# request upstream over TLS (with plain DNS inside the TLS stream).
|
||||
# Default is no. Can be turned on and off with unbound-control.
|
||||
# ssl-upstream: no
|
||||
# tls-upstream: no
|
||||
|
||||
# Certificates used to authenticate connections made upstream.
|
||||
# tls-cert-bundle: ""
|
||||
|
||||
# Add system certs to the cert bundle, from the Windows Cert Store
|
||||
# tls-win-cert: no
|
||||
|
||||
# Also serve tls on these port numbers (eg. 443, ...), by listing
|
||||
# tls-additional-port: portno for each of the port numbers.
|
||||
|
||||
# DNS64 prefix. Must be specified when DNS64 is use.
|
||||
# Enable dns64 in module-config. Used to synthesize IPv6 from IPv4.
|
||||
@@ -698,6 +725,40 @@ 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
|
||||
|
||||
# Specific options for ipsecmod. unbound needs to be configured with
|
||||
# --enable-ipsecmod for these to take effect.
|
||||
#
|
||||
# Enable or disable ipsecmod (it still needs to be defined in
|
||||
# module-config above). Can be used when ipsecmod needs to be
|
||||
# enabled/disabled via remote-control(below).
|
||||
# ipsecmod-enabled: yes
|
||||
#
|
||||
# Path to executable external hook. It must be defined when ipsecmod is
|
||||
# listed in module-config (above).
|
||||
# ipsecmod-hook: "./my_executable"
|
||||
#
|
||||
# When enabled unbound will reply with SERVFAIL if the return value of
|
||||
# the ipsecmod-hook is not 0.
|
||||
# ipsecmod-strict: no
|
||||
#
|
||||
# Maximum time to live (TTL) for cached A/AAAA records with IPSECKEY.
|
||||
# ipsecmod-max-ttl: 3600
|
||||
#
|
||||
# Reply with A/AAAA even if the relevant IPSECKEY is bogus. Mainly used for
|
||||
# testing.
|
||||
# ipsecmod-ignore-bogus: no
|
||||
#
|
||||
# Domains for which ipsecmod will be triggered. If not defined (default)
|
||||
# all domains are treated as being whitelisted.
|
||||
# ipsecmod-whitelist: "example.com"
|
||||
# ipsecmod-whitelist: "nlnetlabs.nl"
|
||||
|
||||
|
||||
# Python config section. To enable:
|
||||
# o use --with-pythonmodule to configure before compiling.
|
||||
@@ -713,18 +774,20 @@ remote-control:
|
||||
# set up the keys and certificates with unbound-control-setup.
|
||||
# control-enable: no
|
||||
|
||||
# Set to no and use an absolute path as control-interface to use
|
||||
# a unix local named pipe for unbound-control.
|
||||
# control-use-cert: yes
|
||||
|
||||
# what interfaces are listened to for remote control.
|
||||
# give 0.0.0.0 and ::0 to listen to all interfaces.
|
||||
# set to an absolute path to use a unix local name pipe, certificates
|
||||
# are not used for that, so key and cert files need not be present.
|
||||
# control-interface: 127.0.0.1
|
||||
# control-interface: ::1
|
||||
|
||||
# port number for remote control operations.
|
||||
# control-port: 8953
|
||||
|
||||
# for localhost, you can disable use of TLS by setting this to "no"
|
||||
# For local sockets this option is ignored, and TLS is not used.
|
||||
# control-use-cert: "yes"
|
||||
|
||||
# unbound server key file.
|
||||
# server-key-file: "@UNBOUND_RUN_DIR@/unbound_server.key"
|
||||
|
||||
@@ -750,7 +813,7 @@ remote-control:
|
||||
# stub-addr: 192.0.2.68
|
||||
# stub-prime: no
|
||||
# stub-first: no
|
||||
# stub-ssl-upstream: no
|
||||
# stub-tls-upstream: no
|
||||
# stub-zone:
|
||||
# name: "example.org"
|
||||
# stub-host: ns.example.com.
|
||||
@@ -766,11 +829,37 @@ remote-control:
|
||||
# forward-addr: 192.0.2.68
|
||||
# forward-addr: 192.0.2.73@5355 # forward to port 5355.
|
||||
# forward-first: no
|
||||
# forward-ssl-upstream: no
|
||||
# forward-tls-upstream: no
|
||||
# forward-zone:
|
||||
# name: "example.org"
|
||||
# forward-host: fwd.example.com
|
||||
|
||||
# Authority zones
|
||||
# The data for these zones is kept locally, from a file or downloaded.
|
||||
# The data can be served to downstream clients, or used instead of the
|
||||
# upstream (which saves a lookup to the upstream). The first example
|
||||
# has a copy of the root for local usage. The second serves example.org
|
||||
# authoritatively. zonefile: reads from file (and writes to it if you also
|
||||
# download it), master: fetches with AXFR and IXFR, or url to zonefile.
|
||||
# With allow-notify: you can give additional (apart from masters) sources of
|
||||
# notifies.
|
||||
# auth-zone:
|
||||
# name: "."
|
||||
# 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
|
||||
# for-upstream: yes
|
||||
# zonefile: "example.org.zone"
|
||||
|
||||
# Views
|
||||
# Create named views. Name must be unique. Map views to requests using
|
||||
# the access-control-view option. Views can contain zero or more local-zone
|
||||
@@ -782,7 +871,7 @@ remote-control:
|
||||
# name: "viewname"
|
||||
# local-zone: "example.com" redirect
|
||||
# local-data: "example.com A 192.0.2.3"
|
||||
# local-data-ptr: "192.0.2.3 www.example.com"
|
||||
# local-data-ptr: "192.0.2.3 www.example.com"
|
||||
# view-first: no
|
||||
# view:
|
||||
# name: "anotherview"
|
||||
@@ -807,3 +896,21 @@ remote-control:
|
||||
# dnscrypt-secret-key: /path/unbound-conf/keys2/1.key
|
||||
# dnscrypt-provider-cert: /path/unbound-conf/keys1/1.cert
|
||||
# dnscrypt-provider-cert: /path/unbound-conf/keys2/1.cert
|
||||
|
||||
# CacheDB
|
||||
# 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.
|
||||
# cachedb:
|
||||
# backend: "testframe"
|
||||
# # secret seed string to calculate hashed keys
|
||||
# secret-seed: "default"
|
||||
#
|
||||
# # For "redis" backend:
|
||||
# # redis server's IP address or host name
|
||||
# redis-server-host: 127.0.0.1
|
||||
# # redis server's TCP port
|
||||
# redis-server-port: 6379
|
||||
# # timeout (in ms) for communication with the redis server
|
||||
# redis-timeout: 100
|
||||
|
||||
+11
-3
@@ -150,7 +150,8 @@
|
||||
is an implementation of a DNS resolver, that does caching and
|
||||
DNSSEC validation. This is the library API, for using the \-lunbound library.
|
||||
The server daemon is described in \fIunbound\fR(8).
|
||||
The library can be used to convert hostnames to ip addresses, and back,
|
||||
The library works independent from a running unbound server, and
|
||||
can be used to convert hostnames to ip addresses, and back,
|
||||
and obtain other information from the DNS. The library performs public\-key
|
||||
validation of results with DNSSEC.
|
||||
.P
|
||||
@@ -162,7 +163,7 @@ and deleting it with
|
||||
It can be created and deleted at any time. Creating it anew removes any
|
||||
previous configuration (such as trusted keys) and clears any cached results.
|
||||
.P
|
||||
The functions are thread\-safe, and a context an be used in a threaded (as
|
||||
The functions are thread\-safe, and a context can be used in a threaded (as
|
||||
well as in a non\-threaded) environment. Also resolution (and validation)
|
||||
can be performed blocking and non\-blocking (also called asynchronous).
|
||||
The async method returns from the call immediately, so that processing
|
||||
@@ -203,7 +204,10 @@ without trailing ':'. The returned value must be free(2)d by the caller.
|
||||
A power\-user interface that lets you specify an unbound config file, see
|
||||
\fIunbound.conf\fR(5), which is read for configuration. Not all options are
|
||||
relevant. For some specific options, such as adding trust anchors, special
|
||||
routines exist.
|
||||
routines exist. This function is thread\-safe only if a single instance of
|
||||
ub_ctx* exists in the application. If several instances exist the
|
||||
application has to ensure that ub_ctx_config is not called in parallel by
|
||||
the different instances.
|
||||
.TP
|
||||
.B ub_ctx_set_fwd
|
||||
Set machine to forward DNS queries to, the caching resolver to use.
|
||||
@@ -407,6 +411,10 @@ returns NULL on an error (a malloc failure).
|
||||
returns true if some information may be available, false otherwise.
|
||||
.B ub_fd
|
||||
returns a file descriptor or \-1 on error.
|
||||
.B ub_ctx_config
|
||||
and
|
||||
.B ub_ctx_resolvconf
|
||||
attempt to leave errno informative on a function return with file read failure.
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound\fR(8).
|
||||
|
||||
@@ -81,7 +81,7 @@ o Too many Features.
|
||||
|
||||
5. Choices
|
||||
----------
|
||||
o rfc2181 decourages duplicates RRs in RRsets. unbound does not create
|
||||
o rfc2181 discourages duplicates RRs in RRsets. unbound does not create
|
||||
duplicates, but when presented with duplicates on the wire from the
|
||||
authoritative servers, does not perform duplicate removal.
|
||||
It does do some rrsig duplicate removal, in the msgparser, for dnssec qtype
|
||||
|
||||
@@ -144,6 +144,9 @@ Remove the name, type information from the cache.
|
||||
Remove all information at or below the name from the cache.
|
||||
The rrsets and key entries are removed so that new lookups will be performed.
|
||||
This needs to walk and inspect the entire cache, and is a slow operation.
|
||||
The entries are set to expired in the implementation of this command (so,
|
||||
with serve\-expired enabled, it'll serve that information but schedule a
|
||||
prefetch for new information).
|
||||
.TP
|
||||
.B flush_bogus
|
||||
Remove all bogus data from the cache.
|
||||
@@ -286,6 +289,10 @@ estimated qps and qps limit from config. With +a it prints all ips, not
|
||||
just the ratelimited ips, with their estimated qps. The ratelimited
|
||||
ips are dropped before checking the cache.
|
||||
.TP
|
||||
.B list_auth_zones
|
||||
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 view_list_local_zones \fIview\fR
|
||||
\fIlist_local_zones\fR for given view.
|
||||
.TP
|
||||
@@ -337,6 +344,19 @@ number of queries that were successfully answered using a cache lookup
|
||||
.I threadX.num.cachemiss
|
||||
number of queries that needed recursive processing
|
||||
.TP
|
||||
.I threadX.num.dnscrypt.crypted
|
||||
number of queries that were encrypted and successfully decapsulated by dnscrypt.
|
||||
.TP
|
||||
.I threadX.num.dnscrypt.cert
|
||||
number of queries that were requesting dnscrypt certificates.
|
||||
.TP
|
||||
.I threadX.num.dnscrypt.cleartext
|
||||
number of queries received on dnscrypt port that were cleartext and not a
|
||||
request for certificates.
|
||||
.TP
|
||||
.I threadX.num.dnscrypt.malformed
|
||||
number of request that were neither cleartext, not valid dnscrypt messages.
|
||||
.TP
|
||||
.I threadX.num.prefetch
|
||||
number of cache prefetches performed. This number is included in
|
||||
cachehits, as the original query had the unprefetched answer from cache,
|
||||
@@ -393,6 +413,18 @@ summed over threads.
|
||||
.I total.num.cachemiss
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.dnscrypt.crypted
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.dnscrypt.cert
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.dnscrypt.cleartext
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.dnscrypt.malformed
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.prefetch
|
||||
summed over threads.
|
||||
.TP
|
||||
@@ -439,6 +471,12 @@ Memory in bytes in use by the RRset cache.
|
||||
.I mem.cache.message
|
||||
Memory in bytes in use by the message cache.
|
||||
.TP
|
||||
.I mem.cache.dnscrypt_shared_secret
|
||||
Memory in bytes in use by the dnscrypt shared secrets cache.
|
||||
.TP
|
||||
.I mem.cache.dnscrypt_nonce
|
||||
Memory in bytes in use by the dnscrypt nonce cache.
|
||||
.TP
|
||||
.I mem.mod.iterator
|
||||
Memory in bytes in use by the iterator module.
|
||||
.TP
|
||||
@@ -493,6 +531,18 @@ number of queries that had an EDNS OPT record present.
|
||||
number of queries that had an EDNS OPT record with the DO (DNSSEC OK) bit set.
|
||||
These queries are also included in the num.query.edns.present number.
|
||||
.TP
|
||||
.I num.query.ratelimited
|
||||
The number of queries that are turned away from being send to nameserver due to
|
||||
ratelimiting.
|
||||
.TP
|
||||
.I num.query.dnscrypt.shared_secret.cachemiss
|
||||
The number of dnscrypt queries that did not find a shared secret in the cache.
|
||||
The can be use to compute the shared secret hitrate.
|
||||
.TP
|
||||
.I num.query.dnscrypt.replay
|
||||
The number of dnscrypt queries that found a nonce hit in the nonce cache and
|
||||
hence are considered a query replay.
|
||||
.TP
|
||||
.I num.answer.rcode.NXDOMAIN
|
||||
The number of answers to queries, from cache or from recursion, that had the
|
||||
return code NXDOMAIN. Also printed for the other return codes.
|
||||
@@ -542,6 +592,39 @@ timing and protocol support information.
|
||||
.I key.cache.count
|
||||
The number of items in the key cache. These are DNSSEC keys, one item
|
||||
per delegation point, and their validation status.
|
||||
.TP
|
||||
.I dnscrypt_shared_secret.cache.count
|
||||
The number of items in the shared secret cache. These are precomputed shared
|
||||
secrets for a given client public key/server secret key pair. Shared secrets
|
||||
are CPU intensive and this cache allows unbound to avoid recomputing the
|
||||
shared secret when multiple dnscrypt queries are sent from the same client.
|
||||
.TP
|
||||
.I dnscrypt_nonce.cache.count
|
||||
The number of items in the client nonce cache. This cache is used to prevent
|
||||
dnscrypt queries replay. The client nonce must be unique for each client public
|
||||
key/server secret key pair. This cache should be able to host QPS * `replay
|
||||
window` interval keys to prevent replay of a query during `replay window`
|
||||
seconds.
|
||||
.TP
|
||||
.I num.query.authzone.up
|
||||
The number of queries answered from auth\-zone data, upstream queries.
|
||||
These queries would otherwise have been sent (with fallback enabled) to
|
||||
the internet, but are now answered from the auth zone.
|
||||
.TP
|
||||
.I num.query.authzone.down
|
||||
The number of queries for downstream answered from auth\-zone data.
|
||||
These queries are from downstream clients, and have had an answer from
|
||||
the data in the auth zone.
|
||||
.TP
|
||||
.I num.query.aggressive.NOERROR
|
||||
The number of queries answered using cached NSEC records with NODATA RCODE.
|
||||
These queries would otherwise have been sent to the internet, but are now
|
||||
answered using cached data.
|
||||
.TP
|
||||
.I num.query.aggressive.NXDOMAIN
|
||||
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.
|
||||
.SH "FILES"
|
||||
.TP
|
||||
.I @ub_conf_file@
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
.B unbound
|
||||
.RB [ \-h ]
|
||||
.RB [ \-d ]
|
||||
.RB [ \-p ]
|
||||
.RB [ \-v ]
|
||||
.RB [ \-c
|
||||
.IR cfgfile ]
|
||||
@@ -67,6 +68,11 @@ the thread\-spawn time, so that most config and setup errors appear on
|
||||
stderr. If given twice or more, logging does not switch to the log file
|
||||
or to syslog, but the log messages are printed to stderr all the time.
|
||||
.TP
|
||||
.B \-p
|
||||
Don't use a pidfile. This argument should only be used by supervision
|
||||
systems which can ensure that only one instance of unbound will run
|
||||
concurrently.
|
||||
.TP
|
||||
.B \-v
|
||||
Increase verbosity. If given multiple times, more information is logged.
|
||||
This is in addition to the verbosity (if any) from the config file.
|
||||
|
||||
+607
-212
File diff suppressed because it is too large
Load Diff
@@ -302,6 +302,7 @@ static int
|
||||
getbit(const addrkey_t *addr, addrlen_t addrlen, addrlen_t n)
|
||||
{
|
||||
log_assert(addrlen > n);
|
||||
(void)addrlen;
|
||||
return (int)(addr[n/KEYWIDTH]>>((KEYWIDTH-1)-(n%KEYWIDTH))) & 1;
|
||||
}
|
||||
|
||||
@@ -484,7 +485,7 @@ addrtree_find(struct addrtree *tree, const addrkey_t *addr,
|
||||
/* does this node have data? if yes, see if we have a match */
|
||||
if (node->elem && node->ttl >= now) {
|
||||
/* saved at wrong depth */;
|
||||
log_assert(node->scope >= depth)
|
||||
log_assert(node->scope >= depth);
|
||||
if (depth == node->scope ||
|
||||
(node->scope > sourcemask &&
|
||||
depth == sourcemask)) {
|
||||
|
||||
@@ -108,7 +108,7 @@ struct addrnode {
|
||||
struct addredge {
|
||||
/** address of connected node */
|
||||
addrkey_t *str;
|
||||
/** lenght in bits of str */
|
||||
/** length in bits of str */
|
||||
addrlen_t len;
|
||||
/** child node this edge is connected to */
|
||||
struct addrnode *node;
|
||||
|
||||
@@ -50,42 +50,44 @@
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/storage/dnstree.h"
|
||||
#include "sldns/str2wire.h"
|
||||
#include "util/data/dname.h"
|
||||
|
||||
struct ednssubnet_upstream*
|
||||
upstream_create(void)
|
||||
struct ecs_whitelist*
|
||||
ecs_whitelist_create(void)
|
||||
{
|
||||
struct ednssubnet_upstream* upstream =
|
||||
(struct ednssubnet_upstream*)calloc(1,
|
||||
sizeof(struct ednssubnet_upstream));
|
||||
if(!upstream)
|
||||
struct ecs_whitelist* whitelist =
|
||||
(struct ecs_whitelist*)calloc(1,
|
||||
sizeof(struct ecs_whitelist));
|
||||
if(!whitelist)
|
||||
return NULL;
|
||||
upstream->region = regional_create();
|
||||
if(!upstream->region) {
|
||||
upstream_delete(upstream);
|
||||
whitelist->region = regional_create();
|
||||
if(!whitelist->region) {
|
||||
ecs_whitelist_delete(whitelist);
|
||||
return NULL;
|
||||
}
|
||||
return upstream;
|
||||
return whitelist;
|
||||
}
|
||||
|
||||
void
|
||||
upstream_delete(struct ednssubnet_upstream* upstream)
|
||||
ecs_whitelist_delete(struct ecs_whitelist* whitelist)
|
||||
{
|
||||
if(!upstream)
|
||||
if(!whitelist)
|
||||
return;
|
||||
regional_destroy(upstream->region);
|
||||
free(upstream);
|
||||
regional_destroy(whitelist->region);
|
||||
free(whitelist);
|
||||
}
|
||||
|
||||
/** insert new address into upstream structure */
|
||||
/** insert new address into whitelist structure */
|
||||
static int
|
||||
upstream_insert(struct ednssubnet_upstream* upstream,
|
||||
upstream_insert(struct ecs_whitelist* whitelist,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int net)
|
||||
{
|
||||
struct addr_tree_node* node = (struct addr_tree_node*)regional_alloc(
|
||||
upstream->region, sizeof(*node));
|
||||
whitelist->region, sizeof(*node));
|
||||
if(!node)
|
||||
return 0;
|
||||
if(!addr_tree_insert(&upstream->tree, node, addr, addrlen, net)) {
|
||||
if(!addr_tree_insert(&whitelist->upstream, node, addr, addrlen, net)) {
|
||||
verbose(VERB_QUERY,
|
||||
"duplicate send-client-subnet address ignored.");
|
||||
}
|
||||
@@ -94,7 +96,7 @@ upstream_insert(struct ednssubnet_upstream* upstream,
|
||||
|
||||
/** apply edns-subnet string */
|
||||
static int
|
||||
upstream_str_cfg(struct ednssubnet_upstream* upstream, const char* str)
|
||||
upstream_str_cfg(struct ecs_whitelist* whitelist, const char* str)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
int net;
|
||||
@@ -104,7 +106,7 @@ upstream_str_cfg(struct ednssubnet_upstream* upstream, const char* str)
|
||||
log_err("cannot parse send-client-subnet netblock: %s", str);
|
||||
return 0;
|
||||
}
|
||||
if(!upstream_insert(upstream, &addr, addrlen, net)) {
|
||||
if(!upstream_insert(whitelist, &addr, addrlen, net)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
@@ -113,41 +115,93 @@ upstream_str_cfg(struct ednssubnet_upstream* upstream, const char* str)
|
||||
|
||||
/** read client_subnet config */
|
||||
static int
|
||||
read_upstream(struct ednssubnet_upstream* upstream, struct config_file* cfg)
|
||||
read_upstream(struct ecs_whitelist* whitelist, struct config_file* cfg)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
for(p = cfg->client_subnet; p; p = p->next) {
|
||||
log_assert(p->str);
|
||||
if(!upstream_str_cfg(upstream, p->str))
|
||||
if(!upstream_str_cfg(whitelist, p->str))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
upstream_apply_cfg(struct ednssubnet_upstream* upstream,
|
||||
struct config_file* cfg)
|
||||
/** read client_subnet_zone config */
|
||||
static int
|
||||
read_names(struct ecs_whitelist* whitelist, struct config_file* cfg)
|
||||
{
|
||||
regional_free_all(upstream->region);
|
||||
addr_tree_init(&upstream->tree);
|
||||
if(!read_upstream(upstream, cfg))
|
||||
return 0;
|
||||
addr_tree_init_parents(&upstream->tree);
|
||||
/* parse names, report errors, insert into tree */
|
||||
struct config_strlist* p;
|
||||
struct name_tree_node* n;
|
||||
uint8_t* nm, *nmr;
|
||||
size_t nm_len;
|
||||
int nm_labs;
|
||||
|
||||
for(p = cfg->client_subnet_zone; p; p = p->next) {
|
||||
log_assert(p->str);
|
||||
nm = sldns_str2wire_dname(p->str, &nm_len);
|
||||
if(!nm) {
|
||||
log_err("cannot parse client-subnet-zone: %s", p->str);
|
||||
return 0;
|
||||
}
|
||||
nm_labs = dname_count_size_labels(nm, &nm_len);
|
||||
nmr = (uint8_t*)regional_alloc_init(whitelist->region, nm,
|
||||
nm_len);
|
||||
free(nm);
|
||||
if(!nmr) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
n = (struct name_tree_node*)regional_alloc(whitelist->region,
|
||||
sizeof(*n));
|
||||
if(!n) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
if(!name_tree_insert(&whitelist->dname, n, nmr, nm_len, nm_labs,
|
||||
LDNS_RR_CLASS_IN)) {
|
||||
verbose(VERB_QUERY, "ignoring duplicate "
|
||||
"client-subnet-zone: %s", p->str);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
upstream_is_whitelisted(struct ednssubnet_upstream* upstream,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
ecs_whitelist_apply_cfg(struct ecs_whitelist* whitelist,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
return addr_tree_lookup(&upstream->tree, addr, addrlen) != NULL;
|
||||
regional_free_all(whitelist->region);
|
||||
addr_tree_init(&whitelist->upstream);
|
||||
name_tree_init(&whitelist->dname);
|
||||
if(!read_upstream(whitelist, cfg))
|
||||
return 0;
|
||||
if(!read_names(whitelist, cfg))
|
||||
return 0;
|
||||
addr_tree_init_parents(&whitelist->upstream);
|
||||
name_tree_init_parents(&whitelist->dname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ecs_is_whitelisted(struct ecs_whitelist* whitelist,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* qname,
|
||||
size_t qname_len, uint16_t qclass)
|
||||
{
|
||||
int labs;
|
||||
if(addr_tree_lookup(&whitelist->upstream, addr, addrlen))
|
||||
return 1;
|
||||
/* Not in upstream whitelist, check dname whitelist. */
|
||||
labs = dname_count_labels(qname);
|
||||
return name_tree_lookup(&whitelist->dname, qname, qname_len, labs,
|
||||
qclass) != NULL;
|
||||
}
|
||||
|
||||
size_t
|
||||
upstream_get_mem(struct ednssubnet_upstream* upstream)
|
||||
ecs_whitelist_get_mem(struct ecs_whitelist* whitelist)
|
||||
{
|
||||
if(!upstream) return 0;
|
||||
return sizeof(*upstream) + regional_get_mem(upstream->region);
|
||||
if(!whitelist) return 0;
|
||||
return sizeof(*whitelist) + regional_get_mem(whitelist->region);
|
||||
}
|
||||
|
||||
#endif /* CLIENT_SUBNET */
|
||||
|
||||
@@ -36,8 +36,8 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Keep track of the white listed servers for subnet option. Based
|
||||
* on acl_list.c|h
|
||||
* Keep track of the white listed servers and domain names for subnet option.
|
||||
* Based on acl_list.c|h
|
||||
*/
|
||||
|
||||
#ifndef EDNSSUBNET_WHITELIST_H
|
||||
@@ -48,9 +48,9 @@ struct config_file;
|
||||
struct regional;
|
||||
|
||||
/**
|
||||
* ednssubnet_upstream structure
|
||||
* ecs_whitelist structure
|
||||
*/
|
||||
struct ednssubnet_upstream {
|
||||
struct ecs_whitelist {
|
||||
/** regional for allocation */
|
||||
struct regional* region;
|
||||
/**
|
||||
@@ -58,45 +58,54 @@ struct ednssubnet_upstream {
|
||||
* contents of type addr_tree_node. Each node is an address span
|
||||
* Unbound will append subnet option for.
|
||||
*/
|
||||
rbtree_type tree;
|
||||
rbtree_type upstream;
|
||||
/**
|
||||
* Tree of domain names for which Unbound will append an ECS option.
|
||||
* rbtree of struct name_tree_node.
|
||||
*/
|
||||
rbtree_type dname;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create ednssubnet_upstream structure
|
||||
* Create ecs_whitelist structure
|
||||
* @return new structure or NULL on error.
|
||||
*/
|
||||
struct ednssubnet_upstream* upstream_create(void);
|
||||
struct ecs_whitelist* ecs_whitelist_create(void);
|
||||
|
||||
/**
|
||||
* Delete ednssubnet_upstream structure.
|
||||
* @param upstream: to delete.
|
||||
* Delete ecs_whitelist structure.
|
||||
* @param whitelist: to delete.
|
||||
*/
|
||||
void upstream_delete(struct ednssubnet_upstream* upstream);
|
||||
void ecs_whitelist_delete(struct ecs_whitelist* whitelist);
|
||||
|
||||
/**
|
||||
* Process ednssubnet_upstream config.
|
||||
* @param upstream: where to store.
|
||||
* Process ecs_whitelist config.
|
||||
* @param whitelist: where to store.
|
||||
* @param cfg: config options.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
int upstream_apply_cfg(struct ednssubnet_upstream* upstream,
|
||||
int ecs_whitelist_apply_cfg(struct ecs_whitelist* whitelist,
|
||||
struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* See if an address is whitelisted.
|
||||
* @param upstream: structure for address storage.
|
||||
* See if an address or domain is whitelisted.
|
||||
* @param whitelist: structure for address storage.
|
||||
* @param addr: address to check
|
||||
* @param addrlen: length of addr.
|
||||
* @param qname: dname in query
|
||||
* @param qname_len: length of dname
|
||||
* @param qclass: class in query
|
||||
* @return: true if the address is whitelisted for subnet option.
|
||||
*/
|
||||
int upstream_is_whitelisted(struct ednssubnet_upstream* upstream,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen);
|
||||
int ecs_is_whitelisted(struct ecs_whitelist* whitelist,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* qname,
|
||||
size_t qname_len, uint16_t qclass);
|
||||
|
||||
/**
|
||||
* Get memory used by ednssubnet_upstream structure.
|
||||
* @param upstream: structure for address storage.
|
||||
* Get memory used by ecs_whitelist structure.
|
||||
* @param whitelist: structure for address storage.
|
||||
* @return bytes in use.
|
||||
*/
|
||||
size_t upstream_get_mem(struct ednssubnet_upstream* upstream);
|
||||
size_t ecs_whitelist_get_mem(struct ecs_whitelist* whitelist);
|
||||
|
||||
#endif /* EDNSSUBNET_WHITELIST_H */
|
||||
|
||||
+19
-12
@@ -135,7 +135,7 @@ ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
|
||||
}
|
||||
}
|
||||
|
||||
int ecs_whitelist_check(struct query_info* ATTR_UNUSED(qinfo),
|
||||
int ecs_whitelist_check(struct query_info* qinfo,
|
||||
uint16_t ATTR_UNUSED(flags), struct module_qstate* qstate,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
|
||||
@@ -154,8 +154,9 @@ int ecs_whitelist_check(struct query_info* ATTR_UNUSED(qinfo),
|
||||
|
||||
if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream &&
|
||||
qstate->env->cfg->client_subnet_always_forward) ||
|
||||
upstream_is_whitelisted(sn_env->edns_subnet_upstreams,
|
||||
addr, addrlen))) {
|
||||
ecs_is_whitelisted(sn_env->whitelist,
|
||||
addr, addrlen, qinfo->qname, qinfo->qname_len,
|
||||
qinfo->qclass))) {
|
||||
/* Address on whitelist or client query contains ECS option, we
|
||||
* want to sent out ECS. Only add option if it is not already
|
||||
* set. */
|
||||
@@ -199,9 +200,9 @@ subnetmod_init(struct module_env *env, int id)
|
||||
return 0;
|
||||
}
|
||||
/* whitelist for edns subnet capable servers */
|
||||
sn_env->edns_subnet_upstreams = upstream_create();
|
||||
if(!sn_env->edns_subnet_upstreams ||
|
||||
!upstream_apply_cfg(sn_env->edns_subnet_upstreams, env->cfg)) {
|
||||
sn_env->whitelist = ecs_whitelist_create();
|
||||
if(!sn_env->whitelist ||
|
||||
!ecs_whitelist_apply_cfg(sn_env->whitelist, env->cfg)) {
|
||||
log_err("subnet: could not create ECS whitelist");
|
||||
slabhash_delete(sn_env->subnet_msg_cache);
|
||||
free(sn_env);
|
||||
@@ -217,7 +218,7 @@ subnetmod_init(struct module_env *env, int id)
|
||||
env->cfg->client_subnet_always_forward /* bypass cache */,
|
||||
0 /* no aggregation */, env)) {
|
||||
log_err("subnet: could not register opcode");
|
||||
upstream_delete(sn_env->edns_subnet_upstreams);
|
||||
ecs_whitelist_delete(sn_env->whitelist);
|
||||
slabhash_delete(sn_env->subnet_msg_cache);
|
||||
free(sn_env);
|
||||
env->modinfo[id] = NULL;
|
||||
@@ -243,7 +244,8 @@ subnetmod_deinit(struct module_env *env, int id)
|
||||
lock_rw_destroy(&sn_env->biglock);
|
||||
inplace_cb_delete(env, inplace_cb_edns_back_parsed, id);
|
||||
inplace_cb_delete(env, inplace_cb_query, id);
|
||||
upstream_delete(sn_env->edns_subnet_upstreams);
|
||||
inplace_cb_delete(env, inplace_cb_query_response, id);
|
||||
ecs_whitelist_delete(sn_env->whitelist);
|
||||
slabhash_delete(sn_env->subnet_msg_cache);
|
||||
alloc_clear(&sn_env->alloc);
|
||||
free(sn_env);
|
||||
@@ -337,6 +339,7 @@ update_cache(struct module_qstate *qstate, int id)
|
||||
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) {
|
||||
@@ -350,7 +353,9 @@ update_cache(struct module_qstate *qstate, int id)
|
||||
log_err("Subnet cache insertion failed");
|
||||
return;
|
||||
}
|
||||
lock_quick_lock(&sne->alloc.lock);
|
||||
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);
|
||||
log_err("Subnet cache insertion failed");
|
||||
@@ -372,6 +377,7 @@ update_cache(struct module_qstate *qstate, int id)
|
||||
if (acquired_lock) {
|
||||
lock_rw_unlock(&lru_entry->lock);
|
||||
} else {
|
||||
lock_rw_unlock(&lru_entry->lock);
|
||||
slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data,
|
||||
NULL);
|
||||
}
|
||||
@@ -530,7 +536,7 @@ parse_subnet_option(struct edns_option* ecs_option, struct ecs_data* ecs)
|
||||
ecs->subnet_addr_fam = sldns_read_uint16(ecs_option->opt_data);
|
||||
ecs->subnet_source_mask = ecs_option->opt_data[2];
|
||||
ecs->subnet_scope_mask = ecs_option->opt_data[3];
|
||||
/* remaing bytes indicate address */
|
||||
/* remaining bytes indicate address */
|
||||
|
||||
/* validate input*/
|
||||
/* option length matches calculated length? */
|
||||
@@ -600,7 +606,7 @@ ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
|
||||
|
||||
if(sq->subnet_sent &&
|
||||
FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_REFUSED) {
|
||||
/* REFUSED reponse to ECS query, remove ECS option. */
|
||||
/* REFUSED response to ECS query, remove ECS option. */
|
||||
edns_opt_list_remove(&qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode);
|
||||
sq->subnet_sent = 0;
|
||||
@@ -626,7 +632,7 @@ ecs_edns_back_parsed(struct module_qstate* qstate, int id,
|
||||
sq->ecs_server_in.subnet_validdata)
|
||||
/* Only skip global cache store if we sent an ECS option
|
||||
* and received one back. Answers from non-whitelisted
|
||||
* servers will end up in global cache. Ansers for
|
||||
* servers will end up in global cache. Answers for
|
||||
* queries with 0 source will not (unless nameserver
|
||||
* does not support ECS). */
|
||||
qstate->no_cache_store = 1;
|
||||
@@ -720,6 +726,7 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
sq->ecs_server_out.subnet_scope_mask = 0;
|
||||
sq->ecs_server_out.subnet_validdata = 1;
|
||||
if(sq->ecs_server_out.subnet_source_mask != 0 &&
|
||||
qstate->env->cfg->client_subnet_always_forward &&
|
||||
sq->subnet_downstream)
|
||||
/* ECS specific data required, do not look at the global
|
||||
* cache in other modules. */
|
||||
@@ -781,7 +788,7 @@ subnetmod_get_mem(struct module_env *env, int id)
|
||||
if (!sn_env) return 0;
|
||||
return sizeof(*sn_env) +
|
||||
slabhash_get_mem(sn_env->subnet_msg_cache) +
|
||||
upstream_get_mem(sn_env->edns_subnet_upstreams);
|
||||
ecs_whitelist_get_mem(sn_env->whitelist);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -57,7 +57,7 @@ struct subnet_env {
|
||||
* data: struct subnet_msg_cache_data* */
|
||||
struct slabhash* subnet_msg_cache;
|
||||
/** access control, which upstream servers we send client address */
|
||||
struct ednssubnet_upstream* edns_subnet_upstreams;
|
||||
struct ecs_whitelist* whitelist;
|
||||
/** allocation service */
|
||||
struct alloc_cache alloc;
|
||||
lock_rw_type biglock;
|
||||
@@ -119,7 +119,7 @@ int ecs_whitelist_check(struct query_info* qinfo, uint16_t flags,
|
||||
socklen_t addrlen, uint8_t* zone, size_t zonelen,
|
||||
struct regional* region, int id, void* cbargs);
|
||||
|
||||
/** Check whether reponse from server contains ECS record, if so, skip cache
|
||||
/** Check whether response from server contains ECS record, if so, skip cache
|
||||
* store. Called just after parsing EDNS data from server. */
|
||||
int ecs_edns_back_parsed(struct module_qstate* qstate, int id, void* cbargs);
|
||||
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* ipsecmod/ipsecmod-whitelist.h - White listed domains for the ipsecmod to
|
||||
* operate on.
|
||||
*
|
||||
* Copyright (c) 2017, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* 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 NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Keep track of the white listed domains for ipsecmod.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef USE_IPSECMOD
|
||||
#include "ipsecmod/ipsecmod.h"
|
||||
#include "ipsecmod/ipsecmod-whitelist.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/rbtree.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/storage/dnstree.h"
|
||||
#include "sldns/str2wire.h"
|
||||
|
||||
/** Apply ipsecmod-whitelist string. */
|
||||
static int
|
||||
whitelist_str_cfg(rbtree_type* whitelist, const char* name)
|
||||
{
|
||||
struct name_tree_node* n;
|
||||
size_t len;
|
||||
uint8_t* nm = sldns_str2wire_dname(name, &len);
|
||||
if(!nm) {
|
||||
log_err("ipsecmod: could not parse %s for whitelist.", name);
|
||||
return 0;
|
||||
}
|
||||
n = (struct name_tree_node*)calloc(1, sizeof(*n));
|
||||
if(!n) {
|
||||
log_err("ipsecmod: out of memory while creating whitelist.");
|
||||
free(nm);
|
||||
return 0;
|
||||
}
|
||||
n->node.key = n;
|
||||
n->name = nm;
|
||||
n->len = len;
|
||||
n->labs = dname_count_labels(nm);
|
||||
n->dclass = LDNS_RR_CLASS_IN;
|
||||
if(!name_tree_insert(whitelist, n, nm, len, n->labs, n->dclass)) {
|
||||
/* duplicate element ignored, idempotent */
|
||||
free(n->name);
|
||||
free(n);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Read ipsecmod-whitelist config. */
|
||||
static int
|
||||
read_whitelist(rbtree_type* whitelist, struct config_file* cfg)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
for(p = cfg->ipsecmod_whitelist; p; p = p->next) {
|
||||
log_assert(p->str);
|
||||
if(!whitelist_str_cfg(whitelist, p->str))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ipsecmod_whitelist_apply_cfg(struct ipsecmod_env* ie,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
ie->whitelist = rbtree_create(name_tree_compare);
|
||||
if(!read_whitelist(ie->whitelist, cfg))
|
||||
return 0;
|
||||
name_tree_init_parents(ie->whitelist);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Delete ipsecmod_env->whitelist element. */
|
||||
static void
|
||||
whitelist_free(struct rbnode_type* n, void* ATTR_UNUSED(d))
|
||||
{
|
||||
if(n) {
|
||||
free(((struct name_tree_node*)n)->name);
|
||||
free(n);
|
||||
}
|
||||
}
|
||||
|
||||
/** Get memory usage of ipsecmod_env->whitelist element. */
|
||||
static void
|
||||
whitelist_get_mem(struct rbnode_type* n, void* arg)
|
||||
{
|
||||
struct name_tree_node* node = (struct name_tree_node*)n;
|
||||
size_t* size = (size_t*) arg;
|
||||
if(node) {
|
||||
*size += sizeof(node) + node->len;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ipsecmod_whitelist_delete(rbtree_type* whitelist)
|
||||
{
|
||||
if(whitelist) {
|
||||
traverse_postorder(whitelist, whitelist_free, NULL);
|
||||
free(whitelist);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ipsecmod_domain_is_whitelisted(struct ipsecmod_env* ie, uint8_t* dname,
|
||||
size_t dname_len, uint16_t qclass)
|
||||
{
|
||||
if(!ie->whitelist) return 1; /* No whitelist, treat as whitelisted. */
|
||||
return name_tree_lookup(ie->whitelist, dname, dname_len,
|
||||
dname_count_labels(dname), qclass) != NULL;
|
||||
}
|
||||
|
||||
size_t
|
||||
ipsecmod_whitelist_get_mem(rbtree_type* whitelist)
|
||||
{
|
||||
size_t size = 0;
|
||||
if(whitelist) {
|
||||
traverse_postorder(whitelist, whitelist_get_mem, &size);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
#endif /* USE_IPSECMOD */
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* ipsecmod/ipsecmod-whitelist.h - White listed domains for the ipsecmod to
|
||||
* operate on.
|
||||
*
|
||||
* Copyright (c) 2017, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* 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 NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Keep track of the white listed domains for ipsecmod.
|
||||
*/
|
||||
|
||||
#ifndef IPSECMOD_WHITELIST_H
|
||||
#define IPSECMOD_WHITELIST_H
|
||||
#include "util/storage/dnstree.h"
|
||||
|
||||
struct config_file;
|
||||
struct regional;
|
||||
|
||||
/**
|
||||
* Process ipsecmod_whitelist config.
|
||||
* @param ie: ipsecmod environment.
|
||||
* @param cfg: config options.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
int ipsecmod_whitelist_apply_cfg(struct ipsecmod_env* ie,
|
||||
struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Delete the ipsecmod whitelist.
|
||||
* @param whitelist: ipsecmod whitelist.
|
||||
*/
|
||||
void ipsecmod_whitelist_delete(rbtree_type* whitelist);
|
||||
|
||||
/**
|
||||
* See if a domain is whitelisted.
|
||||
* @param ie: ipsecmod environment.
|
||||
* @param dname: domain name to check.
|
||||
* @param dname_len: length of domain name.
|
||||
* @param qclass: query CLASS.
|
||||
* @return: true if the domain is whitelisted for the ipsecmod.
|
||||
*/
|
||||
int ipsecmod_domain_is_whitelisted(struct ipsecmod_env* ie, uint8_t* dname,
|
||||
size_t dname_len, uint16_t qclass);
|
||||
|
||||
/**
|
||||
* Get memory used by ipsecmod whitelist.
|
||||
* @param whitelist: structure for domain storage.
|
||||
* @return bytes in use.
|
||||
*/
|
||||
size_t ipsecmod_whitelist_get_mem(rbtree_type* whitelist);
|
||||
|
||||
#endif /* IPSECMOD_WHITELIST_H */
|
||||
@@ -0,0 +1,515 @@
|
||||
/*
|
||||
* ipsecmod/ipsecmod.c - facilitate opportunistic IPsec module
|
||||
*
|
||||
* Copyright (c) 2017, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* 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 NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains a module that facilitates opportunistic IPsec. It does so
|
||||
* by also quering for the IPSECKEY for A/AAAA queries and calling a
|
||||
* configurable hook (eg. signaling an IKE daemon) before replying.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#ifdef USE_IPSECMOD
|
||||
#include "ipsecmod/ipsecmod.h"
|
||||
#include "ipsecmod/ipsecmod-whitelist.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/config_file.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "sldns/wire2str.h"
|
||||
|
||||
/** Apply configuration to ipsecmod module 'global' state. */
|
||||
static int
|
||||
ipsecmod_apply_cfg(struct ipsecmod_env* ipsecmod_env, struct config_file* cfg)
|
||||
{
|
||||
if(!cfg->ipsecmod_hook || (cfg->ipsecmod_hook && !cfg->ipsecmod_hook[0])) {
|
||||
log_err("ipsecmod: missing ipsecmod-hook.");
|
||||
return 0;
|
||||
}
|
||||
if(cfg->ipsecmod_whitelist &&
|
||||
!ipsecmod_whitelist_apply_cfg(ipsecmod_env, cfg))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ipsecmod_init(struct module_env* env, int id)
|
||||
{
|
||||
struct ipsecmod_env* ipsecmod_env = (struct ipsecmod_env*)calloc(1,
|
||||
sizeof(struct ipsecmod_env));
|
||||
if(!ipsecmod_env) {
|
||||
log_err("malloc failure");
|
||||
return 0;
|
||||
}
|
||||
env->modinfo[id] = (void*)ipsecmod_env;
|
||||
ipsecmod_env->whitelist = NULL;
|
||||
if(!ipsecmod_apply_cfg(ipsecmod_env, env->cfg)) {
|
||||
log_err("ipsecmod: could not apply configuration settings.");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
ipsecmod_deinit(struct module_env* env, int id)
|
||||
{
|
||||
struct ipsecmod_env* ipsecmod_env;
|
||||
if(!env || !env->modinfo[id])
|
||||
return;
|
||||
ipsecmod_env = (struct ipsecmod_env*)env->modinfo[id];
|
||||
/* Free contents. */
|
||||
ipsecmod_whitelist_delete(ipsecmod_env->whitelist);
|
||||
free(ipsecmod_env);
|
||||
env->modinfo[id] = NULL;
|
||||
}
|
||||
|
||||
/** New query for ipsecmod. */
|
||||
static int
|
||||
ipsecmod_new(struct module_qstate* qstate, int id)
|
||||
{
|
||||
struct ipsecmod_qstate* iq = (struct ipsecmod_qstate*)regional_alloc(
|
||||
qstate->region, sizeof(struct ipsecmod_qstate));
|
||||
memset(iq, 0, sizeof(*iq));
|
||||
qstate->minfo[id] = iq;
|
||||
if(!iq)
|
||||
return 0;
|
||||
/* Initialise it. */
|
||||
iq->enabled = qstate->env->cfg->ipsecmod_enabled;
|
||||
iq->is_whitelisted = ipsecmod_domain_is_whitelisted(
|
||||
(struct ipsecmod_env*)qstate->env->modinfo[id], qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len, qstate->qinfo.qclass);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit module with an error status.
|
||||
* @param qstate: query state
|
||||
* @param id: module id.
|
||||
*/
|
||||
static void
|
||||
ipsecmod_error(struct module_qstate* qstate, int id)
|
||||
{
|
||||
qstate->ext_state[id] = module_error;
|
||||
qstate->return_rcode = LDNS_RCODE_SERVFAIL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a request for the IPSECKEY.
|
||||
*
|
||||
* @param qstate: query state that is the parent.
|
||||
* @param id: module id.
|
||||
* @param name: what name to query for.
|
||||
* @param namelen: length of name.
|
||||
* @param qtype: query type.
|
||||
* @param qclass: query class.
|
||||
* @param flags: additional flags, such as the CD bit (BIT_CD), or 0.
|
||||
* @return false on alloc failure.
|
||||
*/
|
||||
static int
|
||||
generate_request(struct module_qstate* qstate, int id, uint8_t* name,
|
||||
size_t namelen, uint16_t qtype, uint16_t qclass, uint16_t flags)
|
||||
{
|
||||
struct module_qstate* newq;
|
||||
struct query_info ask;
|
||||
ask.qname = name;
|
||||
ask.qname_len = namelen;
|
||||
ask.qtype = qtype;
|
||||
ask.qclass = qclass;
|
||||
ask.local_alias = NULL;
|
||||
log_query_info(VERB_ALGO, "ipsecmod: generate request", &ask);
|
||||
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
|
||||
if(!(*qstate->env->attach_sub)(qstate, &ask,
|
||||
(uint16_t)(BIT_RD|flags), 0, 0, &newq)){
|
||||
log_err("Could not generate request: out of memory");
|
||||
return 0;
|
||||
}
|
||||
qstate->ext_state[id] = module_wait_subquery;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data and call the hook.
|
||||
*
|
||||
* @param qstate: query state.
|
||||
* @param iq: ipsecmod qstate.
|
||||
* @param ie: ipsecmod environment.
|
||||
* @return true on success, false otherwise.
|
||||
*/
|
||||
static int
|
||||
call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
|
||||
struct ipsecmod_env* ATTR_UNUSED(ie))
|
||||
{
|
||||
size_t slen, tempdata_len, tempstring_len, i;
|
||||
char str[65535], *s, *tempstring;
|
||||
int w;
|
||||
struct ub_packed_rrset_key* rrset_key;
|
||||
struct packed_rrset_data* rrset_data;
|
||||
uint8_t *tempdata;
|
||||
|
||||
/* Check if a shell is available */
|
||||
if(system(NULL) == 0) {
|
||||
log_err("ipsecmod: no shell available for ipsecmod-hook");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Zero the buffer. */
|
||||
s = str;
|
||||
slen = sizeof(str);
|
||||
memset(s, 0, slen);
|
||||
|
||||
/* Copy the hook into the buffer. */
|
||||
sldns_str_print(&s, &slen, "%s", qstate->env->cfg->ipsecmod_hook);
|
||||
/* Put space into the buffer. */
|
||||
sldns_str_print(&s, &slen, " ");
|
||||
/* Copy the qname into the buffer. */
|
||||
tempstring = sldns_wire2str_dname(qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len);
|
||||
if(!tempstring) {
|
||||
log_err("ipsecmod: out of memory when calling the hook");
|
||||
return 0;
|
||||
}
|
||||
sldns_str_print(&s, &slen, "\"%s\"", tempstring);
|
||||
free(tempstring);
|
||||
/* Put space into the buffer. */
|
||||
sldns_str_print(&s, &slen, " ");
|
||||
/* Copy the IPSECKEY TTL into the buffer. */
|
||||
rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data;
|
||||
sldns_str_print(&s, &slen, "\"%ld\"", (long)rrset_data->ttl);
|
||||
/* Put space into the buffer. */
|
||||
sldns_str_print(&s, &slen, " ");
|
||||
/* Copy the A/AAAA record(s) into the buffer. Start and end this section
|
||||
* with a double quote. */
|
||||
rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
rrset_data = (struct packed_rrset_data*)rrset_key->entry.data;
|
||||
sldns_str_print(&s, &slen, "\"");
|
||||
for(i=0; i<rrset_data->count; i++) {
|
||||
if(i > 0) {
|
||||
/* Put space into the buffer. */
|
||||
sldns_str_print(&s, &slen, " ");
|
||||
}
|
||||
/* Ignore the first two bytes, they are the rr_data len. */
|
||||
w = sldns_wire2str_rdata_buf(rrset_data->rr_data[i] + 2,
|
||||
rrset_data->rr_len[i] - 2, s, slen, qstate->qinfo.qtype);
|
||||
if(w < 0) {
|
||||
/* Error in printout. */
|
||||
return -1;
|
||||
} else if((size_t)w >= slen) {
|
||||
s = NULL; /* We do not want str to point outside of buffer. */
|
||||
slen = 0;
|
||||
return -1;
|
||||
} else {
|
||||
s += w;
|
||||
slen -= w;
|
||||
}
|
||||
}
|
||||
sldns_str_print(&s, &slen, "\"");
|
||||
/* Put space into the buffer. */
|
||||
sldns_str_print(&s, &slen, " ");
|
||||
/* Copy the IPSECKEY record(s) into the buffer. Start and end this section
|
||||
* with a double quote. */
|
||||
sldns_str_print(&s, &slen, "\"");
|
||||
rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data;
|
||||
for(i=0; i<rrset_data->count; i++) {
|
||||
if(i > 0) {
|
||||
/* Put space into the buffer. */
|
||||
sldns_str_print(&s, &slen, " ");
|
||||
}
|
||||
/* Ignore the first two bytes, they are the rr_data len. */
|
||||
tempdata = rrset_data->rr_data[i] + 2;
|
||||
tempdata_len = rrset_data->rr_len[i] - 2;
|
||||
/* Save the buffer pointers. */
|
||||
tempstring = s; tempstring_len = slen;
|
||||
w = sldns_wire2str_ipseckey_scan(&tempdata, &tempdata_len, &s, &slen,
|
||||
NULL, 0);
|
||||
/* There was an error when parsing the IPSECKEY; reset the buffer
|
||||
* pointers to their previous values. */
|
||||
if(w == -1){
|
||||
s = tempstring; slen = tempstring_len;
|
||||
}
|
||||
}
|
||||
sldns_str_print(&s, &slen, "\"");
|
||||
verbose(VERB_ALGO, "ipsecmod: hook command: '%s'", str);
|
||||
/* ipsecmod-hook should return 0 on success. */
|
||||
if(system(str) != 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an ipsecmod module event with a query
|
||||
* @param qstate: query state (from the mesh), passed between modules.
|
||||
* contains qstate->env module environment with global caches and so on.
|
||||
* @param iq: query state specific for this module. per-query.
|
||||
* @param ie: environment specific for this module. global.
|
||||
* @param id: module id.
|
||||
*/
|
||||
static void
|
||||
ipsecmod_handle_query(struct module_qstate* qstate,
|
||||
struct ipsecmod_qstate* iq, struct ipsecmod_env* ie, int id)
|
||||
{
|
||||
struct ub_packed_rrset_key* rrset_key;
|
||||
struct packed_rrset_data* rrset_data;
|
||||
size_t i;
|
||||
/* Pass to next module if we are not enabled and whitelisted. */
|
||||
if(!(iq->enabled && iq->is_whitelisted)) {
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
/* New query, check if the query is for an A/AAAA record and disable
|
||||
* caching for other modules. */
|
||||
if(!iq->ipseckey_done) {
|
||||
if(qstate->qinfo.qtype == LDNS_RR_TYPE_A ||
|
||||
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) {
|
||||
char type[16];
|
||||
sldns_wire2str_type_buf(qstate->qinfo.qtype, type,
|
||||
sizeof(type));
|
||||
verbose(VERB_ALGO, "ipsecmod: query for %s; engaging",
|
||||
type);
|
||||
qstate->no_cache_store = 1;
|
||||
}
|
||||
/* Pass request to next module. */
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
/* IPSECKEY subquery is finished. */
|
||||
/* We have an IPSECKEY answer. */
|
||||
if(iq->ipseckey_rrset) {
|
||||
rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data;
|
||||
if(rrset_data) {
|
||||
/* If bogus return SERVFAIL. */
|
||||
if(!qstate->env->cfg->ipsecmod_ignore_bogus &&
|
||||
rrset_data->security == sec_status_bogus) {
|
||||
log_err("ipsecmod: bogus IPSECKEY");
|
||||
ipsecmod_error(qstate, id);
|
||||
return;
|
||||
}
|
||||
/* We have a valid IPSECKEY reply, call hook. */
|
||||
if(!call_hook(qstate, iq, ie) &&
|
||||
qstate->env->cfg->ipsecmod_strict) {
|
||||
log_err("ipsecmod: ipsecmod-hook failed");
|
||||
ipsecmod_error(qstate, id);
|
||||
return;
|
||||
}
|
||||
/* Make sure the A/AAAA's TTL is equal/less than the
|
||||
* ipsecmod_max_ttl. */
|
||||
rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
rrset_data = (struct packed_rrset_data*)rrset_key->entry.data;
|
||||
if(rrset_data->ttl > (time_t)qstate->env->cfg->ipsecmod_max_ttl) {
|
||||
/* Update TTL for rrset to fixed value. */
|
||||
rrset_data->ttl = qstate->env->cfg->ipsecmod_max_ttl;
|
||||
for(i=0; i<rrset_data->count+rrset_data->rrsig_count; i++)
|
||||
rrset_data->rr_ttl[i] = qstate->env->cfg->ipsecmod_max_ttl;
|
||||
/* Also update reply_info's TTL */
|
||||
if(qstate->return_msg->rep->ttl > (time_t)qstate->env->cfg->ipsecmod_max_ttl) {
|
||||
qstate->return_msg->rep->ttl =
|
||||
qstate->env->cfg->ipsecmod_max_ttl;
|
||||
qstate->return_msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(
|
||||
qstate->return_msg->rep->ttl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Store A/AAAA in cache. */
|
||||
if(!dns_cache_store(qstate->env, &qstate->qinfo,
|
||||
qstate->return_msg->rep, 0, qstate->prefetch_leeway,
|
||||
0, qstate->region, qstate->query_flags)) {
|
||||
log_err("ipsecmod: out of memory caching record");
|
||||
}
|
||||
qstate->ext_state[id] = module_finished;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an ipsecmod module event with a response from the iterator.
|
||||
* @param qstate: query state (from the mesh), passed between modules.
|
||||
* contains qstate->env module environment with global caches and so on.
|
||||
* @param iq: query state specific for this module. per-query.
|
||||
* @param ie: environment specific for this module. global.
|
||||
* @param id: module id.
|
||||
*/
|
||||
static void
|
||||
ipsecmod_handle_response(struct module_qstate* qstate,
|
||||
struct ipsecmod_qstate* ATTR_UNUSED(iq),
|
||||
struct ipsecmod_env* ATTR_UNUSED(ie), int id)
|
||||
{
|
||||
/* Pass to previous module if we are not enabled and whitelisted. */
|
||||
if(!(iq->enabled && iq->is_whitelisted)) {
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
/* check if the response is for an A/AAAA query. */
|
||||
if((qstate->qinfo.qtype == LDNS_RR_TYPE_A ||
|
||||
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) &&
|
||||
/* check that we had an answer for the A/AAAA query. */
|
||||
qstate->return_msg &&
|
||||
reply_find_answer_rrset(&qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep) &&
|
||||
/* check that another module didn't SERVFAIL. */
|
||||
qstate->return_rcode == LDNS_RCODE_NOERROR) {
|
||||
char type[16];
|
||||
sldns_wire2str_type_buf(qstate->qinfo.qtype, type,
|
||||
sizeof(type));
|
||||
verbose(VERB_ALGO, "ipsecmod: response for %s; generating IPSECKEY "
|
||||
"subquery", type);
|
||||
/* generate an IPSECKEY query. */
|
||||
if(!generate_request(qstate, id, qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len, LDNS_RR_TYPE_IPSECKEY,
|
||||
qstate->qinfo.qclass, 0)) {
|
||||
log_err("ipsecmod: could not generate subquery.");
|
||||
ipsecmod_error(qstate, id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* we are done with the query. */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
}
|
||||
|
||||
void
|
||||
ipsecmod_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
struct outbound_entry* outbound)
|
||||
{
|
||||
struct ipsecmod_env* ie = (struct ipsecmod_env*)qstate->env->modinfo[id];
|
||||
struct ipsecmod_qstate* iq = (struct ipsecmod_qstate*)qstate->minfo[id];
|
||||
verbose(VERB_QUERY, "ipsecmod[module %d] operate: extstate:%s event:%s",
|
||||
id, strextstate(qstate->ext_state[id]), strmodulevent(event));
|
||||
if(iq) log_query_info(VERB_QUERY, "ipsecmod operate: query",
|
||||
&qstate->qinfo);
|
||||
|
||||
/* create ipsecmod_qstate. */
|
||||
if((event == module_event_new || event == module_event_pass) &&
|
||||
iq == NULL) {
|
||||
if(!ipsecmod_new(qstate, id)) {
|
||||
ipsecmod_error(qstate, id);
|
||||
return;
|
||||
}
|
||||
iq = (struct ipsecmod_qstate*)qstate->minfo[id];
|
||||
}
|
||||
if(iq && (event == module_event_pass || event == module_event_new)) {
|
||||
ipsecmod_handle_query(qstate, iq, ie, id);
|
||||
return;
|
||||
}
|
||||
if(iq && (event == module_event_moddone)) {
|
||||
ipsecmod_handle_response(qstate, iq, ie, id);
|
||||
return;
|
||||
}
|
||||
if(iq && outbound) {
|
||||
/* cachedb does not need to process responses at this time
|
||||
* ignore it.
|
||||
cachedb_process_response(qstate, iq, ie, id, outbound, event);
|
||||
*/
|
||||
return;
|
||||
}
|
||||
if(event == module_event_error) {
|
||||
verbose(VERB_ALGO, "got called with event error, giving up");
|
||||
ipsecmod_error(qstate, id);
|
||||
return;
|
||||
}
|
||||
if(!iq && (event == module_event_moddone)) {
|
||||
/* during priming, module done but we never started. */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
|
||||
log_err("ipsecmod: bad event %s", strmodulevent(event));
|
||||
ipsecmod_error(qstate, id);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
ipsecmod_inform_super(struct module_qstate* qstate, int id,
|
||||
struct module_qstate* super)
|
||||
{
|
||||
struct ipsecmod_qstate* siq;
|
||||
log_query_info(VERB_ALGO, "ipsecmod: inform_super, sub is",
|
||||
&qstate->qinfo);
|
||||
log_query_info(VERB_ALGO, "super is", &super->qinfo);
|
||||
siq = (struct ipsecmod_qstate*)super->minfo[id];
|
||||
if(!siq) {
|
||||
verbose(VERB_ALGO, "super has no ipsecmod state");
|
||||
return;
|
||||
}
|
||||
|
||||
if(qstate->return_msg) {
|
||||
struct ub_packed_rrset_key* rrset_key = reply_find_answer_rrset(
|
||||
&qstate->return_msg->qinfo, qstate->return_msg->rep);
|
||||
if(rrset_key) {
|
||||
/* We have an answer. */
|
||||
/* Copy to super's region. */
|
||||
rrset_key = packed_rrset_copy_region(rrset_key, super->region, 0);
|
||||
siq->ipseckey_rrset = rrset_key;
|
||||
if(!rrset_key) {
|
||||
log_err("ipsecmod: out of memory.");
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Notify super to proceed. */
|
||||
siq->ipseckey_done = 1;
|
||||
}
|
||||
|
||||
void
|
||||
ipsecmod_clear(struct module_qstate* qstate, int id)
|
||||
{
|
||||
if(!qstate)
|
||||
return;
|
||||
qstate->minfo[id] = NULL;
|
||||
}
|
||||
|
||||
size_t
|
||||
ipsecmod_get_mem(struct module_env* env, int id)
|
||||
{
|
||||
struct ipsecmod_env* ie = (struct ipsecmod_env*)env->modinfo[id];
|
||||
if(!ie)
|
||||
return 0;
|
||||
return sizeof(*ie) + ipsecmod_whitelist_get_mem(ie->whitelist);
|
||||
}
|
||||
|
||||
/**
|
||||
* The ipsecmod function block
|
||||
*/
|
||||
static struct module_func_block ipsecmod_block = {
|
||||
"ipsecmod",
|
||||
&ipsecmod_init, &ipsecmod_deinit, &ipsecmod_operate,
|
||||
&ipsecmod_inform_super, &ipsecmod_clear, &ipsecmod_get_mem
|
||||
};
|
||||
|
||||
struct module_func_block*
|
||||
ipsecmod_get_funcblock(void)
|
||||
{
|
||||
return &ipsecmod_block;
|
||||
}
|
||||
#endif /* USE_IPSECMOD */
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* ipsecmod/ipsecmod.h - facilitate opportunistic IPsec module
|
||||
*
|
||||
* Copyright (c) 2017, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* 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 NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains a module that facilitates opportunistic IPsec. It does so
|
||||
* by also quering for the IPSECKEY for A/AAAA queries and calling a
|
||||
* configurable hook (eg. signaling an IKE daemon) before replying.
|
||||
*/
|
||||
|
||||
#ifndef IPSECMOD_H
|
||||
#define IPSECMOD_H
|
||||
#include "util/module.h"
|
||||
#include "util/rbtree.h"
|
||||
|
||||
/**
|
||||
* The global variable environment contents for the ipsecmod
|
||||
* Shared between threads, this represents long term information.
|
||||
*/
|
||||
struct ipsecmod_env {
|
||||
/** White listed domains for ipsecmod. */
|
||||
rbtree_type* whitelist;
|
||||
};
|
||||
|
||||
/**
|
||||
* Per query state for the ipsecmod module.
|
||||
*/
|
||||
struct ipsecmod_qstate {
|
||||
/** State of the IPsec module. */
|
||||
/** NOTE: This value is copied here from the configuration so that a change
|
||||
* with unbound-control would not complicate an already running mesh. */
|
||||
int enabled;
|
||||
/** If the qname is whitelisted or not. */
|
||||
/** NOTE: No whitelist means all qnames are whitelisted. */
|
||||
int is_whitelisted;
|
||||
/** Pointer to IPSECKEY rrset allocated in the qstate region. NULL if there
|
||||
* was no IPSECKEY reply from the subquery. */
|
||||
struct ub_packed_rrset_key* ipseckey_rrset;
|
||||
/** If the IPSECKEY subquery has finished. */
|
||||
int ipseckey_done;
|
||||
};
|
||||
|
||||
/** Init the ipsecmod module */
|
||||
int ipsecmod_init(struct module_env* env, int id);
|
||||
/** Deinit the ipsecmod module */
|
||||
void ipsecmod_deinit(struct module_env* env, int id);
|
||||
/** Operate on an event on a query (in qstate). */
|
||||
void ipsecmod_operate(struct module_qstate* qstate, enum module_ev event,
|
||||
int id, struct outbound_entry* outbound);
|
||||
/** Subordinate query done, inform this super request of its conclusion */
|
||||
void ipsecmod_inform_super(struct module_qstate* qstate, int id,
|
||||
struct module_qstate* super);
|
||||
/** clear the ipsecmod query-specific contents out of qstate */
|
||||
void ipsecmod_clear(struct module_qstate* qstate, int id);
|
||||
/** return memory estimate for the ipsecmod module */
|
||||
size_t ipsecmod_get_mem(struct module_env* env, int id);
|
||||
|
||||
/**
|
||||
* Get the function block with pointers to the ipsecmod functions
|
||||
* @return the function block for "ipsecmod".
|
||||
*/
|
||||
struct module_func_block* ipsecmod_get_funcblock(void);
|
||||
|
||||
#endif /* IPSECMOD_H */
|
||||
+28
-6
@@ -84,7 +84,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
|
||||
}
|
||||
for(a = dp->target_list; a; a = a->next_target) {
|
||||
if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen,
|
||||
a->bogus, a->lame))
|
||||
a->bogus, a->lame, a->tls_auth_name))
|
||||
return NULL;
|
||||
}
|
||||
return copy;
|
||||
@@ -176,13 +176,13 @@ delegpt_add_target(struct delegpt* dp, struct regional* region,
|
||||
if(ns->got4 && ns->got6)
|
||||
ns->resolved = 1;
|
||||
}
|
||||
return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame);
|
||||
return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
delegpt_add_addr(struct delegpt* dp, struct regional* region,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus,
|
||||
uint8_t lame)
|
||||
uint8_t lame, char* tls_auth_name)
|
||||
{
|
||||
struct delegpt_addr* a;
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
@@ -210,6 +210,13 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region,
|
||||
a->bogus = bogus;
|
||||
a->lame = lame;
|
||||
a->dnsseclame = 0;
|
||||
if(tls_auth_name) {
|
||||
a->tls_auth_name = regional_strdup(region, tls_auth_name);
|
||||
if(!a->tls_auth_name)
|
||||
return 0;
|
||||
} else {
|
||||
a->tls_auth_name = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -276,11 +283,16 @@ void delegpt_log(enum verbosity_value v, struct delegpt* dp)
|
||||
(ns->done_pside6?" PSIDE_AAAA":""));
|
||||
}
|
||||
for(a = dp->target_list; a; a = a->next_target) {
|
||||
char s[128];
|
||||
const char* str = " ";
|
||||
if(a->bogus && a->lame) str = " BOGUS ADDR_LAME ";
|
||||
else if(a->bogus) str = " BOGUS ";
|
||||
else if(a->lame) str = " ADDR_LAME ";
|
||||
log_addr(VERB_ALGO, str, &a->addr, a->addrlen);
|
||||
if(a->tls_auth_name)
|
||||
snprintf(s, sizeof(s), "%s[%s]", str,
|
||||
a->tls_auth_name);
|
||||
else snprintf(s, sizeof(s), "%s", str);
|
||||
log_addr(VERB_ALGO, s, &a->addr, a->addrlen);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -539,6 +551,7 @@ void delegpt_free_mlc(struct delegpt* dp)
|
||||
a = dp->target_list;
|
||||
while(a) {
|
||||
na = a->next_target;
|
||||
free(a->tls_auth_name);
|
||||
free(a);
|
||||
a = na;
|
||||
}
|
||||
@@ -585,7 +598,7 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame)
|
||||
}
|
||||
|
||||
int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t bogus, uint8_t lame)
|
||||
socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name)
|
||||
{
|
||||
struct delegpt_addr* a;
|
||||
log_assert(dp->dp_type_mlc);
|
||||
@@ -612,6 +625,15 @@ int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
|
||||
a->bogus = bogus;
|
||||
a->lame = lame;
|
||||
a->dnsseclame = 0;
|
||||
if(tls_auth_name) {
|
||||
a->tls_auth_name = strdup(tls_auth_name);
|
||||
if(!a->tls_auth_name) {
|
||||
free(a);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
a->tls_auth_name = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -632,7 +654,7 @@ int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen,
|
||||
if(ns->got4 && ns->got6)
|
||||
ns->resolved = 1;
|
||||
}
|
||||
return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame);
|
||||
return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame, NULL);
|
||||
}
|
||||
|
||||
size_t delegpt_get_mem(struct delegpt* dp)
|
||||
|
||||
@@ -83,6 +83,8 @@ struct delegpt {
|
||||
uint8_t dp_type_mlc;
|
||||
/** use SSL for upstream query */
|
||||
uint8_t ssl_upstream;
|
||||
/** delegpt from authoritative zone that is locally hosted */
|
||||
uint8_t auth_dp;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -149,6 +151,8 @@ struct delegpt_addr {
|
||||
* option is useful to mark the address dnsseclame.
|
||||
* This value is not copied in addr-copy and dp-copy. */
|
||||
uint8_t dnsseclame;
|
||||
/** the TLS authentication name, (if not NULL) to use. */
|
||||
char* tls_auth_name;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -257,11 +261,12 @@ int delegpt_add_rrset(struct delegpt* dp, struct regional* regional,
|
||||
* @param addrlen: the length of addr.
|
||||
* @param bogus: if address is bogus.
|
||||
* @param lame: if address is lame.
|
||||
* @param tls_auth_name: TLS authentication name (or NULL).
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_addr(struct delegpt* dp, struct regional* regional,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t bogus, uint8_t lame);
|
||||
uint8_t bogus, uint8_t lame, char* tls_auth_name);
|
||||
|
||||
/**
|
||||
* Find NS record in name list of delegation point.
|
||||
@@ -392,10 +397,11 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame);
|
||||
* @param addrlen: the length of addr.
|
||||
* @param bogus: if address is bogus.
|
||||
* @param lame: if address is lame.
|
||||
* @param tls_auth_name: TLS authentication name (or NULL).
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t bogus, uint8_t lame);
|
||||
socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name);
|
||||
|
||||
/**
|
||||
* Add target address to the delegation point.
|
||||
|
||||
+4
-2
@@ -231,14 +231,16 @@ read_fwds_addr(struct config_stub* s, struct delegpt* dp)
|
||||
struct config_strlist* p;
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen;
|
||||
char* tls_auth_name;
|
||||
for(p = s->addrs; p; p = p->next) {
|
||||
log_assert(p->str);
|
||||
if(!extstrtoaddr(p->str, &addr, &addrlen)) {
|
||||
if(!authextstrtoaddr(p->str, &addr, &addrlen, &tls_auth_name)) {
|
||||
log_err("cannot parse forward %s ip address: '%s'",
|
||||
s->name, p->str);
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
|
||||
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
|
||||
tls_auth_name)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ compile_time_root_prime(int do_ip4, int do_ip6)
|
||||
dp->has_parent_side_NS = 1;
|
||||
if(do_ip4) {
|
||||
if(!ah(dp, "A.ROOT-SERVERS.NET.", "198.41.0.4")) goto failed;
|
||||
if(!ah(dp, "B.ROOT-SERVERS.NET.", "192.228.79.201")) goto failed;
|
||||
if(!ah(dp, "B.ROOT-SERVERS.NET.", "199.9.14.201")) goto failed;
|
||||
if(!ah(dp, "C.ROOT-SERVERS.NET.", "192.33.4.12")) goto failed;
|
||||
if(!ah(dp, "D.ROOT-SERVERS.NET.", "199.7.91.13")) goto failed;
|
||||
if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) goto failed;
|
||||
@@ -144,7 +144,7 @@ compile_time_root_prime(int do_ip4, int do_ip6)
|
||||
}
|
||||
if(do_ip6) {
|
||||
if(!ah(dp, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) goto failed;
|
||||
if(!ah(dp, "B.ROOT-SERVERS.NET.", "2001:500:84::b")) goto failed;
|
||||
if(!ah(dp, "B.ROOT-SERVERS.NET.", "2001:500:200::b")) goto failed;
|
||||
if(!ah(dp, "C.ROOT-SERVERS.NET.", "2001:500:2::c")) goto failed;
|
||||
if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) goto failed;
|
||||
if(!ah(dp, "E.ROOT-SERVERS.NET.", "2001:500:a8::e")) goto failed;
|
||||
@@ -244,14 +244,16 @@ read_stubs_addr(struct config_stub* s, struct delegpt* dp)
|
||||
struct config_strlist* p;
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen;
|
||||
char* auth_name;
|
||||
for(p = s->addrs; p; p = p->next) {
|
||||
log_assert(p->str);
|
||||
if(!extstrtoaddr(p->str, &addr, &addrlen)) {
|
||||
if(!authextstrtoaddr(p->str, &addr, &addrlen, &auth_name)) {
|
||||
log_err("cannot parse stub %s ip address: '%s'",
|
||||
s->name, p->str);
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
|
||||
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
|
||||
auth_name)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -503,6 +503,24 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* if this is type DS and we query for type DS we just got
|
||||
* a referral answer for our type DS query, fix packet */
|
||||
if(rrset->type==LDNS_RR_TYPE_DS &&
|
||||
qinfo->qtype == LDNS_RR_TYPE_DS &&
|
||||
dname_pkt_compare(pkt, qinfo->qname, rrset->dname) == 0) {
|
||||
rrset->section = LDNS_SECTION_ANSWER;
|
||||
msg->ancount = rrset->rr_count + rrset->rrsig_count;
|
||||
msg->nscount = 0;
|
||||
msg->arcount = 0;
|
||||
msg->an_rrsets = 1;
|
||||
msg->ns_rrsets = 0;
|
||||
msg->ar_rrsets = 0;
|
||||
msg->rrset_count = 1;
|
||||
msg->rrset_first = rrset;
|
||||
msg->rrset_last = rrset;
|
||||
rrset->rrset_all_next = NULL;
|
||||
return 1;
|
||||
}
|
||||
mark_additional_rrset(pkt, msg, rrset);
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
|
||||
+23
-7
@@ -312,9 +312,9 @@ static int
|
||||
iter_filter_order(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* selected_rtt, int open_target,
|
||||
struct sock_list* blacklist)
|
||||
struct sock_list* blacklist, time_t prefetch)
|
||||
{
|
||||
int got_num = 0, low_rtt = 0, swap_to_front;
|
||||
int got_num = 0, low_rtt = 0, swap_to_front, rtt_band = RTT_BAND;
|
||||
struct delegpt_addr* a, *n, *prev=NULL;
|
||||
|
||||
/* fillup sel_rtt and find best rtt in the bunch */
|
||||
@@ -329,6 +329,16 @@ 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) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
got_num = 0;
|
||||
a = dp->result_list;
|
||||
while(a) {
|
||||
@@ -340,10 +350,10 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
|
||||
}
|
||||
/* classify the server address and determine what to do */
|
||||
swap_to_front = 0;
|
||||
if(a->sel_rtt >= low_rtt && a->sel_rtt - low_rtt <= RTT_BAND) {
|
||||
if(a->sel_rtt >= low_rtt && a->sel_rtt - low_rtt <= rtt_band) {
|
||||
got_num++;
|
||||
swap_to_front = 1;
|
||||
} else if(a->sel_rtt<low_rtt && low_rtt-a->sel_rtt<=RTT_BAND) {
|
||||
} else if(a->sel_rtt<low_rtt && low_rtt-a->sel_rtt<=rtt_band) {
|
||||
got_num++;
|
||||
swap_to_front = 1;
|
||||
}
|
||||
@@ -400,13 +410,14 @@ struct delegpt_addr*
|
||||
iter_server_selection(struct iter_env* iter_env,
|
||||
struct module_env* env, struct delegpt* dp,
|
||||
uint8_t* name, size_t namelen, uint16_t qtype, int* dnssec_lame,
|
||||
int* chase_to_rd, int open_target, struct sock_list* blacklist)
|
||||
int* chase_to_rd, int open_target, struct sock_list* blacklist,
|
||||
time_t prefetch)
|
||||
{
|
||||
int sel;
|
||||
int selrtt;
|
||||
struct delegpt_addr* a, *prev;
|
||||
int num = iter_filter_order(iter_env, env, name, namelen, qtype,
|
||||
*env->now, dp, &selrtt, open_target, blacklist);
|
||||
*env->now, dp, &selrtt, open_target, blacklist, prefetch);
|
||||
|
||||
if(num == 0)
|
||||
return NULL;
|
||||
@@ -625,7 +636,7 @@ iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
|
||||
}
|
||||
|
||||
int
|
||||
iter_indicates_dnssec_fwd(struct module_env* env, struct query_info *qinfo)
|
||||
iter_qname_indicates_dnssec(struct module_env* env, struct query_info *qinfo)
|
||||
{
|
||||
struct trust_anchor* a;
|
||||
if(!env || !env->anchors || !qinfo || !qinfo->qname)
|
||||
@@ -656,6 +667,11 @@ iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
|
||||
/* a trust anchor exists with this name, RRSIGs expected */
|
||||
if((a=anchor_find(env->anchors, dp->name, dp->namelabs, dp->namelen,
|
||||
dclass))) {
|
||||
if(a->numDS == 0 && a->numDNSKEY == 0) {
|
||||
/* insecure trust point */
|
||||
lock_basic_unlock(&a->lock);
|
||||
return 0;
|
||||
}
|
||||
lock_basic_unlock(&a->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
+11
-7
@@ -87,13 +87,18 @@ int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg);
|
||||
* @param open_target: number of currently outstanding target queries.
|
||||
* If we wait for these, perhaps more server addresses become available.
|
||||
* @param blacklist: the IP blacklist to use.
|
||||
* @param prefetch: if not 0, prefetch is in use for this query.
|
||||
* This means the query can have different timing, because prefetch is
|
||||
* not waited upon by the downstream client, and thus a good time to
|
||||
* perform exploration of other targets.
|
||||
* @return best target or NULL if no target.
|
||||
* if not null, that target is removed from the result list in the dp.
|
||||
*/
|
||||
struct delegpt_addr* iter_server_selection(struct iter_env* iter_env,
|
||||
struct module_env* env, struct delegpt* dp, uint8_t* name,
|
||||
size_t namelen, uint16_t qtype, int* dnssec_lame,
|
||||
int* chase_to_rd, int open_target, struct sock_list* blacklist);
|
||||
int* chase_to_rd, int open_target, struct sock_list* blacklist,
|
||||
time_t prefetch);
|
||||
|
||||
/**
|
||||
* Allocate dns_msg from parsed msg, in regional.
|
||||
@@ -174,15 +179,14 @@ int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
|
||||
struct delegpt* dp);
|
||||
|
||||
/**
|
||||
* See if qname has DNSSEC needs in the forwarding case. This is true if
|
||||
* there is a trust anchor above it. Whether there is an insecure delegation
|
||||
* to the data is unknown, but CD-retry is needed.
|
||||
* See if qname has DNSSEC needs. This is true if there is a trust anchor above
|
||||
* it. Whether there is an insecure delegation to the data is unknown.
|
||||
* @param env: environment with anchors.
|
||||
* @param qinfo: query name and class.
|
||||
* @return true if trust anchor above qname, false if no anchor or insecure
|
||||
* point above qname.
|
||||
*/
|
||||
int iter_indicates_dnssec_fwd(struct module_env* env,
|
||||
int iter_qname_indicates_dnssec(struct module_env* env,
|
||||
struct query_info *qinfo);
|
||||
|
||||
/**
|
||||
@@ -193,7 +197,7 @@ int iter_indicates_dnssec_fwd(struct module_env* env,
|
||||
* @param dp: delegation point.
|
||||
* @param msg: delegation message, with DS if a secure referral.
|
||||
* @param dclass: class of query.
|
||||
* @return 1 if dnssec is expected, 0 if not.
|
||||
* @return 1 if dnssec is expected, 0 if not or insecure point above qname.
|
||||
*/
|
||||
int iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
|
||||
struct dns_msg* msg, uint16_t dclass);
|
||||
@@ -252,7 +256,7 @@ void caps_strip_reply(struct reply_info* rep);
|
||||
int caps_failed_rcode(struct reply_info* rep);
|
||||
|
||||
/**
|
||||
* Store parent-side rrset in seperate rrset cache entries for later
|
||||
* Store parent-side rrset in separate rrset cache entries for later
|
||||
* last-resort * lookups in case the child-side versions of this information
|
||||
* fails.
|
||||
* @param env: environment with cache, time, ...
|
||||
|
||||
+445
-158
@@ -36,7 +36,7 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains a module that performs recusive iterative DNS query
|
||||
* This file contains a module that performs recursive iterative DNS query
|
||||
* processing.
|
||||
*/
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#include "validator/val_neg.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/authzone.h"
|
||||
#include "util/module.h"
|
||||
#include "util/netevent.h"
|
||||
#include "util/net_help.h"
|
||||
@@ -78,6 +79,12 @@ iter_init(struct module_env* env, int id)
|
||||
return 0;
|
||||
}
|
||||
env->modinfo[id] = (void*)iter_env;
|
||||
|
||||
lock_basic_init(&iter_env->queries_ratelimit_lock);
|
||||
lock_protect(&iter_env->queries_ratelimit_lock,
|
||||
&iter_env->num_queries_ratelimited,
|
||||
sizeof(iter_env->num_queries_ratelimited));
|
||||
|
||||
if(!iter_apply_cfg(iter_env, env->cfg)) {
|
||||
log_err("iterator: could not apply configuration settings.");
|
||||
return 0;
|
||||
@@ -103,6 +110,7 @@ iter_deinit(struct module_env* env, int id)
|
||||
if(!env || !env->modinfo[id])
|
||||
return;
|
||||
iter_env = (struct iter_env*)env->modinfo[id];
|
||||
lock_basic_destroy(&iter_env->queries_ratelimit_lock);
|
||||
free(iter_env->target_fetch_policy);
|
||||
priv_delete(iter_env->priv);
|
||||
donotq_delete(iter_env->donotq);
|
||||
@@ -288,6 +296,22 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)
|
||||
return error_response(qstate, id, rcode);
|
||||
/* if that fails (not in cache), fall through to store err */
|
||||
}
|
||||
if(qstate->env->cfg->serve_expired) {
|
||||
/* if serving expired contents, and such content is
|
||||
* already available, don't overwrite this 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, 0, 0))
|
||||
!= NULL) {
|
||||
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) */
|
||||
}
|
||||
memset(&err, 0, sizeof(err));
|
||||
err.flags = (uint16_t)(BIT_QR | BIT_RA);
|
||||
FLAGS_SET_RCODE(err.flags, rcode);
|
||||
@@ -509,6 +533,35 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** see if last resort is possible - does config allow queries to parent */
|
||||
static int
|
||||
can_have_last_resort(struct module_env* env, uint8_t* nm, size_t nmlen,
|
||||
uint16_t qclass, struct delegpt** retdp)
|
||||
{
|
||||
struct delegpt* fwddp;
|
||||
struct iter_hints_stub* stub;
|
||||
int labs = dname_count_labels(nm);
|
||||
/* do not process a last resort (the parent side) if a stub
|
||||
* or forward is configured, because we do not want to go 'above'
|
||||
* the configured servers */
|
||||
if(!dname_is_root(nm) && (stub = (struct iter_hints_stub*)
|
||||
name_tree_find(&env->hints->tree, nm, nmlen, labs, qclass)) &&
|
||||
/* has_parent side is turned off for stub_first, where we
|
||||
* are allowed to go to the parent */
|
||||
stub->dp->has_parent_side_NS) {
|
||||
if(retdp) *retdp = stub->dp;
|
||||
return 0;
|
||||
}
|
||||
if((fwddp = forwards_find(env->fwds, nm, qclass)) &&
|
||||
/* has_parent_side is turned off for forward_first, where
|
||||
* we are allowed to go to the parent */
|
||||
fwddp->has_parent_side_NS) {
|
||||
if(retdp) *retdp = fwddp;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** see if target name is caps-for-id whitelisted */
|
||||
static int
|
||||
is_caps_whitelisted(struct iter_env* ie, struct iter_qstate* iq)
|
||||
@@ -721,6 +774,11 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
||||
if(!stub)
|
||||
return 0;
|
||||
stub_dp = stub->dp;
|
||||
/* if we have an auth_zone dp, and stub is equal, don't prime stub
|
||||
* yet, unless we want to fallback and avoid the auth_zone */
|
||||
if(!iq->auth_zone_avoid && iq->dp && iq->dp->auth_dp &&
|
||||
query_dname_compare(iq->dp->name, stub_dp->name) == 0)
|
||||
return 0;
|
||||
|
||||
/* is it a noprime stub (always use) */
|
||||
if(stub->noprime) {
|
||||
@@ -781,9 +839,99 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a delegation point for an auth zone (unless cached dp is better)
|
||||
* false on alloc failure.
|
||||
*/
|
||||
static int
|
||||
auth_zone_delegpt(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
uint8_t* delname, size_t delnamelen)
|
||||
{
|
||||
struct auth_zone* z;
|
||||
if(iq->auth_zone_avoid)
|
||||
return 1;
|
||||
if(!delname) {
|
||||
delname = iq->qchase.qname;
|
||||
delnamelen = iq->qchase.qname_len;
|
||||
}
|
||||
lock_rw_rdlock(&qstate->env->auth_zones->lock);
|
||||
z = auth_zones_find_zone(qstate->env->auth_zones, delname, delnamelen,
|
||||
qstate->qinfo.qclass);
|
||||
if(!z) {
|
||||
lock_rw_unlock(&qstate->env->auth_zones->lock);
|
||||
return 1;
|
||||
}
|
||||
lock_rw_rdlock(&z->lock);
|
||||
lock_rw_unlock(&qstate->env->auth_zones->lock);
|
||||
if(z->for_upstream) {
|
||||
if(iq->dp && query_dname_compare(z->name, iq->dp->name) == 0
|
||||
&& iq->dp->auth_dp && qstate->blacklist &&
|
||||
z->fallback_enabled) {
|
||||
/* cache is blacklisted and fallback, and we
|
||||
* already have an auth_zone dp */
|
||||
if(verbosity>=VERB_ALGO) {
|
||||
char buf[255+1];
|
||||
dname_str(z->name, buf);
|
||||
verbose(VERB_ALGO, "auth_zone %s "
|
||||
"fallback because cache blacklisted",
|
||||
buf);
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
iq->dp = NULL;
|
||||
return 1;
|
||||
}
|
||||
if(iq->dp==NULL || dname_subdomain_c(z->name, iq->dp->name)) {
|
||||
struct delegpt* dp;
|
||||
if(qstate->blacklist && z->fallback_enabled) {
|
||||
/* cache is blacklisted because of a DNSSEC
|
||||
* validation failure, and the zone allows
|
||||
* fallback to the internet, query there. */
|
||||
if(verbosity>=VERB_ALGO) {
|
||||
char buf[255+1];
|
||||
dname_str(z->name, buf);
|
||||
verbose(VERB_ALGO, "auth_zone %s "
|
||||
"fallback because cache blacklisted",
|
||||
buf);
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 1;
|
||||
}
|
||||
dp = (struct delegpt*)regional_alloc_zero(
|
||||
qstate->region, sizeof(*dp));
|
||||
if(!dp) {
|
||||
log_err("alloc failure");
|
||||
if(z->fallback_enabled) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 1; /* just fallback */
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 0;
|
||||
}
|
||||
dp->name = regional_alloc_init(qstate->region,
|
||||
z->name, z->namelen);
|
||||
if(!dp->name) {
|
||||
log_err("alloc failure");
|
||||
if(z->fallback_enabled) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 1; /* just fallback */
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 0;
|
||||
}
|
||||
dp->namelen = z->namelen;
|
||||
dp->namelabs = z->namelabs;
|
||||
dp->auth_dp = 1;
|
||||
iq->dp = dp;
|
||||
}
|
||||
}
|
||||
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate A and AAAA checks for glue that is in-zone for the referral
|
||||
* we just got to obtain authoritative information on the adresses.
|
||||
* we just got to obtain authoritative information on the addresses.
|
||||
*
|
||||
* @param qstate: the qtstate that triggered the need to prime.
|
||||
* @param iq: iterator query state.
|
||||
@@ -853,6 +1001,9 @@ generate_ns_check(struct module_qstate* qstate, struct iter_qstate* iq, int id)
|
||||
|
||||
if(iq->depth == ie->max_dependency_depth)
|
||||
return;
|
||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
|
||||
iq->qchase.qclass, NULL))
|
||||
return;
|
||||
/* is this query the same as the nscheck? */
|
||||
if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS &&
|
||||
query_dname_compare(iq->dp->name, qstate->qinfo.qname)==0 &&
|
||||
@@ -861,6 +1012,9 @@ generate_ns_check(struct module_qstate* qstate, struct iter_qstate* iq, int id)
|
||||
generate_a_aaaa_check(qstate, iq, id);
|
||||
return;
|
||||
}
|
||||
/* no need to get the NS record for DS, it is above the zonecut */
|
||||
if(qstate->qinfo.qtype == LDNS_RR_TYPE_DS)
|
||||
return;
|
||||
|
||||
log_nametypeclass(VERB_ALGO, "schedule ns fetch",
|
||||
iq->dp->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
|
||||
@@ -1025,6 +1179,18 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return next_state(iq, COLLECT_CLASS_STATE);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are restricted by a forward-zone or a stub-zone, we
|
||||
* can't re-fetch glue for this delegation point.
|
||||
* we won’t try to re-fetch glue if the iq->dp is null.
|
||||
*/
|
||||
if (iq->refetch_glue &&
|
||||
iq->dp &&
|
||||
!can_have_last_resort(qstate->env, iq->dp->name,
|
||||
iq->dp->namelen, iq->qchase.qclass, NULL)) {
|
||||
iq->refetch_glue = 0;
|
||||
}
|
||||
|
||||
/* Resolver Algorithm Step 1 -- Look for the answer in local data. */
|
||||
|
||||
/* This either results in a query restart (CNAME cache response), a
|
||||
@@ -1039,14 +1205,16 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
msg = dns_cache_lookup(qstate->env, iq->qchase.qname,
|
||||
iq->qchase.qname_len, iq->qchase.qtype,
|
||||
iq->qchase.qclass, qstate->query_flags,
|
||||
qstate->region, qstate->env->scratch);
|
||||
if(!msg && qstate->env->neg_cache) {
|
||||
qstate->region, qstate->env->scratch, 0);
|
||||
if(!msg && qstate->env->neg_cache &&
|
||||
iter_qname_indicates_dnssec(qstate->env, &iq->qchase)) {
|
||||
/* lookup in negative cache; may result in
|
||||
* NOERROR/NODATA or NXDOMAIN answers that need validation */
|
||||
msg = val_neg_getmsg(qstate->env->neg_cache, &iq->qchase,
|
||||
qstate->region, qstate->env->rrset_cache,
|
||||
qstate->env->scratch_buffer,
|
||||
*qstate->env->now, 1/*add SOA*/, NULL);
|
||||
*qstate->env->now, 1/*add SOA*/, NULL,
|
||||
qstate->env->cfg);
|
||||
}
|
||||
/* item taken from cache does not match our query name, thus
|
||||
* security needs to be re-examined later */
|
||||
@@ -1097,7 +1265,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->response = msg;
|
||||
return final_state(iq);
|
||||
}
|
||||
|
||||
|
||||
/* attempt to forward the request */
|
||||
if(forward_request(qstate, iq))
|
||||
{
|
||||
@@ -1131,7 +1299,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
delnamelen = iq->qchase.qname_len;
|
||||
}
|
||||
if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue ||
|
||||
(iq->qchase.qtype == LDNS_RR_TYPE_NS && qstate->prefetch_leeway)) {
|
||||
(iq->qchase.qtype == LDNS_RR_TYPE_NS && qstate->prefetch_leeway
|
||||
&& can_have_last_resort(qstate->env, delname, delnamelen, iq->qchase.qclass, NULL))) {
|
||||
/* remove first label from delname, root goes to hints,
|
||||
* but only to fetch glue, not for qtype=DS. */
|
||||
/* also when prefetching an NS record, fetch it again from
|
||||
@@ -1158,8 +1327,15 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* If the cache has returned nothing, then we have a
|
||||
* root priming situation. */
|
||||
if(iq->dp == NULL) {
|
||||
int r;
|
||||
/* if under auth zone, no prime needed */
|
||||
if(!auth_zone_delegpt(qstate, iq, delname, delnamelen))
|
||||
return error_response(qstate, id,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
if(iq->dp) /* use auth zone dp */
|
||||
return next_state(iq, INIT_REQUEST_2_STATE);
|
||||
/* if there is a stub, then no root prime needed */
|
||||
int r = prime_stub(qstate, iq, id, delname,
|
||||
r = prime_stub(qstate, iq, id, delname,
|
||||
iq->qchase.qclass);
|
||||
if(r == 2)
|
||||
break; /* got noprime-stub-zone, continue */
|
||||
@@ -1216,6 +1392,9 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
"delegation point", iq->dp->name,
|
||||
LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN);
|
||||
} else {
|
||||
lock_basic_lock(&ie->queries_ratelimit_lock);
|
||||
ie->num_queries_ratelimited++;
|
||||
lock_basic_unlock(&ie->queries_ratelimit_lock);
|
||||
log_nametypeclass(VERB_ALGO, "ratelimit exceeded with "
|
||||
"delegation point", iq->dp->name,
|
||||
LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN);
|
||||
@@ -1237,6 +1416,28 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
*/
|
||||
if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
|
||||
iq->dp)) {
|
||||
struct delegpt* retdp = NULL;
|
||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &retdp)) {
|
||||
if(retdp) {
|
||||
verbose(VERB_QUERY, "cache has stub "
|
||||
"or fwd but no addresses, "
|
||||
"fallback to config");
|
||||
iq->dp = delegpt_copy(retdp,
|
||||
qstate->region);
|
||||
if(!iq->dp) {
|
||||
log_err("out of memory in "
|
||||
"stub/fwd fallback");
|
||||
return error_response(qstate,
|
||||
id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
verbose(VERB_ALGO, "useless dp "
|
||||
"but cannot go up, servfail");
|
||||
delegpt_log(VERB_ALGO, iq->dp);
|
||||
return error_response(qstate, id,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(dname_is_root(iq->dp->name)) {
|
||||
/* use safety belt */
|
||||
verbose(VERB_QUERY, "Cache has root NS but "
|
||||
@@ -1283,7 +1484,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* the same init processing as ones that do not. Request events that reach
|
||||
* this state must have a valid currentDelegationPoint set.
|
||||
*
|
||||
* This part is primarly handling stub zone priming. Events that reach this
|
||||
* This part is primarily handling stub zone priming. Events that reach this
|
||||
* state must have a current delegation point.
|
||||
*
|
||||
* @param qstate: query state.
|
||||
@@ -1301,22 +1502,36 @@ processInitRequest2(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
log_query_info(VERB_QUERY, "resolving (init part 2): ",
|
||||
&qstate->qinfo);
|
||||
|
||||
delname = iq->qchase.qname;
|
||||
delnamelen = iq->qchase.qname_len;
|
||||
if(iq->refetch_glue) {
|
||||
struct iter_hints_stub* stub;
|
||||
if(!iq->dp) {
|
||||
log_err("internal or malloc fail: no dp for refetch");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
delname = iq->dp->name;
|
||||
delnamelen = iq->dp->namelen;
|
||||
} else {
|
||||
delname = iq->qchase.qname;
|
||||
delnamelen = iq->qchase.qname_len;
|
||||
/* Do not send queries above stub, do not set delname to dp if
|
||||
* this is above stub without stub-first. */
|
||||
stub = hints_lookup_stub(
|
||||
qstate->env->hints, iq->qchase.qname, iq->qchase.qclass,
|
||||
iq->dp);
|
||||
if(!stub || !stub->dp->has_parent_side_NS ||
|
||||
dname_subdomain_c(iq->dp->name, stub->dp->name)) {
|
||||
delname = iq->dp->name;
|
||||
delnamelen = iq->dp->namelen;
|
||||
}
|
||||
}
|
||||
if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue) {
|
||||
if(!dname_is_root(delname))
|
||||
dname_remove_label(&delname, &delnamelen);
|
||||
iq->refetch_glue = 0; /* if CNAME causes restart, no refetch */
|
||||
}
|
||||
|
||||
/* see if we have an auth zone to answer from, improves dp from cache
|
||||
* (if any dp from cache) with auth zone dp, if that is lower */
|
||||
if(!auth_zone_delegpt(qstate, iq, delname, delnamelen))
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
|
||||
/* Check to see if we need to prime a stub zone. */
|
||||
if(prime_stub(qstate, iq, id, delname, iq->qchase.qclass)) {
|
||||
/* A priming sub request was made */
|
||||
@@ -1558,35 +1773,6 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** see if last resort is possible - does config allow queries to parent */
|
||||
static int
|
||||
can_have_last_resort(struct module_env* env, struct delegpt* dp,
|
||||
struct iter_qstate* iq)
|
||||
{
|
||||
struct delegpt* fwddp;
|
||||
struct iter_hints_stub* stub;
|
||||
/* do not process a last resort (the parent side) if a stub
|
||||
* or forward is configured, because we do not want to go 'above'
|
||||
* the configured servers */
|
||||
if(!dname_is_root(dp->name) && (stub = (struct iter_hints_stub*)
|
||||
name_tree_find(&env->hints->tree, dp->name, dp->namelen,
|
||||
dp->namelabs, iq->qchase.qclass)) &&
|
||||
/* has_parent side is turned off for stub_first, where we
|
||||
* are allowed to go to the parent */
|
||||
stub->dp->has_parent_side_NS) {
|
||||
verbose(VERB_QUERY, "configured stub servers failed -- returning SERVFAIL");
|
||||
return 0;
|
||||
}
|
||||
if((fwddp = forwards_find(env->fwds, dp->name, iq->qchase.qclass)) &&
|
||||
/* has_parent_side is turned off for forward_first, where
|
||||
* we are allowed to go to the parent */
|
||||
fwddp->has_parent_side_NS) {
|
||||
verbose(VERB_QUERY, "configured forward servers failed -- returning SERVFAIL");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by processQueryTargets when it would like extra targets to query
|
||||
* but it seems to be out of options. At last resort some less appealing
|
||||
@@ -1608,9 +1794,11 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
verbose(VERB_ALGO, "No more query targets, attempting last resort");
|
||||
log_assert(iq->dp);
|
||||
|
||||
if(!can_have_last_resort(qstate->env, iq->dp, iq)) {
|
||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
|
||||
iq->qchase.qclass, NULL)) {
|
||||
/* fail -- no more targets, no more hope of targets, no hope
|
||||
* of a response. */
|
||||
verbose(VERB_QUERY, "configured stub or forward servers failed -- returning SERVFAIL");
|
||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(!iq->dp->has_parent_side_NS && dname_is_root(iq->dp->name)) {
|
||||
@@ -1627,7 +1815,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
for(a = p->target_list; a; a=a->next_target) {
|
||||
(void)delegpt_add_addr(iq->dp, qstate->region,
|
||||
&a->addr, a->addrlen, a->bogus,
|
||||
a->lame);
|
||||
a->lame, a->tls_auth_name);
|
||||
}
|
||||
}
|
||||
iq->dp->has_parent_side_NS = 1;
|
||||
@@ -1695,6 +1883,19 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* see if we can issue queries to get nameserver addresses */
|
||||
/* this lookup is not randomized, but sequential. */
|
||||
for(ns = iq->dp->nslist; ns; ns = ns->next) {
|
||||
/* if this nameserver is at a delegation point, but that
|
||||
* delegation point is a stub and we cannot go higher, skip*/
|
||||
if( ((ie->supports_ipv6 && !ns->done_pside6) ||
|
||||
(ie->supports_ipv4 && !ns->done_pside4)) &&
|
||||
!can_have_last_resort(qstate->env, ns->name, ns->namelen,
|
||||
iq->qchase.qclass, NULL)) {
|
||||
log_nametypeclass(VERB_ALGO, "cannot pside lookup ns "
|
||||
"because it is also a stub/forward,",
|
||||
ns->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
|
||||
if(ie->supports_ipv6) ns->done_pside6 = 1;
|
||||
if(ie->supports_ipv4) ns->done_pside4 = 1;
|
||||
continue;
|
||||
}
|
||||
/* query for parent-side A and AAAA for nameservers */
|
||||
if(ie->supports_ipv6 && !ns->done_pside6) {
|
||||
/* Send the AAAA request. */
|
||||
@@ -1815,6 +2016,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
int tf_policy;
|
||||
struct delegpt_addr* target;
|
||||
struct outbound_entry* outq;
|
||||
int auth_fallback = 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,
|
||||
@@ -1859,6 +2061,159 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(iq->minimisation_state == INIT_MINIMISE_STATE) {
|
||||
/* (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
|
||||
* than MAX_MINIMISE_COUNT labels). */
|
||||
if(!(iq->qinfo_out.qname_len
|
||||
&& dname_subdomain_c(iq->qchase.qname,
|
||||
iq->qinfo_out.qname)
|
||||
&& dname_subdomain_c(iq->qinfo_out.qname,
|
||||
iq->dp->name))) {
|
||||
iq->qinfo_out.qname = iq->dp->name;
|
||||
iq->qinfo_out.qname_len = iq->dp->namelen;
|
||||
iq->qinfo_out.qtype = LDNS_RR_TYPE_A;
|
||||
iq->qinfo_out.qclass = iq->qchase.qclass;
|
||||
iq->qinfo_out.local_alias = NULL;
|
||||
iq->minimise_count = 0;
|
||||
}
|
||||
|
||||
iq->minimisation_state = MINIMISE_STATE;
|
||||
}
|
||||
if(iq->minimisation_state == MINIMISE_STATE) {
|
||||
int qchaselabs = dname_count_labels(iq->qchase.qname);
|
||||
int labdiff = qchaselabs -
|
||||
dname_count_labels(iq->qinfo_out.qname);
|
||||
|
||||
iq->qinfo_out.qname = iq->qchase.qname;
|
||||
iq->qinfo_out.qname_len = iq->qchase.qname_len;
|
||||
iq->minimise_count++;
|
||||
iq->minimise_timeout_count = 0;
|
||||
|
||||
iter_dec_attempts(iq->dp, 1);
|
||||
|
||||
/* Limit number of iterations for QNAMEs with more
|
||||
* than MAX_MINIMISE_COUNT labels. Send first MINIMISE_ONE_LAB
|
||||
* labels of QNAME always individually.
|
||||
*/
|
||||
if(qchaselabs > MAX_MINIMISE_COUNT && labdiff > 1 &&
|
||||
iq->minimise_count > MINIMISE_ONE_LAB) {
|
||||
if(iq->minimise_count < MAX_MINIMISE_COUNT) {
|
||||
int multilabs = qchaselabs - 1 -
|
||||
MINIMISE_ONE_LAB;
|
||||
int extralabs = multilabs /
|
||||
MINIMISE_MULTIPLE_LABS;
|
||||
|
||||
if (MAX_MINIMISE_COUNT - iq->minimise_count >=
|
||||
multilabs % MINIMISE_MULTIPLE_LABS)
|
||||
/* Default behaviour is to add 1 label
|
||||
* every iteration. Therefore, decrement
|
||||
* the extralabs by 1 */
|
||||
extralabs--;
|
||||
if (extralabs < labdiff)
|
||||
labdiff -= extralabs;
|
||||
else
|
||||
labdiff = 1;
|
||||
}
|
||||
/* Last minimised iteration, send all labels with
|
||||
* QTYPE=NS */
|
||||
else
|
||||
labdiff = 1;
|
||||
}
|
||||
|
||||
if(labdiff > 1) {
|
||||
verbose(VERB_QUERY, "removing %d labels", labdiff-1);
|
||||
dname_remove_labels(&iq->qinfo_out.qname,
|
||||
&iq->qinfo_out.qname_len,
|
||||
labdiff-1);
|
||||
}
|
||||
if(labdiff < 1 || (labdiff < 2
|
||||
&& (iq->qchase.qtype == LDNS_RR_TYPE_DS
|
||||
|| iq->qchase.qtype == LDNS_RR_TYPE_A)))
|
||||
/* Stop minimising this query, resolve "as usual" */
|
||||
iq->minimisation_state = DONOT_MINIMISE_STATE;
|
||||
else if(!qstate->no_cache_lookup) {
|
||||
struct dns_msg* msg = dns_cache_lookup(qstate->env,
|
||||
iq->qinfo_out.qname, iq->qinfo_out.qname_len,
|
||||
iq->qinfo_out.qtype, iq->qinfo_out.qclass,
|
||||
qstate->query_flags, qstate->region,
|
||||
qstate->env->scratch, 0);
|
||||
if(msg && msg->rep->an_numrrsets == 0
|
||||
&& FLAGS_GET_RCODE(msg->rep->flags) ==
|
||||
LDNS_RCODE_NOERROR)
|
||||
/* no need to send query if it is already
|
||||
* cached as NOERROR/NODATA */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(iq->minimisation_state == SKIP_MINIMISE_STATE) {
|
||||
if(iq->minimise_timeout_count < MAX_MINIMISE_TIMEOUT_COUNT)
|
||||
/* Do not increment qname, continue incrementing next
|
||||
* iteration */
|
||||
iq->minimisation_state = MINIMISE_STATE;
|
||||
else if(!qstate->env->cfg->qname_minimisation_strict)
|
||||
/* Too many time-outs detected for this QNAME and QTYPE.
|
||||
* We give up, disable QNAME minimisation. */
|
||||
iq->minimisation_state = DONOT_MINIMISE_STATE;
|
||||
}
|
||||
if(iq->minimisation_state == DONOT_MINIMISE_STATE)
|
||||
iq->qinfo_out = iq->qchase;
|
||||
|
||||
/* now find an answer to this query */
|
||||
/* see if authority zones have an answer */
|
||||
/* now we know the dp, we can check the auth zone for locally hosted
|
||||
* contents */
|
||||
if(!iq->auth_zone_avoid && qstate->blacklist) {
|
||||
if(auth_zones_can_fallback(qstate->env->auth_zones,
|
||||
iq->dp->name, iq->dp->namelen, iq->qinfo_out.qclass)) {
|
||||
/* if cache is blacklisted and this zone allows us
|
||||
* to fallback to the internet, then do so, and
|
||||
* fetch results from the internet servers */
|
||||
iq->auth_zone_avoid = 1;
|
||||
}
|
||||
}
|
||||
if(iq->auth_zone_avoid) {
|
||||
iq->auth_zone_avoid = 0;
|
||||
auth_fallback = 1;
|
||||
} else if(auth_zones_lookup(qstate->env->auth_zones, &iq->qinfo_out,
|
||||
qstate->region, &iq->response, &auth_fallback, iq->dp->name,
|
||||
iq->dp->namelen)) {
|
||||
/* use this as a response to be processed by the iterator */
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
log_dns_msg("msg from auth zone",
|
||||
&iq->response->qinfo, iq->response->rep);
|
||||
}
|
||||
if((iq->chase_flags&BIT_RD) && !(iq->response->rep->flags&BIT_AA)) {
|
||||
verbose(VERB_ALGO, "forwarder, ignoring referral from auth zone");
|
||||
} else {
|
||||
lock_rw_wrlock(&qstate->env->auth_zones->lock);
|
||||
qstate->env->auth_zones->num_query_up++;
|
||||
lock_rw_unlock(&qstate->env->auth_zones->lock);
|
||||
iq->num_current_queries++;
|
||||
iq->chase_to_rd = 0;
|
||||
iq->dnssec_lame_query = 0;
|
||||
iq->auth_zone_response = 1;
|
||||
return next_state(iq, QUERY_RESP_STATE);
|
||||
}
|
||||
}
|
||||
iq->auth_zone_response = 0;
|
||||
if(auth_fallback == 0) {
|
||||
/* like we got servfail from the auth zone lookup, and
|
||||
* no internet fallback */
|
||||
verbose(VERB_ALGO, "auth zone lookup failed, no fallback,"
|
||||
" servfail");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(iq->dp && 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;
|
||||
return next_state(iq, INIT_REQUEST_STATE);
|
||||
}
|
||||
/* but mostly, fallback==1 (like, when no such auth zone exists)
|
||||
* and we continue with lookups */
|
||||
|
||||
tf_policy = 0;
|
||||
/* < not <=, because although the array is large enough for <=, the
|
||||
* generated query will immediately be discarded due to depth and
|
||||
@@ -1929,7 +2284,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
target = iter_server_selection(ie, qstate->env, iq->dp,
|
||||
iq->dp->name, iq->dp->namelen, iq->qchase.qtype,
|
||||
&iq->dnssec_lame_query, &iq->chase_to_rd,
|
||||
iq->num_target_queries, qstate->blacklist);
|
||||
iq->num_target_queries, qstate->blacklist,
|
||||
qstate->prefetch_leeway);
|
||||
|
||||
/* If no usable target was selected... */
|
||||
if(!target) {
|
||||
@@ -2018,111 +2374,14 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
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)) {
|
||||
lock_basic_lock(&ie->queries_ratelimit_lock);
|
||||
ie->num_queries_ratelimited++;
|
||||
lock_basic_unlock(&ie->queries_ratelimit_lock);
|
||||
verbose(VERB_ALGO, "query exceeded ratelimits");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
}
|
||||
|
||||
if(iq->minimisation_state == INIT_MINIMISE_STATE) {
|
||||
/* (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
|
||||
* than MAX_MINIMISE_COUNT labels). */
|
||||
if(!(iq->qinfo_out.qname_len
|
||||
&& dname_subdomain_c(iq->qchase.qname,
|
||||
iq->qinfo_out.qname)
|
||||
&& dname_subdomain_c(iq->qinfo_out.qname,
|
||||
iq->dp->name))) {
|
||||
iq->qinfo_out.qname = iq->dp->name;
|
||||
iq->qinfo_out.qname_len = iq->dp->namelen;
|
||||
iq->qinfo_out.qtype = LDNS_RR_TYPE_A;
|
||||
iq->qinfo_out.qclass = iq->qchase.qclass;
|
||||
iq->qinfo_out.local_alias = NULL;
|
||||
iq->minimise_count = 0;
|
||||
}
|
||||
|
||||
iq->minimisation_state = MINIMISE_STATE;
|
||||
}
|
||||
if(iq->minimisation_state == MINIMISE_STATE) {
|
||||
int qchaselabs = dname_count_labels(iq->qchase.qname);
|
||||
int labdiff = qchaselabs -
|
||||
dname_count_labels(iq->qinfo_out.qname);
|
||||
|
||||
iq->qinfo_out.qname = iq->qchase.qname;
|
||||
iq->qinfo_out.qname_len = iq->qchase.qname_len;
|
||||
iq->minimise_count++;
|
||||
iq->minimise_timeout_count = 0;
|
||||
|
||||
iter_dec_attempts(iq->dp, 1);
|
||||
|
||||
/* Limit number of iterations for QNAMEs with more
|
||||
* than MAX_MINIMISE_COUNT labels. Send first MINIMISE_ONE_LAB
|
||||
* labels of QNAME always individually.
|
||||
*/
|
||||
if(qchaselabs > MAX_MINIMISE_COUNT && labdiff > 1 &&
|
||||
iq->minimise_count > MINIMISE_ONE_LAB) {
|
||||
if(iq->minimise_count < MAX_MINIMISE_COUNT) {
|
||||
int multilabs = qchaselabs - 1 -
|
||||
MINIMISE_ONE_LAB;
|
||||
int extralabs = multilabs /
|
||||
MINIMISE_MULTIPLE_LABS;
|
||||
|
||||
if (MAX_MINIMISE_COUNT - iq->minimise_count >=
|
||||
multilabs % MINIMISE_MULTIPLE_LABS)
|
||||
/* Default behaviour is to add 1 label
|
||||
* every iteration. Therefore, decrement
|
||||
* the extralabs by 1 */
|
||||
extralabs--;
|
||||
if (extralabs < labdiff)
|
||||
labdiff -= extralabs;
|
||||
else
|
||||
labdiff = 1;
|
||||
}
|
||||
/* Last minimised iteration, send all labels with
|
||||
* QTYPE=NS */
|
||||
else
|
||||
labdiff = 1;
|
||||
}
|
||||
|
||||
if(labdiff > 1) {
|
||||
verbose(VERB_QUERY, "removing %d labels", labdiff-1);
|
||||
dname_remove_labels(&iq->qinfo_out.qname,
|
||||
&iq->qinfo_out.qname_len,
|
||||
labdiff-1);
|
||||
}
|
||||
if(labdiff < 1 || (labdiff < 2
|
||||
&& (iq->qchase.qtype == LDNS_RR_TYPE_DS
|
||||
|| iq->qchase.qtype == LDNS_RR_TYPE_A)))
|
||||
/* Stop minimising this query, resolve "as usual" */
|
||||
iq->minimisation_state = DONOT_MINIMISE_STATE;
|
||||
else if(!qstate->no_cache_lookup) {
|
||||
struct dns_msg* msg = dns_cache_lookup(qstate->env,
|
||||
iq->qinfo_out.qname, iq->qinfo_out.qname_len,
|
||||
iq->qinfo_out.qtype, iq->qinfo_out.qclass,
|
||||
qstate->query_flags, qstate->region,
|
||||
qstate->env->scratch);
|
||||
if(msg && msg->rep->an_numrrsets == 0
|
||||
&& FLAGS_GET_RCODE(msg->rep->flags) ==
|
||||
LDNS_RCODE_NOERROR)
|
||||
/* no need to send query if it is already
|
||||
* cached as NOERROR/NODATA */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(iq->minimisation_state == SKIP_MINIMISE_STATE) {
|
||||
iq->minimise_timeout_count++;
|
||||
if(iq->minimise_timeout_count < MAX_MINIMISE_TIMEOUT_COUNT)
|
||||
/* Do not increment qname, continue incrementing next
|
||||
* iteration */
|
||||
iq->minimisation_state = MINIMISE_STATE;
|
||||
else if(!qstate->env->cfg->qname_minimisation_strict)
|
||||
/* Too many time-outs detected for this QNAME and QTYPE.
|
||||
* We give up, disable QNAME minimisation. */
|
||||
iq->minimisation_state = DONOT_MINIMISE_STATE;
|
||||
}
|
||||
if(iq->minimisation_state == DONOT_MINIMISE_STATE)
|
||||
iq->qinfo_out = iq->qchase;
|
||||
|
||||
/* We have a valid target. */
|
||||
if(verbosity >= VERB_QUERY) {
|
||||
log_query_info(VERB_QUERY, "sending query:", &iq->qinfo_out);
|
||||
@@ -2139,18 +2398,21 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* (blacklist nonempty) and no trust-anchors are configured
|
||||
* above the qname or on the first attempt when dnssec is on */
|
||||
EDNS_DO| ((iq->chase_to_rd||(iq->chase_flags&BIT_RD)!=0)&&
|
||||
!qstate->blacklist&&(!iter_indicates_dnssec_fwd(qstate->env,
|
||||
!qstate->blacklist&&(!iter_qname_indicates_dnssec(qstate->env,
|
||||
&iq->qinfo_out)||target->attempts==1)?0:BIT_CD),
|
||||
iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted(
|
||||
ie, iq), &target->addr, target->addrlen,
|
||||
iq->dp->name, iq->dp->namelen,
|
||||
(iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream), qstate);
|
||||
(iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream),
|
||||
target->tls_auth_name, qstate);
|
||||
if(!outq) {
|
||||
log_addr(VERB_DETAIL, "error sending query to auth server",
|
||||
&target->addr, target->addrlen);
|
||||
if(!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok)
|
||||
infra_ratelimit_dec(qstate->env->infra_cache, iq->dp->name,
|
||||
iq->dp->namelen, *qstate->env->now);
|
||||
if(qstate->env->cfg->qname_minimisation)
|
||||
iq->minimisation_state = SKIP_MINIMISE_STATE;
|
||||
return next_state(iq, QUERYTARGETS_STATE);
|
||||
}
|
||||
outbound_list_insert(&iq->outlist, outq);
|
||||
@@ -2200,8 +2462,10 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
|
||||
if(iq->response == NULL) {
|
||||
/* Don't increment qname when QNAME minimisation is enabled */
|
||||
if(qstate->env->cfg->qname_minimisation)
|
||||
if(qstate->env->cfg->qname_minimisation) {
|
||||
iq->minimise_timeout_count++;
|
||||
iq->minimisation_state = SKIP_MINIMISE_STATE;
|
||||
}
|
||||
iq->chase_to_rd = 0;
|
||||
iq->dnssec_lame_query = 0;
|
||||
verbose(VERB_ALGO, "query response was timeout");
|
||||
@@ -2209,9 +2473,10 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
type = response_type_from_server(
|
||||
(int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd),
|
||||
iq->response, &iq->qchase, iq->dp);
|
||||
iq->response, &iq->qinfo_out, iq->dp);
|
||||
iq->chase_to_rd = 0;
|
||||
if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD)) {
|
||||
if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD) &&
|
||||
!iq->auth_zone_response) {
|
||||
/* When forwarding (RD bit is set), we handle referrals
|
||||
* differently. No queries should be sent elsewhere */
|
||||
type = RESPONSE_TYPE_ANSWER;
|
||||
@@ -2334,7 +2599,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if(FLAGS_GET_RCODE(iq->response->rep->flags) ==
|
||||
LDNS_RCODE_NXDOMAIN) {
|
||||
/* Stop resolving when NXDOMAIN is DNSSEC
|
||||
* signed. Based on assumption that namservers
|
||||
* signed. Based on assumption that nameservers
|
||||
* serving signed zones do not return NXDOMAIN
|
||||
* for empty-non-terminals. */
|
||||
if(iq->dnssec_expected)
|
||||
@@ -2505,15 +2770,18 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* set the current request's qname to the new value. */
|
||||
iq->qchase.qname = sname;
|
||||
iq->qchase.qname_len = snamelen;
|
||||
if (qstate->env->cfg->qname_minimisation)
|
||||
iq->minimisation_state = INIT_MINIMISE_STATE;
|
||||
/* Clear the query state, since this is a query restart. */
|
||||
iq->deleg_msg = NULL;
|
||||
iq->dp = NULL;
|
||||
iq->dsns_point = NULL;
|
||||
/* Note the query restart. */
|
||||
iq->query_restart_count++;
|
||||
iq->auth_zone_response = 0;
|
||||
iq->sent_count = 0;
|
||||
if(iq->minimisation_state != MINIMISE_STATE)
|
||||
/* Only count as query restart when it is not an extra
|
||||
* query as result of qname minimisation. */
|
||||
iq->query_restart_count++;
|
||||
if(qstate->env->cfg->qname_minimisation)
|
||||
iq->minimisation_state = INIT_MINIMISE_STATE;
|
||||
|
||||
/* stop current outstanding queries.
|
||||
* FIXME: should the outstanding queries be waited for and
|
||||
@@ -2583,6 +2851,25 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if (qstate->env->cfg->qname_minimisation &&
|
||||
!qstate->env->cfg->qname_minimisation_strict)
|
||||
iq->minimisation_state = DONOT_MINIMISE_STATE;
|
||||
if(iq->auth_zone_response) {
|
||||
/* can we fallback? */
|
||||
iq->auth_zone_response = 0;
|
||||
if(!auth_zones_can_fallback(qstate->env->auth_zones,
|
||||
iq->dp->name, iq->dp->namelen, qstate->qinfo.qclass)) {
|
||||
verbose(VERB_ALGO, "auth zone response bad, and no"
|
||||
" fallback possible, servfail");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
verbose(VERB_ALGO, "auth zone response was bad, "
|
||||
"fallback enabled");
|
||||
iq->auth_zone_avoid = 1;
|
||||
if(iq->dp->auth_dp) {
|
||||
/* we are using a dp for the auth zone, with no
|
||||
* nameservers, get one first */
|
||||
iq->dp = NULL;
|
||||
return next_state(iq, INIT_REQUEST_STATE);
|
||||
}
|
||||
}
|
||||
return next_state(iq, QUERYTARGETS_STATE);
|
||||
}
|
||||
|
||||
@@ -2691,7 +2978,7 @@ processPrimeResponse(struct module_qstate* qstate, int id)
|
||||
/**
|
||||
* Do final processing on responses to target queries. Events reach this
|
||||
* state after the iterative resolution algorithm terminates. This state is
|
||||
* responsible for reactiving the original event, and housekeeping related
|
||||
* responsible for reactivating the original event, and housekeeping related
|
||||
* to received target responses (caching, updating the current delegation
|
||||
* point, etc).
|
||||
* Callback from walk_supers for every super state that is interested in
|
||||
@@ -3034,7 +3321,7 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
|
||||
/*
|
||||
* Return priming query results to interestes super querystates.
|
||||
* Return priming query results to interested super querystates.
|
||||
*
|
||||
* Sets the delegation point and delegation message (not nonRD queries).
|
||||
* This is a callback from walk_supers.
|
||||
|
||||
+16
-9
@@ -36,7 +36,7 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains a module that performs recusive iterative DNS query
|
||||
* This file contains a module that performs recursive iterative DNS query
|
||||
* processing.
|
||||
*/
|
||||
|
||||
@@ -62,7 +62,7 @@ struct rbtree_type;
|
||||
/** max number of queries-sent-out. Make sure large NS set does not loop */
|
||||
#define MAX_SENT_COUNT 32
|
||||
/** max number of queries for which to perform dnsseclameness detection,
|
||||
* (rrsigs misssing detection) after that, just pick up that response */
|
||||
* (rrsigs missing detection) after that, just pick up that response */
|
||||
#define DNSSEC_LAME_DETECT_COUNT 4
|
||||
/**
|
||||
* max number of QNAME minimisation iterations. Limits number of queries for
|
||||
@@ -130,8 +130,10 @@ struct iter_env {
|
||||
*/
|
||||
int* target_fetch_policy;
|
||||
|
||||
/** ip6.arpa dname in wireformat, used for qname-minimisation */
|
||||
uint8_t* ip6arpa_dname;
|
||||
/** lock on ratelimit counter */
|
||||
lock_basic_type queries_ratelimit_lock;
|
||||
/** number of queries that have been ratelimited */
|
||||
size_t num_queries_ratelimited;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -140,11 +142,11 @@ struct iter_env {
|
||||
enum minimisation_state {
|
||||
/**
|
||||
* (Re)start minimisation. Outgoing QNAME should be set to dp->name.
|
||||
* State entered on new query or after following refferal or CNAME.
|
||||
* State entered on new query or after following referral or CNAME.
|
||||
*/
|
||||
INIT_MINIMISE_STATE = 0,
|
||||
/**
|
||||
* QNAME minimisataion ongoing. Increase QNAME on every iteration.
|
||||
* QNAME minimisation ongoing. Increase QNAME on every iteration.
|
||||
*/
|
||||
MINIMISE_STATE,
|
||||
/**
|
||||
@@ -182,7 +184,7 @@ enum iter_state {
|
||||
/**
|
||||
* Each time a delegation point changes for a given query or a
|
||||
* query times out and/or wakes up, this state is (re)visited.
|
||||
* This state is reponsible for iterating through a list of
|
||||
* This state is responsible for iterating through a list of
|
||||
* nameserver targets.
|
||||
*/
|
||||
QUERYTARGETS_STATE,
|
||||
@@ -376,7 +378,7 @@ struct iter_qstate {
|
||||
struct query_info qinfo_out;
|
||||
|
||||
/**
|
||||
* Count number of QNAME minisation iterations. Used to limit number of
|
||||
* Count number of QNAME minimisation iterations. Used to limit number of
|
||||
* outgoing queries when QNAME minimisation is enabled.
|
||||
*/
|
||||
int minimise_count;
|
||||
@@ -385,6 +387,11 @@ struct iter_qstate {
|
||||
* Count number of time-outs. Used to prevent resolving failures when
|
||||
* the QNAME minimisation QTYPE is blocked. */
|
||||
int minimise_timeout_count;
|
||||
|
||||
/** True if the current response is from auth_zone */
|
||||
int auth_zone_response;
|
||||
/** True if the auth_zones should not be consulted for the query */
|
||||
int auth_zone_avoid;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -428,7 +435,7 @@ void iter_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
struct outbound_entry* outbound);
|
||||
|
||||
/**
|
||||
* Return priming query results to interestes super querystates.
|
||||
* Return priming query results to interested super querystates.
|
||||
*
|
||||
* Sets the delegation point and delegation message (not nonRD queries).
|
||||
* This is a callback from walk_supers.
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "services/localzone.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/authzone.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
@@ -68,6 +69,8 @@ context_finalize(struct ub_ctx* ctx)
|
||||
return UB_NOMEM;
|
||||
if(!local_zones_apply_cfg(ctx->local_zones, cfg))
|
||||
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) {
|
||||
@@ -127,7 +130,7 @@ find_id(struct ub_ctx* ctx, int* id)
|
||||
|
||||
struct ctx_query*
|
||||
context_new(struct ub_ctx* ctx, const char* name, int rrtype, int rrclass,
|
||||
ub_callback_type cb, void* cbarg)
|
||||
ub_callback_type cb, ub_event_callback_type cb_event, void* cbarg)
|
||||
{
|
||||
struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q));
|
||||
if(!q) return NULL;
|
||||
@@ -139,8 +142,9 @@ context_new(struct ub_ctx* ctx, const char* name, int rrtype, int rrclass,
|
||||
}
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
q->node.key = &q->querynum;
|
||||
q->async = (cb != NULL);
|
||||
q->async = (cb != NULL || cb_event != NULL);
|
||||
q->cb = cb;
|
||||
q->cb_event = cb_event;
|
||||
q->cb_arg = cbarg;
|
||||
q->res = (struct ub_result*)calloc(1, sizeof(*q->res));
|
||||
if(!q->res) {
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "util/rbtree.h"
|
||||
#include "services/modstack.h"
|
||||
#include "libunbound/unbound.h"
|
||||
#include "libunbound/unbound-event.h"
|
||||
#include "util/data/packed_rrset.h"
|
||||
struct libworker;
|
||||
struct tube;
|
||||
@@ -90,7 +91,7 @@ struct ub_ctx {
|
||||
int dothread;
|
||||
/** next thread number for new threads */
|
||||
int thr_next_num;
|
||||
/** if logfile is overriden */
|
||||
/** if logfile is overridden */
|
||||
int logfile_override;
|
||||
/** what logfile to use instead */
|
||||
FILE* log_out;
|
||||
@@ -148,8 +149,10 @@ struct ctx_query {
|
||||
/** was this query cancelled (for bg worker) */
|
||||
int cancelled;
|
||||
|
||||
/** for async query, the callback function */
|
||||
/** for async query, the callback function of type ub_callback_type */
|
||||
ub_callback_type cb;
|
||||
/** for event callbacks the type is ub_event_callback_type */
|
||||
ub_event_callback_type cb_event;
|
||||
/** for async query, the callback user arg */
|
||||
void* cb_arg;
|
||||
|
||||
@@ -238,11 +241,13 @@ void context_query_delete(struct ctx_query* q);
|
||||
* @param rrtype: type
|
||||
* @param rrclass: class
|
||||
* @param cb: callback for async, or NULL for sync.
|
||||
* @param cb_event: event callback for async, or NULL for sync.
|
||||
* @param cbarg: user arg for async queries.
|
||||
* @return new ctx_query or NULL for malloc failure.
|
||||
*/
|
||||
struct ctx_query* context_new(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
int rrclass, ub_callback_type cb, void* cbarg);
|
||||
int rrclass, ub_callback_type cb, ub_event_callback_type cb_event,
|
||||
void* cbarg);
|
||||
|
||||
/**
|
||||
* Get a new alloc. Creates a new one or uses a cached one.
|
||||
|
||||
+17
-5
@@ -37,7 +37,7 @@
|
||||
* \file
|
||||
*
|
||||
* This file contains functions to resolve DNS queries and
|
||||
* validate the answers. Synchonously and asynchronously.
|
||||
* validate the answers. Synchronously and asynchronously.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
#include "services/localzone.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/authzone.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#ifdef HAVE_PTHREAD
|
||||
#include <signal.h>
|
||||
@@ -88,6 +89,7 @@ static struct ub_ctx* ub_ctx_create_nopipe(void)
|
||||
WSADATA wsa_data;
|
||||
#endif
|
||||
|
||||
checklock_start();
|
||||
log_init(NULL, 0, NULL); /* logs to stderr */
|
||||
log_ident_set("libunbound");
|
||||
#ifdef USE_WINSOCK
|
||||
@@ -141,6 +143,16 @@ static struct ub_ctx* ub_ctx_create_nopipe(void)
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
ctx->env->auth_zones = auth_zones_create();
|
||||
if(!ctx->env->auth_zones) {
|
||||
edns_known_options_delete(ctx->env);
|
||||
config_delete(ctx->env->cfg);
|
||||
free(ctx->env);
|
||||
ub_randfree(ctx->seed_rnd);
|
||||
free(ctx);
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
ctx->env->alloc = &ctx->superalloc;
|
||||
ctx->env->worker = NULL;
|
||||
ctx->env->need_to_validate = 0;
|
||||
@@ -310,6 +322,7 @@ ub_ctx_delete(struct ub_ctx* ctx)
|
||||
infra_delete(ctx->env->infra_cache);
|
||||
config_delete(ctx->env->cfg);
|
||||
edns_known_options_delete(ctx->env);
|
||||
auth_zones_delete(ctx->env->auth_zones);
|
||||
free(ctx->env);
|
||||
}
|
||||
ub_randfree(ctx->seed_rnd);
|
||||
@@ -677,7 +690,7 @@ ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
}
|
||||
/* create new ctx_query and attempt to add to the list */
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
q = context_new(ctx, name, rrtype, rrclass, NULL, NULL);
|
||||
q = context_new(ctx, name, rrtype, rrclass, NULL, NULL, NULL);
|
||||
if(!q)
|
||||
return UB_NOMEM;
|
||||
/* become a resolver thread for a bit */
|
||||
@@ -734,8 +747,7 @@ ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
ub_comm_base_now(ctx->event_worker->base);
|
||||
|
||||
/* create new ctx_query and attempt to add to the list */
|
||||
q = context_new(ctx, name, rrtype, rrclass, (ub_callback_type)callback,
|
||||
mydata);
|
||||
q = context_new(ctx, name, rrtype, rrclass, NULL, callback, mydata);
|
||||
if(!q)
|
||||
return UB_NOMEM;
|
||||
|
||||
@@ -780,7 +792,7 @@ ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
}
|
||||
|
||||
/* create new ctx_query and attempt to add to the list */
|
||||
q = context_new(ctx, name, rrtype, rrclass, callback, mydata);
|
||||
q = context_new(ctx, name, rrtype, rrclass, callback, NULL, mydata);
|
||||
if(!q)
|
||||
return UB_NOMEM;
|
||||
|
||||
|
||||
+51
-31
@@ -55,6 +55,7 @@
|
||||
#include "services/localzone.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/outbound_list.h"
|
||||
#include "services/authzone.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "util/module.h"
|
||||
#include "util/regional.h"
|
||||
@@ -157,8 +158,9 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
|
||||
hints_delete(w->env->hints);
|
||||
w->env->hints = NULL;
|
||||
}
|
||||
if(cfg->ssl_upstream) {
|
||||
w->sslctx = connect_sslctx_create(NULL, NULL, NULL);
|
||||
if(cfg->ssl_upstream || (cfg->tls_cert_bundle && cfg->tls_cert_bundle[0]) || cfg->tls_win_cert) {
|
||||
w->sslctx = connect_sslctx_create(NULL, NULL,
|
||||
cfg->tls_cert_bundle, cfg->tls_win_cert);
|
||||
if(!w->sslctx) {
|
||||
/* to make the setup fail after unlock */
|
||||
hints_delete(w->env->hints);
|
||||
@@ -214,6 +216,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
|
||||
libworker_delete(w);
|
||||
return NULL;
|
||||
}
|
||||
w->env->worker_base = w->base;
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
}
|
||||
@@ -232,9 +235,10 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
|
||||
cfg->do_tcp?cfg->outgoing_num_tcp:0,
|
||||
w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id,
|
||||
ports, numports, cfg->unwanted_threshold,
|
||||
cfg->outgoing_tcp_mss,
|
||||
&libworker_alloc_cleanup, w, cfg->do_udp, w->sslctx,
|
||||
cfg->outgoing_tcp_mss, &libworker_alloc_cleanup, w,
|
||||
cfg->do_udp || cfg->udp_upstream_without_downstream, w->sslctx,
|
||||
cfg->delay_close, NULL);
|
||||
w->env->outnet = w->back;
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
}
|
||||
@@ -251,6 +255,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
|
||||
w->env->send_query = &libworker_send_query;
|
||||
w->env->detach_subs = &mesh_detach_subs;
|
||||
w->env->attach_sub = &mesh_attach_sub;
|
||||
w->env->add_sub = &mesh_add_sub;
|
||||
w->env->kill_sub = &mesh_state_delete;
|
||||
w->env->detect_cycle = &mesh_detect_cycle;
|
||||
comm_base_timept(w->base, &w->env->now, &w->env->now_tv);
|
||||
@@ -294,6 +299,7 @@ libworker_do_cmd(struct libworker* w, uint8_t* msg, uint32_t len)
|
||||
log_err("unknown command for bg worker %d",
|
||||
(int)context_serial_getcmd(msg, len));
|
||||
/* and fall through to quit */
|
||||
/* fallthrough */
|
||||
case UB_LIBCMD_QUIT:
|
||||
free(msg);
|
||||
comm_base_exit(w->base);
|
||||
@@ -359,6 +365,7 @@ libworker_dobg(void* arg)
|
||||
|
||||
/* cleanup */
|
||||
m = UB_LIBCMD_QUIT;
|
||||
w->want_quit = 1;
|
||||
tube_remove_bg_listen(w->ctx->qq_pipe);
|
||||
tube_remove_bg_write(w->ctx->rr_pipe);
|
||||
libworker_delete(w);
|
||||
@@ -417,25 +424,6 @@ int libworker_bg(struct ub_ctx* ctx)
|
||||
return UB_NOERROR;
|
||||
}
|
||||
|
||||
/** get msg reply struct (in temp region) */
|
||||
static struct reply_info*
|
||||
parse_reply(sldns_buffer* pkt, struct regional* region, struct query_info* qi)
|
||||
{
|
||||
struct reply_info* rep;
|
||||
struct msg_parse* msg;
|
||||
if(!(msg = regional_alloc(region, sizeof(*msg)))) {
|
||||
return NULL;
|
||||
}
|
||||
memset(msg, 0, sizeof(*msg));
|
||||
sldns_buffer_set_position(pkt, 0);
|
||||
if(parse_packet(pkt, msg, region) != 0)
|
||||
return 0;
|
||||
if(!parse_create_msg(pkt, msg, NULL, qi, &rep, region)) {
|
||||
return 0;
|
||||
}
|
||||
return rep;
|
||||
}
|
||||
|
||||
/** insert canonname */
|
||||
static int
|
||||
fill_canon(struct ub_result* res, uint8_t* s)
|
||||
@@ -509,7 +497,7 @@ libworker_enter_result(struct ub_result* res, sldns_buffer* buf,
|
||||
struct query_info rq;
|
||||
struct reply_info* rep;
|
||||
res->rcode = LDNS_RCODE_SERVFAIL;
|
||||
rep = parse_reply(buf, temp, &rq);
|
||||
rep = parse_reply_in_temp_region(buf, temp, &rq);
|
||||
if(!rep) {
|
||||
log_err("cannot parse buf");
|
||||
return; /* error parsing buf, or out of memory */
|
||||
@@ -525,7 +513,8 @@ libworker_enter_result(struct ub_result* res, sldns_buffer* buf,
|
||||
res->nxdomain = 1;
|
||||
if(msg_security == sec_status_secure)
|
||||
res->secure = 1;
|
||||
if(msg_security == sec_status_bogus)
|
||||
if(msg_security == sec_status_bogus ||
|
||||
msg_security == sec_status_secure_sentinel_fail)
|
||||
res->bogus = 1;
|
||||
}
|
||||
|
||||
@@ -619,6 +608,15 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
|
||||
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)) {
|
||||
regional_free_all(w->env->scratch);
|
||||
libworker_fillup_fg(q, LDNS_RCODE_NOERROR,
|
||||
w->back->udp_buff, sec_status_insecure, NULL);
|
||||
libworker_delete(w);
|
||||
free(qinfo.qname);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
/* process new query */
|
||||
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
|
||||
w->back->udp_buff, qid, libworker_fg_done_cb, q)) {
|
||||
@@ -639,7 +637,7 @@ libworker_event_done_cb(void* arg, int rcode, sldns_buffer* buf,
|
||||
enum sec_status s, char* why_bogus)
|
||||
{
|
||||
struct ctx_query* q = (struct ctx_query*)arg;
|
||||
ub_event_callback_type cb = (ub_event_callback_type)q->cb;
|
||||
ub_event_callback_type cb = q->cb_event;
|
||||
void* cb_arg = q->cb_arg;
|
||||
int cancelled = q->cancelled;
|
||||
|
||||
@@ -689,6 +687,14 @@ int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q,
|
||||
w->back->udp_buff, sec_status_insecure, NULL);
|
||||
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)) {
|
||||
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);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
/* process new query */
|
||||
if(async_id)
|
||||
*async_id = q->querynum;
|
||||
@@ -709,6 +715,10 @@ add_bg_result(struct libworker* w, struct ctx_query* q, sldns_buffer* pkt,
|
||||
uint8_t* msg = NULL;
|
||||
uint32_t len = 0;
|
||||
|
||||
if(w->want_quit) {
|
||||
context_query_delete(q);
|
||||
return;
|
||||
}
|
||||
/* serialize and delete unneeded q */
|
||||
if(w->is_bg_thread) {
|
||||
lock_basic_lock(&w->ctx->cfglock);
|
||||
@@ -749,7 +759,7 @@ libworker_bg_done_cb(void* arg, int rcode, sldns_buffer* buf, enum sec_status s,
|
||||
{
|
||||
struct ctx_query* q = (struct ctx_query*)arg;
|
||||
|
||||
if(q->cancelled) {
|
||||
if(q->cancelled || q->w->back->want_to_quit) {
|
||||
if(q->w->is_bg_thread) {
|
||||
/* delete it now */
|
||||
struct ub_ctx* ctx = q->w->ctx;
|
||||
@@ -810,6 +820,14 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
|
||||
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)) {
|
||||
regional_free_all(w->env->scratch);
|
||||
q->msg_security = sec_status_insecure;
|
||||
add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL);
|
||||
free(qinfo.qname);
|
||||
return;
|
||||
}
|
||||
q->w = w;
|
||||
/* process new query */
|
||||
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
|
||||
@@ -829,7 +847,8 @@ void libworker_alloc_cleanup(void* arg)
|
||||
struct outbound_entry* libworker_send_query(struct query_info* qinfo,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, int ssl_upstream, struct module_qstate* q)
|
||||
size_t zonelen, int ssl_upstream, char* tls_auth_name,
|
||||
struct module_qstate* q)
|
||||
{
|
||||
struct libworker* w = (struct libworker*)q->env->worker;
|
||||
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
|
||||
@@ -839,8 +858,8 @@ struct outbound_entry* libworker_send_query(struct query_info* qinfo,
|
||||
e->qstate = q;
|
||||
e->qsent = outnet_serviced_query(w->back, qinfo, flags, dnssec,
|
||||
want_dnssec, nocaps, q->env->cfg->tcp_upstream, ssl_upstream,
|
||||
addr, addrlen, zone, zonelen, q, libworker_handle_service_reply,
|
||||
e, w->back->udp_buff, q->env);
|
||||
tls_auth_name, addr, addrlen, zone, zonelen, q,
|
||||
libworker_handle_service_reply, e, w->back->udp_buff, q->env);
|
||||
if(!e->qsent) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -960,7 +979,8 @@ struct outbound_entry* worker_send_query(struct query_info* ATTR_UNUSED(qinfo),
|
||||
int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen),
|
||||
uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
|
||||
int ATTR_UNUSED(ssl_upstream), struct module_qstate* ATTR_UNUSED(q))
|
||||
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
|
||||
struct module_qstate* ATTR_UNUSED(q))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
|
||||
@@ -75,6 +75,8 @@ struct libworker {
|
||||
int is_bg;
|
||||
/** is this a bg worker that is threaded (not forked)? */
|
||||
int is_bg_thread;
|
||||
/** want to quit, stop handling new content */
|
||||
int want_quit;
|
||||
|
||||
/** copy of the module environment with worker local entries. */
|
||||
struct module_env* env;
|
||||
|
||||
@@ -23,7 +23,7 @@ IDN converted attributes
|
||||
The :class:`unbound.ub_data` class contains attributes suffix which converts
|
||||
the dname to UTF string. These attributes have the ``_idn`` suffix.
|
||||
|
||||
Apart from this aproach, two conversion functions exist
|
||||
Apart from this approach, two conversion functions exist
|
||||
(:func:`unbound.idn2dname` and :func:`unbound.dname2idn`).
|
||||
|
||||
Source code
|
||||
|
||||
+185
-2
@@ -37,7 +37,7 @@
|
||||
* \file
|
||||
*
|
||||
* This file contains functions to resolve DNS queries and
|
||||
* validate the answers. Synchonously and asynchronously.
|
||||
* validate the answers. Synchronously and asynchronously.
|
||||
*
|
||||
* Several ways to use this interface from an application wishing
|
||||
* to perform (validated) DNS lookups.
|
||||
@@ -177,7 +177,7 @@ struct ub_result {
|
||||
* False, if validation failed or domain queried has no security info.
|
||||
*
|
||||
* It is possible to get a result with no data (havedata is false),
|
||||
* and secure is true. This means that the non-existance of the data
|
||||
* and secure is true. This means that the non-existence of the data
|
||||
* was cryptographically proven (with signatures).
|
||||
*/
|
||||
int secure;
|
||||
@@ -601,6 +601,189 @@ int ub_ctx_data_remove(struct ub_ctx* ctx, const char *data);
|
||||
*/
|
||||
const char* ub_version(void);
|
||||
|
||||
/**
|
||||
* Some global statistics that are not in struct stats_info,
|
||||
* this struct is shared on a shm segment (shm-key in unbound.conf)
|
||||
*/
|
||||
struct ub_shm_stat_info {
|
||||
int num_threads;
|
||||
|
||||
struct {
|
||||
long long now_sec, now_usec;
|
||||
long long up_sec, up_usec;
|
||||
long long elapsed_sec, elapsed_usec;
|
||||
} time;
|
||||
|
||||
struct {
|
||||
long long msg;
|
||||
long long rrset;
|
||||
long long val;
|
||||
long long iter;
|
||||
long long subnet;
|
||||
long long ipsecmod;
|
||||
long long respip;
|
||||
long long dnscrypt_shared_secret;
|
||||
long long dnscrypt_nonce;
|
||||
} mem;
|
||||
};
|
||||
|
||||
/** number of qtype that is stored for in array */
|
||||
#define UB_STATS_QTYPE_NUM 256
|
||||
/** number of qclass that is stored for in array */
|
||||
#define UB_STATS_QCLASS_NUM 256
|
||||
/** number of rcodes in stats */
|
||||
#define UB_STATS_RCODE_NUM 16
|
||||
/** number of opcodes in stats */
|
||||
#define UB_STATS_OPCODE_NUM 16
|
||||
/** number of histogram buckets */
|
||||
#define UB_STATS_BUCKET_NUM 40
|
||||
|
||||
/** per worker statistics. */
|
||||
struct ub_server_stats {
|
||||
/** number of queries from clients received. */
|
||||
long long num_queries;
|
||||
/** number of queries that have been dropped/ratelimited by ip. */
|
||||
long long num_queries_ip_ratelimited;
|
||||
/** number of queries that had a cache-miss. */
|
||||
long long num_queries_missed_cache;
|
||||
/** number of prefetch queries - cachehits with prefetch */
|
||||
long long num_queries_prefetch;
|
||||
|
||||
/**
|
||||
* Sum of the querylistsize of the worker for
|
||||
* every query that missed cache. To calculate average.
|
||||
*/
|
||||
long long sum_query_list_size;
|
||||
/** max value of query list size reached. */
|
||||
long long max_query_list_size;
|
||||
|
||||
/** Extended stats below (bool) */
|
||||
int extended;
|
||||
|
||||
/** qtype stats */
|
||||
long long qtype[UB_STATS_QTYPE_NUM];
|
||||
/** bigger qtype values not in array */
|
||||
long long qtype_big;
|
||||
/** qclass stats */
|
||||
long long qclass[UB_STATS_QCLASS_NUM];
|
||||
/** bigger qclass values not in array */
|
||||
long long qclass_big;
|
||||
/** query opcodes */
|
||||
long long qopcode[UB_STATS_OPCODE_NUM];
|
||||
/** number of queries over TCP */
|
||||
long long qtcp;
|
||||
/** number of outgoing queries over TCP */
|
||||
long long qtcp_outgoing;
|
||||
/** number of queries over IPv6 */
|
||||
long long qipv6;
|
||||
/** number of queries with QR bit */
|
||||
long long qbit_QR;
|
||||
/** number of queries with AA bit */
|
||||
long long qbit_AA;
|
||||
/** number of queries with TC bit */
|
||||
long long qbit_TC;
|
||||
/** number of queries with RD bit */
|
||||
long long qbit_RD;
|
||||
/** number of queries with RA bit */
|
||||
long long qbit_RA;
|
||||
/** number of queries with Z bit */
|
||||
long long qbit_Z;
|
||||
/** number of queries with AD bit */
|
||||
long long qbit_AD;
|
||||
/** number of queries with CD bit */
|
||||
long long qbit_CD;
|
||||
/** number of queries with EDNS OPT record */
|
||||
long long qEDNS;
|
||||
/** number of queries with EDNS with DO flag */
|
||||
long long qEDNS_DO;
|
||||
/** answer rcodes */
|
||||
long long ans_rcode[UB_STATS_RCODE_NUM];
|
||||
/** answers with pseudo rcode 'nodata' */
|
||||
long long ans_rcode_nodata;
|
||||
/** answers that were secure (AD) */
|
||||
long long ans_secure;
|
||||
/** answers that were bogus (withheld as SERVFAIL) */
|
||||
long long ans_bogus;
|
||||
/** rrsets marked bogus by validator */
|
||||
long long rrset_bogus;
|
||||
/** number of queries that have been ratelimited by domain recursion. */
|
||||
long long queries_ratelimited;
|
||||
/** unwanted traffic received on server-facing ports */
|
||||
long long unwanted_replies;
|
||||
/** unwanted traffic received on client-facing ports */
|
||||
long long unwanted_queries;
|
||||
/** usage of tcp accept list */
|
||||
long long tcp_accept_usage;
|
||||
/** answers served from expired cache */
|
||||
long long zero_ttl_responses;
|
||||
/** histogram data exported to array
|
||||
* if the array is the same size, no data is lost, and
|
||||
* if all histograms are same size (is so by default) then
|
||||
* adding up works well. */
|
||||
long long hist[UB_STATS_BUCKET_NUM];
|
||||
|
||||
/** number of message cache entries */
|
||||
long long msg_cache_count;
|
||||
/** number of rrset cache entries */
|
||||
long long rrset_cache_count;
|
||||
/** number of infra cache entries */
|
||||
long long infra_cache_count;
|
||||
/** number of key cache entries */
|
||||
long long key_cache_count;
|
||||
|
||||
/** number of queries that used dnscrypt */
|
||||
long long num_query_dnscrypt_crypted;
|
||||
/** number of queries that queried dnscrypt certificates */
|
||||
long long num_query_dnscrypt_cert;
|
||||
/** number of queries in clear text and not asking for the certificates */
|
||||
long long num_query_dnscrypt_cleartext;
|
||||
/** number of malformed encrypted queries */
|
||||
long long num_query_dnscrypt_crypted_malformed;
|
||||
/** number of queries which did not have a shared secret in cache */
|
||||
long long num_query_dnscrypt_secret_missed_cache;
|
||||
/** number of dnscrypt shared secret cache entries */
|
||||
long long shared_secret_cache_count;
|
||||
/** number of queries which are replays */
|
||||
long long num_query_dnscrypt_replay;
|
||||
/** number of dnscrypt nonces cache entries */
|
||||
long long nonce_cache_count;
|
||||
/** number of queries for unbound's auth_zones, upstream query */
|
||||
long long num_query_authzone_up;
|
||||
/** number of queries for unbound's auth_zones, downstream answers */
|
||||
long long num_query_authzone_down;
|
||||
/** number of times neg cache records were used to generate NOERROR
|
||||
* responses. */
|
||||
long long num_neg_cache_noerror;
|
||||
/** number of times neg cache records were used to generate NXDOMAIN
|
||||
* responses. */
|
||||
long long num_neg_cache_nxdomain;
|
||||
};
|
||||
|
||||
/**
|
||||
* Statistics to send over the control pipe when asked
|
||||
* This struct is made to be memcopied, sent in binary.
|
||||
* shm mapped with (number+1) at num_threads+1, with first as total
|
||||
*/
|
||||
struct ub_stats_info {
|
||||
/** the thread stats */
|
||||
struct ub_server_stats svr;
|
||||
|
||||
/** mesh stats: current number of states */
|
||||
long long mesh_num_states;
|
||||
/** mesh stats: current number of reply (user) states */
|
||||
long long mesh_num_reply_states;
|
||||
/** mesh stats: number of reply states overwritten with a new one */
|
||||
long long mesh_jostled;
|
||||
/** mesh stats: number of incoming queries dropped */
|
||||
long long mesh_dropped;
|
||||
/** mesh stats: replies sent */
|
||||
long long mesh_replies_sent;
|
||||
/** mesh stats: sum of waiting times for the replies */
|
||||
long long mesh_replies_sum_wait_sec, mesh_replies_sum_wait_usec;
|
||||
/** mesh stats: median of waiting times for replies (in sec) */
|
||||
double mesh_time_median;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+8
-2
@@ -63,6 +63,8 @@ struct query_info;
|
||||
* @param zone: delegation point name.
|
||||
* @param zonelen: length of zone name wireformat dname.
|
||||
* @param ssl_upstream: use SSL for upstream queries.
|
||||
* @param tls_auth_name: if ssl_upstream, use this name with TLS
|
||||
* authentication.
|
||||
* @param q: wich query state to reactivate upon return.
|
||||
* @return: false on failure (memory or socket related). no query was
|
||||
* sent.
|
||||
@@ -70,7 +72,8 @@ struct query_info;
|
||||
struct outbound_entry* libworker_send_query(struct query_info* qinfo,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, int ssl_upstream, struct module_qstate* q);
|
||||
size_t zonelen, int ssl_upstream, char* tls_auth_name,
|
||||
struct module_qstate* q);
|
||||
|
||||
/** process incoming replies from the network */
|
||||
int libworker_handle_reply(struct comm_point* c, void* arg, int error,
|
||||
@@ -115,6 +118,8 @@ void worker_sighandler(int sig, void* arg);
|
||||
* @param zone: wireformat dname of the zone.
|
||||
* @param zonelen: length of zone name.
|
||||
* @param ssl_upstream: use SSL for upstream queries.
|
||||
* @param tls_auth_name: if ssl_upstream, use this name with TLS
|
||||
* authentication.
|
||||
* @param q: wich query state to reactivate upon return.
|
||||
* @return: false on failure (memory or socket related). no query was
|
||||
* sent.
|
||||
@@ -122,7 +127,8 @@ void worker_sighandler(int sig, void* arg);
|
||||
struct outbound_entry* worker_send_query(struct query_info* qinfo,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, int ssl_upstream, struct module_qstate* q);
|
||||
size_t zonelen, int ssl_upstream, char* tls_auth_name,
|
||||
struct module_qstate* q);
|
||||
|
||||
/**
|
||||
* process control messages from the main thread. Frees the control
|
||||
|
||||
+13
-7
@@ -254,12 +254,12 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
# 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-asm -DOPENSSL_NO_CAPIENG mingw64"
|
||||
sslflags="no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64"
|
||||
else
|
||||
sslflags="no-asm -DOPENSSL_NO_CAPIENG mingw"
|
||||
sslflags="no-shared 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 ./Configure --prefix="$sslinstall" $sslflags || error_cleanup "OpenSSL Configure failed"
|
||||
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: make"
|
||||
make || error_cleanup "OpenSSL crosscompile failed"
|
||||
# only install sw not docs, which take a long time.
|
||||
@@ -272,15 +272,15 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
if test -n "$WINEXPAT"; then
|
||||
info "Cross compile $WINEXPAT"
|
||||
info "wxp: tar unpack"
|
||||
(cd ..; gzip -cd $WINEXPAT) | tar xf - || error_cleanup "tar unpack of $WINEXPAT failed"
|
||||
(cd ..; bzip2 -cd $WINEXPAT) | tar xf - || error_cleanup "tar unpack of $WINEXPAT failed"
|
||||
wxpinstall="`pwd`/wxpinstall"
|
||||
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 installlib"
|
||||
make installlib || error_cleanup "libexpat install failed"
|
||||
info "wxp: make install"
|
||||
make install || error_cleanup "libexpat install failed"
|
||||
cross_flag="$cross_flag --with-libexpat=$wxpinstall"
|
||||
cd ..
|
||||
fi
|
||||
@@ -345,6 +345,7 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
file="unbound-$version.zip"
|
||||
rm -f $file
|
||||
info "Creating $file"
|
||||
grep '^". IN DS' smallapp/unbound-anchor.c | sed -e 's/"//' -e 's/\\n.*$//' > root.key
|
||||
mkdir tmp.$$
|
||||
# keep debug symbols
|
||||
#$strip unbound.exe
|
||||
@@ -356,16 +357,21 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
#$strip unbound-service-install.exe
|
||||
#$strip unbound-service-remove.exe
|
||||
cd tmp.$$
|
||||
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 .
|
||||
# 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 unbound-website.url create_unbound_ad_servers.cmd warmup.cmd unbound_cache.cmd Changelog
|
||||
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
|
||||
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
|
||||
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
|
||||
fi
|
||||
"$makensis" ../winrc/setup_ed.nsi
|
||||
info "Created installer"
|
||||
cd ..
|
||||
|
||||
@@ -24,7 +24,7 @@ def operate(id, event, qstate, qdata):
|
||||
|
||||
if event == MODULE_EVENT_PASS:
|
||||
log_info("pythonmod: event_pass")
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
qstate.ext_state[id] = MODULE_WAIT_MODULE
|
||||
return True
|
||||
|
||||
log_err("pythonmod: BAD event")
|
||||
|
||||
@@ -109,7 +109,7 @@ Script file must contain four compulsory functions:
|
||||
return True
|
||||
|
||||
if event == MODULE_EVENT_PASS:
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
qstate.ext_state[id] = MODULE_WAIT_MODULE
|
||||
return True
|
||||
|
||||
log_err("pythonmod: BAD event")
|
||||
|
||||
@@ -46,4 +46,4 @@ Dig produces the following output::
|
||||
;; MSG SIZE rcvd: 54
|
||||
|
||||
As we handle (override) in the python module only queries ending with
|
||||
``localdomain.``, unboud can still resolve host names.
|
||||
``localdomain.``, unbound can still resolve host names.
|
||||
|
||||
@@ -10,7 +10,7 @@ As soon as the iterator module returns the response, we :
|
||||
3. rewrite the data in cache
|
||||
4. return modified packet
|
||||
|
||||
Note that the steps 1 and 3 are neccessary only in case, the python module is the first module in the processing chain.
|
||||
Note that the steps 1 and 3 are necessary only in case, the python module is the first module in the processing chain.
|
||||
In other cases, the validator module guarantees updating data which are produced by iterator module.
|
||||
|
||||
Complete source code
|
||||
|
||||
@@ -3,7 +3,7 @@ EDNS options
|
||||
|
||||
This example shows how to interact with EDNS options.
|
||||
|
||||
When quering unbound with the EDNS option ``65001`` and data ``0xc001`` we
|
||||
When querying unbound with the EDNS option ``65001`` and data ``0xc001`` we
|
||||
expect an answer with the same EDNS option code and data ``0xdeadbeef``.
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ and use a valid script path::
|
||||
|
||||
python-script: "./examples/edns.py"
|
||||
|
||||
Quering with EDNS option ``65001:0xc001``:
|
||||
Querying with EDNS option ``65001:0xc001``:
|
||||
|
||||
::
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ The callback function's prototype is the following:
|
||||
:param rep: reply_info struct;
|
||||
:param rcode: return code for the query;
|
||||
:param edns: edns_data sent from the client side. The list with the EDNS
|
||||
options is accesible through edns.opt_list. It SHOULD NOT be
|
||||
options is accessible through edns.opt_list. It SHOULD NOT be
|
||||
altered;
|
||||
:param opt_list_out: the list with the EDNS options that will be sent as a
|
||||
reply. It can be populated with EDNS options;
|
||||
@@ -120,7 +120,7 @@ The callback function's prototype is the following:
|
||||
:param rep: reply_info struct;
|
||||
:param rcode: return code for the query;
|
||||
:param edns: edns_data sent from the client side. The list with the
|
||||
EDNS options is accesible through edns.opt_list. It
|
||||
EDNS options is accessible through edns.opt_list. It
|
||||
SHOULD NOT be altered;
|
||||
:param opt_list_out: the list with the EDNS options that will be sent as a
|
||||
reply. It can be populated with EDNS options;
|
||||
|
||||
@@ -24,7 +24,7 @@ Cache
|
||||
:param qstate: :class:`module_qstate`
|
||||
:param qinfo: :class:`query_info`
|
||||
:param msgrep: :class:`reply_info`
|
||||
:param is_referal: integer
|
||||
:param is_referral: integer
|
||||
:rtype: boolean
|
||||
|
||||
.. function:: invalidateQueryInCache(qstate, qinfo)
|
||||
|
||||
@@ -108,7 +108,7 @@ query_info
|
||||
|
||||
.. attribute:: qname_len
|
||||
|
||||
Lenght of question name (number of bytes).
|
||||
Length of question name (number of bytes).
|
||||
|
||||
.. attribute:: qname_list[]
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ Controled by secured queries secured with private key.
|
||||
|
||||
Dynamic translation service
|
||||
---------------------------
|
||||
DNS request can be translated to virtualy any answer, that's easy to implement in client side
|
||||
DNS request can be translated to virtually any answer, that's easy to implement in client side
|
||||
because of many DNS libraries available.
|
||||
|
||||
Examples :
|
||||
|
||||
@@ -77,7 +77,7 @@ def init_standard(id, env):
|
||||
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 accesible configuration options can now be found in
|
||||
..note:: The previously accessible configuration options can now be found in
|
||||
env.cgf.
|
||||
"""
|
||||
log_info("python: inited script {}".format(env.cfg.python_script))
|
||||
@@ -94,7 +94,7 @@ def init(id, cfg):
|
||||
"""Previous version 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 ommited to avoid confusion to the
|
||||
present this function SHOULD be omitted to avoid confusion to the
|
||||
reader.
|
||||
"""
|
||||
return True
|
||||
|
||||
@@ -99,7 +99,7 @@ def inplace_cache_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
:param rep: reply_info struct;
|
||||
:param rcode: return code for the query;
|
||||
:param edns: edns_data sent from the client side. The list with the EDNS
|
||||
options is accesible through edns.opt_list. It SHOULD NOT be
|
||||
options is accessible through edns.opt_list. It SHOULD NOT be
|
||||
altered;
|
||||
:param opt_list_out: the list with the EDNS options that will be sent as a
|
||||
reply. It can be populated with EDNS options;
|
||||
@@ -107,7 +107,7 @@ def inplace_cache_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
want to append a new option to opt_list_out.
|
||||
:return: True on success, False on failure.
|
||||
|
||||
For demostration purposes we want to see if EDNS option 65002 is present
|
||||
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.")
|
||||
@@ -142,7 +142,7 @@ def inplace_local_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
:param rep: reply_info struct;
|
||||
:param rcode: return code for the query;
|
||||
:param edns: edns_data sent from the client side. The list with the
|
||||
EDNS options is accesible through edns.opt_list. It
|
||||
EDNS options is accessible through edns.opt_list. It
|
||||
SHOULD NOT be altered;
|
||||
:param opt_list_out: the list with the EDNS options that will be sent as a
|
||||
reply. It can be populated with EDNS options;
|
||||
@@ -173,7 +173,7 @@ def inplace_servfail_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
want to append a new option to opt_list_out.
|
||||
:return: True on success, False on failure.
|
||||
|
||||
For demostration purposes we want to reply with an empty EDNS code '65003'.
|
||||
For demonstration purposes we want to reply with an empty EDNS code '65003'.
|
||||
"""
|
||||
log_info("python: called back while servfail.")
|
||||
b = bytearray.fromhex("")
|
||||
@@ -186,7 +186,7 @@ def init_standard(id, env):
|
||||
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 accesible configuration options can now be found in
|
||||
..note:: The previously accessible configuration options can now be found in
|
||||
env.cgf.
|
||||
"""
|
||||
log_info("python: inited script {}".format(env.cfg.python_script))
|
||||
@@ -218,7 +218,7 @@ def init(id, cfg):
|
||||
"""Previous version 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 ommited to avoid confusion to the
|
||||
present this function SHOULD be omitted to avoid confusion to the
|
||||
reader.
|
||||
"""
|
||||
return True
|
||||
|
||||
@@ -574,7 +574,7 @@ struct module_env {
|
||||
struct outbound_entry* (*send_query)(struct query_info* qinfo,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, int ssl_upstream,
|
||||
uint8_t* zone, size_t zonelen, int ssl_upstream, char* tls_auth_name,
|
||||
struct module_qstate* q);
|
||||
void (*detach_subs)(struct module_qstate* qstate);
|
||||
int (*attach_sub)(struct module_qstate* qstate,
|
||||
@@ -883,7 +883,7 @@ struct config_file {
|
||||
struct config_strlist* local_zones_nodefault;
|
||||
struct config_strlist* local_data;
|
||||
int remote_control_enable;
|
||||
struct config_strlist* control_ifs;
|
||||
struct config_strlist_head control_ifs;
|
||||
int control_port;
|
||||
char* server_key_file;
|
||||
char* server_cert_file;
|
||||
@@ -1277,7 +1277,7 @@ struct delegpt* find_delegation(struct module_qstate* qstate, char *nm, size_t n
|
||||
Functions
|
||||
* ************************************************************************************ */
|
||||
/******************************
|
||||
* Various debuging functions *
|
||||
* Various debugging functions *
|
||||
******************************/
|
||||
void verbose(enum verbosity_value level, const char* format, ...);
|
||||
void log_info(const char* format, ...);
|
||||
|
||||
@@ -41,8 +41,10 @@
|
||||
/* ignore the varargs unused warning from SWIGs internal vararg support */
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#ifndef __clang__
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
|
||||
@@ -261,6 +261,7 @@ respip_enter_rr(struct regional* region, struct resp_addr* raddr,
|
||||
log_err("bad response-ip-data: %s", rrstr);
|
||||
return 0;
|
||||
}
|
||||
free(nm);
|
||||
sa = (struct sockaddr*)&raddr->node.addr;
|
||||
if (rrtype == LDNS_RR_TYPE_CNAME && raddr->data) {
|
||||
log_err("CNAME response-ip data (%s) can not co-exist with other "
|
||||
|
||||
+6570
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,653 @@
|
||||
/*
|
||||
* services/authzone.h - authoritative zone that is locally hosted.
|
||||
*
|
||||
* Copyright (c) 2017, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* 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 NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains the functions for an authority zone. This zone
|
||||
* is queried by the iterator, just like a stub or forward zone, but then
|
||||
* the data is locally held.
|
||||
*/
|
||||
|
||||
#ifndef SERVICES_AUTHZONE_H
|
||||
#define SERVICES_AUTHZONE_H
|
||||
#include "util/rbtree.h"
|
||||
#include "util/locks.h"
|
||||
#include "services/mesh.h"
|
||||
struct ub_packed_rrset_key;
|
||||
struct regional;
|
||||
struct config_file;
|
||||
struct config_auth;
|
||||
struct query_info;
|
||||
struct dns_msg;
|
||||
struct edns_data;
|
||||
struct module_env;
|
||||
struct worker;
|
||||
struct comm_point;
|
||||
struct comm_timer;
|
||||
struct comm_reply;
|
||||
struct auth_rrset;
|
||||
struct auth_nextprobe;
|
||||
struct auth_probe;
|
||||
struct auth_transfer;
|
||||
struct auth_master;
|
||||
struct auth_chunk;
|
||||
|
||||
/**
|
||||
* Authoritative zones, shared.
|
||||
*/
|
||||
struct auth_zones {
|
||||
/** lock on the authzone trees */
|
||||
lock_rw_type lock;
|
||||
/** rbtree of struct auth_zone */
|
||||
rbtree_type ztree;
|
||||
/** rbtree of struct auth_xfer */
|
||||
rbtree_type xtree;
|
||||
/** do we have downstream enabled */
|
||||
int have_downstream;
|
||||
/** number of queries upstream */
|
||||
size_t num_query_up;
|
||||
/** number of queries downstream */
|
||||
size_t num_query_down;
|
||||
};
|
||||
|
||||
/**
|
||||
* Auth zone. Authoritative data, that is fetched from instead of sending
|
||||
* packets to the internet.
|
||||
*/
|
||||
struct auth_zone {
|
||||
/** rbtree node, key is name and class */
|
||||
rbnode_type node;
|
||||
|
||||
/** zone name, in uncompressed wireformat */
|
||||
uint8_t* name;
|
||||
/** length of zone name */
|
||||
size_t namelen;
|
||||
/** number of labels in zone name */
|
||||
int namelabs;
|
||||
/** the class of this zone, in host byteorder.
|
||||
* uses 'dclass' to not conflict with c++ keyword class. */
|
||||
uint16_t dclass;
|
||||
|
||||
/** lock on the data in the structure
|
||||
* For the node, parent, name, namelen, namelabs, dclass, you
|
||||
* need to also hold the zones_tree lock to change them (or to
|
||||
* delete this zone) */
|
||||
lock_rw_type lock;
|
||||
|
||||
/** auth data for this zone
|
||||
* rbtree of struct auth_data */
|
||||
rbtree_type data;
|
||||
|
||||
/** zonefile name (or NULL for no zonefile) */
|
||||
char* zonefile;
|
||||
/** fallback to the internet on failure or ttl-expiry of auth zone */
|
||||
int fallback_enabled;
|
||||
/** the zone has expired (enabled by the xfer worker), fallback
|
||||
* happens if that option is enabled. */
|
||||
int zone_expired;
|
||||
/** zone is a slave zone (it has masters) */
|
||||
int zone_is_slave;
|
||||
/** for downstream: this zone answers queries towards the downstream
|
||||
* clients */
|
||||
int for_downstream;
|
||||
/** for upstream: this zone answers queries that unbound intends to
|
||||
* send upstream. */
|
||||
int for_upstream;
|
||||
/** zone has been deleted */
|
||||
int zone_deleted;
|
||||
/** deletelist pointer, unused normally except during delete */
|
||||
struct auth_zone* delete_next;
|
||||
};
|
||||
|
||||
/**
|
||||
* Auth data. One domain name, and the RRs to go with it.
|
||||
*/
|
||||
struct auth_data {
|
||||
/** rbtree node, key is name only */
|
||||
rbnode_type node;
|
||||
/** domain name */
|
||||
uint8_t* name;
|
||||
/** length of name */
|
||||
size_t namelen;
|
||||
/** number of labels in name */
|
||||
int namelabs;
|
||||
/** the data rrsets, with different types, linked list.
|
||||
* if the list if NULL the node would be an empty non-terminal,
|
||||
* but in this data structure such nodes that represent an empty
|
||||
* non-terminal are not needed; they just don't exist.
|
||||
*/
|
||||
struct auth_rrset* rrsets;
|
||||
};
|
||||
|
||||
/**
|
||||
* A auth data RRset
|
||||
*/
|
||||
struct auth_rrset {
|
||||
/** next in list */
|
||||
struct auth_rrset* next;
|
||||
/** RR type in host byteorder */
|
||||
uint16_t type;
|
||||
/** RRset data item */
|
||||
struct packed_rrset_data* data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Authoritative zone transfer structure.
|
||||
* Create and destroy needs the auth_zones* biglock.
|
||||
* The structure consists of different tasks. Each can be unowned (-1) or
|
||||
* owner by a worker (worker-num). A worker can pick up a task and then do
|
||||
* it. This means the events (timeouts, sockets) are for that worker.
|
||||
*
|
||||
* (move this to tasks).
|
||||
* They don't have locks themselves, the worker (that owns it) uses it,
|
||||
* also as part of callbacks, hence it has separate zonename pointers for
|
||||
* lookup in the main zonetree. If the zone has no transfers, this
|
||||
* structure is not created.
|
||||
*/
|
||||
struct auth_xfer {
|
||||
/** rbtree node, key is name and class */
|
||||
rbnode_type node;
|
||||
|
||||
/** lock on this structure, and on the workernum elements of the
|
||||
* tasks. First hold the tree-lock in auth_zones, find the auth_xfer,
|
||||
* lock this lock. Then a worker can reassign itself to fill up
|
||||
* one of the tasks.
|
||||
* Once it has the task assigned to it, the worker can access the
|
||||
* other elements of the task structure without a lock, because that
|
||||
* is necessary for the eventloop and callbacks from that. */
|
||||
lock_basic_type lock;
|
||||
|
||||
/** zone name, in uncompressed wireformat */
|
||||
uint8_t* name;
|
||||
/** length of zone name */
|
||||
size_t namelen;
|
||||
/** number of labels in zone name */
|
||||
int namelabs;
|
||||
/** the class of this zone, in host byteorder.
|
||||
* uses 'dclass' to not conflict with c++ keyword class. */
|
||||
uint16_t dclass;
|
||||
|
||||
/** task to wait for next-probe-timeout,
|
||||
* once timeouted, see if a SOA probe is needed, or already
|
||||
* in progress */
|
||||
struct auth_nextprobe* task_nextprobe;
|
||||
|
||||
/** task for SOA probe. Check if the zone can be updated */
|
||||
struct auth_probe* task_probe;
|
||||
|
||||
/** Task for transfer. Transferring and updating the zone. This
|
||||
* includes trying (potentially) several upstream masters. Downloading
|
||||
* and storing the zone */
|
||||
struct auth_transfer* task_transfer;
|
||||
|
||||
/** a notify was received, but a zone transfer or probe was already
|
||||
* acted on.
|
||||
* However, the zone transfer could signal a newer serial number.
|
||||
* The serial number of that notify is saved below. The transfer and
|
||||
* probe tasks should check this once done to see if they need to
|
||||
* restart the transfer task for the newer notify serial.
|
||||
* Hold the lock to access this member (and the serial).
|
||||
*/
|
||||
int notify_received;
|
||||
/** true if the notify_received has a serial number */
|
||||
int notify_has_serial;
|
||||
/** serial number of the notify */
|
||||
uint32_t notify_serial;
|
||||
/** the list of masters for checking notifies. This list is
|
||||
* empty on start, and a copy of the list from the probe_task when
|
||||
* it is done looking them up. */
|
||||
struct auth_master* allow_notify_list;
|
||||
|
||||
/* protected by the lock on the structure, information about
|
||||
* the loaded authority zone. */
|
||||
/** is the zone currently considered expired? after expiry also older
|
||||
* serial numbers are allowed (not just newer) */
|
||||
int zone_expired;
|
||||
/** do we have a zone (if 0, no zone data at all) */
|
||||
int have_zone;
|
||||
|
||||
/** current serial (from SOA), if we have no zone, 0 */
|
||||
uint32_t serial;
|
||||
/** retry time (from SOA), time to wait with next_probe
|
||||
* if no master responds */
|
||||
time_t retry;
|
||||
/** refresh time (from SOA), time to wait with next_probe
|
||||
* if everything is fine */
|
||||
time_t refresh;
|
||||
/** expiry time (from SOA), time until zone data is not considered
|
||||
* valid any more, if no master responds within this time, either
|
||||
* with the current zone or a new zone. */
|
||||
time_t expiry;
|
||||
|
||||
/** zone lease start time (start+expiry is expiration time).
|
||||
* this is renewed every SOA probe and transfer. On zone load
|
||||
* from zonefile it is also set (with probe set soon to check) */
|
||||
time_t lease_time;
|
||||
};
|
||||
|
||||
/**
|
||||
* The next probe task.
|
||||
* This task consists of waiting for the probetimeout. It is a task because
|
||||
* it needs an event in the eventtable. Once the timeout has passed, that
|
||||
* worker can (potentially) become the auth_probe worker, or if another worker
|
||||
* is already doing that, do nothing. Tasks becomes unowned.
|
||||
* The probe worker, if it detects nothing has to be done picks up this task,
|
||||
* if unowned.
|
||||
*/
|
||||
struct auth_nextprobe {
|
||||
/* Worker pointer. NULL means unowned. */
|
||||
struct worker* worker;
|
||||
/* module env for this task */
|
||||
struct module_env* env;
|
||||
|
||||
/** increasing backoff for failures */
|
||||
time_t backoff;
|
||||
/** Timeout for next probe (for SOA) */
|
||||
time_t next_probe;
|
||||
/** timeout callback for next_probe or expiry(if that is sooner).
|
||||
* it is on the worker's event_base */
|
||||
struct comm_timer* timer;
|
||||
};
|
||||
|
||||
/**
|
||||
* The probe task.
|
||||
* Send a SOA UDP query to see if the zone needs to be updated (or similar,
|
||||
* potential, HTTP probe query) and check serial number.
|
||||
* If yes, start the auth_transfer task. If no, make sure auth_nextprobe
|
||||
* timeout wait task is running.
|
||||
* Needs to be a task, because the UDP query needs an event entry.
|
||||
* This task could also be started by eg. a NOTIFY being received, even though
|
||||
* another worker is performing the nextprobe task (and that worker keeps
|
||||
* waiting uninterrupted).
|
||||
*/
|
||||
struct auth_probe {
|
||||
/* Worker pointer. NULL means unowned. */
|
||||
struct worker* worker;
|
||||
/* module env for this task */
|
||||
struct module_env* env;
|
||||
|
||||
/** list of upstream masters for this zone, from config */
|
||||
struct auth_master* masters;
|
||||
|
||||
/** for the hostname lookups, which master is current */
|
||||
struct auth_master* lookup_target;
|
||||
/** are we looking up A or AAAA, first A, then AAAA (if ip6 enabled) */
|
||||
int lookup_aaaa;
|
||||
/** we only want to do lookups for making config work (for notify),
|
||||
* don't proceed with UDP SOA probe queries */
|
||||
int only_lookup;
|
||||
|
||||
/** once notified, or the timeout has been reached. a scan starts. */
|
||||
/** the scan specific target (notify source), or NULL if none */
|
||||
struct auth_master* scan_specific;
|
||||
/** scan tries all the upstream masters. the scan current target.
|
||||
* or NULL if not working on sequential scan */
|
||||
struct auth_master* scan_target;
|
||||
/** if not NULL, the specific addr for the current master */
|
||||
struct auth_addr* scan_addr;
|
||||
|
||||
/** dns id of packet in flight */
|
||||
uint16_t id;
|
||||
/** the SOA probe udp event.
|
||||
* on the workers event base. */
|
||||
struct comm_point* cp;
|
||||
/** timeout for packets.
|
||||
* on the workers event base. */
|
||||
struct comm_timer* timer;
|
||||
/** timeout in msec */
|
||||
int timeout;
|
||||
};
|
||||
|
||||
/**
|
||||
* The transfer task.
|
||||
* Once done, make sure the nextprobe waiting task is running, whether done
|
||||
* with failure or success. If failure, use shorter timeout for wait time.
|
||||
*/
|
||||
struct auth_transfer {
|
||||
/* Worker pointer. NULL means unowned. */
|
||||
struct worker* worker;
|
||||
/* module env for this task */
|
||||
struct module_env* env;
|
||||
|
||||
/** xfer data that has been transferred, the data is applied
|
||||
* once the transfer has completed correctly */
|
||||
struct auth_chunk* chunks_first;
|
||||
/** last element in chunks list (to append new data at the end) */
|
||||
struct auth_chunk* chunks_last;
|
||||
|
||||
/** list of upstream masters for this zone, from config */
|
||||
struct auth_master* masters;
|
||||
|
||||
/** for the hostname lookups, which master is current */
|
||||
struct auth_master* lookup_target;
|
||||
/** are we looking up A or AAAA, first A, then AAAA (if ip6 enabled) */
|
||||
int lookup_aaaa;
|
||||
|
||||
/** once notified, or the timeout has been reached. a scan starts. */
|
||||
/** the scan specific target (notify source), or NULL if none */
|
||||
struct auth_master* scan_specific;
|
||||
/** scan tries all the upstream masters. the scan current target.
|
||||
* or NULL if not working on sequential scan */
|
||||
struct auth_master* scan_target;
|
||||
/** what address we are scanning for the master, or NULL if the
|
||||
* master is in IP format itself */
|
||||
struct auth_addr* scan_addr;
|
||||
/** the zone transfer in progress (or NULL if in scan). It is
|
||||
* from this master */
|
||||
struct auth_master* master;
|
||||
|
||||
/** failed ixfr transfer, retry with axfr (to the current master),
|
||||
* the IXFR was 'REFUSED', 'SERVFAIL', 'NOTIMPL' or the contents of
|
||||
* the IXFR did not apply cleanly (out of sync, delete of nonexistent
|
||||
* data or add of duplicate data). Flag is cleared once the retry
|
||||
* with axfr is done. */
|
||||
int ixfr_fail;
|
||||
/** we are doing IXFR right now */
|
||||
int on_ixfr;
|
||||
/** did we detect the current AXFR/IXFR serial number yet, 0 not yet,
|
||||
* 1 we saw the first, 2 we saw the second, 3 must be last SOA in xfr*/
|
||||
int got_xfr_serial;
|
||||
/** number of RRs scanned for AXFR/IXFR detection */
|
||||
size_t rr_scan_num;
|
||||
/** we are doing an IXFR but we detected an AXFR contents */
|
||||
int on_ixfr_is_axfr;
|
||||
/** the serial number for the current AXFR/IXFR incoming reply,
|
||||
* for IXFR, the outermost SOA records serial */
|
||||
uint32_t incoming_xfr_serial;
|
||||
|
||||
/** dns id of AXFR query */
|
||||
uint16_t id;
|
||||
/** the transfer (TCP) to the master.
|
||||
* on the workers event base. */
|
||||
struct comm_point* cp;
|
||||
};
|
||||
|
||||
/** list of addresses */
|
||||
struct auth_addr {
|
||||
/** next in list */
|
||||
struct auth_addr* next;
|
||||
/** IP address */
|
||||
struct sockaddr_storage addr;
|
||||
/** addr length */
|
||||
socklen_t addrlen;
|
||||
};
|
||||
|
||||
/** auth zone master upstream, and the config settings for it */
|
||||
struct auth_master {
|
||||
/** next master in list */
|
||||
struct auth_master* next;
|
||||
/** master IP address (and port), or hostname, string */
|
||||
char* host;
|
||||
/** for http, filename */
|
||||
char* file;
|
||||
/** use HTTP for this master */
|
||||
int http;
|
||||
/** use IXFR for this master */
|
||||
int ixfr;
|
||||
/** this is an allow notify member, the master can send notifies
|
||||
* to us, but we don't send SOA probes, or zone transfer from it */
|
||||
int allow_notify;
|
||||
/** use ssl for channel */
|
||||
int ssl;
|
||||
/** the port number (for urls) */
|
||||
int port;
|
||||
/** if the host is a hostname, the list of resolved addrs, if any*/
|
||||
struct auth_addr* list;
|
||||
};
|
||||
|
||||
/** auth zone master zone transfer data chunk */
|
||||
struct auth_chunk {
|
||||
/** next chunk in list */
|
||||
struct auth_chunk* next;
|
||||
/** the data from this chunk, this is what was received.
|
||||
* for an IXFR that means results from comm_net tcp actions,
|
||||
* packets. also for an AXFR. For HTTP a zonefile chunk. */
|
||||
uint8_t* data;
|
||||
/** length of allocated data */
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create auth zones structure
|
||||
*/
|
||||
struct auth_zones* auth_zones_create(void);
|
||||
|
||||
/**
|
||||
* Apply configuration to auth zones. Reads zonefiles.
|
||||
* @param az: auth zones structure
|
||||
* @param cfg: config to apply.
|
||||
* @param setup: if true, also sets up values in the auth zones structure
|
||||
* @return false on failure.
|
||||
*/
|
||||
int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
|
||||
int setup);
|
||||
|
||||
/** initial pick up of worker timeouts, ties events to worker event loop
|
||||
* @param az: auth zones structure
|
||||
* @param env: worker env, of first worker that receives the events (if any)
|
||||
* in its eventloop.
|
||||
*/
|
||||
void auth_xfer_pickup_initial(struct auth_zones* az, struct module_env* env);
|
||||
|
||||
/**
|
||||
* Cleanup auth zones. This removes all events from event bases.
|
||||
* Stops the xfr tasks. But leaves zone data.
|
||||
* @param az: auth zones structure.
|
||||
*/
|
||||
void auth_zones_cleanup(struct auth_zones* az);
|
||||
|
||||
/**
|
||||
* Delete auth zones structure
|
||||
*/
|
||||
void auth_zones_delete(struct auth_zones* az);
|
||||
|
||||
/**
|
||||
* Write auth zone data to file, in zonefile format.
|
||||
*/
|
||||
int auth_zone_write_file(struct auth_zone* z, const char* fname);
|
||||
|
||||
/**
|
||||
* Use auth zones to lookup the answer to a query.
|
||||
* The query is from the iterator. And the auth zones attempts to provide
|
||||
* the answer instead of going to the internet.
|
||||
*
|
||||
* @param az: auth zones structure.
|
||||
* @param qinfo: query info to lookup.
|
||||
* @param region: region to use to allocate the reply in.
|
||||
* @param msg: reply is stored here (if one).
|
||||
* @param fallback: if true, fallback to making a query to the internet.
|
||||
* @param dp_nm: name of delegation point to look for. This zone is used
|
||||
* to answer the query.
|
||||
* If the dp_nm is not found, fallback is set to true and false returned.
|
||||
* @param dp_nmlen: length of dp_nm.
|
||||
* @return 0: failure (an error of some sort, like servfail).
|
||||
* if 0 and fallback is true, fallback to the internet.
|
||||
* if 0 and fallback is false, like getting servfail.
|
||||
* If true, an answer is available.
|
||||
*/
|
||||
int auth_zones_lookup(struct auth_zones* az, struct query_info* qinfo,
|
||||
struct regional* region, struct dns_msg** msg, int* fallback,
|
||||
uint8_t* dp_nm, size_t dp_nmlen);
|
||||
|
||||
/**
|
||||
* Answer query from auth zone. Create authoritative answer.
|
||||
* @param az: auth zones structure.
|
||||
* @param env: the module environment.
|
||||
* @param qinfo: query info (parsed).
|
||||
* @param edns: edns info (parsed).
|
||||
* @param buf: buffer with query ID and flags, also for reply.
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* Find the auth zone that is above the given qname.
|
||||
* Return NULL when there is no auth_zone above the give name, otherwise
|
||||
* returns the closest auth_zone above the qname that pertains to it.
|
||||
* @param az: auth zones structure.
|
||||
* @param name: query to look up for.
|
||||
* @param name_len: length of name.
|
||||
* @param dclass: class of zone to find.
|
||||
* @return NULL or auth_zone that pertains to the query.
|
||||
*/
|
||||
struct auth_zone* auth_zones_find_zone(struct auth_zones* az,
|
||||
uint8_t* name, size_t name_len, uint16_t dclass);
|
||||
|
||||
/** find an auth zone by name (exact match by name or NULL returned) */
|
||||
struct auth_zone* auth_zone_find(struct auth_zones* az, uint8_t* nm,
|
||||
size_t nmlen, uint16_t dclass);
|
||||
|
||||
/** find an xfer zone by name (exact match by name or NULL returned) */
|
||||
struct auth_xfer* auth_xfer_find(struct auth_zones* az, uint8_t* nm,
|
||||
size_t nmlen, uint16_t dclass);
|
||||
|
||||
/** create an auth zone. returns wrlocked zone. caller must have wrlock
|
||||
* on az. returns NULL on malloc failure */
|
||||
struct auth_zone* auth_zone_create(struct auth_zones* az, uint8_t* nm,
|
||||
size_t nmlen, uint16_t dclass);
|
||||
|
||||
/** set auth zone zonefile string. caller must have lock on zone */
|
||||
int auth_zone_set_zonefile(struct auth_zone* z, char* zonefile);
|
||||
|
||||
/** set auth zone fallback. caller must have lock on zone.
|
||||
* fallbackstr is "yes" or "no". false on parse failure. */
|
||||
int auth_zone_set_fallback(struct auth_zone* z, char* fallbackstr);
|
||||
|
||||
/** see if the auth zone for the name can fallback
|
||||
* @param az: auth zones
|
||||
* @param nm: name of delegation point.
|
||||
* @param nmlen: length of nm.
|
||||
* @param dclass: class of zone to look for.
|
||||
* @return true if fallback_enabled is true. false if not.
|
||||
* if the zone does not exist, fallback is true (more lenient)
|
||||
* also true if zone does not do upstream requests.
|
||||
*/
|
||||
int auth_zones_can_fallback(struct auth_zones* az, uint8_t* nm, size_t nmlen,
|
||||
uint16_t dclass);
|
||||
|
||||
/** process notify for auth zones.
|
||||
* first checks the access list. Then processes the notify. This starts
|
||||
* the probe sequence or it notes the serial number (if any)
|
||||
* @param az: auth zones structure.
|
||||
* @param env: module env of the worker that is handling the notify. it will
|
||||
* pick up the task probe (or transfer), unless already in progress by
|
||||
* another worker.
|
||||
* @param nm: name of the zone. Uncompressed. from query.
|
||||
* @param nmlen: length of name.
|
||||
* @param dclass: class of zone.
|
||||
* @param addr: source address of notify
|
||||
* @param addrlen: length of addr.
|
||||
* @param has_serial: if true, the notify has a serial attached.
|
||||
* @param serial: the serial number, if has_serial is true.
|
||||
* @param refused: is set to true on failure to note refused access.
|
||||
* @return fail on failures (refused is false) and when access is
|
||||
* denied (refused is true). True when processed.
|
||||
*/
|
||||
int auth_zones_notify(struct auth_zones* az, struct module_env* env,
|
||||
uint8_t* nm, size_t nmlen, uint16_t dclass,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int has_serial,
|
||||
uint32_t serial, int* refused);
|
||||
|
||||
/** process notify packet and read serial number from SOA.
|
||||
* returns 0 if no soa record in the notify */
|
||||
int auth_zone_parse_notify_serial(struct sldns_buffer* pkt, uint32_t *serial);
|
||||
|
||||
/** read auth zone from zonefile. caller must lock zone. false on failure */
|
||||
int auth_zone_read_zonefile(struct auth_zone* z);
|
||||
|
||||
/** find serial number of zone or false if none (no SOA record) */
|
||||
int auth_zone_get_serial(struct auth_zone* z, uint32_t* serial);
|
||||
|
||||
/** compare auth_zones for sorted rbtree */
|
||||
int auth_zone_cmp(const void* z1, const void* z2);
|
||||
|
||||
/** compare auth_data for sorted rbtree */
|
||||
int auth_data_cmp(const void* z1, const void* z2);
|
||||
|
||||
/** compare auth_xfer for sorted rbtree */
|
||||
int auth_xfer_cmp(const void* z1, const void* z2);
|
||||
|
||||
/** Create auth_xfer structure.
|
||||
* Caller must have wrlock on az. Returns locked xfer zone.
|
||||
* @param az: zones structure.
|
||||
* @param z: zone with name and class
|
||||
* @return xfer zone or NULL
|
||||
*/
|
||||
struct auth_xfer* auth_xfer_create(struct auth_zones* az, struct auth_zone* z);
|
||||
|
||||
/**
|
||||
* Set masters in auth xfer structure from config.
|
||||
* @param list: pointer to start of list. The malloced list is returned here.
|
||||
* @param c: the config items to copy over.
|
||||
* @param with_http: if true, http urls are also included, before the masters.
|
||||
* @return false on failure.
|
||||
*/
|
||||
int xfer_set_masters(struct auth_master** list, struct config_auth* c,
|
||||
int with_http);
|
||||
|
||||
/** xfer nextprobe timeout callback, this is part of task_nextprobe */
|
||||
void auth_xfer_timer(void* arg);
|
||||
|
||||
/** callback for commpoint udp replies to task_probe */
|
||||
int auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err,
|
||||
struct comm_reply* repinfo);
|
||||
/** callback for task_transfer tcp connections */
|
||||
int auth_xfer_transfer_tcp_callback(struct comm_point* c, void* arg, int err,
|
||||
struct comm_reply* repinfo);
|
||||
/** callback for task_transfer http connections */
|
||||
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);
|
||||
/** 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);
|
||||
/** 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);
|
||||
|
||||
/*
|
||||
* Compares two 32-bit serial numbers as defined in RFC1982. Returns
|
||||
* <0 if a < b, 0 if a == b, and >0 if a > b. The result is undefined
|
||||
* if a != b but neither is greater or smaller (see RFC1982 section
|
||||
* 3.2.).
|
||||
*/
|
||||
int compare_serial(uint32_t a, uint32_t b);
|
||||
|
||||
#endif /* SERVICES_AUTHZONE_H */
|
||||
Vendored
+109
-23
@@ -41,6 +41,7 @@
|
||||
#include "config.h"
|
||||
#include "iterator/iter_delegpt.h"
|
||||
#include "validator/val_nsec.h"
|
||||
#include "validator/val_utils.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "util/data/msgreply.h"
|
||||
@@ -98,16 +99,61 @@ store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
|
||||
}
|
||||
}
|
||||
/* no break: also copy key item */
|
||||
/* the line below is matched by gcc regex and silences
|
||||
* the fallthrough warning */
|
||||
/* fallthrough */
|
||||
case 1: /* ref updated, item inserted */
|
||||
rep->rrsets[i] = rep->ref[i].key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** delete message from message cache */
|
||||
static void
|
||||
msg_cache_remove(struct module_env* env, uint8_t* qname, size_t qnamelen,
|
||||
uint16_t qtype, uint16_t qclass, uint16_t flags)
|
||||
{
|
||||
struct query_info k;
|
||||
hashvalue_type h;
|
||||
|
||||
k.qname = qname;
|
||||
k.qname_len = qnamelen;
|
||||
k.qtype = qtype;
|
||||
k.qclass = qclass;
|
||||
k.local_alias = NULL;
|
||||
h = query_info_hash(&k, flags);
|
||||
slabhash_remove(env->msg_cache, h, &k);
|
||||
}
|
||||
|
||||
/** remove servfail msg cache entry */
|
||||
static void
|
||||
msg_del_servfail(struct module_env* env, struct query_info* qinfo,
|
||||
uint32_t flags)
|
||||
{
|
||||
struct msgreply_entry* e;
|
||||
/* see if the entry is servfail, and then remove it, so that
|
||||
* lookups move from the cacheresponse stage to the recursionresponse
|
||||
* stage */
|
||||
e = msg_cache_lookup(env, qinfo->qname, qinfo->qname_len,
|
||||
qinfo->qtype, qinfo->qclass, flags, 0, 0);
|
||||
if(!e) return;
|
||||
/* we don't check for the ttl here, also expired servfail entries
|
||||
* are removed. If the user uses serve-expired, they would still be
|
||||
* used to answer from cache */
|
||||
if(FLAGS_GET_RCODE(((struct reply_info*)e->entry.data)->flags)
|
||||
!= LDNS_RCODE_SERVFAIL) {
|
||||
lock_rw_unlock(&e->entry.lock);
|
||||
return;
|
||||
}
|
||||
lock_rw_unlock(&e->entry.lock);
|
||||
msg_cache_remove(env, qinfo->qname, qinfo->qname_len, qinfo->qtype,
|
||||
qinfo->qclass, flags);
|
||||
}
|
||||
|
||||
void
|
||||
dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
hashvalue_type hash, struct reply_info* rep, time_t leeway, int pside,
|
||||
struct reply_info* qrep, struct regional* region)
|
||||
struct reply_info* qrep, uint32_t flags, struct regional* region)
|
||||
{
|
||||
struct msgreply_entry* e;
|
||||
time_t ttl = rep->ttl;
|
||||
@@ -123,11 +169,17 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
* unnecessary, because the cache gets locked per rrset. */
|
||||
reply_info_set_ttls(rep, *env->now);
|
||||
store_rrsets(env, rep, *env->now, leeway, pside, qrep, region);
|
||||
if(ttl == 0) {
|
||||
if(ttl == 0 && !(flags & DNSCACHE_STORE_ZEROTTL)) {
|
||||
/* we do not store the message, but we did store the RRs,
|
||||
* which could be useful for delegation information */
|
||||
verbose(VERB_ALGO, "TTL 0: dropped msg from cache");
|
||||
free(rep);
|
||||
/* if the message is SERVFAIL in cache, remove that SERVFAIL,
|
||||
* so that the TTL 0 response can be returned for future
|
||||
* responses (i.e. don't get answered by the servfail from
|
||||
* cache, but instead go to recursion to get this TTL0
|
||||
* response). */
|
||||
msg_del_servfail(env, qinfo, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -182,7 +234,7 @@ addr_to_additional(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
}
|
||||
|
||||
/** lookup message in message cache */
|
||||
static struct msgreply_entry*
|
||||
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)
|
||||
{
|
||||
@@ -391,8 +443,7 @@ dns_msg_authadd(struct dns_msg* msg, struct regional* region,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** add rrset to answer section */
|
||||
static int
|
||||
int
|
||||
dns_msg_ansadd(struct dns_msg* msg, struct regional* region,
|
||||
struct ub_packed_rrset_key* rrset, time_t now)
|
||||
{
|
||||
@@ -564,7 +615,7 @@ rrset_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
/** synthesize DNAME+CNAME response from cached DNAME item */
|
||||
static struct dns_msg*
|
||||
synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
time_t now, struct query_info* q)
|
||||
time_t now, struct query_info* q, enum sec_status* sec_status)
|
||||
{
|
||||
struct dns_msg* msg;
|
||||
struct ub_packed_rrset_key* ck;
|
||||
@@ -576,8 +627,9 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
return NULL;
|
||||
/* only allow validated (with DNSSEC) DNAMEs used from cache
|
||||
* for insecure DNAMEs, query again. */
|
||||
if(d->security != sec_status_secure)
|
||||
return NULL;
|
||||
*sec_status = d->security;
|
||||
/* return sec status, so the status of the CNAME can be checked
|
||||
* by the calling routine. */
|
||||
msg = gen_dns_msg(region, q, 2); /* DNAME + CNAME RRset */
|
||||
if(!msg)
|
||||
return NULL;
|
||||
@@ -707,7 +759,8 @@ fill_any(struct module_env* env,
|
||||
struct dns_msg*
|
||||
dns_cache_lookup(struct module_env* env,
|
||||
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
|
||||
uint16_t flags, struct regional* region, struct regional* scratch)
|
||||
uint16_t flags, struct regional* region, struct regional* scratch,
|
||||
int no_partial)
|
||||
{
|
||||
struct lruhash_entry* e;
|
||||
struct query_info k;
|
||||
@@ -739,26 +792,59 @@ dns_cache_lookup(struct module_env* env,
|
||||
/* see if a DNAME exists. Checked for first, to enforce that DNAMEs
|
||||
* are more important, the CNAME is resynthesized and thus
|
||||
* consistent with the DNAME */
|
||||
if( (rrset=find_closest_of_type(env, qname, qnamelen, qclass, now,
|
||||
if(!no_partial &&
|
||||
(rrset=find_closest_of_type(env, qname, qnamelen, qclass, now,
|
||||
LDNS_RR_TYPE_DNAME, 1))) {
|
||||
/* synthesize a DNAME+CNAME message based on this */
|
||||
struct dns_msg* msg = synth_dname_msg(rrset, region, now, &k);
|
||||
enum sec_status sec_status = sec_status_unchecked;
|
||||
struct dns_msg* msg = synth_dname_msg(rrset, region, now, &k,
|
||||
&sec_status);
|
||||
if(msg) {
|
||||
struct ub_packed_rrset_key* cname_rrset;
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
/* now, after unlocking the DNAME rrset lock,
|
||||
* check the sec_status, and see if we need to look
|
||||
* up the CNAME record associated before it can
|
||||
* be used */
|
||||
/* normally, only secure DNAMEs allowed from cache*/
|
||||
if(sec_status == sec_status_secure)
|
||||
return msg;
|
||||
/* but if we have a CNAME cached with this name, then we
|
||||
* have previously already allowed this name to pass.
|
||||
* the next cache lookup is going to fetch that CNAME itself,
|
||||
* but it is better to have the (unsigned)DNAME + CNAME in
|
||||
* that case */
|
||||
cname_rrset = rrset_cache_lookup(
|
||||
env->rrset_cache, qname, qnamelen,
|
||||
LDNS_RR_TYPE_CNAME, qclass, 0, now, 0);
|
||||
if(cname_rrset) {
|
||||
/* CNAME already synthesized by
|
||||
* synth_dname_msg routine, so we can
|
||||
* straight up return the msg */
|
||||
lock_rw_unlock(&cname_rrset->entry.lock);
|
||||
return msg;
|
||||
}
|
||||
} else {
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
return msg;
|
||||
}
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
}
|
||||
|
||||
/* see if we have CNAME for this domain,
|
||||
* but not for DS records (which are part of the parent) */
|
||||
if( qtype != LDNS_RR_TYPE_DS &&
|
||||
if(!no_partial && qtype != LDNS_RR_TYPE_DS &&
|
||||
(rrset=rrset_cache_lookup(env->rrset_cache, qname, qnamelen,
|
||||
LDNS_RR_TYPE_CNAME, qclass, 0, now, 0))) {
|
||||
struct dns_msg* msg = rrset_msg(rrset, region, now, &k);
|
||||
if(msg) {
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
return msg;
|
||||
uint8_t* wc = NULL;
|
||||
size_t wl;
|
||||
/* if the rrset is not a wildcard expansion, with wcname */
|
||||
/* because, if we return that CNAME rrset on its own, it is
|
||||
* missing the NSEC or NSEC3 proof */
|
||||
if(!(val_rrset_wildcard(rrset, &wc, &wl) && wc != NULL)) {
|
||||
struct dns_msg* msg = rrset_msg(rrset, region, now, &k);
|
||||
if(msg) {
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
}
|
||||
@@ -832,17 +918,17 @@ dns_cache_lookup(struct module_env* env,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
struct reply_info* msgrep, int is_referral, time_t leeway, int pside,
|
||||
struct regional* region, uint16_t flags)
|
||||
struct regional* region, uint32_t flags)
|
||||
{
|
||||
struct reply_info* rep = NULL;
|
||||
/* alloc, malloc properly (not in region, like msg is) */
|
||||
rep = reply_info_copy(msgrep, env->alloc, NULL);
|
||||
if(!rep)
|
||||
return 0;
|
||||
/* ttl must be relative ;i.e. 0..86400 not time(0)+86400.
|
||||
/* ttl must be relative ;i.e. 0..86400 not time(0)+86400.
|
||||
* the env->now is added to message and RRsets in this routine. */
|
||||
/* the leeway is used to invalidate other rrsets earlier */
|
||||
|
||||
@@ -880,9 +966,9 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
* Not AA from cache. Not CD in cache (depends on client bit). */
|
||||
rep->flags |= (BIT_RA | BIT_QR);
|
||||
rep->flags &= ~(BIT_AA | BIT_CD);
|
||||
h = query_info_hash(&qinf, flags);
|
||||
h = query_info_hash(&qinf, (uint16_t)flags);
|
||||
dns_cache_store_msg(env, &qinf, h, rep, leeway, pside, msgrep,
|
||||
region);
|
||||
flags, region);
|
||||
/* qname is used inside query_info_entrysetup, and set to
|
||||
* NULL. If it has not been used, free it. free(0) is safe. */
|
||||
free(qinf.qname);
|
||||
|
||||
Vendored
+33
-3
@@ -49,6 +49,12 @@ struct reply_info;
|
||||
struct regional;
|
||||
struct delegpt;
|
||||
|
||||
/** Flags to control behavior of dns_cache_store() and dns_cache_store_msg().
|
||||
* Must be an unsigned 32-bit value larger than 0xffff */
|
||||
|
||||
/** Allow caching a DNS message with a zero TTL. */
|
||||
#define DNSCACHE_STORE_ZEROTTL 0x100000
|
||||
|
||||
/**
|
||||
* Region allocated message reply
|
||||
*/
|
||||
@@ -80,11 +86,13 @@ struct dns_msg {
|
||||
* @param region: region to allocate better entries from cache into.
|
||||
* (used when is_referral is false).
|
||||
* @param flags: flags with BIT_CD for AAAA queries in dns64 translation.
|
||||
* The higher 16 bits are used internally to customize the cache policy.
|
||||
* (See DNSCACHE_STORE_xxx flags).
|
||||
* @return 0 on alloc error (out of memory).
|
||||
*/
|
||||
int dns_cache_store(struct module_env* env, struct query_info* qinf,
|
||||
struct reply_info* rep, int is_referral, time_t leeway, int pside,
|
||||
struct regional* region, uint16_t flags);
|
||||
struct regional* region, uint32_t flags);
|
||||
|
||||
/**
|
||||
* Store message in the cache. Stores in message cache and rrset cache.
|
||||
@@ -103,11 +111,12 @@ int dns_cache_store(struct module_env* env, struct query_info* qinf,
|
||||
* from the parentside of the zonecut. This means that the type NS
|
||||
* can be updated to full TTL even in prefetch situations.
|
||||
* @param qrep: message that can be altered with better rrs from cache.
|
||||
* @param flags: customization flags for the cache policy.
|
||||
* @param region: to allocate into for qmsg.
|
||||
*/
|
||||
void dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
hashvalue_type hash, struct reply_info* rep, time_t leeway, int pside,
|
||||
struct reply_info* qrep, struct regional* region);
|
||||
struct reply_info* qrep, uint32_t flags, struct regional* region);
|
||||
|
||||
/**
|
||||
* Find a delegation from the cache.
|
||||
@@ -150,13 +159,16 @@ struct dns_msg* tomsg(struct module_env* env, struct query_info* q,
|
||||
* @param flags: flags with BIT_CD for AAAA queries in dns64 translation.
|
||||
* @param region: where to allocate result.
|
||||
* @param scratch: where to allocate temporary data.
|
||||
* @param no_partial: if true, only complete messages and not a partial
|
||||
* one (with only the start of the CNAME chain and not the rest).
|
||||
* @return new response message (alloced in region, rrsets do not have IDs).
|
||||
* or NULL on error or if not found in cache.
|
||||
* TTLs are made relative to the current time.
|
||||
*/
|
||||
struct dns_msg* dns_cache_lookup(struct module_env* env,
|
||||
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
|
||||
uint16_t flags, struct regional* region, struct regional* scratch);
|
||||
uint16_t flags, struct regional* region, struct regional* scratch,
|
||||
int no_partial);
|
||||
|
||||
/**
|
||||
* find and add A and AAAA records for missing nameservers in delegpt
|
||||
@@ -195,6 +207,18 @@ struct dns_msg* dns_msg_create(uint8_t* qname, size_t qnamelen, uint16_t qtype,
|
||||
int dns_msg_authadd(struct dns_msg* msg, struct regional* region,
|
||||
struct ub_packed_rrset_key* rrset, time_t now);
|
||||
|
||||
/**
|
||||
* Add rrset to authority section in unpacked dns_msg message. Must have enough
|
||||
* space left, does not grow the array.
|
||||
* @param msg: msg to put it in.
|
||||
* @param region: region to alloc in
|
||||
* @param rrset: to add in authority section
|
||||
* @param now: now.
|
||||
* @return true if worked, false on fail
|
||||
*/
|
||||
int dns_msg_ansadd(struct dns_msg* msg, struct regional* region,
|
||||
struct ub_packed_rrset_key* rrset, time_t now);
|
||||
|
||||
/**
|
||||
* Adjust the prefetch_ttl for a cached message. This adds a value to the
|
||||
* prefetch ttl - postponing the time when it will be prefetched for future
|
||||
@@ -208,4 +232,10 @@ int dns_msg_authadd(struct dns_msg* msg, struct regional* region,
|
||||
int dns_cache_prefetch_adjust(struct module_env* env, struct query_info* qinfo,
|
||||
time_t adjust, uint16_t flags);
|
||||
|
||||
/** lookup message in message cache
|
||||
* the returned nonNULL entry is locked and has to be unlocked by the caller */
|
||||
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);
|
||||
|
||||
#endif /* SERVICES_CACHE_DNS_H */
|
||||
|
||||
Vendored
+18
-16
@@ -232,24 +232,22 @@ infra_create(struct config_file* cfg)
|
||||
infra->host_ttl = cfg->host_ttl;
|
||||
name_tree_init(&infra->domain_limits);
|
||||
infra_dp_ratelimit = cfg->ratelimit;
|
||||
if(cfg->ratelimit != 0) {
|
||||
infra->domain_rates = slabhash_create(cfg->ratelimit_slabs,
|
||||
INFRA_HOST_STARTSIZE, cfg->ratelimit_size,
|
||||
&rate_sizefunc, &rate_compfunc, &rate_delkeyfunc,
|
||||
&rate_deldatafunc, NULL);
|
||||
if(!infra->domain_rates) {
|
||||
infra_delete(infra);
|
||||
return NULL;
|
||||
}
|
||||
/* insert config data into ratelimits */
|
||||
if(!infra_ratelimit_cfg_insert(infra, cfg)) {
|
||||
infra_delete(infra);
|
||||
return NULL;
|
||||
}
|
||||
name_tree_init_parents(&infra->domain_limits);
|
||||
infra->domain_rates = slabhash_create(cfg->ratelimit_slabs,
|
||||
INFRA_HOST_STARTSIZE, cfg->ratelimit_size,
|
||||
&rate_sizefunc, &rate_compfunc, &rate_delkeyfunc,
|
||||
&rate_deldatafunc, NULL);
|
||||
if(!infra->domain_rates) {
|
||||
infra_delete(infra);
|
||||
return NULL;
|
||||
}
|
||||
/* insert config data into ratelimits */
|
||||
if(!infra_ratelimit_cfg_insert(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->ratelimit_slabs,
|
||||
infra->client_ip_rates = slabhash_create(cfg->ip_ratelimit_slabs,
|
||||
INFRA_HOST_STARTSIZE, cfg->ip_ratelimit_size, &ip_rate_sizefunc,
|
||||
&ip_rate_compfunc, &ip_rate_delkeyfunc, &ip_rate_deldatafunc, NULL);
|
||||
if(!infra->client_ip_rates) {
|
||||
@@ -893,6 +891,8 @@ int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name,
|
||||
|
||||
/* find ratelimit */
|
||||
lim = infra_find_ratelimit(infra, name, namelen);
|
||||
if(!lim)
|
||||
return 1; /* disabled for this domain */
|
||||
|
||||
/* find or insert ratedata */
|
||||
entry = infra_find_ratedata(infra, name, namelen, 1);
|
||||
@@ -941,6 +941,8 @@ int infra_ratelimit_exceeded(struct infra_cache* infra, uint8_t* name,
|
||||
|
||||
/* find ratelimit */
|
||||
lim = infra_find_ratelimit(infra, name, namelen);
|
||||
if(!lim)
|
||||
return 0; /* disabled for this domain */
|
||||
|
||||
/* find current rate */
|
||||
entry = infra_find_ratedata(infra, name, namelen, 0);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user