mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
Compare commits
722
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cdcb7cf09 | ||
|
|
3a9bb34d14 | ||
|
|
1dff48d188 | ||
|
|
e00e9d2839 | ||
|
|
5361b081d3 | ||
|
|
e2786e481a | ||
|
|
2c6462c943 | ||
|
|
d29761322f | ||
|
|
4b3fd4f789 | ||
|
|
ccebf0ff92 | ||
|
|
4bc1bfeb20 | ||
|
|
c3f6ca3997 | ||
|
|
79ffc1ab81 | ||
|
|
742256f2c7 | ||
|
|
239b552b6d | ||
|
|
9aaff22d88 | ||
|
|
e66964bfb3 | ||
|
|
7f0542f674 | ||
|
|
a8e468fc67 | ||
|
|
033ad37837 | ||
|
|
18f2fc28de | ||
|
|
94290ece06 | ||
|
|
f700558dc0 | ||
|
|
9c4bbfd37d | ||
|
|
1ade6965b2 | ||
|
|
b44780b22c | ||
|
|
508ea86578 | ||
|
|
5e5e89b9f5 | ||
|
|
6280983293 | ||
|
|
99cb5c6968 | ||
|
|
83f5814a07 | ||
|
|
940f6d98de | ||
|
|
b790f02df7 | ||
|
|
093b8b0c5a | ||
|
|
47183cc7ef | ||
|
|
44aeac1fc9 | ||
|
|
ca7ded0457 | ||
|
|
04abceeafa | ||
|
|
bbe6cb922a | ||
|
|
a9d248e7c9 | ||
|
|
f9762ba453 | ||
|
|
3b78588def | ||
|
|
217ef3d9a3 | ||
|
|
9046a52364 | ||
|
|
c5af4ce159 | ||
|
|
ca8e258cde | ||
|
|
07470115e5 | ||
|
|
061e2dd431 | ||
|
|
76f273aed5 | ||
|
|
fa94a9753d | ||
|
|
f82edc1b64 | ||
|
|
3c55073799 | ||
|
|
85c915f116 | ||
|
|
d16524d39a | ||
|
|
b212b302e6 | ||
|
|
0f1aa80123 | ||
|
|
68e7d81863 | ||
|
|
03c4ee417a | ||
|
|
482fbf3872 | ||
|
|
d6aba21ac4 | ||
|
|
d4f49a7a40 | ||
|
|
6cab3a1dda | ||
|
|
f37bd4f2ce | ||
|
|
64b28585e0 | ||
|
|
6b1222dcb6 | ||
|
|
44e894b6c2 | ||
|
|
4943101c09 | ||
|
|
c7872942ac | ||
|
|
1467c5de52 | ||
|
|
097c70be91 | ||
|
|
87ded67cb6 | ||
|
|
98b6f90637 | ||
|
|
b9ed797a22 | ||
|
|
25096aa3ab | ||
|
|
42e23da129 | ||
|
|
cd8e4a0bc5 | ||
|
|
d051dfaf19 | ||
|
|
f2da5c6867 | ||
|
|
97456b8f4c | ||
|
|
6ba973a8bd | ||
|
|
7090975243 | ||
|
|
62f3b7bb93 | ||
|
|
ccf4099366 | ||
|
|
15c805677c | ||
|
|
15aacbe89b | ||
|
|
452b7fce3a | ||
|
|
598beb1b06 | ||
|
|
06a3f735d7 | ||
|
|
eb03758c79 | ||
|
|
c42a74b77c | ||
|
|
8903dd175a | ||
|
|
5c73dbdbc0 | ||
|
|
277b1a1c2d | ||
|
|
da1bd6fd3f | ||
|
|
fe56d9e504 | ||
|
|
85016da2cb | ||
|
|
159d5a18b6 | ||
|
|
b375ba3455 | ||
|
|
65cc9f1dd1 | ||
|
|
43ab18d6ed | ||
|
|
aafed76b0f | ||
|
|
0a1195f690 | ||
|
|
ea158af48d | ||
|
|
6dd1dbd09f | ||
|
|
3d4f037f53 | ||
|
|
3930e23b8c | ||
|
|
6819016a83 | ||
|
|
2d2c04c271 | ||
|
|
13a839d624 | ||
|
|
2bf79c2e65 | ||
|
|
53a448ffae | ||
|
|
d71a1ba0c2 | ||
|
|
e1a817338e | ||
|
|
cf147df593 | ||
|
|
279f409636 | ||
|
|
a0db316445 | ||
|
|
8e472aa8c4 | ||
|
|
ec452bed83 | ||
|
|
d9a2a36049 | ||
|
|
1b08416dbe | ||
|
|
1c0f5a8aba | ||
|
|
bafc5741ba | ||
|
|
eb926f15da | ||
|
|
b441875206 | ||
|
|
8e20d58fa8 | ||
|
|
fa3337d42a | ||
|
|
0d5441bd8a | ||
|
|
d17f39416b | ||
|
|
4e92719611 | ||
|
|
fc52ee5aca | ||
|
|
ac103fc5bd | ||
|
|
af71677114 | ||
|
|
6e46110ae8 | ||
|
|
82ebbe32d1 | ||
|
|
1736d8078a | ||
|
|
57199f80c9 | ||
|
|
d7172c55ed | ||
|
|
9429092966 | ||
|
|
7f6827cc97 | ||
|
|
773d8e3b84 | ||
|
|
682ff957ed | ||
|
|
c90d6d2538 | ||
|
|
8e1cb52458 | ||
|
|
987c707a4d | ||
|
|
eac4a9604c | ||
|
|
9bbc6f4b56 | ||
|
|
718dcce317 | ||
|
|
08835e01ee | ||
|
|
d64b14cff9 | ||
|
|
943f8f43b9 | ||
|
|
7a58fdcebc | ||
|
|
db6cd0a635 | ||
|
|
03a7425ead | ||
|
|
d25268b7ee | ||
|
|
e789dac9a1 | ||
|
|
850525139b | ||
|
|
db33e4dbf6 | ||
|
|
05aaa8a138 | ||
|
|
09b9ea04a3 | ||
|
|
358fd2ad07 | ||
|
|
14059dca14 | ||
|
|
388d0639bc | ||
|
|
e8050a5587 | ||
|
|
c352ee2e85 | ||
|
|
9117191d44 | ||
|
|
924789d877 | ||
|
|
8c2f658cd1 | ||
|
|
8cafd0e379 | ||
|
|
ad2fa5c810 | ||
|
|
bec8d15cd0 | ||
|
|
dff630c788 | ||
|
|
30038d8fa6 | ||
|
|
71e85ee6fb | ||
|
|
b54efa5c69 | ||
|
|
c480290a30 | ||
|
|
c1d79638c4 | ||
|
|
6f6ccee95b | ||
|
|
c44ef11de5 | ||
|
|
9c8ac75026 | ||
|
|
31f071db25 | ||
|
|
b5337c1e05 | ||
|
|
2e26ec2d01 | ||
|
|
cf8ee796c9 | ||
|
|
8b078cc509 | ||
|
|
589924e36c | ||
|
|
fd9aa53370 | ||
|
|
6dd2c0467e | ||
|
|
a7ec2af62a | ||
|
|
bbfb2f2202 | ||
|
|
1238b7979f | ||
|
|
1f29a98366 | ||
|
|
0916e1d0ea | ||
|
|
65ad15da56 | ||
|
|
5ae8bec719 | ||
|
|
e0fd0ef80c | ||
|
|
8e62925ffb | ||
|
|
e7282a291b | ||
|
|
fa909b6cc7 | ||
|
|
5fa08a0be9 | ||
|
|
1cf44b0b5c | ||
|
|
111ef6f862 | ||
|
|
33e6deb675 | ||
|
|
1aa1c1404c | ||
|
|
694f02f1df | ||
|
|
9761d0c6de | ||
|
|
3b35e412f5 | ||
|
|
35172e89f4 | ||
|
|
eb29370697 | ||
|
|
01f3e90871 | ||
|
|
7bdae2d545 | ||
|
|
ae666ea203 | ||
|
|
557aad4b72 | ||
|
|
bbb583e754 | ||
|
|
2824d0ad52 | ||
|
|
6dfa0d643b | ||
|
|
3395637700 | ||
|
|
29ce27f300 | ||
|
|
e3e6246860 | ||
|
|
c8696005a7 | ||
|
|
fc7f057d0b | ||
|
|
1befacc444 | ||
|
|
a1c76554a2 | ||
|
|
cf1d2135e1 | ||
|
|
1cee11cba8 | ||
|
|
ae5d794c47 | ||
|
|
a08cf3c4e5 | ||
|
|
8f5596f643 | ||
|
|
a798dcb5bd | ||
|
|
939c103a73 | ||
|
|
ef4d9a1ecb | ||
|
|
9a0b040403 | ||
|
|
b8b2ce58d0 | ||
|
|
6a918b841f | ||
|
|
115c36a94e | ||
|
|
03c34b695f | ||
|
|
aa0536dcb5 | ||
|
|
28131d5845 | ||
|
|
69aafe3a1c | ||
|
|
2479955f9f | ||
|
|
9b47af529e | ||
|
|
11f5e16932 | ||
|
|
3d5cef932e | ||
|
|
0f825eb283 | ||
|
|
7ea69fe9c2 | ||
|
|
83367411ef | ||
|
|
51810c1408 | ||
|
|
ddddbf284f | ||
|
|
28c9738062 | ||
|
|
cefc027dbc | ||
|
|
d66ff13f9c | ||
|
|
01027a8322 | ||
|
|
086e31e88d | ||
|
|
ce63172a67 | ||
|
|
684429e6c8 | ||
|
|
80424bc16e | ||
|
|
a16c24b4f0 | ||
|
|
52f4247c48 | ||
|
|
dfd769b60c | ||
|
|
680b0d1cce | ||
|
|
bcdd32e7e1 | ||
|
|
b6d88c0b41 | ||
|
|
7cf757596c | ||
|
|
0f57f21ca2 | ||
|
|
68d82e9ce4 | ||
|
|
881f0ad30f | ||
|
|
d9ceec4005 | ||
|
|
f82a0847eb | ||
|
|
c3f5b5f773 | ||
|
|
b72d40f3dd | ||
|
|
c4cac78f10 | ||
|
|
164f86e377 | ||
|
|
c30e90b435 | ||
|
|
365f87a4a4 | ||
|
|
1af30c02fc | ||
|
|
83938e1d3b | ||
|
|
1daad9d9c0 | ||
|
|
af93d6033c | ||
|
|
46eeced066 | ||
|
|
70c8f304c2 | ||
|
|
1a2b78e51a | ||
|
|
54d0ed9a70 | ||
|
|
d56aef7b33 | ||
|
|
accc4a6f68 | ||
|
|
39de97e176 | ||
|
|
05e118b7d5 | ||
|
|
174604914f | ||
|
|
d265c02f69 | ||
|
|
17e5bba504 | ||
|
|
5ab9b9c8f9 | ||
|
|
09375e16e7 | ||
|
|
22290ac234 | ||
|
|
86c4c11ca2 | ||
|
|
63c07d13ce | ||
|
|
e8ec432579 | ||
|
|
ad864b0f7e | ||
|
|
cafc73a74f | ||
|
|
8c04c2e187 | ||
|
|
27b5d25703 | ||
|
|
dbd816fafb | ||
|
|
47653ae679 | ||
|
|
3d2156dacc | ||
|
|
25319e6737 | ||
|
|
7359d84e2f | ||
|
|
5f08751b3b | ||
|
|
60e8c22040 | ||
|
|
a742415b5c | ||
|
|
7b5262ccd2 | ||
|
|
c3da97fb35 | ||
|
|
844b5e71b1 | ||
|
|
172260232e | ||
|
|
c155cfc8bc | ||
|
|
447b6a1149 | ||
|
|
7070c35e11 | ||
|
|
dd03b668c5 | ||
|
|
1dff4206d5 | ||
|
|
bbe76430fe | ||
|
|
2c9bf883c9 | ||
|
|
59f5480df1 | ||
|
|
bc06ab0377 | ||
|
|
668bcfc499 | ||
|
|
9229c58c2f | ||
|
|
c89323ef93 | ||
|
|
4f68378640 | ||
|
|
ff23baadcc | ||
|
|
7c128d5013 | ||
|
|
b279987e9f | ||
|
|
8ecb52c532 | ||
|
|
28912ed659 | ||
|
|
f24f631838 | ||
|
|
42730aad99 | ||
|
|
8def9c1043 | ||
|
|
ecf4deedbe | ||
|
|
139ab47dc6 | ||
|
|
608f82a1cd | ||
|
|
5cbf6d059b | ||
|
|
a11fbf9ca0 | ||
|
|
30a339d1a8 | ||
|
|
92e1ec3444 | ||
|
|
62eea87455 | ||
|
|
30602d5d59 | ||
|
|
b23ed42b55 | ||
|
|
784d659e91 | ||
|
|
4df60a1343 | ||
|
|
ca38a8bd55 | ||
|
|
6e9d8fb22c | ||
|
|
35140bb612 | ||
|
|
de82245d3e | ||
|
|
3922eed584 | ||
|
|
efb9c02d54 | ||
|
|
04fa474ac3 | ||
|
|
3c87eb6c49 | ||
|
|
fcc7f9dae0 | ||
|
|
654a9160f5 | ||
|
|
682ad09bc4 | ||
|
|
ffb54322cb | ||
|
|
cc763c103b | ||
|
|
9053ee101d | ||
|
|
0b0a580422 | ||
|
|
b4a089ff0d | ||
|
|
ee6f5c5b51 | ||
|
|
c2299a3c5f | ||
|
|
255d669e58 | ||
|
|
c07e17fda3 | ||
|
|
d8928e1b19 | ||
|
|
01dd4a3568 | ||
|
|
1550bc65f3 | ||
|
|
4011c3861b | ||
|
|
58c2cc2740 | ||
|
|
87296966ae | ||
|
|
eed924d7be | ||
|
|
36d5a75848 | ||
|
|
5996f3b2a9 | ||
|
|
5e2a137562 | ||
|
|
5a154aeb78 | ||
|
|
5ecf75d623 | ||
|
|
797ef20155 | ||
|
|
f7b911b120 | ||
|
|
5feb72d1eb | ||
|
|
22ac684cd9 | ||
|
|
e2dc829258 | ||
|
|
f5a97a3e8f | ||
|
|
790cb51775 | ||
|
|
eaee99fa3b | ||
|
|
583eabb13e | ||
|
|
4a746142cf | ||
|
|
62230b5e04 | ||
|
|
b25ebf0be2 | ||
|
|
35c3a25896 | ||
|
|
6457e97255 | ||
|
|
05e9f914c5 | ||
|
|
046143af20 | ||
|
|
c71f33ead4 | ||
|
|
0bc54677db | ||
|
|
003658eea0 | ||
|
|
15b14306ed | ||
|
|
daab92e954 | ||
|
|
f378068b32 | ||
|
|
e9582487d9 | ||
|
|
c4c8a65ff2 | ||
|
|
f8796f94f4 | ||
|
|
ecb9db442d | ||
|
|
bc7ac1981a | ||
|
|
57f309ab1d | ||
|
|
dd8e44ac37 | ||
|
|
9997255caa | ||
|
|
79f4ca6a28 | ||
|
|
78cc3d8ae1 | ||
|
|
5e62750fcd | ||
|
|
289f13bc25 | ||
|
|
8c5b3d3c8f | ||
|
|
e430e8cef8 | ||
|
|
95da05c4bc | ||
|
|
c9dbc9907a | ||
|
|
6976832ffe | ||
|
|
2fe65ab2b5 | ||
|
|
4e8ae039fa | ||
|
|
c140638659 | ||
|
|
0b30fca935 | ||
|
|
f41a92daf5 | ||
|
|
93e8ff1bb0 | ||
|
|
04e45f98d6 | ||
|
|
08c580bb32 | ||
|
|
d748bca7de | ||
|
|
a3a1119f54 | ||
|
|
74505ea3f2 | ||
|
|
98c4161631 | ||
|
|
4bc34509fa | ||
|
|
f625bfdd15 | ||
|
|
93ffd44608 | ||
|
|
fcf1157fa4 | ||
|
|
488aee467a | ||
|
|
ba340cd07a | ||
|
|
1eb0eea744 | ||
|
|
25ea68e730 | ||
|
|
881245fa9d | ||
|
|
d7a6b3f914 | ||
|
|
f794810a5f | ||
|
|
758a42643a | ||
|
|
fdfa7b2793 | ||
|
|
a6b302f117 | ||
|
|
498cc8ab88 | ||
|
|
a032ac2f61 | ||
|
|
a72fe210ca | ||
|
|
573ce5a4de | ||
|
|
4dca799fbf | ||
|
|
f2ae3e8167 | ||
|
|
d0f2287d44 | ||
|
|
5533861c28 | ||
|
|
2bdb094f7b | ||
|
|
25a2e1da5a | ||
|
|
ea85e23516 | ||
|
|
c5fe4a8bf3 | ||
|
|
2e9fa86c76 | ||
|
|
e238b47b0a | ||
|
|
8cf752e577 | ||
|
|
2645b3e634 | ||
|
|
e5e0a1c857 | ||
|
|
b20f11c6a7 | ||
|
|
614cbb3e92 | ||
|
|
a0b58301ca | ||
|
|
9fb312ec32 | ||
|
|
c60c5d188e | ||
|
|
39bbb1c9e9 | ||
|
|
abe1057c41 | ||
|
|
32a9e3a225 | ||
|
|
e922bf901a | ||
|
|
66b2b90f43 | ||
|
|
a26f3d70dc | ||
|
|
2584075a94 | ||
|
|
68103c0ffb | ||
|
|
5d2ef1f925 | ||
|
|
1b773f682f | ||
|
|
bc54fa3e58 | ||
|
|
b3254d663b | ||
|
|
cf72b1a55d | ||
|
|
64fba64826 | ||
|
|
46345c0809 | ||
|
|
236d4cea25 | ||
|
|
cb978ff7be | ||
|
|
00ae321bf4 | ||
|
|
f3a4dad2c8 | ||
|
|
a2e4d07a4b | ||
|
|
fb4a5492da | ||
|
|
b3e4186cf2 | ||
|
|
45ef5b2ad6 | ||
|
|
cbe4354928 | ||
|
|
57b3409e2a | ||
|
|
322b68dbf4 | ||
|
|
c9d34cdecf | ||
|
|
67897d9c0d | ||
|
|
560e1d7e8a | ||
|
|
05c403f805 | ||
|
|
b7f7a772fb | ||
|
|
e9d7301b0a | ||
|
|
eb696dc385 | ||
|
|
f64d9d0e43 | ||
|
|
741e28309e | ||
|
|
7e315dafcf | ||
|
|
61be6bc238 | ||
|
|
cf7ececb83 | ||
|
|
c007b34cc1 | ||
|
|
224d547178 | ||
|
|
a29d966678 | ||
|
|
023c2b7dd9 | ||
|
|
dcb871a755 | ||
|
|
6f0a64d3a2 | ||
|
|
eb3114596c | ||
|
|
9f44640fa7 | ||
|
|
8ef0b0ff30 | ||
|
|
1c2a8d977c | ||
|
|
1797024a4e | ||
|
|
d75bca38f9 | ||
|
|
18523f7620 | ||
|
|
e399b79baa | ||
|
|
aac3c03f72 | ||
|
|
3b8cc374e7 | ||
|
|
8b274b92aa | ||
|
|
6b69130f36 | ||
|
|
c3f180eebb | ||
|
|
bf3c0e07d6 | ||
|
|
67eb2bbc32 | ||
|
|
cf19a76bf6 | ||
|
|
2a6a51c465 | ||
|
|
95db04a64c | ||
|
|
f26b55ea7e | ||
|
|
01c1bd13db | ||
|
|
8ec31ebbcc | ||
|
|
723a54f948 | ||
|
|
599aec4a23 | ||
|
|
9d66b48885 | ||
|
|
38c435e0c2 | ||
|
|
7b406bc70a | ||
|
|
89845bca03 | ||
|
|
78216e8d02 | ||
|
|
118c2c60d8 | ||
|
|
179ec8ad20 | ||
|
|
89f459c8a1 | ||
|
|
a34fe6ea8a | ||
|
|
6021182b64 | ||
|
|
e0a0eafef0 | ||
|
|
40f8fe2815 | ||
|
|
71cab42c9b | ||
|
|
2e149c4ced | ||
|
|
b701d70147 | ||
|
|
7963430481 | ||
|
|
ca36fd0110 | ||
|
|
4c4671a63f | ||
|
|
0db4fd57a7 | ||
|
|
f54f117885 | ||
|
|
21477ad68a | ||
|
|
dccbb4e518 | ||
|
|
45f74a1497 | ||
|
|
f10b2c0b33 | ||
|
|
1aa6413b32 | ||
|
|
d437ccb141 | ||
|
|
3070cf38f0 | ||
|
|
d2f9be56a5 | ||
|
|
317f97fe8e | ||
|
|
67c16277ee | ||
|
|
0066333685 | ||
|
|
6df29c32e4 | ||
|
|
f042f0dd5d | ||
|
|
391e1912de | ||
|
|
3c79358ff7 | ||
|
|
7d9caee481 | ||
|
|
c188d259d6 | ||
|
|
d332a19aa0 | ||
|
|
bfc0ddd0e0 | ||
|
|
13a1ed01fd | ||
|
|
4e8095062b | ||
|
|
fe6b110393 | ||
|
|
9633600fff | ||
|
|
2e24678204 | ||
|
|
a71d4eab36 | ||
|
|
885cde085a | ||
|
|
654d66d6a7 | ||
|
|
56b100a692 | ||
|
|
518504ff5c | ||
|
|
6351307ab4 | ||
|
|
0a848d686c | ||
|
|
595eab57de | ||
|
|
14f178e486 | ||
|
|
60035e31a2 | ||
|
|
3088075574 | ||
|
|
e76cd88470 | ||
|
|
5c0fe2154f | ||
|
|
76280e3b7e | ||
|
|
907ee56090 | ||
|
|
4ed18b1108 | ||
|
|
afc09709ad | ||
|
|
c1128af87e | ||
|
|
6325974a0b | ||
|
|
d1a68958a9 | ||
|
|
9d406d199f | ||
|
|
ecbeaed66c | ||
|
|
1601f2fd6f | ||
|
|
f98a1e2d32 | ||
|
|
cb3b649707 | ||
|
|
75c811cc35 | ||
|
|
d7fec82eaa | ||
|
|
6070d61076 | ||
|
|
96df860673 | ||
|
|
2eaed3573b | ||
|
|
b014aac438 | ||
|
|
1f0f85b59a | ||
|
|
b9603c178a | ||
|
|
780de8fd15 | ||
|
|
6575585b07 | ||
|
|
4df876c700 | ||
|
|
1f9172697c | ||
|
|
b65fa84ea5 | ||
|
|
4a38afe99b | ||
|
|
66b70b945b | ||
|
|
dc84dc08c0 | ||
|
|
4987cb525c | ||
|
|
165e6710e5 | ||
|
|
1e8551e1ce | ||
|
|
dd89196f9b | ||
|
|
8d71f58837 | ||
|
|
567e3933bc | ||
|
|
d57466c316 | ||
|
|
ba4ff40d9d | ||
|
|
1bd8583d3f | ||
|
|
8360afa15f | ||
|
|
da9ddfe2d1 | ||
|
|
d9e6fd3bac | ||
|
|
153fd4a7f6 | ||
|
|
66b24c3cb2 | ||
|
|
6ef058f9b0 | ||
|
|
6d77834955 | ||
|
|
233fb4466e | ||
|
|
e495a41bc1 | ||
|
|
1c49e9ac97 | ||
|
|
75bce22b30 | ||
|
|
4cc482e222 | ||
|
|
807a1c5b74 | ||
|
|
d9b715bbd7 | ||
|
|
b4b641807b | ||
|
|
271445fa4d | ||
|
|
22a622f8f5 | ||
|
|
816c6a513b | ||
|
|
7276cf7dd0 | ||
|
|
8f4957a0e0 | ||
|
|
5c4fbf10b1 | ||
|
|
cccba6e2c7 | ||
|
|
0a6ad89984 | ||
|
|
2adfe6bdba | ||
|
|
a29b2ad908 | ||
|
|
12e20eb5f4 | ||
|
|
339d94b643 | ||
|
|
52894339df | ||
|
|
3a754ae461 | ||
|
|
f12b7a8dd9 | ||
|
|
12c9c68dce | ||
|
|
8ccc01a2f6 | ||
|
|
fa3f1a60ec | ||
|
|
910bad74ea | ||
|
|
ef10cae6eb | ||
|
|
eca8b049ac | ||
|
|
35f3d4ecb1 | ||
|
|
109fbe2350 | ||
|
|
4c7edee5f3 | ||
|
|
e24f653871 | ||
|
|
3f598364c9 | ||
|
|
8e772c37b2 | ||
|
|
0a8c4943f5 | ||
|
|
ac59d6d96a | ||
|
|
1085e72135 | ||
|
|
8452c8cd5d | ||
|
|
3352f687cd | ||
|
|
4d10a37247 | ||
|
|
c79d732647 | ||
|
|
601355d9b0 | ||
|
|
0720e1a9a1 | ||
|
|
fa21f6e524 | ||
|
|
df9db1a0ee | ||
|
|
36c46a8f71 | ||
|
|
560f4aab03 | ||
|
|
bec7e7a552 | ||
|
|
553e2de09b | ||
|
|
e36a4b1bc5 | ||
|
|
8c8667d9f7 | ||
|
|
f13263d045 | ||
|
|
77f49a5510 | ||
|
|
8413dd946e | ||
|
|
18a7df3d5c | ||
|
|
9717ad2be8 | ||
|
|
efb19fd26a | ||
|
|
bc4770ea7d | ||
|
|
01792e928e | ||
|
|
11ecb5183b | ||
|
|
ad620622a5 | ||
|
|
5e9b6092d0 | ||
|
|
1e503c6430 | ||
|
|
5e1e389a15 | ||
|
|
8a3ef34194 | ||
|
|
e7939029f8 | ||
|
|
ac4534f3e0 | ||
|
|
dd8dcfb317 | ||
|
|
75565262f7 | ||
|
|
cd57530efd | ||
|
|
091050add6 | ||
|
|
42599b7044 | ||
|
|
ecd677ebbe | ||
|
|
367c2abbf3 | ||
|
|
6fb53c7c93 | ||
|
|
62228ae450 | ||
|
|
5dd34e6145 | ||
|
|
776643e6d7 | ||
|
|
50336bddbe | ||
|
|
e3d6aaf697 | ||
|
|
788cd9d6ee | ||
|
|
10880d861f | ||
|
|
147d47eee7 | ||
|
|
e56a5b72cb | ||
|
|
c6b987a816 | ||
|
|
e652a69a69 | ||
|
|
3668d64b47 | ||
|
|
6c7526f53b | ||
|
|
8c7781fb24 | ||
|
|
590facc3d8 | ||
|
|
03e53f14b0 |
+1045
-279
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,5 @@
|
||||
Unbound README
|
||||
* ./configure && make && make install
|
||||
* on BSDs and Solaris use gmake (GNU make).
|
||||
* You can use libevent if you want. libevent is useful when using
|
||||
many (10000) outgoing ports. By default max 256 ports are opened at
|
||||
the same time and the builtin alternative is equally capable and a
|
||||
|
||||
Vendored
+1277
-795
File diff suppressed because it is too large
Load Diff
+125
-27
@@ -2,7 +2,20 @@
|
||||
# Copyright 2009, Wouter Wijngaards, NLnet Labs.
|
||||
# BSD licensed.
|
||||
#
|
||||
# Version 8
|
||||
# Version 21
|
||||
# 2012-02-09 Fix AHX_MEMCMP_BROKEN with undef in compat/memcmp.h.
|
||||
# 2012-01-20 Fix COMPILER_FLAGS_UNBOUND for gcc 4.6.2 assigned-not-used-warns.
|
||||
# 2011-12-05 Fix getaddrinfowithincludes on windows with fedora16 mingw32-gcc.
|
||||
# Fix ACX_MALLOC for redefined malloc error.
|
||||
# Fix GETADDRINFO_WITH_INCLUDES to add -lws2_32
|
||||
# 2011-11-10 Fix FLTO test to not drop a.out in current directory.
|
||||
# 2011-11-01 Fix FLTO test for llvm on Lion.
|
||||
# 2011-08-01 Fix nonblock test (broken at v13).
|
||||
# 2011-08-01 Fix autoconf 2.68 warnings
|
||||
# 2011-06-23 Add ACX_CHECK_FLTO to check -flto.
|
||||
# 2010-08-16 Fix FLAG_OMITTED for AS_TR_CPP changes in autoconf-2.66.
|
||||
# 2010-07-02 Add check for ss_family (for minix).
|
||||
# 2010-04-26 Fix to use CPPFLAGS for CHECK_COMPILER_FLAGS.
|
||||
# 2010-03-01 Fix RPATH using CONFIG_COMMANDS to run at the very end.
|
||||
# 2010-02-18 WITH_SSL outputs the LIBSSL_LDFLAGS, LIBS, CPPFLAGS seperate, -ldl
|
||||
# 2010-02-01 added ACX_CHECK_MEMCMP_SIGNED, AHX_MEMCMP_BROKEN
|
||||
@@ -29,6 +42,7 @@
|
||||
# ACX_DETERMINE_EXT_FLAGS_UNBOUND - find out which flags enable BSD and POSIX.
|
||||
# ACX_CHECK_FORMAT_ATTRIBUTE - find cc printf format syntax.
|
||||
# ACX_CHECK_UNUSED_ATTRIBUTE - find cc variable unused syntax.
|
||||
# ACX_CHECK_FLTO - see if cc supports -flto and use it if so.
|
||||
# ACX_LIBTOOL_C_ONLY - create libtool for C only, improved.
|
||||
# ACX_TYPE_U_CHAR - u_char type.
|
||||
# ACX_TYPE_RLIM_T - rlim_t type.
|
||||
@@ -73,6 +87,7 @@
|
||||
# AHX_CONFIG_EXT_FLAGS - define the stripped extension flags
|
||||
# ACX_CHECK_MEMCMP_SIGNED - check if memcmp uses signed characters.
|
||||
# AHX_MEMCMP_BROKEN - replace memcmp func for CHECK_MEMCMP_SIGNED.
|
||||
# ACX_CHECK_SS_FAMILY - check for sockaddr_storage.ss_family
|
||||
#
|
||||
|
||||
dnl Escape backslashes as \\, for C:\ paths, for the C preprocessor defines.
|
||||
@@ -102,7 +117,7 @@ cache=`echo $1 | sed 'y%.=/+-%___p_%'`
|
||||
AC_CACHE_VAL(cv_prog_cc_flag_$cache,
|
||||
[
|
||||
echo 'void f(){}' >conftest.c
|
||||
if test -z "`$CC -$1 -c conftest.c 2>&1`"; then
|
||||
if test -z "`$CC $CPPFLAGS $CFLAGS -$1 -c conftest.c 2>&1`"; then
|
||||
eval "cv_prog_cc_flag_$cache=yes"
|
||||
else
|
||||
eval "cv_prog_cc_flag_$cache=no"
|
||||
@@ -146,18 +161,18 @@ AC_CACHE_VAL(cv_prog_cc_flag_needed_$cache,
|
||||
[
|
||||
echo '$2' > conftest.c
|
||||
echo 'void f(){}' >>conftest.c
|
||||
if test -z "`$CC $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then
|
||||
if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then
|
||||
eval "cv_prog_cc_flag_needed_$cache=no"
|
||||
else
|
||||
[
|
||||
if test -z "`$CC $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1`"; then
|
||||
if test -z "`$CC $CPPFLAGS $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1`"; then
|
||||
eval "cv_prog_cc_flag_needed_$cache=yes"
|
||||
else
|
||||
eval "cv_prog_cc_flag_needed_$cache=fail"
|
||||
#echo 'Test with flag fails too!'
|
||||
#cat conftest.c
|
||||
#echo "$CC $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1"
|
||||
#echo `$CC $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1`
|
||||
#echo "$CC $CPPFLAGS $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1"
|
||||
#echo `$CC $CPPFLAGS $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1`
|
||||
#exit 1
|
||||
fi
|
||||
]
|
||||
@@ -173,8 +188,8 @@ if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then
|
||||
AC_MSG_RESULT(no)
|
||||
#echo 'Test with flag is no!'
|
||||
#cat conftest.c
|
||||
#echo "$CC $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1"
|
||||
#echo `$CC $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1`
|
||||
#echo "$CC $CPPFLAGS $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1"
|
||||
#echo `$CC $CPPFLAGS $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1`
|
||||
#exit 1
|
||||
:
|
||||
$4
|
||||
@@ -246,6 +261,8 @@ int test() {
|
||||
a = getopt(2, opts, "a");
|
||||
a = isascii(32);
|
||||
str = gai_strerror(0);
|
||||
if(str && t && tv.tv_usec && msg.msg_control)
|
||||
a = 0;
|
||||
return a;
|
||||
}
|
||||
], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE"])
|
||||
@@ -281,6 +298,8 @@ int test() {
|
||||
a = getopt(2, opts, "a");
|
||||
a = isascii(32);
|
||||
str = gai_strerror(0);
|
||||
if(str && t && tv.tv_usec && msg.msg_control)
|
||||
a = 0;
|
||||
return a;
|
||||
}
|
||||
], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE"])
|
||||
@@ -347,6 +366,8 @@ int test() {
|
||||
const char* str = NULL;
|
||||
t = ctime_r(&time, buf);
|
||||
str = gai_strerror(0);
|
||||
if(t && str)
|
||||
a = 0;
|
||||
return a;
|
||||
}
|
||||
], [CFLAGS="$CFLAGS -D_POSIX_C_SOURCE=200112"])
|
||||
@@ -373,12 +394,32 @@ int test() {
|
||||
srandom(32);
|
||||
a = getopt(2, opts, "a");
|
||||
a = isascii(32);
|
||||
if(tv.tv_usec)
|
||||
a = 0;
|
||||
return a;
|
||||
}
|
||||
], [CFLAGS="$CFLAGS -D__EXTENSIONS__"])
|
||||
|
||||
])dnl End of ACX_DETERMINE_EXT_FLAGS_UNBOUND
|
||||
|
||||
dnl Check if CC supports -flto.
|
||||
dnl in a way that supports clang and suncc (that flag does something else,
|
||||
dnl but fails to link). It sets it in CFLAGS if it works.
|
||||
AC_DEFUN([ACX_CHECK_FLTO],
|
||||
[AC_MSG_CHECKING([if $CC supports -flto])
|
||||
BAKCFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -flto"
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], [
|
||||
if $CC $CFLAGS -o conftest conftest.c 2>&1 | grep "warning: no debug symbols in executable" >/dev/null; then
|
||||
CFLAGS="$BAKCFLAGS"
|
||||
AC_MSG_RESULT(no)
|
||||
else
|
||||
AC_MSG_RESULT(yes)
|
||||
fi
|
||||
rm -f conftest conftest.c conftest.o
|
||||
], [CFLAGS="$BAKCFLAGS" ; AC_MSG_RESULT(no)])
|
||||
])
|
||||
|
||||
dnl Check the printf-format attribute (if any)
|
||||
dnl result in HAVE_ATTR_FORMAT.
|
||||
dnl Make sure you also include the AHX_CONFIG_FORMAT_ATTRIBUTE.
|
||||
@@ -750,7 +791,7 @@ AC_DEFUN([ACX_CHECK_GETADDRINFO_WITH_INCLUDES],
|
||||
AC_MSG_CHECKING(for getaddrinfo)
|
||||
ac_cv_func_getaddrinfo=no
|
||||
AC_LINK_IFELSE(
|
||||
[
|
||||
[AC_LANG_SOURCE([[
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
@@ -764,14 +805,21 @@ int main() {
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
],
|
||||
]])],
|
||||
dnl this case on linux, solaris, bsd
|
||||
[ac_cv_func_getaddrinfo="yes"],
|
||||
[ac_cv_func_getaddrinfo="yes"
|
||||
dnl see if on windows
|
||||
if test "$ac_cv_header_windows_h" = "yes"; then
|
||||
AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
|
||||
USE_WINSOCK="1"
|
||||
LIBS="$LIBS -lws2_32"
|
||||
fi
|
||||
],
|
||||
dnl no quick getaddrinfo, try mingw32 and winsock2 library.
|
||||
ORIGLIBS="$LIBS"
|
||||
LIBS="$LIBS -lws2_32"
|
||||
AC_LINK_IFELSE(
|
||||
AC_LANG_PROGRAM(
|
||||
[AC_LANG_PROGRAM(
|
||||
[
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
#include <ws2tcpip.h>
|
||||
@@ -780,7 +828,7 @@ AC_LANG_PROGRAM(
|
||||
[
|
||||
(void)getaddrinfo(NULL, NULL, NULL, NULL);
|
||||
]
|
||||
),
|
||||
)],
|
||||
[
|
||||
ac_cv_func_getaddrinfo="yes"
|
||||
dnl already: LIBS="$LIBS -lws2_32"
|
||||
@@ -844,7 +892,8 @@ if echo $target | grep mingw32 >/dev/null; then
|
||||
AC_MSG_RESULT([no (windows)])
|
||||
AC_DEFINE([NONBLOCKING_IS_BROKEN], 1, [Define if the network stack does not fully support nonblocking io (causes lower performance).])
|
||||
else
|
||||
AC_RUN_IFELSE(AC_LANG_PROGRAM([
|
||||
AC_RUN_IFELSE([
|
||||
AC_LANG_SOURCE([[
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@@ -868,7 +917,9 @@ AC_RUN_IFELSE(AC_LANG_PROGRAM([
|
||||
#ifdef HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
],[[
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int port;
|
||||
int sfd, cfd;
|
||||
int num = 10;
|
||||
@@ -961,7 +1012,9 @@ AC_RUN_IFELSE(AC_LANG_PROGRAM([
|
||||
|
||||
close(sfd);
|
||||
close(cfd);
|
||||
]]), [
|
||||
return 0;
|
||||
}
|
||||
]])], [
|
||||
AC_MSG_RESULT([yes])
|
||||
], [
|
||||
AC_MSG_RESULT([no])
|
||||
@@ -1001,13 +1054,13 @@ AC_DEFUN([ACX_FUNC_IOCTLSOCKET],
|
||||
[
|
||||
# check ioctlsocket
|
||||
AC_MSG_CHECKING(for ioctlsocket)
|
||||
AC_LINK_IFELSE(AC_LANG_PROGRAM([
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
], [
|
||||
(void)ioctlsocket(0, 0, NULL);
|
||||
]), [
|
||||
])], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_IOCTLSOCKET, 1, [if the function 'ioctlsocket' is available])
|
||||
],[AC_MSG_RESULT(no)])
|
||||
@@ -1017,10 +1070,23 @@ dnl detect malloc and provide malloc compat prototype.
|
||||
dnl $1: unique name for compat code
|
||||
AC_DEFUN([ACX_FUNC_MALLOC],
|
||||
[
|
||||
AC_FUNC_MALLOC
|
||||
if test "$ac_cv_func_malloc_0_nonnull" = no; then
|
||||
AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])
|
||||
fi
|
||||
AC_MSG_CHECKING([for GNU libc compatible malloc])
|
||||
AC_RUN_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#if defined STDC_HEADERS || defined HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
char *malloc ();
|
||||
#endif
|
||||
]], [ if(malloc(0) != 0) return 1;])
|
||||
],
|
||||
[AC_MSG_RESULT([no])
|
||||
AC_LIBOBJ(malloc)
|
||||
AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])] ,
|
||||
[AC_MSG_RESULT([yes])
|
||||
AC_DEFINE([HAVE_MALLOC], 1, [If have GNU libc compatible malloc])],
|
||||
[AC_MSG_RESULT([no (crosscompile)])
|
||||
AC_LIBOBJ(malloc)
|
||||
AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])] )
|
||||
])
|
||||
|
||||
dnl Define fallback for fseeko and ftello if needed.
|
||||
@@ -1189,7 +1255,7 @@ AC_DEFUN([ACX_CFLAGS_STRIP],
|
||||
[
|
||||
if echo $CFLAGS | grep " $1" >/dev/null 2>&1; then
|
||||
CFLAGS="`echo $CFLAGS | sed -e 's/ $1//g'`"
|
||||
AC_DEFINE(AS_TR_CPP(OMITTED_$1), 1, Put $1 define in config.h)
|
||||
AC_DEFINE(m4_bpatsubst(OMITTED_$1,[[-=]],_), 1, Put $1 define in config.h)
|
||||
fi
|
||||
])
|
||||
|
||||
@@ -1220,7 +1286,7 @@ AC_DEFUN([AHX_CONFIG_FLAG_OMITTED],
|
||||
dnl Wrapper for AHX_CONFIG_FLAG_OMITTED for -D style flags
|
||||
dnl $1: the -DNAME or -DNAME=value string.
|
||||
AC_DEFUN([AHX_CONFIG_FLAG_EXT],
|
||||
[AHX_CONFIG_FLAG_OMITTED(AS_TR_CPP(OMITTED_$1),m4_bpatsubst(m4_bpatsubst($1,-D,),=.*$,),m4_if(m4_bregexp($1,=),-1,1,m4_bpatsubst($1,^.*=,)))
|
||||
[AHX_CONFIG_FLAG_OMITTED(m4_bpatsubst(OMITTED_$1,[[-=]],_),m4_bpatsubst(m4_bpatsubst($1,-D,),=.*$,),m4_if(m4_bregexp($1,=),-1,1,m4_bpatsubst($1,^.*=,)))
|
||||
])
|
||||
|
||||
dnl config.h part to define omitted cflags, use with ACX_STRIP_EXT_FLAGS.
|
||||
@@ -1261,12 +1327,44 @@ int main(void)
|
||||
dnl define memcmp to its replacement, pass unique id for program as arg
|
||||
AC_DEFUN([AHX_MEMCMP_BROKEN], [
|
||||
#ifdef MEMCMP_IS_BROKEN
|
||||
# ifdef memcmp
|
||||
# undef memcmp
|
||||
# endif
|
||||
#include "compat/memcmp.h"
|
||||
#define memcmp memcmp_$1
|
||||
int memcmp(const void *x, const void *y, size_t n);
|
||||
#endif
|
||||
])
|
||||
|
||||
dnl ACX_CHECK_SS_FAMILY - check for sockaddr_storage.ss_family
|
||||
AC_DEFUN([ACX_CHECK_SS_FAMILY],
|
||||
[AC_CHECK_MEMBER([struct sockaddr_storage.ss_family], [], [
|
||||
AC_CHECK_MEMBER([struct sockaddr_storage.__ss_family], [
|
||||
AC_DEFINE([ss_family], [__ss_family], [Fallback member name for socket family in struct sockaddr_storage])
|
||||
],, [AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
])
|
||||
], [AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
]) ])
|
||||
|
||||
dnl End of file
|
||||
|
||||
+6
-3
@@ -129,7 +129,7 @@ $ac_distutils_result])
|
||||
AC_MSG_CHECKING([for Python site-packages path])
|
||||
if test -z "$PYTHON_SITE_PKG"; then
|
||||
PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print distutils.sysconfig.get_python_lib(0,0);"`
|
||||
print distutils.sysconfig.get_python_lib(1,0);"`
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_SITE_PKG])
|
||||
AC_SUBST([PYTHON_SITE_PKG])
|
||||
@@ -164,8 +164,11 @@ $ac_distutils_result])
|
||||
AC_MSG_CHECKING([consistency of all components of python development environment])
|
||||
AC_LANG_PUSH([C])
|
||||
# save current global flags
|
||||
LIBS="$ac_save_LIBS $PYTHON_LDFLAGS"
|
||||
CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS"
|
||||
ac_save_LIBS="$LIBS"
|
||||
ac_save_CPPFLAGS="$CPPFLAGS"
|
||||
|
||||
LIBS="$LIBS $PYTHON_LDFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS"
|
||||
AC_TRY_LINK([
|
||||
#include <Python.h>
|
||||
],[
|
||||
|
||||
+4
-1
@@ -32,8 +32,11 @@ char *ctime_r(const time_t *timep, char *buf)
|
||||
}
|
||||
lock_basic_lock(&ctime_lock);
|
||||
result = ctime(timep);
|
||||
if(buf && result)
|
||||
if(buf && result) {
|
||||
if(strlen(result) > 10 && result[7]==' ' && result[8]=='0')
|
||||
result[8]=' '; /* fix error in windows ctime */
|
||||
strcpy(buf, result);
|
||||
}
|
||||
lock_basic_unlock(&ctime_lock);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -135,7 +135,9 @@ inet_ntop6(const u_char *src, char *dst, size_t size)
|
||||
for (i = 0; i < IN6ADDRSZ; i++)
|
||||
words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
|
||||
best.base = -1;
|
||||
best.len = 0;
|
||||
cur.base = -1;
|
||||
cur.len = 0;
|
||||
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
|
||||
if (words[i] == 0) {
|
||||
if (cur.base == -1)
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* memcmp.h: undef memcmp for compat.
|
||||
*
|
||||
* Copyright (c) 2012, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* See LICENSE for the license.
|
||||
*/
|
||||
#ifndef COMPAT_MEMCMP_H
|
||||
#define COMPAT_MEMCMP_H
|
||||
|
||||
#ifdef memcmp
|
||||
/* undef here otherwise autoheader messes it up in config.h */
|
||||
# undef memcmp
|
||||
#endif
|
||||
|
||||
#endif /* COMPAT_MEMCMP_H */
|
||||
@@ -0,0 +1,345 @@
|
||||
/** strptime workaround (for oa macos leopard)
|
||||
* This strptime follows the man strptime (2001-11-12)
|
||||
* conforming to SUSv2, POSIX.1-2001
|
||||
*
|
||||
* This very simple version of strptime has no:
|
||||
* - E alternatives
|
||||
* - O alternatives
|
||||
* - Glibc additions
|
||||
* - Does not process week numbers
|
||||
* - Does not properly processes year day
|
||||
*
|
||||
* LICENSE
|
||||
* Copyright (c) 2008, NLnet Labs, Matthijs Mekking
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 NLnetLabs 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 OWNER 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.
|
||||
**/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef HAVE_CONFIG_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#ifndef STRPTIME_WORKS
|
||||
|
||||
#define TM_YEAR_BASE 1900
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
static const char *abb_weekdays[] = {
|
||||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL
|
||||
};
|
||||
static const char *full_weekdays[] = {
|
||||
"Sunday", "Monday", "Tuesday", "Wednesday",
|
||||
"Thursday", "Friday", "Saturday", NULL
|
||||
};
|
||||
static const char *abb_months[] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL
|
||||
};
|
||||
static const char *full_months[] = {
|
||||
"January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December", NULL
|
||||
};
|
||||
static const char *ampm[] = {
|
||||
"am", "pm", NULL
|
||||
};
|
||||
|
||||
static int
|
||||
match_string(const char **buf, const char **strs)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; strs[i] != NULL; i++) {
|
||||
int len = strlen(strs[i]);
|
||||
if (strncasecmp (*buf, strs[i], len) == 0) {
|
||||
*buf += len;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
str2int(const char **buf, int max)
|
||||
{
|
||||
int ret=0, count=0;
|
||||
|
||||
while (*buf[0] != '\0' && isdigit(*buf[0]) && count<max) {
|
||||
ret = ret*10 + (*buf[0] - '0');
|
||||
(*buf)++;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (!count)
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Converts the character string s to values which are stored in tm
|
||||
* using the format specified by format
|
||||
**/
|
||||
char *
|
||||
unbound_strptime(const char *s, const char *format, struct tm *tm)
|
||||
{
|
||||
int c, ret;
|
||||
int split_year = 0;
|
||||
|
||||
while ((c = *format) != '\0') {
|
||||
/* whitespace, literal or format */
|
||||
if (isspace(c)) { /* whitespace */
|
||||
/** whitespace matches zero or more whitespace characters in the
|
||||
* input string.
|
||||
**/
|
||||
while (isspace(*s))
|
||||
s++;
|
||||
}
|
||||
else if (c == '%') { /* format */
|
||||
format++;
|
||||
c = *format;
|
||||
switch (c) {
|
||||
case '%': /* %% is converted to % */
|
||||
if (*s != c) {
|
||||
return NULL;
|
||||
}
|
||||
s++;
|
||||
break;
|
||||
case 'a': /* weekday name, abbreviated or full */
|
||||
case 'A':
|
||||
ret = match_string(&s, full_weekdays);
|
||||
if (ret < 0)
|
||||
ret = match_string(&s, abb_weekdays);
|
||||
if (ret < 0) {
|
||||
return NULL;
|
||||
}
|
||||
tm->tm_wday = ret;
|
||||
break;
|
||||
case 'b': /* month name, abbreviated or full */
|
||||
case 'B':
|
||||
case 'h':
|
||||
ret = match_string(&s, full_months);
|
||||
if (ret < 0)
|
||||
ret = match_string(&s, abb_months);
|
||||
if (ret < 0) {
|
||||
return NULL;
|
||||
}
|
||||
tm->tm_mon = ret;
|
||||
break;
|
||||
case 'c': /* date and time representation */
|
||||
if (!(s = unbound_strptime(s, "%x %X", tm))) {
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case 'C': /* century number */
|
||||
ret = str2int(&s, 2);
|
||||
if (ret < 0 || ret > 99) { /* must be in [00,99] */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (split_year) {
|
||||
tm->tm_year = ret*100 + (tm->tm_year%100);
|
||||
}
|
||||
else {
|
||||
tm->tm_year = ret*100 - TM_YEAR_BASE;
|
||||
split_year = 1;
|
||||
}
|
||||
break;
|
||||
case 'd': /* day of month */
|
||||
case 'e':
|
||||
ret = str2int(&s, 2);
|
||||
if (ret < 1 || ret > 31) { /* must be in [01,31] */
|
||||
return NULL;
|
||||
}
|
||||
tm->tm_mday = ret;
|
||||
break;
|
||||
case 'D': /* equivalent to %m/%d/%y */
|
||||
if (!(s = unbound_strptime(s, "%m/%d/%y", tm))) {
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case 'H': /* hour */
|
||||
ret = str2int(&s, 2);
|
||||
if (ret < 0 || ret > 23) { /* must be in [00,23] */
|
||||
return NULL;
|
||||
}
|
||||
tm->tm_hour = ret;
|
||||
break;
|
||||
case 'I': /* 12hr clock hour */
|
||||
ret = str2int(&s, 2);
|
||||
if (ret < 1 || ret > 12) { /* must be in [01,12] */
|
||||
return NULL;
|
||||
}
|
||||
if (ret == 12) /* actually [0,11] */
|
||||
ret = 0;
|
||||
tm->tm_hour = ret;
|
||||
break;
|
||||
case 'j': /* day of year */
|
||||
ret = str2int(&s, 2);
|
||||
if (ret < 1 || ret > 366) { /* must be in [001,366] */
|
||||
return NULL;
|
||||
}
|
||||
tm->tm_yday = ret;
|
||||
break;
|
||||
case 'm': /* month */
|
||||
ret = str2int(&s, 2);
|
||||
if (ret < 1 || ret > 12) { /* must be in [01,12] */
|
||||
return NULL;
|
||||
}
|
||||
/* months go from 0-11 */
|
||||
tm->tm_mon = (ret-1);
|
||||
break;
|
||||
case 'M': /* minute */
|
||||
ret = str2int(&s, 2);
|
||||
if (ret < 0 || ret > 59) { /* must be in [00,59] */
|
||||
return NULL;
|
||||
}
|
||||
tm->tm_min = ret;
|
||||
break;
|
||||
case 'n': /* arbitrary whitespace */
|
||||
case 't':
|
||||
while (isspace(*s))
|
||||
s++;
|
||||
break;
|
||||
case 'p': /* am pm */
|
||||
ret = match_string(&s, ampm);
|
||||
if (ret < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (tm->tm_hour < 0 || tm->tm_hour > 11) { /* %I */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ret == 1) /* pm */
|
||||
tm->tm_hour += 12;
|
||||
break;
|
||||
case 'r': /* equivalent of %I:%M:%S %p */
|
||||
if (!(s = unbound_strptime(s, "%I:%M:%S %p", tm))) {
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case 'R': /* equivalent of %H:%M */
|
||||
if (!(s = unbound_strptime(s, "%H:%M", tm))) {
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case 'S': /* seconds */
|
||||
ret = str2int(&s, 2);
|
||||
/* 60 may occur for leap seconds */
|
||||
/* earlier 61 was also allowed */
|
||||
if (ret < 0 || ret > 60) { /* must be in [00,60] */
|
||||
return NULL;
|
||||
}
|
||||
tm->tm_sec = ret;
|
||||
break;
|
||||
case 'T': /* equivalent of %H:%M:%S */
|
||||
if (!(s = unbound_strptime(s, "%H:%M:%S", tm))) {
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case 'U': /* week number, with the first Sun of Jan being w1 */
|
||||
ret = str2int(&s, 2);
|
||||
if (ret < 0 || ret > 53) { /* must be in [00,53] */
|
||||
return NULL;
|
||||
}
|
||||
/** it is hard (and not necessary for nsd) to determine time
|
||||
* data from week number.
|
||||
**/
|
||||
break;
|
||||
case 'w': /* day of week */
|
||||
ret = str2int(&s, 1);
|
||||
if (ret < 0 || ret > 6) { /* must be in [0,6] */
|
||||
return NULL;
|
||||
}
|
||||
tm->tm_wday = ret;
|
||||
break;
|
||||
case 'W': /* week number, with the first Mon of Jan being w1 */
|
||||
ret = str2int(&s, 2);
|
||||
if (ret < 0 || ret > 53) { /* must be in [00,53] */
|
||||
return NULL;
|
||||
}
|
||||
/** it is hard (and not necessary for nsd) to determine time
|
||||
* data from week number.
|
||||
**/
|
||||
break;
|
||||
case 'x': /* date format */
|
||||
if (!(s = unbound_strptime(s, "%m/%d/%y", tm))) {
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case 'X': /* time format */
|
||||
if (!(s = unbound_strptime(s, "%H:%M:%S", tm))) {
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case 'y': /* last two digits of a year */
|
||||
ret = str2int(&s, 2);
|
||||
if (ret < 0 || ret > 99) { /* must be in [00,99] */
|
||||
return NULL;
|
||||
}
|
||||
if (split_year) {
|
||||
tm->tm_year = ((tm->tm_year/100) * 100) + ret;
|
||||
}
|
||||
else {
|
||||
split_year = 1;
|
||||
|
||||
/** currently:
|
||||
* if in [0,68] we are in 21th century,
|
||||
* if in [69,99] we are in 20th century.
|
||||
**/
|
||||
if (ret < 69) /* 2000 */
|
||||
ret += 100;
|
||||
tm->tm_year = ret;
|
||||
}
|
||||
break;
|
||||
case 'Y': /* year */
|
||||
ret = str2int(&s, 4);
|
||||
if (ret < 0 || ret > 9999) {
|
||||
return NULL;
|
||||
}
|
||||
tm->tm_year = ret - TM_YEAR_BASE;
|
||||
break;
|
||||
case '\0':
|
||||
default: /* unsupported, cannot match format */
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else { /* literal */
|
||||
/* if input cannot match format, return NULL */
|
||||
if (*s != c)
|
||||
return NULL;
|
||||
s++;
|
||||
}
|
||||
|
||||
format++;
|
||||
}
|
||||
|
||||
/* return pointer to remainder of s */
|
||||
return (char*) s;
|
||||
}
|
||||
|
||||
#endif /* STRPTIME_WORKS */
|
||||
Vendored
+68
-128
@@ -1,10 +1,10 @@
|
||||
#! /bin/sh
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
# Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2009-04-27'
|
||||
timestamp='2009-11-20'
|
||||
|
||||
# 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
|
||||
@@ -27,16 +27,16 @@ timestamp='2009-04-27'
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
|
||||
# Originally written by Per Bothner <per@bothner.com>.
|
||||
# Please send patches to <config-patches@gnu.org>. Submit a context
|
||||
# diff and a properly formatted ChangeLog entry.
|
||||
# Originally written by Per Bothner. Please send patches (context
|
||||
# diff format) to <config-patches@gnu.org> and include a ChangeLog
|
||||
# entry.
|
||||
#
|
||||
# This script attempts to guess a canonical system name similar to
|
||||
# config.sub. If it succeeds, it prints the system name on stdout, and
|
||||
# exits with 0. Otherwise, it exits with 1.
|
||||
#
|
||||
# The plan is that this can be called by configure scripts if you
|
||||
# don't specify an explicit build system type.
|
||||
# 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
|
||||
|
||||
me=`echo "$0" | sed -e 's,.*/,,'`
|
||||
|
||||
@@ -170,7 +170,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
|
||||
eval $set_cc_for_build
|
||||
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
| grep __ELF__ >/dev/null
|
||||
| grep -q __ELF__
|
||||
then
|
||||
# Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
|
||||
# Return netbsd for either. FIX?
|
||||
@@ -333,6 +333,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
|
||||
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit ;;
|
||||
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
|
||||
echo i386-pc-auroraux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
|
||||
eval $set_cc_for_build
|
||||
SUN_ARCH="i386"
|
||||
@@ -656,7 +659,7 @@ EOF
|
||||
# => hppa64-hp-hpux11.23
|
||||
|
||||
if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
|
||||
grep __LP64__ >/dev/null
|
||||
grep -q __LP64__
|
||||
then
|
||||
HP_ARCH="hppa2.0w"
|
||||
else
|
||||
@@ -807,12 +810,12 @@ EOF
|
||||
i*:PW*:*)
|
||||
echo ${UNAME_MACHINE}-pc-pw32
|
||||
exit ;;
|
||||
*:Interix*:[3456]*)
|
||||
*:Interix*:*)
|
||||
case ${UNAME_MACHINE} in
|
||||
x86)
|
||||
echo i586-pc-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
EM64T | authenticamd | genuineintel)
|
||||
authenticamd | genuineintel | EM64T)
|
||||
echo x86_64-unknown-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
IA64)
|
||||
@@ -822,6 +825,9 @@ EOF
|
||||
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
|
||||
echo i${UNAME_MACHINE}-pc-mks
|
||||
exit ;;
|
||||
8664:Windows_NT:*)
|
||||
echo x86_64-pc-mks
|
||||
exit ;;
|
||||
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
|
||||
# How do we know it's Interix rather than the generic POSIX subsystem?
|
||||
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
|
||||
@@ -851,6 +857,20 @@ EOF
|
||||
i*86:Minix:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-minix
|
||||
exit ;;
|
||||
alpha:Linux:*:*)
|
||||
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
|
||||
EV5) UNAME_MACHINE=alphaev5 ;;
|
||||
EV56) UNAME_MACHINE=alphaev56 ;;
|
||||
PCA56) UNAME_MACHINE=alphapca56 ;;
|
||||
PCA57) UNAME_MACHINE=alphapca56 ;;
|
||||
EV6) UNAME_MACHINE=alphaev6 ;;
|
||||
EV67) UNAME_MACHINE=alphaev67 ;;
|
||||
EV68*) UNAME_MACHINE=alphaev68 ;;
|
||||
esac
|
||||
objdump --private-headers /bin/sh | grep -q ld.so.1
|
||||
if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
|
||||
exit ;;
|
||||
arm*:Linux:*:*)
|
||||
eval $set_cc_for_build
|
||||
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
@@ -873,6 +893,17 @@ EOF
|
||||
frv:Linux:*:*)
|
||||
echo frv-unknown-linux-gnu
|
||||
exit ;;
|
||||
i*86:Linux:*:*)
|
||||
LIBC=gnu
|
||||
eval $set_cc_for_build
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
#ifdef __dietlibc__
|
||||
LIBC=dietlibc
|
||||
#endif
|
||||
EOF
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
|
||||
echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
|
||||
exit ;;
|
||||
ia64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit ;;
|
||||
@@ -882,78 +913,34 @@ EOF
|
||||
m68*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit ;;
|
||||
mips:Linux:*:*)
|
||||
mips:Linux:*:* | mips64:Linux:*:*)
|
||||
eval $set_cc_for_build
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
#undef CPU
|
||||
#undef mips
|
||||
#undef mipsel
|
||||
#undef ${UNAME_MACHINE}
|
||||
#undef ${UNAME_MACHINE}el
|
||||
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
|
||||
CPU=mipsel
|
||||
CPU=${UNAME_MACHINE}el
|
||||
#else
|
||||
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
|
||||
CPU=mips
|
||||
CPU=${UNAME_MACHINE}
|
||||
#else
|
||||
CPU=
|
||||
#endif
|
||||
#endif
|
||||
EOF
|
||||
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
|
||||
/^CPU/{
|
||||
s: ::g
|
||||
p
|
||||
}'`"
|
||||
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
|
||||
;;
|
||||
mips64:Linux:*:*)
|
||||
eval $set_cc_for_build
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
#undef CPU
|
||||
#undef mips64
|
||||
#undef mips64el
|
||||
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
|
||||
CPU=mips64el
|
||||
#else
|
||||
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
|
||||
CPU=mips64
|
||||
#else
|
||||
CPU=
|
||||
#endif
|
||||
#endif
|
||||
EOF
|
||||
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
|
||||
/^CPU/{
|
||||
s: ::g
|
||||
p
|
||||
}'`"
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
|
||||
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
|
||||
;;
|
||||
or32:Linux:*:*)
|
||||
echo or32-unknown-linux-gnu
|
||||
exit ;;
|
||||
ppc:Linux:*:*)
|
||||
echo powerpc-unknown-linux-gnu
|
||||
exit ;;
|
||||
ppc64:Linux:*:*)
|
||||
echo powerpc64-unknown-linux-gnu
|
||||
exit ;;
|
||||
alpha:Linux:*:*)
|
||||
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
|
||||
EV5) UNAME_MACHINE=alphaev5 ;;
|
||||
EV56) UNAME_MACHINE=alphaev56 ;;
|
||||
PCA56) UNAME_MACHINE=alphapca56 ;;
|
||||
PCA57) UNAME_MACHINE=alphapca56 ;;
|
||||
EV6) UNAME_MACHINE=alphaev6 ;;
|
||||
EV67) UNAME_MACHINE=alphaev67 ;;
|
||||
EV68*) UNAME_MACHINE=alphaev68 ;;
|
||||
esac
|
||||
objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
|
||||
if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
|
||||
exit ;;
|
||||
padre:Linux:*:*)
|
||||
echo sparc-unknown-linux-gnu
|
||||
exit ;;
|
||||
parisc64:Linux:*:* | hppa64:Linux:*:*)
|
||||
echo hppa64-unknown-linux-gnu
|
||||
exit ;;
|
||||
parisc:Linux:*:* | hppa:Linux:*:*)
|
||||
# Look for CPU level
|
||||
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
|
||||
@@ -962,8 +949,11 @@ EOF
|
||||
*) echo hppa-unknown-linux-gnu ;;
|
||||
esac
|
||||
exit ;;
|
||||
parisc64:Linux:*:* | hppa64:Linux:*:*)
|
||||
echo hppa64-unknown-linux-gnu
|
||||
ppc64:Linux:*:*)
|
||||
echo powerpc64-unknown-linux-gnu
|
||||
exit ;;
|
||||
ppc:Linux:*:*)
|
||||
echo powerpc-unknown-linux-gnu
|
||||
exit ;;
|
||||
s390:Linux:*:* | s390x:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-ibm-linux
|
||||
@@ -986,66 +976,6 @@ EOF
|
||||
xtensa*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit ;;
|
||||
i*86:Linux:*:*)
|
||||
# The BFD linker knows what the default object file format is, so
|
||||
# first see if it will tell us. cd to the root directory to prevent
|
||||
# problems with other programs or directories called `ld' in the path.
|
||||
# Set LC_ALL=C to ensure ld outputs messages in English.
|
||||
ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
|
||||
| sed -ne '/supported targets:/!d
|
||||
s/[ ][ ]*/ /g
|
||||
s/.*supported targets: *//
|
||||
s/ .*//
|
||||
p'`
|
||||
case "$ld_supported_targets" in
|
||||
elf32-i386)
|
||||
TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
|
||||
;;
|
||||
a.out-i386-linux)
|
||||
echo "${UNAME_MACHINE}-pc-linux-gnuaout"
|
||||
exit ;;
|
||||
"")
|
||||
# Either a pre-BFD a.out linker (linux-gnuoldld) or
|
||||
# one that does not give us useful --help.
|
||||
echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
|
||||
exit ;;
|
||||
esac
|
||||
# Determine whether the default compiler is a.out or elf
|
||||
eval $set_cc_for_build
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
#include <features.h>
|
||||
#ifdef __ELF__
|
||||
# ifdef __GLIBC__
|
||||
# if __GLIBC__ >= 2
|
||||
LIBC=gnu
|
||||
# else
|
||||
LIBC=gnulibc1
|
||||
# endif
|
||||
# else
|
||||
LIBC=gnulibc1
|
||||
# endif
|
||||
#else
|
||||
#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
LIBC=gnu
|
||||
#else
|
||||
LIBC=gnuaout
|
||||
#endif
|
||||
#endif
|
||||
#ifdef __dietlibc__
|
||||
LIBC=dietlibc
|
||||
#endif
|
||||
EOF
|
||||
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
|
||||
/^LIBC/{
|
||||
s: ::g
|
||||
p
|
||||
}'`"
|
||||
test x"${LIBC}" != x && {
|
||||
echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
|
||||
exit
|
||||
}
|
||||
test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
|
||||
;;
|
||||
i*86:DYNIX/ptx:4*:*)
|
||||
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
|
||||
# earlier versions are messed up and put the nodename in both
|
||||
@@ -1074,7 +1004,7 @@ EOF
|
||||
i*86:syllable:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-syllable
|
||||
exit ;;
|
||||
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
|
||||
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
|
||||
echo i386-unknown-lynxos${UNAME_RELEASE}
|
||||
exit ;;
|
||||
i*86:*DOS:*:*)
|
||||
@@ -1182,7 +1112,7 @@ EOF
|
||||
rs6000:LynxOS:2.*:*)
|
||||
echo rs6000-unknown-lynxos${UNAME_RELEASE}
|
||||
exit ;;
|
||||
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
|
||||
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
|
||||
echo powerpc-unknown-lynxos${UNAME_RELEASE}
|
||||
exit ;;
|
||||
SM[BE]S:UNIX_SV:*:*)
|
||||
@@ -1275,6 +1205,16 @@ EOF
|
||||
*:Darwin:*:*)
|
||||
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
|
||||
case $UNAME_PROCESSOR in
|
||||
i386)
|
||||
eval $set_cc_for_build
|
||||
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
|
||||
UNAME_PROCESSOR="x86_64"
|
||||
fi
|
||||
fi ;;
|
||||
unknown) UNAME_PROCESSOR=powerpc ;;
|
||||
esac
|
||||
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
|
||||
|
||||
+86
-28
@@ -6,6 +6,15 @@
|
||||
/* Pathname to the Unbound configuration file */
|
||||
#undef CONFIGFILE
|
||||
|
||||
/* configure flags */
|
||||
#undef CONFIGURE_BUILD_WITH
|
||||
|
||||
/* configure date */
|
||||
#undef CONFIGURE_DATE
|
||||
|
||||
/* configure target system */
|
||||
#undef CONFIGURE_TARGET
|
||||
|
||||
/* Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work
|
||||
*/
|
||||
#undef DARWIN_BROKEN_SETREUID
|
||||
@@ -16,6 +25,11 @@
|
||||
/* Define if you want to use debug lock checking (slow). */
|
||||
#undef ENABLE_LOCK_CHECKS
|
||||
|
||||
/* Define this if you enabled-allsymbols from libunbound to link binaries to
|
||||
it for smaller install size, but the libunbound export table is polluted by
|
||||
internal symbols */
|
||||
#undef EXPORT_ALL_SYMBOLS
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#undef HAVE_ARPA_INET_H
|
||||
|
||||
@@ -37,6 +51,18 @@
|
||||
/* Define to 1 if you have the `daemon' function. */
|
||||
#undef HAVE_DAEMON
|
||||
|
||||
/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_NID_SECP384R1
|
||||
|
||||
/* Define to 1 if you have the declaration of `NID_X9_62_prime256v1', and to 0
|
||||
if you don't. */
|
||||
#undef HAVE_DECL_NID_X9_62_PRIME256V1
|
||||
|
||||
/* Define to 1 if you have the declaration of `sk_SSL_COMP_pop_free', and to 0
|
||||
if you don't. */
|
||||
#undef HAVE_DECL_SK_SSL_COMP_POP_FREE
|
||||
|
||||
/* Define to 1 if you have the declaration of
|
||||
`SSL_COMP_get_compression_methods', and to 0 if you don't. */
|
||||
#undef HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS
|
||||
@@ -68,12 +94,21 @@
|
||||
/* Define to 1 if you have the `EVP_sha512' function. */
|
||||
#undef HAVE_EVP_SHA512
|
||||
|
||||
/* Define to 1 if you have the `ev_default_loop' function. */
|
||||
#undef HAVE_EV_DEFAULT_LOOP
|
||||
|
||||
/* Define to 1 if you have the `ev_loop' function. */
|
||||
#undef HAVE_EV_LOOP
|
||||
|
||||
/* Define to 1 if you have the <expat.h> header file. */
|
||||
#undef HAVE_EXPAT_H
|
||||
|
||||
/* Define to 1 if you have the `fcntl' function. */
|
||||
#undef HAVE_FCNTL
|
||||
|
||||
/* Define to 1 if you have the `FIPS_mode' function. */
|
||||
#undef HAVE_FIPS_MODE
|
||||
|
||||
/* Define to 1 if you have the `fork' function. */
|
||||
#undef HAVE_FORK
|
||||
|
||||
@@ -131,6 +166,9 @@
|
||||
/* Define to 1 if you have the `kill' function. */
|
||||
#undef HAVE_KILL
|
||||
|
||||
/* Define to 1 if you have the `ldns_key_EVP_unload_gost' function. */
|
||||
#undef HAVE_LDNS_KEY_EVP_UNLOAD_GOST
|
||||
|
||||
/* Define to 1 if you have the <ldns/ldns.h> header file. */
|
||||
#undef HAVE_LDNS_LDNS_H
|
||||
|
||||
@@ -143,8 +181,7 @@
|
||||
/* Define to 1 if you have the <login_cap.h> header file. */
|
||||
#undef HAVE_LOGIN_CAP_H
|
||||
|
||||
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
|
||||
to 0 otherwise. */
|
||||
/* If have GNU libc compatible malloc */
|
||||
#undef HAVE_MALLOC
|
||||
|
||||
/* Define to 1 if you have the `memmove' function. */
|
||||
@@ -159,6 +196,9 @@
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#undef HAVE_NETINET_IN_H
|
||||
|
||||
/* Use libnss for crypto */
|
||||
#undef HAVE_NSS
|
||||
|
||||
/* Define to 1 if you have the `OPENSSL_config' function. */
|
||||
#undef HAVE_OPENSSL_CONFIG
|
||||
|
||||
@@ -216,6 +256,9 @@
|
||||
/* Define to 1 if you have the `setreuid' function. */
|
||||
#undef HAVE_SETREUID
|
||||
|
||||
/* Define to 1 if you have the `setrlimit' function. */
|
||||
#undef HAVE_SETRLIMIT
|
||||
|
||||
/* Define to 1 if you have the `setsid' function. */
|
||||
#undef HAVE_SETSID
|
||||
|
||||
@@ -231,6 +274,9 @@
|
||||
/* Define to 1 if you have the `snprintf' function. */
|
||||
#undef HAVE_SNPRINTF
|
||||
|
||||
/* Define to 1 if you have the `socketpair' function. */
|
||||
#undef HAVE_SOCKETPAIR
|
||||
|
||||
/* Using Solaris threads */
|
||||
#undef HAVE_SOLARIS_THREADS
|
||||
|
||||
@@ -264,6 +310,12 @@
|
||||
/* Define to 1 if you have the `strlcpy' function. */
|
||||
#undef HAVE_STRLCPY
|
||||
|
||||
/* Define to 1 if you have the `strptime' function. */
|
||||
#undef HAVE_STRPTIME
|
||||
|
||||
/* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */
|
||||
#undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST
|
||||
|
||||
/* Define if you have Swig libraries and header files. */
|
||||
#undef HAVE_SWIG
|
||||
|
||||
@@ -389,6 +441,9 @@
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
@@ -402,6 +457,12 @@
|
||||
/* Define as the return type of signal handlers (`int' or `void'). */
|
||||
#undef RETSIGTYPE
|
||||
|
||||
/* default rootkey location */
|
||||
#undef ROOT_ANCHOR_FILE
|
||||
|
||||
/* default rootcert location */
|
||||
#undef ROOT_CERT_FILE
|
||||
|
||||
/* version number for resource files */
|
||||
#undef RSRC_PACKAGE_VERSION
|
||||
|
||||
@@ -414,6 +475,9 @@
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* use default strptime. */
|
||||
#undef STRPTIME_WORKS
|
||||
|
||||
/* Use win32 resources and API */
|
||||
#undef UB_ON_WINDOWS
|
||||
|
||||
@@ -432,6 +496,12 @@
|
||||
/* define this to enable debug checks. */
|
||||
#undef UNBOUND_DEBUG
|
||||
|
||||
/* Define this to enable ECDSA support. */
|
||||
#undef USE_ECDSA
|
||||
|
||||
/* Define this to enable an EVP workaround for older openssl */
|
||||
#undef USE_ECDSA_EVP_WORKAROUND
|
||||
|
||||
/* Define this to enable GOST support. */
|
||||
#undef USE_GOST
|
||||
|
||||
@@ -653,26 +723,6 @@
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_ATTR_FORMAT
|
||||
@@ -784,9 +834,7 @@ struct tm *gmtime_r(const time_t *timep, struct tm *result);
|
||||
|
||||
|
||||
#ifdef MEMCMP_IS_BROKEN
|
||||
# ifdef memcmp
|
||||
# undef memcmp
|
||||
# endif
|
||||
#include "compat/memcmp.h"
|
||||
#define memcmp memcmp_unbound
|
||||
int memcmp(const void *x, const void *y, size_t n);
|
||||
#endif
|
||||
@@ -798,7 +846,13 @@ int memcmp(const void *x, const void *y, size_t n);
|
||||
char *ctime_r(const time_t *timep, char *buf);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_EVENT_H) && !defined(HAVE_EVENT_BASE_ONCE) && (defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS))
|
||||
#if !defined(HAVE_STRPTIME) || !defined(STRPTIME_WORKS)
|
||||
#define strptime unbound_strptime
|
||||
struct tm;
|
||||
char *strptime(const char *s, const char *format, struct tm *tm);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_EVENT_H) && !defined(HAVE_EVENT_BASE_ONCE) && !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && (defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS))
|
||||
/* using version of libevent that is not threadsafe. */
|
||||
# define LIBEVENT_SIGNAL_PROBLEM 1
|
||||
#endif
|
||||
@@ -819,8 +873,6 @@ struct sockaddr_storage;
|
||||
#include "compat/fake-rfc2553.h"
|
||||
#endif
|
||||
|
||||
#include "ldns/ldns.h"
|
||||
|
||||
#ifdef UNBOUND_ALLOC_STATS
|
||||
# define malloc(s) unbound_stat_malloc_log(s, __FILE__, __LINE__, __func__)
|
||||
# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__)
|
||||
@@ -844,4 +896,10 @@ 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 unbound control traffic, registered port with IANA,
|
||||
ub-dns-control 8953/tcp unbound dns nameserver control */
|
||||
#define UNBOUND_CONTROL_PORT 8953
|
||||
/** the version of unbound-control that this software implements */
|
||||
#define UNBOUND_CONTROL_VERSION 1
|
||||
|
||||
|
||||
|
||||
Vendored
+31
-12
@@ -1,10 +1,10 @@
|
||||
#! /bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
# Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2009-04-17'
|
||||
timestamp='2009-11-20'
|
||||
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
@@ -32,13 +32,16 @@ timestamp='2009-04-17'
|
||||
|
||||
|
||||
# Please send patches to <config-patches@gnu.org>. Submit a context
|
||||
# diff and a properly formatted ChangeLog entry.
|
||||
# diff and a properly formatted GNU ChangeLog entry.
|
||||
#
|
||||
# Configuration subroutine to validate and canonicalize a configuration type.
|
||||
# Supply the specified configuration type as an argument.
|
||||
# If it is invalid, we print an error message on stderr and exit with code 1.
|
||||
# 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
|
||||
|
||||
# This file is supposed to be the same for all GNU packages
|
||||
# and recognize all the CPU types, system types and aliases
|
||||
# that are meaningful with *any* GNU software.
|
||||
@@ -149,10 +152,13 @@ case $os in
|
||||
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
||||
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
||||
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
||||
-apple | -axis | -knuth | -cray)
|
||||
-apple | -axis | -knuth | -cray | -microblaze)
|
||||
os=
|
||||
basic_machine=$1
|
||||
;;
|
||||
-bluegene*)
|
||||
os=-cnk
|
||||
;;
|
||||
-sim | -cisco | -oki | -wec | -winbond)
|
||||
os=
|
||||
basic_machine=$1
|
||||
@@ -281,6 +287,7 @@ case $basic_machine in
|
||||
| pdp10 | pdp11 | pj | pjl \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
||||
| pyramid \
|
||||
| rx \
|
||||
| score \
|
||||
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh64 | sh64le \
|
||||
@@ -288,13 +295,14 @@ case $basic_machine in
|
||||
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
|
||||
| spu | strongarm \
|
||||
| tahoe | thumb | tic4x | tic80 | tron \
|
||||
| ubicom32 \
|
||||
| v850 | v850e \
|
||||
| we32k \
|
||||
| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
|
||||
| z8k | z80)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12)
|
||||
m6811 | m68hc11 | m6812 | m68hc12 | picochip)
|
||||
# Motorola 68HC11/12.
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-none
|
||||
@@ -337,7 +345,7 @@ case $basic_machine in
|
||||
| lm32-* \
|
||||
| m32c-* | m32r-* | m32rle-* \
|
||||
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
|
||||
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
|
||||
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
||||
| mips16-* \
|
||||
| mips64-* | mips64el-* \
|
||||
@@ -365,7 +373,7 @@ case $basic_machine in
|
||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
||||
| pyramid-* \
|
||||
| romp-* | rs6000-* \
|
||||
| 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-* \
|
||||
@@ -374,6 +382,7 @@ case $basic_machine in
|
||||
| tahoe-* | thumb-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
|
||||
| tron-* \
|
||||
| ubicom32-* \
|
||||
| v850-* | v850e-* | vax-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
|
||||
@@ -467,6 +476,10 @@ case $basic_machine in
|
||||
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
bluegene*)
|
||||
basic_machine=powerpc-ibm
|
||||
os=-cnk
|
||||
;;
|
||||
c90)
|
||||
basic_machine=c90-cray
|
||||
os=-unicos
|
||||
@@ -719,6 +732,9 @@ case $basic_machine in
|
||||
basic_machine=ns32k-utek
|
||||
os=-sysv
|
||||
;;
|
||||
microblaze)
|
||||
basic_machine=microblaze-xilinx
|
||||
;;
|
||||
mingw32)
|
||||
basic_machine=i386-pc
|
||||
os=-mingw32
|
||||
@@ -1240,6 +1256,9 @@ case $os in
|
||||
# First match some system type aliases
|
||||
# that might get confused with valid system types.
|
||||
# -solaris* is a basic system type, with this one exception.
|
||||
-auroraux)
|
||||
os=-auroraux
|
||||
;;
|
||||
-solaris1 | -solaris1.*)
|
||||
os=`echo $os | sed -e 's|solaris1|sunos4|'`
|
||||
;;
|
||||
@@ -1260,9 +1279,9 @@ case $os in
|
||||
# Each alternative MUST END IN A *, to match a version number.
|
||||
# -sysv* is not here because it comes later, after sysvr4.
|
||||
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
|
||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
|
||||
| -kopensolaris* \
|
||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
|
||||
| -sym* | -kopensolaris* \
|
||||
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
||||
| -aos* | -aros* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
@@ -1283,7 +1302,7 @@ case $os in
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
@@ -1613,7 +1632,7 @@ case $basic_machine in
|
||||
-sunos*)
|
||||
vendor=sun
|
||||
;;
|
||||
-aix*)
|
||||
-cnk*|-aix*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-beos*)
|
||||
|
||||
+593
-145
@@ -6,11 +6,11 @@ sinclude(acx_pthread.m4)
|
||||
sinclude(acx_python.m4)
|
||||
sinclude(ac_pkg_swig.m4)
|
||||
|
||||
AC_INIT(unbound, 1.4.3, unbound-bugs@nlnetlabs.nl, unbound)
|
||||
AC_INIT(unbound, 1.4.19, unbound-bugs@nlnetlabs.nl, unbound)
|
||||
|
||||
LIBUNBOUND_CURRENT=2
|
||||
LIBUNBOUND_REVISION=3
|
||||
LIBUNBOUND_AGE=0
|
||||
LIBUNBOUND_CURRENT=3
|
||||
LIBUNBOUND_REVISION=4
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
# 1.0.2 had 0:14:0
|
||||
@@ -28,6 +28,23 @@ LIBUNBOUND_AGE=0
|
||||
# 1.4.1 had 2:1:0
|
||||
# 1.4.2 had 2:2:0
|
||||
# 1.4.3 had 2:3:0
|
||||
# 1.4.4 had 2:4:0
|
||||
# 1.4.5 had 2:5:0
|
||||
# 1.4.6 had 2:6:0
|
||||
# 1.4.7 had 2:7:0
|
||||
# 1.4.8 had 2:8:0
|
||||
# 1.4.9 had 2:9:0
|
||||
# 1.4.10 had 2:10:0
|
||||
# 1.4.11 had 2:11:0
|
||||
# 1.4.12 had 2:12:0
|
||||
# 1.4.13 had 2:13:0
|
||||
# and 1.4.13p1 and 1.4.13.p2
|
||||
# 1.4.14 had 2:14:0
|
||||
# 1.4.15 had 3:0:1 # adds ub_version()
|
||||
# 1.4.16 had 3:1:1
|
||||
# 1.4.17 had 3:2:1
|
||||
# 1.4.18 had 3:3:1
|
||||
# 1.4.19 had 3:4:1
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -51,6 +68,19 @@ AC_SUBST(LIBUNBOUND_CURRENT)
|
||||
AC_SUBST(LIBUNBOUND_REVISION)
|
||||
AC_SUBST(LIBUNBOUND_AGE)
|
||||
|
||||
pretty_cmdline() {
|
||||
cmdline=""
|
||||
while test -n "$1"; do
|
||||
cmdline="$cmdline '"`echo $1 | sed -e 's/\\\\/\\\\\\\\/g' | sed -e 's/"/\\\\"/g' `"'"
|
||||
shift
|
||||
done
|
||||
}
|
||||
pretty_cmdline $@
|
||||
AC_DEFINE_UNQUOTED(CONFIGURE_BUILD_WITH, ["$cmdline"], [configure flags])
|
||||
AC_CANONICAL_TARGET
|
||||
AC_DEFINE_UNQUOTED(CONFIGURE_TARGET, ["$target"], [configure target system])
|
||||
AC_DEFINE_UNQUOTED(CONFIGURE_DATE, ["`date`"], [configure date])
|
||||
|
||||
CFLAGS="$CFLAGS"
|
||||
AC_AIX
|
||||
|
||||
@@ -112,7 +142,7 @@ else
|
||||
fi
|
||||
)
|
||||
AC_SUBST(UNBOUND_CHROOT_DIR)
|
||||
ACX_ESCAPE_BACKSLASH($UNBOUND_CHOOT_DIR, hdr_chroot)
|
||||
ACX_ESCAPE_BACKSLASH($UNBOUND_CHROOT_DIR, hdr_chroot)
|
||||
AC_DEFINE_UNQUOTED(CHROOT_DIR, ["$hdr_chroot"], [Directory to chroot to])
|
||||
|
||||
AC_ARG_WITH(share-dir,
|
||||
@@ -137,6 +167,34 @@ AC_SUBST(UNBOUND_PIDFILE)
|
||||
ACX_ESCAPE_BACKSLASH($UNBOUND_PIDFILE, hdr_pid)
|
||||
AC_DEFINE_UNQUOTED(PIDFILE, ["$hdr_pid"], [default pidfile location])
|
||||
|
||||
AC_ARG_WITH(rootkey-file,
|
||||
AC_HELP_STRING([--with-rootkey-file=filename],
|
||||
[set default pathname to root key file (default run-dir/root.key). This file is read and written.]),
|
||||
UNBOUND_ROOTKEY_FILE="$withval",
|
||||
if test $on_mingw = no; then
|
||||
UNBOUND_ROOTKEY_FILE="$UNBOUND_RUN_DIR/root.key"
|
||||
else
|
||||
UNBOUND_ROOTKEY_FILE="C:\\Program Files\\Unbound\\root.key"
|
||||
fi
|
||||
)
|
||||
AC_SUBST(UNBOUND_ROOTKEY_FILE)
|
||||
ACX_ESCAPE_BACKSLASH($UNBOUND_ROOTKEY_FILE, hdr_rkey)
|
||||
AC_DEFINE_UNQUOTED(ROOT_ANCHOR_FILE, ["$hdr_rkey"], [default rootkey location])
|
||||
|
||||
AC_ARG_WITH(rootcert-file,
|
||||
AC_HELP_STRING([--with-rootcert-file=filename],
|
||||
[set default pathname to root update certificate file (default run-dir/icannbundle.pem). This file need not exist if you are content with the builtin.]),
|
||||
UNBOUND_ROOTCERT_FILE="$withval",
|
||||
if test $on_mingw = no; then
|
||||
UNBOUND_ROOTCERT_FILE="$UNBOUND_RUN_DIR/icannbundle.pem"
|
||||
else
|
||||
UNBOUND_ROOTCERT_FILE="C:\\Program Files\\Unbound\\icannbundle.pem"
|
||||
fi
|
||||
)
|
||||
AC_SUBST(UNBOUND_ROOTCERT_FILE)
|
||||
ACX_ESCAPE_BACKSLASH($UNBOUND_ROOTCERT_FILE, hdr_rpem)
|
||||
AC_DEFINE_UNQUOTED(ROOT_CERT_FILE, ["$hdr_rpem"], [default rootcert location])
|
||||
|
||||
AC_ARG_WITH(username,
|
||||
AC_HELP_STRING([--with-username=user],
|
||||
[set default user that unbound changes to (default user is unbound)]),
|
||||
@@ -152,16 +210,15 @@ AC_DEFINE_UNQUOTED(RSRC_PACKAGE_VERSION, [$wnvs], [version number for resource f
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
AC_LANG_C
|
||||
# allow user to override the -g -O2 flags.
|
||||
if test "x$CFLAGS" = "x" ; then
|
||||
ACX_CHECK_COMPILER_FLAG(g, [CFLAGS="$CFLAGS -g"])
|
||||
ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"])
|
||||
fi
|
||||
AC_PROG_CC
|
||||
ACX_DEPFLAG
|
||||
ACX_DETERMINE_EXT_FLAGS_UNBOUND
|
||||
|
||||
# for Sun studio 11.
|
||||
ACX_CHECK_COMPILER_FLAG(xO4, [CFLAGS="$CFLAGS -xO4"])
|
||||
ACX_CHECK_COMPILER_FLAG(xtarget=generic, [CFLAGS="$CFLAGS -xtarget=generic"])
|
||||
|
||||
# debug mode flags warnings
|
||||
AC_ARG_ENABLE(checking, AC_HELP_STRING([--enable-checking], [Enable warnings, asserts, makefile-dependencies]))
|
||||
AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [same as enable-checking]))
|
||||
@@ -180,6 +237,7 @@ case "$debug_enabled" in
|
||||
# nothing to do.
|
||||
;;
|
||||
esac
|
||||
ACX_CHECK_FLTO
|
||||
|
||||
AC_C_INLINE
|
||||
ACX_CHECK_FORMAT_ATTRIBUTE
|
||||
@@ -231,6 +289,90 @@ ACX_CHECK_MEMCMP_SIGNED
|
||||
|
||||
# add option to disable the evil rpath
|
||||
ACX_ARG_RPATH
|
||||
AC_SUBST(RUNTIME_PATH)
|
||||
|
||||
# check to see if libraries are needed for these functions.
|
||||
AC_SEARCH_LIBS([inet_pton], [nsl])
|
||||
AC_SEARCH_LIBS([socket], [socket])
|
||||
|
||||
# check wether strptime also works
|
||||
AC_DEFUN([AC_CHECK_STRPTIME_WORKS],
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
AC_MSG_CHECKING(whether strptime works)
|
||||
if test c${cross_compiling} = cno; then
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#define _XOPEN_SOURCE
|
||||
#include <time.h>
|
||||
int main(void) { struct tm tm; char *res;
|
||||
res = strptime("2010-07-15T00:00:00+00:00", "%t%Y%t-%t%m%t-%t%d%tT%t%H%t:%t%M%t:%t%S%t", &tm);
|
||||
if (!res) return 2;
|
||||
res = strptime("20070207111842", "%Y%m%d%H%M%S", &tm);
|
||||
if (!res) return 1; return 0; }
|
||||
]])] , [eval "ac_cv_c_strptime_works=yes"], [eval "ac_cv_c_strptime_works=no"])
|
||||
else
|
||||
eval "ac_cv_c_strptime_works=maybe"
|
||||
fi
|
||||
AC_MSG_RESULT($ac_cv_c_strptime_works)
|
||||
if test $ac_cv_c_strptime_works = no; then
|
||||
AC_LIBOBJ(strptime)
|
||||
else
|
||||
AC_DEFINE_UNQUOTED([STRPTIME_WORKS], 1, [use default strptime.])
|
||||
fi
|
||||
])dnl
|
||||
|
||||
# check some functions of the OS before linking libs (while still runnable).
|
||||
AC_FUNC_CHOWN
|
||||
AC_FUNC_FORK
|
||||
AC_TYPE_SIGNAL
|
||||
AC_FUNC_FSEEKO
|
||||
ACX_SYS_LARGEFILE
|
||||
ACX_CHECK_NONBLOCKING_BROKEN
|
||||
ACX_MKDIR_ONE_ARG
|
||||
AC_CHECK_FUNCS([strptime],[AC_CHECK_STRPTIME_WORKS],[AC_LIBOBJ([strptime])])
|
||||
|
||||
# set memory allocation checking if requested
|
||||
AC_ARG_ENABLE(alloc-checks, AC_HELP_STRING([--enable-alloc-checks],
|
||||
[ enable to memory allocation statistics, for debug purposes ]),
|
||||
, )
|
||||
AC_ARG_ENABLE(alloc-lite, AC_HELP_STRING([--enable-alloc-lite],
|
||||
[ enable for lightweight alloc assertions, for debug purposes ]),
|
||||
, )
|
||||
AC_ARG_ENABLE(alloc-nonregional, AC_HELP_STRING([--enable-alloc-nonregional],
|
||||
[ enable nonregional allocs, slow but exposes regional allocations to other memory purifiers, for debug purposes ]),
|
||||
, )
|
||||
if test x_$enable_alloc_nonregional = x_yes; then
|
||||
AC_DEFINE(UNBOUND_ALLOC_NONREGIONAL, 1, [use malloc not regions, for debug use])
|
||||
fi
|
||||
if test x_$enable_alloc_checks = x_yes; then
|
||||
AC_DEFINE(UNBOUND_ALLOC_STATS, 1, [use statistics for allocs and frees, for debug use])
|
||||
else
|
||||
if test x_$enable_alloc_lite = x_yes; then
|
||||
AC_DEFINE(UNBOUND_ALLOC_LITE, 1, [use to enable lightweight alloc assertions, for debug use])
|
||||
else
|
||||
ACX_FUNC_MALLOC([unbound])
|
||||
fi
|
||||
fi
|
||||
|
||||
# check windows threads (we use them, not pthreads, on windows).
|
||||
if test "$on_mingw" = "yes"; then
|
||||
# check windows threads
|
||||
AC_CHECK_HEADERS([windows.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_MSG_CHECKING([for CreateThread])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
#include <windows.h>
|
||||
#endif
|
||||
], [
|
||||
HANDLE t = CreateThread(NULL, 0, NULL, NULL, 0, NULL);
|
||||
])],
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_WINDOWS_THREADS, 1, [Using Windows threads])
|
||||
,
|
||||
AC_MSG_RESULT(no)
|
||||
)
|
||||
|
||||
else
|
||||
# not on mingw, check thread libraries.
|
||||
|
||||
# check for thread library.
|
||||
# check this first, so that the pthread lib does not get linked in via
|
||||
@@ -272,23 +414,7 @@ if test x_$withval != x_no; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# check windows threads
|
||||
if test x_$ub_have_pthreads = x_no -a x_$ub_have_sol_threads = x_no; then
|
||||
AC_CHECK_HEADERS([windows.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_MSG_CHECKING([for CreateThread])
|
||||
AC_TRY_COMPILE([
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
#include <windows.h>
|
||||
#endif
|
||||
], [
|
||||
HANDLE t = CreateThread(NULL, 0, NULL, NULL, 0, NULL);
|
||||
],
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_WINDOWS_THREADS, 1, [Using Windows threads])
|
||||
,
|
||||
AC_MSG_RESULT(no)
|
||||
)
|
||||
fi
|
||||
fi # end of non-mingw check of thread libraries
|
||||
|
||||
# Check for PyUnbound
|
||||
AC_ARG_WITH(pyunbound,
|
||||
@@ -320,6 +446,7 @@ if test x_$ub_test_python != x_no; then
|
||||
|
||||
# Check for Python
|
||||
ub_have_python=no
|
||||
ac_save_LIBS="$LIBS" dnl otherwise AC_PYTHON_DEVEL thrashes $LIBS
|
||||
AC_PYTHON_DEVEL
|
||||
if test ! -z "$PYTHON_VERSION"; then
|
||||
if test `$PYTHON -c "print '$PYTHON_VERSION' >= '2.4.0'"` = "False"; then
|
||||
@@ -349,6 +476,14 @@ if test x_$ub_test_python != x_no; then
|
||||
AC_DEFINE(WITH_PYTHONMODULE, 1, [Define if you want Python module.])
|
||||
WITH_PYTHONMODULE=yes
|
||||
AC_SUBST(WITH_PYTHONMODULE)
|
||||
PYTHONMOD_OBJ="pythonmod.lo pythonmod_utils.lo"
|
||||
AC_SUBST(PYTHONMOD_OBJ)
|
||||
PYTHONMOD_HEADER='$(srcdir)/pythonmod/pythonmod.h'
|
||||
AC_SUBST(PYTHONMOD_HEADER)
|
||||
PYTHONMOD_INSTALL=pythonmod-install
|
||||
AC_SUBST(PYTHONMOD_INSTALL)
|
||||
PYTHONMOD_UNINSTALL=pythonmod-uninstall
|
||||
AC_SUBST(PYTHONMOD_UNINSTALL)
|
||||
fi
|
||||
|
||||
# Declare PyUnbound
|
||||
@@ -356,6 +491,14 @@ if test x_$ub_test_python != x_no; then
|
||||
AC_DEFINE(WITH_PYUNBOUND, 1, [Define if you want PyUnbound.])
|
||||
WITH_PYUNBOUND=yes
|
||||
AC_SUBST(WITH_PYUNBOUND)
|
||||
PYUNBOUND_OBJ="libunbound_wrap.lo"
|
||||
AC_SUBST(PYUNBOUND_OBJ)
|
||||
PYUNBOUND_TARGET="_unbound.la"
|
||||
AC_SUBST(PYUNBOUND_TARGET)
|
||||
PYUNBOUND_INSTALL=pyunbound-install
|
||||
AC_SUBST(PYUNBOUND_INSTALL)
|
||||
PYUNBOUND_UNINSTALL=pyunbound-uninstall
|
||||
AC_SUBST(PYUNBOUND_UNINSTALL)
|
||||
fi
|
||||
fi
|
||||
else
|
||||
@@ -365,13 +508,42 @@ if test x_$ub_test_python != x_no; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "`uname`" = "NetBSD"; then
|
||||
NETBSD_LINTFLAGS='"-D__RENAME(x)=" -D_NETINET_IN_H_'
|
||||
AC_SUBST(NETBSD_LINTFLAGS)
|
||||
fi
|
||||
CONFIG_DATE=`date +%Y%m%d`
|
||||
AC_SUBST(CONFIG_DATE)
|
||||
|
||||
# Checks for libraries.
|
||||
|
||||
# libnss
|
||||
USE_NSS="no"
|
||||
AC_ARG_WITH([nss], AC_HELP_STRING([--with-nss=path],
|
||||
[use libnss instead of openssl, installed at path.]),
|
||||
[
|
||||
USE_NSS="yes"
|
||||
AC_DEFINE(HAVE_NSS, 1, [Use libnss for crypto])
|
||||
if test "$withval" != "/usr" -a "$withval" != "" -a "$withval" != "yes"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$withval/include"
|
||||
LDFLAGS="$LDFLAGS -L$withval/lib"
|
||||
ACX_RUNTIME_PATH_ADD([$withval/lib])
|
||||
CPPFLAGS="-I$withval/include/nspr4 $CPPFLAGS"
|
||||
else
|
||||
CPPFLAGS="-I/usr/include/nspr4 $CPPFLAGS"
|
||||
fi
|
||||
LIBS="$LIBS -lnss3 -lnspr4"
|
||||
]
|
||||
)
|
||||
|
||||
# openssl
|
||||
if test $USE_NSS = "no"; then
|
||||
ACX_WITH_SSL
|
||||
ACX_LIB_SSL
|
||||
AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512])
|
||||
AC_CHECK_DECLS([SSL_COMP_get_compression_methods], [], [], [
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode])
|
||||
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free], [], [], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
#include <openssl/err.h>
|
||||
@@ -391,6 +563,8 @@ AC_INCLUDES_DEFAULT
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/evp.h>
|
||||
])
|
||||
fi
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sha2, AC_HELP_STRING([--disable-sha2], [Disable SHA256 and SHA512 RRSIG support]))
|
||||
case "$enable_sha2" in
|
||||
@@ -401,21 +575,148 @@ case "$enable_sha2" in
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(gost, AC_HELP_STRING([--enable-gost], [Enable GOST support, experimental]))
|
||||
# check wether gost also works
|
||||
AC_DEFUN([AC_CHECK_GOST_WORKS],
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
AC_MSG_CHECKING([if GOST works])
|
||||
if test c${cross_compiling} = cno; then
|
||||
BAKCFLAGS="$CFLAGS"
|
||||
if test -n "$ssldir"; then
|
||||
CFLAGS="$CFLAGS -Wl,-rpath,$ssldir/lib"
|
||||
fi
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <string.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/conf.h>
|
||||
/* routine to load gost from ldns */
|
||||
int load_gost_id(void)
|
||||
{
|
||||
static int gost_id = 0;
|
||||
const EVP_PKEY_ASN1_METHOD* meth;
|
||||
ENGINE* e;
|
||||
|
||||
if(gost_id) return gost_id;
|
||||
|
||||
/* see if configuration loaded gost implementation from other engine*/
|
||||
meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
|
||||
if(meth) {
|
||||
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
|
||||
return gost_id;
|
||||
}
|
||||
|
||||
/* see if engine can be loaded already */
|
||||
e = ENGINE_by_id("gost");
|
||||
if(!e) {
|
||||
/* load it ourself, in case statically linked */
|
||||
ENGINE_load_builtin_engines();
|
||||
ENGINE_load_dynamic();
|
||||
e = ENGINE_by_id("gost");
|
||||
}
|
||||
if(!e) {
|
||||
/* no gost engine in openssl */
|
||||
return 0;
|
||||
}
|
||||
if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
|
||||
ENGINE_finish(e);
|
||||
ENGINE_free(e);
|
||||
return 0;
|
||||
}
|
||||
|
||||
meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
|
||||
if(!meth) {
|
||||
/* algo not found */
|
||||
ENGINE_finish(e);
|
||||
ENGINE_free(e);
|
||||
return 0;
|
||||
}
|
||||
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
|
||||
return gost_id;
|
||||
}
|
||||
int main(void) {
|
||||
EVP_MD_CTX* ctx;
|
||||
const EVP_MD* md;
|
||||
unsigned char digest[64]; /* its a 256-bit digest, so uses 32 bytes */
|
||||
const char* str = "Hello world";
|
||||
const unsigned char check[] = {
|
||||
0x40 , 0xed , 0xf8 , 0x56 , 0x5a , 0xc5 , 0x36 , 0xe1 ,
|
||||
0x33 , 0x7c , 0x7e , 0x87 , 0x62 , 0x1c , 0x42 , 0xe0 ,
|
||||
0x17 , 0x1b , 0x5e , 0xce , 0xa8 , 0x46 , 0x65 , 0x4d ,
|
||||
0x8d , 0x3e , 0x22 , 0x9b , 0xe1 , 0x30 , 0x19 , 0x9d
|
||||
};
|
||||
OPENSSL_config(NULL);
|
||||
(void)load_gost_id();
|
||||
md = EVP_get_digestbyname("md_gost94");
|
||||
if(!md) return 1;
|
||||
memset(digest, 0, sizeof(digest));
|
||||
ctx = EVP_MD_CTX_create();
|
||||
if(!ctx) return 2;
|
||||
if(!EVP_DigestInit_ex(ctx, md, NULL)) return 3;
|
||||
if(!EVP_DigestUpdate(ctx, str, 10)) return 4;
|
||||
if(!EVP_DigestFinal_ex(ctx, digest, NULL)) return 5;
|
||||
/* uncomment to see the hash calculated.
|
||||
{int i;
|
||||
for(i=0; i<32; i++)
|
||||
printf(" %2.2x", (int)digest[i]);
|
||||
printf("\n");}
|
||||
*/
|
||||
if(memcmp(digest, check, sizeof(check)) != 0)
|
||||
return 6;
|
||||
return 0;
|
||||
}
|
||||
]])] , [eval "ac_cv_c_gost_works=yes"], [eval "ac_cv_c_gost_works=no"])
|
||||
CFLAGS="$BAKCFLAGS"
|
||||
else
|
||||
eval "ac_cv_c_gost_works=maybe"
|
||||
fi
|
||||
AC_MSG_RESULT($ac_cv_c_gost_works)
|
||||
])dnl
|
||||
|
||||
AC_ARG_ENABLE(gost, AC_HELP_STRING([--disable-gost], [Disable GOST support]))
|
||||
use_gost="no"
|
||||
if test $USE_NSS = "no"; then
|
||||
case "$enable_gost" in
|
||||
yes)
|
||||
AC_CHECK_FUNC(EVP_PKEY_set_type_str, [:],[AC_MSG_ERROR([OpenSSL >= 1.0.0 is needed for GOST support])])
|
||||
AC_DEFINE([USE_GOST], [1], [Define this to enable GOST support.])
|
||||
no)
|
||||
;;
|
||||
no|*)
|
||||
*)
|
||||
AC_CHECK_FUNC(EVP_PKEY_set_type_str, [:],[AC_MSG_ERROR([OpenSSL 1.0.0 is needed for GOST support])])
|
||||
AC_CHECK_FUNC(EC_KEY_new, [], [AC_MSG_ERROR([OpenSSL does not support ECC, needed for GOST support])])
|
||||
AC_CHECK_GOST_WORKS
|
||||
if test "$ac_cv_c_gost_works" != no; then
|
||||
use_gost="yes"
|
||||
AC_DEFINE([USE_GOST], [1], [Define this to enable GOST support.])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi dnl !USE_NSS
|
||||
|
||||
# check to see if libraries are needed for these functions.
|
||||
AC_SEARCH_LIBS([inet_pton], [nsl])
|
||||
AC_SEARCH_LIBS([socket], [socket])
|
||||
|
||||
AC_SUBST(RUNTIME_PATH)
|
||||
AC_ARG_ENABLE(ecdsa, AC_HELP_STRING([--disable-ecdsa], [Disable ECDSA support]))
|
||||
use_ecdsa="no"
|
||||
case "$enable_ecdsa" in
|
||||
no)
|
||||
;;
|
||||
*)
|
||||
if test $USE_NSS = "no"; then
|
||||
AC_CHECK_FUNC(ECDSA_sign, [], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])])
|
||||
AC_CHECK_FUNC(SHA384_Init, [], [AC_MSG_ERROR([OpenSSL does not support SHA384: please upgrade or rerun with --disable-ecdsa])])
|
||||
AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [], [AC_MSG_ERROR([OpenSSL does not support the ECDSA curves: please upgrade or rerun with --disable-ecdsa])], [AC_INCLUDES_DEFAULT
|
||||
#include <openssl/evp.h>
|
||||
])
|
||||
# see if OPENSSL 1.0.0 or later (has EVP MD and Verify independency)
|
||||
AC_MSG_CHECKING([if openssl supports SHA2 and ECDSA with EVP])
|
||||
if grep OPENSSL_VERSION_NUMBER $ssldir/include/openssl/opensslv.h | grep 0x0 >/dev/null; then
|
||||
AC_MSG_RESULT([no])
|
||||
AC_DEFINE_UNQUOTED([USE_ECDSA_EVP_WORKAROUND], [1], [Define this to enable an EVP workaround for older openssl])
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
fi
|
||||
# we now know we have ECDSA and the required curves.
|
||||
AC_DEFINE_UNQUOTED([USE_ECDSA], [1], [Define this to enable ECDSA support.])
|
||||
use_ecdsa="yes"
|
||||
;;
|
||||
esac
|
||||
|
||||
# check for libevent
|
||||
AC_ARG_WITH(libevent, AC_HELP_STRING([--with-libevent=pathname],
|
||||
@@ -473,13 +774,21 @@ large outgoing port ranges. ])
|
||||
# check for library used by libevent after 1.3c
|
||||
AC_SEARCH_LIBS([clock_gettime], [rt])
|
||||
|
||||
AC_SEARCH_LIBS(event_set, [event])
|
||||
# is the event.h header libev or libevent?
|
||||
AC_CHECK_HEADERS([event.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_DECL(EV_VERSION_MAJOR, [
|
||||
AC_SEARCH_LIBS(event_set, [ev])
|
||||
],[
|
||||
AC_SEARCH_LIBS(event_set, [event])
|
||||
],[AC_INCLUDES_DEFAULT
|
||||
#include <event.h>
|
||||
])
|
||||
AC_CHECK_FUNCS([event_base_free]) # only in libevent 1.2 and later
|
||||
AC_CHECK_FUNCS([event_base_once]) # only in libevent 1.4.1 and later
|
||||
AC_CHECK_FUNCS([event_base_new]) # only in libevent 1.4.1 and later
|
||||
AC_CHECK_FUNCS([event_base_get_method]) # only in libevent 1.4.3 and later
|
||||
AC_CHECK_FUNCS([ev_loop]) # only in libev. (tested on 3.51)
|
||||
AC_CHECK_FUNCS([ev_default_loop]) # only in libev. (tested on 4.00)
|
||||
if test -n "$BAK_LDFLAGS_SET"; then
|
||||
LDFLAGS="$BAK_LDFLAGS"
|
||||
fi
|
||||
@@ -487,10 +796,33 @@ else
|
||||
AC_DEFINE(USE_MINI_EVENT, 1, [Define if you want to use internal select based events])
|
||||
fi
|
||||
|
||||
# check for libexpat
|
||||
AC_ARG_WITH(libexpat, AC_HELP_STRING([--with-libexpat=path],
|
||||
[specify explicit path for libexpat.]),
|
||||
[ ],[ withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr" ])
|
||||
AC_MSG_CHECKING(for libexpat)
|
||||
found_libexpat="no"
|
||||
for dir in $withval ; do
|
||||
if test -f "$dir/include/expat.h"; then
|
||||
found_libexpat="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)
|
||||
break;
|
||||
fi
|
||||
done
|
||||
if test x_$found_libexpat != x_yes; then
|
||||
AC_ERROR([Could not find libexpat, expat.h])
|
||||
fi
|
||||
AC_CHECK_HEADERS([expat.h],,, [AC_INCLUDES_DEFAULT])
|
||||
|
||||
# set static linking if requested
|
||||
AC_SUBST(staticexe)
|
||||
staticexe=""
|
||||
AC_ARG_ENABLE(staticexe, AC_HELP_STRING([--enable-static-exe],
|
||||
AC_ARG_ENABLE(static-exe, AC_HELP_STRING([--enable-static-exe],
|
||||
[ enable to compile executables statically against event, ldns libs, for debug purposes ]),
|
||||
, )
|
||||
if test x_$enable_static_exe = x_yes; then
|
||||
@@ -510,53 +842,40 @@ AC_ARG_ENABLE(lock_checks, AC_HELP_STRING([--enable-lock-checks],
|
||||
, )
|
||||
if test x_$enable_lock_checks = x_yes; then
|
||||
AC_DEFINE(ENABLE_LOCK_CHECKS, 1, [Define if you want to use debug lock checking (slow).])
|
||||
CHECKLOCK_SRC="testcode/checklocks.c"
|
||||
AC_SUBST(CHECKLOCK_SRC)
|
||||
CHECKLOCK_OBJ="checklocks.lo"
|
||||
AC_SUBST(CHECKLOCK_OBJ)
|
||||
fi
|
||||
|
||||
# set memory allocation checking if requested
|
||||
AC_ARG_ENABLE(alloc-checks, AC_HELP_STRING([--enable-alloc-checks],
|
||||
[ enable to memory allocation statistics, for debug purposes ]),
|
||||
, )
|
||||
AC_ARG_ENABLE(alloc-lite, AC_HELP_STRING([--enable-alloc-lite],
|
||||
[ enable for lightweight alloc assertions, for debug purposes ]),
|
||||
, )
|
||||
AC_ARG_ENABLE(alloc-nonregional, AC_HELP_STRING([--enable-alloc-nonregional],
|
||||
[ enable nonregional allocs, slow but exposes regional allocations to other memory purifiers, for debug purposes ]),
|
||||
, )
|
||||
if test x_$enable_alloc_nonregional = x_yes; then
|
||||
AC_DEFINE(UNBOUND_ALLOC_NONREGIONAL, 1, [use malloc not regions, for debug use])
|
||||
fi
|
||||
if test x_$enable_alloc_checks = x_yes; then
|
||||
AC_DEFINE(UNBOUND_ALLOC_STATS, 1, [use statistics for allocs and frees, for debug use])
|
||||
else
|
||||
if test x_$enable_alloc_lite = x_yes; then
|
||||
AC_DEFINE(UNBOUND_ALLOC_LITE, 1, [use to enable lightweight alloc assertions, for debug use])
|
||||
else
|
||||
ACX_FUNC_MALLOC([unbound])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_FUNC_CHOWN
|
||||
AC_FUNC_FORK
|
||||
AC_TYPE_SIGNAL
|
||||
AC_FUNC_FSEEKO
|
||||
ACX_SYS_LARGEFILE
|
||||
|
||||
ACX_CHECK_GETADDRINFO_WITH_INCLUDES
|
||||
if test "$USE_WINSOCK" = 1; then
|
||||
AC_DEFINE(UB_ON_WINDOWS, 1, [Use win32 resources and API])
|
||||
UB_ON_WINDOWS=yes
|
||||
AC_SUBST(UB_ON_WINDOWS)
|
||||
AC_CHECK_HEADERS([iphlpapi.h],,, [AC_INCLUDES_DEFAULT
|
||||
#include <windows.h>
|
||||
])
|
||||
AC_CHECK_TOOL(WINDRES, windres)
|
||||
LIBS="$LIBS -liphlpapi"
|
||||
WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe"
|
||||
AC_SUBST(WINAPPS)
|
||||
WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c"
|
||||
AC_SUBST(WIN_DAEMON_SRC)
|
||||
WIN_DAEMON_OBJ="win_svc.lo w_inst.lo"
|
||||
AC_SUBST(WIN_DAEMON_OBJ)
|
||||
WIN_DAEMON_OBJ_LINK="rsrc_unbound.o"
|
||||
AC_SUBST(WIN_DAEMON_OBJ_LINK)
|
||||
WIN_HOST_OBJ_LINK="rsrc_unbound_host.o"
|
||||
AC_SUBST(WIN_HOST_OBJ_LINK)
|
||||
WIN_UBANCHOR_OBJ_LINK="rsrc_unbound_anchor.o log.lo locks.lo"
|
||||
AC_SUBST(WIN_UBANCHOR_OBJ_LINK)
|
||||
WIN_CONTROL_OBJ_LINK="rsrc_unbound_control.o"
|
||||
AC_SUBST(WIN_CONTROL_OBJ_LINK)
|
||||
WIN_CHECKCONF_OBJ_LINK="rsrc_unbound_checkconf.o"
|
||||
AC_SUBST(WIN_CHECKCONF_OBJ_LINK)
|
||||
fi
|
||||
if test $ac_cv_func_getaddrinfo = no; then
|
||||
AC_LIBOBJ([fake-rfc2553])
|
||||
fi
|
||||
# check after getaddrinfo for its libraries
|
||||
ACX_FUNC_IOCTLSOCKET
|
||||
|
||||
# see if daemon(3) exists, and if it is deprecated.
|
||||
AC_CHECK_FUNCS([daemon])
|
||||
@@ -566,16 +885,45 @@ if test $ac_cv_func_daemon = yes; then
|
||||
])
|
||||
fi
|
||||
|
||||
AC_CHECK_MEMBERS([struct in_pktinfo.ipi_spec_dst],,,[
|
||||
AC_INCLUDES_DEFAULT
|
||||
#if HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_UIO_H
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
])
|
||||
AC_SEARCH_LIBS([setusercontext], [util])
|
||||
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam getrlimit setsid sbrk chroot kill sleep usleep random srandom recvmsg sendmsg writev setresuid setreuid setresgid setregid glob initgroups strftime localtime_r setusercontext _beginthreadex])
|
||||
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam getrlimit setrlimit setsid sbrk chroot kill sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex])
|
||||
AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])])
|
||||
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
|
||||
AC_DEFINE(DARWIN_BROKEN_SETREUID, 1, [Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work])
|
||||
fi
|
||||
ACX_CHECK_NONBLOCKING_BROKEN
|
||||
ACX_MKDIR_ONE_ARG
|
||||
ACX_FUNC_IOCTLSOCKET
|
||||
AC_REPLACE_FUNCS(inet_aton)
|
||||
AC_REPLACE_FUNCS(inet_pton)
|
||||
AC_REPLACE_FUNCS(inet_ntop)
|
||||
@@ -583,63 +931,173 @@ AC_REPLACE_FUNCS(snprintf)
|
||||
AC_REPLACE_FUNCS(strlcpy)
|
||||
AC_REPLACE_FUNCS(memmove)
|
||||
AC_REPLACE_FUNCS(gmtime_r)
|
||||
LIBOBJ_WITHOUT_CTIME="$LIBOBJS"
|
||||
AC_SUBST(LIBOBJ_WITHOUT_CTIME)
|
||||
AC_REPLACE_FUNCS(ctime_r)
|
||||
|
||||
AC_ARG_ENABLE(allsymbols, AC_HELP_STRING([--enable-allsymbols], [export all symbols from libunbound and link binaries to it, smaller install size but libunbound export table is polluted by internal symbols]))
|
||||
case "$enable_allsymbols" in
|
||||
yes)
|
||||
COMMON_OBJ_ALL_SYMBOLS=""
|
||||
UBSYMS=""
|
||||
EXTRALINK="-L. -L.libs -lunbound"
|
||||
AC_DEFINE(EXPORT_ALL_SYMBOLS, 1, [Define this if you enabled-allsymbols from libunbound to link binaries to it for smaller install size, but the libunbound export table is polluted by internal symbols])
|
||||
;;
|
||||
no|*)
|
||||
COMMON_OBJ_ALL_SYMBOLS='$(COMMON_OBJ)'
|
||||
UBSYMS='-export-symbols $(srcdir)/libunbound/ubsyms.def'
|
||||
EXTRALINK=""
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(COMMON_OBJ_ALL_SYMBOLS)
|
||||
AC_SUBST(EXTRALINK)
|
||||
AC_SUBST(UBSYMS)
|
||||
if test x_$enable_lock_checks = x_yes; then
|
||||
UBSYMS="-export-symbols clubsyms.def"
|
||||
cp ${srcdir}/libunbound/ubsyms.def clubsyms.def
|
||||
echo lock_protect >> clubsyms.def
|
||||
echo lock_unprotect >> clubsyms.def
|
||||
echo lock_get_mem >> clubsyms.def
|
||||
echo checklock_start >> clubsyms.def
|
||||
echo checklock_stop >> clubsyms.def
|
||||
echo checklock_lock >> clubsyms.def
|
||||
echo checklock_unlock >> clubsyms.def
|
||||
echo checklock_init >> clubsyms.def
|
||||
echo checklock_thrcreate >> clubsyms.def
|
||||
echo checklock_thrjoin >> clubsyms.def
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([if ${MAKE:-make} supports $< with implicit rule in scope])
|
||||
# on openBSD, the implicit rule make $< work.
|
||||
# on Solaris, it does not work ($? is changed sources, $^ lists dependencies).
|
||||
# gmake works.
|
||||
cat >conftest.make <<EOF
|
||||
all: conftest.lo
|
||||
|
||||
conftest.lo foo.lo bla.lo:
|
||||
if test -f "\$<"; then touch \$@; fi
|
||||
|
||||
.SUFFIXES: .lo
|
||||
.c.lo:
|
||||
if test -f "\$<"; then touch \$@; fi
|
||||
|
||||
conftest.lo: conftest.dir/conftest.c
|
||||
EOF
|
||||
mkdir conftest.dir
|
||||
touch conftest.dir/conftest.c
|
||||
rm -f conftest.lo conftest.c
|
||||
${MAKE:-make} -f conftest.make >/dev/null
|
||||
rm -f conftest.make conftest.c conftest.dir/conftest.c
|
||||
rm -rf conftest.dir
|
||||
if test ! -f conftest.lo; then
|
||||
AC_MSG_RESULT(no)
|
||||
SOURCEDETERMINE='echo "$^" | awk "-F " "{print \$$1;}" > .source'
|
||||
SOURCEFILE='`cat .source`'
|
||||
else
|
||||
AC_MSG_RESULT(yes)
|
||||
SOURCEDETERMINE=':'
|
||||
SOURCEFILE='$<'
|
||||
fi
|
||||
rm -f conftest.lo
|
||||
AC_SUBST(SOURCEDETERMINE)
|
||||
AC_SUBST(SOURCEFILE)
|
||||
|
||||
# see if we want to build the library or everything
|
||||
ALLTARGET="alltargets"
|
||||
AC_ARG_WITH(libunbound-only, AC_HELP_STRING([--with-libunbound-only],
|
||||
[do not build daemon and tool programs]),
|
||||
[
|
||||
if test "$withval" = "yes"; then
|
||||
ALLTARGET="lib"
|
||||
fi
|
||||
])
|
||||
AC_SUBST(ALLTARGET)
|
||||
|
||||
# check this after all other compilation checks, since the linking of the lib
|
||||
# may break checks after this.
|
||||
use_ldns_builtin="no"
|
||||
AC_ARG_WITH(ldns, AC_HELP_STRING([--with-ldns=PATH],
|
||||
[specify prefix of path of ldns library to use]),
|
||||
[ specialldnsdir="$withval"
|
||||
if test "$withval" != ""; then
|
||||
CPPFLAGS="-I$withval/include $CPPFLAGS"
|
||||
LDFLAGS="-L$withval -L$withval/lib $LDFLAGS"
|
||||
ACX_RUNTIME_PATH_ADD([$withval/lib])
|
||||
[
|
||||
if test "$withval" != "yes"; then
|
||||
if test "$withval" != "/usr" -a "$withval" != ""; then
|
||||
CPPFLAGS="-I$withval/include $CPPFLAGS"
|
||||
LDFLAGS="-L$withval/lib $LDFLAGS"
|
||||
ACX_RUNTIME_PATH_ADD([$withval/lib])
|
||||
fi
|
||||
ldnsdir="$withval"
|
||||
AC_SUBST(ldnsdir)
|
||||
fi
|
||||
ldnsdir="$withval"
|
||||
AC_SUBST(ldnsdir)
|
||||
])
|
||||
|
||||
AC_ARG_WITH(ldns-builtin, AC_HELP_STRING([--with-ldns-builtin],
|
||||
[forces use of package included with this one]), [
|
||||
use_ldns_builtin="yes"
|
||||
])
|
||||
|
||||
# check if ldns is good enough
|
||||
if test "$use_ldns_builtin" = "no"; then
|
||||
AC_CHECK_LIB(ldns, ldns_buffer_copy)
|
||||
AC_CHECK_FUNC(ldns_key_buf2rsa_raw)
|
||||
AC_CHECK_HEADERS([ldns/ldns.h],,, [AC_INCLUDES_DEFAULT])
|
||||
if test $ac_cv_lib_ldns_ldns_buffer_copy = yes \
|
||||
-a $ac_cv_func_ldns_key_buf2rsa_raw = yes \
|
||||
-a $ac_cv_header_ldns_ldns_h = yes; then
|
||||
dnl ldns was found, check compat functions
|
||||
AC_CHECK_FUNC([ldns_b32_ntop_extended_hex],, [
|
||||
AC_MSG_ERROR([ldns version too old, need >=1.4.0])])
|
||||
else
|
||||
use_ldns_builtin="yes"
|
||||
fi
|
||||
AC_CHECK_LIB(ldns, ldns_rr_new,,[
|
||||
AC_MSG_ERROR([No ldns library found, install the ldns library into system lib dir or use --with-ldns=path to other location. The --with-ldns can point to the make-dir of ldns. Install the package ldns or download source http://www.nlnetlabs.nl/projects/ldns])
|
||||
])
|
||||
AC_CHECK_FUNC(ldns_buffer_copy)
|
||||
if test $USE_NSS = "no"; then
|
||||
AC_CHECK_FUNC(ldns_key_buf2rsa_raw)
|
||||
else
|
||||
dnl ignore test
|
||||
ac_cv_func_ldns_key_buf2rsa_raw="yes"
|
||||
fi
|
||||
AC_CHECK_FUNC(ldns_get_random)
|
||||
AC_CHECK_FUNC(ldns_b32_ntop_extended_hex)
|
||||
if test x$use_gost = xyes -a x$USE_NSS = xno; then
|
||||
AC_CHECK_FUNC(ldns_key_EVP_load_gost_id)
|
||||
AC_CHECK_FUNCS([ldns_key_EVP_unload_gost])
|
||||
else
|
||||
dnl ignore test
|
||||
ac_cv_func_ldns_key_EVP_load_gost_id="yes"
|
||||
fi
|
||||
if test x$use_ecdsa = xyes; then
|
||||
AC_CHECK_DECL([LDNS_ECDSAP384SHA384], [], [], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
# include <ws2tcpip.h>
|
||||
#endif
|
||||
#include <ldns/ldns.h>
|
||||
])
|
||||
else
|
||||
ac_cv_have_decl_LDNS_ECDSAP384SHA384="yes"
|
||||
fi
|
||||
AC_CHECK_HEADERS([ldns/ldns.h],,[
|
||||
AC_MSG_ERROR([No ldns include file found, install the ldns library development files. Install package ldns-dev or ldns-devel or download source http://www.nlnetlabs.nl/projects/ldns])
|
||||
], [AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
if test "$use_ldns_builtin" = "yes"; then
|
||||
dnl use the builtin ldns-src.tar.gz file to build ldns.
|
||||
if test ! -f $srcdir/ldns-src.tar.gz; then
|
||||
AC_MSG_ERROR([No ldns library found and no ldns-src.tar.gz, use --with-ldns=path.])
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
])
|
||||
if test $ac_cv_func_ldns_buffer_copy = yes \
|
||||
-a $ac_cv_func_ldns_key_buf2rsa_raw = yes \
|
||||
-a $ac_cv_func_ldns_get_random = yes \
|
||||
-a $ac_cv_header_ldns_ldns_h = yes \
|
||||
-a $ac_cv_func_ldns_b32_ntop_extended_hex = yes \
|
||||
-a $ac_cv_func_ldns_key_EVP_load_gost_id = yes \
|
||||
-a $ac_cv_have_decl_LDNS_ECDSAP384SHA384 = yes; then
|
||||
dnl ldns was found
|
||||
:
|
||||
else
|
||||
AC_MSG_ERROR([ldns library is not recent, update the ldns library, install it into system lib dir or use --with-ldns=path to other location. The --with-ldns can point to the make-dir of ldns. Package libldns or download source http://www.nlnetlabs.nl/projects/ldns])
|
||||
fi
|
||||
echo "****************************************************************"
|
||||
echo "*** ***"
|
||||
echo "*** Building ldns library from package included in this one. ***"
|
||||
echo "*** ***"
|
||||
echo "****************************************************************"
|
||||
if test -d $srcdir/ldns-src; then rm -rf $srcdir/ldns-src; fi
|
||||
mkdir $srcdir/ldns-src; cp $srcdir/ldns-src.tar.gz $srcdir/ldns-src/ldns-src.tar.gz; (cd $srcdir/ldns-src; gzip -cd ldns-src.tar.gz | tar xf -); rm -f $srcdir/ldns-src/ldns-src.tar.gz; mv $srcdir/ldns-src $srcdir/ldns-srcb; mv $srcdir/ldns-srcb/ldns* $srcdir/ldns-src; rmdir $srcdir/ldns-srcb
|
||||
ldnsdir="ldns-src"
|
||||
AC_MSG_NOTICE([Configure $ldnsdir scheduled after config.status])
|
||||
AC_CONFIG_SUBDIRS([ldns-src])
|
||||
CPPFLAGS="-I$ldnsdir/include $CPPFLAGS"
|
||||
LDFLAGS="$LDFLAGS $ldnsdir/*.lo"
|
||||
AC_SUBST(ldnsdir)
|
||||
fi dnl end of use_ldns_builtin == yes
|
||||
|
||||
ACX_STRIP_EXT_FLAGS
|
||||
LDFLAGS="$LATE_LDFLAGS $LDFLAGS"
|
||||
@@ -699,26 +1157,6 @@ dnl includes
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
#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
|
||||
]
|
||||
|
||||
AHX_CONFIG_FORMAT_ATTRIBUTE
|
||||
@@ -746,7 +1184,13 @@ AHX_MEMCMP_BROKEN(unbound)
|
||||
char *ctime_r(const time_t *timep, char *buf);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_EVENT_H) && !defined(HAVE_EVENT_BASE_ONCE) && (defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS))
|
||||
#if !defined(HAVE_STRPTIME) || !defined(STRPTIME_WORKS)
|
||||
#define strptime unbound_strptime
|
||||
struct tm;
|
||||
char *strptime(const char *s, const char *format, struct tm *tm);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_EVENT_H) && !defined(HAVE_EVENT_BASE_ONCE) && !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && (defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS))
|
||||
/* using version of libevent that is not threadsafe. */
|
||||
# define LIBEVENT_SIGNAL_PROBLEM 1
|
||||
#endif
|
||||
@@ -767,8 +1211,6 @@ struct sockaddr_storage;
|
||||
#include "compat/fake-rfc2553.h"
|
||||
#endif
|
||||
|
||||
#include "ldns/ldns.h"
|
||||
|
||||
#ifdef UNBOUND_ALLOC_STATS
|
||||
# define malloc(s) unbound_stat_malloc_log(s, __FILE__, __LINE__, __func__)
|
||||
# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__)
|
||||
@@ -792,8 +1234,14 @@ 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 unbound control traffic, registered port with IANA,
|
||||
ub-dns-control 8953/tcp unbound dns nameserver control */
|
||||
#define UNBOUND_CONTROL_PORT 8953
|
||||
/** the version of unbound-control that this software implements */
|
||||
#define UNBOUND_CONTROL_VERSION 1
|
||||
|
||||
])
|
||||
|
||||
AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8])
|
||||
AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8])
|
||||
AC_CONFIG_HEADER([config.h])
|
||||
AC_OUTPUT
|
||||
|
||||
+6
-3
@@ -7,12 +7,15 @@ distribution but may be helpful.
|
||||
* unbound.spec and unbound.init: RPM specfile and Linux rc.d initfile.
|
||||
* update-anchor.sh: shell script that uses unbound-host to update a set
|
||||
of trust anchor files. Run from cron twice a month.
|
||||
* update-itar.sh: shell script that updates from itar.iana.org. Run from cron.
|
||||
* split-itar.sh: shell script to split anchors.mf from itar.iana.org into
|
||||
multiple key files so it can be used with auto-trust-anchor-file.
|
||||
* unbound_munin_ : plugin for munin statistics report
|
||||
* unbound_cacti.tar.gz : setup files for cacti statistics report
|
||||
* selinux: the .fc and .te files for SElinux protection of the unbound daemon
|
||||
* unbound.plist: launchd configuration file for MacOSX.
|
||||
* build-unbound-localzone-from-hosts.pl: perl script to turn /etc/hosts into
|
||||
a local-zone and local-data include file for unbound.conf.
|
||||
* unbound-host.nagios.patch: makes unbound-host return status that fits right
|
||||
in with the nagios monitoring framework. Contributed by Migiel de Vos.
|
||||
* unbound_unixsock.diff: Add Unix socket support for unbound-control.
|
||||
Contributed by Ilya Bakulin, 2012-08-28.
|
||||
* patch_rsamd5_enable.diff: this patch enables RSAMD5 validation (otherwise
|
||||
it is treated as insecure). The RSAMD5 algorithm is deprecated (RFC6725).
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
Index: validator/val_secalgo.c
|
||||
===================================================================
|
||||
--- validator/val_secalgo.c (revision 2759)
|
||||
+++ validator/val_secalgo.c (working copy)
|
||||
@@ -153,7 +153,7 @@
|
||||
switch(id) {
|
||||
case LDNS_RSAMD5:
|
||||
/* RFC 6725 deprecates RSAMD5 */
|
||||
- return 0;
|
||||
+ return 1;
|
||||
case LDNS_DSA:
|
||||
case LDNS_DSA_NSEC3:
|
||||
case LDNS_RSASHA1:
|
||||
@@ -617,7 +617,7 @@
|
||||
switch(id) {
|
||||
case LDNS_RSAMD5:
|
||||
/* RFC 6725 deprecates RSAMD5 */
|
||||
- return 0;
|
||||
+ return 1;
|
||||
case LDNS_DSA:
|
||||
case LDNS_DSA_NSEC3:
|
||||
case LDNS_RSASHA1:
|
||||
@@ -1,46 +0,0 @@
|
||||
#/usr/bin/env bash
|
||||
# Contributed by Tom Hendrikx <tom@whyscream.net>
|
||||
|
||||
PROGNAME=$(basename $0)
|
||||
|
||||
usage() {
|
||||
echo "$PROGNAME: split the anchors.mf file from IANA into separate files." >&2
|
||||
echo "" >&2
|
||||
echo "$PROGNAME uses 2 arguments:" >&2
|
||||
echo " - the path to the anchors.mf, available at: https://itar.iana.org/" >&2
|
||||
echo " - the directory to leave the files, defaults to '.' (current working dir)" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ -n "$1" ] && [ -r "$1" ]; then
|
||||
itar="$1"
|
||||
echo "Reading from: $itar"
|
||||
else
|
||||
echo "Error: no anchors file given" >&2
|
||||
usage
|
||||
fi
|
||||
|
||||
if [ -n "$2" ]; then
|
||||
dir="$2"
|
||||
else
|
||||
dir=$(pwd)
|
||||
fi
|
||||
|
||||
if [ ! -d "$dir" ]; then
|
||||
echo "Error: $dir is not a directory" >&2
|
||||
usage
|
||||
fi
|
||||
|
||||
while read cn line; do
|
||||
if [ $(expr match "$cn" '[a-zA-Z0-9-]*\.') -gt 0 ]; then
|
||||
# first line of key
|
||||
out="$dir/$cn"anchor
|
||||
echo "writing key for $cn to: $out"
|
||||
echo "$cn $line" > $out
|
||||
elif [ "$cn" == "DS" ]; then
|
||||
# second or later line of earlier defined key
|
||||
echo " $cn $line" >> $out
|
||||
fi
|
||||
done < "$itar"
|
||||
|
||||
echo "Done."
|
||||
@@ -0,0 +1,134 @@
|
||||
Index: smallapp/unbound-host.c
|
||||
===================================================================
|
||||
--- smallapp/unbound-host.c (revision 2115)
|
||||
+++ smallapp/unbound-host.c (working copy)
|
||||
@@ -62,9 +62,18 @@
|
||||
#include "libunbound/unbound.h"
|
||||
#include <ldns/ldns.h>
|
||||
|
||||
+/** status variable ala nagios */
|
||||
+#define FINAL_STATUS_OK 0
|
||||
+#define FINAL_STATUS_WARNING 1
|
||||
+#define FINAL_STATUS_CRITICAL 2
|
||||
+#define FINAL_STATUS_UNKNOWN 3
|
||||
+
|
||||
/** verbosity for unbound-host app */
|
||||
static int verb = 0;
|
||||
|
||||
+/** variable to determine final output */
|
||||
+static int final_status = FINAL_STATUS_UNKNOWN;
|
||||
+
|
||||
/** Give unbound-host usage, and exit (1). */
|
||||
static void
|
||||
usage()
|
||||
@@ -93,7 +102,7 @@
|
||||
printf("Version %s\n", PACKAGE_VERSION);
|
||||
printf("BSD licensed, see LICENSE in source package for details.\n");
|
||||
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
|
||||
- exit(1);
|
||||
+ exit(FINAL_STATUS_UNKNOWN);
|
||||
}
|
||||
|
||||
/** determine if str is ip4 and put into reverse lookup format */
|
||||
@@ -138,7 +147,7 @@
|
||||
*res = strdup(buf);
|
||||
if(!*res) {
|
||||
fprintf(stderr, "error: out of memory\n");
|
||||
- exit(1);
|
||||
+ exit(FINAL_STATUS_UNKNOWN);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -158,7 +167,7 @@
|
||||
}
|
||||
if(!res) {
|
||||
fprintf(stderr, "error: out of memory\n");
|
||||
- exit(1);
|
||||
+ exit(FINAL_STATUS_UNKNOWN);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -172,7 +181,7 @@
|
||||
if(r == 0 && strcasecmp(t, "TYPE0") != 0 &&
|
||||
strcmp(t, "") != 0) {
|
||||
fprintf(stderr, "error unknown type %s\n", t);
|
||||
- exit(1);
|
||||
+ exit(FINAL_STATUS_UNKNOWN);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
@@ -191,7 +200,7 @@
|
||||
if(r == 0 && strcasecmp(c, "CLASS0") != 0 &&
|
||||
strcmp(c, "") != 0) {
|
||||
fprintf(stderr, "error unknown class %s\n", c);
|
||||
- exit(1);
|
||||
+ exit(FINAL_STATUS_UNKNOWN);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
@@ -207,6 +216,19 @@
|
||||
return "(insecure)";
|
||||
}
|
||||
|
||||
+/** update the final status for the exit code */
|
||||
+void
|
||||
+update_final_status(struct ub_result* result)
|
||||
+{
|
||||
+ if (final_status == FINAL_STATUS_UNKNOWN || final_status == FINAL_STATUS_OK) {
|
||||
+ if (result->secure) final_status = FINAL_STATUS_OK;
|
||||
+ else if (result->bogus) final_status = FINAL_STATUS_CRITICAL;
|
||||
+ else final_status = FINAL_STATUS_WARNING;
|
||||
+ }
|
||||
+ else if (final_status == FINAL_STATUS_WARNING && result->bogus)
|
||||
+ final_status = FINAL_STATUS_CRITICAL;
|
||||
+}
|
||||
+
|
||||
/** nice string for type */
|
||||
static void
|
||||
pretty_type(char* s, size_t len, int t)
|
||||
@@ -353,7 +375,7 @@
|
||||
} else {
|
||||
fprintf(stderr, "could not parse "
|
||||
"reply packet to ANY query\n");
|
||||
- exit(1);
|
||||
+ exit(FINAL_STATUS_UNKNOWN);
|
||||
}
|
||||
ldns_pkt_free(p);
|
||||
|
||||
@@ -388,9 +410,10 @@
|
||||
ret = ub_resolve(ctx, q, t, c, &result);
|
||||
if(ret != 0) {
|
||||
fprintf(stderr, "resolve error: %s\n", ub_strerror(ret));
|
||||
- exit(1);
|
||||
+ exit(FINAL_STATUS_UNKNOWN);
|
||||
}
|
||||
pretty_output(q, t, c, result, docname);
|
||||
+ update_final_status(result);
|
||||
ret = result->nxdomain;
|
||||
ub_resolve_free(result);
|
||||
return ret;
|
||||
@@ -427,7 +450,7 @@
|
||||
{
|
||||
if(r != 0) {
|
||||
fprintf(stderr, "error: %s\n", ub_strerror(r));
|
||||
- exit(1);
|
||||
+ exit(FINAL_STATUS_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,7 +471,7 @@
|
||||
ctx = ub_ctx_create();
|
||||
if(!ctx) {
|
||||
fprintf(stderr, "error: out of memory\n");
|
||||
- exit(1);
|
||||
+ exit(FINAL_STATUS_UNKNOWN);
|
||||
}
|
||||
|
||||
/* parse the options */
|
||||
@@ -509,5 +532,5 @@
|
||||
usage();
|
||||
|
||||
lookup(ctx, argv[0], qtype, qclass);
|
||||
- return 0;
|
||||
+ return final_status;
|
||||
}
|
||||
+15
-6
@@ -1,14 +1,15 @@
|
||||
Summary: Validating, recursive, and caching DNS resolver
|
||||
Name: unbound
|
||||
Version: 1.0.1
|
||||
Version: 1.4.18
|
||||
Release: 1%{?dist}
|
||||
License: BSD
|
||||
Url: http://www.nlnetlabs.nl/unbound/
|
||||
Source: http://www.unbound.net/downloads/%{name}-%{version}.tar.gz
|
||||
#Source1: unbound.init
|
||||
Group: System Environment/Daemons
|
||||
Requires: ldns
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
BuildRequires: flex, openssl-devel
|
||||
BuildRequires: flex, openssl-devel, expat-devel, ldns-devel
|
||||
|
||||
%description
|
||||
Unbound is a validating, recursive, and caching DNS resolver.
|
||||
@@ -28,10 +29,6 @@ The source code is under a BSD License.
|
||||
|
||||
# configure with /var/unbound/unbound.conf so that all default chroot,
|
||||
# pidfile and config file are in /var/unbound, ready for chroot jail set up.
|
||||
#
|
||||
# This is a build using libldns builtin version, the resulting binaries
|
||||
# do not require libldns and this package does not have version dependencies.
|
||||
# Could be smaller using a dependency on libldns (use --with-ldns=).
|
||||
%configure --with-conf-file=%{_localstatedir}/%{name}/unbound.conf --disable-rpath
|
||||
|
||||
%build
|
||||
@@ -92,6 +89,18 @@ if [ "$1" -ge "1" ]; then
|
||||
fi
|
||||
|
||||
%changelog
|
||||
* Thu Jul 13 2011 Wouter Wijngaards <wouter@nlnetlabs.nl> - 1.4.8
|
||||
- ldns required and ldns-devel required for build, no more ldns-builtin.
|
||||
|
||||
* Thu Mar 17 2011 Wouter Wijngaards <wouter@nlnetlabs.nl> - 1.4.8
|
||||
- removed --disable-gost, assume recent openssl on the destination platform.
|
||||
|
||||
* Wed Mar 16 2011 Harold Jones <hajones@verisign.com> - 1.4.8
|
||||
- Bump version number to latest
|
||||
- Add expat-devel to BuildRequires
|
||||
- Added --disable-gost for building on CentOS 5.x
|
||||
- Added --with-ldns-builtin for CentOS 5.x
|
||||
|
||||
* Thu May 22 2008 Wouter Wijngaards <wouter@nlnetlabs.nl> - 1.0.0
|
||||
- contrib changes from Patrick Vande Walle.
|
||||
|
||||
|
||||
+108
-14
@@ -8,7 +8,7 @@
|
||||
|
||||
Summary: Validating, recursive, and caching DNS(SEC) resolver
|
||||
Name: unbound
|
||||
Version: 1.4.2
|
||||
Version: 1.4.13
|
||||
Release: 1%{?dist}
|
||||
License: BSD
|
||||
Url: http://www.nlnetlabs.nl/unbound/
|
||||
@@ -16,16 +16,20 @@ Source: http://www.unbound.net/downloads/%{name}-%{version}.tar.gz
|
||||
Source1: unbound.init
|
||||
Source2: unbound.conf
|
||||
Source3: unbound.munin
|
||||
Source4: dlv.isc.org.key
|
||||
Source4: unbound_munin_
|
||||
Source5: root.key
|
||||
Source6: dlv.isc.org.key
|
||||
Patch1: unbound-1.2-glob.patch
|
||||
|
||||
Group: System Environment/Daemons
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
BuildRequires: flex, openssl-devel , ldns-devel >= 1.5.0,
|
||||
BuildRequires: libevent-devel
|
||||
BuildRequires: libevent-devel expat-devel
|
||||
%if %{with_python}
|
||||
BuildRequires: python-devel
|
||||
BuildRequires: python-devel swig
|
||||
%endif
|
||||
# Required for SVN versions
|
||||
# BuildRequires: bison
|
||||
|
||||
Requires(post): chkconfig
|
||||
Requires(preun): chkconfig
|
||||
@@ -34,6 +38,9 @@ Requires(postun): initscripts
|
||||
Requires: ldns >= 1.5.0
|
||||
Requires(pre): shadow-utils
|
||||
|
||||
Obsoletes: dnssec-conf < 1.27-2
|
||||
Provides: dnssec-conf = 1.27-1
|
||||
|
||||
%description
|
||||
Unbound is a validating, recursive, and caching DNS(SEC) resolver.
|
||||
|
||||
@@ -67,7 +74,7 @@ Summary: Libraries used by the unbound server and client applications
|
||||
Group: Applications/System
|
||||
Requires(post): /sbin/ldconfig
|
||||
Requires(postun): /sbin/ldconfig
|
||||
Requires: openssl >= 0.9.8g-12
|
||||
Requires: openssl
|
||||
|
||||
%description libs
|
||||
Contains libraries used by the unbound server and client applications
|
||||
@@ -88,14 +95,14 @@ Python modules and extensions for unbound
|
||||
|
||||
%build
|
||||
%configure --with-ldns= --with-libevent --with-pthreads --with-ssl \
|
||||
--disable-rpath --enable-debug --disable-static \
|
||||
--disable-rpath --disable-static \
|
||||
--with-conf-file=%{_sysconfdir}/%{name}/unbound.conf \
|
||||
--with-pidfile=%{_localstatedir}/run/%{name}/%{name}.pid \
|
||||
%if %{with_python}
|
||||
--with-pythonmodule --with-pyunbound \
|
||||
%endif
|
||||
--enable-sha2
|
||||
%{__make}
|
||||
--enable-sha2 --disable-gost
|
||||
%{__make} %{?_smp_mflags}
|
||||
|
||||
%install
|
||||
rm -rf %{buildroot}
|
||||
@@ -107,16 +114,19 @@ install -m 0755 %{SOURCE2} %{buildroot}%{_sysconfdir}/unbound
|
||||
install -d 0755 %{buildroot}%{_sysconfdir}/munin/plugin-conf.d
|
||||
install -m 0644 %{SOURCE3} %{buildroot}%{_sysconfdir}/munin/plugin-conf.d/unbound
|
||||
install -d 0755 %{buildroot}%{_datadir}/munin/plugins/
|
||||
install -m 0755 contrib/unbound_munin_ %{buildroot}%{_datadir}/munin/plugins/unbound
|
||||
install -m 0755 %{SOURCE4} %{buildroot}%{_datadir}/munin/plugins/unbound
|
||||
for plugin in unbound_munin_hits unbound_munin_queue unbound_munin_memory unbound_munin_by_type unbound_munin_by_class unbound_munin_by_opcode unbound_munin_by_rcode unbound_munin_by_flags unbound_munin_histogram; do
|
||||
ln -s unbound %{buildroot}%{_datadir}/munin/plugins/$plugin
|
||||
done
|
||||
|
||||
# install DLV key
|
||||
install -m 0644 %{SOURCE4} %{buildroot}%{_sysconfdir}/unbound/
|
||||
# install root and DLV key
|
||||
install -m 0644 %{SOURCE5} %{SOURCE6} %{buildroot}%{_sysconfdir}/unbound/
|
||||
|
||||
# remove static library from install (fedora packaging guidelines)
|
||||
rm -rf %{buildroot}%{_libdir}/*.la
|
||||
rm %{buildroot}%{_libdir}/*.la
|
||||
%if %{with_python}
|
||||
rm %{buildroot}%{python_sitearch}/*.la
|
||||
%endif
|
||||
|
||||
mkdir -p %{buildroot}%{_localstatedir}/run/unbound
|
||||
|
||||
@@ -128,15 +138,19 @@ rm -rf ${RPM_BUILD_ROOT}
|
||||
%doc doc/README doc/CREDITS doc/LICENSE doc/FEATURES
|
||||
%attr(0755,root,root) %{_initrddir}/%{name}
|
||||
%attr(0755,root,root) %dir %{_sysconfdir}/%{name}
|
||||
%attr(0755,unbound,unbound) %dir %{_localstatedir}/run/%{name}
|
||||
%ghost %attr(0755,unbound,unbound) %dir %{_localstatedir}/run/%{name}
|
||||
%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/%{name}/unbound.conf
|
||||
%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/%{name}/dlv.isc.org.key
|
||||
%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/%{name}/root.key
|
||||
%{_sbindir}/*
|
||||
%{_mandir}/*/*
|
||||
|
||||
%if %{with_python}
|
||||
%files python
|
||||
%{python_sitelib}/*
|
||||
%defattr(-,root,root,-)
|
||||
%{python_sitearch}/*
|
||||
%doc libunbound/python/examples/*
|
||||
%doc pythonmod/examples/*
|
||||
%endif
|
||||
|
||||
%files munin
|
||||
@@ -186,10 +200,90 @@ fi
|
||||
%postun libs -p /sbin/ldconfig
|
||||
|
||||
%changelog
|
||||
* Tue Sep 06 2011 Paul Wouters <paul@xelerance.com> - 1.4.13-1
|
||||
- Updated to 1.4.13
|
||||
- Fix install location of pythonmod from sitelib to sitearch
|
||||
- Removed patches merged in by upstream
|
||||
- Removed versioned openssl dep, it differs per branch
|
||||
|
||||
* Mon Aug 08 2011 Paul Wouters <paul@xelerance.com> - 1.4.12-3
|
||||
- Added pythonmod docs and examples
|
||||
- Fix for python module load in the server (Tom Hendrikx)
|
||||
- No longer enable --enable-debug as it causes degraded performance
|
||||
under load.
|
||||
|
||||
* Mon Jul 18 2011 Paul Wouters <paul@xelerance.com> - 1.4.12-1
|
||||
- Updated to 1.4.12
|
||||
|
||||
* Sun Jul 03 2011 Paul Wouters <paul@xelerance.com> - 1.4.11-1
|
||||
- Updated to 1.4.11
|
||||
- removed integrated CVE patch
|
||||
- updated stock unbound.conf for new options introduced
|
||||
|
||||
* Mon Jun 06 2011 Paul Wouters <paul@xelerance.com> - 1.4.10-1
|
||||
- Added ghost for /var/run/unbound (bz#656710)
|
||||
|
||||
* Mon Jun 06 2011 Paul Wouters <paul@xelerance.com> - 1.4.9-3
|
||||
- rebuilt
|
||||
|
||||
* Wed May 25 2011 Paul Wouters <paul@xelerance.com> - 1.4.9-2
|
||||
- Applied patch for CVE-2011-1922 DoS vulnerability
|
||||
|
||||
* Sun Mar 27 2011 Paul Wouters <paul@xelerance.com> - 1.4.9-1
|
||||
- Updated to 1.4.9
|
||||
|
||||
* Sat Feb 12 2011 Paul Wouters <paul@xelerance.com> - 1.4.8-2
|
||||
- rebuilt
|
||||
|
||||
* Tue Jan 25 2011 Paul Wouters <paul@xelerance.com> - 1.4.8-1
|
||||
- Updated to 1.4.8
|
||||
- Enable root key for DNSSEC
|
||||
- Fix unbound-munin to use proper file (could cause excessive logging)
|
||||
- Build unbound-python per default
|
||||
- Disable gost as Fedora/EPEL does not allow ECC and has mangled openssl
|
||||
|
||||
* Tue Oct 26 2010 Paul Wouters <paul@xelerance.com> - 1.4.5-4
|
||||
- Revert last build - it was on the wrong branch
|
||||
|
||||
* Tue Oct 26 2010 Paul Wouters <paul@xelerance.com> - 1.4.5-3
|
||||
- Disable do-ipv6 per default - causes severe degradation on non-ipv6 machines
|
||||
(see comments in inbound.conf)
|
||||
|
||||
* Tue Jun 15 2010 Paul Wouters <paul@xelerance.com> - 1.4.5-2
|
||||
- Bump release - forgot to upload the new tar ball.
|
||||
|
||||
* Tue Jun 15 2010 Paul Wouters <paul@xelerance.com> - 1.4.5-1
|
||||
- Upgraded to 1.4.5
|
||||
|
||||
* Mon May 31 2010 Paul Wouters <paul@xelerance.com> - 1.4.4-2
|
||||
- Added accidentally omitted svn patches to cvs
|
||||
|
||||
* Mon May 31 2010 Paul Wouters <paul@xelerance.com> - 1.4.4-1
|
||||
- Upgraded to 1.4.4 with svn patches
|
||||
- Obsolete dnssec-conf to ensure it is de-installed
|
||||
|
||||
* Thu Mar 11 2010 Paul Wouters <paul@xelerance.com> - 1.4.3-1
|
||||
- Update to 1.4.3 that fixes 64bit crasher
|
||||
|
||||
* Tue Mar 09 2010 Paul Wouters <paul@xelerance.com> - 1.4.2-1
|
||||
- Updated to 1.4.2
|
||||
- Updated unbound.conf with new options
|
||||
- Enabled pre-fetching DNSKEY records (DNSSEC speedup)
|
||||
- Enabled re-fetching popular records before they expire
|
||||
- Enabled logging of DNSSEC validation errors
|
||||
|
||||
* Mon Mar 01 2010 Paul Wouters <paul@xelerance.com> - 1.4.1-5
|
||||
- Overriding -D_GNU_SOURCE is no longer needed. This fixes DSO issues
|
||||
with pthreads
|
||||
|
||||
* Wed Feb 24 2010 Paul Wouters <paul@xelerance.com> - 1.4.1-3
|
||||
- Change make/configure lines to attempt to fix -lphtread linking issue
|
||||
|
||||
* Thu Feb 18 2010 Paul Wouters <paul@xelerance.com> - 1.4.1-2
|
||||
- Removed dependancy for dnssec-conf
|
||||
- Added ISC DLV key (formerly in dnssec-conf)
|
||||
- Fixup old DLV locations in unbound.conf file via %%post
|
||||
- Fix parent child disagreement handling and no-ipv6 present [svn r1953]
|
||||
|
||||
* Tue Jan 05 2010 Paul Wouters <paul@xelerance.com> - 1.4.1-1
|
||||
- Updated to 1.4.1
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# plugin for munin to monitor usage of unbound servers.
|
||||
# To install copy this to /usr/local/share/munin/plugins/unbound_munin_
|
||||
# and use munin-node-configure (--suggest, --shell).
|
||||
#
|
||||
# (C) 2008 W.C.A. Wijngaards. BSD Licensed.
|
||||
#
|
||||
@@ -45,9 +47,9 @@
|
||||
# unbound_munin_histogram - histogram of query resolving times
|
||||
#
|
||||
# Magic markers - optional - used by installation scripts and
|
||||
# munin-config:
|
||||
# munin-config: (originally contrib family but munin-node-configure ignores it)
|
||||
#
|
||||
#%# family=contrib
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf suggest
|
||||
|
||||
# POD documentation
|
||||
@@ -175,7 +177,7 @@ if test "$1" = "autoconf" ; then
|
||||
exit 1
|
||||
fi
|
||||
if test ! -d `dirname $state`; then
|
||||
echo no "($state directory does not exist)"
|
||||
echo no "(`dirname $state` directory does not exist)"
|
||||
exit 1
|
||||
fi
|
||||
echo yes
|
||||
@@ -228,9 +230,8 @@ if test "$1" = "config" ; then
|
||||
echo "graph_args --base 1000 -l 0"
|
||||
echo "graph_vlabel queries / second"
|
||||
echo "graph_category DNS"
|
||||
for x in thread0.num.queries thread1.num.queries \
|
||||
thread2.num.queries thread3.num.queries thread4.num.queries \
|
||||
thread5.num.queries thread6.num.queries thread7.num.queries; do
|
||||
for x in `grep "^thread[0-9][0-9]*\.num\.queries=" $state |
|
||||
sed -e 's/=.*//'`; do
|
||||
exist_config $x "queries handled by `basename $x .num.queries`"
|
||||
done
|
||||
p_config "total.num.queries" "total queries from clients"
|
||||
@@ -421,9 +422,8 @@ print_value ( ) {
|
||||
|
||||
case $id in
|
||||
hits)
|
||||
for x in thread0.num.queries thread1.num.queries thread2.num.queries \
|
||||
thread3.num.queries thread4.num.queries thread5.num.queries \
|
||||
thread6.num.queries thread7.num.queries total.num.queries \
|
||||
for x in `grep "^thread[0-9][0-9]*\.num\.queries=" $state |
|
||||
sed -e 's/=.*//'` total.num.queries \
|
||||
total.num.cachehits total.num.prefetch num.query.tcp \
|
||||
num.query.ipv6 unwanted.queries unwanted.replies; do
|
||||
if grep "^"$x"=" $state >/dev/null 2>&1; then
|
||||
|
||||
@@ -0,0 +1,305 @@
|
||||
diff --git a/daemon/remote.c b/daemon/remote.c
|
||||
index a2b2204..b6990f3 100644
|
||||
--- a/daemon/remote.c
|
||||
+++ b/daemon/remote.c
|
||||
@@ -81,6 +81,11 @@
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
+#ifdef HAVE_PWD_H
|
||||
+#include <pwd.h>
|
||||
+#include <sys/stat.h>
|
||||
+#include <fcntl.h>
|
||||
+#endif
|
||||
|
||||
/* just for portability */
|
||||
#ifdef SQ
|
||||
@@ -235,7 +240,8 @@ void daemon_remote_delete(struct daemon_remote* rc)
|
||||
* @return false on failure.
|
||||
*/
|
||||
static int
|
||||
-add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err)
|
||||
+add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
|
||||
+ struct config_file* cfg)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
struct addrinfo* res;
|
||||
@@ -246,29 +252,74 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err)
|
||||
snprintf(port, sizeof(port), "%d", nr);
|
||||
port[sizeof(port)-1]=0;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
- hints.ai_socktype = SOCK_STREAM;
|
||||
- hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
|
||||
- if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) {
|
||||
-#ifdef USE_WINSOCK
|
||||
- if(!noproto_is_err && r == EAI_NONAME) {
|
||||
- /* tried to lookup the address as name */
|
||||
- return 1; /* return success, but do nothing */
|
||||
+
|
||||
+ if(ip[0] == '/') {
|
||||
+ /* This looks like UNIX socket! */
|
||||
+ fd = create_domain_accept_sock(ip);
|
||||
+/*
|
||||
+ * When unbound starts, it first creates a socket and then
|
||||
+ * drops privs, so the socket is created as root user.
|
||||
+ * This is fine, but we would like to set _unbound user group
|
||||
+ * for this socket, and permissions should be 0660 so only
|
||||
+ * root and _unbound group members can invoke unbound-control.
|
||||
+ * The username used here is the same as username that unbound
|
||||
+ * uses for its worker processes.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * Note: this code is an exact copy of code from daemon.c
|
||||
+ * Normally this should be either wrapped into a function,
|
||||
+ * or gui/gid values should be retrieved at config parsing time
|
||||
+ * and then stored in configfile structure.
|
||||
+ * This requires action from unbound developers!
|
||||
+*/
|
||||
+#ifdef HAVE_GETPWNAM
|
||||
+ struct passwd *pwd = NULL;
|
||||
+ uid_t uid;
|
||||
+ gid_t gid;
|
||||
+ /* initialize, but not to 0 (root) */
|
||||
+ memset(&uid, 112, sizeof(uid));
|
||||
+ memset(&gid, 112, sizeof(gid));
|
||||
+ log_assert(cfg);
|
||||
+
|
||||
+ if(cfg->username && cfg->username[0]) {
|
||||
+ if((pwd = getpwnam(cfg->username)) == NULL)
|
||||
+ fatal_exit("user '%s' does not exist.",
|
||||
+ cfg->username);
|
||||
+ uid = pwd->pw_uid;
|
||||
+ gid = pwd->pw_gid;
|
||||
+ endpwent();
|
||||
}
|
||||
+
|
||||
+ chown(ip, 0, gid);
|
||||
+ chmod(ip, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
||||
+#endif
|
||||
+ } else {
|
||||
+ hints.ai_socktype = SOCK_STREAM;
|
||||
+ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
|
||||
+ if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) {
|
||||
+#ifdef USE_WINSOCK
|
||||
+ if(!noproto_is_err && r == EAI_NONAME) {
|
||||
+ /* tried to lookup the address as name */
|
||||
+ return 1; /* return success, but do nothing */
|
||||
+ }
|
||||
#endif /* USE_WINSOCK */
|
||||
- log_err("control interface %s:%s getaddrinfo: %s %s",
|
||||
- ip?ip:"default", port, gai_strerror(r),
|
||||
+ log_err("control interface %s:%s getaddrinfo: %s %s",
|
||||
+ ip?ip:"default", port, gai_strerror(r),
|
||||
#ifdef EAI_SYSTEM
|
||||
r==EAI_SYSTEM?(char*)strerror(errno):""
|
||||
#else
|
||||
""
|
||||
#endif
|
||||
);
|
||||
- return 0;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* open fd */
|
||||
+ fd = create_tcp_accept_sock(res, 1, &noproto);
|
||||
+ freeaddrinfo(res);
|
||||
}
|
||||
|
||||
- /* open fd */
|
||||
- fd = create_tcp_accept_sock(res, 1, &noproto);
|
||||
- freeaddrinfo(res);
|
||||
if(fd == -1 && noproto) {
|
||||
if(!noproto_is_err)
|
||||
return 1; /* return success, but do nothing */
|
||||
@@ -305,7 +356,7 @@ struct listen_port* daemon_remote_open_ports(struct config_file* cfg)
|
||||
if(cfg->control_ifs) {
|
||||
struct config_strlist* p;
|
||||
for(p = cfg->control_ifs; p; p = p->next) {
|
||||
- if(!add_open(p->str, cfg->control_port, &l, 1)) {
|
||||
+ if(!add_open(p->str, cfg->control_port, &l, 1, cfg)) {
|
||||
listening_ports_free(l);
|
||||
return NULL;
|
||||
}
|
||||
@@ -313,12 +364,12 @@ struct listen_port* daemon_remote_open_ports(struct config_file* cfg)
|
||||
} else {
|
||||
/* defaults */
|
||||
if(cfg->do_ip6 &&
|
||||
- !add_open("::1", cfg->control_port, &l, 0)) {
|
||||
+ !add_open("::1", cfg->control_port, &l, 0, cfg)) {
|
||||
listening_ports_free(l);
|
||||
return NULL;
|
||||
}
|
||||
if(cfg->do_ip4 &&
|
||||
- !add_open("127.0.0.1", cfg->control_port, &l, 1)) {
|
||||
+ !add_open("127.0.0.1", cfg->control_port, &l, 1, cfg)) {
|
||||
listening_ports_free(l);
|
||||
return NULL;
|
||||
}
|
||||
diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c
|
||||
index ea7ec3a..4cb04e2 100644
|
||||
--- a/services/listen_dnsport.c
|
||||
+++ b/services/listen_dnsport.c
|
||||
@@ -55,6 +55,10 @@
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
+#ifndef USE_WINSOCK
|
||||
+#include <sys/un.h>
|
||||
+#endif
|
||||
+
|
||||
/** number of queued TCP connections for listen() */
|
||||
#define TCP_BACKLOG 5
|
||||
|
||||
@@ -376,6 +380,53 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
}
|
||||
|
||||
int
|
||||
+create_domain_accept_sock(char *path) {
|
||||
+ int s;
|
||||
+ struct sockaddr_un unixaddr;
|
||||
+
|
||||
+#ifndef USE_WINSOCK
|
||||
+ unixaddr.sun_len = sizeof(unixaddr);
|
||||
+ unixaddr.sun_family = AF_UNIX;
|
||||
+ strlcpy(unixaddr.sun_path, path, 104);
|
||||
+
|
||||
+ if((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
||||
+ log_err("Cannot create UNIX socket %s (%s)",
|
||||
+ path, strerror(errno));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if(unlink(path) && errno != ENOENT) {
|
||||
+ /* The socket already exists and cannot be removed */
|
||||
+ log_err("Cannot remove old UNIX socket %s (%s)",
|
||||
+ path, strerror(errno));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if(bind(s, (struct sockaddr *) &unixaddr,
|
||||
+ sizeof(struct sockaddr_un)) == -1) {
|
||||
+ log_err("Cannot bind UNIX socket %s (%s)",
|
||||
+ path, strerror(errno));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if(!fd_set_nonblock(s)) {
|
||||
+ log_err("Cannot set non-blocking mode");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if(listen(s, TCP_BACKLOG) == -1) {
|
||||
+ log_err("can't listen: %s", strerror(errno));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return s;
|
||||
+#else
|
||||
+ log_err("UNIX sockets are not supported");
|
||||
+ return -1;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+int
|
||||
create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto)
|
||||
{
|
||||
int s;
|
||||
diff --git a/smallapp/unbound-control.c b/smallapp/unbound-control.c
|
||||
index a872f92..10631fd 100644
|
||||
--- a/smallapp/unbound-control.c
|
||||
+++ b/smallapp/unbound-control.c
|
||||
@@ -59,6 +59,8 @@
|
||||
#include "util/locks.h"
|
||||
#include "util/net_help.h"
|
||||
|
||||
+#include <sys/un.h>
|
||||
+
|
||||
/** Give unbound-control usage, and exit (1). */
|
||||
static void
|
||||
usage()
|
||||
@@ -158,6 +160,7 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen;
|
||||
+ int addrfamily = 0;
|
||||
int fd;
|
||||
/* use svr or the first config entry */
|
||||
if(!svr) {
|
||||
@@ -176,12 +179,21 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
|
||||
if(strchr(svr, '@')) {
|
||||
if(!extstrtoaddr(svr, &addr, &addrlen))
|
||||
fatal_exit("could not parse IP@port: %s", svr);
|
||||
+ } else if(svr[0] == '/') {
|
||||
+ struct sockaddr_un* unixsock = (struct sockaddr_un *) &addr;
|
||||
+ unixsock->sun_family = AF_UNIX;
|
||||
+ unixsock->sun_len = sizeof(unixsock);
|
||||
+ strlcpy(unixsock->sun_path, svr, 104);
|
||||
+ addrlen = sizeof(struct sockaddr_un);
|
||||
+ addrfamily = AF_UNIX;
|
||||
} else {
|
||||
if(!ipstrtoaddr(svr, cfg->control_port, &addr, &addrlen))
|
||||
fatal_exit("could not parse IP: %s", svr);
|
||||
}
|
||||
- fd = socket(addr_is_ip6(&addr, addrlen)?AF_INET6:AF_INET,
|
||||
- SOCK_STREAM, 0);
|
||||
+
|
||||
+ if(addrfamily != AF_UNIX)
|
||||
+ addrfamily = addr_is_ip6(&addr, addrlen)?AF_INET6:AF_INET;
|
||||
+ fd = socket(addrfamily, SOCK_STREAM, 0);
|
||||
if(fd == -1) {
|
||||
#ifndef USE_WINSOCK
|
||||
fatal_exit("socket: %s", strerror(errno));
|
||||
diff --git a/util/net_help.c b/util/net_help.c
|
||||
index b3136a3..5b5b4a3 100644
|
||||
--- a/util/net_help.c
|
||||
+++ b/util/net_help.c
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "util/module.h"
|
||||
#include "util/regional.h"
|
||||
#include <fcntl.h>
|
||||
+#include <sys/un.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
@@ -135,7 +136,7 @@ log_addr(enum verbosity_value v, const char* str,
|
||||
{
|
||||
uint16_t port;
|
||||
const char* family = "unknown";
|
||||
- char dest[100];
|
||||
+ char dest[108];
|
||||
int af = (int)((struct sockaddr_in*)addr)->sin_family;
|
||||
void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
|
||||
if(verbosity < v)
|
||||
@@ -148,15 +149,23 @@ log_addr(enum verbosity_value v, const char* str,
|
||||
case AF_UNIX: family="unix"; break;
|
||||
default: break;
|
||||
}
|
||||
- if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
|
||||
- strncpy(dest, "(inet_ntop error)", sizeof(dest));
|
||||
+
|
||||
+ if(af != AF_UNIX) {
|
||||
+ if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
|
||||
+ strncpy(dest, "(inet_ntop error)", sizeof(dest));
|
||||
+ }
|
||||
+ dest[sizeof(dest)-1] = 0;
|
||||
+ port = ntohs(((struct sockaddr_in*)addr)->sin_port);
|
||||
+ if(verbosity >= 4)
|
||||
+ verbose(v, "%s %s %s port %d (len %d)", str, family,
|
||||
+ dest, (int)port, (int)addrlen);
|
||||
+ else verbose(v, "%s %s port %d", str, dest, (int)port);
|
||||
+ } else {
|
||||
+ struct sockaddr_un* unixsock;
|
||||
+ unixsock = (struct sockaddr_un *) addr;
|
||||
+ strlcpy(dest, unixsock->sun_path, sizeof(dest));
|
||||
+ verbose(v, "%s %s %s", str, family, dest);
|
||||
}
|
||||
- dest[sizeof(dest)-1] = 0;
|
||||
- port = ntohs(((struct sockaddr_in*)addr)->sin_port);
|
||||
- if(verbosity >= 4)
|
||||
- verbose(v, "%s %s %s port %d (len %d)", str, family, dest,
|
||||
- (int)port, (int)addrlen);
|
||||
- else verbose(v, "%s %s port %d", str, dest, (int)port);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -1,128 +0,0 @@
|
||||
#!/bin/sh
|
||||
# update-itar.sh - update from the interim trust anchor repository
|
||||
# Copyright 2009, W.C.A. Wijngaards
|
||||
# This file is BSD licensed, see doc/LICENSE.
|
||||
|
||||
# --- Some settings
|
||||
|
||||
# directory where unbound works
|
||||
thedir="."
|
||||
# where is the file that unbound is going to read
|
||||
ub_ta_file="$thedir/anchors.mf"
|
||||
# where is the itar master file format
|
||||
itar_url="ftp://ftp.iana.org/itar/anchors.mf"
|
||||
# where is the itar PGP signature
|
||||
itar_sig="ftp://ftp.iana.org/itar/anchors.mf.sig"
|
||||
|
||||
# which command to fetch urls, cmd $dest $url. "wget -O" "curl -o"
|
||||
fetch_cmd="wget -O"
|
||||
# file with pgp public key
|
||||
pgp_pub_key_file="$thedir/update-itar.key"
|
||||
# our pgp keyring (goes into .gnupg directory)
|
||||
pgp_keyring_file="update-itar.ring"
|
||||
# pgp command to use
|
||||
pgp_cmd="gpg"
|
||||
|
||||
|
||||
# --- The script is below
|
||||
usage ( )
|
||||
{
|
||||
echo "usage: update-itar"
|
||||
echo " Updates the trust anchors from the interim trust"
|
||||
echo " anchor repository, https://itar.iana.org, and checks PGP sig."
|
||||
echo
|
||||
echo " Updates $ub_ta_file with the latest keys."
|
||||
echo " Read that file from the unbound config with"
|
||||
echo " trust-anchor-file: "'"'"$ub_ta_file"'"'
|
||||
echo
|
||||
echo " Exit code 0 means anchors updated, 1 no changes, "
|
||||
echo " others are errors. So, in a cronjob you can do:"
|
||||
echo " cd /usr/local/etc/unbound # your unbound work dir"
|
||||
echo " ./update-itar.sh && unbound-control reload"
|
||||
exit 2
|
||||
}
|
||||
|
||||
if test $# -ne 0; then
|
||||
usage
|
||||
fi
|
||||
tmpf="/tmp/update-itar.$$"
|
||||
|
||||
# one argument: explanation string
|
||||
error_exit ( )
|
||||
{
|
||||
if test -f $tmpf.log; then cat $tmpf.log; fi
|
||||
rm -f $tmpf $tmpf.sig $tmpf.log
|
||||
echo "Error updating trust anchors: $1"
|
||||
exit 2
|
||||
}
|
||||
|
||||
if test ! -f $pgp_pub_key_file || test ! -f $HOME/.gnupg/$pgp_keyring_file || \
|
||||
test "$pgp_pub_key_file" -nt $HOME/.gnupg/$pgp_keyring_file; then
|
||||
# default key contents right here
|
||||
if test ! -f $pgp_pub_key_file; then
|
||||
echo "creating default IANA ITAR pgp key file"
|
||||
cat >$pgp_pub_key_file <<EOF
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: GnuPG v1.4.5
|
||||
|
||||
mQGiBElr2DcRBAC+6YK6eSP7rzstvnMPQXMrpvVfuIR5FeTpGuwae9JP78V/iOXr
|
||||
N0yW8Dn6kdAztCMuRizL1Ij9IgaD7pjn8h09VgR4cN4LDv75rcQeWLzNxKy4UNRF
|
||||
aStL77RcIoTblBeCgHAK9FLzd0XfTGZCNaLNy9BYVSLyADOVDIqgBcrvBwCglz03
|
||||
QhOMIgaSx/XuRh6kYtynZ6kD/2GXx6pFs57b7rww8yOpdurCSOMB1wuEXiIXznTI
|
||||
06ARiib0G5VDvOdpy0LDU2526Q9f/WAERlhcExTgnTFigG4mRksUiDrrai4GIr+6
|
||||
JaivcGFVYdZZ4mZ088jcwujS/UY3C0ryGR9ufYUDAnfx6frhSl6o6j5is+jeGndF
|
||||
JYRAA/9B/1OXNVwFSiIxnP2aPUwsT1li1vaW8dhA/5PcuPLOVvEjPc1Pc16HGLhE
|
||||
8CRmMn66LqB1ccInE5hLKGGvV3pctjan+IOhaq3OHt/a+buDtTPgykchMZ2k1AzT
|
||||
RYk+gksxpIl6yTZsBH4hoRt8auxEJW8AiYbNtXXkNuWcoQL40bQsSUFOQSBUcnVz
|
||||
dCBBbmNob3IgUmVwb3NpdG9yeSA8aXRhckBpYW5hLm9yZz6IYAQTEQIAIAUCSWvY
|
||||
NwIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEPR9+zCB1GT0GUAAn29/TacF
|
||||
Teh87dls8pmkjxS4pKf1AKCJS/MvzR54AblO4DNMyc9q0G4frrkCDQRJa9g3EAgA
|
||||
ywoLxF4HVb9o926UIXw8JxNIzDPkt8galAcKRUmHQMNa/QA80WMl9Ia6DIxavGlV
|
||||
I5O1fvms297RV2KSSBjKWn6G+0me80A7aw0eHNg7habM5VtzDz5DhJbQFdJV9aYV
|
||||
DoTSnY6uR6iSSRrdZNaYdlCwDS8lBCnOKoGMArHzVCa2EdCBeCUY/eObOXtu8Gm3
|
||||
nDkuWeLPv08/0lvtr6d6VoDUEVPEsJAPONEYtpz/D+EZddUraF+3JscWqfRApBOz
|
||||
/8WHaeTNdzIH+h1ntktiizA6eH40EM6coQQxtIRsxg1DPTxofdovreMkcMI0EUUP
|
||||
awDn8gDtgG3g6Ud5zCdknwAEDQf/W3rxrEN6OZxJvWti8Iu6KOgxtuINiAsimPPX
|
||||
qy9KHowyEE9EMPzgADjWC9Reyusr4CwcootjWw7ryUwU0fXvVULKhg32NzLsx/Ci
|
||||
WtgCPSR58WZ1KKhnoB05+PTrwzhU+u64Cd/vJtFqGxSrANl2FAkPswHJMr8dMwAz
|
||||
uni7zzLJ+homW1T5AaixwmN3jeDHWshJH9E9JIhr5Y/8AzMl1V10r2u1c2ej0lBJ
|
||||
Y4GegI5cYAEBerS9d+mrbPlvbJ8AfuAuEf0y/PWJh0z1+Kck5qIbXMn/rpMBYvLJ
|
||||
Uj5CfqWlh8+hxqSYJDXtLm8hBiQFiMEew0jOc2Tw4F91OZ+jyYhJBBgRAgAJBQJJ
|
||||
a9g3AhsMAAoJEPR9+zCB1GT0AUwAn2ZtBwAyVxppdeTqilXufUvAkvjbAJ9dUpR1
|
||||
9a17/5BvDDJcIxSEKTJmDw==
|
||||
=zCNZ
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
EOF
|
||||
fi
|
||||
# import the new key
|
||||
$pgp_cmd --no-default-keyring --keyring $pgp_keyring_file \
|
||||
--primary-keyring $pgp_keyring_file \
|
||||
--import $pgp_pub_key_file >$tmpf.log 2>&1 \
|
||||
|| error_exit "could not import pgp public key into keyring"
|
||||
fi
|
||||
|
||||
$fetch_cmd $tmpf $itar_url >$tmpf.log 2>&1 \
|
||||
|| error_exit "fetching $itar_url failed"
|
||||
tail -2 $tmpf | grep "; End of file" >/dev/null 2>&1 || \
|
||||
error_exit "The file fetched from $itar_url was partial"
|
||||
$fetch_cmd $tmpf.sig $itar_sig >$tmpf.log 2>&1 \
|
||||
|| error_exit "fetching $itar_sig failed"
|
||||
|
||||
# check the file with pgp
|
||||
$pgp_cmd --no-default-keyring --keyring $pgp_keyring_file \
|
||||
--verify $tmpf.sig $tmpf >$tmpf.log 2>&1 \
|
||||
|| error_exit "the PGP signature failed!"
|
||||
|
||||
# check for differences
|
||||
val=1
|
||||
if diff "$ub_ta_file" $tmpf 2>/dev/null ; then
|
||||
# echo "The interim trust anchor repository did not change."
|
||||
:
|
||||
else
|
||||
echo "Updating $ub_ta_file"
|
||||
cp $tmpf $ub_ta_file
|
||||
val=0
|
||||
fi
|
||||
|
||||
rm -f $tmpf $tmpf.sig $tmpf.log
|
||||
exit $val
|
||||
Executable
+117
@@ -0,0 +1,117 @@
|
||||
#!/bin/sh
|
||||
# validation reporter - reports validation failures to a collection server.
|
||||
# Copyright NLnet Labs, 2010
|
||||
# BSD license.
|
||||
|
||||
|
||||
###
|
||||
# Here is the configuration for the validation reporter
|
||||
# it greps the failure lines out of the log and sends them to a server.
|
||||
|
||||
# The pidfile for the reporter daemon.
|
||||
pidfile="/var/run/validation-reporter.pid"
|
||||
|
||||
# The logfile to watch for logged validation failures.
|
||||
logfile="/var/log/unbound.log"
|
||||
|
||||
# how to notify the upstream
|
||||
# nc is netcat, it sends tcp to given host port. It makes a tcp connection
|
||||
# and writes one log-line to it (grepped from the logfile).
|
||||
# the notify command can be: "nc the.server.name.org 1234"
|
||||
# the listening daemon could be: nc -lk 127.0.0.1 1234 >> outputfile &
|
||||
notify_cmd="nc localhost 1234"
|
||||
|
||||
|
||||
###
|
||||
# Below this line is the code for the validation reporter,
|
||||
# first the daemon itself, then the controller for the daemon.
|
||||
reporter_daemon() {
|
||||
trap "rm -f \"$pidfile\"" EXIT
|
||||
tail -F $logfile | grep --line-buffered "unbound.*info: validation failure" | \
|
||||
while read x; do
|
||||
echo "$x" | $notify_cmd
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
###
|
||||
# controller for daemon.
|
||||
start_daemon() {
|
||||
echo "starting reporter"
|
||||
nohup $0 rundaemon </dev/null >/dev/null 2>&1 &
|
||||
echo $! > "$pidfile"
|
||||
}
|
||||
|
||||
kill_daemon() {
|
||||
echo "stopping reporter"
|
||||
if test -s "$pidfile"; then
|
||||
kill `cat "$pidfile"`
|
||||
# check it is really dead
|
||||
if kill -0 `cat "$pidfile"` >/dev/null 2>&1; then
|
||||
sleep 1
|
||||
while kill -0 `cat "$pidfile"` >/dev/null 2>&1; do
|
||||
kill `cat "$pidfile"` >/dev/null 2>&1
|
||||
echo "waiting for reporter to stop"
|
||||
sleep 1
|
||||
done
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
get_status_daemon() {
|
||||
if test -s "$pidfile"; then
|
||||
if kill -0 `cat "$pidfile"`; then
|
||||
return 0;
|
||||
fi
|
||||
fi
|
||||
return 1;
|
||||
}
|
||||
|
||||
restart_daemon() {
|
||||
kill_daemon
|
||||
start_daemon
|
||||
}
|
||||
|
||||
condrestart_daemon() {
|
||||
if get_status_daemon; then
|
||||
echo "reporter ("`cat "$pidfile"`") is running"
|
||||
exit 0
|
||||
fi
|
||||
start_daemon
|
||||
exit 0
|
||||
}
|
||||
|
||||
status_daemon() {
|
||||
if get_status_daemon; then
|
||||
echo "reporter ("`cat "$pidfile"`") is running"
|
||||
exit 0
|
||||
fi
|
||||
echo "reporter is not running"
|
||||
exit 1
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
rundaemon)
|
||||
reporter_daemon
|
||||
;;
|
||||
start)
|
||||
start_daemon
|
||||
;;
|
||||
stop)
|
||||
kill_daemon
|
||||
;;
|
||||
restart)
|
||||
restart_daemon
|
||||
;;
|
||||
condrestart)
|
||||
condrestart_daemon
|
||||
;;
|
||||
status)
|
||||
status_daemon
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|condrestart|status}"
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
exit $?
|
||||
+1
-1
@@ -47,7 +47,7 @@
|
||||
#include "util/net_help.h"
|
||||
|
||||
struct acl_list*
|
||||
acl_list_create()
|
||||
acl_list_create(void)
|
||||
{
|
||||
struct acl_list* acl = (struct acl_list*)calloc(1,
|
||||
sizeof(struct acl_list));
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ struct acl_addr {
|
||||
* Create acl structure
|
||||
* @return new structure or NULL on error.
|
||||
*/
|
||||
struct acl_list* acl_list_create();
|
||||
struct acl_list* acl_list_create(void);
|
||||
|
||||
/**
|
||||
* Delete acl structure.
|
||||
|
||||
+47
-22
@@ -40,14 +40,13 @@
|
||||
* to text format.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <ldns/ldns.h>
|
||||
#include "daemon/cachedump.h"
|
||||
#include "daemon/remote.h"
|
||||
#include "daemon/worker.h"
|
||||
#include "daemon/daemon.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/modstack.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/net_help.h"
|
||||
@@ -403,7 +402,7 @@ load_rr(SSL* ssl, ldns_buffer* buf, struct regional* region,
|
||||
status = ldns_rr_new_frm_str(&rr, (char*)ldns_buffer_begin(buf),
|
||||
LDNS_DEFAULT_TTL, NULL, NULL);
|
||||
if(status != LDNS_STATUS_OK) {
|
||||
log_warn("error cannot parse rr :%s: %s",
|
||||
log_warn("error cannot parse rr: %s: %s",
|
||||
ldns_get_errorstr_by_id(status),
|
||||
(char*)ldns_buffer_begin(buf));
|
||||
return 0;
|
||||
@@ -420,7 +419,7 @@ load_rr(SSL* ssl, ldns_buffer* buf, struct regional* region,
|
||||
ldns_buffer_skip(buf, 2);
|
||||
status = ldns_rr_rdata2buffer_wire(buf, rr);
|
||||
if(status != LDNS_STATUS_OK) {
|
||||
log_warn("error cannot rr2wire :%s",
|
||||
log_warn("error cannot rr2wire: %s",
|
||||
ldns_get_errorstr_by_id(status));
|
||||
ldns_rr_free(rr);
|
||||
return 0;
|
||||
@@ -443,6 +442,12 @@ load_rr(SSL* ssl, ldns_buffer* buf, struct regional* region,
|
||||
rk->rk.rrset_class = htons(ldns_rr_get_class(rr));
|
||||
ldns_buffer_clear(buf);
|
||||
status = ldns_dname2buffer_wire(buf, ldns_rr_owner(rr));
|
||||
if(status != LDNS_STATUS_OK) {
|
||||
log_warn("error cannot dname2buffer: %s",
|
||||
ldns_get_errorstr_by_id(status));
|
||||
ldns_rr_free(rr);
|
||||
return 0;
|
||||
}
|
||||
ldns_buffer_flip(buf);
|
||||
rk->rk.dname_len = ldns_buffer_limit(buf);
|
||||
rk->rk.dname = regional_alloc_init(region,
|
||||
@@ -758,7 +763,7 @@ load_msg(SSL* ssl, ldns_buffer* buf, struct worker* worker)
|
||||
if(!go_on)
|
||||
return 1; /* skip this one, not all references satisfied */
|
||||
|
||||
if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0)) {
|
||||
if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL)) {
|
||||
log_warn("error out of memory");
|
||||
return 0;
|
||||
}
|
||||
@@ -795,7 +800,9 @@ print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp)
|
||||
{
|
||||
char buf[257];
|
||||
struct delegpt_addr* a;
|
||||
int lame, dlame, rlame, rtt, edns_vs, to, lost;
|
||||
int lame, dlame, rlame, rto, edns_vs, to, delay, entry_ttl,
|
||||
tA = 0, tAAAA = 0, tother = 0;
|
||||
struct rtt_info ri;
|
||||
uint8_t edns_lame_known;
|
||||
for(a = dp->target_list; a; a = a->next_target) {
|
||||
addr_to_str(&a->addr, a->addrlen, buf, sizeof(buf));
|
||||
@@ -806,30 +813,54 @@ print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp)
|
||||
return;
|
||||
}
|
||||
/* lookup in infra cache */
|
||||
delay=0;
|
||||
entry_ttl = infra_get_host_rto(worker->env.infra_cache,
|
||||
&a->addr, a->addrlen, dp->name, dp->namelen,
|
||||
&ri, &delay, *worker->env.now, &tA, &tAAAA, &tother);
|
||||
if(entry_ttl == -2 && ri.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
if(!ssl_printf(ssl, "expired, rto %d msec, tA %d "
|
||||
"tAAAA %d tother %d.\n", ri.rto, tA, tAAAA,
|
||||
tother))
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
if(entry_ttl == -1 || entry_ttl == -2) {
|
||||
if(!ssl_printf(ssl, "not in infra cache.\n"))
|
||||
return;
|
||||
continue; /* skip stuff not in infra cache */
|
||||
}
|
||||
|
||||
/* uses type_A because most often looked up, but other
|
||||
* lameness won't be reported then */
|
||||
if(!infra_get_lame_rtt(worker->env.infra_cache,
|
||||
&a->addr, a->addrlen, dp->name, dp->namelen,
|
||||
LDNS_RR_TYPE_A, &lame, &dlame, &rlame, &rtt, &lost,
|
||||
LDNS_RR_TYPE_A, &lame, &dlame, &rlame, &rto,
|
||||
*worker->env.now)) {
|
||||
if(!ssl_printf(ssl, "not in infra cache.\n"))
|
||||
return;
|
||||
continue; /* skip stuff not in infra cache */
|
||||
}
|
||||
if(!ssl_printf(ssl, "%s%s%s%srtt %d msec, %d lost. ",
|
||||
if(!ssl_printf(ssl, "%s%s%s%srto %d msec, ttl %d, ping %d "
|
||||
"var %d rtt %d, tA %d, tAAAA %d, tother %d",
|
||||
lame?"LAME ":"", dlame?"NoDNSSEC ":"",
|
||||
a->lame?"AddrWasParentSide ":"",
|
||||
rlame?"NoAuthButRecursive ":"", rtt, lost))
|
||||
rlame?"NoAuthButRecursive ":"", rto, entry_ttl,
|
||||
ri.srtt, ri.rttvar, rtt_notimeout(&ri),
|
||||
tA, tAAAA, tother))
|
||||
return;
|
||||
if(delay)
|
||||
if(!ssl_printf(ssl, ", probedelay %d", delay))
|
||||
return;
|
||||
if(infra_host(worker->env.infra_cache, &a->addr, a->addrlen,
|
||||
*worker->env.now, &edns_vs, &edns_lame_known, &to)) {
|
||||
dp->name, dp->namelen, *worker->env.now, &edns_vs,
|
||||
&edns_lame_known, &to)) {
|
||||
if(edns_vs == -1) {
|
||||
if(!ssl_printf(ssl, "noEDNS%s.",
|
||||
edns_lame_known?" probed":""))
|
||||
if(!ssl_printf(ssl, ", noEDNS%s.",
|
||||
edns_lame_known?" probed":" assumed"))
|
||||
return;
|
||||
} else {
|
||||
if(!ssl_printf(ssl, "EDNS %d%s.",
|
||||
edns_vs, edns_lame_known?" probed":""))
|
||||
if(!ssl_printf(ssl, ", EDNS %d%s.", edns_vs,
|
||||
edns_lame_known?" probed":" assumed"))
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -878,19 +909,12 @@ int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
|
||||
char b[260];
|
||||
struct query_info qinfo;
|
||||
struct iter_hints_stub* stub;
|
||||
struct iter_env* ie;
|
||||
regional_free_all(region);
|
||||
qinfo.qname = nm;
|
||||
qinfo.qname_len = nmlen;
|
||||
qinfo.qtype = LDNS_RR_TYPE_A;
|
||||
qinfo.qclass = LDNS_RR_CLASS_IN;
|
||||
|
||||
if(modstack_find(&worker->daemon->mods, "iterator") == -1) {
|
||||
return ssl_printf(ssl, "error: no iterator module\n");
|
||||
}
|
||||
ie = (struct iter_env*)worker->env.modinfo[modstack_find(&worker->
|
||||
daemon->mods, "iterator")];
|
||||
|
||||
dname_str(nm, b);
|
||||
if(!ssl_printf(ssl, "The following name servers are used for lookup "
|
||||
"of %s\n", b))
|
||||
@@ -935,7 +959,8 @@ int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
stub = hints_lookup_stub(ie->hints, nm, qinfo.qclass, dp);
|
||||
stub = hints_lookup_stub(worker->env.hints, nm, qinfo.qclass,
|
||||
dp);
|
||||
if(stub) {
|
||||
if(stub->noprime) {
|
||||
if(!ssl_printf(ssl, "The noprime stub servers "
|
||||
|
||||
+70
-19
@@ -40,6 +40,27 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#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
|
||||
|
||||
#ifdef HAVE_NSS
|
||||
#include <nss3/nss.h>
|
||||
#endif
|
||||
|
||||
#include <ldns/ldns.h>
|
||||
#include "daemon/daemon.h"
|
||||
#include "daemon/worker.h"
|
||||
#include "daemon/remote.h"
|
||||
@@ -47,6 +68,7 @@
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/storage/lookup3.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "services/cache/rrset.h"
|
||||
@@ -56,6 +78,7 @@
|
||||
#include "util/module.h"
|
||||
#include "util/random.h"
|
||||
#include "util/tube.h"
|
||||
#include "util/net_help.h"
|
||||
#include <signal.h>
|
||||
|
||||
/** How many quit requests happened. */
|
||||
@@ -115,7 +138,7 @@ static RETSIGTYPE record_sigh(int sig)
|
||||
* Stores signals to replay later.
|
||||
*/
|
||||
static void
|
||||
signal_handling_record()
|
||||
signal_handling_record(void)
|
||||
{
|
||||
if( signal(SIGTERM, record_sigh) == SIG_ERR ||
|
||||
#ifdef SIGQUIT
|
||||
@@ -153,7 +176,7 @@ signal_handling_playback(struct worker* wrk)
|
||||
}
|
||||
|
||||
struct daemon*
|
||||
daemon_init()
|
||||
daemon_init(void)
|
||||
{
|
||||
struct daemon* daemon = (struct daemon*)calloc(1,
|
||||
sizeof(struct daemon));
|
||||
@@ -172,20 +195,29 @@ daemon_init()
|
||||
#endif /* USE_WINSOCK */
|
||||
signal_handling_record();
|
||||
checklock_start();
|
||||
#ifdef HAVE_SSL
|
||||
ERR_load_crypto_strings();
|
||||
ERR_load_SSL_strings();
|
||||
#ifdef HAVE_OPENSSL_CONFIG
|
||||
# ifdef HAVE_OPENSSL_CONFIG
|
||||
OPENSSL_config("unbound");
|
||||
#endif
|
||||
#ifdef USE_GOST
|
||||
# endif
|
||||
# ifdef USE_GOST
|
||||
(void)ldns_key_EVP_load_gost_id();
|
||||
#endif
|
||||
# endif
|
||||
OpenSSL_add_all_algorithms();
|
||||
#if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS
|
||||
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS
|
||||
/* grab the COMP method ptr because openssl leaks it */
|
||||
comp_meth = (void*)SSL_COMP_get_compression_methods();
|
||||
#endif
|
||||
# endif
|
||||
(void)SSL_library_init();
|
||||
# if defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
|
||||
if(!ub_openssl_lock_init())
|
||||
fatal_exit("could not init openssl locks");
|
||||
# endif
|
||||
#elif defined(HAVE_NSS)
|
||||
if(NSS_NoDB_Init(NULL) != SECSuccess)
|
||||
fatal_exit("could not init NSS");
|
||||
#endif /* HAVE_SSL or HAVE_NSS */
|
||||
#ifdef HAVE_TZSET
|
||||
/* init timezone info while we are not chrooted yet */
|
||||
tzset();
|
||||
@@ -260,7 +292,7 @@ static void daemon_setup_modules(struct daemon* daemon)
|
||||
* @param shufport: the portlist output.
|
||||
* @return number of ports available.
|
||||
*/
|
||||
int daemon_get_shufport(struct daemon* daemon, int* shufport)
|
||||
static int daemon_get_shufport(struct daemon* daemon, int* shufport)
|
||||
{
|
||||
int i, n, k, temp;
|
||||
int avail = 0;
|
||||
@@ -276,7 +308,7 @@ int daemon_get_shufport(struct daemon* daemon, int* shufport)
|
||||
/* Knuth shuffle */
|
||||
n = avail;
|
||||
while(--n > 0) {
|
||||
k = ub_random(daemon->rand) % (n+1); /* 0<= k<= n */
|
||||
k = ub_random_max(daemon->rand, n+1); /* 0<= k<= n */
|
||||
temp = shufport[k];
|
||||
shufport[k] = shufport[n];
|
||||
shufport[n] = temp;
|
||||
@@ -304,13 +336,14 @@ daemon_create_workers(struct daemon* daemon)
|
||||
if(!daemon->rand)
|
||||
fatal_exit("could not init random generator");
|
||||
}
|
||||
hash_set_raninit((uint32_t)ub_random(daemon->rand));
|
||||
shufport = (int*)calloc(65536, sizeof(int));
|
||||
if(!shufport)
|
||||
fatal_exit("out of memory during daemon init");
|
||||
numport = daemon_get_shufport(daemon, shufport);
|
||||
verbose(VERB_ALGO, "total of %d outgoing ports available", numport);
|
||||
|
||||
daemon->num = daemon->cfg->num_threads;
|
||||
daemon->num = (daemon->cfg->num_threads?daemon->cfg->num_threads:1);
|
||||
daemon->workers = (struct worker**)calloc((size_t)daemon->num,
|
||||
sizeof(struct worker*));
|
||||
for(i=0; i<daemon->num; i++) {
|
||||
@@ -323,12 +356,13 @@ daemon_create_workers(struct daemon* daemon)
|
||||
free(shufport);
|
||||
}
|
||||
|
||||
#ifdef THREADS_DISABLED
|
||||
/**
|
||||
* Close all pipes except for the numbered thread.
|
||||
* @param daemon: daemon to close pipes in.
|
||||
* @param thr: thread number 0..num-1 of thread to skip.
|
||||
*/
|
||||
void close_other_pipes(struct daemon* daemon, int thr)
|
||||
static void close_other_pipes(struct daemon* daemon, int thr)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<daemon->num; i++)
|
||||
@@ -343,6 +377,7 @@ void close_other_pipes(struct daemon* daemon, int thr)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* THREADS_DISABLED */
|
||||
|
||||
/**
|
||||
* Function to start one thread.
|
||||
@@ -431,7 +466,7 @@ daemon_fork(struct daemon* daemon)
|
||||
*/
|
||||
daemon_create_workers(daemon);
|
||||
|
||||
#ifdef HAVE_EV_LOOP
|
||||
#if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
|
||||
/* in libev the first inited base gets signals */
|
||||
if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports, 1))
|
||||
fatal_exit("Could not initialize main thread");
|
||||
@@ -445,7 +480,7 @@ daemon_fork(struct daemon* daemon)
|
||||
/* Special handling for the main thread. This is the thread
|
||||
* that handles signals and remote control.
|
||||
*/
|
||||
#ifndef HAVE_EV_LOOP
|
||||
#if !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP))
|
||||
/* libevent has the last inited base get signals (or any base) */
|
||||
if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports, 1))
|
||||
fatal_exit("Could not initialize main thread");
|
||||
@@ -510,24 +545,40 @@ daemon_delete(struct daemon* daemon)
|
||||
free(daemon->chroot);
|
||||
free(daemon->pidfile);
|
||||
free(daemon->env);
|
||||
#ifdef HAVE_SSL
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_sslctx);
|
||||
SSL_CTX_free((SSL_CTX*)daemon->connect_sslctx);
|
||||
#endif
|
||||
free(daemon);
|
||||
#ifdef LEX_HAS_YYLEX_DESTROY
|
||||
/* lex cleanup */
|
||||
ub_c_lex_destroy();
|
||||
#endif
|
||||
/* libcrypto cleanup */
|
||||
#if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS
|
||||
sk_SSL_COMP_free(comp_meth);
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_CONFIG
|
||||
#ifdef HAVE_SSL
|
||||
# if defined(USE_GOST) && defined(HAVE_LDNS_KEY_EVP_UNLOAD_GOST)
|
||||
ldns_key_EVP_unload_gost();
|
||||
# endif
|
||||
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS && HAVE_DECL_SK_SSL_COMP_POP_FREE
|
||||
# ifndef S_SPLINT_S
|
||||
sk_SSL_COMP_pop_free(comp_meth, (void(*)())CRYPTO_free);
|
||||
# endif
|
||||
# endif
|
||||
# ifdef HAVE_OPENSSL_CONFIG
|
||||
EVP_cleanup();
|
||||
ENGINE_cleanup();
|
||||
CONF_modules_free();
|
||||
#endif
|
||||
# endif
|
||||
CRYPTO_cleanup_all_ex_data(); /* safe, no more threads right now */
|
||||
ERR_remove_state(0);
|
||||
ERR_free_strings();
|
||||
RAND_cleanup();
|
||||
# if defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
|
||||
ub_openssl_lock_delete();
|
||||
# endif
|
||||
#elif defined(HAVE_NSS)
|
||||
NSS_Shutdown();
|
||||
#endif /* HAVE_SSL or HAVE_NSS */
|
||||
checklock_stop();
|
||||
#ifdef USE_WINSOCK
|
||||
if(WSACleanup() != 0) {
|
||||
|
||||
+3
-1
@@ -80,6 +80,8 @@ struct daemon {
|
||||
struct listen_port* rc_ports;
|
||||
/** remote control connections management (for first worker) */
|
||||
struct daemon_remote* rc;
|
||||
/** ssl context for listening to dnstcp over ssl, and connecting ssl */
|
||||
void* listen_sslctx, *connect_sslctx;
|
||||
/** num threads allocated */
|
||||
int num;
|
||||
/** the worker entries */
|
||||
@@ -108,7 +110,7 @@ struct daemon {
|
||||
* Initialize daemon structure.
|
||||
* @return: The daemon structure, or NULL on error.
|
||||
*/
|
||||
struct daemon* daemon_init();
|
||||
struct daemon* daemon_init(void);
|
||||
|
||||
/**
|
||||
* Open shared listening ports (if needed).
|
||||
|
||||
+503
-95
@@ -43,6 +43,11 @@
|
||||
* Both the server and the client(control tool) have their own keys.
|
||||
*/
|
||||
#include "config.h"
|
||||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <ldns/ldns.h>
|
||||
#include "daemon/remote.h"
|
||||
#include "daemon/worker.h"
|
||||
#include "daemon/daemon.h"
|
||||
@@ -54,6 +59,7 @@
|
||||
#include "util/module.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/mesh.h"
|
||||
#include "services/localzone.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
@@ -62,6 +68,7 @@
|
||||
#include "validator/validator.h"
|
||||
#include "validator/val_kcache.h"
|
||||
#include "validator/val_kentry.h"
|
||||
#include "validator/val_anchor.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
@@ -86,21 +93,6 @@
|
||||
/** if true, inhibits a lot of =0 lines from the stats output */
|
||||
static const int inhibit_zero = 1;
|
||||
|
||||
/** log ssl crypto err */
|
||||
static void
|
||||
log_crypto_err(const char* str)
|
||||
{
|
||||
/* error:[error code]:[library name]:[function name]:[reason string] */
|
||||
char buf[128];
|
||||
unsigned long e;
|
||||
ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
|
||||
log_err("%s crypto %s", str, buf);
|
||||
while( (e=ERR_get_error()) ) {
|
||||
ERR_error_string_n(e, buf, sizeof(buf));
|
||||
log_err("and additionally crypto %s", buf);
|
||||
}
|
||||
}
|
||||
|
||||
/** subtract timers and the values do not overflow or become negative */
|
||||
static void
|
||||
timeval_subtract(struct timeval* d, const struct timeval* end,
|
||||
@@ -312,7 +304,7 @@ struct listen_port* daemon_remote_open_ports(struct config_file* cfg)
|
||||
struct listen_port* l = NULL;
|
||||
log_assert(cfg->remote_control_enable && cfg->control_port);
|
||||
if(cfg->control_ifs) {
|
||||
struct config_strlist* p = cfg->control_ifs;
|
||||
struct config_strlist* p;
|
||||
for(p = cfg->control_ifs; p; p = p->next) {
|
||||
if(!add_open(p->str, cfg->control_port, &l, 1)) {
|
||||
listening_ports_free(l);
|
||||
@@ -370,6 +362,22 @@ int daemon_remote_open_accept(struct daemon_remote* rc,
|
||||
return 1;
|
||||
}
|
||||
|
||||
void daemon_remote_stop_accept(struct daemon_remote* rc)
|
||||
{
|
||||
struct listen_list* p;
|
||||
for(p=rc->accept_list; p; p=p->next) {
|
||||
comm_point_stop_listening(p->com);
|
||||
}
|
||||
}
|
||||
|
||||
void daemon_remote_start_accept(struct daemon_remote* rc)
|
||||
{
|
||||
struct listen_list* p;
|
||||
for(p=rc->accept_list; p; p=p->next) {
|
||||
comm_point_start_listening(p->com, -1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
int remote_accept_callback(struct comm_point* c, void* arg, int err,
|
||||
struct comm_reply* ATTR_UNUSED(rep))
|
||||
{
|
||||
@@ -389,7 +397,6 @@ int remote_accept_callback(struct comm_point* c, void* arg, int err,
|
||||
/* create new commpoint unless we are servicing already */
|
||||
if(rc->active >= rc->max_active) {
|
||||
log_warn("drop incoming remote control: too many connections");
|
||||
comm_point_stop_listening(c);
|
||||
close_exit:
|
||||
#ifndef USE_WINSOCK
|
||||
close(newfd);
|
||||
@@ -423,6 +430,7 @@ int remote_accept_callback(struct comm_point* c, void* arg, int err,
|
||||
n->ssl = SSL_new(rc->ctx);
|
||||
if(!n->ssl) {
|
||||
log_crypto_err("could not SSL_new");
|
||||
comm_point_delete(n->c);
|
||||
free(n);
|
||||
goto close_exit;
|
||||
}
|
||||
@@ -431,6 +439,7 @@ int remote_accept_callback(struct comm_point* c, void* arg, int err,
|
||||
if(!SSL_set_fd(n->ssl, newfd)) {
|
||||
log_crypto_err("could not SSL_set_fd");
|
||||
SSL_free(n->ssl);
|
||||
comm_point_delete(n->c);
|
||||
free(n);
|
||||
goto close_exit;
|
||||
}
|
||||
@@ -696,13 +705,14 @@ print_mem(SSL* ssl, struct worker* worker, struct daemon* daemon)
|
||||
|
||||
/** print uptime stats */
|
||||
static int
|
||||
print_uptime(SSL* ssl, struct worker* worker)
|
||||
print_uptime(SSL* ssl, struct worker* worker, int reset)
|
||||
{
|
||||
struct timeval now = *worker->env.now_tv;
|
||||
struct timeval up, dt;
|
||||
timeval_subtract(&up, &now, &worker->daemon->time_boot);
|
||||
timeval_subtract(&dt, &now, &worker->daemon->time_last_stat);
|
||||
worker->daemon->time_last_stat = now;
|
||||
if(reset)
|
||||
worker->daemon->time_last_stat = now;
|
||||
if(!ssl_printf(ssl, "time.now"SQ"%d.%6.6d\n",
|
||||
(unsigned)now.tv_sec, (unsigned)now.tv_usec)) return 0;
|
||||
if(!ssl_printf(ssl, "time.up"SQ"%d.%6.6d\n",
|
||||
@@ -872,6 +882,7 @@ do_stats(SSL* ssl, struct daemon_remote* rc, int reset)
|
||||
struct stats_info total;
|
||||
struct stats_info s;
|
||||
int i;
|
||||
log_assert(daemon->num > 0);
|
||||
/* gather all thread statistics in one place */
|
||||
for(i=0; i<daemon->num; i++) {
|
||||
server_stats_obtain(rc->worker, daemon->workers[i], &s, reset);
|
||||
@@ -885,7 +896,7 @@ do_stats(SSL* ssl, struct daemon_remote* rc, int reset)
|
||||
total.mesh_time_median /= (double)daemon->num;
|
||||
if(!print_stats(ssl, "total", &total))
|
||||
return;
|
||||
if(!print_uptime(ssl, rc->worker))
|
||||
if(!print_uptime(ssl, rc->worker, reset))
|
||||
return;
|
||||
if(daemon->cfg->stat_extended) {
|
||||
if(!print_mem(ssl, rc->worker, daemon))
|
||||
@@ -1055,6 +1066,9 @@ do_cache_remove(struct worker* worker, uint8_t* nm, size_t nmlen,
|
||||
hashvalue_t h;
|
||||
struct query_info k;
|
||||
rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, t, c, 0);
|
||||
if(t == LDNS_RR_TYPE_SOA)
|
||||
rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, t, c,
|
||||
PACKED_RRSET_SOA_NEG);
|
||||
k.qname = nm;
|
||||
k.qname_len = nmlen;
|
||||
k.qtype = t;
|
||||
@@ -1091,14 +1105,6 @@ do_flush_stats(SSL* ssl, struct worker* worker)
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** flush requestlist */
|
||||
static void
|
||||
do_flush_requestlist(SSL* ssl, struct worker* worker)
|
||||
{
|
||||
mesh_delete_all(worker->env.mesh);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Local info for deletion functions
|
||||
*/
|
||||
@@ -1111,6 +1117,8 @@ struct del_info {
|
||||
size_t len;
|
||||
/** labels */
|
||||
int labs;
|
||||
/** now */
|
||||
uint32_t now;
|
||||
/** time to invalidate to */
|
||||
uint32_t expired;
|
||||
/** number of rrsets removed */
|
||||
@@ -1119,8 +1127,76 @@ struct del_info {
|
||||
size_t num_msgs;
|
||||
/** number of key entries removed */
|
||||
size_t num_keys;
|
||||
/** length of addr */
|
||||
socklen_t addrlen;
|
||||
/** socket address for host deletion */
|
||||
struct sockaddr_storage addr;
|
||||
};
|
||||
|
||||
/** callback to delete hosts in infra cache */
|
||||
static void
|
||||
infra_del_host(struct lruhash_entry* e, void* arg)
|
||||
{
|
||||
/* entry is locked */
|
||||
struct del_info* inf = (struct del_info*)arg;
|
||||
struct infra_key* k = (struct infra_key*)e->key;
|
||||
if(sockaddr_cmp(&inf->addr, inf->addrlen, &k->addr, k->addrlen) == 0) {
|
||||
struct infra_data* d = (struct infra_data*)e->data;
|
||||
d->probedelay = 0;
|
||||
d->timeout_A = 0;
|
||||
d->timeout_AAAA = 0;
|
||||
d->timeout_other = 0;
|
||||
rtt_init(&d->rtt);
|
||||
if(d->ttl >= inf->now) {
|
||||
d->ttl = inf->expired;
|
||||
inf->num_keys++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** flush infra cache */
|
||||
static void
|
||||
do_flush_infra(SSL* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t len;
|
||||
struct del_info inf;
|
||||
if(strcmp(arg, "all") == 0) {
|
||||
slabhash_clear(worker->env.infra_cache->hosts);
|
||||
send_ok(ssl);
|
||||
return;
|
||||
}
|
||||
if(!ipstrtoaddr(arg, UNBOUND_DNS_PORT, &addr, &len)) {
|
||||
(void)ssl_printf(ssl, "error parsing ip addr: '%s'\n", arg);
|
||||
return;
|
||||
}
|
||||
/* delete all entries from cache */
|
||||
/* what we do is to set them all expired */
|
||||
inf.worker = worker;
|
||||
inf.name = 0;
|
||||
inf.len = 0;
|
||||
inf.labs = 0;
|
||||
inf.now = *worker->env.now;
|
||||
inf.expired = *worker->env.now;
|
||||
inf.expired -= 3; /* handle 3 seconds skew between threads */
|
||||
inf.num_rrsets = 0;
|
||||
inf.num_msgs = 0;
|
||||
inf.num_keys = 0;
|
||||
inf.addrlen = len;
|
||||
memmove(&inf.addr, &addr, len);
|
||||
slabhash_traverse(worker->env.infra_cache->hosts, 1, &infra_del_host,
|
||||
&inf);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** flush requestlist */
|
||||
static void
|
||||
do_flush_requestlist(SSL* ssl, struct worker* worker)
|
||||
{
|
||||
mesh_delete_all(worker->env.mesh);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** callback to delete rrsets in a zone */
|
||||
static void
|
||||
zone_del_rrset(struct lruhash_entry* e, void* arg)
|
||||
@@ -1131,8 +1207,10 @@ zone_del_rrset(struct lruhash_entry* e, void* arg)
|
||||
if(dname_subdomain_c(k->rk.dname, inf->name)) {
|
||||
struct packed_rrset_data* d =
|
||||
(struct packed_rrset_data*)e->data;
|
||||
d->ttl = inf->expired;
|
||||
inf->num_rrsets++;
|
||||
if(d->ttl >= inf->now) {
|
||||
d->ttl = inf->expired;
|
||||
inf->num_rrsets++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1145,8 +1223,10 @@ zone_del_msg(struct lruhash_entry* e, void* arg)
|
||||
struct msgreply_entry* k = (struct msgreply_entry*)e->key;
|
||||
if(dname_subdomain_c(k->key.qname, inf->name)) {
|
||||
struct reply_info* d = (struct reply_info*)e->data;
|
||||
d->ttl = inf->expired;
|
||||
inf->num_msgs++;
|
||||
if(d->ttl >= inf->now) {
|
||||
d->ttl = inf->expired;
|
||||
inf->num_msgs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1159,8 +1239,10 @@ zone_del_kcache(struct lruhash_entry* e, void* arg)
|
||||
struct key_entry_key* k = (struct key_entry_key*)e->key;
|
||||
if(dname_subdomain_c(k->name, inf->name)) {
|
||||
struct key_entry_data* d = (struct key_entry_data*)e->data;
|
||||
d->ttl = inf->expired;
|
||||
inf->num_keys++;
|
||||
if(d->ttl >= inf->now) {
|
||||
d->ttl = inf->expired;
|
||||
inf->num_keys++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1180,6 +1262,7 @@ do_flush_zone(SSL* ssl, struct worker* worker, char* arg)
|
||||
inf.name = nm;
|
||||
inf.len = nmlen;
|
||||
inf.labs = nmlabs;
|
||||
inf.now = *worker->env.now;
|
||||
inf.expired = *worker->env.now;
|
||||
inf.expired -= 3; /* handle 3 seconds skew between threads */
|
||||
inf.num_rrsets = 0;
|
||||
@@ -1203,6 +1286,74 @@ do_flush_zone(SSL* ssl, struct worker* worker, char* arg)
|
||||
(unsigned)inf.num_msgs, (unsigned)inf.num_keys);
|
||||
}
|
||||
|
||||
/** callback to delete bogus rrsets */
|
||||
static void
|
||||
bogus_del_rrset(struct lruhash_entry* e, void* arg)
|
||||
{
|
||||
/* entry is locked */
|
||||
struct del_info* inf = (struct del_info*)arg;
|
||||
struct packed_rrset_data* d = (struct packed_rrset_data*)e->data;
|
||||
if(d->security == sec_status_bogus) {
|
||||
d->ttl = inf->expired;
|
||||
inf->num_rrsets++;
|
||||
}
|
||||
}
|
||||
|
||||
/** callback to delete bogus messages */
|
||||
static void
|
||||
bogus_del_msg(struct lruhash_entry* e, void* arg)
|
||||
{
|
||||
/* entry is locked */
|
||||
struct del_info* inf = (struct del_info*)arg;
|
||||
struct reply_info* d = (struct reply_info*)e->data;
|
||||
if(d->security == sec_status_bogus) {
|
||||
d->ttl = inf->expired;
|
||||
inf->num_msgs++;
|
||||
}
|
||||
}
|
||||
|
||||
/** callback to delete bogus keys */
|
||||
static void
|
||||
bogus_del_kcache(struct lruhash_entry* e, void* arg)
|
||||
{
|
||||
/* entry is locked */
|
||||
struct del_info* inf = (struct del_info*)arg;
|
||||
struct key_entry_data* d = (struct key_entry_data*)e->data;
|
||||
if(d->isbad) {
|
||||
d->ttl = inf->expired;
|
||||
inf->num_keys++;
|
||||
}
|
||||
}
|
||||
|
||||
/** remove all rrsets and keys from zone from cache */
|
||||
static void
|
||||
do_flush_bogus(SSL* ssl, struct worker* worker)
|
||||
{
|
||||
struct del_info inf;
|
||||
/* what we do is to set them all expired */
|
||||
inf.worker = worker;
|
||||
inf.now = *worker->env.now;
|
||||
inf.expired = *worker->env.now;
|
||||
inf.expired -= 3; /* handle 3 seconds skew between threads */
|
||||
inf.num_rrsets = 0;
|
||||
inf.num_msgs = 0;
|
||||
inf.num_keys = 0;
|
||||
slabhash_traverse(&worker->env.rrset_cache->table, 1,
|
||||
&bogus_del_rrset, &inf);
|
||||
|
||||
slabhash_traverse(worker->env.msg_cache, 1, &bogus_del_msg, &inf);
|
||||
|
||||
/* and validator cache */
|
||||
if(worker->env.key_cache) {
|
||||
slabhash_traverse(worker->env.key_cache->slab, 1,
|
||||
&bogus_del_kcache, &inf);
|
||||
}
|
||||
|
||||
(void)ssl_printf(ssl, "ok removed %u rrsets, %u messages "
|
||||
"and %u key entries\n", (unsigned)inf.num_rrsets,
|
||||
(unsigned)inf.num_msgs, (unsigned)inf.num_keys);
|
||||
}
|
||||
|
||||
/** remove name rrset from cache */
|
||||
static void
|
||||
do_flush_name(SSL* ssl, struct worker* w, char* arg)
|
||||
@@ -1276,15 +1427,15 @@ print_root_fwds(SSL* ssl, struct iter_forwards* fwds, uint8_t* root)
|
||||
|
||||
/** parse args into delegpt */
|
||||
static struct delegpt*
|
||||
parse_delegpt(SSL* ssl, struct regional* region, char* args, uint8_t* root)
|
||||
parse_delegpt(SSL* ssl, char* args, uint8_t* nm, int allow_names)
|
||||
{
|
||||
/* parse args and add in */
|
||||
char* p = args;
|
||||
char* todo;
|
||||
struct delegpt* dp = delegpt_create(region);
|
||||
struct delegpt* dp = delegpt_create_mlc(nm);
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen;
|
||||
if(!dp || !delegpt_set_name(dp, region, root)) {
|
||||
if(!dp) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
@@ -1297,14 +1448,38 @@ parse_delegpt(SSL* ssl, struct regional* region, char* args, uint8_t* root)
|
||||
}
|
||||
/* parse address */
|
||||
if(!extstrtoaddr(todo, &addr, &addrlen)) {
|
||||
(void)ssl_printf(ssl, "error cannot parse"
|
||||
" IP address '%s'\n", todo);
|
||||
return NULL;
|
||||
}
|
||||
/* add address */
|
||||
if(!delegpt_add_addr(dp, region, &addr, addrlen, 0, 0, 1)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
return NULL;
|
||||
if(allow_names) {
|
||||
uint8_t* n = NULL;
|
||||
size_t ln;
|
||||
int lb;
|
||||
if(!parse_arg_name(ssl, todo, &n, &ln, &lb)) {
|
||||
(void)ssl_printf(ssl, "error cannot "
|
||||
"parse IP address or name "
|
||||
"'%s'\n", todo);
|
||||
delegpt_free_mlc(dp);
|
||||
return NULL;
|
||||
}
|
||||
if(!delegpt_add_ns_mlc(dp, n, 0)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
free(n);
|
||||
delegpt_free_mlc(dp);
|
||||
return NULL;
|
||||
}
|
||||
free(n);
|
||||
|
||||
} else {
|
||||
(void)ssl_printf(ssl, "error cannot parse"
|
||||
" IP address '%s'\n", todo);
|
||||
delegpt_free_mlc(dp);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
/* add address */
|
||||
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
delegpt_free_mlc(dp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp;
|
||||
@@ -1328,14 +1503,11 @@ do_forward(SSL* ssl, struct worker* worker, char* args)
|
||||
* the actual mesh is not running, so we can freely edit it. */
|
||||
/* delete all the existing queries first */
|
||||
mesh_delete_all(worker->env.mesh);
|
||||
/* reset the fwd structure ; the cfg is unchanged (shared by threads)*/
|
||||
/* this reset frees up memory */
|
||||
forwards_apply_cfg(fwd, worker->env.cfg);
|
||||
if(strcmp(args, "off") == 0) {
|
||||
forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, root);
|
||||
} else {
|
||||
struct delegpt* dp;
|
||||
if(!(dp = parse_delegpt(ssl, fwd->region, args, root)))
|
||||
if(!(dp = parse_delegpt(ssl, args, root, 0)))
|
||||
return;
|
||||
if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
@@ -1345,6 +1517,152 @@ do_forward(SSL* ssl, struct worker* worker, char* args)
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
static int
|
||||
parse_fs_args(SSL* ssl, char* args, uint8_t** nm, struct delegpt** dp,
|
||||
int* insecure, int* prime)
|
||||
{
|
||||
char* zonename;
|
||||
char* rest;
|
||||
size_t nmlen;
|
||||
int nmlabs;
|
||||
/* parse all -x args */
|
||||
while(args[0] == '+') {
|
||||
if(!find_arg2(ssl, args, &rest))
|
||||
return 0;
|
||||
while(*(++args) != 0) {
|
||||
if(*args == 'i' && insecure)
|
||||
*insecure = 1;
|
||||
else if(*args == 'p' && prime)
|
||||
*prime = 1;
|
||||
else {
|
||||
(void)ssl_printf(ssl, "error: unknown option %s\n", args);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
args = rest;
|
||||
}
|
||||
/* parse name */
|
||||
if(dp) {
|
||||
if(!find_arg2(ssl, args, &rest))
|
||||
return 0;
|
||||
zonename = args;
|
||||
args = rest;
|
||||
} else zonename = args;
|
||||
if(!parse_arg_name(ssl, zonename, nm, &nmlen, &nmlabs))
|
||||
return 0;
|
||||
|
||||
/* parse dp */
|
||||
if(dp) {
|
||||
if(!(*dp = parse_delegpt(ssl, args, *nm, 1))) {
|
||||
free(*nm);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** do the forward_add command */
|
||||
static void
|
||||
do_forward_add(SSL* ssl, struct worker* worker, char* args)
|
||||
{
|
||||
struct iter_forwards* fwd = worker->env.fwds;
|
||||
int insecure = 0;
|
||||
uint8_t* nm = NULL;
|
||||
struct delegpt* dp = NULL;
|
||||
if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, NULL))
|
||||
return;
|
||||
if(insecure) {
|
||||
if(!anchors_add_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
|
||||
nm)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
delegpt_free_mlc(dp);
|
||||
free(nm);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
free(nm);
|
||||
return;
|
||||
}
|
||||
free(nm);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** do the forward_remove command */
|
||||
static void
|
||||
do_forward_remove(SSL* ssl, struct worker* worker, char* args)
|
||||
{
|
||||
struct iter_forwards* fwd = worker->env.fwds;
|
||||
int insecure = 0;
|
||||
uint8_t* nm = NULL;
|
||||
if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL))
|
||||
return;
|
||||
if(insecure)
|
||||
anchors_delete_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
|
||||
nm);
|
||||
forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, nm);
|
||||
free(nm);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** do the stub_add command */
|
||||
static void
|
||||
do_stub_add(SSL* ssl, struct worker* worker, char* args)
|
||||
{
|
||||
struct iter_forwards* fwd = worker->env.fwds;
|
||||
int insecure = 0, prime = 0;
|
||||
uint8_t* nm = NULL;
|
||||
struct delegpt* dp = NULL;
|
||||
if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, &prime))
|
||||
return;
|
||||
if(insecure) {
|
||||
if(!anchors_add_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
|
||||
nm)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
delegpt_free_mlc(dp);
|
||||
free(nm);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(!forwards_add_stub_hole(fwd, LDNS_RR_CLASS_IN, nm)) {
|
||||
if(insecure) anchors_delete_insecure(worker->env.anchors,
|
||||
LDNS_RR_CLASS_IN, nm);
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
delegpt_free_mlc(dp);
|
||||
free(nm);
|
||||
return;
|
||||
}
|
||||
if(!hints_add_stub(worker->env.hints, LDNS_RR_CLASS_IN, dp, !prime)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
forwards_delete_stub_hole(fwd, LDNS_RR_CLASS_IN, nm);
|
||||
if(insecure) anchors_delete_insecure(worker->env.anchors,
|
||||
LDNS_RR_CLASS_IN, nm);
|
||||
free(nm);
|
||||
return;
|
||||
}
|
||||
free(nm);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** do the stub_remove command */
|
||||
static void
|
||||
do_stub_remove(SSL* ssl, struct worker* worker, char* args)
|
||||
{
|
||||
struct iter_forwards* fwd = worker->env.fwds;
|
||||
int insecure = 0;
|
||||
uint8_t* nm = NULL;
|
||||
if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL))
|
||||
return;
|
||||
if(insecure)
|
||||
anchors_delete_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
|
||||
nm);
|
||||
forwards_delete_stub_hole(fwd, LDNS_RR_CLASS_IN, nm);
|
||||
hints_delete_stub(worker->env.hints, LDNS_RR_CLASS_IN, nm);
|
||||
free(nm);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** do the status command */
|
||||
static void
|
||||
do_status(SSL* ssl, struct worker* worker)
|
||||
@@ -1479,6 +1797,59 @@ do_dump_requestlist(SSL* ssl, struct worker* worker)
|
||||
}
|
||||
}
|
||||
|
||||
/** structure for argument data for dump infra host */
|
||||
struct infra_arg {
|
||||
/** the infra cache */
|
||||
struct infra_cache* infra;
|
||||
/** the SSL connection */
|
||||
SSL* ssl;
|
||||
/** the time now */
|
||||
uint32_t now;
|
||||
};
|
||||
|
||||
/** callback for every host element in the infra cache */
|
||||
static void
|
||||
dump_infra_host(struct lruhash_entry* e, void* arg)
|
||||
{
|
||||
struct infra_arg* a = (struct infra_arg*)arg;
|
||||
struct infra_key* k = (struct infra_key*)e->key;
|
||||
struct infra_data* d = (struct infra_data*)e->data;
|
||||
char ip_str[1024];
|
||||
char name[257];
|
||||
addr_to_str(&k->addr, k->addrlen, ip_str, sizeof(ip_str));
|
||||
dname_str(k->zonename, name);
|
||||
/* skip expired stuff (only backed off) */
|
||||
if(d->ttl < a->now) {
|
||||
if(d->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
if(!ssl_printf(a->ssl, "%s %s expired rto %d\n", ip_str,
|
||||
name, d->rtt.rto)) return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(!ssl_printf(a->ssl, "%s %s ttl %d ping %d var %d rtt %d rto %d "
|
||||
"tA %d tAAAA %d tother %d "
|
||||
"ednsknown %d edns %d delay %d lame dnssec %d rec %d A %d "
|
||||
"other %d\n", ip_str, name, (int)(d->ttl - a->now),
|
||||
d->rtt.srtt, d->rtt.rttvar, rtt_notimeout(&d->rtt), d->rtt.rto,
|
||||
d->timeout_A, d->timeout_AAAA, d->timeout_other,
|
||||
(int)d->edns_lame_known, (int)d->edns_version,
|
||||
(int)(a->now<d->probedelay?d->probedelay-a->now:0),
|
||||
(int)d->isdnsseclame, (int)d->rec_lame, (int)d->lame_type_A,
|
||||
(int)d->lame_other))
|
||||
return;
|
||||
}
|
||||
|
||||
/** do the dump_infra command */
|
||||
static void
|
||||
do_dump_infra(SSL* ssl, struct worker* worker)
|
||||
{
|
||||
struct infra_arg arg;
|
||||
arg.infra = worker->env.infra_cache;
|
||||
arg.ssl = ssl;
|
||||
arg.now = *worker->env.now;
|
||||
slabhash_traverse(arg.infra->hosts, 0, &dump_infra_host, (void*)&arg);
|
||||
}
|
||||
|
||||
/** do the log_reopen command */
|
||||
static void
|
||||
do_log_reopen(SSL* ssl, struct worker* worker)
|
||||
@@ -1540,17 +1911,8 @@ do_list_forwards(SSL* ssl, struct worker* worker)
|
||||
static void
|
||||
do_list_stubs(SSL* ssl, struct worker* worker)
|
||||
{
|
||||
/* readonly structure */
|
||||
int m;
|
||||
struct iter_hints_stub* z;
|
||||
struct iter_env* ie;
|
||||
m = modstack_find(&worker->env.mesh->mods, "iterator");
|
||||
if(m == -1) {
|
||||
(void)ssl_printf(ssl, "error no iterator module\n");
|
||||
return;
|
||||
}
|
||||
ie = (struct iter_env*)worker->env.modinfo[m];
|
||||
RBTREE_FOR(z, struct iter_hints_stub*, &ie->hints->tree) {
|
||||
RBTREE_FOR(z, struct iter_hints_stub*, &worker->env.hints->tree) {
|
||||
if(!ssl_print_name_dp(ssl,
|
||||
z->noprime?"stub noprime":"stub prime", z->node.name,
|
||||
z->node.dclass, z->dp))
|
||||
@@ -1603,7 +1965,7 @@ do_list_local_data(SSL* ssl, struct worker* worker)
|
||||
}
|
||||
|
||||
/** tell other processes to execute the command */
|
||||
void
|
||||
static void
|
||||
distribute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd)
|
||||
{
|
||||
int i;
|
||||
@@ -1621,62 +1983,89 @@ distribute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd)
|
||||
}
|
||||
}
|
||||
|
||||
/** check for name with end-of-string, space or tab after it */
|
||||
static int
|
||||
cmdcmp(char* p, const char* cmd, size_t len)
|
||||
{
|
||||
return strncmp(p,cmd,len)==0 && (p[len]==0||p[len]==' '||p[len]=='\t');
|
||||
}
|
||||
|
||||
/** execute a remote control command */
|
||||
static void
|
||||
execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd,
|
||||
struct worker* worker)
|
||||
{
|
||||
char* p = skipwhite(cmd);
|
||||
/* compare command - check longer strings first in case of substrings*/
|
||||
if(strncmp(p, "stop", 4) == 0) {
|
||||
/* compare command */
|
||||
if(cmdcmp(p, "stop", 4)) {
|
||||
do_stop(ssl, rc);
|
||||
return;
|
||||
} else if(strncmp(p, "reload", 6) == 0) {
|
||||
} else if(cmdcmp(p, "reload", 6)) {
|
||||
do_reload(ssl, rc);
|
||||
return;
|
||||
} else if(strncmp(p, "stats_noreset", 13) == 0) {
|
||||
} else if(cmdcmp(p, "stats_noreset", 13)) {
|
||||
do_stats(ssl, rc, 0);
|
||||
return;
|
||||
} else if(strncmp(p, "stats", 5) == 0) {
|
||||
} else if(cmdcmp(p, "stats", 5)) {
|
||||
do_stats(ssl, rc, 1);
|
||||
return;
|
||||
} else if(strncmp(p, "status", 6) == 0) {
|
||||
} else if(cmdcmp(p, "status", 6)) {
|
||||
do_status(ssl, worker);
|
||||
return;
|
||||
} else if(strncmp(p, "dump_cache", 10) == 0) {
|
||||
} else if(cmdcmp(p, "dump_cache", 10)) {
|
||||
(void)dump_cache(ssl, worker);
|
||||
return;
|
||||
} else if(strncmp(p, "load_cache", 10) == 0) {
|
||||
} else if(cmdcmp(p, "load_cache", 10)) {
|
||||
if(load_cache(ssl, worker)) send_ok(ssl);
|
||||
return;
|
||||
} else if(strncmp(p, "list_forwards", 13) == 0) {
|
||||
} else if(cmdcmp(p, "list_forwards", 13)) {
|
||||
do_list_forwards(ssl, worker);
|
||||
return;
|
||||
} else if(strncmp(p, "list_stubs", 10) == 0) {
|
||||
} else if(cmdcmp(p, "list_stubs", 10)) {
|
||||
do_list_stubs(ssl, worker);
|
||||
return;
|
||||
} else if(strncmp(p, "list_local_zones", 16) == 0) {
|
||||
} else if(cmdcmp(p, "list_local_zones", 16)) {
|
||||
do_list_local_zones(ssl, worker);
|
||||
return;
|
||||
} else if(strncmp(p, "list_local_data", 15) == 0) {
|
||||
} else if(cmdcmp(p, "list_local_data", 15)) {
|
||||
do_list_local_data(ssl, worker);
|
||||
return;
|
||||
} else if(strncmp(p, "forward", 7) == 0) {
|
||||
} else if(cmdcmp(p, "stub_add", 8)) {
|
||||
/* must always distribute this cmd */
|
||||
if(rc) distribute_cmd(rc, ssl, cmd);
|
||||
do_stub_add(ssl, worker, skipwhite(p+8));
|
||||
return;
|
||||
} else if(cmdcmp(p, "stub_remove", 11)) {
|
||||
/* must always distribute this cmd */
|
||||
if(rc) distribute_cmd(rc, ssl, cmd);
|
||||
do_stub_remove(ssl, worker, skipwhite(p+11));
|
||||
return;
|
||||
} else if(cmdcmp(p, "forward_add", 11)) {
|
||||
/* must always distribute this cmd */
|
||||
if(rc) distribute_cmd(rc, ssl, cmd);
|
||||
do_forward_add(ssl, worker, skipwhite(p+11));
|
||||
return;
|
||||
} else if(cmdcmp(p, "forward_remove", 14)) {
|
||||
/* must always distribute this cmd */
|
||||
if(rc) distribute_cmd(rc, ssl, cmd);
|
||||
do_forward_remove(ssl, worker, skipwhite(p+14));
|
||||
return;
|
||||
} else if(cmdcmp(p, "forward", 7)) {
|
||||
/* must always distribute this cmd */
|
||||
if(rc) distribute_cmd(rc, ssl, cmd);
|
||||
do_forward(ssl, worker, skipwhite(p+7));
|
||||
return;
|
||||
} else if(strncmp(p, "flush_stats", 11) == 0) {
|
||||
} else if(cmdcmp(p, "flush_stats", 11)) {
|
||||
/* must always distribute this cmd */
|
||||
if(rc) distribute_cmd(rc, ssl, cmd);
|
||||
do_flush_stats(ssl, worker);
|
||||
return;
|
||||
} else if(strncmp(p, "flush_requestlist", 17) == 0) {
|
||||
} else if(cmdcmp(p, "flush_requestlist", 17)) {
|
||||
/* must always distribute this cmd */
|
||||
if(rc) distribute_cmd(rc, ssl, cmd);
|
||||
do_flush_requestlist(ssl, worker);
|
||||
return;
|
||||
} else if(strncmp(p, "lookup", 6) == 0) {
|
||||
} else if(cmdcmp(p, "lookup", 6)) {
|
||||
do_lookup(ssl, worker, skipwhite(p+6));
|
||||
return;
|
||||
}
|
||||
@@ -1689,30 +2078,36 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd,
|
||||
distribute_cmd(rc, ssl, cmd);
|
||||
}
|
||||
#endif
|
||||
if(strncmp(p, "verbosity", 9) == 0) {
|
||||
if(cmdcmp(p, "verbosity", 9)) {
|
||||
do_verbosity(ssl, skipwhite(p+9));
|
||||
} else if(strncmp(p, "local_zone_remove", 17) == 0) {
|
||||
} else if(cmdcmp(p, "local_zone_remove", 17)) {
|
||||
do_zone_remove(ssl, worker, skipwhite(p+17));
|
||||
} else if(strncmp(p, "local_zone", 10) == 0) {
|
||||
} else if(cmdcmp(p, "local_zone", 10)) {
|
||||
do_zone_add(ssl, worker, skipwhite(p+10));
|
||||
} else if(strncmp(p, "local_data_remove", 17) == 0) {
|
||||
} else if(cmdcmp(p, "local_data_remove", 17)) {
|
||||
do_data_remove(ssl, worker, skipwhite(p+17));
|
||||
} else if(strncmp(p, "local_data", 10) == 0) {
|
||||
} else if(cmdcmp(p, "local_data", 10)) {
|
||||
do_data_add(ssl, worker, skipwhite(p+10));
|
||||
} else if(strncmp(p, "flush_zone", 10) == 0) {
|
||||
} else if(cmdcmp(p, "flush_zone", 10)) {
|
||||
do_flush_zone(ssl, worker, skipwhite(p+10));
|
||||
} else if(strncmp(p, "flush_type", 10) == 0) {
|
||||
} else if(cmdcmp(p, "flush_type", 10)) {
|
||||
do_flush_type(ssl, worker, skipwhite(p+10));
|
||||
} else if(strncmp(p, "flush", 5) == 0) {
|
||||
} else if(cmdcmp(p, "flush_infra", 11)) {
|
||||
do_flush_infra(ssl, worker, skipwhite(p+11));
|
||||
} else if(cmdcmp(p, "flush", 5)) {
|
||||
do_flush_name(ssl, worker, skipwhite(p+5));
|
||||
} else if(strncmp(p, "dump_requestlist", 16) == 0) {
|
||||
} else if(cmdcmp(p, "dump_requestlist", 16)) {
|
||||
do_dump_requestlist(ssl, worker);
|
||||
} else if(strncmp(p, "log_reopen", 10) == 0) {
|
||||
} else if(cmdcmp(p, "dump_infra", 10)) {
|
||||
do_dump_infra(ssl, worker);
|
||||
} else if(cmdcmp(p, "log_reopen", 10)) {
|
||||
do_log_reopen(ssl, worker);
|
||||
} else if(strncmp(p, "set_option", 10) == 0) {
|
||||
} else if(cmdcmp(p, "set_option", 10)) {
|
||||
do_set_option(ssl, worker, skipwhite(p+10));
|
||||
} else if(strncmp(p, "get_option", 10) == 0) {
|
||||
} else if(cmdcmp(p, "get_option", 10)) {
|
||||
do_get_option(ssl, worker, skipwhite(p+10));
|
||||
} else if(cmdcmp(p, "flush_bogus", 11)) {
|
||||
do_flush_bogus(ssl, worker);
|
||||
} else {
|
||||
(void)ssl_printf(ssl, "error unknown command '%s'\n", p);
|
||||
}
|
||||
@@ -1738,7 +2133,8 @@ static void
|
||||
handle_req(struct daemon_remote* rc, struct rc_state* s, SSL* ssl)
|
||||
{
|
||||
int r;
|
||||
char magic[5];
|
||||
char pre[10];
|
||||
char magic[7];
|
||||
char buf[1024];
|
||||
#ifdef USE_WINSOCK
|
||||
/* makes it possible to set the socket blocking again. */
|
||||
@@ -1747,7 +2143,7 @@ handle_req(struct daemon_remote* rc, struct rc_state* s, SSL* ssl)
|
||||
#endif
|
||||
fd_set_block(s->c->fd);
|
||||
|
||||
/* try to read magic UBCT string */
|
||||
/* try to read magic UBCT[version]_space_ string */
|
||||
ERR_clear_error();
|
||||
if((r=SSL_read(ssl, magic, (int)sizeof(magic)-1)) <= 0) {
|
||||
if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN)
|
||||
@@ -1755,9 +2151,10 @@ handle_req(struct daemon_remote* rc, struct rc_state* s, SSL* ssl)
|
||||
log_crypto_err("could not SSL_read");
|
||||
return;
|
||||
}
|
||||
magic[4] = 0;
|
||||
if( r != 4 || strcmp(magic, "UBCT") != 0) {
|
||||
magic[6] = 0;
|
||||
if( r != 6 || strncmp(magic, "UBCT", 4) != 0) {
|
||||
verbose(VERB_QUERY, "control connection has bad magic string");
|
||||
/* probably wrong tool connected, ignore it completely */
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1765,6 +2162,13 @@ handle_req(struct daemon_remote* rc, struct rc_state* s, SSL* ssl)
|
||||
if(!ssl_read_line(ssl, buf, sizeof(buf))) {
|
||||
return;
|
||||
}
|
||||
snprintf(pre, sizeof(pre), "UBCT%d ", UNBOUND_CONTROL_VERSION);
|
||||
if(strcmp(magic, pre) != 0) {
|
||||
verbose(VERB_QUERY, "control connection had bad "
|
||||
"version %s, cmd: %s", magic, buf);
|
||||
ssl_printf(ssl, "error version mismatch\n");
|
||||
return;
|
||||
}
|
||||
verbose(VERB_DETAIL, "control cmd: %s", buf);
|
||||
|
||||
/* figure out what to do */
|
||||
@@ -1787,8 +2191,8 @@ int remote_control_callback(struct comm_point* c, void* arg, int err,
|
||||
ERR_clear_error();
|
||||
r = SSL_do_handshake(s->ssl);
|
||||
if(r != 1) {
|
||||
r = SSL_get_error(s->ssl, r);
|
||||
if(r == SSL_ERROR_WANT_READ) {
|
||||
int r2 = SSL_get_error(s->ssl, r);
|
||||
if(r2 == SSL_ERROR_WANT_READ) {
|
||||
if(s->shake_state == rc_hs_read) {
|
||||
/* try again later */
|
||||
return 0;
|
||||
@@ -1796,7 +2200,7 @@ int remote_control_callback(struct comm_point* c, void* arg, int err,
|
||||
s->shake_state = rc_hs_read;
|
||||
comm_point_listen_for_rw(c, 1, 0);
|
||||
return 0;
|
||||
} else if(r == SSL_ERROR_WANT_WRITE) {
|
||||
} else if(r2 == SSL_ERROR_WANT_WRITE) {
|
||||
if(s->shake_state == rc_hs_write) {
|
||||
/* try again later */
|
||||
return 0;
|
||||
@@ -1805,6 +2209,10 @@ int remote_control_callback(struct comm_point* c, void* arg, int err,
|
||||
comm_point_listen_for_rw(c, 0, 1);
|
||||
return 0;
|
||||
} else {
|
||||
if(r == 0)
|
||||
log_err("remote control connection closed prematurely");
|
||||
log_addr(1, "failed connection from",
|
||||
&s->c->repinfo.addr, s->c->repinfo.addrlen);
|
||||
log_crypto_err("remote control failed ssl");
|
||||
clean_point(rc, s);
|
||||
return 0;
|
||||
|
||||
@@ -45,6 +45,9 @@
|
||||
|
||||
#ifndef DAEMON_REMOTE_H
|
||||
#define DAEMON_REMOTE_H
|
||||
#ifdef HAVE_OPENSSL_SSL_H
|
||||
#include "openssl/ssl.h"
|
||||
#endif
|
||||
struct config_file;
|
||||
struct listen_list;
|
||||
struct listen_port;
|
||||
@@ -66,8 +69,10 @@ struct rc_state {
|
||||
struct comm_point* c;
|
||||
/** in the handshake part */
|
||||
enum { rc_none, rc_hs_read, rc_hs_write } shake_state;
|
||||
#ifdef HAVE_SSL
|
||||
/** the ssl state */
|
||||
SSL* ssl;
|
||||
#endif
|
||||
/** the rc this is part of */
|
||||
struct daemon_remote* rc;
|
||||
};
|
||||
@@ -90,8 +95,10 @@ struct daemon_remote {
|
||||
int max_active;
|
||||
/** current commpoints busy; should be a short list, malloced */
|
||||
struct rc_state* busy_list;
|
||||
#ifdef HAVE_SSL
|
||||
/** the SSL context for creating new SSL streams */
|
||||
SSL_CTX* ctx;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -132,6 +139,18 @@ struct listen_port* daemon_remote_open_ports(struct config_file* cfg);
|
||||
int daemon_remote_open_accept(struct daemon_remote* rc,
|
||||
struct listen_port* ports, struct worker* worker);
|
||||
|
||||
/**
|
||||
* Stop accept handlers for TCP (until enabled again)
|
||||
* @param rc: state
|
||||
*/
|
||||
void daemon_remote_stop_accept(struct daemon_remote* rc);
|
||||
|
||||
/**
|
||||
* Stop accept handlers for TCP (until enabled again)
|
||||
* @param rc: state
|
||||
*/
|
||||
void daemon_remote_start_accept(struct daemon_remote* rc);
|
||||
|
||||
/**
|
||||
* Handle nonthreaded remote cmd execution.
|
||||
* @param worker: this worker (the remote worker).
|
||||
@@ -144,6 +163,7 @@ int remote_accept_callback(struct comm_point*, void*, int, struct comm_reply*);
|
||||
/** handle remote control data callbacks */
|
||||
int remote_control_callback(struct comm_point*, void*, int, struct comm_reply*);
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
/**
|
||||
* Print fixed line of text over ssl connection in blocking mode
|
||||
* @param ssl: print to
|
||||
@@ -170,6 +190,7 @@ int ssl_printf(SSL* ssl, const char* format, ...)
|
||||
* @return false on connection failure.
|
||||
*/
|
||||
int ssl_read_line(SSL* ssl, char* buf, size_t max);
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
/** routine to printout option values over SSL */
|
||||
void remote_get_opt_ssl(char* line, void* arg);
|
||||
|
||||
+5
-2
@@ -40,6 +40,7 @@
|
||||
* numbers. These 'statistics' may be of interest to the operator.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <ldns/wire2host.h>
|
||||
#include "daemon/stats.h"
|
||||
#include "daemon/worker.h"
|
||||
#include "daemon/daemon.h"
|
||||
@@ -99,12 +100,14 @@ void server_stats_log(struct server_stats* stats, struct worker* worker,
|
||||
(unsigned)stats->num_queries_missed_cache,
|
||||
(unsigned)stats->num_queries_prefetch);
|
||||
log_info("server stats for thread %d: requestlist max %u avg %g "
|
||||
"exceeded %u", threadnum, (unsigned)stats->max_query_list_size,
|
||||
"exceeded %u jostled %u", threadnum,
|
||||
(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+
|
||||
stats->num_queries_prefetch) : 0.0,
|
||||
(unsigned)worker->env.mesh->stats_dropped);
|
||||
(unsigned)worker->env.mesh->stats_dropped,
|
||||
(unsigned)worker->env.mesh->stats_jostled);
|
||||
}
|
||||
|
||||
/** get rrsets bogus number from validator */
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#ifndef DAEMON_STATS_H
|
||||
#define DAEMON_STATS_H
|
||||
#include "util/timehist.h"
|
||||
#include <ldns/buffer.h>
|
||||
struct worker;
|
||||
struct config_file;
|
||||
struct comm_point;
|
||||
|
||||
+136
-36
@@ -41,6 +41,10 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
#include "util/log.h"
|
||||
#include "daemon/daemon.h"
|
||||
#include "daemon/remote.h"
|
||||
@@ -51,6 +55,7 @@
|
||||
#include "services/cache/infra.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/module.h"
|
||||
#include "util/net_help.h"
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <openssl/crypto.h>
|
||||
@@ -82,13 +87,66 @@
|
||||
# include "winrc/win_svc.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NSS
|
||||
# include <nss3/nss.h>
|
||||
#endif
|
||||
|
||||
/** global debug value to keep track of heap memory allocation */
|
||||
void* unbound_start_brk = 0;
|
||||
|
||||
#if !defined(HAVE_EVENT_BASE_GET_METHOD) && (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP))
|
||||
static const char* ev_backend2str(int b)
|
||||
{
|
||||
switch(b) {
|
||||
case EVBACKEND_SELECT: return "select";
|
||||
case EVBACKEND_POLL: return "poll";
|
||||
case EVBACKEND_EPOLL: return "epoll";
|
||||
case EVBACKEND_KQUEUE: return "kqueue";
|
||||
case EVBACKEND_DEVPOLL: return "devpoll";
|
||||
case EVBACKEND_PORT: return "evport";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
#endif
|
||||
|
||||
/** get the event system in use */
|
||||
static void get_event_sys(const char** n, const char** s, const char** m)
|
||||
{
|
||||
#ifdef USE_WINSOCK
|
||||
*n = "event";
|
||||
*s = "winsock";
|
||||
*m = "WSAWaitForMultipleEvents";
|
||||
#elif defined(USE_MINI_EVENT)
|
||||
*n = "mini-event";
|
||||
*s = "internal";
|
||||
*m = "select";
|
||||
#else
|
||||
struct event_base* b;
|
||||
*s = event_get_version();
|
||||
# ifdef HAVE_EVENT_BASE_GET_METHOD
|
||||
*n = "libevent";
|
||||
b = event_base_new();
|
||||
*m = event_base_get_method(b);
|
||||
# elif defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
|
||||
*n = "libev";
|
||||
b = (struct event_base*)ev_default_loop(EVFLAG_AUTO);
|
||||
*m = ev_backend2str(ev_backend((struct ev_loop*)b));
|
||||
# else
|
||||
*n = "unknown";
|
||||
*m = "not obtainable";
|
||||
b = NULL;
|
||||
# endif
|
||||
# ifdef HAVE_EVENT_BASE_FREE
|
||||
event_base_free(b);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/** print usage. */
|
||||
static void usage()
|
||||
{
|
||||
const char** m;
|
||||
const char *evnm="event", *evsys="", *evmethod="";
|
||||
printf("usage: unbound [options]\n");
|
||||
printf(" start unbound daemon DNS resolver.\n");
|
||||
printf("-h this help\n");
|
||||
@@ -102,20 +160,21 @@ static void usage()
|
||||
printf(" service - used to start from services control panel\n");
|
||||
#endif
|
||||
printf("Version %s\n", PACKAGE_VERSION);
|
||||
printf("linked libs: event %s, ldns %s, %s\n",
|
||||
#ifdef USE_WINSOCK
|
||||
"winsock",
|
||||
#elif defined(USE_MINI_EVENT)
|
||||
"internal",
|
||||
#else
|
||||
event_get_version(),
|
||||
get_event_sys(&evnm, &evsys, &evmethod);
|
||||
printf("linked libs: %s %s (it uses %s), ldns %s, %s\n",
|
||||
evnm, evsys, evmethod, ldns_version(),
|
||||
#ifdef HAVE_SSL
|
||||
SSLeay_version(SSLEAY_VERSION)
|
||||
#elif defined(HAVE_NSS)
|
||||
NSS_GetVersion()
|
||||
#endif
|
||||
ldns_version(),
|
||||
SSLeay_version(SSLEAY_VERSION));
|
||||
);
|
||||
printf("linked modules:");
|
||||
for(m = module_list_avail(); *m; m++)
|
||||
printf(" %s", *m);
|
||||
printf("\n");
|
||||
printf("configured for %s on %s with options:%s\n",
|
||||
CONFIGURE_TARGET, CONFIGURE_DATE, CONFIGURE_BUILD_WITH);
|
||||
printf("BSD licensed, see LICENSE in source package for details.\n");
|
||||
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
|
||||
}
|
||||
@@ -150,12 +209,41 @@ checkrlimits(struct config_file* cfg)
|
||||
#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
|
||||
int numthread = 1; /* it forks */
|
||||
#else
|
||||
int numthread = cfg->num_threads;
|
||||
int numthread = (cfg->num_threads?cfg->num_threads:1);
|
||||
#endif
|
||||
size_t total = numthread * perthread + misc;
|
||||
size_t avail;
|
||||
struct rlimit rlim;
|
||||
|
||||
if(total > 1024 &&
|
||||
strncmp(event_get_version(), "mini-event", 10) == 0) {
|
||||
log_warn("too many file descriptors requested. The builtin"
|
||||
"mini-event cannot handle more than 1024. Config "
|
||||
"for less fds or compile with libevent");
|
||||
if(numthread*perthread_noudp+15 > 1024)
|
||||
fatal_exit("too much tcp. not enough fds.");
|
||||
cfg->outgoing_num_ports = (int)((1024
|
||||
- numthread*perthread_noudp
|
||||
- 10 /* safety margin */) /numthread);
|
||||
log_warn("continuing with less udp ports: %u",
|
||||
cfg->outgoing_num_ports);
|
||||
total = 1024;
|
||||
}
|
||||
if(perthread > 64 &&
|
||||
strncmp(event_get_version(), "winsock-event", 13) == 0) {
|
||||
log_err("too many file descriptors requested. The winsock"
|
||||
" event handler cannot handle more than 64 per "
|
||||
" thread. Config for less fds");
|
||||
if(perthread_noudp+2 > 64)
|
||||
fatal_exit("too much tcp. not enough fds.");
|
||||
cfg->outgoing_num_ports = (int)((64
|
||||
- perthread_noudp
|
||||
- 2/* safety margin */));
|
||||
log_warn("continuing with less udp ports: %u",
|
||||
cfg->outgoing_num_ports);
|
||||
total = numthread*(perthread_noudp+
|
||||
(size_t)cfg->outgoing_num_ports)+misc;
|
||||
}
|
||||
if(getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
|
||||
log_warn("getrlimit: %s", strerror(errno));
|
||||
return;
|
||||
@@ -166,8 +254,12 @@ checkrlimits(struct config_file* cfg)
|
||||
avail = (size_t)rlim.rlim_cur;
|
||||
rlim.rlim_cur = (rlim_t)(total + 10);
|
||||
rlim.rlim_max = (rlim_t)(total + 10);
|
||||
#ifdef HAVE_SETRLIMIT
|
||||
if(setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
|
||||
log_warn("setrlimit: %s", strerror(errno));
|
||||
#else
|
||||
if(1) {
|
||||
#endif
|
||||
log_warn("cannot increase max open fds from %u to %u",
|
||||
(unsigned)avail, (unsigned)total+10);
|
||||
/* check that calculation below does not underflow,
|
||||
@@ -179,27 +271,13 @@ checkrlimits(struct config_file* cfg)
|
||||
- 10 /* safety margin */) /numthread);
|
||||
log_warn("continuing with less udp ports: %u",
|
||||
cfg->outgoing_num_ports);
|
||||
log_warn("increase ulimit or decrease threads, ports in config to remove this warning");
|
||||
log_warn("increase ulimit or decrease threads, "
|
||||
"ports in config to remove this warning");
|
||||
return;
|
||||
}
|
||||
log_warn("increased limit(open files) from %u to %u",
|
||||
(unsigned)avail, (unsigned)total+10);
|
||||
}
|
||||
if(total > 1024 &&
|
||||
strncmp(event_get_version(), "mini-event", 10) == 0) {
|
||||
log_err("too many file descriptors requested. The builtin"
|
||||
"mini-event cannot handle more than 1024. Config "
|
||||
"for less fds or compile with libevent");
|
||||
fatal_exit("configuration needs too many file descriptors");
|
||||
}
|
||||
if(perthread > 64 &&
|
||||
strncmp(event_get_version(), "winsock-event", 13) == 0) {
|
||||
log_err("too many file descriptors requested. The winsock"
|
||||
" event handler cannot handle more than 64 per "
|
||||
" thread. Config for less fds or compile with "
|
||||
" libevent");
|
||||
fatal_exit("configuration needs too many file descriptors");
|
||||
}
|
||||
#else
|
||||
(void)cfg;
|
||||
#endif /* HAVE_GETRLIMIT */
|
||||
@@ -376,8 +454,17 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
* given to unbound on the commandline. */
|
||||
|
||||
/* read ssl keys while superuser and outside chroot */
|
||||
#ifdef HAVE_SSL
|
||||
if(!(daemon->rc = daemon_remote_create(cfg)))
|
||||
fatal_exit("could not set up remote-control");
|
||||
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
|
||||
if(!(daemon->listen_sslctx = listen_sslctx_create(
|
||||
cfg->ssl_service_key, cfg->ssl_service_pem, NULL)))
|
||||
fatal_exit("could not set up listen SSL_CTX");
|
||||
}
|
||||
if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL, NULL)))
|
||||
fatal_exit("could not set up connect SSL_CTX");
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_KILL
|
||||
/* check old pid file before forking */
|
||||
@@ -415,7 +502,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
* chown to get permissions */
|
||||
if(cfg->username && cfg->username[0]) {
|
||||
if(chown(daemon->pidfile, uid, gid) == -1) {
|
||||
fatal_exit("cannot chown %u.%u %s: %s",
|
||||
log_err("cannot chown %u.%u %s: %s",
|
||||
(unsigned)uid, (unsigned)gid,
|
||||
daemon->pidfile, strerror(errno));
|
||||
}
|
||||
@@ -426,6 +513,21 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
(void)daemon;
|
||||
#endif
|
||||
|
||||
/* Set user context */
|
||||
#ifdef HAVE_GETPWNAM
|
||||
if(cfg->username && cfg->username[0]) {
|
||||
#ifdef HAVE_SETUSERCONTEXT
|
||||
/* setusercontext does initgroups, setuid, setgid, and
|
||||
* also resource limits from login config, but we
|
||||
* still call setresuid, setresgid to be sure to set all uid*/
|
||||
if(setusercontext(NULL, pwd, uid,
|
||||
LOGIN_SETALL & ~LOGIN_SETUSER & ~LOGIN_SETGROUP) != 0)
|
||||
log_warn("unable to setusercontext %s: %s",
|
||||
cfg->username, strerror(errno));
|
||||
#endif /* HAVE_SETUSERCONTEXT */
|
||||
}
|
||||
#endif /* HAVE_GETPWNAM */
|
||||
|
||||
/* box into the chroot */
|
||||
#ifdef HAVE_CHROOT
|
||||
if(cfg->chrootdir && cfg->chrootdir[0]) {
|
||||
@@ -437,6 +539,9 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
if(chroot(cfg->chrootdir))
|
||||
fatal_exit("unable to chroot to %s: %s",
|
||||
cfg->chrootdir, strerror(errno));
|
||||
if(chdir("/"))
|
||||
fatal_exit("unable to chdir to / in chroot %s: %s",
|
||||
cfg->chrootdir, strerror(errno));
|
||||
verbose(VERB_QUERY, "chroot to %s", cfg->chrootdir);
|
||||
if(strncmp(*cfgfile, cfg->chrootdir,
|
||||
strlen(cfg->chrootdir)) == 0)
|
||||
@@ -478,20 +583,11 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
/* drop permissions after chroot, getpwnam, pidfile, syslog done*/
|
||||
#ifdef HAVE_GETPWNAM
|
||||
if(cfg->username && cfg->username[0]) {
|
||||
#ifdef HAVE_SETUSERCONTEXT
|
||||
/* setusercontext does initgroups, setuid, setgid, and
|
||||
* also resource limits from login config, but we
|
||||
* still call setresuid, setresgid to be sure to set all uid*/
|
||||
if(setusercontext(NULL, pwd, uid, LOGIN_SETALL) != 0)
|
||||
log_warn("unable to setusercontext %s: %s",
|
||||
cfg->username, strerror(errno));
|
||||
#else /* !HAVE_SETUSERCONTEXT */
|
||||
# ifdef HAVE_INITGROUPS
|
||||
if(initgroups(cfg->username, gid) != 0)
|
||||
log_warn("unable to initgroups %s: %s",
|
||||
cfg->username, strerror(errno));
|
||||
# endif /* HAVE_INITGROUPS */
|
||||
#endif /* HAVE_SETUSERCONTEXT */
|
||||
endpwent();
|
||||
|
||||
#ifdef HAVE_SETRESGID
|
||||
@@ -607,7 +703,9 @@ main(int argc, char* argv[])
|
||||
const char* winopt = NULL;
|
||||
int cmdline_verbose = 0;
|
||||
int debug_mode = 0;
|
||||
#ifdef UB_ON_WINDOWS
|
||||
int cmdline_cfg = 0;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SBRK
|
||||
/* take debug snapshot of heap */
|
||||
@@ -620,7 +718,9 @@ main(int argc, char* argv[])
|
||||
switch(c) {
|
||||
case 'c':
|
||||
cfgfile = optarg;
|
||||
#ifdef UB_ON_WINDOWS
|
||||
cmdline_cfg = 1;
|
||||
#endif
|
||||
break;
|
||||
case 'v':
|
||||
cmdline_verbose ++;
|
||||
|
||||
+82
-75
@@ -40,6 +40,7 @@
|
||||
* pending requests.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <ldns/wire2host.h>
|
||||
#include "util/log.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/random.h"
|
||||
@@ -66,7 +67,9 @@
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "util/tube.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
#include "validator/autotrust.h"
|
||||
#include "validator/val_anchor.h"
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
@@ -140,14 +143,14 @@ debug_total_mem(size_t calctotal)
|
||||
#endif /* UNBOUND_ALLOC_STATS */
|
||||
|
||||
/** Report on memory usage by this thread and global */
|
||||
void
|
||||
static void
|
||||
worker_mem_report(struct worker* ATTR_UNUSED(worker),
|
||||
struct serviced_query* ATTR_UNUSED(cur_serv))
|
||||
{
|
||||
#ifdef UNBOUND_ALLOC_STATS
|
||||
/* debug func in validator module */
|
||||
size_t total, front, back, mesh, msg, rrset, infra, ac, superac;
|
||||
size_t me, iter, val;
|
||||
size_t me, iter, val, anch;
|
||||
int i;
|
||||
if(verbosity < VERB_ALGO)
|
||||
return;
|
||||
@@ -159,6 +162,7 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
|
||||
mesh = mesh_get_mem(worker->env.mesh);
|
||||
ac = alloc_get_mem(&worker->alloc);
|
||||
superac = alloc_get_mem(&worker->daemon->superalloc);
|
||||
anch = anchors_get_mem(worker->env.anchors);
|
||||
iter = 0;
|
||||
val = 0;
|
||||
for(i=0; i<worker->env.mesh->mods.num; i++) {
|
||||
@@ -176,18 +180,21 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
|
||||
+ regional_get_mem(worker->scratchpad)
|
||||
+ sizeof(*worker->env.scratch_buffer)
|
||||
+ ldns_buffer_capacity(worker->env.scratch_buffer)
|
||||
+ forwards_get_mem(worker->env.fwds);
|
||||
+ forwards_get_mem(worker->env.fwds)
|
||||
+ hints_get_mem(worker->env.hints);
|
||||
if(worker->thread_num == 0)
|
||||
me += acl_list_get_mem(worker->daemon->acl);
|
||||
if(cur_serv) {
|
||||
me += serviced_get_mem(cur_serv);
|
||||
}
|
||||
total = front+back+mesh+msg+rrset+infra+iter+val+ac+superac+me;
|
||||
log_info("Memory conditions: %u front=%u back=%u mesh=%u msg=%u "
|
||||
"rrset=%u infra=%u iter=%u val=%u "
|
||||
"rrset=%u infra=%u iter=%u val=%u anchors=%u "
|
||||
"alloccache=%u globalalloccache=%u me=%u",
|
||||
(unsigned)total, (unsigned)front, (unsigned)back,
|
||||
(unsigned)mesh, (unsigned)msg, (unsigned)rrset,
|
||||
(unsigned)infra, (unsigned)iter, (unsigned)val, (unsigned)ac,
|
||||
(unsigned)superac, (unsigned)me);
|
||||
(unsigned)infra, (unsigned)iter, (unsigned)val, (unsigned)anch,
|
||||
(unsigned)ac, (unsigned)superac, (unsigned)me);
|
||||
debug_total_mem(total);
|
||||
#else /* no UNBOUND_ALLOC_STATS */
|
||||
size_t val = 0;
|
||||
@@ -282,9 +289,10 @@ worker_handle_service_reply(struct comm_point* c, void* arg, int error,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** check request sanity. Returns error code, 0 OK, or -1 discard.
|
||||
/** check request sanity.
|
||||
* @param pkt: the wire packet to examine for sanity.
|
||||
* @param worker: parameters for checking.
|
||||
* @return error code, 0 OK, or -1 discard.
|
||||
*/
|
||||
static int
|
||||
worker_check_request(ldns_buffer* pkt, struct worker* worker)
|
||||
@@ -442,7 +450,8 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
uint16_t udpsize = edns->udp_size;
|
||||
int secure = 0;
|
||||
uint32_t timenow = *worker->env.now;
|
||||
int must_validate = !(flags&BIT_CD) && worker->env.need_to_validate;
|
||||
int must_validate = (!(flags&BIT_CD) || worker->env.cfg->ignore_cd)
|
||||
&& worker->env.need_to_validate;
|
||||
struct dns_msg *msg = NULL;
|
||||
struct delegpt *dp;
|
||||
|
||||
@@ -518,7 +527,8 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
uint32_t timenow = *worker->env.now;
|
||||
uint16_t udpsize = edns->udp_size;
|
||||
int secure;
|
||||
int must_validate = !(flags&BIT_CD) && worker->env.need_to_validate;
|
||||
int must_validate = (!(flags&BIT_CD) || worker->env.cfg->ignore_cd)
|
||||
&& worker->env.need_to_validate;
|
||||
/* see if it is possible */
|
||||
if(rep->ttl < timenow) {
|
||||
/* the rrsets may have been updated in the meantime.
|
||||
@@ -733,17 +743,21 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
worker->stats.unwanted_queries++;
|
||||
return 0;
|
||||
} else if(acl == acl_refuse) {
|
||||
log_addr(VERB_ALGO, "refused query from",
|
||||
&repinfo->addr, repinfo->addrlen);
|
||||
log_buf(VERB_ALGO, "refuse", c->buffer);
|
||||
if(worker->stats.extended)
|
||||
worker->stats.unwanted_queries++;
|
||||
if(worker_check_request(c->buffer, worker) == -1) {
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0; /* discard this */
|
||||
}
|
||||
ldns_buffer_set_limit(c->buffer, LDNS_HEADER_SIZE);
|
||||
ldns_buffer_write_at(c->buffer, 4,
|
||||
(uint8_t*)"\0\0\0\0\0\0\0\0", 8);
|
||||
LDNS_QR_SET(ldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(ldns_buffer_begin(c->buffer),
|
||||
LDNS_RCODE_REFUSED);
|
||||
log_addr(VERB_ALGO, "refused query from",
|
||||
&repinfo->addr, repinfo->addrlen);
|
||||
log_buf(VERB_ALGO, "refuse", c->buffer);
|
||||
if(worker->stats.extended)
|
||||
worker->stats.unwanted_queries++;
|
||||
return 1;
|
||||
}
|
||||
if((ret=worker_check_request(c->buffer, worker)) != 0) {
|
||||
@@ -769,10 +783,16 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
server_stats_insrcode(&worker->stats, c->buffer);
|
||||
return 1;
|
||||
}
|
||||
if(worker->env.cfg->log_queries) {
|
||||
char ip[128];
|
||||
addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
|
||||
log_nametypeclass(0, ip, qinfo.qname, qinfo.qtype, qinfo.qclass);
|
||||
}
|
||||
if(qinfo.qtype == LDNS_RR_TYPE_AXFR ||
|
||||
qinfo.qtype == LDNS_RR_TYPE_IXFR) {
|
||||
verbose(VERB_ALGO, "worker request: refused zone transfer.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
ldns_buffer_rewind(c->buffer);
|
||||
LDNS_QR_SET(ldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(ldns_buffer_begin(c->buffer),
|
||||
LDNS_RCODE_REFUSED);
|
||||
@@ -905,14 +925,6 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
}
|
||||
|
||||
/* grab a work request structure for this new request */
|
||||
if(worker->env.mesh->num_reply_addrs>worker->request_size*16) {
|
||||
/* protect our memory usage from storing reply addresses */
|
||||
verbose(VERB_ALGO, "Too many requests queued. "
|
||||
"dropping incoming query.");
|
||||
worker->env.mesh->stats_dropped++;
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
mesh_new_client(worker->env.mesh, &qinfo,
|
||||
ldns_buffer_read_u16_at(c->buffer, 2),
|
||||
&edns, repinfo, *(uint16_t*)ldns_buffer_begin(c->buffer));
|
||||
@@ -1000,6 +1012,7 @@ void worker_probe_timer_cb(void* arg)
|
||||
struct worker*
|
||||
worker_create(struct daemon* daemon, int id, int* ports, int n)
|
||||
{
|
||||
unsigned int seed;
|
||||
struct worker* worker = (struct worker*)calloc(1,
|
||||
sizeof(struct worker));
|
||||
if(!worker)
|
||||
@@ -1017,6 +1030,19 @@ worker_create(struct daemon* daemon, int id, int* ports, int n)
|
||||
free(worker);
|
||||
return NULL;
|
||||
}
|
||||
/* create random state here to avoid locking trouble in RAND_bytes */
|
||||
seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^
|
||||
(((unsigned int)worker->thread_num)<<17);
|
||||
/* shift thread_num so it does not match out pid bits */
|
||||
if(!(worker->rndstate = ub_initstate(seed, daemon->rand))) {
|
||||
seed = 0;
|
||||
log_err("could not init random numbers.");
|
||||
tube_delete(worker->cmd);
|
||||
free(worker->ports);
|
||||
free(worker);
|
||||
return NULL;
|
||||
}
|
||||
seed = 0;
|
||||
return worker;
|
||||
}
|
||||
|
||||
@@ -1024,7 +1050,6 @@ int
|
||||
worker_init(struct worker* worker, struct config_file *cfg,
|
||||
struct listen_port* ports, int do_sigs)
|
||||
{
|
||||
unsigned int seed;
|
||||
worker->need_to_exit = 0;
|
||||
worker->base = comm_base_create(do_sigs);
|
||||
if(!worker->base) {
|
||||
@@ -1032,6 +1057,8 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
comm_base_set_slow_accept_handlers(worker->base, &worker_stop_accept,
|
||||
&worker_start_accept, worker);
|
||||
if(do_sigs) {
|
||||
#ifdef SIGHUP
|
||||
ub_thread_sig_unblock(SIGHUP);
|
||||
@@ -1069,19 +1096,9 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
} else { /* !do_sigs */
|
||||
worker->comsig = NULL;
|
||||
}
|
||||
seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^
|
||||
(((unsigned int)worker->thread_num)<<17);
|
||||
/* shift thread_num so it does not match out pid bits */
|
||||
if(!(worker->rndstate = ub_initstate(seed, NULL))) {
|
||||
seed = 0;
|
||||
log_err("could not init random numbers.");
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
seed = 0;
|
||||
worker->front = listen_create(worker->base, ports,
|
||||
cfg->msg_buffer_size, (int)cfg->incoming_num_tcp,
|
||||
worker_handle_request, worker);
|
||||
worker->daemon->listen_sslctx, worker_handle_request, worker);
|
||||
if(!worker->front) {
|
||||
log_err("could not create listening sockets");
|
||||
worker_delete(worker);
|
||||
@@ -1094,7 +1111,7 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
worker->daemon->env->infra_cache, worker->rndstate,
|
||||
cfg->use_caps_bits_for_id, worker->ports, worker->numports,
|
||||
cfg->unwanted_threshold, &worker_alloc_cleanup, worker,
|
||||
cfg->do_udp);
|
||||
cfg->do_udp, worker->daemon->connect_sslctx);
|
||||
if(!worker->back) {
|
||||
log_err("could not create outgoing sockets");
|
||||
worker_delete(worker);
|
||||
@@ -1121,7 +1138,6 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
worker->request_size = cfg->num_queries_per_thread;
|
||||
|
||||
server_stats_init(&worker->stats, cfg);
|
||||
alloc_init(&worker->alloc, &worker->daemon->superalloc,
|
||||
@@ -1132,7 +1148,6 @@ 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.send_packet = &worker_send_packet;
|
||||
worker->env.send_query = &worker_send_query;
|
||||
worker->env.alloc = &worker->alloc;
|
||||
worker->env.rnd = worker->rndstate;
|
||||
@@ -1149,6 +1164,12 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
if(!(worker->env.hints = hints_create()) ||
|
||||
!hints_apply_cfg(worker->env.hints, cfg)) {
|
||||
log_err("Could not set root or stub hints");
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
/* one probe timer per process -- if we have 5011 anchors */
|
||||
if(autr_get_num_anchors(worker->env.anchors) > 0
|
||||
#ifndef THREADS_DISABLED
|
||||
@@ -1201,6 +1222,7 @@ worker_delete(struct worker* worker)
|
||||
mesh_delete(worker->env.mesh);
|
||||
ldns_buffer_free(worker->env.scratch_buffer);
|
||||
forwards_delete(worker->env.fwds);
|
||||
hints_delete(worker->env.hints);
|
||||
listen_delete(worker->front);
|
||||
outside_network_delete(worker->back);
|
||||
comm_signal_delete(worker->comsig);
|
||||
@@ -1221,35 +1243,11 @@ worker_delete(struct worker* worker)
|
||||
free(worker);
|
||||
}
|
||||
|
||||
int
|
||||
worker_send_packet(ldns_buffer* pkt, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int timeout, struct module_qstate* q, int use_tcp)
|
||||
{
|
||||
struct worker* worker = q->env->worker;
|
||||
if(use_tcp) {
|
||||
return pending_tcp_query(worker->back, pkt, addr, addrlen,
|
||||
timeout, worker_handle_reply, q) != 0;
|
||||
}
|
||||
return pending_udp_query(worker->back, pkt, addr, addrlen,
|
||||
timeout*1000, worker_handle_reply, q) != 0;
|
||||
}
|
||||
|
||||
/** compare outbound entry qstates */
|
||||
static int
|
||||
outbound_entry_compare(void* a, void* b)
|
||||
{
|
||||
struct outbound_entry* e1 = (struct outbound_entry*)a;
|
||||
struct outbound_entry* e2 = (struct outbound_entry*)b;
|
||||
if(e1->qstate == e2->qstate)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct outbound_entry*
|
||||
worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
|
||||
uint16_t qclass, uint16_t flags, int dnssec,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct module_qstate* q)
|
||||
uint16_t qclass, uint16_t flags, int dnssec, int want_dnssec,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, struct module_qstate* q)
|
||||
{
|
||||
struct worker* worker = q->env->worker;
|
||||
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
|
||||
@@ -1258,9 +1256,10 @@ worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
|
||||
return NULL;
|
||||
e->qstate = q;
|
||||
e->qsent = outnet_serviced_query(worker->back, qname,
|
||||
qnamelen, qtype, qclass, flags, dnssec, addr, addrlen,
|
||||
worker_handle_service_reply, e, worker->back->udp_buff,
|
||||
&outbound_entry_compare);
|
||||
qnamelen, qtype, qclass, flags, dnssec, want_dnssec,
|
||||
q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr,
|
||||
addrlen, zone, zonelen, worker_handle_service_reply, e,
|
||||
worker->back->udp_buff);
|
||||
if(!e->qsent) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -1282,20 +1281,28 @@ void worker_stats_clear(struct worker* worker)
|
||||
worker->back->unwanted_replies = 0;
|
||||
}
|
||||
|
||||
/* --- fake callbacks for fptr_wlist to work --- */
|
||||
int libworker_send_packet(ldns_buffer* ATTR_UNUSED(pkt),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen), int ATTR_UNUSED(timeout),
|
||||
struct module_qstate* ATTR_UNUSED(q), int ATTR_UNUSED(use_tcp))
|
||||
void worker_start_accept(void* arg)
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
struct worker* worker = (struct worker*)arg;
|
||||
listen_start_accept(worker->front);
|
||||
if(worker->thread_num == 0)
|
||||
daemon_remote_start_accept(worker->daemon->rc);
|
||||
}
|
||||
|
||||
void worker_stop_accept(void* arg)
|
||||
{
|
||||
struct worker* worker = (struct worker*)arg;
|
||||
listen_stop_accept(worker->front);
|
||||
if(worker->thread_num == 0)
|
||||
daemon_remote_stop_accept(worker->daemon->rc);
|
||||
}
|
||||
|
||||
/* --- fake callbacks for fptr_wlist to work --- */
|
||||
struct outbound_entry* libworker_send_query(uint8_t* ATTR_UNUSED(qname),
|
||||
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
|
||||
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
|
||||
int ATTR_UNUSED(dnssec), struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen), struct module_qstate* ATTR_UNUSED(q))
|
||||
{
|
||||
log_assert(0);
|
||||
|
||||
+11
-19
@@ -102,9 +102,6 @@ struct worker {
|
||||
/** timer for statistics */
|
||||
struct comm_timer* stat_timer;
|
||||
|
||||
/** number of requests that can be handled by this worker */
|
||||
size_t request_size;
|
||||
|
||||
/** random() table for this worker. */
|
||||
struct ub_randstate* rndstate;
|
||||
/** do we need to restart or quit (on signal) */
|
||||
@@ -167,20 +164,6 @@ void worker_send_cmd(struct worker* worker, enum worker_commands cmd);
|
||||
*/
|
||||
void worker_sighandler(int sig, void* arg);
|
||||
|
||||
/**
|
||||
* Worker service routine to send udp messages for modules.
|
||||
* @param pkt: packet to send.
|
||||
* @param addr: where to.
|
||||
* @param addrlen: length of addr.
|
||||
* @param timeout: seconds to wait until timeout.
|
||||
* @param q: wich query state to reactivate upon return.
|
||||
* @param use_tcp: true to use TCP, false for UDP.
|
||||
* @return: false on failure (memory or socket related). no query was
|
||||
* sent.
|
||||
*/
|
||||
int worker_send_packet(ldns_buffer* pkt, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int timeout, struct module_qstate* q, int use_tcp);
|
||||
|
||||
/**
|
||||
* Worker service routine to send serviced queries to authoritative servers.
|
||||
* @param qname: query name. (host order)
|
||||
@@ -189,16 +172,19 @@ int worker_send_packet(ldns_buffer* pkt, struct sockaddr_storage* addr,
|
||||
* @param qclass: query class. (host order)
|
||||
* @param flags: host order flags word, with opcode and CD bit.
|
||||
* @param dnssec: if set, EDNS record will have DO bit set.
|
||||
* @param want_dnssec: signatures needed.
|
||||
* @param addr: where to.
|
||||
* @param addrlen: length of addr.
|
||||
* @param zone: wireformat dname of the zone.
|
||||
* @param zonelen: length of zone name.
|
||||
* @param q: wich query state to reactivate upon return.
|
||||
* @return: false on failure (memory or socket related). no query was
|
||||
* sent.
|
||||
*/
|
||||
struct outbound_entry* worker_send_query(uint8_t* qname, size_t qnamelen,
|
||||
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct module_qstate* q);
|
||||
int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, struct module_qstate* q);
|
||||
|
||||
/**
|
||||
* process control messages from the main thread. Frees the control
|
||||
@@ -239,4 +225,10 @@ void worker_stat_timer_cb(void* arg);
|
||||
/** probe timer callback handler */
|
||||
void worker_probe_timer_cb(void* arg);
|
||||
|
||||
/** start accept callback handler */
|
||||
void worker_start_accept(void* arg);
|
||||
|
||||
/** stop accept callback handler */
|
||||
void worker_stop_accept(void* arg);
|
||||
|
||||
#endif /* DAEMON_WORKER_H */
|
||||
|
||||
@@ -18,3 +18,4 @@ cz.nic - sponsoring 'summer of code' development by Zdenek and Marek.
|
||||
Brett Carr - windows beta testing.
|
||||
Luca Bruno - patch for windows support in libunbound hosts and resolvconf().
|
||||
Tom Hendrikx - contributed split-itar.sh a useful script to 5011-track ITAR.
|
||||
Daisuke HIGASHI - patch for rrset-roundrobin and minimal-responses.
|
||||
|
||||
+1293
File diff suppressed because it is too large
Load Diff
+34
-23
@@ -12,31 +12,45 @@ Big Features
|
||||
Recursive service.
|
||||
Caching service.
|
||||
Forwarding and stub zones.
|
||||
No authoritative service.
|
||||
Very limited authoritative service.
|
||||
DNSSEC Validation options.
|
||||
EDNS0, NSEC3, Unknown-RR-types.
|
||||
|
||||
EDNS0, NSEC3, IPv6, DNAME, Unknown-RR-types.
|
||||
RSASHA256, GOST, ECDSA, SHA384 DNSSEC algorithms.
|
||||
|
||||
Details
|
||||
-------
|
||||
Processing support
|
||||
RFC 1034-1035: as a recursive, caching server. Not authoritative.
|
||||
including CNAMEs, referrals, wildcards, classes, ...
|
||||
AAAA type, and IP6 dual stack support.
|
||||
type ANY queries are supported, class ANY queries are supported.
|
||||
RFC 1123, 6.1 Requirements for DNS of internet hosts.
|
||||
RFC 4033-4035: as a validating caching server (unbound daemon).
|
||||
as a validating stub (libunbound).
|
||||
RFC 1918.
|
||||
RFC 2181: completely, including the trust model, keeping rrsets together.
|
||||
RFC 2672: DNAME support.
|
||||
RFC 3597: Unknown RR type support.
|
||||
RFC 2671: EDNS0 support, default advertisement 4Kb size.
|
||||
RFC 5155: NSEC3, NSEC3PARAM types
|
||||
AAAA type. and IP6 dual stack support.
|
||||
type ANY queries are supported.
|
||||
RFC 2308: TTL directive, and the rest of the RFC too.
|
||||
RFC 4592: wildcards.
|
||||
|
||||
RFC 1995, 1996, 2136: not authoritative, so no AXFR, IXFR, NOTIFY or
|
||||
dynamic update services are appropriate.
|
||||
RFC 2181: completely, including the trust model, keeping rrsets together.
|
||||
RFC 2308: TTL directive, and the rest of the RFC too.
|
||||
RFC 2671: EDNS0 support, default advertisement 4Kb size.
|
||||
RFC 2672: DNAME support.
|
||||
RFC 3597: Unknown RR type support.
|
||||
RFC 4343: case insensitive handling of domain names.
|
||||
RFC 4509: SHA256 DS hash.
|
||||
RFC 4592: wildcards.
|
||||
RFC 4697: No DNS Resolution Misbehavior.
|
||||
RFC 5011: update of trust anchors with timers.
|
||||
RFC 5155: NSEC3, NSEC3PARAM types
|
||||
RFC 5358: reflectors-are-evil: access control list for recursive
|
||||
service. In fact for all DNS service so cache snooping is halted.
|
||||
RFC 5452: forgery resilience. all recommendations followed.
|
||||
RFC 5702: RSASHA256 signature algorithm.
|
||||
RFC 5933: GOST signature algorithm.
|
||||
RFC 6303: default local zones.
|
||||
It is possible to block zones or return an address for localhost.
|
||||
This is a very limited authoritative service. Defaults as in draft.
|
||||
RFC 6604: xNAME RCODE and status bits.
|
||||
RFC 6605: ECDSA signature algorithm, SHA384 DS hash.
|
||||
|
||||
chroot and drop-root-privileges support, default enabled in config file.
|
||||
|
||||
@@ -44,27 +58,23 @@ AD bit in query can be used to request AD bit in response (w/o using DO bit).
|
||||
CD bit in query can be used to request bogus data.
|
||||
UDP and TCP service is provided downstream.
|
||||
UDP and TCP are used to request from upstream servers.
|
||||
SSL wrapped TCP service can be used upstream and provided downstream.
|
||||
Multiple queries can be made over a TCP stream.
|
||||
|
||||
No TSIG support at this time.
|
||||
No SIG0 support at this time.
|
||||
No dTLS support at this time.
|
||||
This is not a DNS statistics package, but some operationally useful
|
||||
values are provided.
|
||||
TXT RRs from the Chaos class (id.server, hostname.bind, ...) supported.
|
||||
values are provided via unbound-control stats.
|
||||
TXT RRs from the Chaos class (id.server, hostname.bind, ...) are supported.
|
||||
|
||||
draft-forgery-resilience: all recommendations followed.
|
||||
draft-0x20: experimental implementation (incomplete).
|
||||
implements bitwise echo of the query to support downstream 0x20.
|
||||
draft-ietf-dnsop-default-local-zones is fully supported (-04).
|
||||
It is possible to block zones or return an address for localhost.
|
||||
This is a very limited authoritative service. Defaults as in draft.
|
||||
draft-0x20: implemented, use caps-for-id option to enable use.
|
||||
Also implements bitwise echo of the query to support downstream 0x20.
|
||||
draft-ietf-dnsop-resolver-priming(-00): can prime and can fallback to
|
||||
a safety belt list.
|
||||
draft-ietf-dnsop-dnssec-trust-anchor(-01): DS records can be configured
|
||||
as trust anchors. Also DNSKEYs are allowed, by the way.
|
||||
draft-ietf-dnsop-reflectors-are-evil: access control list for recursive
|
||||
service. In fact for all DNS service so cache snooping is halted.
|
||||
draft-ietf-dnsext-dnssec-bis-updates: supported.
|
||||
|
||||
Record type syntax support, extensive, from lib ldns.
|
||||
For these types only syntax and parsing support is needed.
|
||||
@@ -82,6 +92,7 @@ AAAA type
|
||||
2672: DNAME type.
|
||||
OPT type
|
||||
3123: APL
|
||||
3596: AAAA
|
||||
SSHFP type
|
||||
4025: IPSECKEY
|
||||
4033-4035: DS, RRSIG, NSEC, DNSKEY
|
||||
|
||||
+41
-9
@@ -11,16 +11,13 @@ This software is under BSD license, see LICENSE for details.
|
||||
|
||||
* Uses the following libraries;
|
||||
* ldns http://www.nlnetlabs.nl/ldns/ (BSD license)
|
||||
(required) can use tarball from source directory.
|
||||
(required) can use ldns build directory directly with --with-ldns=path.
|
||||
* libevent http://www.monkey.org/~provos/libevent/ (BSD license)
|
||||
(optional) can use builtin alternative instead.
|
||||
|
||||
* Make and install: ./configure; make; make install
|
||||
* Use GNU make; default on linux, often called 'gmake' on BSD and Solaris.
|
||||
* --with-ldns=/path/to/ldns
|
||||
If ldns is not detected on the system, a prepackaged tarball
|
||||
of the ldns library is used to compile and statically link against.
|
||||
If detected on the system, it will dynamically link against it.
|
||||
It will dynamically link against it.
|
||||
* --with-libevent=/path/to/libevent
|
||||
Can be set to either the system install or the build directory.
|
||||
--with-libevent=no (default) gives a builtin alternative
|
||||
@@ -28,6 +25,8 @@ This software is under BSD license, see LICENSE for details.
|
||||
of outgoing ports. This improves randomization and spoof
|
||||
resistance. For the default of 16 ports the builtin alternative
|
||||
works well and is a little faster.
|
||||
* --with-libexpat=/path/to/libexpat
|
||||
Can be set to the install directory of libexpat.
|
||||
* --without-pthreads
|
||||
This disables pthreads. Without this option the pthreads library
|
||||
is detected automatically. Use this option to disable threading
|
||||
@@ -59,6 +58,13 @@ This software is under BSD license, see LICENSE for details.
|
||||
* --with-chroot-dir=path
|
||||
Set default chroot directory,
|
||||
the default is /usr/local/etc/unbound.
|
||||
* --with-rootkey-file=path
|
||||
Set the default root.key path. This file is read and written.
|
||||
the default is /usr/local/etc/unbound/root.key
|
||||
* --with-rootcert-file=path
|
||||
Set the default root update certificate path. A builtin certificate
|
||||
is used if this file is empty or does not exist.
|
||||
the default is /usr/local/etc/unbound/icannbundle.pem
|
||||
* --with-username=user
|
||||
Set default user name to change to,
|
||||
the default is the "unbound" user.
|
||||
@@ -69,11 +75,10 @@ This software is under BSD license, see LICENSE for details.
|
||||
Compile the python module that processes responses in the server.
|
||||
* --disable-sha2
|
||||
Disable support for RSASHA256 and RSASHA512 crypto.
|
||||
* --enable-gost
|
||||
Enable draft support for GOST crypto.
|
||||
* --disable-gost
|
||||
Disable support for GOST crypto, RFC 5933.
|
||||
|
||||
* 'make test' attempts to run a series of tests, depending on the support
|
||||
programs that are installed.
|
||||
* 'make test' runs a series of self checks.
|
||||
|
||||
Known issues
|
||||
------------
|
||||
@@ -97,6 +102,7 @@ o The warning 'openssl has no entropy, seeding with time', with chroot
|
||||
o On Solaris 5.10 some libtool packages from repositories do not work with
|
||||
gcc, showing errors gcc: unrecognized option `-KPIC'
|
||||
To solve this do ./configure libtool=./libtool [your options...].
|
||||
On Solaris you may pass CFLAGS="-xO4 -xtarget=generic" if you use sun-cc.
|
||||
o If unbound-control (or munin graphs) do not work, this can often be because
|
||||
the unbound-control-setup script creates the keys with restricted
|
||||
permissions, and the files need to be made readable or ownered by both the
|
||||
@@ -115,4 +121,30 @@ o Other code origins are from the NSD (NLnet Labs) and LDNS (NLnet Labs)
|
||||
projects. Such as buffer, region-allocator and red-black tree code.
|
||||
o See Credits file for contributors.
|
||||
|
||||
|
||||
Your Support
|
||||
------------
|
||||
NLnet Labs offers all of its software products as open source, most are
|
||||
published under a BSD license. You can download them, not only from the
|
||||
NLnet Labs website but also through the various OS distributions for
|
||||
which NSD, ldns, and Unbound are packaged. We therefore have little idea
|
||||
who uses our software in production environments and have no direct ties
|
||||
with 'our customers'.
|
||||
|
||||
Therefore, we ask you to contact us at users@NLnetLabs.nl and tell us
|
||||
whether you use one of our products in your production environment,
|
||||
what that environment looks like, and maybe even share some praise.
|
||||
We would like to refer to the fact that your organization is using our
|
||||
products. We will only do that if you explicitly allow us. In all other
|
||||
cases we will keep the information you share with us to ourselves.
|
||||
|
||||
In addition to the moral support you can also support us
|
||||
financially. NLnet Labs is a recognized not-for-profit charity foundation
|
||||
that is chartered to develop open-source software and open-standards
|
||||
for the Internet. If you use our software to satisfaction please express
|
||||
that by giving us a donation. For small donations PayPal can be used. For
|
||||
larger and regular donations please contact us at users@NLnetLabs.nl. Also
|
||||
see http://www.nlnetlabs.nl/labs/contributors/.
|
||||
|
||||
|
||||
* mailto:unbound-bugs@nlnetlabs.nl
|
||||
|
||||
+6
-7
@@ -1,21 +1,20 @@
|
||||
README unbound tests
|
||||
|
||||
There is a test setup for unbound. Use
|
||||
For a quick test that runs unit tests and state machine tests, use
|
||||
make test
|
||||
To make and run the tests. The results are summarized at the end.
|
||||
|
||||
There is a long test setup for unbound that needs tools installed. Use
|
||||
make longtest
|
||||
To make and run the long tests. The results are summarized at the end.
|
||||
|
||||
You need to have the following programs installed and in your PATH.
|
||||
* dig - from the bind-tools package. Used to send DNS queries.
|
||||
* splint (optional) - for lint test
|
||||
* doxygen (optional) - for doc completeness test
|
||||
* ldns-testns (optional) - from ldns examples. Used as DNS auth server.
|
||||
* ldns-testns - from ldns examples. Used as DNS auth server.
|
||||
* xxd and nc (optional) - for (malformed) packet transmission.
|
||||
The optional programs are detected and can be omitted.
|
||||
|
||||
Without any support programs, unittest and testbound can still be used.
|
||||
(cd testdata; ../testcode/mini_tpkg.sh exe 02-unittest.tpkg)
|
||||
(cd testdata; ../testcode/mini_tpkg.sh exe 03-testbound.tpkg)
|
||||
|
||||
testdata/ contains the data for tests.
|
||||
testcode/ contains scripts and c code for the tests.
|
||||
|
||||
|
||||
@@ -69,3 +69,8 @@ later
|
||||
document high scalable, high available unbound setup onepager.
|
||||
- prefetch DNSKEY when DS in delegation seen (nonCD, underTA).
|
||||
- use libevent if available on system by default(?), default outgoing 256to1024
|
||||
|
||||
[1] BIND-like query logging to see who's looking up what and when
|
||||
[2] more logging about stuff like SERVFAIL and REFUSED responses
|
||||
[3] a Makefile that works without gnumake
|
||||
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
|
||||
Specification for the unbound-control protocol.
|
||||
|
||||
Server listens on 953 TCP (localhost by default). Client connects,
|
||||
Server listens on 8953 TCP (localhost by default). Client connects,
|
||||
SSLv3 or TLSv1 connection setup (server selfsigned certificate,
|
||||
client has cert signed by server certificate).
|
||||
|
||||
Port 8953 is registered with IANA as:
|
||||
ub-dns-control 8953/tcp unbound dns nameserver control
|
||||
# Wouter Wijngaards <wouter&nlnetlabs.nl> 10 May 2011
|
||||
On may 11 2011, ticket [IANA #442315].
|
||||
|
||||
Query and Response
|
||||
------------------
|
||||
Client sends
|
||||
UBCT [commandline] \n
|
||||
fixed string UBCT, then an ascii text line, with a command,
|
||||
some whitespace allowed. Line ends with '\n'.
|
||||
UBCT[version] [commandline] \n
|
||||
fixed string UBCT1 (for version 1), then an ascii text line,
|
||||
with a command, some whitespace allowed. Line ends with '\n'.
|
||||
|
||||
Server executes command. And sends reply in ascii text over channel,
|
||||
closes the channel when done.
|
||||
@@ -62,5 +67,4 @@ local_data <resource record string>
|
||||
local_data_add www.example.com. IN A 192.0.2.2
|
||||
if no local_zone exists for it; a transparent zone with the same
|
||||
name as the data is created.
|
||||
|
||||
|
||||
Other commands in the unbound-control manual page.
|
||||
|
||||
+67
-20
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Example configuration file.
|
||||
#
|
||||
# See unbound.conf(5) man page.
|
||||
# See unbound.conf(5) man page, version @version@.
|
||||
#
|
||||
# this is a comment.
|
||||
|
||||
@@ -54,8 +54,9 @@ server:
|
||||
# outgoing-interface: 2001:DB8::6
|
||||
|
||||
# number of ports to allocate per thread, determines the size of the
|
||||
# port range that can be open simultaneously.
|
||||
# outgoing-range: 256
|
||||
# port range that can be open simultaneously. About double the
|
||||
# num-queries-per-thread, or, use as many as the OS will allow you.
|
||||
# outgoing-range: 4096
|
||||
|
||||
# permit unbound to use this port number or port range for
|
||||
# making outgoing queries, using an outgoing interface.
|
||||
@@ -66,6 +67,8 @@ server:
|
||||
# Use this to make sure unbound does not grab a UDP port that some
|
||||
# other server on this computer needs. The default is to avoid
|
||||
# IANA-assigned port numbers.
|
||||
# If multiple outgoing-port-permit and outgoing-port-avoid options
|
||||
# are present, they are processed in order.
|
||||
# outgoing-port-avoid: "3200-3208"
|
||||
|
||||
# number of outgoing simultaneous tcp buffers to hold per thread.
|
||||
@@ -78,6 +81,10 @@ server:
|
||||
# 0 is system default. Use 4m to catch query spikes for busy servers.
|
||||
# so-rcvbuf: 0
|
||||
|
||||
# buffer size for UDP port 53 outgoing (SO_SNDBUF socket option).
|
||||
# 0 is system default. Use 4m to handle spikes on very busy servers.
|
||||
# so-sndbuf: 0
|
||||
|
||||
# EDNS reassembly buffer to advertise to UDP peers (the actual buffer
|
||||
# is set with msg-buffer-size). 1480 can solve fragmentation (timeouts).
|
||||
# edns-buffer-size: 4096
|
||||
@@ -118,24 +125,18 @@ server:
|
||||
# cache. Items are not cached for longer. In seconds.
|
||||
# cache-max-ttl: 86400
|
||||
|
||||
# the time to live (TTL) value for cached roundtrip times and
|
||||
# the time to live (TTL) value for cached roundtrip times, lameness and
|
||||
# EDNS version information for hosts. In seconds.
|
||||
# infra-host-ttl: 900
|
||||
|
||||
# the time to live (TTL) value for cached lame delegations. In sec.
|
||||
# infra-lame-ttl: 900
|
||||
|
||||
# the number of slabs to use for the Infrastructure cache.
|
||||
# the number of slabs must be a power of 2.
|
||||
# more slabs reduce lock contention, but fragment memory usage.
|
||||
# infra-cache-slabs: 4
|
||||
|
||||
# the maximum number of hosts that are cached (roundtrip times, EDNS).
|
||||
# the maximum number of hosts that are cached (roundtrip, EDNS, lame).
|
||||
# infra-cache-numhosts: 10000
|
||||
|
||||
# the maximum size of the lame zones cached per host. in bytes.
|
||||
# infra-cache-lame-size: 10k
|
||||
|
||||
# Enable IPv4, "yes" or "no".
|
||||
# do-ip4: yes
|
||||
|
||||
@@ -148,6 +149,10 @@ server:
|
||||
# Enable TCP, "yes" or "no".
|
||||
# do-tcp: yes
|
||||
|
||||
# upstream connections use TCP only (and no UDP), "yes" or "no"
|
||||
# useful for tunneling scenarios, default no.
|
||||
# tcp-upstream: no
|
||||
|
||||
# Detach from the terminal, run in background, "yes" or "no".
|
||||
# do-daemonize: yes
|
||||
|
||||
@@ -207,6 +212,9 @@ server:
|
||||
|
||||
# print UTC timestamp in ascii to logfile, default is epoch in seconds.
|
||||
# log-time-ascii: no
|
||||
|
||||
# print one line with time, IP, name, type, class for every query.
|
||||
# log-queries: no
|
||||
|
||||
# the pid file. Can be an absolute path outside of chroot/work dir.
|
||||
# pidfile: "@UNBOUND_PIDFILE@"
|
||||
@@ -252,6 +260,9 @@ server:
|
||||
# Default on, which insists on dnssec data for trust-anchored zones.
|
||||
# harden-dnssec-stripped: yes
|
||||
|
||||
# Harden against queries that fall under dnssec-signed nxdomain names.
|
||||
# harden-below-nxdomain: no
|
||||
|
||||
# Harden the referral path by performing additional queries for
|
||||
# infrastructure data. Validates the replies (if possible).
|
||||
# Default off, because the lookups burden the server. Experimental
|
||||
@@ -270,7 +281,7 @@ server:
|
||||
# private-address: 10.0.0.0/8
|
||||
# private-address: 172.16.0.0/12
|
||||
# private-address: 192.168.0.0/16
|
||||
# private-address: 192.254.0.0/16
|
||||
# private-address: 169.254.0.0/16
|
||||
# private-address: fd00::/8
|
||||
# private-address: fe80::/10
|
||||
|
||||
@@ -300,10 +311,27 @@ server:
|
||||
# if yes, perform key lookups adjacent to normal lookups.
|
||||
# prefetch-key: no
|
||||
|
||||
# if yes, Unbound rotates RRSet order in response.
|
||||
# rrset-roundrobin: no
|
||||
|
||||
# if yes, Unbound doesn't insert authority/additional sections
|
||||
# into response messages when those sections are not required.
|
||||
# minimal-responses: no
|
||||
|
||||
# module configuration of the server. A string with identifiers
|
||||
# separated by spaces. "iterator" or "validator iterator"
|
||||
# module-config: "validator iterator"
|
||||
|
||||
# File with trusted keys, kept uptodate using RFC5011 probes,
|
||||
# initial file like trust-anchor-file, then it stores metadata.
|
||||
# Use several entries, one per domain name, to track multiple zones.
|
||||
#
|
||||
# If you want to perform DNSSEC validation, run unbound-anchor before
|
||||
# you start unbound (i.e. in the system boot scripts). And enable:
|
||||
# Please note usage of unbound-anchor root anchor is at your own risk
|
||||
# and under the terms of our LICENSE (see that file in the source).
|
||||
# auto-trust-anchor-file: "@UNBOUND_ROOTKEY_FILE@"
|
||||
|
||||
# File with DLV trusted keys. Same format as trust-anchor-file.
|
||||
# There can be only one DLV configured, it is trusted from root down.
|
||||
# Download http://ftp.isc.org/www/dlv/dlv.isc.org.key
|
||||
@@ -312,15 +340,12 @@ server:
|
||||
# File with trusted keys for validation. Specify more than one file
|
||||
# with several entries, one file per entry.
|
||||
# Zone file format, with DS and DNSKEY entries.
|
||||
# Note this gets out of date, use auto-trust-anchor-file please.
|
||||
# trust-anchor-file: ""
|
||||
|
||||
# File with trusted keys, kept uptodate using RFC5011 probes,
|
||||
# initial file like trust-anchor-file, then it stores metadata.
|
||||
# Use several entries, one per domain name, to track multiple zones.
|
||||
# auto-trust-anchor-file: ""
|
||||
|
||||
# Trusted key for validation. DS or DNSKEY. specify the RR on a
|
||||
# single line, surrounded by "". TTL is ignored. class is IN default.
|
||||
# Note this gets out of date, use auto-trust-anchor-file please.
|
||||
# (These examples are from August 2007 and may not be valid anymore).
|
||||
# trust-anchor: "nlnetlabs.nl. DNSKEY 257 3 5 AQPzzTWMz8qSWIQlfRnPckx2BiVmkVN6LPupO3mbz7FhLSnm26n6iG9N Lby97Ji453aWZY3M5/xJBSOS2vWtco2t8C0+xeO1bc/d6ZTy32DHchpW 6rDH1vp86Ll+ha0tmwyy9QP7y2bVw5zSbFCrefk8qCUBgfHm9bHzMG1U BYtEIQ=="
|
||||
# trust-anchor: "jelte.nlnetlabs.nl. DS 42860 5 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A"
|
||||
@@ -329,6 +354,7 @@ server:
|
||||
# with several entries, one file per entry. Like trust-anchor-file
|
||||
# but has a different file format. Format is BIND-9 style format,
|
||||
# the trusted-keys { name flag proto algo "key"; }; clauses are read.
|
||||
# you need external update procedures to track changes in keys.
|
||||
# trusted-keys-file: ""
|
||||
|
||||
# Ignore chain of trust. Domain is treated as insecure.
|
||||
@@ -336,7 +362,7 @@ server:
|
||||
|
||||
# Override the date for validation with a specific fixed date.
|
||||
# Do not set this unless you are debugging signature inception
|
||||
# and expiration. "" or "0" turns the feature off.
|
||||
# and expiration. "" or "0" turns the feature off. -1 ignores date.
|
||||
# val-override-date: ""
|
||||
|
||||
# The time to live for bogus data, rrsets and messages. This avoids
|
||||
@@ -344,7 +370,7 @@ server:
|
||||
# val-bogus-ttl: 60
|
||||
|
||||
# The signature inception and expiration dates are allowed to be off
|
||||
# by 10% of the lifetime of the signature from our local clock.
|
||||
# by 10% of the signature lifetime (expir-incep) from our local clock.
|
||||
# This leeway is capped with a minimum and a maximum. In seconds.
|
||||
# val-sig-skew-min: 3600
|
||||
# val-sig-skew-max: 86400
|
||||
@@ -362,6 +388,11 @@ server:
|
||||
# replies if the message is found secure. The default is off.
|
||||
# val-permissive-mode: no
|
||||
|
||||
# Ignore the CD flag in incoming queries and refuse them bogus data.
|
||||
# Enable it if the only clients of unbound are legacy servers (w2008)
|
||||
# that set CD but cannot validate themselves.
|
||||
# ignore-cd-flag: no
|
||||
|
||||
# Have the validator log failed validations for your diagnosis.
|
||||
# 0: off. 1: A line per failed user query. 2: With reason and bad IP.
|
||||
# val-log-level: 0
|
||||
@@ -404,6 +435,7 @@ server:
|
||||
# o transparent gives local data, but resolves normally for other names
|
||||
# o redirect serves the zone data for any subdomain in the zone.
|
||||
# o nodefault can be used to normally resolve AS112 zones.
|
||||
# o typetransparent resolves normally for other types and other names
|
||||
#
|
||||
# defaults are localhost address, reverse for 127.0.0.1 and ::1
|
||||
# and nxdomain for AS112 zones. If you configure one of these zones
|
||||
@@ -430,6 +462,17 @@ server:
|
||||
# you need to do the reverse notation yourself.
|
||||
# local-data-ptr: "192.0.2.3 www.example.com"
|
||||
|
||||
# service clients over SSL (on the TCP sockets), with plain DNS inside
|
||||
# the SSL stream. Give the certificate to use and private key.
|
||||
# default is "" (disabled). requires restart to take effect.
|
||||
# ssl-service-key: "path/to/privatekeyfile.key"
|
||||
# ssl-service-pem: "path/to/publiccertfile.pem"
|
||||
# ssl-port: 443
|
||||
|
||||
# request upstream over SSL (with plain DNS inside the SSL stream).
|
||||
# Default is no. Can be turned on and off with unbound-control.
|
||||
# ssl-upstream: no
|
||||
|
||||
# Python config section. To enable:
|
||||
# o use --with-pythonmodule to configure before compiling.
|
||||
# o list python in the module-config string (above) to enable.
|
||||
@@ -450,7 +493,7 @@ remote-control:
|
||||
# control-interface: ::1
|
||||
|
||||
# port number for remote control operations.
|
||||
# control-port: 953
|
||||
# control-port: 8953
|
||||
|
||||
# unbound server key file.
|
||||
# server-key-file: "@UNBOUND_RUN_DIR@/unbound_server.key"
|
||||
@@ -469,10 +512,12 @@ remote-control:
|
||||
# 'example.org' go to the given list of nameservers. list zero or more
|
||||
# nameservers by hostname or by ipaddress. If you set stub-prime to yes,
|
||||
# the list is treated as priming hints (default is no).
|
||||
# With stub-first yes, it attempts without the stub if it fails.
|
||||
# stub-zone:
|
||||
# name: "example.com"
|
||||
# stub-addr: 192.0.2.68
|
||||
# stub-prime: no
|
||||
# stub-first: no
|
||||
# stub-zone:
|
||||
# name: "example.org"
|
||||
# stub-host: ns.example.com.
|
||||
@@ -482,10 +527,12 @@ remote-control:
|
||||
# 'example.org' go to the given list of servers. These servers have to handle
|
||||
# recursion to other nameservers. List zero or more nameservers by hostname
|
||||
# or by ipaddress. Use an entry with name "." to forward all queries.
|
||||
# If you enable forward-first, it attempts without the forward if it fails.
|
||||
# forward-zone:
|
||||
# name: "example.com"
|
||||
# forward-addr: 192.0.2.68
|
||||
# forward-addr: 192.0.2.73@5355 # forward to port 5355.
|
||||
# forward-first: no
|
||||
# forward-zone:
|
||||
# name: "example.org"
|
||||
# forward-host: fwd.example.com
|
||||
|
||||
+3
-1
@@ -203,7 +203,9 @@ At this time it is only possible to set configuration before the
|
||||
first resolve is done.
|
||||
.TP
|
||||
.B ub_ctx_resolvconf
|
||||
Read list of nameservers to use from the filename given.
|
||||
By default the root servers are queried and full resolver mode is used, but
|
||||
you can use this call to read the list of nameservers to use from the
|
||||
filename given.
|
||||
Usually "/etc/resolv.conf". Uses those nameservers as caching proxies.
|
||||
If they do not support DNSSEC, validation may fail.
|
||||
Only nameservers are picked up, the searchdomain, ndots and other
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
.TH "unbound-anchor" "8" "@date@" "NLnet Labs" "unbound @version@"
|
||||
.\"
|
||||
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
|
||||
.\"
|
||||
.\" Copyright (c) 2008, NLnet Labs. All rights reserved.
|
||||
.\"
|
||||
.\" See LICENSE for the license.
|
||||
.\"
|
||||
.\"
|
||||
.SH "NAME"
|
||||
.LP
|
||||
.B unbound\-anchor
|
||||
\- Unbound anchor utility.
|
||||
.SH "SYNOPSIS"
|
||||
.B unbound\-anchor
|
||||
.RB [ opts ]
|
||||
.SH "DESCRIPTION"
|
||||
.B Unbound\-anchor
|
||||
performs setup or update of the root trust anchor for DNSSEC validation.
|
||||
It can be run (as root) from the commandline, or run as part of startup
|
||||
scripts. Before you start the \fIunbound\fR(8) DNS server.
|
||||
.P
|
||||
Suggested usage:
|
||||
.P
|
||||
.nf
|
||||
# in the init scripts.
|
||||
# provide or update the root anchor (if necessary)
|
||||
unbound-anchor -a "@UNBOUND_ROOTKEY_FILE@"
|
||||
# Please note usage of this root anchor is at your own risk
|
||||
# and under the terms of our LICENSE (see source).
|
||||
#
|
||||
# start validating resolver
|
||||
# the unbound.conf contains:
|
||||
# auto-trust-anchor-file: "@UNBOUND_ROOTKEY_FILE@"
|
||||
unbound -c unbound.conf
|
||||
.fi
|
||||
.P
|
||||
This tool provides builtin default contents for the root anchor and root
|
||||
update certificate files.
|
||||
.P
|
||||
It tests if the root anchor file works, and if not, and an update is possible,
|
||||
attempts to update the root anchor using the root update certificate.
|
||||
It performs a https fetch of root-anchors.xml and checks the results, if
|
||||
all checks are successful, it updates the root anchor file. Otherwise
|
||||
the root anchor file is unchanged. It performs RFC5011 tracking if the
|
||||
DNSSEC information available via the DNS makes that possible.
|
||||
.P
|
||||
It does not perform an update if the certificate is expired, if the network
|
||||
is down or other errors occur.
|
||||
.P
|
||||
The available options are:
|
||||
.TP
|
||||
.B \-a \fIfile
|
||||
The root anchor key file, that is read in and written out.
|
||||
Default is @UNBOUND_ROOTKEY_FILE@.
|
||||
If the file does not exist, or is empty, a builtin root key is written to it.
|
||||
.TP
|
||||
.B \-c \fIfile
|
||||
The root update certificate file, that is read in.
|
||||
Default is @UNBOUND_ROOTCERT_FILE@.
|
||||
If the file does not exist, or is empty, a builtin certificate is used.
|
||||
.TP
|
||||
.B \-l
|
||||
List the builtin root key and builtin root update certificate on stdout.
|
||||
.TP
|
||||
.B \-u \fIname
|
||||
The server name, it connects to https://name. Specify without https:// prefix.
|
||||
The default is "data.iana.org". It connects to the port specified with \-P.
|
||||
You can pass an IPv4 addres or IPv6 address (no brackets) if you want.
|
||||
.TP
|
||||
.B \-x \fIpath
|
||||
The pathname to the root\-anchors.xml file on the server. (forms URL with \-u).
|
||||
The default is /root\-anchors/root\-anchors.xml.
|
||||
.TP
|
||||
.B \-s \fIpath
|
||||
The pathname to the root\-anchors.p7s file on the server. (forms URL with \-u).
|
||||
The default is /root\-anchors/root\-anchors.p7s. This file has to be a PKCS7
|
||||
signature over the xml file, using the pem file (\-c) as trust anchor.
|
||||
.TP
|
||||
.B \-4
|
||||
Use IPv4 for domain resolution and contacting the server on https. Default is
|
||||
to use IPv4 and IPv6 where appropriate.
|
||||
.TP
|
||||
.B \-6
|
||||
Use IPv6 for domain resolution and contacting the server on https. Default is
|
||||
to use IPv4 and IPv6 where appropriate.
|
||||
.TP
|
||||
.B \-f \fIresolv.conf
|
||||
Use the given resolv.conf file. Not enabled by default, but you could try to
|
||||
pass /etc/resolv.conf on some systems. It contains the IP addresses of the
|
||||
recursive nameservers to use. However, since this tool could be used to
|
||||
bootstrap that very recursive nameserver, it would not be useful (since
|
||||
that server is not up yet, since we are bootstrapping it). It could be
|
||||
useful in a situation where you know an upstream cache is deployed (and
|
||||
running) and in captive portal situations.
|
||||
.TP
|
||||
.B \-r \fIroot.hints
|
||||
Use the given root.hints file (same syntax as the BIND and Unbound root hints
|
||||
file) to bootstrap domain resolution. By default a list of builtin root
|
||||
hints is used. Unbound\-anchor goes to the network itself for these roots,
|
||||
to resolve the server (\-u option) and to check the root DNSKEY records.
|
||||
It does so, because the tool when used for bootstrapping the recursive
|
||||
resolver, cannot use that recursive resolver itself because it is bootstrapping
|
||||
that server.
|
||||
.TP
|
||||
.B \-v
|
||||
More verbose. Once prints informational messages, multiple times may enable
|
||||
large debug amounts (such as full certificates or byte\-dumps of downloaded
|
||||
files). By default it prints almost nothing. It also prints nothing on
|
||||
errors by default; in that case the original root anchor file is simply
|
||||
left undisturbed, so that a recursive server can start right after it.
|
||||
.TP
|
||||
.B \-C \fIunbound.conf
|
||||
Debug option to read unbound.conf into the resolver process used.
|
||||
.TP
|
||||
.B \-P \fIport
|
||||
Set the port number to use for the https connection. The default is 443.
|
||||
.TP
|
||||
.B \-F
|
||||
Debug option to force update of the root anchor through downloading the xml
|
||||
file and verifying it with the certificate. By default it first tries to
|
||||
update by contacting the DNS, which uses much less bandwidth, is much
|
||||
faster (200 msec not 2 sec), and is nicer to the deployed infrastructure.
|
||||
With this option, it still attempts to do so (and may verbosely tell you),
|
||||
but then ignores the result and goes on to use the xml fallback method.
|
||||
.TP
|
||||
.B \-h
|
||||
Show the version and commandline option help.
|
||||
.SH "EXIT CODE"
|
||||
This tool exits with value 1 if the root anchor was updated using the
|
||||
certificate or if the builtin root-anchor was used. It exits with code
|
||||
0 if no update was necessary, if the update was possible with RFC5011
|
||||
tracking, or if an error occurred.
|
||||
.P
|
||||
You can check the exit value in this manner:
|
||||
.nf
|
||||
unbound-anchor -a "root.key" || logger "Please check root.key"
|
||||
.fi
|
||||
Or something more suitable for your operational environment.
|
||||
.SH "TRUST"
|
||||
The root keys and update certificate included in this tool
|
||||
are provided for convenience and under the terms of our
|
||||
license (see the LICENSE file in the source distribution or
|
||||
http://unbound.nlnetlabs.nl/svn/trunk/LICENSE) and might be stale or
|
||||
not suitable to your purpose.
|
||||
.P
|
||||
By running "unbound\-anchor \-l" the keys and certificate that are
|
||||
configured in the code are printed for your convenience.
|
||||
.P
|
||||
The build\-in configuration can be overridden by providing a root\-cert
|
||||
file and a rootkey file.
|
||||
.SH "FILES"
|
||||
.TP
|
||||
.I @UNBOUND_ROOTKEY_FILE@
|
||||
The root anchor file, updated with 5011 tracking, and read and written to.
|
||||
The file is created if it does not exist.
|
||||
.TP
|
||||
.I @UNBOUND_ROOTCERT_FILE@
|
||||
The trusted self\-signed certificate that is used to verify the downloaded
|
||||
DNSSEC root trust anchor. You can update it by fetching it from
|
||||
https://data.iana.org/root\-anchors/icannbundle.pem (and validate it).
|
||||
If the file does not exist or is empty, a builtin version is used.
|
||||
.TP
|
||||
.I https://data.iana.org/root\-anchors/root\-anchors.xml
|
||||
Source for the root key information.
|
||||
.TP
|
||||
.I https://data.iana.org/root\-anchors/root\-anchors.p7s
|
||||
Signature on the root key information.
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound\fR(8).
|
||||
+61
-10
@@ -14,7 +14,7 @@
|
||||
\- Unbound remote server control utility.
|
||||
.SH "SYNOPSIS"
|
||||
.B unbound\-control
|
||||
.RB [ \-h ]
|
||||
.RB [ \-hq ]
|
||||
.RB [ \-c
|
||||
.IR cfgfile ]
|
||||
.RB [ \-s
|
||||
@@ -38,6 +38,9 @@ config file @ub_conf_file@ is used.
|
||||
.B \-s \fIserver[@port]
|
||||
IPv4 or IPv6 address of the server to contact. If not given, the
|
||||
address is read from the config file.
|
||||
.TP
|
||||
.B \-q
|
||||
quiet, if the option is given it does not print anything if it works ok.
|
||||
.SH "COMMANDS"
|
||||
There are several commands that the server understands.
|
||||
.TP
|
||||
@@ -127,6 +130,9 @@ Remove all information at or below the name from the cache.
|
||||
The rrsets and key entries are removed so that new lookups will be performed.
|
||||
This needs to walk and inspect the entire cache, and is a slow operation.
|
||||
.TP
|
||||
.B flush_bogus
|
||||
Remove all bogus data from the cache.
|
||||
.TP
|
||||
.B flush_stats
|
||||
Reset statistics to zero.
|
||||
.TP
|
||||
@@ -142,18 +148,40 @@ Show what is worked on. Prints all queries that the server is currently
|
||||
working on. Prints the time that users have been waiting. For internal
|
||||
requests, no time is printed. And then prints out the module status.
|
||||
.TP
|
||||
.B flush_infra \fIall|IP
|
||||
If all then entire infra cache is emptied. If a specific IP address, the
|
||||
entry for that address is removed from the cache. It contains EDNS, ping
|
||||
and lameness data.
|
||||
.TP
|
||||
.B dump_infra
|
||||
Show the contents of the infra cache.
|
||||
.TP
|
||||
.B set_option \fIopt: val
|
||||
Set the option to the given value without a reload. The cache is therefore
|
||||
not flushed. The option must end with a ':' and whitespace must be between the
|
||||
option and the value. Some values may not have an effect if set this way,
|
||||
the new values are not written to the config file, not all options are supported.
|
||||
Set the option to the given value without a reload. The cache is
|
||||
therefore not flushed. The option must end with a ':' and whitespace
|
||||
must be between the option and the value. Some values may not have an
|
||||
effect if set this way, the new values are not written to the config file,
|
||||
not all options are supported. This is different from the set_option call
|
||||
in libunbound, where all values work because unbound has not been inited.
|
||||
.IP
|
||||
The values that work are: statistics\-interval, statistics\-cumulative,
|
||||
do\-not\-query\-localhost, harden\-short\-bufsize, harden\-large\-queries,
|
||||
harden\-glue, harden\-dnssec\-stripped, harden\-below\-nxdomain,
|
||||
harden\-referral\-path, prefetch, prefetch\-key, log\-queries,
|
||||
hide\-identity, hide\-version, identity, version, val\-log\-level,
|
||||
val\-log\-squelch, ignore\-cd\-flag, add\-holddown, del\-holddown,
|
||||
keep\-missing, tcp\-upstream, ssl\-upstream.
|
||||
.TP
|
||||
.B get_option \fIopt
|
||||
Get the value of the option. Give the option name without a trailing ':'.
|
||||
The value is printed. If the value is "", nothing is printed and the
|
||||
connection closes. On error 'error ...' is printed (it gives a syntax
|
||||
error on unknown option). For some options a list of values, one on
|
||||
each line, is printed. Not all options are supported.
|
||||
The value is printed. If the value is "", nothing is printed
|
||||
and the connection closes. On error 'error ...' is printed (it gives
|
||||
a syntax error on unknown option). For some options a list of values,
|
||||
one on each line, is printed. The options are shown from the config file
|
||||
as modified with set_option. For some options an override may have been
|
||||
taken that does not show up with this command, not results from e.g. the
|
||||
verbosity and forward control commands. Not all options work, see list_stubs,
|
||||
list_forwards, list_local_zones and list_local_data for those.
|
||||
.TP
|
||||
.B list_stubs
|
||||
List the stub zones in use. These are printed one by one to the output.
|
||||
@@ -168,6 +196,27 @@ List the local zones in use. These are printed one per line with zone type.
|
||||
.B list_local_data
|
||||
List the local data RRs in use. The resource records are printed.
|
||||
.TP
|
||||
.B forward_add \fR[\fI+i\fR] \fIzone addr ...
|
||||
Add a new forward zone to running unbound. With +i option also adds a
|
||||
\fIdomain\-insecure\fR for the zone (so it can resolve insecurely if you have
|
||||
a DNSSEC root trust anchor configured for other names).
|
||||
The addr can be IP4, IP6 or nameserver names, like \fIforward-zone\fR config
|
||||
in unbound.conf.
|
||||
.TP
|
||||
.B forward_remove \fR[\fI+i\fR] \fIzone
|
||||
Remove a forward zone from running unbound. The +i also removes a
|
||||
\fIdomain\-insecure\fR for the zone.
|
||||
.TP
|
||||
.B stub_add \fR[\fI+ip\fR] \fIzone addr ...
|
||||
Add a new stub zone to running unbound. With +i option also adds a
|
||||
\fIdomain\-insecure\fR for the zone. With +p the stub zone is set to prime,
|
||||
without it it is set to notprime. The addr can be IP4, IP6 or nameserver
|
||||
names, like the \fIstub-zone\fR config in unbound.conf.
|
||||
.TP
|
||||
.B stub_remove \fR[\fI+i\fR] \fIzone
|
||||
Remove a stub zone from running unbound. The +i also removes a
|
||||
\fIdomain\-insecure\fR for the zone.
|
||||
.TP
|
||||
.B forward \fR[\fIoff\fR | \fIaddr ...\fR ]
|
||||
Setup forwarding mode. Configures if the server should ask other upstream
|
||||
nameservers, should go to the internet root nameservers itself, or show
|
||||
@@ -194,8 +243,10 @@ The unbound\-control program exits with status code 1 on error, 0 on success.
|
||||
The setup requires a self\-signed certificate and private keys for both
|
||||
the server and client. The script \fIunbound\-control\-setup\fR generates
|
||||
these in the default run directory, or with \-d in another directory.
|
||||
If you change the access control permissions on the key files you can decide
|
||||
who can use unbound\-control, by default owner and group but not all users.
|
||||
Run the script under the same username as you have configured in unbound.conf
|
||||
so that the daemon is permitted to read the files, for example with:
|
||||
or as root, so that the daemon is permitted to read the files, for example with:
|
||||
.nf
|
||||
sudo \-u unbound unbound\-control\-setup
|
||||
.fi
|
||||
|
||||
+142
-42
@@ -71,12 +71,12 @@ is followed by its containing attributes, or a value.
|
||||
.P
|
||||
Files can be included using the
|
||||
.B include:
|
||||
directive. It can appear anywhere, and takes a single filename as an argument.
|
||||
directive. It can appear anywhere, it accepts a single file name as argument.
|
||||
Processing continues as if the text from the included file was copied into
|
||||
the config file at that point. If also using chroot, using full path names
|
||||
for the included files works, relative pathnames for the included names work
|
||||
if the directory where the daemon is started equals its chroot/working
|
||||
directory.
|
||||
directory. Wildcards can be used to include multiple files, see \fIglob\fR(7).
|
||||
.SS "Server Options"
|
||||
These options are part of the
|
||||
.B server:
|
||||
@@ -92,7 +92,10 @@ The verbosity can also be increased from the commandline, see \fIunbound\fR(8).
|
||||
.TP
|
||||
.B statistics\-interval: \fI<seconds>
|
||||
The number of seconds between printing statistics to the log for every thread.
|
||||
Disable with value 0 or "". Default is disabled.
|
||||
Disable with value 0 or "". Default is disabled. The histogram statistics
|
||||
are only printed if replies were sent during the statistics interval,
|
||||
requestlist statistics are printed for every interval (but can be 0).
|
||||
This is because the median calculation requires data to be present.
|
||||
.TP
|
||||
.B statistics\-cumulative: \fI<yes or no>
|
||||
If enabled, statistics are cumulative since starting unbound, without clearing
|
||||
@@ -100,7 +103,8 @@ the statistics counters after logging the statistics. Default is no.
|
||||
.TP
|
||||
.B extended\-statistics: \fI<yes or no>
|
||||
If enabled, extended statistics are printed from \fIunbound\-control\fR(8).
|
||||
Default is off, because keeping track of more statistics takes time.
|
||||
Default is off, because keeping track of more statistics takes time. The
|
||||
counters are listed in \fIunbound\-control\fR(8).
|
||||
.TP
|
||||
.B num\-threads: \fI<number>
|
||||
The number of threads to create to serve clients. Use 1 for no threading.
|
||||
@@ -120,9 +124,8 @@ interface and port number), if not specified the default port (from
|
||||
.TP
|
||||
.B interface\-automatic: \fI<yes or no>
|
||||
Detect source interface on UDP queries and copy them to replies. This
|
||||
feature is experimental, and needs support in your OS for IPv6
|
||||
(and its socket options) and IPv4 (and have source\-interface socket options).
|
||||
Default value is no.
|
||||
feature is experimental, and needs support in your OS for particular socket
|
||||
options. Default value is no.
|
||||
.TP
|
||||
.B outgoing\-interface: \fI<ip address>
|
||||
Interface to use to connect to the network. This interface is used to send
|
||||
@@ -137,8 +140,9 @@ sent via a random outgoing interface to counter spoofing.
|
||||
.TP
|
||||
.B outgoing\-range: \fI<number>
|
||||
Number of ports to open. This number of file descriptors can be opened per
|
||||
thread. Must be at least 1. Default is 256. Larger numbers need extra
|
||||
resources from the operating system.
|
||||
thread. Must be at least 1. Default depends on compile options. Larger
|
||||
numbers need extra resources from the operating system. For performance a
|
||||
a very large value is best, use libevent to make this possible.
|
||||
.TP
|
||||
.B outgoing\-port\-permit: \fI<port number or range>
|
||||
Permit unbound to open this port or range of ports for use to send queries.
|
||||
@@ -172,7 +176,7 @@ to 0, or if do_tcp is "no", no TCP queries from clients are accepted.
|
||||
Number of bytes size to advertise as the EDNS reassembly buffer size.
|
||||
This is the value put into datagrams over UDP towards peers. The actual
|
||||
buffer size is determined by msg\-buffer\-size (both for TCP and UDP). Do
|
||||
not set lower than that value. Default is 4096 which is RFC recommended.
|
||||
not set higher than that value. Default is 4096 which is RFC recommended.
|
||||
If you have fragmentation reassembly problems, usually seen as timeouts,
|
||||
then a value of 1480 can fix it. Setting to 512 bypasses even the most
|
||||
stringent path MTU problems, but is seen as extreme, since the amount
|
||||
@@ -201,7 +205,7 @@ The number of queries that every thread will service simultaneously.
|
||||
If more queries arrive that need servicing, and no queries can be jostled out
|
||||
(see \fIjostle\-timeout\fR), then the queries are dropped. This forces
|
||||
the client to resend after a timeout; allowing the server time to work on
|
||||
the existing queries. Default 1024.
|
||||
the existing queries. Default depends on compile options, 512 or 1024.
|
||||
.TP
|
||||
.B jostle\-timeout: \fI<msec>
|
||||
Timeout used when the server is very busy. Set to a value that usually
|
||||
@@ -210,6 +214,11 @@ arrive, then 50% of the queries are allowed to run to completion, and
|
||||
the other 50% are replaced with the new incoming query if they have already
|
||||
spent more than their allowed time. This protects against denial of
|
||||
service by slow queries or high query rates. Default 200 milliseconds.
|
||||
The effect is that the qps for long-lasting queries is about
|
||||
(numqueriesperthread / 2) / (average time for such long queries) qps.
|
||||
The qps for short queries can be about (numqueriesperthread / 2)
|
||||
/ (jostletimeout in whole seconds) qps per thread, about (1024/2)*5 = 2560
|
||||
qps by default.
|
||||
.TP
|
||||
.B so\-rcvbuf: \fI<number>
|
||||
If not 0, then set the SO_RCVBUF socket option to get more buffer
|
||||
@@ -222,6 +231,17 @@ net.core.rmem_max. On BSD change kern.ipc.maxsockbuf in /etc/sysctl.conf.
|
||||
On OpenBSD change header and recompile kernel. On Solaris ndd \-set
|
||||
/dev/udp udp_max_buf 8388608.
|
||||
.TP
|
||||
.B so\-sndbuf: \fI<number>
|
||||
If not 0, then set the SO_SNDBUF socket option to get more buffer space on
|
||||
UDP port 53 outgoing queries. This for very busy servers handles spikes
|
||||
in answer traffic, otherwise 'send: resource temporarily unavailable'
|
||||
can get logged, the buffer overrun is also visible by netstat \-su.
|
||||
Default is 0 (use system value). Specify the number of bytes to ask
|
||||
for, try "4m" on a very busy server. The OS caps it at a maximum, on
|
||||
linux unbound needs root permission to bypass the limit, or the admin
|
||||
can use sysctl net.core.wmem_max. On BSD, Solaris changes are similar
|
||||
to so\-rcvbuf.
|
||||
.TP
|
||||
.B rrset\-cache\-size: \fI<number>
|
||||
Number of bytes size of the RRset cache. Default is 4 megabytes.
|
||||
A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes
|
||||
@@ -249,10 +269,7 @@ the data in the cache does not match up with the actual data any more.
|
||||
.TP
|
||||
.B infra\-host\-ttl: \fI<seconds>
|
||||
Time to live for entries in the host cache. The host cache contains
|
||||
roundtrip timing and EDNS support information. Default is 900.
|
||||
.TP
|
||||
.B infra\-lame\-ttl: \fI<seconds>
|
||||
The time to live when a delegation is discovered to be lame. Default is 900.
|
||||
roundtrip timing, lameness and EDNS support information. Default is 900.
|
||||
.TP
|
||||
.B infra\-cache\-slabs: \fI<number>
|
||||
Number of slabs in the infrastructure cache. Slabs reduce lock contention
|
||||
@@ -261,11 +278,6 @@ by threads. Must be set to a power of 2.
|
||||
.B infra\-cache\-numhosts: \fI<number>
|
||||
Number of hosts for which information is cached. Default is 10000.
|
||||
.TP
|
||||
.B infra\-cache\-lame\-size: \fI<number>
|
||||
Number of bytes that the lameness cache per host is allowed to use. Default
|
||||
is 10 kb, which gives maximum storage for a couple score zones, depending on
|
||||
the lame zone name lengths.
|
||||
.TP
|
||||
.B do\-ip4: \fI<yes or no>
|
||||
Enable or disable whether ip4 queries are answered or issued. Default is yes.
|
||||
.TP
|
||||
@@ -280,6 +292,33 @@ Enable or disable whether UDP queries are answered or issued. Default is yes.
|
||||
.B do\-tcp: \fI<yes or no>
|
||||
Enable or disable whether TCP queries are answered or issued. Default is yes.
|
||||
.TP
|
||||
.B tcp\-upstream: \fI<yes or no>
|
||||
Enable or disable whether the upstream queries use TCP only for transport.
|
||||
Default is no. Useful in tunneling scenarios.
|
||||
.TP
|
||||
.B ssl\-upstream: \fI<yes or no>
|
||||
Enabled or disable whether the upstream queries use SSL only for transport.
|
||||
Default is no. Useful in tunneling scenarios. The SSL contains plain DNS in
|
||||
TCP wireformat. The other server must support this (see \fBssl\-service\-key\fR).
|
||||
.TP
|
||||
.B ssl\-service-key: \fI<file>
|
||||
If enabled, the server provider SSL service on its TCP sockets. The clients
|
||||
have to use ssl\-upstream: yes. The file is the private key for the TLS
|
||||
session. The public certificate is in the ssl\-service\-pem file. Default
|
||||
is "", turned off. Requires a restart (a reload is not enough) if changed,
|
||||
because the private key is read while root permissions are held and before
|
||||
chroot (if any). Normal DNS TCP service is not provided and gives errors,
|
||||
this service is best run with a different \fBport:\fR config or \fI@port\fR
|
||||
suffixes in the \fBinterface\fR config.
|
||||
.TP
|
||||
.B ssl\-service\-pem: \fI<file>
|
||||
The public key certificate pem file for the ssl service. Default is "",
|
||||
turned off.
|
||||
.TP
|
||||
.B ssl\-port: \fI<number>
|
||||
The port number on which to provide TCP SSL service, default 443, only
|
||||
interfaces configured with that port number as @number get the SSL service.
|
||||
.TP
|
||||
.B do\-daemonize: \fI<yes or no>
|
||||
Enable or disable whether the unbound server forks into the background as
|
||||
a daemon. Default is yes.
|
||||
@@ -375,6 +414,12 @@ Sets logfile lines to use a timestamp in UTC ascii. Default is no, which
|
||||
prints the seconds since 1970 in brackets. No effect if using syslog, in
|
||||
that case syslog formats the timestamp printed into the log files.
|
||||
.TP
|
||||
.B log\-queries: \fI<yes or no>
|
||||
Prints one line per query to the log, with the log timestamp and IP address,
|
||||
name, type and class. Default is no. Note that it takes time to print these
|
||||
lines which makes the server (significantly) slower. Odd (nonprintable)
|
||||
characters in names are printed as '?'.
|
||||
.TP
|
||||
.B pidfile: \fI<filename>
|
||||
The process id is written to the file. Default is "@UNBOUND_PIDFILE@".
|
||||
So,
|
||||
@@ -446,6 +491,15 @@ removes DNSSEC data from packets, or a zone changes from signed to
|
||||
unsigned to badly signed often. If turned off you run the risk of a
|
||||
downgrade attack that disables security for a zone. Default is on.
|
||||
.TP
|
||||
.B harden\-below\-nxdomain: \fI<yes or no>
|
||||
From draft-vixie-dnsext-resimprove, returns nxdomain to queries for a name
|
||||
below another name that is already known to be nxdomain. DNSSEC mandates
|
||||
noerror for empty nonterminals, hence this is possible. Very old software
|
||||
might return nxdomain for empty nonterminals (that usually happen for reverse
|
||||
IP address lookups), and thus may be incompatible with this. To try to avoid
|
||||
this only DNSSEC-secure nxdomains are used, because the old software does not
|
||||
have DNSSEC. Default is off.
|
||||
.TP
|
||||
.B harden\-referral\-path: \fI<yes or no>
|
||||
Harden the referral path by performing additional queries for
|
||||
infrastructure data. Validates the replies if trust anchors are configured
|
||||
@@ -455,6 +509,8 @@ path to the answer.
|
||||
Default off, because it burdens the authority servers, and it is
|
||||
not RFC standard, and could lead to performance problems because of the
|
||||
extra query load that is generated. Experimental option.
|
||||
If you enable it consider adding more numbers after the target\-fetch\-policy
|
||||
to increase the max depth that is checked to.
|
||||
.TP
|
||||
.B use\-caps\-for\-id: \fI<yes or no>
|
||||
Use 0x20\-encoded random bits in the query to foil spoof attempts.
|
||||
@@ -476,7 +532,7 @@ that you configured is allowed to, and you can specify additional
|
||||
names using \fBprivate\-domain\fR. No private addresses are enabled
|
||||
by default. We consider to enable this for the RFC1918 private IP
|
||||
address space by default in later releases. That would enable private
|
||||
addresses for 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 192.254.0.0/16
|
||||
addresses for 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 169.254.0.0/16
|
||||
fd00::/8 and fe80::/10, since the RFC standards say these addresses
|
||||
should not be visible on the public internet. Turning on 127.0.0.0/8
|
||||
would hinder many spamblocklists as they use that.
|
||||
@@ -514,6 +570,18 @@ If yes, fetch the DNSKEYs earlier in the validation process, when a DS
|
||||
record is encountered. This lowers the latency of requests. It does use
|
||||
a little more CPU. Also if the cache is set to 0, it is no use. Default is no.
|
||||
.TP
|
||||
.B rrset-roundrobin: \fI<yes or no>
|
||||
If yes, Unbound rotates RRSet order in response (the random number is taken
|
||||
from the query ID, for speed and thread safety). Default is no.
|
||||
.TP
|
||||
.B minimal-responses: \fI<yes or no>
|
||||
If yes, Unbound doesn't insert authority/additional sections into response
|
||||
messages when those sections are not required. This reduces response
|
||||
size significantly, and may avoid TCP fallback for some responses.
|
||||
This may cause a slight speedup. The default is no, because the DNS
|
||||
protocol RFCs mandate these sections, and the additional content could
|
||||
be of use and save roundtrips for clients.
|
||||
.TP
|
||||
.B module\-config: \fI<"module names">
|
||||
Module configuration, a list of module names separated by spaces, surround
|
||||
the string with quotes (""). The modules can be validator, iterator.
|
||||
@@ -577,21 +645,24 @@ externally can create validation failures for that internal domain.
|
||||
Default is "" or "0", which disables this debugging feature. If enabled by
|
||||
giving a RRSIG style date, that date is used for verifying RRSIG inception
|
||||
and expiration dates, instead of the current date. Do not set this unless
|
||||
you are debugging signature inception and expiration.
|
||||
you are debugging signature inception and expiration. The value \-1 ignores
|
||||
the date altogether, useful for some special applications.
|
||||
.TP
|
||||
.B val\-sig\-skew\-min: \fI<seconds>
|
||||
Minimum number of seconds of clock skew to apply to validated signatures.
|
||||
A value of 10% of the signature lifetime is used, capped by this setting.
|
||||
Default is 3600 (1 hour) which allows for daylight savings differences.
|
||||
Lower this value for more strict checking of short lived signatures.
|
||||
A value of 10% of the signature lifetime (expiration \- inception) is
|
||||
used, capped by this setting. Default is 3600 (1 hour) which allows for
|
||||
daylight savings differences. Lower this value for more strict checking
|
||||
of short lived signatures.
|
||||
.TP
|
||||
.B val\-sig\-skew\-max: \fI<seconds>
|
||||
Maximum number of seconds of clock skew to apply to validated signatures.
|
||||
A value of 10% of the signature lifetime is used, capped by this setting.
|
||||
Default is 86400 (24 hours) which allows for timezone setting problems in
|
||||
stable domains. Setting both min and max very low disables the clock skew
|
||||
allowances. Setting both min and max very high makes the validator check
|
||||
the signature timestamps less strictly.
|
||||
A value of 10% of the signature lifetime (expiration \- inception)
|
||||
is used, capped by this setting. Default is 86400 (24 hours) which
|
||||
allows for timezone setting problems in stable domains. Setting both
|
||||
min and max very low disables the clock skew allowances. Setting both
|
||||
min and max very high makes the validator check the signature timestamps
|
||||
less strictly.
|
||||
.TP
|
||||
.B val\-bogus\-ttl: \fI<number>
|
||||
The time to live for bogus data. This is data that has failed validation;
|
||||
@@ -623,6 +694,14 @@ receives the bogus data. For messages that are found to be secure the AD bit
|
||||
is set in replies. Also logging is performed as for full validation.
|
||||
The default value is "no".
|
||||
.TP
|
||||
.B ignore\-cd\-flag: \fI<yes or no>
|
||||
Instruct unbound to ignore the CD flag from clients and refuse to
|
||||
return bogus answers to them. Thus, the CD (Checking Disabled) flag
|
||||
does not disable checking any more. This is useful if legacy (w2008)
|
||||
servers that set the CD flag but cannot validate DNSSEC themselves are
|
||||
the clients, and then unbound provides them with DNSSEC protection.
|
||||
The default value is "no".
|
||||
.TP
|
||||
.B val\-nsec3\-keysize\-iterations: \fI<"list of values">
|
||||
List of keysize and iteration count values, separated by spaces, surrounded
|
||||
by quotes. Default is "1024 150 2048 500 4096 2500". This determines the
|
||||
@@ -668,11 +747,12 @@ A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes
|
||||
or gigabytes (1024*1024 bytes in a megabyte).
|
||||
.TP
|
||||
.B local\-zone: \fI<zone> <type>
|
||||
Configure a local zone. The type determines the answer to give if there is
|
||||
no match from local\-data. The types are deny, refuse, static, transparent,
|
||||
redirect, nodefault, and are explained below. After that the default settings
|
||||
are listed. Use local\-data: to enter data into the local zone. Answers for
|
||||
local zones are authoritative DNS answers. By default the zones are class IN.
|
||||
Configure a local zone. The type determines the answer to give if
|
||||
there is no match from local\-data. The types are deny, refuse, static,
|
||||
transparent, redirect, nodefault, typetransparent, and are explained
|
||||
below. After that the default settings are listed. Use local\-data: to
|
||||
enter data into the local zone. Answers for local zones are authoritative
|
||||
DNS answers. By default the zones are class IN.
|
||||
.IP
|
||||
If you need more complicated authoritative data, with referrals, wildcards,
|
||||
CNAME/DNAME support, or DNSSEC authoritative service, setup a stub\-zone for
|
||||
@@ -700,6 +780,13 @@ given in localdata, then a noerror nodata answer is returned.
|
||||
If no local\-zone is given local\-data causes a transparent zone
|
||||
to be created by default.
|
||||
.TP 10
|
||||
\h'5'\fItypetransparent\fR
|
||||
If there is a match from local data, the query is answered. If the query
|
||||
is for a different name, or for the same name but for a different type,
|
||||
the query is resolved normally. So, similar to transparent but types
|
||||
that are not listed in local data are resolved normally, so if an A record
|
||||
is in the local data that does not cause a nodata reply for AAAA queries.
|
||||
.TP 10
|
||||
\h'5'\fIredirect\fR
|
||||
The query is answered from the local data for the zone name.
|
||||
There may be no local data beneath the zone name.
|
||||
@@ -773,7 +860,8 @@ records are provided.
|
||||
.TP 10
|
||||
\h'5'\fIreverse RFC3330 IP4 this, link\-local, testnet and broadcast\fR
|
||||
Reverse data for zones 0.in\-addr.arpa, 254.169.in\-addr.arpa,
|
||||
2.0.192.in\-addr.arpa, 255.255.255.255.in\-addr.arpa.
|
||||
2.0.192.in\-addr.arpa (TEST NET 1), 100.51.198.in\-addr.arpa (TEST NET 2),
|
||||
113.0.203.in\-addr.arpa (TEST NET 3), 255.255.255.255.in\-addr.arpa.
|
||||
.TP 10
|
||||
\h'5'\fIreverse RFC4291 IP6 unspecified\fR
|
||||
Reverse data for zone
|
||||
@@ -794,6 +882,8 @@ tutorials and examples. You can remove the block on this zone with:
|
||||
.nf
|
||||
local\-zone: 8.B.D.0.1.0.0.2.ip6.arpa. nodefault
|
||||
.fi
|
||||
You can also selectively unblock a part of the zone by making that part
|
||||
transparent with a local\-zone statement.
|
||||
This also works with the other default zones.
|
||||
.\" End of local-zone listing.
|
||||
.TP 5
|
||||
@@ -835,10 +925,9 @@ By default localhost (127.0.0.1 and ::1) is listened to.
|
||||
Use 0.0.0.0 and ::0 to listen to all interfaces.
|
||||
.TP 5
|
||||
.B control\-port: <port number>
|
||||
The port number to listen on for control commands, default is 953
|
||||
(that is the same port number named uses to listen to rndc).
|
||||
If you change this port number, and permissions have been dropped, a
|
||||
reload is not sufficient to open the port again, you must then restart.
|
||||
The port number to listen on for control commands, default is 8953.
|
||||
If you change this port number, and permissions have been dropped,
|
||||
a reload is not sufficient to open the port again, you must then restart.
|
||||
.TP 5
|
||||
.B server\-key\-file: "<private key file>"
|
||||
Path to the server private key, by default unbound_server.key.
|
||||
@@ -902,6 +991,12 @@ This option is by default off. If enabled it performs NS set priming,
|
||||
which is similar to root hints, where it starts using the list of nameservers
|
||||
currently published by the zone. Thus, if the hint list is slightly outdated,
|
||||
the resolver picks up a correct list online.
|
||||
.TP
|
||||
.B stub\-first: \fI<yes or no>
|
||||
If enabled, a query is attempted without the stub clause if it fails.
|
||||
The data could not be retrieved and would have caused SERVFAIL because
|
||||
the servers are unreachable, instead it is tried without this clause.
|
||||
The default is no.
|
||||
.SS "Forward Zone Options"
|
||||
.LP
|
||||
There may be multiple
|
||||
@@ -926,6 +1021,12 @@ Name of server to forward to. Is itself resolved before it is used.
|
||||
.B forward\-addr: \fI<IP address>
|
||||
IP address of server to forward to. Can be IP 4 or IP 6.
|
||||
To use a nondefault port for DNS communication append '@' with the port number.
|
||||
.TP
|
||||
.B forward\-first: \fI<yes or no>
|
||||
If enabled, a query is attempted without the forward clause if it fails.
|
||||
The data could not be retrieved and would have caused SERVFAIL because
|
||||
the servers are unreachable, instead it is tried without this clause.
|
||||
The default is no.
|
||||
.SS "Python Module Options"
|
||||
.LP
|
||||
The
|
||||
@@ -953,7 +1054,7 @@ server:
|
||||
num\-threads: 1
|
||||
outgoing\-num\-tcp: 1 # this limits TCP service, uses less buffers.
|
||||
incoming\-num\-tcp: 1
|
||||
outgoing\-range: 16 # uses less memory, but less performance.
|
||||
outgoing\-range: 60 # uses less memory, but less performance.
|
||||
msg\-buffer\-size: 8192 # note this limits service, 'no huge stuff'.
|
||||
msg\-cache\-size: 100k
|
||||
msg\-cache\-slabs: 1
|
||||
@@ -961,7 +1062,6 @@ server:
|
||||
rrset\-cache\-slabs: 1
|
||||
infra\-cache\-numhosts: 200
|
||||
infra\-cache\-slabs: 1
|
||||
infra\-cache\-lame\-size: 1k
|
||||
key\-cache\-size: 100k
|
||||
key\-cache\-slabs: 1
|
||||
neg\-cache\-size: 10k
|
||||
|
||||
+929
-550
File diff suppressed because it is too large
Load Diff
+209
-32
@@ -69,16 +69,19 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
|
||||
if(!delegpt_set_name(copy, region, dp->name))
|
||||
return NULL;
|
||||
copy->bogus = dp->bogus;
|
||||
copy->has_parent_side_NS = dp->has_parent_side_NS;
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
if(!delegpt_add_ns(copy, region, ns->name))
|
||||
if(!delegpt_add_ns(copy, region, ns->name, (int)ns->lame))
|
||||
return NULL;
|
||||
copy->nslist->resolved = ns->resolved;
|
||||
copy->nslist->got4 = ns->got4;
|
||||
copy->nslist->got6 = ns->got6;
|
||||
copy->nslist->done_pside4 = ns->done_pside4;
|
||||
copy->nslist->done_pside6 = ns->done_pside6;
|
||||
}
|
||||
for(a = dp->target_list; a; a = a->next_target) {
|
||||
if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen,
|
||||
a->bogus, a->lame, 0))
|
||||
a->bogus, a->lame))
|
||||
return NULL;
|
||||
}
|
||||
return copy;
|
||||
@@ -87,17 +90,20 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
|
||||
int
|
||||
delegpt_set_name(struct delegpt* dp, struct regional* region, uint8_t* name)
|
||||
{
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
dp->namelabs = dname_count_size_labels(name, &dp->namelen);
|
||||
dp->name = regional_alloc_init(region, name, dp->namelen);
|
||||
return dp->name != 0;
|
||||
}
|
||||
|
||||
int
|
||||
delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name)
|
||||
delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name,
|
||||
int lame)
|
||||
{
|
||||
struct delegpt_ns* ns;
|
||||
size_t len;
|
||||
(void)dname_count_size_labels(name, &len);
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
/* slow check for duplicates to avoid counting failures when
|
||||
* adding the same server as a dependency twice */
|
||||
if(delegpt_find_ns(dp, name, len))
|
||||
@@ -113,7 +119,10 @@ delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name)
|
||||
ns->resolved = 0;
|
||||
ns->got4 = 0;
|
||||
ns->got6 = 0;
|
||||
return 1;
|
||||
ns->lame = (uint8_t)lame;
|
||||
ns->done_pside4 = 0;
|
||||
ns->done_pside6 = 0;
|
||||
return ns->name != 0;
|
||||
}
|
||||
|
||||
struct delegpt_ns*
|
||||
@@ -147,9 +156,10 @@ delegpt_find_addr(struct delegpt* dp, struct sockaddr_storage* addr,
|
||||
int
|
||||
delegpt_add_target(struct delegpt* dp, struct regional* region,
|
||||
uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int bogus, int lame, int nodup)
|
||||
socklen_t addrlen, int bogus, int lame)
|
||||
{
|
||||
struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen);
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
if(!ns) {
|
||||
/* ignore it */
|
||||
return 1;
|
||||
@@ -161,23 +171,23 @@ 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, nodup);
|
||||
return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame);
|
||||
}
|
||||
|
||||
int
|
||||
delegpt_add_addr(struct delegpt* dp, struct regional* region,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int bogus,
|
||||
int lame, int nodup)
|
||||
int lame)
|
||||
{
|
||||
struct delegpt_addr* a;
|
||||
if(nodup) {
|
||||
if((a = delegpt_find_addr(dp, addr, addrlen))) {
|
||||
if(bogus)
|
||||
a->bogus = bogus;
|
||||
if(!lame)
|
||||
a->lame = 0;
|
||||
return 1;
|
||||
}
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
/* check for duplicates */
|
||||
if((a = delegpt_find_addr(dp, addr, addrlen))) {
|
||||
if(bogus)
|
||||
a->bogus = bogus;
|
||||
if(!lame)
|
||||
a->lame = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
a = (struct delegpt_addr*)regional_alloc(region,
|
||||
@@ -245,15 +255,19 @@ void delegpt_log(enum verbosity_value v, struct delegpt* dp)
|
||||
delegpt_count_ns(dp, &numns, &missing);
|
||||
delegpt_count_addr(dp, &numaddr, &numres, &numavail);
|
||||
log_info("DelegationPoint<%s>: %u names (%u missing), "
|
||||
"%u addrs (%u result, %u avail)",
|
||||
"%u addrs (%u result, %u avail)%s",
|
||||
buf, (unsigned)numns, (unsigned)missing,
|
||||
(unsigned)numaddr, (unsigned)numres, (unsigned)numavail);
|
||||
(unsigned)numaddr, (unsigned)numres, (unsigned)numavail,
|
||||
(dp->has_parent_side_NS?" parentNS":" cacheNS"));
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
dname_str(ns->name, buf);
|
||||
log_info(" %s %s%s%s%s", buf, (ns->resolved?"*":""),
|
||||
log_info(" %s %s%s%s%s%s%s%s", buf,
|
||||
(ns->resolved?"*":""),
|
||||
(ns->got4?" A":""), (ns->got6?" AAAA":""),
|
||||
(dp->bogus?" BOGUS":"") );
|
||||
(dp->bogus?" BOGUS":""), (ns->lame?" PARENTSIDE":""),
|
||||
(ns->done_pside4?" PSIDE_A":""),
|
||||
(ns->done_pside6?" PSIDE_AAAA":""));
|
||||
}
|
||||
for(a = dp->target_list; a; a = a->next_target) {
|
||||
const char* str = " ";
|
||||
@@ -277,6 +291,16 @@ delegpt_add_unused_targets(struct delegpt* dp)
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
delegpt_count_targets(struct delegpt* dp)
|
||||
{
|
||||
struct delegpt_addr* a;
|
||||
size_t n = 0;
|
||||
for(a = dp->target_list; a; a = a->next_target)
|
||||
n++;
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t
|
||||
delegpt_count_missing_targets(struct delegpt* dp)
|
||||
{
|
||||
@@ -325,9 +349,10 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region)
|
||||
dp = delegpt_create(region);
|
||||
if(!dp)
|
||||
return NULL;
|
||||
dp->has_parent_side_NS = 1; /* created from message */
|
||||
if(!delegpt_set_name(dp, region, ns_rrset->rk.dname))
|
||||
return NULL;
|
||||
if(!delegpt_rrset_add_ns(dp, region, ns_rrset))
|
||||
if(!delegpt_rrset_add_ns(dp, region, ns_rrset, 0))
|
||||
return NULL;
|
||||
|
||||
/* add glue, A and AAAA in answer and additional section */
|
||||
@@ -339,10 +364,10 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region)
|
||||
continue;
|
||||
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_A) {
|
||||
if(!delegpt_add_rrset_A(dp, region, s, 0, 0))
|
||||
if(!delegpt_add_rrset_A(dp, region, s, 0))
|
||||
return NULL;
|
||||
} else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA) {
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, s, 0, 0))
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, s, 0))
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -351,11 +376,12 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region)
|
||||
|
||||
int
|
||||
delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region,
|
||||
struct ub_packed_rrset_key* ns_rrset)
|
||||
struct ub_packed_rrset_key* ns_rrset, int lame)
|
||||
{
|
||||
struct packed_rrset_data* nsdata = (struct packed_rrset_data*)
|
||||
ns_rrset->entry.data;
|
||||
size_t i;
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
if(nsdata->security == sec_status_bogus)
|
||||
dp->bogus = 1;
|
||||
for(i=0; i<nsdata->count; i++) {
|
||||
@@ -364,7 +390,7 @@ delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region,
|
||||
(size_t)ldns_read_uint16(nsdata->rr_data[i]))
|
||||
continue; /* bad format */
|
||||
/* add rdata of NS (= wirefmt dname), skip rdatalen bytes */
|
||||
if(!delegpt_add_ns(dp, region, nsdata->rr_data[i]+2))
|
||||
if(!delegpt_add_ns(dp, region, nsdata->rr_data[i]+2, lame))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -372,12 +398,13 @@ delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region,
|
||||
|
||||
int
|
||||
delegpt_add_rrset_A(struct delegpt* dp, struct regional* region,
|
||||
struct ub_packed_rrset_key* ak, int lame, int nodup)
|
||||
struct ub_packed_rrset_key* ak, int lame)
|
||||
{
|
||||
struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data;
|
||||
size_t i;
|
||||
struct sockaddr_in sa;
|
||||
socklen_t len = (socklen_t)sizeof(sa);
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
memset(&sa, 0, len);
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
|
||||
@@ -387,7 +414,7 @@ delegpt_add_rrset_A(struct delegpt* dp, struct regional* region,
|
||||
memmove(&sa.sin_addr, d->rr_data[i]+2, INET_SIZE);
|
||||
if(!delegpt_add_target(dp, region, ak->rk.dname,
|
||||
ak->rk.dname_len, (struct sockaddr_storage*)&sa,
|
||||
len, (d->security==sec_status_bogus), lame, nodup))
|
||||
len, (d->security==sec_status_bogus), lame))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -395,12 +422,13 @@ delegpt_add_rrset_A(struct delegpt* dp, struct regional* region,
|
||||
|
||||
int
|
||||
delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region,
|
||||
struct ub_packed_rrset_key* ak, int lame, int nodup)
|
||||
struct ub_packed_rrset_key* ak, int lame)
|
||||
{
|
||||
struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data;
|
||||
size_t i;
|
||||
struct sockaddr_in6 sa;
|
||||
socklen_t len = (socklen_t)sizeof(sa);
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
memset(&sa, 0, len);
|
||||
sa.sin6_family = AF_INET6;
|
||||
sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
|
||||
@@ -410,7 +438,7 @@ delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region,
|
||||
memmove(&sa.sin6_addr, d->rr_data[i]+2, INET6_SIZE);
|
||||
if(!delegpt_add_target(dp, region, ak->rk.dname,
|
||||
ak->rk.dname_len, (struct sockaddr_storage*)&sa,
|
||||
len, (d->security==sec_status_bogus), lame, nodup))
|
||||
len, (d->security==sec_status_bogus), lame))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -418,16 +446,16 @@ delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region,
|
||||
|
||||
int
|
||||
delegpt_add_rrset(struct delegpt* dp, struct regional* region,
|
||||
struct ub_packed_rrset_key* rrset)
|
||||
struct ub_packed_rrset_key* rrset, int lame)
|
||||
{
|
||||
if(!rrset)
|
||||
return 1;
|
||||
if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_NS)
|
||||
return delegpt_rrset_add_ns(dp, region, rrset);
|
||||
return delegpt_rrset_add_ns(dp, region, rrset, lame);
|
||||
else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A)
|
||||
return delegpt_add_rrset_A(dp, region, rrset, 0, 1);
|
||||
return delegpt_add_rrset_A(dp, region, rrset, lame);
|
||||
else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA)
|
||||
return delegpt_add_rrset_AAAA(dp, region, rrset, 0, 1);
|
||||
return delegpt_add_rrset_AAAA(dp, region, rrset, lame);
|
||||
log_warn("Unknown rrset type added to delegpt");
|
||||
return 1;
|
||||
}
|
||||
@@ -461,3 +489,152 @@ void delegpt_no_ipv6(struct delegpt* dp)
|
||||
ns->resolved = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void delegpt_no_ipv4(struct delegpt* dp)
|
||||
{
|
||||
struct delegpt_ns* ns;
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
/* no ipv4, so only ipv6 is enough to resolve a nameserver */
|
||||
if(ns->got6)
|
||||
ns->resolved = 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct delegpt* delegpt_create_mlc(uint8_t* name)
|
||||
{
|
||||
struct delegpt* dp=(struct delegpt*)calloc(1, sizeof(*dp));
|
||||
if(!dp)
|
||||
return NULL;
|
||||
dp->dp_type_mlc = 1;
|
||||
if(name) {
|
||||
dp->namelabs = dname_count_size_labels(name, &dp->namelen);
|
||||
dp->name = memdup(name, dp->namelen);
|
||||
if(!dp->name) {
|
||||
free(dp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
void delegpt_free_mlc(struct delegpt* dp)
|
||||
{
|
||||
struct delegpt_ns* n, *nn;
|
||||
struct delegpt_addr* a, *na;
|
||||
if(!dp) return;
|
||||
log_assert(dp->dp_type_mlc);
|
||||
n = dp->nslist;
|
||||
while(n) {
|
||||
nn = n->next;
|
||||
free(n->name);
|
||||
free(n);
|
||||
n = nn;
|
||||
}
|
||||
a = dp->target_list;
|
||||
while(a) {
|
||||
na = a->next_target;
|
||||
free(a);
|
||||
a = na;
|
||||
}
|
||||
free(dp->name);
|
||||
free(dp);
|
||||
}
|
||||
|
||||
int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name)
|
||||
{
|
||||
log_assert(dp->dp_type_mlc);
|
||||
dp->namelabs = dname_count_size_labels(name, &dp->namelen);
|
||||
dp->name = memdup(name, dp->namelen);
|
||||
return (dp->name != NULL);
|
||||
}
|
||||
|
||||
int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, int lame)
|
||||
{
|
||||
struct delegpt_ns* ns;
|
||||
size_t len;
|
||||
(void)dname_count_size_labels(name, &len);
|
||||
log_assert(dp->dp_type_mlc);
|
||||
/* slow check for duplicates to avoid counting failures when
|
||||
* adding the same server as a dependency twice */
|
||||
if(delegpt_find_ns(dp, name, len))
|
||||
return 1;
|
||||
ns = (struct delegpt_ns*)malloc(sizeof(struct delegpt_ns));
|
||||
if(!ns)
|
||||
return 0;
|
||||
ns->namelen = len;
|
||||
ns->name = memdup(name, ns->namelen);
|
||||
if(!ns->name) {
|
||||
free(ns);
|
||||
return 0;
|
||||
}
|
||||
ns->next = dp->nslist;
|
||||
dp->nslist = ns;
|
||||
ns->resolved = 0;
|
||||
ns->got4 = 0;
|
||||
ns->got6 = 0;
|
||||
ns->lame = (uint8_t)lame;
|
||||
ns->done_pside4 = 0;
|
||||
ns->done_pside6 = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int bogus, int lame)
|
||||
{
|
||||
struct delegpt_addr* a;
|
||||
log_assert(dp->dp_type_mlc);
|
||||
/* check for duplicates */
|
||||
if((a = delegpt_find_addr(dp, addr, addrlen))) {
|
||||
if(bogus)
|
||||
a->bogus = bogus;
|
||||
if(!lame)
|
||||
a->lame = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
a = (struct delegpt_addr*)malloc(sizeof(struct delegpt_addr));
|
||||
if(!a)
|
||||
return 0;
|
||||
a->next_target = dp->target_list;
|
||||
dp->target_list = a;
|
||||
a->next_result = 0;
|
||||
a->next_usable = dp->usable_list;
|
||||
dp->usable_list = a;
|
||||
memcpy(&a->addr, addr, addrlen);
|
||||
a->addrlen = addrlen;
|
||||
a->attempts = 0;
|
||||
a->bogus = bogus;
|
||||
a->lame = lame;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int lame)
|
||||
{
|
||||
struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen);
|
||||
log_assert(dp->dp_type_mlc);
|
||||
if(!ns) {
|
||||
/* ignore it */
|
||||
return 1;
|
||||
}
|
||||
if(!lame) {
|
||||
if(addr_is_ip6(addr, addrlen))
|
||||
ns->got6 = 1;
|
||||
else ns->got4 = 1;
|
||||
if(ns->got4 && ns->got6)
|
||||
ns->resolved = 1;
|
||||
}
|
||||
return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame);
|
||||
}
|
||||
|
||||
size_t delegpt_get_mem(struct delegpt* dp)
|
||||
{
|
||||
struct delegpt_ns* ns;
|
||||
size_t s;
|
||||
if(!dp) return 0;
|
||||
s = sizeof(*dp) + dp->namelen +
|
||||
delegpt_count_targets(dp)*sizeof(struct delegpt_addr);
|
||||
for(ns=dp->nslist; ns; ns=ns->next)
|
||||
s += sizeof(*ns)+ns->namelen;
|
||||
return s;
|
||||
}
|
||||
|
||||
+102
-15
@@ -74,6 +74,13 @@ struct delegpt {
|
||||
|
||||
/** if true, the NS RRset was bogus. All info is bad. */
|
||||
int bogus;
|
||||
/** if true, the parent-side NS record has been applied:
|
||||
* its names have been added and their addresses can follow later.
|
||||
* Also true if the delegationpoint was created from a delegation
|
||||
* message and thus contains the parent-side-info already. */
|
||||
uint8_t has_parent_side_NS;
|
||||
/** for assertions on type of delegpt */
|
||||
uint8_t dp_type_mlc;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -90,13 +97,26 @@ struct delegpt_ns {
|
||||
* If the name has been resolved. false if not queried for yet.
|
||||
* true if the A, AAAA queries have been generated.
|
||||
* marked true if those queries fail.
|
||||
* and marked true is got4 and got6 are both true.
|
||||
* and marked true if got4 and got6 are both true.
|
||||
*/
|
||||
int resolved;
|
||||
/** if the ipv4 address is in the delegpt */
|
||||
uint8_t got4;
|
||||
/** if the ipv6 address is in the delegpt */
|
||||
uint8_t got6;
|
||||
/**
|
||||
* If the name is parent-side only and thus dispreferred.
|
||||
* Its addresses become dispreferred as well
|
||||
*/
|
||||
uint8_t lame;
|
||||
/** if the parent-side ipv4 address has been looked up (last resort).
|
||||
* Also enabled if a parent-side cache entry exists, or a parent-side
|
||||
* negative-cache entry exists. */
|
||||
uint8_t done_pside4;
|
||||
/** if the parent-side ipv6 address has been looked up (last resort).
|
||||
* Also enabled if a parent-side cache entry exists, or a parent-side
|
||||
* negative-cache entry exists. */
|
||||
uint8_t done_pside6;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -155,20 +175,22 @@ int delegpt_set_name(struct delegpt* dp, struct regional* regional,
|
||||
* @param dp: delegation point.
|
||||
* @param regional: where to allocate the info.
|
||||
* @param name: domain name in wire format.
|
||||
* @param lame: name is lame, disprefer it.
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_ns(struct delegpt* dp, struct regional* regional,
|
||||
uint8_t* name);
|
||||
uint8_t* name, int lame);
|
||||
|
||||
/**
|
||||
* Add NS rrset; calls add_ns repeatedly.
|
||||
* @param dp: delegation point.
|
||||
* @param regional: where to allocate the info.
|
||||
* @param ns_rrset: NS rrset.
|
||||
* return 0 on alloc error.
|
||||
* @param lame: rrset is lame, disprefer it.
|
||||
* @return 0 on alloc error.
|
||||
*/
|
||||
int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* regional,
|
||||
struct ub_packed_rrset_key* ns_rrset);
|
||||
struct ub_packed_rrset_key* ns_rrset, int lame);
|
||||
|
||||
/**
|
||||
* Add target address to the delegation point.
|
||||
@@ -181,13 +203,11 @@ int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* regional,
|
||||
* @param addrlen: the length of addr.
|
||||
* @param bogus: security status for the address, pass true if bogus.
|
||||
* @param lame: address is lame.
|
||||
* @param nodup: if true, no address duplicates are made by this add.
|
||||
* name duplicates are always filtered.
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_target(struct delegpt* dp, struct regional* regional,
|
||||
uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int bogus, int lame, int nodup);
|
||||
socklen_t addrlen, int bogus, int lame);
|
||||
|
||||
/**
|
||||
* Add A RRset to delegpt.
|
||||
@@ -195,11 +215,10 @@ int delegpt_add_target(struct delegpt* dp, struct regional* regional,
|
||||
* @param regional: where to allocate the info.
|
||||
* @param rrset: RRset A to add.
|
||||
* @param lame: rrset is lame, disprefer it.
|
||||
* @param nodup: if true, no duplicates are made by this add. takes time.
|
||||
* @return 0 on alloc error.
|
||||
*/
|
||||
int delegpt_add_rrset_A(struct delegpt* dp, struct regional* regional,
|
||||
struct ub_packed_rrset_key* rrset, int lame, int nodup);
|
||||
struct ub_packed_rrset_key* rrset, int lame);
|
||||
|
||||
/**
|
||||
* Add AAAA RRset to delegpt.
|
||||
@@ -207,11 +226,10 @@ int delegpt_add_rrset_A(struct delegpt* dp, struct regional* regional,
|
||||
* @param regional: where to allocate the info.
|
||||
* @param rrset: RRset AAAA to add.
|
||||
* @param lame: rrset is lame, disprefer it.
|
||||
* @param nodup: if true, no duplicates are made by this add. takes time.
|
||||
* @return 0 on alloc error.
|
||||
*/
|
||||
int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* regional,
|
||||
struct ub_packed_rrset_key* rrset, int lame, int nodup);
|
||||
struct ub_packed_rrset_key* rrset, int lame);
|
||||
|
||||
/**
|
||||
* Add any RRset to delegpt.
|
||||
@@ -219,10 +237,11 @@ int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* regional,
|
||||
* @param dp: delegation point.
|
||||
* @param regional: where to allocate the info.
|
||||
* @param rrset: RRset to add, NS, A, AAAA.
|
||||
* @param lame: rrset is lame, disprefer it.
|
||||
* @return 0 on alloc error.
|
||||
*/
|
||||
int delegpt_add_rrset(struct delegpt* dp, struct regional* regional,
|
||||
struct ub_packed_rrset_key* rrset);
|
||||
struct ub_packed_rrset_key* rrset, int lame);
|
||||
|
||||
/**
|
||||
* Add address to the delegation point. No servername is associated or checked.
|
||||
@@ -232,12 +251,10 @@ 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 nodup: if true, no duplicates are made by this add. takes time.
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_addr(struct delegpt* dp, struct regional* regional,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int bogus,
|
||||
int lame, int nodup);
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int lame);
|
||||
|
||||
/**
|
||||
* Find NS record in name list of delegation point.
|
||||
@@ -286,6 +303,9 @@ void delegpt_add_unused_targets(struct delegpt* dp);
|
||||
*/
|
||||
size_t delegpt_count_missing_targets(struct delegpt* dp);
|
||||
|
||||
/** count total number of targets in dp */
|
||||
size_t delegpt_count_targets(struct delegpt* dp);
|
||||
|
||||
/**
|
||||
* Create new delegation point from a dns message
|
||||
*
|
||||
@@ -321,4 +341,71 @@ void delegpt_add_neg_msg(struct delegpt* dp, struct msgreply_entry* msg);
|
||||
*/
|
||||
void delegpt_no_ipv6(struct delegpt* dp);
|
||||
|
||||
/**
|
||||
* Register the fact that there is no ipv4 and thus As are not going
|
||||
* to be queried for or be useful.
|
||||
* @param dp: the delegation point. Updated to reflect no ipv4.
|
||||
*/
|
||||
void delegpt_no_ipv4(struct delegpt* dp);
|
||||
|
||||
/**
|
||||
* create malloced delegation point, with the given name
|
||||
* @param name: uncompressed wireformat of degegpt name.
|
||||
* @return NULL on alloc failure
|
||||
*/
|
||||
struct delegpt* delegpt_create_mlc(uint8_t* name);
|
||||
|
||||
/**
|
||||
* free malloced delegation point.
|
||||
* @param dp: must have been created with delegpt_create_mlc, free'd.
|
||||
*/
|
||||
void delegpt_free_mlc(struct delegpt* dp);
|
||||
|
||||
/**
|
||||
* Set name of delegation point.
|
||||
* @param dp: delegation point. malloced.
|
||||
* @param name: name to use.
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name);
|
||||
|
||||
/**
|
||||
* add a name to malloced delegation point.
|
||||
* @param dp: must have been created with delegpt_create_mlc.
|
||||
* @param name: the name to add.
|
||||
* @param lame: the name is lame, disprefer.
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, int lame);
|
||||
|
||||
/**
|
||||
* add an address to a malloced delegation point.
|
||||
* @param dp: must have been created with delegpt_create_mlc.
|
||||
* @param addr: the address.
|
||||
* @param addrlen: the length of addr.
|
||||
* @param bogus: if address is bogus.
|
||||
* @param lame: if address is lame.
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int bogus, int lame);
|
||||
|
||||
/**
|
||||
* Add target address to the delegation point.
|
||||
* @param dp: must have been created with delegpt_create_mlc.
|
||||
* @param name: name for which target was found (must be in nslist).
|
||||
* This name is marked resolved.
|
||||
* @param namelen: length of name.
|
||||
* @param addr: the address.
|
||||
* @param addrlen: the length of addr.
|
||||
* @param bogus: security status for the address, pass true if bogus.
|
||||
* @param lame: address is lame.
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int lame);
|
||||
|
||||
/** get memory in use by dp */
|
||||
size_t delegpt_get_mem(struct delegpt* dp);
|
||||
|
||||
#endif /* ITERATOR_ITER_DELEGPT_H */
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
#include "util/net_help.h"
|
||||
|
||||
struct iter_donotq*
|
||||
donotq_create()
|
||||
donotq_create(void)
|
||||
{
|
||||
struct iter_donotq* dq = (struct iter_donotq*)calloc(1,
|
||||
sizeof(struct iter_donotq));
|
||||
|
||||
@@ -65,7 +65,7 @@ struct iter_donotq {
|
||||
* Create donotqueryaddresses structure
|
||||
* @return new structure or NULL on error.
|
||||
*/
|
||||
struct iter_donotq* donotq_create();
|
||||
struct iter_donotq* donotq_create(void);
|
||||
|
||||
/**
|
||||
* Delete donotqueryaddresses structure.
|
||||
|
||||
+125
-74
@@ -40,9 +40,11 @@
|
||||
* Keep track of forward zones and config settings.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <ldns/rdata.h>
|
||||
#include <ldns/dname.h>
|
||||
#include <ldns/rr.h>
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_delegpt.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
@@ -64,27 +66,42 @@ fwd_cmp(const void* k1, const void* k2)
|
||||
}
|
||||
|
||||
struct iter_forwards*
|
||||
forwards_create()
|
||||
forwards_create(void)
|
||||
{
|
||||
struct iter_forwards* fwd = (struct iter_forwards*)calloc(1,
|
||||
sizeof(struct iter_forwards));
|
||||
if(!fwd)
|
||||
return NULL;
|
||||
fwd->region = regional_create();
|
||||
if(!fwd->region) {
|
||||
forwards_delete(fwd);
|
||||
return NULL;
|
||||
}
|
||||
return fwd;
|
||||
}
|
||||
|
||||
static void fwd_zone_free(struct iter_forward_zone* n)
|
||||
{
|
||||
if(!n) return;
|
||||
delegpt_free_mlc(n->dp);
|
||||
free(n->name);
|
||||
free(n);
|
||||
}
|
||||
|
||||
static void delfwdnode(rbnode_t* n, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct iter_forward_zone* node = (struct iter_forward_zone*)n;
|
||||
fwd_zone_free(node);
|
||||
}
|
||||
|
||||
static void fwd_del_tree(struct iter_forwards* fwd)
|
||||
{
|
||||
if(fwd->tree)
|
||||
traverse_postorder(fwd->tree, &delfwdnode, NULL);
|
||||
free(fwd->tree);
|
||||
}
|
||||
|
||||
void
|
||||
forwards_delete(struct iter_forwards* fwd)
|
||||
{
|
||||
if(!fwd)
|
||||
return;
|
||||
regional_destroy(fwd->region);
|
||||
free(fwd->tree);
|
||||
fwd_del_tree(fwd);
|
||||
free(fwd);
|
||||
}
|
||||
|
||||
@@ -93,20 +110,28 @@ static int
|
||||
forwards_insert_data(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
|
||||
size_t nmlen, int nmlabs, struct delegpt* dp)
|
||||
{
|
||||
struct iter_forward_zone* node = regional_alloc(fwd->region,
|
||||
struct iter_forward_zone* node = (struct iter_forward_zone*)malloc(
|
||||
sizeof(struct iter_forward_zone));
|
||||
if(!node)
|
||||
if(!node) {
|
||||
delegpt_free_mlc(dp);
|
||||
return 0;
|
||||
}
|
||||
node->node.key = node;
|
||||
node->dclass = c;
|
||||
node->name = regional_alloc_init(fwd->region, nm, nmlen);
|
||||
if(!node->name)
|
||||
node->name = memdup(nm, nmlen);
|
||||
if(!node->name) {
|
||||
delegpt_free_mlc(dp);
|
||||
free(node);
|
||||
return 0;
|
||||
}
|
||||
node->namelen = nmlen;
|
||||
node->namelabs = nmlabs;
|
||||
node->dp = dp;
|
||||
if(!rbtree_insert(fwd->tree, &node->node)) {
|
||||
log_err("duplicate forward zone ignored.");
|
||||
delegpt_free_mlc(dp);
|
||||
free(node->name);
|
||||
free(node);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -149,33 +174,32 @@ fwd_init_parents(struct iter_forwards* fwd)
|
||||
}
|
||||
|
||||
/** set zone name */
|
||||
static int
|
||||
read_fwds_name(struct iter_forwards* fwd, struct config_stub* s,
|
||||
struct delegpt* dp)
|
||||
static struct delegpt*
|
||||
read_fwds_name(struct config_stub* s)
|
||||
{
|
||||
struct delegpt* dp;
|
||||
ldns_rdf* rdf;
|
||||
if(!s->name) {
|
||||
log_err("forward zone without a name (use name \".\" to forward everything)");
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
rdf = ldns_dname_new_frm_str(s->name);
|
||||
if(!rdf) {
|
||||
log_err("cannot parse forward zone name %s", s->name);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
if(!delegpt_set_name(dp, fwd->region, ldns_rdf_data(rdf))) {
|
||||
if(!(dp=delegpt_create_mlc(ldns_rdf_data(rdf)))) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
ldns_rdf_deep_free(rdf);
|
||||
return 1;
|
||||
return dp;
|
||||
}
|
||||
|
||||
/** set fwd host names */
|
||||
static int
|
||||
read_fwds_host(struct iter_forwards* fwd, struct config_stub* s,
|
||||
struct delegpt* dp)
|
||||
read_fwds_host(struct config_stub* s, struct delegpt* dp)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
ldns_rdf* rdf;
|
||||
@@ -187,7 +211,7 @@ read_fwds_host(struct iter_forwards* fwd, struct config_stub* s,
|
||||
s->name, p->str);
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_add_ns(dp, fwd->region, ldns_rdf_data(rdf))) {
|
||||
if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(rdf), 0)) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
@@ -199,8 +223,7 @@ read_fwds_host(struct iter_forwards* fwd, struct config_stub* s,
|
||||
|
||||
/** set fwd server addresses */
|
||||
static int
|
||||
read_fwds_addr(struct iter_forwards* fwd, struct config_stub* s,
|
||||
struct delegpt* dp)
|
||||
read_fwds_addr(struct config_stub* s, struct delegpt* dp)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
struct sockaddr_storage addr;
|
||||
@@ -212,8 +235,7 @@ read_fwds_addr(struct iter_forwards* fwd, struct config_stub* s,
|
||||
s->name, p->str);
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_add_addr(dp, fwd->region, &addr, addrlen,
|
||||
0, 0, 1)) {
|
||||
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
@@ -227,40 +249,38 @@ read_forwards(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
{
|
||||
struct config_stub* s;
|
||||
for(s = cfg->forwards; s; s = s->next) {
|
||||
struct delegpt* dp = delegpt_create(fwd->region);
|
||||
if(!dp) {
|
||||
log_err("out of memory");
|
||||
struct delegpt* dp;
|
||||
if(!(dp=read_fwds_name(s)))
|
||||
return 0;
|
||||
if(!read_fwds_host(s, dp) || !read_fwds_addr(s, dp)) {
|
||||
delegpt_free_mlc(dp);
|
||||
return 0;
|
||||
}
|
||||
if(!read_fwds_name(fwd, s, dp) ||
|
||||
!read_fwds_host(fwd, s, dp) ||
|
||||
!read_fwds_addr(fwd, s, dp))
|
||||
return 0;
|
||||
if(!forwards_insert(fwd, LDNS_RR_CLASS_IN, dp))
|
||||
return 0;
|
||||
/* set flag that parent side NS information is included.
|
||||
* Asking a (higher up) server on the internet is not useful */
|
||||
/* the flag is turned off for 'forward-first' so that the
|
||||
* last resort will ask for parent-side NS record and thus
|
||||
* fallback to the internet name servers on a failure */
|
||||
dp->has_parent_side_NS = (uint8_t)!s->isfirst;
|
||||
verbose(VERB_QUERY, "Forward zone server list:");
|
||||
delegpt_log(VERB_QUERY, dp);
|
||||
if(!forwards_insert(fwd, LDNS_RR_CLASS_IN, dp))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** see if zone needs to have a hole inserted */
|
||||
/** insert a stub hole (if necessary) for stub name */
|
||||
static int
|
||||
need_hole_insert(rbtree_t* tree, struct iter_forward_zone* zone)
|
||||
fwd_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||
{
|
||||
struct iter_forward_zone k;
|
||||
if(rbtree_search(tree, zone))
|
||||
return 0; /* exact match exists */
|
||||
k = *zone;
|
||||
k.node.key = &k;
|
||||
/* search up the tree */
|
||||
do {
|
||||
dname_remove_label(&k.name, &k.namelen);
|
||||
k.namelabs --;
|
||||
if(rbtree_search(tree, &k))
|
||||
return 1; /* found an upper forward zone, need hole */
|
||||
} while(k.namelabs > 1);
|
||||
return 0; /* no forwards above, no holes needed */
|
||||
struct iter_forward_zone key;
|
||||
key.node.key = &key;
|
||||
key.dclass = c;
|
||||
key.name = nm;
|
||||
key.namelabs = dname_count_size_labels(key.name, &key.namelen);
|
||||
return forwards_insert_data(fwd, key.dclass, key.name,
|
||||
key.namelen, key.namelabs, NULL);
|
||||
}
|
||||
|
||||
/** make NULL entries for stubs */
|
||||
@@ -268,23 +288,14 @@ static int
|
||||
make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
{
|
||||
struct config_stub* s;
|
||||
struct iter_forward_zone key;
|
||||
key.node.key = &key;
|
||||
key.dclass = LDNS_RR_CLASS_IN;
|
||||
for(s = cfg->stubs; s; s = s->next) {
|
||||
ldns_rdf* rdf = ldns_dname_new_frm_str(s->name);
|
||||
if(!rdf) {
|
||||
log_err("cannot parse stub name '%s'", s->name);
|
||||
return 0;
|
||||
}
|
||||
key.name = ldns_rdf_data(rdf);
|
||||
key.namelabs = dname_count_size_labels(key.name, &key.namelen);
|
||||
if(!need_hole_insert(fwd->tree, &key)) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
continue;
|
||||
}
|
||||
if(!forwards_insert_data(fwd, key.dclass, key.name,
|
||||
key.namelen, key.namelabs, NULL)) {
|
||||
if(!fwd_add_stub_hole(fwd, LDNS_RR_CLASS_IN,
|
||||
ldns_rdf_data(rdf))) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
@@ -297,8 +308,7 @@ make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
int
|
||||
forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
{
|
||||
free(fwd->tree);
|
||||
regional_free_all(fwd->region);
|
||||
fwd_del_tree(fwd);
|
||||
fwd->tree = rbtree_create(fwd_cmp);
|
||||
if(!fwd->tree)
|
||||
return 0;
|
||||
@@ -406,15 +416,36 @@ forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass)
|
||||
size_t
|
||||
forwards_get_mem(struct iter_forwards* fwd)
|
||||
{
|
||||
struct iter_forward_zone* p;
|
||||
size_t s;
|
||||
if(!fwd)
|
||||
return 0;
|
||||
return sizeof(*fwd) + sizeof(*fwd->tree) +
|
||||
regional_get_mem(fwd->region);
|
||||
s = sizeof(*fwd) + sizeof(*fwd->tree);
|
||||
RBTREE_FOR(p, struct iter_forward_zone*, fwd->tree) {
|
||||
s += sizeof(*p) + p->namelen + delegpt_get_mem(p->dp);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static struct iter_forward_zone*
|
||||
fwd_zone_find(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||
{
|
||||
struct iter_forward_zone key;
|
||||
key.node.key = &key;
|
||||
key.dclass = c;
|
||||
key.name = nm;
|
||||
key.namelabs = dname_count_size_labels(nm, &key.namelen);
|
||||
return (struct iter_forward_zone*)rbtree_search(fwd->tree, &key);
|
||||
}
|
||||
|
||||
int
|
||||
forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
|
||||
{
|
||||
struct iter_forward_zone *z;
|
||||
if((z=fwd_zone_find(fwd, c, dp->name)) != NULL) {
|
||||
(void)rbtree_delete(fwd->tree, &z->node);
|
||||
fwd_zone_free(z);
|
||||
}
|
||||
if(!forwards_insert(fwd, c, dp))
|
||||
return 0;
|
||||
fwd_init_parents(fwd);
|
||||
@@ -424,14 +455,34 @@ forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
|
||||
void
|
||||
forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||
{
|
||||
struct iter_forward_zone key;
|
||||
key.node.key = &key;
|
||||
key.dclass = c;
|
||||
key.name = nm;
|
||||
key.namelabs = dname_count_size_labels(nm, &key.namelen);
|
||||
if(!rbtree_search(fwd->tree, &key))
|
||||
struct iter_forward_zone *z;
|
||||
if(!(z=fwd_zone_find(fwd, c, nm)))
|
||||
return; /* nothing to do */
|
||||
(void)rbtree_delete(fwd->tree, &key);
|
||||
(void)rbtree_delete(fwd->tree, &z->node);
|
||||
fwd_zone_free(z);
|
||||
fwd_init_parents(fwd);
|
||||
}
|
||||
|
||||
int
|
||||
forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||
{
|
||||
if(!fwd_add_stub_hole(fwd, c, nm)) {
|
||||
return 0;
|
||||
}
|
||||
fwd_init_parents(fwd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||
{
|
||||
struct iter_forward_zone *z;
|
||||
if(!(z=fwd_zone_find(fwd, c, nm)))
|
||||
return; /* nothing to do */
|
||||
if(z->dp != NULL)
|
||||
return; /* not a stub hole */
|
||||
(void)rbtree_delete(fwd->tree, &z->node);
|
||||
fwd_zone_free(z);
|
||||
fwd_init_parents(fwd);
|
||||
}
|
||||
|
||||
|
||||
+26
-10
@@ -45,14 +45,11 @@
|
||||
#include "util/rbtree.h"
|
||||
struct config_file;
|
||||
struct delegpt;
|
||||
struct regional;
|
||||
|
||||
/**
|
||||
* Iterator forward zones structure
|
||||
*/
|
||||
struct iter_forwards {
|
||||
/** regional where forward zone server addresses are allocated */
|
||||
struct regional* region;
|
||||
/**
|
||||
* Zones are stored in this tree. Sort order is specially chosen.
|
||||
* first sorted on qclass. Then on dname in nsec-like order, so that
|
||||
@@ -77,7 +74,9 @@ struct iter_forward_zone {
|
||||
int namelabs;
|
||||
/** delegation point with forward server information for this zone.
|
||||
* If NULL then this forward entry is used to indicate that a
|
||||
* stub-zone with the same name exists, and should be used. */
|
||||
* stub-zone with the same name exists, and should be used.
|
||||
* This delegation point is malloced.
|
||||
*/
|
||||
struct delegpt* dp;
|
||||
/** pointer to parent in tree (or NULL if none) */
|
||||
struct iter_forward_zone* parent;
|
||||
@@ -89,7 +88,7 @@ struct iter_forward_zone {
|
||||
* Create forwards
|
||||
* @return new forwards or NULL on error.
|
||||
*/
|
||||
struct iter_forwards* forwards_create();
|
||||
struct iter_forwards* forwards_create(void);
|
||||
|
||||
/**
|
||||
* Delete forwards.
|
||||
@@ -152,9 +151,7 @@ int fwd_cmp(const void* k1, const void* k2);
|
||||
* @param fwd: the forward data structure
|
||||
* @param c: class of zone
|
||||
* @param dp: delegation point with name and target nameservers for new
|
||||
* forward zone. This delegation point and all its data must be
|
||||
* malloced in the fwd->region. (then it is freed when the fwd is
|
||||
* deleted).
|
||||
* forward zone. malloced.
|
||||
* @return false on failure (out of memory);
|
||||
*/
|
||||
int forwards_add_zone(struct iter_forwards* fwd, uint16_t c,
|
||||
@@ -162,12 +159,31 @@ int forwards_add_zone(struct iter_forwards* fwd, uint16_t c,
|
||||
|
||||
/**
|
||||
* Remove zone from forward structure. For external use since it
|
||||
* recalcs the tree parents. Does not actually release any memory, the region
|
||||
* is unchanged.
|
||||
* recalcs the tree parents.
|
||||
* @param fwd: the forward data structure
|
||||
* @param c: class of zone
|
||||
* @param nm: name of zone (in uncompressed wireformat).
|
||||
*/
|
||||
void forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm);
|
||||
|
||||
/**
|
||||
* Add stub hole (empty entry in forward table, that makes resolution skip
|
||||
* a forward-zone because the stub zone should override the forward zone).
|
||||
* Does not add one if not necessary.
|
||||
* @param fwd: the forward data structure
|
||||
* @param c: class of zone
|
||||
* @param nm: name of zone (in uncompressed wireformat).
|
||||
* @return false on failure (out of memory);
|
||||
*/
|
||||
int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm);
|
||||
|
||||
/**
|
||||
* Remove stub hole, if one exists.
|
||||
* @param fwd: the forward data structure
|
||||
* @param c: class of zone
|
||||
* @param nm: name of zone (in uncompressed wireformat).
|
||||
*/
|
||||
void forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
|
||||
uint8_t* nm);
|
||||
|
||||
#endif /* ITERATOR_ITER_FWD_H */
|
||||
|
||||
+143
-79
@@ -40,41 +40,55 @@
|
||||
* Keep track of stub and root hints, and read those from config.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <ldns/dname.h>
|
||||
#include <ldns/rr.h>
|
||||
#include "iterator/iter_hints.h"
|
||||
#include "iterator/iter_delegpt.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/data/dname.h"
|
||||
|
||||
struct iter_hints*
|
||||
hints_create()
|
||||
hints_create(void)
|
||||
{
|
||||
struct iter_hints* hints = (struct iter_hints*)calloc(1,
|
||||
sizeof(struct iter_hints));
|
||||
if(!hints)
|
||||
return NULL;
|
||||
hints->region = regional_create();
|
||||
if(!hints->region) {
|
||||
hints_delete(hints);
|
||||
return NULL;
|
||||
}
|
||||
return hints;
|
||||
}
|
||||
|
||||
static void hints_stub_free(struct iter_hints_stub* s)
|
||||
{
|
||||
if(!s) return;
|
||||
delegpt_free_mlc(s->dp);
|
||||
free(s);
|
||||
}
|
||||
|
||||
static void delhintnode(rbnode_t* n, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct iter_hints_stub* node = (struct iter_hints_stub*)n;
|
||||
hints_stub_free(node);
|
||||
}
|
||||
|
||||
static void hints_del_tree(struct iter_hints* hints)
|
||||
{
|
||||
traverse_postorder(&hints->tree, &delhintnode, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
hints_delete(struct iter_hints* hints)
|
||||
{
|
||||
if(!hints)
|
||||
return;
|
||||
regional_destroy(hints->region);
|
||||
hints_del_tree(hints);
|
||||
free(hints);
|
||||
}
|
||||
|
||||
/** add hint to delegation hints */
|
||||
static int
|
||||
ah(struct delegpt* dp, struct regional* r, const char* sv, const char* ip)
|
||||
ah(struct delegpt* dp, const char* sv, const char* ip)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen;
|
||||
@@ -83,10 +97,10 @@ ah(struct delegpt* dp, struct regional* r, const char* sv, const char* ip)
|
||||
log_err("could not parse %s", sv);
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_add_ns(dp, r, ldns_rdf_data(rdf)) ||
|
||||
if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(rdf), 0) ||
|
||||
!extstrtoaddr(ip, &addr, &addrlen) ||
|
||||
!delegpt_add_target(dp, r, ldns_rdf_data(rdf), ldns_rdf_size(rdf),
|
||||
&addr, addrlen, 0, 0, 1)) {
|
||||
!delegpt_add_target_mlc(dp, ldns_rdf_data(rdf), ldns_rdf_size(rdf),
|
||||
&addr, addrlen, 0, 0)) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
return 0;
|
||||
}
|
||||
@@ -96,7 +110,7 @@ ah(struct delegpt* dp, struct regional* r, const char* sv, const char* ip)
|
||||
|
||||
/** obtain compiletime provided root hints */
|
||||
static struct delegpt*
|
||||
compile_time_root_prime(struct regional* r, int do_ip4, int do_ip6)
|
||||
compile_time_root_prime(int do_ip4, int do_ip6)
|
||||
{
|
||||
/* from:
|
||||
; This file is made available by InterNIC
|
||||
@@ -105,38 +119,42 @@ compile_time_root_prime(struct regional* r, int do_ip4, int do_ip6)
|
||||
; on server FTP.INTERNIC.NET
|
||||
; -OR- RS.INTERNIC.NET
|
||||
;
|
||||
; related version of root zone: 2008051300
|
||||
; related version of root zone: 2010061700
|
||||
*/
|
||||
struct delegpt* dp = delegpt_create(r);
|
||||
struct delegpt* dp = delegpt_create_mlc((uint8_t*)"\000");
|
||||
if(!dp)
|
||||
return NULL;
|
||||
if(!delegpt_set_name(dp, r, (uint8_t*)"\000"))
|
||||
return NULL;
|
||||
dp->has_parent_side_NS = 1;
|
||||
if(do_ip4) {
|
||||
if(!ah(dp, r, "A.ROOT-SERVERS.NET.", "198.41.0.4")) return 0;
|
||||
if(!ah(dp, r, "B.ROOT-SERVERS.NET.", "192.228.79.201")) return 0;
|
||||
if(!ah(dp, r, "C.ROOT-SERVERS.NET.", "192.33.4.12")) return 0;
|
||||
if(!ah(dp, r, "D.ROOT-SERVERS.NET.", "128.8.10.90")) return 0;
|
||||
if(!ah(dp, r, "E.ROOT-SERVERS.NET.", "192.203.230.10")) return 0;
|
||||
if(!ah(dp, r, "F.ROOT-SERVERS.NET.", "192.5.5.241")) return 0;
|
||||
if(!ah(dp, r, "G.ROOT-SERVERS.NET.", "192.112.36.4")) return 0;
|
||||
if(!ah(dp, r, "H.ROOT-SERVERS.NET.", "128.63.2.53")) return 0;
|
||||
if(!ah(dp, r, "I.ROOT-SERVERS.NET.", "192.36.148.17")) return 0;
|
||||
if(!ah(dp, r, "J.ROOT-SERVERS.NET.", "192.58.128.30")) return 0;
|
||||
if(!ah(dp, r, "K.ROOT-SERVERS.NET.", "193.0.14.129")) return 0;
|
||||
if(!ah(dp, r, "L.ROOT-SERVERS.NET.", "199.7.83.42")) return 0;
|
||||
if(!ah(dp, r, "M.ROOT-SERVERS.NET.", "202.12.27.33")) return 0;
|
||||
if(!ah(dp, "A.ROOT-SERVERS.NET.", "198.41.0.4")) goto failed;
|
||||
if(!ah(dp, "B.ROOT-SERVERS.NET.", "192.228.79.201")) goto failed;
|
||||
if(!ah(dp, "C.ROOT-SERVERS.NET.", "192.33.4.12")) goto failed;
|
||||
if(!ah(dp, "D.ROOT-SERVERS.NET.", "128.8.10.90")) goto failed;
|
||||
if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) goto failed;
|
||||
if(!ah(dp, "F.ROOT-SERVERS.NET.", "192.5.5.241")) goto failed;
|
||||
if(!ah(dp, "G.ROOT-SERVERS.NET.", "192.112.36.4")) goto failed;
|
||||
if(!ah(dp, "H.ROOT-SERVERS.NET.", "128.63.2.53")) goto failed;
|
||||
if(!ah(dp, "I.ROOT-SERVERS.NET.", "192.36.148.17")) goto failed;
|
||||
if(!ah(dp, "J.ROOT-SERVERS.NET.", "192.58.128.30")) goto failed;
|
||||
if(!ah(dp, "K.ROOT-SERVERS.NET.", "193.0.14.129")) goto failed;
|
||||
if(!ah(dp, "L.ROOT-SERVERS.NET.", "199.7.83.42")) goto failed;
|
||||
if(!ah(dp, "M.ROOT-SERVERS.NET.", "202.12.27.33")) goto failed;
|
||||
}
|
||||
if(do_ip6) {
|
||||
if(!ah(dp, r, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) return 0;
|
||||
if(!ah(dp, r, "F.ROOT-SERVERS.NET.", "2001:500:2f::f")) return 0;
|
||||
if(!ah(dp, r, "H.ROOT-SERVERS.NET.", "2001:500:1::803f:235")) return 0;
|
||||
if(!ah(dp, r, "J.ROOT-SERVERS.NET.", "2001:503:c27::2:30")) return 0;
|
||||
if(!ah(dp, r, "K.ROOT-SERVERS.NET.", "2001:7fd::1")) return 0;
|
||||
if(!ah(dp, r, "L.ROOT-SERVERS.NET.", "2001:500:3::42")) return 0;
|
||||
if(!ah(dp, r, "M.ROOT-SERVERS.NET.", "2001:dc3::35")) return 0;
|
||||
if(!ah(dp, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) goto failed;
|
||||
if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) goto failed;
|
||||
if(!ah(dp, "F.ROOT-SERVERS.NET.", "2001:500:2f::f")) goto failed;
|
||||
if(!ah(dp, "H.ROOT-SERVERS.NET.", "2001:500:1::803f:235")) goto failed;
|
||||
if(!ah(dp, "I.ROOT-SERVERS.NET.", "2001:7fe::53")) goto failed;
|
||||
if(!ah(dp, "J.ROOT-SERVERS.NET.", "2001:503:c27::2:30")) goto failed;
|
||||
if(!ah(dp, "K.ROOT-SERVERS.NET.", "2001:7fd::1")) goto failed;
|
||||
if(!ah(dp, "L.ROOT-SERVERS.NET.", "2001:500:3::42")) goto failed;
|
||||
if(!ah(dp, "M.ROOT-SERVERS.NET.", "2001:dc3::35")) goto failed;
|
||||
}
|
||||
return dp;
|
||||
failed:
|
||||
delegpt_free_mlc(dp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** insert new hint info into hint structure */
|
||||
@@ -144,51 +162,50 @@ static int
|
||||
hints_insert(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
||||
int noprime)
|
||||
{
|
||||
struct iter_hints_stub* node = regional_alloc(hints->region,
|
||||
struct iter_hints_stub* node = (struct iter_hints_stub*)malloc(
|
||||
sizeof(struct iter_hints_stub));
|
||||
uint8_t* nm;
|
||||
if(!node)
|
||||
return 0;
|
||||
nm = regional_alloc_init(hints->region, dp->name, dp->namelen);
|
||||
if(!nm)
|
||||
if(!node) {
|
||||
delegpt_free_mlc(dp);
|
||||
return 0;
|
||||
}
|
||||
node->dp = dp;
|
||||
node->noprime = (uint8_t)noprime;
|
||||
if(!name_tree_insert(&hints->tree, &node->node, nm, dp->namelen,
|
||||
if(!name_tree_insert(&hints->tree, &node->node, dp->name, dp->namelen,
|
||||
dp->namelabs, c)) {
|
||||
log_err("second hints ignored.");
|
||||
delegpt_free_mlc(dp);
|
||||
free(node);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** set stub name */
|
||||
static int
|
||||
read_stubs_name(struct iter_hints* hints, struct config_stub* s,
|
||||
struct delegpt* dp)
|
||||
static struct delegpt*
|
||||
read_stubs_name(struct config_stub* s)
|
||||
{
|
||||
struct delegpt* dp;
|
||||
ldns_rdf* rdf;
|
||||
if(!s->name) {
|
||||
log_err("stub zone without a name");
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
rdf = ldns_dname_new_frm_str(s->name);
|
||||
if(!rdf) {
|
||||
log_err("cannot parse stub zone name %s", s->name);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
if(!delegpt_set_name(dp, hints->region, ldns_rdf_data(rdf))) {
|
||||
if(!(dp=delegpt_create_mlc(ldns_rdf_data(rdf)))) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
ldns_rdf_deep_free(rdf);
|
||||
return 1;
|
||||
return dp;
|
||||
}
|
||||
|
||||
/** set stub host names */
|
||||
static int
|
||||
read_stubs_host(struct iter_hints* hints, struct config_stub* s,
|
||||
struct delegpt* dp)
|
||||
read_stubs_host(struct config_stub* s, struct delegpt* dp)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
ldns_rdf* rdf;
|
||||
@@ -200,7 +217,7 @@ read_stubs_host(struct iter_hints* hints, struct config_stub* s,
|
||||
s->name, p->str);
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_add_ns(dp, hints->region, ldns_rdf_data(rdf))) {
|
||||
if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(rdf), 0)) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
@@ -212,8 +229,7 @@ read_stubs_host(struct iter_hints* hints, struct config_stub* s,
|
||||
|
||||
/** set stub server addresses */
|
||||
static int
|
||||
read_stubs_addr(struct iter_hints* hints, struct config_stub* s,
|
||||
struct delegpt* dp)
|
||||
read_stubs_addr(struct config_stub* s, struct delegpt* dp)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
struct sockaddr_storage addr;
|
||||
@@ -225,8 +241,7 @@ read_stubs_addr(struct iter_hints* hints, struct config_stub* s,
|
||||
s->name, p->str);
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_add_addr(dp, hints->region, &addr, addrlen,
|
||||
0, 0, 1)) {
|
||||
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
@@ -239,19 +254,21 @@ static int
|
||||
read_stubs(struct iter_hints* hints, struct config_file* cfg)
|
||||
{
|
||||
struct config_stub* s;
|
||||
struct delegpt* dp;
|
||||
for(s = cfg->stubs; s; s = s->next) {
|
||||
struct delegpt* dp = delegpt_create(hints->region);
|
||||
if(!dp) {
|
||||
log_err("out of memory");
|
||||
if(!(dp=read_stubs_name(s)))
|
||||
return 0;
|
||||
if(!read_stubs_host(s, dp) || !read_stubs_addr(s, dp)) {
|
||||
delegpt_free_mlc(dp);
|
||||
return 0;
|
||||
}
|
||||
if(!read_stubs_name(hints, s, dp) ||
|
||||
!read_stubs_host(hints, s, dp) ||
|
||||
!read_stubs_addr(hints, s, dp))
|
||||
return 0;
|
||||
/* the flag is turned off for 'stub-first' so that the
|
||||
* last resort will ask for parent-side NS record and thus
|
||||
* fallback to the internet name servers on a failure */
|
||||
dp->has_parent_side_NS = (uint8_t)!s->isfirst;
|
||||
delegpt_log(VERB_QUERY, dp);
|
||||
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, !s->isprime))
|
||||
return 0;
|
||||
delegpt_log(VERB_QUERY, dp);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -274,13 +291,14 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
fname, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
dp = delegpt_create(hints->region);
|
||||
dp = delegpt_create_mlc(NULL);
|
||||
if(!dp) {
|
||||
log_err("out of memory reading root hints");
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
verbose(VERB_QUERY, "Reading root hints from %s", fname);
|
||||
dp->has_parent_side_NS = 1;
|
||||
while(!feof(f)) {
|
||||
status = ldns_rr_new_frm_fp_l(&rr, f,
|
||||
&default_ttl, &origin, &prev_rr, &lineno);
|
||||
@@ -294,14 +312,14 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
goto stop_read;
|
||||
}
|
||||
if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_NS) {
|
||||
if(!delegpt_add_ns(dp, hints->region,
|
||||
ldns_rdf_data(ldns_rr_rdf(rr, 0)))) {
|
||||
if(!delegpt_add_ns_mlc(dp,
|
||||
ldns_rdf_data(ldns_rr_rdf(rr, 0)), 0)) {
|
||||
log_err("out of memory reading root hints");
|
||||
goto stop_read;
|
||||
}
|
||||
c = ldns_rr_get_class(rr);
|
||||
if(!dp->name) {
|
||||
if(!delegpt_set_name(dp, hints->region,
|
||||
if(!delegpt_set_name_mlc(dp,
|
||||
ldns_rdf_data(ldns_rr_owner(rr)))){
|
||||
log_err("out of memory.");
|
||||
goto stop_read;
|
||||
@@ -315,11 +333,11 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
|
||||
memmove(&sa.sin_addr,
|
||||
ldns_rdf_data(ldns_rr_rdf(rr, 0)), INET_SIZE);
|
||||
if(!delegpt_add_target(dp, hints->region,
|
||||
if(!delegpt_add_target_mlc(dp,
|
||||
ldns_rdf_data(ldns_rr_owner(rr)),
|
||||
ldns_rdf_size(ldns_rr_owner(rr)),
|
||||
(struct sockaddr_storage*)&sa, len,
|
||||
0, 0, 1)) {
|
||||
0, 0)) {
|
||||
log_err("out of memory reading root hints");
|
||||
goto stop_read;
|
||||
}
|
||||
@@ -331,11 +349,11 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
|
||||
memmove(&sa.sin6_addr,
|
||||
ldns_rdf_data(ldns_rr_rdf(rr, 0)), INET6_SIZE);
|
||||
if(!delegpt_add_target(dp, hints->region,
|
||||
if(!delegpt_add_target_mlc(dp,
|
||||
ldns_rdf_data(ldns_rr_owner(rr)),
|
||||
ldns_rdf_size(ldns_rr_owner(rr)),
|
||||
(struct sockaddr_storage*)&sa, len,
|
||||
0, 0, 1)) {
|
||||
0, 0)) {
|
||||
log_err("out of memory reading root hints");
|
||||
goto stop_read;
|
||||
}
|
||||
@@ -354,6 +372,7 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
fclose(f);
|
||||
if(!dp->name) {
|
||||
log_warn("root hints %s: no NS content", fname);
|
||||
delegpt_free_mlc(dp);
|
||||
return 1;
|
||||
}
|
||||
if(!hints_insert(hints, c, dp, 0)) {
|
||||
@@ -367,6 +386,7 @@ stop_read:
|
||||
ldns_rdf_deep_free(origin);
|
||||
if (prev_rr)
|
||||
ldns_rdf_deep_free(prev_rr);
|
||||
delegpt_free_mlc(dp);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
@@ -394,7 +414,7 @@ read_root_hints_list(struct iter_hints* hints, struct config_file* cfg)
|
||||
int
|
||||
hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
|
||||
{
|
||||
regional_free_all(hints->region);
|
||||
hints_del_tree(hints);
|
||||
name_tree_init(&hints->tree);
|
||||
|
||||
/* read root hints */
|
||||
@@ -407,8 +427,8 @@ hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
|
||||
|
||||
/* use fallback compiletime root hints */
|
||||
if(!hints_lookup_root(hints, LDNS_RR_CLASS_IN)) {
|
||||
struct delegpt* dp = compile_time_root_prime(hints->region,
|
||||
cfg->do_ip4, cfg->do_ip6);
|
||||
struct delegpt* dp = compile_time_root_prime(cfg->do_ip4,
|
||||
cfg->do_ip6);
|
||||
verbose(VERB_ALGO, "no config, using builtin root hints.");
|
||||
if(!dp)
|
||||
return 0;
|
||||
@@ -446,6 +466,13 @@ hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
|
||||
len, labs, qclass);
|
||||
if(!r) return NULL;
|
||||
|
||||
/* If there is no cache (root prime situation) */
|
||||
if(cache_dp == NULL) {
|
||||
if(r->dp->namelabs != 1)
|
||||
return r; /* no cache dp, use any non-root stub */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the stub is same as the delegation we got
|
||||
* And has noprime set, we need to 'prime' to use this stub instead.
|
||||
@@ -470,6 +497,43 @@ int hints_next_root(struct iter_hints* hints, uint16_t* qclass)
|
||||
size_t
|
||||
hints_get_mem(struct iter_hints* hints)
|
||||
{
|
||||
size_t s;
|
||||
struct iter_hints_stub* p;
|
||||
if(!hints) return 0;
|
||||
return sizeof(*hints) + regional_get_mem(hints->region);
|
||||
s = sizeof(*hints);
|
||||
RBTREE_FOR(p, struct iter_hints_stub*, &hints->tree) {
|
||||
s += sizeof(*p) + delegpt_get_mem(p->dp);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
||||
int noprime)
|
||||
{
|
||||
struct iter_hints_stub *z;
|
||||
if((z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
|
||||
dp->name, dp->namelen, dp->namelabs, c)) != NULL) {
|
||||
(void)rbtree_delete(&hints->tree, &z->node);
|
||||
hints_stub_free(z);
|
||||
}
|
||||
if(!hints_insert(hints, c, dp, noprime))
|
||||
return 0;
|
||||
name_tree_init_parents(&hints->tree);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm)
|
||||
{
|
||||
struct iter_hints_stub *z;
|
||||
size_t len;
|
||||
int labs = dname_count_size_labels(nm, &len);
|
||||
if(!(z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
|
||||
nm, len, labs, c)))
|
||||
return; /* nothing to do */
|
||||
(void)rbtree_delete(&hints->tree, &z->node);
|
||||
hints_stub_free(z);
|
||||
name_tree_init_parents(&hints->tree);
|
||||
}
|
||||
|
||||
|
||||
+24
-5
@@ -46,14 +46,11 @@
|
||||
struct iter_env;
|
||||
struct config_file;
|
||||
struct delegpt;
|
||||
struct regional;
|
||||
|
||||
/**
|
||||
* Iterator hints structure
|
||||
*/
|
||||
struct iter_hints {
|
||||
/** regional where hints are allocated */
|
||||
struct regional* region;
|
||||
/**
|
||||
* Hints are stored in this tree. Sort order is specially chosen.
|
||||
* first sorted on qclass. Then on dname in nsec-like order, so that
|
||||
@@ -71,7 +68,7 @@ struct iter_hints {
|
||||
struct iter_hints_stub {
|
||||
/** tree sorted by name, class */
|
||||
struct name_tree_node node;
|
||||
/** delegation point with hint information for this stub. */
|
||||
/** delegation point with hint information for this stub. malloced. */
|
||||
struct delegpt* dp;
|
||||
/** does the stub need to forego priming (like on other ports) */
|
||||
uint8_t noprime;
|
||||
@@ -81,7 +78,7 @@ struct iter_hints_stub {
|
||||
* Create hints
|
||||
* @return new hints or NULL on error.
|
||||
*/
|
||||
struct iter_hints* hints_create();
|
||||
struct iter_hints* hints_create(void);
|
||||
|
||||
/**
|
||||
* Delete hints.
|
||||
@@ -139,4 +136,26 @@ struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
|
||||
*/
|
||||
size_t hints_get_mem(struct iter_hints* hints);
|
||||
|
||||
/**
|
||||
* Add stub to hints structure. For external use since it recalcs
|
||||
* the tree parents.
|
||||
* @param hints: the hints data structure
|
||||
* @param c: class of zone
|
||||
* @param dp: delegation point with name and target nameservers for new
|
||||
* hints stub. malloced.
|
||||
* @param noprime: set noprime option to true or false on new hint stub.
|
||||
* @return false on failure (out of memory);
|
||||
*/
|
||||
int hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
||||
int noprime);
|
||||
|
||||
/**
|
||||
* Remove stub from hints structure. For external use since it
|
||||
* recalcs the tree parents.
|
||||
* @param hints: the hints data structure
|
||||
* @param c: class of stub zone
|
||||
* @param nm: name of stub zone (in uncompressed wireformat).
|
||||
*/
|
||||
void hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm);
|
||||
|
||||
#endif /* ITERATOR_ITER_HINTS_H */
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <ldns/dname.h>
|
||||
#include "iterator/iter_priv.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/log.h"
|
||||
@@ -50,7 +51,7 @@
|
||||
#include "util/net_help.h"
|
||||
#include "util/storage/dnstree.h"
|
||||
|
||||
struct iter_priv* priv_create()
|
||||
struct iter_priv* priv_create(void)
|
||||
{
|
||||
struct iter_priv* priv = (struct iter_priv*)calloc(1, sizeof(*priv));
|
||||
if(!priv)
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#ifndef ITERATOR_ITER_PRIV_H
|
||||
#define ITERATOR_ITER_PRIV_H
|
||||
#include "util/rbtree.h"
|
||||
#include <ldns/buffer.h>
|
||||
struct iter_env;
|
||||
struct config_file;
|
||||
struct regional;
|
||||
@@ -73,7 +74,7 @@ struct iter_priv {
|
||||
* Create priv structure
|
||||
* @return new structure or NULL on error.
|
||||
*/
|
||||
struct iter_priv* priv_create();
|
||||
struct iter_priv* priv_create(void);
|
||||
|
||||
/**
|
||||
* Delete priv structure.
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
* one of the response types.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <ldns/packet.h>
|
||||
#include "iterator/iter_resptype.h"
|
||||
#include "iterator/iter_delegpt.h"
|
||||
#include "services/cache/dns.h"
|
||||
@@ -53,6 +54,8 @@ response_type_from_cache(struct dns_msg* msg,
|
||||
/* If the message is NXDOMAIN, then it is an ANSWER. */
|
||||
if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NXDOMAIN)
|
||||
return RESPONSE_TYPE_ANSWER;
|
||||
if(request->qtype == LDNS_RR_TYPE_ANY)
|
||||
return RESPONSE_TYPE_ANSWER;
|
||||
|
||||
/* First we look at the answer section. This can tell us if this is
|
||||
* CNAME or positive ANSWER. */
|
||||
@@ -105,7 +108,6 @@ response_type_from_server(int rdset,
|
||||
{
|
||||
uint8_t* origzone = (uint8_t*)"\000"; /* the default */
|
||||
struct ub_packed_rrset_key* s;
|
||||
size_t origzonelen = 1;
|
||||
size_t i;
|
||||
|
||||
if(!msg || !request)
|
||||
@@ -117,6 +119,15 @@ response_type_from_server(int rdset,
|
||||
if( (msg->rep->flags&BIT_RA) &&
|
||||
!(msg->rep->flags&BIT_AA) && !rdset)
|
||||
return RESPONSE_TYPE_REC_LAME;
|
||||
/* it could be a CNAME with NXDOMAIN rcode */
|
||||
for(i=0; i<msg->rep->an_numrrsets; i++) {
|
||||
s = msg->rep->rrsets[i];
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME &&
|
||||
query_dname_compare(request->qname,
|
||||
s->rk.dname) == 0) {
|
||||
return RESPONSE_TYPE_CNAME;
|
||||
}
|
||||
}
|
||||
return RESPONSE_TYPE_ANSWER;
|
||||
}
|
||||
|
||||
@@ -129,7 +140,6 @@ response_type_from_server(int rdset,
|
||||
|
||||
if(dp) {
|
||||
origzone = dp->name;
|
||||
origzonelen = dp->namelen;
|
||||
}
|
||||
|
||||
/* First we look at the answer section. This can tell us if this is a
|
||||
@@ -142,7 +152,7 @@ response_type_from_server(int rdset,
|
||||
* answer is there directly, our answer is there after
|
||||
* a cname, or there is just a cname. */
|
||||
for(i=0; i<msg->rep->an_numrrsets; i++) {
|
||||
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
|
||||
s = msg->rep->rrsets[i];
|
||||
|
||||
/* if the answer section has NS rrset, and qtype ANY
|
||||
* and the delegation is lower, and no CNAMEs followed,
|
||||
@@ -153,6 +163,8 @@ response_type_from_server(int rdset,
|
||||
ntohs(s->rk.rrset_class) == request->qclass &&
|
||||
dname_strict_subdomain_c(s->rk.dname,
|
||||
origzone)) {
|
||||
if((msg->rep->flags&BIT_AA))
|
||||
return RESPONSE_TYPE_ANSWER;
|
||||
return RESPONSE_TYPE_REFERRAL;
|
||||
}
|
||||
|
||||
@@ -180,6 +192,9 @@ response_type_from_server(int rdset,
|
||||
get_cname_target(s, &mname, &mname_len);
|
||||
}
|
||||
}
|
||||
/* not a referral, and qtype any, thus an answer */
|
||||
if(request->qtype == LDNS_RR_TYPE_ANY)
|
||||
return RESPONSE_TYPE_ANSWER;
|
||||
/* if we encountered a CNAME (or a bunch of CNAMEs), and
|
||||
* still got to here, then it is a CNAME response.
|
||||
* (This is regardless of the AA bit at this point) */
|
||||
@@ -226,9 +241,14 @@ response_type_from_server(int rdset,
|
||||
/* Or if a lame server is deployed,
|
||||
* which gives ns==zone delegation from cache
|
||||
* without AA bit as well, with nodata nosoa*/
|
||||
/* real answer must be +AA and SOA RFC(2308),
|
||||
* so this is wrong, and we SERVFAIL it if
|
||||
* this is the only possible reply, if it
|
||||
* is misdeployed the THROWAWAY makes us pick
|
||||
* the next server from the selection */
|
||||
if(msg->rep->an_numrrsets==0 &&
|
||||
!(msg->rep->flags&BIT_AA) && !rdset)
|
||||
return RESPONSE_TYPE_REC_LAME;
|
||||
return RESPONSE_TYPE_THROWAWAY;
|
||||
return RESPONSE_TYPE_ANSWER;
|
||||
}
|
||||
/* If we are getting a referral upwards (or to
|
||||
|
||||
+26
-14
@@ -187,11 +187,14 @@ parse_get_cname_target(struct rrset_parse* rrset, uint8_t** sname,
|
||||
size_t* snamelen)
|
||||
{
|
||||
if(rrset->rr_count != 1) {
|
||||
struct rr_parse* sig;
|
||||
verbose(VERB_ALGO, "Found CNAME rrset with "
|
||||
"size > 1: %u", (unsigned)rrset->rr_count);
|
||||
/* use the first CNAME! */
|
||||
rrset->rr_count = 1;
|
||||
rrset->size = rrset->rr_first->size;
|
||||
for(sig=rrset->rrsig_first; sig; sig=sig->next)
|
||||
rrset->size += sig->size;
|
||||
rrset->rr_last = rrset->rr_first;
|
||||
rrset->rr_first->next = NULL;
|
||||
}
|
||||
@@ -363,10 +366,6 @@ scrub_normalize(ldns_buffer* pkt, struct msg_parse* msg,
|
||||
"too long");
|
||||
return 0;
|
||||
}
|
||||
/* internally we have CNAME'd/DNAME'd chains ending
|
||||
* in nxdomain with NOERROR rcode, change rcode
|
||||
* to reflect this (if needed) */
|
||||
FLAGS_SET_RCODE(msg->flags, LDNS_RCODE_NOERROR);
|
||||
if(nx && nx->type == LDNS_RR_TYPE_CNAME &&
|
||||
dname_pkt_compare(pkt, sname, nx->dname) == 0) {
|
||||
/* check next cname */
|
||||
@@ -405,14 +404,21 @@ scrub_normalize(ldns_buffer* pkt, struct msg_parse* msg,
|
||||
|
||||
/* Follow the CNAME chain. */
|
||||
if(rrset->type == LDNS_RR_TYPE_CNAME) {
|
||||
uint8_t* oldsname = sname;
|
||||
if(!parse_get_cname_target(rrset, &sname, &snamelen))
|
||||
return 0;
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
/* internally we have CNAME'd/DNAME'd chains ending
|
||||
* in nxdomain with NOERROR rcode, change rcode
|
||||
* to reflect this (if needed) */
|
||||
FLAGS_SET_RCODE(msg->flags, LDNS_RCODE_NOERROR);
|
||||
/* in CNAME ANY response, can have data after CNAME */
|
||||
if(qinfo->qtype == LDNS_RR_TYPE_ANY) {
|
||||
while(rrset && rrset->section ==
|
||||
LDNS_SECTION_ANSWER &&
|
||||
dname_pkt_compare(pkt, oldsname,
|
||||
rrset->dname) == 0) {
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -446,6 +452,12 @@ scrub_normalize(ldns_buffer* pkt, struct msg_parse* msg,
|
||||
}
|
||||
/* only one NS set allowed in authority section */
|
||||
if(rrset->type==LDNS_RR_TYPE_NS) {
|
||||
/* NS set must be pertinent to the query */
|
||||
if(!sub_of_pkt(pkt, qinfo->qname, rrset->dname)) {
|
||||
remove_rrset("normalize: removing irrelevant "
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
if(nsset == NULL) {
|
||||
nsset = rrset;
|
||||
} else {
|
||||
@@ -523,8 +535,7 @@ store_rrset(ldns_buffer* pkt, struct msg_parse* msg, struct module_env* env,
|
||||
ref.key = k;
|
||||
ref.id = k->id;
|
||||
/*ignore ret: it was in the cache, ref updated */
|
||||
(void)rrset_cache_update(env->rrset_cache, &ref,
|
||||
env->alloc, now);
|
||||
(void)rrset_cache_update(env->rrset_cache, &ref, env->alloc, now);
|
||||
}
|
||||
|
||||
/** Check if there are SOA records in the authority section (negative) */
|
||||
@@ -555,7 +566,7 @@ static int sanitize_nsec_is_overreach(struct rrset_parse* rrset,
|
||||
for(rr = rrset->rr_first; rr; rr = rr->next) {
|
||||
rhs = rr->ttl_data+4+2;
|
||||
len = ldns_read_uint16(rr->ttl_data+4);
|
||||
if(!(len=dname_valid(rhs, len))) {
|
||||
if(!dname_valid(rhs, len)) {
|
||||
/* malformed domain name in rdata */
|
||||
return 1;
|
||||
}
|
||||
@@ -637,9 +648,9 @@ scrub_sanitize(ldns_buffer* pkt, struct msg_parse* msg,
|
||||
if( (rrset->type == LDNS_RR_TYPE_A ||
|
||||
rrset->type == LDNS_RR_TYPE_AAAA) &&
|
||||
priv_rrset_bad(ie->priv, pkt, rrset)) {
|
||||
/* set servfail, so the classification becomes
|
||||
* THROWAWAY, instead of LAME or other unwanted */
|
||||
FLAGS_SET_RCODE(msg->flags, LDNS_RCODE_SERVFAIL);
|
||||
|
||||
/* do not set servfail since this leads to too
|
||||
* many drops of other people using rfc1918 space */
|
||||
remove_rrset("sanitize: removing public name with "
|
||||
"private address", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
@@ -711,6 +722,7 @@ scrub_message(ldns_buffer* pkt, struct msg_parse* msg,
|
||||
return 0;
|
||||
if( !(msg->flags&BIT_QR) )
|
||||
return 0;
|
||||
msg->flags &= ~(BIT_AD|BIT_Z); /* force off bit AD and Z */
|
||||
|
||||
/* make sure that a query is echoed back when NOERROR or NXDOMAIN */
|
||||
/* this is not required for basic operation but is a forgery
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
#ifndef ITERATOR_ITER_SCRUB_H
|
||||
#define ITERATOR_ITER_SCRUB_H
|
||||
#include <ldns/buffer.h>
|
||||
struct msg_parse;
|
||||
struct query_info;
|
||||
struct regional;
|
||||
|
||||
+363
-116
@@ -60,11 +60,14 @@
|
||||
#include "util/random.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "validator/val_anchor.h"
|
||||
#include "validator/val_kcache.h"
|
||||
#include "validator/val_kentry.h"
|
||||
#include "validator/val_utils.h"
|
||||
|
||||
/** time when nameserver glue is said to be 'recent' */
|
||||
#define SUSPICION_RECENT_EXPIRY 86400
|
||||
/** penalty to validation failed blacklisted IPs */
|
||||
#define BLACKLIST_PENALTY (USEFUL_SERVER_TOP_TIMEOUT*3)
|
||||
#define BLACKLIST_PENALTY (USEFUL_SERVER_TOP_TIMEOUT*4)
|
||||
|
||||
/** fillup fetch policy array */
|
||||
static void
|
||||
@@ -111,12 +114,6 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
verbose(VERB_QUERY, "target fetch policy for level %d is %d",
|
||||
i, iter_env->target_fetch_policy[i]);
|
||||
|
||||
if(!iter_env->hints)
|
||||
iter_env->hints = hints_create();
|
||||
if(!iter_env->hints || !hints_apply_cfg(iter_env->hints, cfg)) {
|
||||
log_err("Could not set root or stub hints");
|
||||
return 0;
|
||||
}
|
||||
if(!iter_env->donotq)
|
||||
iter_env->donotq = donotq_create();
|
||||
if(!iter_env->donotq || !donotq_apply_cfg(iter_env->donotq, cfg)) {
|
||||
@@ -130,6 +127,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
return 0;
|
||||
}
|
||||
iter_env->supports_ipv6 = cfg->do_ip6;
|
||||
iter_env->supports_ipv4 = cfg->do_ip4;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -148,6 +146,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
* o The address is bogus (DNSSEC validation failure).
|
||||
* o Listed as donotquery
|
||||
* o is ipv6 but no ipv6 support (in operating system).
|
||||
* o is ipv4 but no ipv4 support (in operating system).
|
||||
* o is lame
|
||||
* Otherwise, an rtt in milliseconds.
|
||||
* 0 .. USEFUL_SERVER_TOP_TIMEOUT-1
|
||||
@@ -158,15 +157,17 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
* This value exactly is given for unresponsive blacklisted.
|
||||
* USEFUL_SERVER_TOP_TIMEOUT+1
|
||||
* For non-blacklisted servers: huge timeout, but has traffic.
|
||||
* USEFUL_SERVER_TOP_TIMEOUT ..
|
||||
* dnsseclame servers get penalty
|
||||
* also for parent-side lame servers (lame in delegpt).
|
||||
* USEFUL_SERVER_TOP_TIMEOUT*1 ..
|
||||
* parent-side lame servers get this penalty. A dispreferential
|
||||
* server. (lame in delegpt).
|
||||
* USEFUL_SERVER_TOP_TIMEOUT*2 ..
|
||||
* dnsseclame servers get penalty
|
||||
* USEFUL_SERVER_TOP_TIMEOUT*3 ..
|
||||
* recursion lame servers get penalty
|
||||
* UNKNOWN_SERVER_NICENESS
|
||||
* If no information is known about the server, this is
|
||||
* returned. 376 msec or so.
|
||||
* +BLACKLIST_PENALTY (of USEFUL_TOP_TIMEOUT*3) for dnssec failed IPs.
|
||||
* +BLACKLIST_PENALTY (of USEFUL_TOP_TIMEOUT*4) for dnssec failed IPs.
|
||||
*
|
||||
* When a final value is chosen that is dnsseclame ; dnsseclameness checking
|
||||
* is turned off (so we do not discard the reply).
|
||||
@@ -179,44 +180,52 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
|
||||
uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now,
|
||||
struct delegpt_addr* a)
|
||||
{
|
||||
int rtt, lame, reclame, dnsseclame, lost;
|
||||
int rtt, lame, reclame, dnsseclame;
|
||||
if(a->bogus)
|
||||
return -1; /* address of server is bogus */
|
||||
if(donotq_lookup(iter_env->donotq, &a->addr, a->addrlen)) {
|
||||
log_addr(VERB_ALGO, "skip addr on the donotquery list",
|
||||
&a->addr, a->addrlen);
|
||||
return -1; /* server is on the donotquery list */
|
||||
}
|
||||
if(!iter_env->supports_ipv6 && addr_is_ip6(&a->addr, a->addrlen)) {
|
||||
return -1; /* there is no ip6 available */
|
||||
}
|
||||
if(!iter_env->supports_ipv4 && !addr_is_ip6(&a->addr, a->addrlen)) {
|
||||
return -1; /* there is no ip4 available */
|
||||
}
|
||||
/* check lameness - need zone , class info */
|
||||
if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen,
|
||||
name, namelen, qtype, &lame, &dnsseclame, &reclame,
|
||||
&rtt, &lost, now)) {
|
||||
&rtt, now)) {
|
||||
log_addr(VERB_ALGO, "servselect", &a->addr, a->addrlen);
|
||||
verbose(VERB_ALGO, " rtt=%d lost=%d%s%s%s%s", rtt, lost,
|
||||
verbose(VERB_ALGO, " rtt=%d%s%s%s%s", rtt,
|
||||
lame?" LAME":"",
|
||||
dnsseclame?" DNSSEC_LAME":"",
|
||||
reclame?" REC_LAME":"",
|
||||
a->lame?" ADDR_LAME":"");
|
||||
if(lame)
|
||||
return -1; /* server is lame */
|
||||
else if(rtt >= USEFUL_SERVER_TOP_TIMEOUT &&
|
||||
lost >= USEFUL_SERVER_MAX_LOST)
|
||||
/* server is unresponsive, but keep trying slowly */
|
||||
return USEFUL_SERVER_TOP_TIMEOUT+1;
|
||||
else if(rtt >= USEFUL_SERVER_TOP_TIMEOUT)
|
||||
/* server is unresponsive,
|
||||
* we used to return TOP_TIMOUT, but fairly useless,
|
||||
* because if == TOP_TIMEOUT is dropped because
|
||||
* blacklisted later, instead, remove it here, so
|
||||
* other choices (that are not blacklisted) can be
|
||||
* tried */
|
||||
return -1;
|
||||
/* select remainder from worst to best */
|
||||
else if(reclame)
|
||||
return rtt+USEFUL_SERVER_TOP_TIMEOUT*3; /* nonpref */
|
||||
else if(dnsseclame )
|
||||
return rtt+USEFUL_SERVER_TOP_TIMEOUT*2; /* nonpref */
|
||||
else if(a->lame)
|
||||
return rtt+USEFUL_SERVER_TOP_TIMEOUT+1; /* nonpref */
|
||||
else if(rtt >= USEFUL_SERVER_TOP_TIMEOUT) /* not blacklisted*/
|
||||
return USEFUL_SERVER_TOP_TIMEOUT+1;
|
||||
else if(reclame)
|
||||
return rtt+USEFUL_SERVER_TOP_TIMEOUT*2; /* nonpref */
|
||||
else if(dnsseclame )
|
||||
return rtt+USEFUL_SERVER_TOP_TIMEOUT; /* nonpref */
|
||||
else return rtt;
|
||||
}
|
||||
/* no server information present */
|
||||
if(a->lame)
|
||||
return USEFUL_SERVER_TOP_TIMEOUT+1; /* nonpref */
|
||||
return USEFUL_SERVER_TOP_TIMEOUT+1+UNKNOWN_SERVER_NICENESS; /* nonpref */
|
||||
return UNKNOWN_SERVER_NICENESS;
|
||||
}
|
||||
|
||||
@@ -308,7 +317,7 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
|
||||
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_expected,
|
||||
uint8_t* name, size_t namelen, uint16_t qtype, int* dnssec_lame,
|
||||
int* chase_to_rd, int open_target, struct sock_list* blacklist)
|
||||
{
|
||||
int sel;
|
||||
@@ -321,18 +330,24 @@ iter_server_selection(struct iter_env* iter_env,
|
||||
return NULL;
|
||||
verbose(VERB_ALGO, "selrtt %d", selrtt);
|
||||
if(selrtt > BLACKLIST_PENALTY) {
|
||||
if(selrtt-BLACKLIST_PENALTY > USEFUL_SERVER_TOP_TIMEOUT*2) {
|
||||
verbose(VERB_ALGO, "chase to recursion lame server");
|
||||
if(selrtt-BLACKLIST_PENALTY > USEFUL_SERVER_TOP_TIMEOUT*3) {
|
||||
verbose(VERB_ALGO, "chase to "
|
||||
"blacklisted recursion lame server");
|
||||
*chase_to_rd = 1;
|
||||
}
|
||||
if(selrtt-BLACKLIST_PENALTY > USEFUL_SERVER_TOP_TIMEOUT*2) {
|
||||
verbose(VERB_ALGO, "chase to "
|
||||
"blacklisted dnssec lame server");
|
||||
*dnssec_lame = 1;
|
||||
}
|
||||
} else {
|
||||
if(selrtt > USEFUL_SERVER_TOP_TIMEOUT*2) {
|
||||
if(selrtt > USEFUL_SERVER_TOP_TIMEOUT*3) {
|
||||
verbose(VERB_ALGO, "chase to recursion lame server");
|
||||
*chase_to_rd = 1;
|
||||
}
|
||||
if(selrtt > USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
if(selrtt > USEFUL_SERVER_TOP_TIMEOUT*2) {
|
||||
verbose(VERB_ALGO, "chase to dnssec lame server");
|
||||
*dnssec_expected = 0;
|
||||
*dnssec_lame = 1;
|
||||
}
|
||||
if(selrtt == USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
verbose(VERB_ALGO, "chase to blacklisted lame server");
|
||||
@@ -350,9 +365,9 @@ iter_server_selection(struct iter_env* iter_env,
|
||||
|
||||
/* randomly select a target from the list */
|
||||
log_assert(num > 1);
|
||||
/* we do not need secure random numbers here, but
|
||||
* we do need it to be threadsafe, so we use this */
|
||||
sel = ub_random(env->rnd) % num;
|
||||
/* grab secure random number, to pick unexpected server.
|
||||
* also we need it to be threadsafe. */
|
||||
sel = ub_random_max(env->rnd, num);
|
||||
a = dp->result_list;
|
||||
prev = NULL;
|
||||
while(sel > 0 && a) {
|
||||
@@ -403,11 +418,14 @@ dns_copy_msg(struct dns_msg* from, struct regional* region)
|
||||
return m;
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
iter_dns_store(struct module_env* env, struct query_info* msgqinf,
|
||||
struct reply_info* msgrep, int is_referral, uint32_t leeway)
|
||||
struct reply_info* msgrep, int is_referral, uint32_t leeway, int pside,
|
||||
struct regional* region)
|
||||
{
|
||||
return dns_cache_store(env, msgqinf, msgrep, is_referral, leeway);
|
||||
if(!dns_cache_store(env, msgqinf, msgrep, is_referral, leeway,
|
||||
pside, region))
|
||||
log_err("out of memory: cannot store data in cache");
|
||||
}
|
||||
|
||||
int
|
||||
@@ -418,58 +436,10 @@ iter_ns_probability(struct ub_randstate* rnd, int n, int m)
|
||||
return 1;
|
||||
/* we do not need secure random numbers here, but
|
||||
* we do need it to be threadsafe, so we use this */
|
||||
sel = ub_random(rnd) % m;
|
||||
sel = ub_random_max(rnd, m);
|
||||
return (sel < n);
|
||||
}
|
||||
|
||||
int iter_suspect_exists(struct query_info* qinfo, struct delegpt* dp,
|
||||
struct module_env* env)
|
||||
{
|
||||
struct ub_packed_rrset_key* r;
|
||||
if(qinfo->qtype != LDNS_RR_TYPE_A && qinfo->qtype != LDNS_RR_TYPE_AAAA)
|
||||
return 0; /* not glue type */
|
||||
if(!dname_subdomain_c(qinfo->qname, dp->name))
|
||||
return 0; /* not in-zone */
|
||||
if(!delegpt_find_ns(dp, qinfo->qname, qinfo->qname_len))
|
||||
return 0; /* not glue */
|
||||
|
||||
/* do we suspect that it exists? lookup with time=0 */
|
||||
r = rrset_cache_lookup(env->rrset_cache, qinfo->qname,
|
||||
qinfo->qname_len, qinfo->qtype, qinfo->qclass, 0, 0, 0);
|
||||
if(r) {
|
||||
struct packed_rrset_data* d = (struct packed_rrset_data*)
|
||||
r->entry.data;
|
||||
/* if it is valid, no need for queries to parent zone */
|
||||
if(*env->now <= d->ttl) {
|
||||
lock_rw_unlock(&r->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
/* was it recently expired? */
|
||||
if( (*env->now - d->ttl) <= SUSPICION_RECENT_EXPIRY) {
|
||||
verbose(VERB_ALGO, "suspect glue at parent: "
|
||||
"rrset recently expired");
|
||||
lock_rw_unlock(&r->entry.lock);
|
||||
return 1;
|
||||
}
|
||||
lock_rw_unlock(&r->entry.lock);
|
||||
}
|
||||
|
||||
/* so, qinfo not there, does the other A/AAAA type exist in cache? */
|
||||
r=rrset_cache_lookup(env->rrset_cache, qinfo->qname, qinfo->qname_len,
|
||||
(qinfo->qtype==LDNS_RR_TYPE_A)?LDNS_RR_TYPE_AAAA:LDNS_RR_TYPE_A,
|
||||
qinfo->qclass, 0, *env->now, 0);
|
||||
if(r) {
|
||||
/* it exists and explains why the glue is there */
|
||||
lock_rw_unlock(&r->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* neither exist, so logically, one should exist for a nameserver */
|
||||
verbose(VERB_ALGO, "suspect glue at parent: "
|
||||
"neither A nor AAAA exist in cache");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** detect dependency cycle for query and target */
|
||||
static int
|
||||
causes_cycle(struct module_qstate* qstate, uint8_t* name, size_t namelen,
|
||||
@@ -508,17 +478,42 @@ iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
iter_mark_pside_cycle_targets(struct module_qstate* qstate, struct delegpt* dp)
|
||||
{
|
||||
struct delegpt_ns* ns;
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
if(ns->done_pside4 && ns->done_pside6)
|
||||
continue;
|
||||
/* see if this ns as target causes dependency cycle */
|
||||
if(causes_cycle(qstate, ns->name, ns->namelen,
|
||||
LDNS_RR_TYPE_A, qstate->qinfo.qclass)) {
|
||||
log_nametypeclass(VERB_QUERY, "skipping target due "
|
||||
"to dependency cycle", ns->name,
|
||||
LDNS_RR_TYPE_A, qstate->qinfo.qclass);
|
||||
ns->done_pside4 = 1;
|
||||
}
|
||||
if(causes_cycle(qstate, ns->name, ns->namelen,
|
||||
LDNS_RR_TYPE_AAAA, qstate->qinfo.qclass)) {
|
||||
log_nametypeclass(VERB_QUERY, "skipping target due "
|
||||
"to dependency cycle", ns->name,
|
||||
LDNS_RR_TYPE_AAAA, qstate->qinfo.qclass);
|
||||
ns->done_pside6 = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
|
||||
struct delegpt* dp)
|
||||
{
|
||||
struct delegpt_ns* ns;
|
||||
/* check:
|
||||
* o RD qflag is off.
|
||||
* o RD qflag is on.
|
||||
* o no addresses are provided.
|
||||
* o all NS items are required glue.
|
||||
* OR
|
||||
* o RD qflag is off.
|
||||
* o RD qflag is on.
|
||||
* o no addresses are provided.
|
||||
* o the query is for one of the nameservers in dp,
|
||||
* and that nameserver is a glue-name for this dp.
|
||||
@@ -564,6 +559,23 @@ iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
|
||||
reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen,
|
||||
LDNS_RR_TYPE_DS, dclass))
|
||||
return 1;
|
||||
/* look in key cache */
|
||||
if(env->key_cache) {
|
||||
struct key_entry_key* kk = key_cache_obtain(env->key_cache,
|
||||
dp->name, dp->namelen, dclass, env->scratch, *env->now);
|
||||
if(kk) {
|
||||
if(query_dname_compare(kk->name, dp->name) == 0) {
|
||||
if(key_entry_isgood(kk) || key_entry_isbad(kk)) {
|
||||
regional_free_all(env->scratch);
|
||||
return 1;
|
||||
} else if(key_entry_isnull(kk)) {
|
||||
regional_free_all(env->scratch);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
regional_free_all(env->scratch);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -668,7 +680,7 @@ rrset_equal(struct ub_packed_rrset_key* k1, struct ub_packed_rrset_key* k2)
|
||||
}
|
||||
|
||||
int
|
||||
reply_equal(struct reply_info* p, struct reply_info* q)
|
||||
reply_equal(struct reply_info* p, struct reply_info* q, ldns_buffer* scratch)
|
||||
{
|
||||
size_t i;
|
||||
if(p->flags != q->flags ||
|
||||
@@ -682,63 +694,190 @@ reply_equal(struct reply_info* p, struct reply_info* q)
|
||||
p->rrset_count != q->rrset_count)
|
||||
return 0;
|
||||
for(i=0; i<p->rrset_count; i++) {
|
||||
if(!rrset_equal(p->rrsets[i], q->rrsets[i]))
|
||||
return 0;
|
||||
if(!rrset_equal(p->rrsets[i], q->rrsets[i])) {
|
||||
/* fallback procedure: try to sort and canonicalize */
|
||||
ldns_rr_list* pl, *ql;
|
||||
pl = packed_rrset_to_rr_list(p->rrsets[i], scratch);
|
||||
ql = packed_rrset_to_rr_list(q->rrsets[i], scratch);
|
||||
if(!pl || !ql) {
|
||||
ldns_rr_list_deep_free(pl);
|
||||
ldns_rr_list_deep_free(ql);
|
||||
return 0;
|
||||
}
|
||||
ldns_rr_list2canonical(pl);
|
||||
ldns_rr_list2canonical(ql);
|
||||
ldns_rr_list_sort(pl);
|
||||
ldns_rr_list_sort(ql);
|
||||
if(ldns_rr_list_compare(pl, ql) != 0) {
|
||||
ldns_rr_list_deep_free(pl);
|
||||
ldns_rr_list_deep_free(ql);
|
||||
return 0;
|
||||
}
|
||||
ldns_rr_list_deep_free(pl);
|
||||
ldns_rr_list_deep_free(ql);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
iter_store_inzone_glue(struct module_env* env, struct query_info* qinfo,
|
||||
struct reply_info* rep)
|
||||
iter_store_parentside_rrset(struct module_env* env,
|
||||
struct ub_packed_rrset_key* rrset)
|
||||
{
|
||||
struct rrset_ref ref;
|
||||
struct ub_packed_rrset_key* rrset;
|
||||
if(qinfo->qtype != LDNS_RR_TYPE_A && qinfo->qtype != LDNS_RR_TYPE_AAAA)
|
||||
return;
|
||||
rrset = reply_find_rrset(rep, qinfo->qname, qinfo->qname_len,
|
||||
qinfo->qtype, qinfo->qclass);
|
||||
if(!rrset)
|
||||
return;
|
||||
/* got A or AAAA glue rrset. store it in case its handy */
|
||||
rrset = packed_rrset_copy_alloc(rrset, env->alloc, *env->now);
|
||||
if(!rrset) {
|
||||
log_err("malloc failure in store_inzone_glue");
|
||||
log_err("malloc failure in store_parentside_rrset");
|
||||
return;
|
||||
}
|
||||
rrset->rk.flags |= PACKED_RRSET_PARENT_SIDE;
|
||||
rrset->entry.hash = rrset_key_hash(&rrset->rk);
|
||||
ref.key = rrset;
|
||||
ref.id = rrset->id;
|
||||
/* ignore ret: it was in the cache, ref updated */
|
||||
/* ignore ret: if it was in the cache, ref updated */
|
||||
(void)rrset_cache_update(env->rrset_cache, &ref, env->alloc, *env->now);
|
||||
}
|
||||
|
||||
/** fetch NS record from reply, if any */
|
||||
static struct ub_packed_rrset_key*
|
||||
reply_get_NS_rrset(struct reply_info* rep)
|
||||
{
|
||||
size_t i;
|
||||
for(i=0; i<rep->rrset_count; i++) {
|
||||
if(rep->rrsets[i]->rk.type == htons(LDNS_RR_TYPE_NS)) {
|
||||
return rep->rrsets[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
iter_store_parentside_NS(struct module_env* env, struct reply_info* rep)
|
||||
{
|
||||
struct ub_packed_rrset_key* rrset = reply_get_NS_rrset(rep);
|
||||
if(rrset) {
|
||||
log_rrset_key(VERB_ALGO, "store parent-side NS", rrset);
|
||||
iter_store_parentside_rrset(env, rrset);
|
||||
}
|
||||
}
|
||||
|
||||
void iter_store_parentside_neg(struct module_env* env,
|
||||
struct query_info* qinfo, struct reply_info* rep)
|
||||
{
|
||||
/* TTL: NS from referral in iq->deleg_msg,
|
||||
* or first RR from iq->response,
|
||||
* or servfail5secs if !iq->response */
|
||||
uint32_t ttl = NORR_TTL;
|
||||
struct ub_packed_rrset_key* neg;
|
||||
struct packed_rrset_data* newd;
|
||||
if(rep) {
|
||||
struct ub_packed_rrset_key* rrset = reply_get_NS_rrset(rep);
|
||||
if(!rrset && rep->rrset_count != 0) rrset = rep->rrsets[0];
|
||||
if(rrset) ttl = ub_packed_rrset_ttl(rrset);
|
||||
}
|
||||
/* create empty rrset to store */
|
||||
neg = (struct ub_packed_rrset_key*)regional_alloc(env->scratch,
|
||||
sizeof(struct ub_packed_rrset_key));
|
||||
if(!neg) {
|
||||
log_err("out of memory in store_parentside_neg");
|
||||
return;
|
||||
}
|
||||
memset(&neg->entry, 0, sizeof(neg->entry));
|
||||
neg->entry.key = neg;
|
||||
neg->rk.type = htons(qinfo->qtype);
|
||||
neg->rk.rrset_class = htons(qinfo->qclass);
|
||||
neg->rk.flags = 0;
|
||||
neg->rk.dname = regional_alloc_init(env->scratch, qinfo->qname,
|
||||
qinfo->qname_len);
|
||||
if(!neg->rk.dname) {
|
||||
log_err("out of memory in store_parentside_neg");
|
||||
return;
|
||||
}
|
||||
neg->rk.dname_len = qinfo->qname_len;
|
||||
neg->entry.hash = rrset_key_hash(&neg->rk);
|
||||
newd = (struct packed_rrset_data*)regional_alloc_zero(env->scratch,
|
||||
sizeof(struct packed_rrset_data) + sizeof(size_t) +
|
||||
sizeof(uint8_t*) + sizeof(uint32_t) + sizeof(uint16_t));
|
||||
if(!newd) {
|
||||
log_err("out of memory in store_parentside_neg");
|
||||
return;
|
||||
}
|
||||
neg->entry.data = newd;
|
||||
newd->ttl = ttl;
|
||||
/* entry must have one RR, otherwise not valid in cache.
|
||||
* put in one RR with empty rdata: those are ignored as nameserver */
|
||||
newd->count = 1;
|
||||
newd->rrsig_count = 0;
|
||||
newd->trust = rrset_trust_ans_noAA;
|
||||
newd->rr_len = (size_t*)((uint8_t*)newd +
|
||||
sizeof(struct packed_rrset_data));
|
||||
newd->rr_len[0] = 0 /* zero len rdata */ + sizeof(uint16_t);
|
||||
packed_rrset_ptr_fixup(newd);
|
||||
newd->rr_ttl[0] = newd->ttl;
|
||||
ldns_write_uint16(newd->rr_data[0], 0 /* zero len rdata */);
|
||||
/* store it */
|
||||
log_rrset_key(VERB_ALGO, "store parent-side negative", neg);
|
||||
iter_store_parentside_rrset(env, neg);
|
||||
}
|
||||
|
||||
int
|
||||
iter_lookup_inzone_glue(struct module_env* env, struct delegpt* dp,
|
||||
iter_lookup_parent_NS_from_cache(struct module_env* env, struct delegpt* dp,
|
||||
struct regional* region, struct query_info* qinfo)
|
||||
{
|
||||
struct ub_packed_rrset_key* akey;
|
||||
akey = rrset_cache_lookup(env->rrset_cache, qinfo->qname,
|
||||
qinfo->qname_len, qinfo->qtype, qinfo->qclass,
|
||||
akey = rrset_cache_lookup(env->rrset_cache, dp->name,
|
||||
dp->namelen, LDNS_RR_TYPE_NS, qinfo->qclass,
|
||||
PACKED_RRSET_PARENT_SIDE, *env->now, 0);
|
||||
if(akey) {
|
||||
if(qinfo->qtype == LDNS_RR_TYPE_A) {
|
||||
if(!delegpt_add_rrset_A(dp, region, akey, 1, 1)) {
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
} else if(qinfo->qtype == LDNS_RR_TYPE_AAAA) {
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, akey, 1, 1)) {
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
log_rrset_key(VERB_ALGO, "found parent-side NS in cache", akey);
|
||||
dp->has_parent_side_NS = 1;
|
||||
/* and mark the new names as lame */
|
||||
if(!delegpt_rrset_add_ns(dp, region, akey, 1)) {
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int iter_lookup_parent_glue_from_cache(struct module_env* env,
|
||||
struct delegpt* dp, struct regional* region, struct query_info* qinfo)
|
||||
{
|
||||
struct ub_packed_rrset_key* akey;
|
||||
struct delegpt_ns* ns;
|
||||
size_t num = delegpt_count_targets(dp);
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
/* get cached parentside A */
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_A, qinfo->qclass,
|
||||
PACKED_RRSET_PARENT_SIDE, *env->now, 0);
|
||||
if(akey) {
|
||||
log_rrset_key(VERB_ALGO, "found parent-side", akey);
|
||||
ns->done_pside4 = 1;
|
||||
/* a negative-cache-element has no addresses it adds */
|
||||
if(!delegpt_add_rrset_A(dp, region, akey, 1))
|
||||
log_err("malloc failure in lookup_parent_glue");
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
}
|
||||
/* get cached parentside AAAA */
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_AAAA, qinfo->qclass,
|
||||
PACKED_RRSET_PARENT_SIDE, *env->now, 0);
|
||||
if(akey) {
|
||||
log_rrset_key(VERB_ALGO, "found parent-side", akey);
|
||||
ns->done_pside6 = 1;
|
||||
/* a negative-cache-element has no addresses it adds */
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, akey, 1))
|
||||
log_err("malloc failure in lookup_parent_glue");
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
}
|
||||
}
|
||||
/* see if new (but lame) addresses have become available */
|
||||
return delegpt_count_targets(dp) != num;
|
||||
}
|
||||
|
||||
int
|
||||
iter_get_next_root(struct iter_hints* hints, struct iter_forwards* fwd,
|
||||
uint16_t* c)
|
||||
@@ -786,3 +925,111 @@ iter_scrub_ds(struct dns_msg* msg, struct ub_packed_rrset_key* ns, uint8_t* z)
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void iter_dec_attempts(struct delegpt* dp, int d)
|
||||
{
|
||||
struct delegpt_addr* a;
|
||||
for(a=dp->target_list; a; a = a->next_target) {
|
||||
if(a->attempts >= OUTBOUND_MSG_RETRY) {
|
||||
/* add back to result list */
|
||||
a->next_result = dp->result_list;
|
||||
dp->result_list = a;
|
||||
}
|
||||
if(a->attempts > d)
|
||||
a->attempts -= d;
|
||||
else a->attempts = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void iter_merge_retry_counts(struct delegpt* dp, struct delegpt* old)
|
||||
{
|
||||
struct delegpt_addr* a, *o, *prev;
|
||||
for(a=dp->target_list; a; a = a->next_target) {
|
||||
o = delegpt_find_addr(old, &a->addr, a->addrlen);
|
||||
if(o) {
|
||||
log_addr(VERB_ALGO, "copy attempt count previous dp",
|
||||
&a->addr, a->addrlen);
|
||||
a->attempts = o->attempts;
|
||||
}
|
||||
}
|
||||
prev = NULL;
|
||||
a = dp->usable_list;
|
||||
while(a) {
|
||||
if(a->attempts >= OUTBOUND_MSG_RETRY) {
|
||||
log_addr(VERB_ALGO, "remove from usable list dp",
|
||||
&a->addr, a->addrlen);
|
||||
/* remove from result list */
|
||||
if(prev)
|
||||
prev->next_usable = a->next_usable;
|
||||
else dp->usable_list = a->next_usable;
|
||||
/* prev stays the same */
|
||||
a = a->next_usable;
|
||||
continue;
|
||||
}
|
||||
prev = a;
|
||||
a = a->next_usable;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
iter_ds_toolow(struct dns_msg* msg, struct delegpt* dp)
|
||||
{
|
||||
/* if for query example.com, there is example.com SOA or a subdomain
|
||||
* of example.com, then we are too low and need to fetch NS. */
|
||||
size_t i;
|
||||
/* if we have a DNAME or CNAME we are probably wrong */
|
||||
/* if we have a qtype DS in the answer section, its fine */
|
||||
for(i=0; i < msg->rep->an_numrrsets; i++) {
|
||||
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_DNAME ||
|
||||
ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME) {
|
||||
/* not the right answer, maybe too low, check the
|
||||
* RRSIG signer name (if there is any) for a hint
|
||||
* that it is from the dp zone anyway */
|
||||
uint8_t* sname;
|
||||
size_t slen;
|
||||
val_find_rrset_signer(s, &sname, &slen);
|
||||
if(sname && query_dname_compare(dp->name, sname)==0)
|
||||
return 0; /* it is fine, from the right dp */
|
||||
return 1;
|
||||
}
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_DS)
|
||||
return 0; /* fine, we have a DS record */
|
||||
}
|
||||
for(i=msg->rep->an_numrrsets;
|
||||
i < msg->rep->an_numrrsets + msg->rep->ns_numrrsets; i++) {
|
||||
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_SOA) {
|
||||
if(dname_subdomain_c(s->rk.dname, msg->qinfo.qname))
|
||||
return 1; /* point is too low */
|
||||
if(query_dname_compare(s->rk.dname, dp->name)==0)
|
||||
return 0; /* right dp */
|
||||
}
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC ||
|
||||
ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) {
|
||||
uint8_t* sname;
|
||||
size_t slen;
|
||||
val_find_rrset_signer(s, &sname, &slen);
|
||||
if(sname && query_dname_compare(dp->name, sname)==0)
|
||||
return 0; /* it is fine, from the right dp */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* we do not know */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp)
|
||||
{
|
||||
/* no delegation point, do not see how we can go down,
|
||||
* robust check, it should really exist */
|
||||
if(!dp) return 0;
|
||||
|
||||
/* see if dp equals the qname, then we cannot go down further */
|
||||
if(query_dname_compare(qinfo->qname, dp->name) == 0)
|
||||
return 0;
|
||||
/* if dp is one label above the name we also cannot go down further */
|
||||
if(dname_count_labels(qinfo->qname) == dp->namelabs+1)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
+110
-31
@@ -43,6 +43,7 @@
|
||||
#ifndef ITERATOR_ITER_UTILS_H
|
||||
#define ITERATOR_ITER_UTILS_H
|
||||
#include "iterator/iter_resptype.h"
|
||||
#include <ldns/buffer.h>
|
||||
struct iter_env;
|
||||
struct iter_hints;
|
||||
struct iter_forwards;
|
||||
@@ -79,7 +80,7 @@ int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg);
|
||||
* @param name: zone name (for lameness check).
|
||||
* @param namelen: length of name.
|
||||
* @param qtype: query type that we want to send.
|
||||
* @param dnssec_expected: set to 0, if a known dnssec-lame server is selected
|
||||
* @param dnssec_lame: set to 1, if a known dnssec-lame server is selected
|
||||
* these are not preferred, but are used as a last resort.
|
||||
* @param chase_to_rd: set to 1 if a known recursion lame server is selected
|
||||
* these are not preferred, but are used as a last resort.
|
||||
@@ -91,7 +92,7 @@ int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg);
|
||||
*/
|
||||
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_expected,
|
||||
size_t namelen, uint16_t qtype, int* dnssec_lame,
|
||||
int* chase_to_rd, int open_target, struct sock_list* blacklist);
|
||||
|
||||
/**
|
||||
@@ -120,10 +121,18 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);
|
||||
* @param is_referral: If true, then the given message to be stored is a
|
||||
* referral. The cache implementation may use this as a hint.
|
||||
* @param leeway: prefetch TTL leeway to expire old rrsets quicker.
|
||||
* @return 0 on alloc error (out of memory).
|
||||
* @param pside: true if dp is parentside, thus message is 'fresh' and NS
|
||||
* can be prefetch-updates.
|
||||
* @param region: to copy modified (cache is better) rrs back to.
|
||||
* @return void, because we are not interested in alloc errors,
|
||||
* the iterator and validator can operate on the results in their
|
||||
* scratch space (the qstate.region) and are not dependent on the cache.
|
||||
* It is useful to log the alloc failure (for the server operator),
|
||||
* but the query resolution can continue without cache storage.
|
||||
*/
|
||||
int iter_dns_store(struct module_env* env, struct query_info* qinf,
|
||||
struct reply_info* rep, int is_referral, uint32_t leeway);
|
||||
void iter_dns_store(struct module_env* env, struct query_info* qinf,
|
||||
struct reply_info* rep, int is_referral, uint32_t leeway, int pside,
|
||||
struct regional* region);
|
||||
|
||||
/**
|
||||
* Select randomly with n/m probability.
|
||||
@@ -144,17 +153,13 @@ int iter_ns_probability(struct ub_randstate* rnd, int n, int m);
|
||||
void iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp);
|
||||
|
||||
/**
|
||||
* See if query is in-zone glue and we suspect that it exists.
|
||||
* Suspicion that it exists, is if there is no A or AAAA in cache (since
|
||||
* one of them is expected for an NS record) or the qtype is in cache but
|
||||
* was recently expired (so we have seen this data recently).
|
||||
* @param qinfo: query info.
|
||||
* @param dp: delegation point we are at.
|
||||
* @param env: environment with rrset cache.
|
||||
* @return true if suspect that this glue exists.
|
||||
* Mark targets that result in a dependency cycle as done, so they
|
||||
* will not get selected as targets. For the parent-side lookups.
|
||||
* @param qstate: query state.
|
||||
* @param dp: delegpt to mark ns in.
|
||||
*/
|
||||
int iter_suspect_exists(struct query_info* qinfo, struct delegpt* dp,
|
||||
struct module_env* env);
|
||||
void iter_mark_pside_cycle_targets(struct module_qstate* qstate,
|
||||
struct delegpt* dp);
|
||||
|
||||
/**
|
||||
* See if delegation is useful or offers immediately no targets for
|
||||
@@ -162,6 +167,7 @@ int iter_suspect_exists(struct query_info* qinfo, struct delegpt* dp,
|
||||
* @param qinfo: query name and type
|
||||
* @param qflags: query flags with RD flag
|
||||
* @param dp: delegpt to check.
|
||||
* @return true if dp is useless.
|
||||
*/
|
||||
int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
|
||||
struct delegpt* dp);
|
||||
@@ -210,31 +216,69 @@ int iter_msg_from_zone(struct dns_msg* msg, struct delegpt* dp,
|
||||
* @param p: reply one. The reply has rrset data pointers in region.
|
||||
* Does not check rrset-IDs
|
||||
* @param q: reply two
|
||||
* @param buf: scratch buffer.
|
||||
* @return if one and two are equal.
|
||||
*/
|
||||
int reply_equal(struct reply_info* p, struct reply_info* q);
|
||||
int reply_equal(struct reply_info* p, struct reply_info* q, ldns_buffer* buf);
|
||||
|
||||
/**
|
||||
* Store in-zone glue in seperate rrset cache entries for later last-resort
|
||||
* lookups in case the child-side versions of this information fails.
|
||||
* Store parent-side rrset in seperate rrset cache entries for later
|
||||
* last-resort * lookups in case the child-side versions of this information
|
||||
* fails.
|
||||
* @param env: environment with cache, time, ...
|
||||
* @param qinfo: query info. must match the information stored to avoid
|
||||
* Kaminsky-style trouble.
|
||||
* @param rep: reply with possibly A or AAAA content to store.
|
||||
* @param rrset: the rrset to store (copied).
|
||||
* Failure to store is logged, but otherwise ignored.
|
||||
*/
|
||||
void iter_store_inzone_glue(struct module_env* env, struct query_info* qinfo,
|
||||
struct reply_info* rep);
|
||||
void iter_store_parentside_rrset(struct module_env* env,
|
||||
struct ub_packed_rrset_key* rrset);
|
||||
|
||||
/**
|
||||
* Find in-zone glue from rrset cache again.
|
||||
* @param env: query env with rrset cache and time.
|
||||
* @param dp: delegation point to store result in.
|
||||
* @param region: region to alloc result in.
|
||||
* @param qinfo: query into that is pertinent.
|
||||
* @return false on malloc failure.
|
||||
* Store parent-side NS records from a referral message
|
||||
* @param env: environment with cache, time, ...
|
||||
* @param rep: response with NS rrset.
|
||||
* Failure to store is logged, but otherwise ignored.
|
||||
*/
|
||||
int iter_lookup_inzone_glue(struct module_env* env, struct delegpt* dp,
|
||||
struct regional* region, struct query_info* qinfo);
|
||||
void iter_store_parentside_NS(struct module_env* env, struct reply_info* rep);
|
||||
|
||||
/**
|
||||
* Store parent-side negative element, the parentside rrset does not exist,
|
||||
* creates an rrset with empty rdata in the rrset cache with PARENTSIDE flag.
|
||||
* @param env: environment with cache, time, ...
|
||||
* @param qinfo: the identity of the rrset that is missing.
|
||||
* @param rep: delegation response or answer response, to glean TTL from.
|
||||
* (malloc) failure is logged but otherwise ignored.
|
||||
*/
|
||||
void iter_store_parentside_neg(struct module_env* env,
|
||||
struct query_info* qinfo, struct reply_info* rep);
|
||||
|
||||
/**
|
||||
* Add parent NS record if that exists in the cache. This is both new
|
||||
* information and acts like a timeout throttle on retries.
|
||||
* @param env: query env with rrset cache and time.
|
||||
* @param dp: delegation point to store result in. Also this dp is used to
|
||||
* see which NS name is needed.
|
||||
* @param region: region to alloc result in.
|
||||
* @param qinfo: pertinent information, the qclass.
|
||||
* @return false on malloc failure.
|
||||
* if true, the routine worked and if such cached information
|
||||
* existed dp->has_parent_side_NS is set true.
|
||||
*/
|
||||
int iter_lookup_parent_NS_from_cache(struct module_env* env,
|
||||
struct delegpt* dp, struct regional* region, struct query_info* qinfo);
|
||||
|
||||
/**
|
||||
* Add parent-side glue if that exists in the cache. This is both new
|
||||
* information and acts like a timeout throttle on retries to fetch them.
|
||||
* @param env: query env with rrset cache and time.
|
||||
* @param dp: delegation point to store result in. Also this dp is used to
|
||||
* see which NS name is needed.
|
||||
* @param region: region to alloc result in.
|
||||
* @param qinfo: pertinent information, the qclass.
|
||||
* @return: true, it worked, no malloc failures, and new addresses (lame)
|
||||
* have been added, giving extra options as query targets.
|
||||
*/
|
||||
int iter_lookup_parent_glue_from_cache(struct module_env* env,
|
||||
struct delegpt* dp, struct regional* region, struct query_info* qinfo);
|
||||
|
||||
/**
|
||||
* Lookup next root-hint or root-forward entry.
|
||||
@@ -256,4 +300,39 @@ int iter_get_next_root(struct iter_hints* hints, struct iter_forwards* fwd,
|
||||
void iter_scrub_ds(struct dns_msg* msg, struct ub_packed_rrset_key* ns,
|
||||
uint8_t* z);
|
||||
|
||||
/**
|
||||
* Remove query attempts from all available ips. For 0x20.
|
||||
* @param dp: delegpt.
|
||||
* @param d: decrease.
|
||||
*/
|
||||
void iter_dec_attempts(struct delegpt* dp, int d);
|
||||
|
||||
/**
|
||||
* Add retry counts from older delegpt to newer delegpt.
|
||||
* Does not waste time on timeout'd (or other failing) addresses.
|
||||
* @param dp: new delegationpoint.
|
||||
* @param old: old delegationpoint.
|
||||
*/
|
||||
void iter_merge_retry_counts(struct delegpt* dp, struct delegpt* old);
|
||||
|
||||
/**
|
||||
* See if a DS response (type ANSWER) is too low: a nodata answer with
|
||||
* a SOA record in the authority section at-or-below the qchase.qname.
|
||||
* Also returns true if we are not sure (i.e. empty message, CNAME nosig).
|
||||
* @param msg: the response.
|
||||
* @param dp: the dp name is used to check if the RRSIG gives a clue that
|
||||
* it was originated from the correct nameserver.
|
||||
* @return true if too low.
|
||||
*/
|
||||
int iter_ds_toolow(struct dns_msg* msg, struct delegpt* dp);
|
||||
|
||||
/**
|
||||
* See if delegpt can go down a step to the qname or not
|
||||
* @param qinfo: the query name looked up.
|
||||
* @param dp: checked if the name can go lower to the qname
|
||||
* @return true if can go down, false if that would not be possible.
|
||||
* the current response seems to be the one and only, best possible, response.
|
||||
*/
|
||||
int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp);
|
||||
|
||||
#endif /* ITERATOR_ITER_UTILS_H */
|
||||
|
||||
+535
-136
File diff suppressed because it is too large
Load Diff
+49
-10
@@ -55,7 +55,11 @@ struct iter_priv;
|
||||
/** max number of query restarts. Determines max number of CNAME chain. */
|
||||
#define MAX_RESTART_COUNT 8
|
||||
/** max number of referrals. Makes sure resolver does not run away */
|
||||
#define MAX_REFERRAL_COUNT 30
|
||||
#define MAX_REFERRAL_COUNT 130
|
||||
/** max number of queries-sent-out. Make sure large NS set does not loop */
|
||||
#define MAX_SENT_COUNT 16
|
||||
/** at what query-sent-count to stop target fetch policy */
|
||||
#define TARGET_FETCH_STOP 3
|
||||
/** how nice is a server without further information, in msec
|
||||
* Equals rtt initial timeout value.
|
||||
*/
|
||||
@@ -75,22 +79,19 @@ struct iter_priv;
|
||||
* Chosen so that the UNKNOWN_SERVER_NICENESS falls within the band of a
|
||||
* fast server, this causes server exploration as a side benefit. msec. */
|
||||
#define RTT_BAND 400
|
||||
/** Start value for blacklisting a host, 2*USEFUL_SERVER_TOP_TIMEOUT in sec */
|
||||
#define INFRA_BACKOFF_INITIAL 240
|
||||
|
||||
/**
|
||||
* Global state for the iterator.
|
||||
*/
|
||||
struct iter_env {
|
||||
/**
|
||||
* The hints -- these aren't stored in the cache because they don't
|
||||
* expire. The hints are always used to "prime" the cache. Note
|
||||
* that both root hints and stub zone "hints" are stored in this
|
||||
* data structure.
|
||||
*/
|
||||
struct iter_hints* hints;
|
||||
|
||||
/** A flag to indicate whether or not we have an IPv6 route */
|
||||
int supports_ipv6;
|
||||
|
||||
/** A flag to indicate whether or not we have an IPv4 route */
|
||||
int supports_ipv4;
|
||||
|
||||
/** A set of inetaddrs that should never be queried. */
|
||||
struct iter_donotq* donotq;
|
||||
|
||||
@@ -154,6 +155,10 @@ enum iter_state {
|
||||
* it spawns off queries for every class, it returns here. */
|
||||
COLLECT_CLASS_STATE,
|
||||
|
||||
/** Find NS record to resolve DS record from, walking to the right
|
||||
* NS spot until we find it */
|
||||
DSNS_FIND_STATE,
|
||||
|
||||
/** Responses that are to be returned upstream end at this state.
|
||||
* As well as responses to target queries. */
|
||||
FINISHED_STATE
|
||||
@@ -247,6 +252,34 @@ struct iter_qstate {
|
||||
/** the number of times this query as followed a referral. */
|
||||
int referral_count;
|
||||
|
||||
/** number of queries fired off */
|
||||
int sent_count;
|
||||
|
||||
/**
|
||||
* The query must store NS records from referrals as parentside RRs
|
||||
* Enabled once it hits resolution problems, to throttle retries.
|
||||
* If enabled it is the pointer to the old delegation point with
|
||||
* the old retry counts for bad-nameserver-addresses.
|
||||
*/
|
||||
struct delegpt* store_parent_NS;
|
||||
|
||||
/**
|
||||
* The query is for parent-side glue(A or AAAA) for a nameserver.
|
||||
* If the item is seen as glue in a referral, and pside_glue is NULL,
|
||||
* then it is stored in pside_glue for later.
|
||||
* If it was never seen, at the end, then a negative caching element
|
||||
* must be created.
|
||||
* The (data or negative) RR cache element then throttles retries.
|
||||
*/
|
||||
int query_for_pside_glue;
|
||||
/** the parent-side-glue element (NULL if none, its first match) */
|
||||
struct ub_packed_rrset_key* pside_glue;
|
||||
|
||||
/** If nonNULL we are walking upwards from DS query to find NS */
|
||||
uint8_t* dsns_point;
|
||||
/** length of the dname in dsns_point */
|
||||
size_t dsns_point_len;
|
||||
|
||||
/**
|
||||
* expected dnssec information for this iteration step.
|
||||
* If dnssec rrsigs are expected and not given, the server is marked
|
||||
@@ -254,6 +287,12 @@ struct iter_qstate {
|
||||
*/
|
||||
int dnssec_expected;
|
||||
|
||||
/**
|
||||
* We are expecting dnssec information, but we also know the server
|
||||
* is DNSSEC lame. The response need not be marked dnssec-lame again.
|
||||
*/
|
||||
int dnssec_lame_query;
|
||||
|
||||
/**
|
||||
* This is flag that, if true, means that this event is
|
||||
* waiting for a stub priming query.
|
||||
@@ -288,7 +327,7 @@ struct iter_prep_list {
|
||||
* Get the iterator function block.
|
||||
* @return: function block with function pointers to iterator methods.
|
||||
*/
|
||||
struct module_func_block* iter_get_funcblock();
|
||||
struct module_func_block* iter_get_funcblock(void);
|
||||
|
||||
/**
|
||||
* Get iterator state as a string
|
||||
|
||||
Binary file not shown.
@@ -44,6 +44,7 @@
|
||||
/* include the public api first, it should be able to stand alone */
|
||||
#include "libunbound/unbound.h"
|
||||
#include "config.h"
|
||||
#include <ctype.h>
|
||||
#include "libunbound/context.h"
|
||||
#include "libunbound/libworker.h"
|
||||
#include "util/locks.h"
|
||||
@@ -66,7 +67,7 @@
|
||||
#endif /* UB_ON_WINDOWS */
|
||||
|
||||
struct ub_ctx*
|
||||
ub_ctx_create()
|
||||
ub_ctx_create(void)
|
||||
{
|
||||
struct ub_ctx* ctx;
|
||||
unsigned int seed;
|
||||
@@ -1116,3 +1117,8 @@ int ub_ctx_data_remove(struct ub_ctx* ctx, char *data)
|
||||
free(nm);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
|
||||
const char* ub_version(void)
|
||||
{
|
||||
return PACKAGE_VERSION;
|
||||
}
|
||||
|
||||
+63
-47
@@ -42,6 +42,9 @@
|
||||
* returns from the procedure when done.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <ldns/dname.h>
|
||||
#include <ldns/wire2host.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include "libunbound/libworker.h"
|
||||
#include "libunbound/context.h"
|
||||
#include "libunbound/unbound.h"
|
||||
@@ -55,6 +58,7 @@
|
||||
#include "util/random.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/netevent.h"
|
||||
#include "util/storage/lookup3.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/data/dname.h"
|
||||
@@ -62,6 +66,7 @@
|
||||
#include "util/data/msgencode.h"
|
||||
#include "util/tube.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
|
||||
/** handle new query command for bg worker */
|
||||
static void handle_newq(struct libworker* w, uint8_t* buf, uint32_t len);
|
||||
@@ -79,9 +84,11 @@ libworker_delete(struct libworker* w)
|
||||
ldns_buffer_free(w->env->scratch_buffer);
|
||||
regional_destroy(w->env->scratch);
|
||||
forwards_delete(w->env->fwds);
|
||||
hints_delete(w->env->hints);
|
||||
ub_randfree(w->env->rnd);
|
||||
free(w->env);
|
||||
}
|
||||
SSL_CTX_free(w->sslctx);
|
||||
outside_network_delete(w->back);
|
||||
comm_base_delete(w->base);
|
||||
free(w);
|
||||
@@ -122,10 +129,24 @@ libworker_setup(struct ub_ctx* ctx, int is_bg)
|
||||
forwards_delete(w->env->fwds);
|
||||
w->env->fwds = NULL;
|
||||
}
|
||||
w->env->hints = hints_create();
|
||||
if(w->env->hints && !hints_apply_cfg(w->env->hints, cfg)) {
|
||||
hints_delete(w->env->hints);
|
||||
w->env->hints = NULL;
|
||||
}
|
||||
if(cfg->ssl_upstream) {
|
||||
w->sslctx = connect_sslctx_create(NULL, NULL, NULL);
|
||||
if(!w->sslctx) {
|
||||
/* to make the setup fail after unlock */
|
||||
hints_delete(w->env->hints);
|
||||
w->env->hints = NULL;
|
||||
}
|
||||
}
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
}
|
||||
if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds) {
|
||||
if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds ||
|
||||
!w->env->hints) {
|
||||
libworker_delete(w);
|
||||
return NULL;
|
||||
}
|
||||
@@ -148,6 +169,19 @@ libworker_setup(struct ub_ctx* ctx, int is_bg)
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
}
|
||||
if(1) {
|
||||
/* primitive lockout for threading: if it overwrites another
|
||||
* thread it is like wiping the cache (which is likely empty
|
||||
* at the start) */
|
||||
/* note we are holding the ctx lock in normal threaded
|
||||
* cases so that is solved properly, it is only for many ctx
|
||||
* in different threads that this may clash */
|
||||
static int done_raninit = 0;
|
||||
if(!done_raninit) {
|
||||
done_raninit = 1;
|
||||
hash_set_raninit((uint32_t)ub_random(w->env->rnd));
|
||||
}
|
||||
}
|
||||
seed = 0;
|
||||
|
||||
w->base = comm_base_create(0);
|
||||
@@ -169,7 +203,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg)
|
||||
cfg->do_tcp?cfg->outgoing_num_tcp:0,
|
||||
w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id,
|
||||
ports, numports, cfg->unwanted_threshold,
|
||||
&libworker_alloc_cleanup, w, cfg->do_udp);
|
||||
&libworker_alloc_cleanup, w, cfg->do_udp, w->sslctx);
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
}
|
||||
@@ -183,7 +217,6 @@ libworker_setup(struct ub_ctx* ctx, int is_bg)
|
||||
libworker_delete(w);
|
||||
return NULL;
|
||||
}
|
||||
w->env->send_packet = &libworker_send_packet;
|
||||
w->env->send_query = &libworker_send_query;
|
||||
w->env->detach_subs = &mesh_detach_subs;
|
||||
w->env->attach_sub = &mesh_attach_sub;
|
||||
@@ -260,7 +293,12 @@ libworker_dobg(void* arg)
|
||||
/* setup */
|
||||
uint32_t m;
|
||||
struct libworker* w = (struct libworker*)arg;
|
||||
struct ub_ctx* ctx = w->ctx;
|
||||
struct ub_ctx* ctx;
|
||||
if(!w) {
|
||||
log_err("libunbound bg worker init failed, nomem");
|
||||
return NULL;
|
||||
}
|
||||
ctx = w->ctx;
|
||||
log_thread_set(&w->thread_num);
|
||||
#ifdef THREADS_DISABLED
|
||||
/* we are forked */
|
||||
@@ -269,10 +307,6 @@ libworker_dobg(void* arg)
|
||||
tube_close_write(ctx->qq_pipe);
|
||||
tube_close_read(ctx->rr_pipe);
|
||||
#endif
|
||||
if(!w) {
|
||||
log_err("libunbound bg worker init failed, nomem");
|
||||
return NULL;
|
||||
}
|
||||
if(!tube_setup_bg_listen(ctx->qq_pipe, w->base,
|
||||
libworker_handle_control_cmd, w)) {
|
||||
log_err("libunbound bg worker init failed, no bglisten");
|
||||
@@ -309,11 +343,11 @@ int libworker_bg(struct ub_ctx* ctx)
|
||||
if(ctx->dothread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
w = libworker_setup(ctx, 1);
|
||||
if(!w) return UB_NOMEM;
|
||||
w->is_bg_thread = 1;
|
||||
#ifdef ENABLE_LOCK_CHECKS
|
||||
w->thread_num = 1; /* for nicer DEBUG checklocks */
|
||||
#endif
|
||||
if(!w) return UB_NOMEM;
|
||||
ub_thread_create(&ctx->bg_tid, libworker_dobg, w);
|
||||
} else {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
@@ -609,6 +643,8 @@ libworker_bg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s,
|
||||
return;
|
||||
}
|
||||
q->msg_security = s;
|
||||
if(!buf)
|
||||
buf = q->w->env->scratch_buffer;
|
||||
if(rcode != 0) {
|
||||
error_encode(buf, rcode, NULL, 0, BIT_RD, NULL);
|
||||
}
|
||||
@@ -669,33 +705,10 @@ void libworker_alloc_cleanup(void* arg)
|
||||
slabhash_clear(w->env->msg_cache);
|
||||
}
|
||||
|
||||
int libworker_send_packet(ldns_buffer* pkt, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int timeout, struct module_qstate* q, int use_tcp)
|
||||
{
|
||||
struct libworker* w = (struct libworker*)q->env->worker;
|
||||
if(use_tcp) {
|
||||
return pending_tcp_query(w->back, pkt, addr, addrlen,
|
||||
timeout, libworker_handle_reply, q) != 0;
|
||||
}
|
||||
return pending_udp_query(w->back, pkt, addr, addrlen,
|
||||
timeout*1000, libworker_handle_reply, q) != 0;
|
||||
}
|
||||
|
||||
/** compare outbound entry qstates */
|
||||
static int
|
||||
outbound_entry_compare(void* a, void* b)
|
||||
{
|
||||
struct outbound_entry* e1 = (struct outbound_entry*)a;
|
||||
struct outbound_entry* e2 = (struct outbound_entry*)b;
|
||||
if(e1->qstate == e2->qstate)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
|
||||
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct module_qstate* q)
|
||||
int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, struct module_qstate* q)
|
||||
{
|
||||
struct libworker* w = (struct libworker*)q->env->worker;
|
||||
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
|
||||
@@ -704,9 +717,10 @@ struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
|
||||
return NULL;
|
||||
e->qstate = q;
|
||||
e->qsent = outnet_serviced_query(w->back, qname,
|
||||
qnamelen, qtype, qclass, flags, dnssec, addr, addrlen,
|
||||
libworker_handle_service_reply, e, w->back->udp_buff,
|
||||
&outbound_entry_compare);
|
||||
qnamelen, qtype, qclass, flags, dnssec, want_dnssec,
|
||||
q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr,
|
||||
addrlen, zone, zonelen, libworker_handle_service_reply, e,
|
||||
w->back->udp_buff);
|
||||
if(!e->qsent) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -821,19 +835,11 @@ void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg))
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
int worker_send_packet(ldns_buffer* ATTR_UNUSED(pkt),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen), int ATTR_UNUSED(timeout),
|
||||
struct module_qstate* ATTR_UNUSED(q), int ATTR_UNUSED(use_tcp))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct outbound_entry* worker_send_query(uint8_t* ATTR_UNUSED(qname),
|
||||
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
|
||||
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
|
||||
int ATTR_UNUSED(dnssec), struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen), struct module_qstate* ATTR_UNUSED(q))
|
||||
{
|
||||
log_assert(0);
|
||||
@@ -856,6 +862,16 @@ void worker_probe_timer_cb(void* ATTR_UNUSED(arg))
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void worker_start_accept(void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void worker_stop_accept(void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
int order_lock_cmp(const void* ATTR_UNUSED(e1), const void* ATTR_UNUSED(e2))
|
||||
{
|
||||
log_assert(0);
|
||||
|
||||
+7
-16
@@ -81,6 +81,8 @@ struct libworker {
|
||||
struct outside_network* back;
|
||||
/** random() table for this worker. */
|
||||
struct ub_randstate* rndstate;
|
||||
/** sslcontext for SSL wrapped DNS over TCP queries */
|
||||
void* sslctx;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -107,20 +109,6 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q);
|
||||
/** cleanup the cache to remove all rrset IDs from it, arg is libworker */
|
||||
void libworker_alloc_cleanup(void* arg);
|
||||
|
||||
/**
|
||||
* Worker service routine to send udp messages for modules.
|
||||
* @param pkt: packet to send.
|
||||
* @param addr: where to.
|
||||
* @param addrlen: length of addr.
|
||||
* @param timeout: seconds to wait until timeout.
|
||||
* @param q: wich query state to reactivate upon return.
|
||||
* @param use_tcp: true to use TCP, false for UDP.
|
||||
* @return: false on failure (memory or socket related). no query was
|
||||
* sent.
|
||||
*/
|
||||
int libworker_send_packet(ldns_buffer* pkt, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int timeout, struct module_qstate* q, int use_tcp);
|
||||
|
||||
/**
|
||||
* Worker service routine to send serviced queries to authoritative servers.
|
||||
* @param qname: query name. (host order)
|
||||
@@ -129,16 +117,19 @@ int libworker_send_packet(ldns_buffer* pkt, struct sockaddr_storage* addr,
|
||||
* @param qclass: query class. (host order)
|
||||
* @param flags: host order flags word, with opcode and CD bit.
|
||||
* @param dnssec: if set, EDNS record will have DO bit set.
|
||||
* @param want_dnssec: signatures needed.
|
||||
* @param addr: where to.
|
||||
* @param addrlen: length of addr.
|
||||
* @param zone: delegation point name.
|
||||
* @param zonelen: length of zone name wireformat dname.
|
||||
* @param q: wich query state to reactivate upon return.
|
||||
* @return: false on failure (memory or socket related). no query was
|
||||
* sent.
|
||||
*/
|
||||
struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
|
||||
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct module_qstate* q);
|
||||
int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, struct module_qstate* q);
|
||||
|
||||
/** process incoming replies from the network */
|
||||
int libworker_handle_reply(struct comm_point* c, void* arg, int error,
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python
|
||||
from unbound import ub_ctx, RR_TYPE_A, RR_TYPE_RRSIG, RR_TYPE_NSEC, RR_TYPE_NSEC3
|
||||
import ldns
|
||||
|
||||
def dnssecParse(domain, rrType=RR_TYPE_A):
|
||||
print "Resolving domain", domain
|
||||
s, r = resolver.resolve(domain)
|
||||
print "status: %s, secure: %s, rcode: %s, havedata: %s, answer_len; %s" % (s, r.secure, r.rcode_str, r.havedata, r.answer_len)
|
||||
|
||||
s, pkt = ldns.ldns_wire2pkt(r.packet)
|
||||
if s != 0:
|
||||
raise RuntimeError("Error parsing DNS packet")
|
||||
|
||||
rrsigs = pkt.rr_list_by_type(RR_TYPE_RRSIG, ldns.LDNS_SECTION_ANSWER)
|
||||
print "RRSIGs from answer:", rrsigs
|
||||
|
||||
rrsigs = pkt.rr_list_by_type(RR_TYPE_RRSIG, ldns.LDNS_SECTION_AUTHORITY)
|
||||
print "RRSIGs from authority:", rrsigs
|
||||
|
||||
nsecs = pkt.rr_list_by_type(RR_TYPE_NSEC, ldns.LDNS_SECTION_AUTHORITY)
|
||||
print "NSECs:", nsecs
|
||||
|
||||
nsec3s = pkt.rr_list_by_type(RR_TYPE_NSEC3, ldns.LDNS_SECTION_AUTHORITY)
|
||||
print "NSEC3s:", nsec3s
|
||||
|
||||
print "---"
|
||||
|
||||
|
||||
resolver = ub_ctx()
|
||||
resolver.add_ta(". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5")
|
||||
|
||||
dnssecParse("nic.cz")
|
||||
dnssecParse("nonexistent-domain-blablabla.cz")
|
||||
dnssecParse("nonexistent-domain-blablabla.root.cz")
|
||||
|
||||
@@ -768,6 +768,10 @@ Result: ['74.125.43.147', '74.125.43.99', '74.125.43.103', '74.125.43.104']
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
PyObject* _packet() {
|
||||
return PyString_FromStringAndSize($self->answer_packet, $self->answer_len);
|
||||
}
|
||||
|
||||
%pythoncode %{
|
||||
def __init__(self):
|
||||
@@ -805,6 +809,7 @@ Result: ['74.125.43.147', '74.125.43.99', '74.125.43.103', '74.125.43.104']
|
||||
return ub_data(self._ub_result_data(self))
|
||||
|
||||
__swig_getmethods__["data"] = _get_data
|
||||
__swig_getmethods__["packet"] = _packet
|
||||
data = property(_get_data, doc="Returns :class:`ub_data` instance containing various decoding functions or None")
|
||||
|
||||
%}
|
||||
|
||||
@@ -26,3 +26,4 @@ ub_ctx_zone_add
|
||||
ub_ctx_zone_remove
|
||||
ub_ctx_data_add
|
||||
ub_ctx_data_remove
|
||||
ub_version
|
||||
|
||||
@@ -93,6 +93,10 @@
|
||||
#ifndef _UB_UNBOUND_H
|
||||
#define _UB_UNBOUND_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The validation context is created to hold the resolver status,
|
||||
* validation keys and a small cache (containing messages, rrsets,
|
||||
@@ -539,4 +543,14 @@ int ub_ctx_data_add(struct ub_ctx* ctx, char *data);
|
||||
*/
|
||||
int ub_ctx_data_remove(struct ub_ctx* ctx, char *data);
|
||||
|
||||
/**
|
||||
* Get a version string from the libunbound implementation.
|
||||
* @return a static constant string with the version number.
|
||||
*/
|
||||
const char* ub_version(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _UB_UNBOUND_H */
|
||||
|
||||
+88
-8
@@ -54,6 +54,9 @@ Generate a distribution tar file for unbound.
|
||||
-d SVN_root Retrieve the unbound source from the specified repository.
|
||||
Detected from svn working copy if not specified.
|
||||
-l ldnsdir Directory where ldns resides. Detected from Makefile.
|
||||
-wssl openssl.xx.tar.gz Also build openssl from tarball for windows dist.
|
||||
-wxp expat.xx.tar.gz Also build expat from tarball for windows dist.
|
||||
-wldns ldns.xx.tar.gz Also build libldns from tarball for windows dist.
|
||||
-w ... Build windows binary dist. last args passed to configure.
|
||||
EOF
|
||||
exit 1
|
||||
@@ -133,6 +136,9 @@ SNAPSHOT="no"
|
||||
RC="no"
|
||||
LDNSDIR=""
|
||||
DOWIN="no"
|
||||
WINSSL=""
|
||||
WINEXPAT=""
|
||||
WINLDNS=""
|
||||
|
||||
# Parse the command line arguments.
|
||||
while [ "$1" ]; do
|
||||
@@ -147,6 +153,18 @@ while [ "$1" ]; do
|
||||
"-s")
|
||||
SNAPSHOT="yes"
|
||||
;;
|
||||
"-wldns")
|
||||
WINLDNS="$2"
|
||||
shift
|
||||
;;
|
||||
"-wssl")
|
||||
WINSSL="$2"
|
||||
shift
|
||||
;;
|
||||
"-wxp")
|
||||
WINEXPAT="$2"
|
||||
shift
|
||||
;;
|
||||
"-w")
|
||||
DOWIN="yes"
|
||||
shift
|
||||
@@ -168,16 +186,71 @@ while [ "$1" ]; do
|
||||
done
|
||||
|
||||
if [ "$DOWIN" = "yes" ]; then
|
||||
# detect crosscompile, from Fedora11 at this point.
|
||||
# detect crosscompile, from Fedora13 at this point.
|
||||
if test "`uname`" = "Linux"; then
|
||||
info "Crosscompile windows dist"
|
||||
cross="yes"
|
||||
configure="mingw32-configure"
|
||||
strip="i686-pc-mingw32-strip"
|
||||
makensis="makensis" # from mingw32-nsis package
|
||||
# flags for crosscompiled dependency libraries
|
||||
cross_flag=""
|
||||
|
||||
check_svn_root
|
||||
create_temp_dir
|
||||
|
||||
# crosscompile openssl for windows.
|
||||
if test -n "$WINSSL"; then
|
||||
info "Cross compile $WINSSL"
|
||||
info "winssl tar unpack"
|
||||
(cd ..; gzip -cd $WINSSL) | tar xf - || error_cleanup "tar unpack of $WINSSL failed"
|
||||
sslinstall="`pwd`/sslinstall"
|
||||
cd openssl-* || error_cleanup "no openssl-X dir in tarball"
|
||||
# configure for crosscompile, without CAPI because it fails
|
||||
# cross-compilation and it is not used anyway
|
||||
sslflags="no-asm --cross-compile-prefix=i686-pc-mingw32- -DOPENSSL_NO_CAPIENG mingw"
|
||||
info "winssl: Configure $sslflags"
|
||||
./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.
|
||||
info "winssl: make install_sw"
|
||||
make install_sw || error_cleanup "OpenSSL install failed"
|
||||
cross_flag="$cross_flag --with-ssl=$sslinstall"
|
||||
cd ..
|
||||
fi
|
||||
|
||||
if test -n "$WINLDNS"; then
|
||||
info "Cross compile $WINLDNS"
|
||||
info "ldns tar unpack"
|
||||
(cd ..; gzip -cd $WINLDNS) | tar xf - || error_cleanup "tar unpack of $WINLDNS failed"
|
||||
cd ldns-* || error_cleanup "no ldns-X dir in tarball"
|
||||
# we can use the cross_flag with openssl in it
|
||||
info "ldns: Configure $cross_flag"
|
||||
mingw32-configure $cross_flag || error_cleanup "ldns configure failed"
|
||||
info "ldns: make"
|
||||
make || error_cleanup "ldns crosscompile failed"
|
||||
# use from the build directory.
|
||||
cross_flag="$cross_flag --with-ldns=`pwd`"
|
||||
cd ..
|
||||
fi
|
||||
|
||||
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"
|
||||
wxpinstall="`pwd`/wxpinstall"
|
||||
cd expat-* || error_cleanup "no expat-X dir in tarball"
|
||||
info "wxp: configure"
|
||||
mingw32-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"
|
||||
cross_flag="$cross_flag --with-libexpat=$wxpinstall"
|
||||
cd ..
|
||||
fi
|
||||
|
||||
info "Exporting source from SVN."
|
||||
svn export "$SVNROOT" unbound || error_cleanup "SVN command failed"
|
||||
cd unbound || error_cleanup "Unbound not exported correctly from SVN"
|
||||
@@ -186,6 +259,7 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
if test -f mingw32-config.cache; then rm mingw32-config.cache; fi
|
||||
else
|
||||
cross="no" # mingw and msys
|
||||
cross_flag=""
|
||||
configure="./configure"
|
||||
strip="strip"
|
||||
makensis="c:/Program Files/NSIS/makensis.exe" # http://nsis.sf.net
|
||||
@@ -206,15 +280,16 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
replace_text "configure.ac" "AC_INIT(unbound, $version" "AC_INIT(unbound, $version2"
|
||||
version="$version2"
|
||||
info "Rebuilding configure script (autoconf) snapshot."
|
||||
autoconf || autoheader || error_cleanup "Autoconf failed."
|
||||
autoconf || error_cleanup "Autoconf failed."
|
||||
autoheader || error_cleanup "Autoheader failed."
|
||||
rm -r autom4te* || echo "ignored"
|
||||
fi
|
||||
|
||||
# procedure for making unbound installer on mingw.
|
||||
info "Creating windows dist unbound $version"
|
||||
info "Calling configure"
|
||||
echo "$configure"' --enable-debug --enable-static-exe '"$*"
|
||||
$configure --enable-debug --enable-static-exe $* \
|
||||
echo "$configure"' --enable-debug --enable-static-exe '"$* $cross_flag"
|
||||
$configure --enable-debug --enable-static-exe $* $cross_flag \
|
||||
|| error_cleanup "Could not configure"
|
||||
info "Calling make"
|
||||
make || error_cleanup "Could not make"
|
||||
@@ -229,14 +304,15 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
$strip anchor-update.exe
|
||||
$strip unbound-control.exe
|
||||
$strip unbound-host.exe
|
||||
$strip unbound-anchor.exe
|
||||
$strip unbound-checkconf.exe
|
||||
$strip unbound-service-install.exe
|
||||
$strip unbound-service-remove.exe
|
||||
cd tmp.$$
|
||||
cp ../doc/example.conf example.conf
|
||||
cp ../unbound.exe ../unbound-host.exe ../unbound-control.exe ../unbound-checkconf.exe ../unbound-service-install.exe ../unbound-service-remove.exe ../LICENSE ../winrc/unbound-website.url ../winrc/service.conf ../winrc/README.txt .
|
||||
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-website.url ../winrc/service.conf ../winrc/README.txt .
|
||||
# zipfile
|
||||
zip ../$file LICENSE README.txt unbound.exe unbound-host.exe unbound-control.exe unbound-checkconf.exe unbound-service-install.exe unbound-service-remove.exe example.conf service.conf unbound-website.url
|
||||
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 example.conf service.conf unbound-website.url
|
||||
info "Testing $file"
|
||||
(cd .. ; zip -T $file )
|
||||
# installer
|
||||
@@ -293,9 +369,11 @@ autoreconf || error_cleanup "Autoconf failed."
|
||||
rm -r autom4te* || error_cleanup "Failed to remove autoconf cache directory."
|
||||
|
||||
info "Building lexer and parser."
|
||||
echo "#include \"util/configyyrename.h\"" > util/configlexer.c || error_cleanup "Failed to create configlexer"
|
||||
echo "#include \"config.h\"" > util/configlexer.c || error_cleanup "Failed to create configlexer"
|
||||
echo "#include \"util/configyyrename.h\"" >> util/configlexer.c || error_cleanup "Failed to create configlexer"
|
||||
flex -i -t util/configlexer.lex >> util/configlexer.c || error_cleanup "Failed to create configlexer"
|
||||
bison -y -d -o util/configparser.c util/configparser.y || error_cleanup "Failed to create configparser"
|
||||
if test -x `which bison` 2>&1; then YACC=bison; else YACC=yacc; fi
|
||||
$YACC -y -d -o util/configparser.c util/configparser.y || error_cleanup "Failed to create configparser"
|
||||
|
||||
# check shared code, ldns-testpkts from ldns examples, if possible.
|
||||
cd ../..
|
||||
@@ -352,7 +430,9 @@ replace_all doc/unbound.8.in
|
||||
replace_all doc/unbound.conf.5.in
|
||||
replace_all doc/unbound-checkconf.8.in
|
||||
replace_all doc/unbound-control.8.in
|
||||
replace_all doc/unbound-anchor.8.in
|
||||
replace_all doc/unbound-host.1
|
||||
replace_all doc/example.conf.in
|
||||
replace_all doc/libunbound.3.in
|
||||
|
||||
info "Renaming Unbound directory to unbound-$version."
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
|
||||
print mod_env.fname # Print module script name
|
||||
mod_env.data = "test" # Store global module data
|
||||
|
||||
def init(id, cfg):
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
|
||||
return True
|
||||
|
||||
@@ -606,10 +606,8 @@ struct config_file {
|
||||
size_t rrset_cache_size;
|
||||
size_t rrset_cache_slabs;
|
||||
int host_ttl;
|
||||
int lame_ttl;
|
||||
size_t infra_cache_slabs;
|
||||
size_t infra_cache_numhosts;
|
||||
size_t infra_cache_lame_size;
|
||||
char* target_fetch_policy;
|
||||
int if_automatic;
|
||||
int num_ifs;
|
||||
@@ -868,6 +866,15 @@ void log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* r
|
||||
void log_query_info(enum verbosity_value v, const char* str, struct query_info* qinf);
|
||||
void regional_log_stats(struct regional *r);
|
||||
|
||||
// Free allocated memory from marked sources returning corresponding types
|
||||
%typemap(newfree, noblock = 1) char * {
|
||||
free($1);
|
||||
}
|
||||
|
||||
// Mark as source returning newly allocated memory
|
||||
%newobject ldns_rr_type2str;
|
||||
%newobject ldns_rr_class2str;
|
||||
|
||||
// LDNS functions
|
||||
char *ldns_rr_type2str(const uint16_t atype);
|
||||
char *ldns_rr_class2str(const uint16_t aclass);
|
||||
|
||||
+30
-19
@@ -41,9 +41,11 @@
|
||||
/* ignore the varargs unused warning from SWIGs internal vararg support */
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include <ldns/ldns.h>
|
||||
|
||||
#undef _POSIX_C_SOURCE
|
||||
#undef _XOPEN_SOURCE
|
||||
@@ -56,6 +58,8 @@
|
||||
|
||||
#ifdef S_SPLINT_S
|
||||
typedef struct PyObject PyObject;
|
||||
typedef struct PyThreadState PyThreadState;
|
||||
typedef void* PyGILState_STATE;
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -66,6 +70,8 @@ struct pythonmod_env {
|
||||
/** Python script filename. */
|
||||
const char* fname;
|
||||
|
||||
/** Python main thread */
|
||||
PyThreadState* mainthr;
|
||||
/** Python module. */
|
||||
PyObject* module;
|
||||
|
||||
@@ -107,6 +113,7 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
/* Initialize module */
|
||||
FILE* script_py = NULL;
|
||||
PyObject* py_cfg, *res;
|
||||
PyGILState_STATE gil;
|
||||
struct pythonmod_env* pe = (struct pythonmod_env*)calloc(1, sizeof(struct pythonmod_env));
|
||||
if (!pe)
|
||||
{
|
||||
@@ -130,11 +137,11 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
Py_NoSiteFlag = 1;
|
||||
Py_Initialize();
|
||||
PyEval_InitThreads();
|
||||
PyEval_ReleaseLock();
|
||||
SWIG_init();
|
||||
pe->mainthr = PyEval_SaveThread();
|
||||
}
|
||||
|
||||
PyEval_AcquireLock();
|
||||
gil = PyGILState_Ensure();
|
||||
|
||||
/* Initialize Python */
|
||||
PyRun_SimpleString("import sys \n");
|
||||
@@ -147,10 +154,12 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
}
|
||||
PyRun_SimpleString("sys.path.append('"RUN_DIR"') \n");
|
||||
PyRun_SimpleString("sys.path.append('"SHARE_DIR"') \n");
|
||||
PyRun_SimpleString("import distutils.sysconfig \n");
|
||||
PyRun_SimpleString("sys.path.append(distutils.sysconfig.get_python_lib(1,0)) \n");
|
||||
if (PyRun_SimpleString("from unboundmodule import *\n") < 0)
|
||||
{
|
||||
log_err("pythonmod: cannot initialize core module: unboundmodule.py");
|
||||
PyEval_ReleaseLock();
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -158,7 +167,7 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
if ((script_py = fopen(pe->fname, "r")) == NULL)
|
||||
{
|
||||
log_err("pythonmod: can't open file %s for reading", pe->fname);
|
||||
PyEval_ReleaseLock();
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -174,7 +183,7 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
if (PyRun_SimpleFile(script_py, pe->fname) < 0)
|
||||
{
|
||||
log_err("pythonmod: can't parse Python script %s", pe->fname);
|
||||
PyEval_ReleaseLock();
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -183,25 +192,25 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
if ((pe->func_init = PyDict_GetItemString(pe->dict, "init")) == NULL)
|
||||
{
|
||||
log_err("pythonmod: function init is missing in %s", pe->fname);
|
||||
PyEval_ReleaseLock();
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
if ((pe->func_deinit = PyDict_GetItemString(pe->dict, "deinit")) == NULL)
|
||||
{
|
||||
log_err("pythonmod: function deinit is missing in %s", pe->fname);
|
||||
PyEval_ReleaseLock();
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
if ((pe->func_operate = PyDict_GetItemString(pe->dict, "operate")) == NULL)
|
||||
{
|
||||
log_err("pythonmod: function operate is missing in %s", pe->fname);
|
||||
PyEval_ReleaseLock();
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
if ((pe->func_inform = PyDict_GetItemString(pe->dict, "inform_super")) == NULL)
|
||||
{
|
||||
log_err("pythonmod: function inform_super is missing in %s", pe->fname);
|
||||
PyEval_ReleaseLock();
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -215,7 +224,7 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
|
||||
Py_XDECREF(res);
|
||||
Py_XDECREF(py_cfg);
|
||||
PyEval_ReleaseLock();
|
||||
PyGILState_Release(gil);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -230,9 +239,9 @@ void pythonmod_deinit(struct module_env* env, int id)
|
||||
if(pe->module != NULL)
|
||||
{
|
||||
PyObject* res;
|
||||
PyGILState_STATE gil = PyGILState_Ensure();
|
||||
|
||||
/* Deinit module */
|
||||
PyEval_AcquireLock();
|
||||
res = PyObject_CallFunction(pe->func_deinit, "i", id);
|
||||
if (PyErr_Occurred()) {
|
||||
log_err("pythonmod: Exception occurred in function deinit");
|
||||
@@ -242,8 +251,11 @@ void pythonmod_deinit(struct module_env* env, int id)
|
||||
Py_XDECREF(res);
|
||||
/* Free shared data if any */
|
||||
Py_XDECREF(pe->data);
|
||||
PyGILState_Release(gil);
|
||||
|
||||
PyEval_RestoreThread(pe->mainthr);
|
||||
Py_Finalize();
|
||||
pe->mainthr = NULL;
|
||||
}
|
||||
pe->fname = NULL;
|
||||
free(pe);
|
||||
@@ -257,6 +269,7 @@ void pythonmod_inform_super(struct module_qstate* qstate, int id, struct module_
|
||||
struct pythonmod_env* pe = (struct pythonmod_env*)qstate->env->modinfo[id];
|
||||
struct pythonmod_qstate* pq = (struct pythonmod_qstate*)qstate->minfo[id];
|
||||
PyObject* py_qstate, *py_sqstate, *res;
|
||||
PyGILState_STATE gil = PyGILState_Ensure();
|
||||
|
||||
log_query_info(VERB_ALGO, "pythonmod: inform_super, sub is", &qstate->qinfo);
|
||||
log_query_info(VERB_ALGO, "super is", &super->qinfo);
|
||||
@@ -264,7 +277,6 @@ void pythonmod_inform_super(struct module_qstate* qstate, int id, struct module_
|
||||
py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
|
||||
py_sqstate = SWIG_NewPointerObj((void*) super, SWIGTYPE_p_module_qstate, 0);
|
||||
|
||||
PyEval_AcquireLock();
|
||||
res = PyObject_CallFunction(pe->func_inform, "iOOO", id, py_qstate,
|
||||
py_sqstate, pq->data);
|
||||
|
||||
@@ -284,7 +296,7 @@ void pythonmod_inform_super(struct module_qstate* qstate, int id, struct module_
|
||||
Py_XDECREF(py_sqstate);
|
||||
Py_XDECREF(py_qstate);
|
||||
|
||||
PyEval_ReleaseLock();
|
||||
PyGILState_Release(gil);
|
||||
}
|
||||
|
||||
void pythonmod_operate(struct module_qstate* qstate, enum module_ev event,
|
||||
@@ -293,6 +305,7 @@ void pythonmod_operate(struct module_qstate* qstate, enum module_ev event,
|
||||
struct pythonmod_env* pe = (struct pythonmod_env*)qstate->env->modinfo[id];
|
||||
struct pythonmod_qstate* pq = (struct pythonmod_qstate*)qstate->minfo[id];
|
||||
PyObject* py_qstate, *res;
|
||||
PyGILState_STATE gil = PyGILState_Ensure();
|
||||
|
||||
if ( pq == NULL)
|
||||
{
|
||||
@@ -304,9 +317,6 @@ void pythonmod_operate(struct module_qstate* qstate, enum module_ev event,
|
||||
Py_INCREF(pq->data);
|
||||
}
|
||||
|
||||
/* Lock Python */
|
||||
PyEval_AcquireLock();
|
||||
|
||||
/* Call operate */
|
||||
py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
|
||||
res = PyObject_CallFunction(pe->func_operate, "iiOO", id, (int) event,
|
||||
@@ -325,8 +335,7 @@ void pythonmod_operate(struct module_qstate* qstate, enum module_ev event,
|
||||
Py_XDECREF(res);
|
||||
Py_XDECREF(py_qstate);
|
||||
|
||||
/* Unlock Python */
|
||||
PyEval_ReleaseLock();
|
||||
PyGILState_Release(gil);
|
||||
}
|
||||
|
||||
void pythonmod_clear(struct module_qstate* qstate, int id)
|
||||
@@ -340,7 +349,9 @@ void pythonmod_clear(struct module_qstate* qstate, int id)
|
||||
(unsigned long int)pq);
|
||||
if(pq != NULL)
|
||||
{
|
||||
PyGILState_STATE gil = PyGILState_Ensure();
|
||||
Py_DECREF(pq->data);
|
||||
PyGILState_Release(gil);
|
||||
/* Free qstate */
|
||||
free(pq);
|
||||
}
|
||||
@@ -367,7 +378,7 @@ static struct module_func_block pythonmod_block = {
|
||||
&pythonmod_clear, &pythonmod_get_mem
|
||||
};
|
||||
|
||||
struct module_func_block* pythonmod_get_funcblock()
|
||||
struct module_func_block* pythonmod_get_funcblock(void)
|
||||
{
|
||||
return &pythonmod_block;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
* Get the module function block.
|
||||
* @return: function block with function pointers to module methods.
|
||||
*/
|
||||
struct module_func_block* pythonmod_get_funcblock();
|
||||
struct module_func_block* pythonmod_get_funcblock(void);
|
||||
|
||||
/** python module init */
|
||||
int pythonmod_init(struct module_env* env, int id);
|
||||
|
||||
@@ -66,7 +66,7 @@ int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, st
|
||||
}
|
||||
|
||||
return dns_cache_store(qstate->env, qinfo, msgrep, is_referral,
|
||||
qstate->prefetch_leeway);
|
||||
qstate->prefetch_leeway, 0, NULL);
|
||||
}
|
||||
|
||||
/* Invalidate the message associated with query_info stored in message cache */
|
||||
|
||||
@@ -74,6 +74,7 @@ void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qin
|
||||
*
|
||||
* @param qstate: module environment
|
||||
* @param pkt: a ldns_buffer which contains ldns_packet data
|
||||
* @return 0 on failure, out of memory or parse error.
|
||||
*/
|
||||
int createResponse(struct module_qstate* qstate, ldns_buffer* pkt);
|
||||
|
||||
|
||||
Vendored
+92
-63
@@ -49,29 +49,64 @@
|
||||
#include "util/module.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/config_file.h"
|
||||
|
||||
/** store rrsets in the rrset cache.
|
||||
* @param env: module environment with caches.
|
||||
* @param rep: contains list of rrsets to store.
|
||||
* @param now: current time.
|
||||
* @param leeway: during prefetch how much leeway to update TTLs.
|
||||
* This makes rrsets (other than type NS) timeout sooner so they get
|
||||
* updated with a new full TTL.
|
||||
* Type NS does not get this, because it must not be refreshed from the
|
||||
* child domain, but keep counting down properly.
|
||||
* @param pside: if from parentside discovered NS, so that its NS is okay
|
||||
* in a prefetch situation to be updated (without becoming sticky).
|
||||
* @param qrep: update rrsets here if cache is better
|
||||
* @param region: for qrep allocs.
|
||||
*/
|
||||
static void
|
||||
store_rrsets(struct module_env* env, struct reply_info* rep, uint32_t now)
|
||||
store_rrsets(struct module_env* env, struct reply_info* rep, uint32_t now,
|
||||
uint32_t leeway, int pside, struct reply_info* qrep,
|
||||
struct regional* region)
|
||||
{
|
||||
size_t i;
|
||||
/* see if rrset already exists in cache, if not insert it. */
|
||||
for(i=0; i<rep->rrset_count; i++) {
|
||||
rep->ref[i].key = rep->rrsets[i];
|
||||
rep->ref[i].id = rep->rrsets[i]->id;
|
||||
if(rrset_cache_update(env->rrset_cache, &rep->ref[i],
|
||||
env->alloc, now)) /* it was in the cache */
|
||||
/* update ref if it was in the cache */
|
||||
switch(rrset_cache_update(env->rrset_cache, &rep->ref[i],
|
||||
env->alloc, now + ((ntohs(rep->ref[i].key->rk.type)==
|
||||
LDNS_RR_TYPE_NS && !pside)?0:leeway))) {
|
||||
case 0: /* ref unchanged, item inserted */
|
||||
break;
|
||||
case 2: /* ref updated, cache is superior */
|
||||
if(region) {
|
||||
struct ub_packed_rrset_key* ck;
|
||||
lock_rw_rdlock(&rep->ref[i].key->entry.lock);
|
||||
/* if deleted rrset, do not copy it */
|
||||
if(rep->ref[i].key->id == 0)
|
||||
ck = NULL;
|
||||
else ck = packed_rrset_copy_region(
|
||||
rep->ref[i].key, region, now);
|
||||
lock_rw_unlock(&rep->ref[i].key->entry.lock);
|
||||
if(ck) {
|
||||
/* use cached copy if memory allows */
|
||||
qrep->rrsets[i] = ck;
|
||||
}
|
||||
}
|
||||
/* no break: also copy key item */
|
||||
case 1: /* ref updated, item inserted */
|
||||
rep->rrsets[i] = rep->ref[i].key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
hashvalue_t hash, struct reply_info* rep, uint32_t leeway)
|
||||
hashvalue_t hash, struct reply_info* rep, uint32_t leeway, int pside,
|
||||
struct reply_info* qrep, struct regional* region)
|
||||
{
|
||||
struct msgreply_entry* e;
|
||||
uint32_t ttl = rep->ttl;
|
||||
@@ -82,9 +117,11 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
rep->ref[i].key = rep->rrsets[i];
|
||||
rep->ref[i].id = rep->rrsets[i]->id;
|
||||
}
|
||||
reply_info_sortref(rep);
|
||||
|
||||
/* there was a reply_info_sortref(rep) here but it seems to be
|
||||
* unnecessary, because the cache gets locked per rrset. */
|
||||
reply_info_set_ttls(rep, *env->now);
|
||||
store_rrsets(env, rep, *env->now+leeway);
|
||||
store_rrsets(env, rep, *env->now, leeway, pside, qrep, region);
|
||||
if(ttl == 0) {
|
||||
/* we do not store the message, but we did store the RRs,
|
||||
* which could be useful for delegation information */
|
||||
@@ -180,7 +217,7 @@ find_add_addrs(struct module_env* env, uint16_t qclass,
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0);
|
||||
if(akey) {
|
||||
if(!delegpt_add_rrset_A(dp, region, akey, 0, 0)) {
|
||||
if(!delegpt_add_rrset_A(dp, region, akey, 0)) {
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
@@ -198,7 +235,7 @@ find_add_addrs(struct module_env* env, uint16_t qclass,
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
|
||||
if(akey) {
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, akey, 0, 0)) {
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, akey, 0)) {
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
@@ -213,27 +250,6 @@ find_add_addrs(struct module_env* env, uint16_t qclass,
|
||||
lock_rw_unlock(&neg->entry.lock);
|
||||
}
|
||||
}
|
||||
/* see if we have parent-side-glue (dispreferred) */
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_A, qclass,
|
||||
PACKED_RRSET_PARENT_SIDE, now, 0);
|
||||
if(akey) {
|
||||
if(!delegpt_add_rrset_A(dp, region, akey, 1, 1)) {
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
}
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_AAAA, qclass,
|
||||
PACKED_RRSET_PARENT_SIDE, now, 0);
|
||||
if(akey) {
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, akey, 1, 1)) {
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -251,7 +267,7 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0);
|
||||
if(akey) {
|
||||
if(!delegpt_add_rrset_A(dp, region, akey, 0, 1)) {
|
||||
if(!delegpt_add_rrset_A(dp, region, akey, (int)ns->lame)) {
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
@@ -269,7 +285,7 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
|
||||
if(akey) {
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, akey, 0, 1)) {
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, akey, (int)ns->lame)) {
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
@@ -284,27 +300,6 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
|
||||
lock_rw_unlock(&neg->entry.lock);
|
||||
}
|
||||
}
|
||||
/* see if we have parent-side-glue (dispreferred) */
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_A, qclass,
|
||||
PACKED_RRSET_PARENT_SIDE, now, 0);
|
||||
if(akey) {
|
||||
if(!delegpt_add_rrset_A(dp, region, akey, 1, 1)) {
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
}
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_AAAA, qclass,
|
||||
PACKED_RRSET_PARENT_SIDE, now, 0);
|
||||
if(akey) {
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, akey, 1, 1)) {
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -420,7 +415,7 @@ dns_cache_find_delegation(struct module_env* env, uint8_t* qname,
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if(!delegpt_rrset_add_ns(dp, region, nskey))
|
||||
if(!delegpt_rrset_add_ns(dp, region, nskey, 0))
|
||||
log_err("find_delegation: addns out of memory");
|
||||
lock_rw_unlock(&nskey->entry.lock); /* first unlock before next lookup*/
|
||||
/* find and add DS/NSEC (if any) */
|
||||
@@ -459,22 +454,22 @@ gen_dns_msg(struct regional* region, struct query_info* q, size_t num)
|
||||
|
||||
/** generate dns_msg from cached message */
|
||||
static struct dns_msg*
|
||||
tomsg(struct module_env* env, struct msgreply_entry* e, struct reply_info* r,
|
||||
tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
|
||||
struct regional* region, uint32_t now, struct regional* scratch)
|
||||
{
|
||||
struct dns_msg* msg;
|
||||
size_t i;
|
||||
if(now > r->ttl)
|
||||
return NULL;
|
||||
msg = gen_dns_msg(region, &e->key, r->rrset_count);
|
||||
msg = gen_dns_msg(region, q, r->rrset_count);
|
||||
if(!msg)
|
||||
return NULL;
|
||||
msg->rep->flags = r->flags;
|
||||
msg->rep->qdcount = r->qdcount;
|
||||
msg->rep->ttl = r->ttl - now;
|
||||
if(r->prefetch_ttl - now > 0)
|
||||
if(r->prefetch_ttl > now)
|
||||
msg->rep->prefetch_ttl = r->prefetch_ttl - now;
|
||||
else msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(r->prefetch_ttl);
|
||||
else msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->security = r->security;
|
||||
msg->rep->an_numrrsets = r->an_numrrsets;
|
||||
msg->rep->ns_numrrsets = r->ns_numrrsets;
|
||||
@@ -648,7 +643,7 @@ dns_cache_lookup(struct module_env* env,
|
||||
if(e) {
|
||||
struct msgreply_entry* key = (struct msgreply_entry*)e->key;
|
||||
struct reply_info* data = (struct reply_info*)e->data;
|
||||
struct dns_msg* msg = tomsg(env, key, data, region, now,
|
||||
struct dns_msg* msg = tomsg(env, &key->key, data, region, now,
|
||||
scratch);
|
||||
if(msg) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
@@ -672,8 +667,10 @@ dns_cache_lookup(struct module_env* env,
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
}
|
||||
|
||||
/* see if we have CNAME for this domain */
|
||||
if( (rrset=rrset_cache_lookup(env->rrset_cache, qname, qnamelen,
|
||||
/* 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 &&
|
||||
(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) {
|
||||
@@ -710,12 +707,40 @@ dns_cache_lookup(struct module_env* env,
|
||||
}
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
}
|
||||
|
||||
/* stop downwards cache search on NXDOMAIN.
|
||||
* Empty nonterminals are NOERROR, so an NXDOMAIN for foo
|
||||
* means bla.foo also does not exist. The DNSSEC proofs are
|
||||
* the same. We search upwards for NXDOMAINs. */
|
||||
if(env->cfg->harden_below_nxdomain)
|
||||
while(!dname_is_root(k.qname)) {
|
||||
dname_remove_label(&k.qname, &k.qname_len);
|
||||
h = query_info_hash(&k);
|
||||
e = slabhash_lookup(env->msg_cache, h, &k, 0);
|
||||
if(e) {
|
||||
struct reply_info* data = (struct reply_info*)e->data;
|
||||
struct dns_msg* msg;
|
||||
if(FLAGS_GET_RCODE(data->flags) == LDNS_RCODE_NXDOMAIN
|
||||
&& data->security == sec_status_secure
|
||||
&& (msg=tomsg(env, &k, data, region, now, scratch))){
|
||||
lock_rw_unlock(&e->lock);
|
||||
msg->qinfo.qname=qname;
|
||||
msg->qinfo.qname_len=qnamelen;
|
||||
/* check that DNSSEC really works out */
|
||||
msg->rep->security = sec_status_unchecked;
|
||||
return msg;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
struct reply_info* msgrep, int is_referral, uint32_t leeway)
|
||||
struct reply_info* msgrep, int is_referral, uint32_t leeway, int pside,
|
||||
struct regional* region)
|
||||
{
|
||||
struct reply_info* rep = NULL;
|
||||
/* alloc, malloc properly (not in region, like msg is) */
|
||||
@@ -736,8 +761,11 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
ref.key = rep->rrsets[i];
|
||||
ref.id = rep->rrsets[i]->id;
|
||||
/*ignore ret: it was in the cache, ref updated */
|
||||
/* no leeway for typeNS */
|
||||
(void)rrset_cache_update(env->rrset_cache, &ref,
|
||||
env->alloc, *env->now + leeway);
|
||||
env->alloc, *env->now +
|
||||
((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS
|
||||
&& !pside) ? 0:leeway));
|
||||
}
|
||||
free(rep);
|
||||
return 1;
|
||||
@@ -758,7 +786,8 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
rep->flags |= (BIT_RA | BIT_QR);
|
||||
rep->flags &= ~(BIT_AA | BIT_CD);
|
||||
h = query_info_hash(&qinf);
|
||||
dns_cache_store_msg(env, &qinf, h, rep, leeway);
|
||||
dns_cache_store_msg(env, &qinf, h, rep, leeway, pside, msgrep,
|
||||
region);
|
||||
/* qname is used inside query_info_entrysetup, and set to
|
||||
* NULL. If it has not been used, free it. free(0) is safe. */
|
||||
free(qinf.qname);
|
||||
|
||||
Vendored
+14
-2
@@ -74,10 +74,16 @@ struct dns_msg {
|
||||
* It will store only the RRsets, not the message.
|
||||
* @param leeway: TTL value, if not 0, other rrsets are considered expired
|
||||
* that many seconds before actual TTL expiry.
|
||||
* @param pside: if true, information came from a server which was fetched
|
||||
* from the parentside of the zonecut. This means that the type NS
|
||||
* can be updated to full TTL even in prefetch situations.
|
||||
* @param region: region to allocate better entries from cache into.
|
||||
* (used when is_referral is false).
|
||||
* @return 0 on alloc error (out of memory).
|
||||
*/
|
||||
int dns_cache_store(struct module_env* env, struct query_info* qinf,
|
||||
struct reply_info* rep, int is_referral, uint32_t leeway);
|
||||
struct reply_info* rep, int is_referral, uint32_t leeway, int pside,
|
||||
struct regional* region);
|
||||
|
||||
/**
|
||||
* Store message in the cache. Stores in message cache and rrset cache.
|
||||
@@ -92,9 +98,15 @@ int dns_cache_store(struct module_env* env, struct query_info* qinf,
|
||||
* Adjusts the reply info TTLs to absolute time.
|
||||
* @param leeway: TTL value, if not 0, other rrsets are considered expired
|
||||
* that many seconds before actual TTL expiry.
|
||||
* @param pside: if true, information came from a server which was fetched
|
||||
* from the parentside of the zonecut. This means that the type NS
|
||||
* can be updated to full TTL even in prefetch situations.
|
||||
* @param qrep: message that can be altered with better rrs from cache.
|
||||
* @param region: to allocate into for qmsg.
|
||||
*/
|
||||
void dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
hashvalue_t hash, struct reply_info* rep, uint32_t leeway);
|
||||
hashvalue_t hash, struct reply_info* rep, uint32_t leeway, int pside,
|
||||
struct reply_info* qrep, struct regional* region);
|
||||
|
||||
/**
|
||||
* Find a delegation from the cache.
|
||||
|
||||
Vendored
+291
-332
@@ -39,6 +39,7 @@
|
||||
* This file contains the infrastructure cache.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <ldns/rr.h>
|
||||
#include "services/cache/infra.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/storage/lookup3.h"
|
||||
@@ -46,38 +47,55 @@
|
||||
#include "util/log.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/config_file.h"
|
||||
#include "iterator/iterator.h"
|
||||
|
||||
/** Timeout when only a single probe query per IP is allowed. */
|
||||
#define PROBE_MAXRTO 12000 /* in msec */
|
||||
|
||||
/** number of timeouts for a type when the domain can be blocked ;
|
||||
* even if another type has completely rtt maxed it, the different type
|
||||
* can do this number of packets (until those all timeout too) */
|
||||
#define TIMEOUT_COUNT_MAX 3
|
||||
|
||||
size_t
|
||||
infra_host_sizefunc(void* k, void* ATTR_UNUSED(d))
|
||||
infra_sizefunc(void* k, void* ATTR_UNUSED(d))
|
||||
{
|
||||
struct infra_host_key* key = (struct infra_host_key*)k;
|
||||
return sizeof(*key) + sizeof(struct infra_host_data)
|
||||
struct infra_key* key = (struct infra_key*)k;
|
||||
return sizeof(*key) + sizeof(struct infra_data) + key->namelen
|
||||
+ lock_get_mem(&key->entry.lock);
|
||||
}
|
||||
|
||||
int
|
||||
infra_host_compfunc(void* key1, void* key2)
|
||||
infra_compfunc(void* key1, void* key2)
|
||||
{
|
||||
struct infra_host_key* k1 = (struct infra_host_key*)key1;
|
||||
struct infra_host_key* k2 = (struct infra_host_key*)key2;
|
||||
return sockaddr_cmp(&k1->addr, k1->addrlen, &k2->addr, k2->addrlen);
|
||||
struct infra_key* k1 = (struct infra_key*)key1;
|
||||
struct infra_key* k2 = (struct infra_key*)key2;
|
||||
int r = sockaddr_cmp(&k1->addr, k1->addrlen, &k2->addr, k2->addrlen);
|
||||
if(r != 0)
|
||||
return r;
|
||||
if(k1->namelen != k2->namelen) {
|
||||
if(k1->namelen < k2->namelen)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
return query_dname_compare(k1->zonename, k2->zonename);
|
||||
}
|
||||
|
||||
void
|
||||
infra_host_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
|
||||
infra_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct infra_host_key* key = (struct infra_host_key*)k;
|
||||
struct infra_key* key = (struct infra_key*)k;
|
||||
if(!key)
|
||||
return;
|
||||
lock_rw_destroy(&key->entry.lock);
|
||||
free(key->zonename);
|
||||
free(key);
|
||||
}
|
||||
|
||||
void
|
||||
infra_host_deldatafunc(void* d, void* ATTR_UNUSED(arg))
|
||||
infra_deldatafunc(void* d, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct infra_host_data* data = (struct infra_host_data*)d;
|
||||
lruhash_delete(data->lameness);
|
||||
struct infra_data* data = (struct infra_data*)d;
|
||||
free(data);
|
||||
}
|
||||
|
||||
@@ -86,20 +104,16 @@ infra_create(struct config_file* cfg)
|
||||
{
|
||||
struct infra_cache* infra = (struct infra_cache*)calloc(1,
|
||||
sizeof(struct infra_cache));
|
||||
/* the size of the lameness tables are not counted */
|
||||
size_t maxmem = cfg->infra_cache_numhosts *
|
||||
(sizeof(struct infra_host_key)+sizeof(struct infra_host_data));
|
||||
size_t maxmem = cfg->infra_cache_numhosts * (sizeof(struct infra_key)+
|
||||
sizeof(struct infra_data)+INFRA_BYTES_NAME);
|
||||
infra->hosts = slabhash_create(cfg->infra_cache_slabs,
|
||||
INFRA_HOST_STARTSIZE, maxmem, &infra_host_sizefunc,
|
||||
&infra_host_compfunc, &infra_host_delkeyfunc,
|
||||
&infra_host_deldatafunc, NULL);
|
||||
INFRA_HOST_STARTSIZE, maxmem, &infra_sizefunc, &infra_compfunc,
|
||||
&infra_delkeyfunc, &infra_deldatafunc, NULL);
|
||||
if(!infra->hosts) {
|
||||
free(infra);
|
||||
return NULL;
|
||||
}
|
||||
infra->host_ttl = cfg->host_ttl;
|
||||
infra->lame_ttl = cfg->lame_ttl;
|
||||
infra->max_lame_size = cfg->infra_cache_lame_size;
|
||||
return infra;
|
||||
}
|
||||
|
||||
@@ -119,10 +133,8 @@ infra_adjust(struct infra_cache* infra, struct config_file* cfg)
|
||||
if(!infra)
|
||||
return infra_create(cfg);
|
||||
infra->host_ttl = cfg->host_ttl;
|
||||
infra->lame_ttl = cfg->lame_ttl;
|
||||
infra->max_lame_size = cfg->infra_cache_lame_size;
|
||||
maxmem = cfg->infra_cache_numhosts *
|
||||
(sizeof(struct infra_host_key)+sizeof(struct infra_host_data));
|
||||
maxmem = cfg->infra_cache_numhosts * (sizeof(struct infra_key)+
|
||||
sizeof(struct infra_data)+INFRA_BYTES_NAME);
|
||||
if(maxmem != slabhash_get_size(infra->hosts) ||
|
||||
cfg->infra_cache_slabs != infra->hosts->size) {
|
||||
infra_delete(infra);
|
||||
@@ -151,39 +163,47 @@ hash_addr(struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
return h;
|
||||
}
|
||||
|
||||
/** lookup version that does not check host ttl (you check it) */
|
||||
static struct lruhash_entry*
|
||||
infra_lookup_host_nottl(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int wr)
|
||||
/** calculate infra hash for a key */
|
||||
static hashvalue_t
|
||||
hash_infra(struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name)
|
||||
{
|
||||
struct infra_host_key k;
|
||||
return dname_query_hash(name, hash_addr(addr, addrlen));
|
||||
}
|
||||
|
||||
/** lookup version that does not check host ttl (you check it) */
|
||||
struct lruhash_entry*
|
||||
infra_lookup_nottl(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* name, size_t namelen, int wr)
|
||||
{
|
||||
struct infra_key k;
|
||||
k.addrlen = addrlen;
|
||||
memcpy(&k.addr, addr, addrlen);
|
||||
k.entry.hash = hash_addr(addr, addrlen);
|
||||
k.namelen = namelen;
|
||||
k.zonename = name;
|
||||
k.entry.hash = hash_infra(addr, addrlen, name);
|
||||
k.entry.key = (void*)&k;
|
||||
k.entry.data = NULL;
|
||||
return slabhash_lookup(infra->hosts, k.entry.hash, &k, wr);
|
||||
}
|
||||
|
||||
struct infra_host_data*
|
||||
infra_lookup_host(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int wr,
|
||||
uint32_t timenow, struct infra_host_key** key)
|
||||
/** init the data elements */
|
||||
static void
|
||||
data_entry_init(struct infra_cache* infra, struct lruhash_entry* e,
|
||||
uint32_t timenow)
|
||||
{
|
||||
struct infra_host_data* data;
|
||||
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
||||
addrlen, wr);
|
||||
*key = NULL;
|
||||
if(!e)
|
||||
return NULL;
|
||||
/* check TTL */
|
||||
data = (struct infra_host_data*)e->data;
|
||||
if(data->ttl < timenow) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
return NULL;
|
||||
}
|
||||
*key = (struct infra_host_key*)e->key;
|
||||
return data;
|
||||
struct infra_data* data = (struct infra_data*)e->data;
|
||||
data->ttl = timenow + infra->host_ttl;
|
||||
rtt_init(&data->rtt);
|
||||
data->edns_version = 0;
|
||||
data->edns_lame_known = 0;
|
||||
data->probedelay = 0;
|
||||
data->isdnsseclame = 0;
|
||||
data->rec_lame = 0;
|
||||
data->lame_type_A = 0;
|
||||
data->lame_other = 0;
|
||||
data->timeout_A = 0;
|
||||
data->timeout_AAAA = 0;
|
||||
data->timeout_other = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,246 +211,142 @@ infra_lookup_host(struct infra_cache* infra,
|
||||
* @param infra: infra structure with config parameters.
|
||||
* @param addr: host address.
|
||||
* @param addrlen: length of addr.
|
||||
* @param name: name of zone
|
||||
* @param namelen: length of name.
|
||||
* @param tm: time now.
|
||||
* @return: the new entry or NULL on malloc failure.
|
||||
*/
|
||||
static struct lruhash_entry*
|
||||
new_host_entry(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint32_t tm)
|
||||
new_entry(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* name, size_t namelen, uint32_t tm)
|
||||
{
|
||||
struct infra_host_data* data;
|
||||
struct infra_host_key* key = (struct infra_host_key*)malloc(
|
||||
sizeof(struct infra_host_key));
|
||||
struct infra_data* data;
|
||||
struct infra_key* key = (struct infra_key*)malloc(sizeof(*key));
|
||||
if(!key)
|
||||
return NULL;
|
||||
data = (struct infra_host_data*)malloc(
|
||||
sizeof(struct infra_host_data));
|
||||
data = (struct infra_data*)malloc(sizeof(struct infra_data));
|
||||
if(!data) {
|
||||
free(key);
|
||||
return NULL;
|
||||
}
|
||||
key->zonename = memdup(name, namelen);
|
||||
if(!key->zonename) {
|
||||
free(key);
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
key->namelen = namelen;
|
||||
lock_rw_init(&key->entry.lock);
|
||||
key->entry.hash = hash_addr(addr, addrlen);
|
||||
key->entry.hash = hash_infra(addr, addrlen, name);
|
||||
key->entry.key = (void*)key;
|
||||
key->entry.data = (void*)data;
|
||||
key->addrlen = addrlen;
|
||||
memcpy(&key->addr, addr, addrlen);
|
||||
data->ttl = tm + infra->host_ttl;
|
||||
data->lameness = NULL;
|
||||
data->edns_version = 0;
|
||||
data->edns_lame_known = 0;
|
||||
data->num_timeouts = 0;
|
||||
rtt_init(&data->rtt);
|
||||
data_entry_init(infra, &key->entry, tm);
|
||||
return &key->entry;
|
||||
}
|
||||
|
||||
int
|
||||
infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint32_t timenow, int* edns_vs,
|
||||
uint8_t* edns_lame_known, int* to)
|
||||
socklen_t addrlen, uint8_t* nm, size_t nmlen, uint32_t timenow,
|
||||
int* edns_vs, uint8_t* edns_lame_known, int* to)
|
||||
{
|
||||
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
||||
addrlen, 0);
|
||||
struct infra_host_data* data;
|
||||
if(e && ((struct infra_host_data*)e->data)->ttl < timenow) {
|
||||
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
|
||||
nm, nmlen, 0);
|
||||
struct infra_data* data;
|
||||
int wr = 0;
|
||||
if(e && ((struct infra_data*)e->data)->ttl < timenow) {
|
||||
/* it expired, try to reuse existing entry */
|
||||
int old = ((struct infra_data*)e->data)->rtt.rto;
|
||||
uint8_t tA = ((struct infra_data*)e->data)->timeout_A;
|
||||
uint8_t tAAAA = ((struct infra_data*)e->data)->timeout_AAAA;
|
||||
uint8_t tother = ((struct infra_data*)e->data)->timeout_other;
|
||||
lock_rw_unlock(&e->lock);
|
||||
e = infra_lookup_host_nottl(infra, addr, addrlen, 1);
|
||||
e = infra_lookup_nottl(infra, addr, addrlen, nm, nmlen, 1);
|
||||
if(e) {
|
||||
/* if its still there we have a writelock, init */
|
||||
/* re-initialise */
|
||||
data = (struct infra_host_data*)e->data;
|
||||
data->ttl = timenow + infra->host_ttl;
|
||||
rtt_init(&data->rtt);
|
||||
/* do not touch lameness, it may be valid still */
|
||||
data->edns_version = 0;
|
||||
data->edns_lame_known = 0;
|
||||
data_entry_init(infra, e, timenow);
|
||||
wr = 1;
|
||||
/* TOP_TIMEOUT remains on reuse */
|
||||
if(old >= USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
((struct infra_data*)e->data)->rtt.rto
|
||||
= USEFUL_SERVER_TOP_TIMEOUT;
|
||||
((struct infra_data*)e->data)->timeout_A = tA;
|
||||
((struct infra_data*)e->data)->timeout_AAAA = tAAAA;
|
||||
((struct infra_data*)e->data)->timeout_other = tother;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!e) {
|
||||
/* insert new entry */
|
||||
if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
|
||||
if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow)))
|
||||
return 0;
|
||||
data = (struct infra_host_data*)e->data;
|
||||
*to = rtt_timeout(&data->rtt);
|
||||
data = (struct infra_data*)e->data;
|
||||
*edns_vs = data->edns_version;
|
||||
*edns_lame_known = data->edns_lame_known;
|
||||
*to = rtt_timeout(&data->rtt);
|
||||
slabhash_insert(infra->hosts, e->hash, e, data, NULL);
|
||||
return 1;
|
||||
}
|
||||
/* use existing entry */
|
||||
data = (struct infra_host_data*)e->data;
|
||||
*to = rtt_timeout(&data->rtt);
|
||||
data = (struct infra_data*)e->data;
|
||||
*edns_vs = data->edns_version;
|
||||
*edns_lame_known = data->edns_lame_known;
|
||||
*to = rtt_timeout(&data->rtt);
|
||||
if(*to >= PROBE_MAXRTO && rtt_notimeout(&data->rtt)*4 <= *to) {
|
||||
/* delay other queries, this is the probe query */
|
||||
if(!wr) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
e = infra_lookup_nottl(infra, addr,addrlen,nm,nmlen, 1);
|
||||
if(!e) { /* flushed from cache real fast, no use to
|
||||
allocate just for the probedelay */
|
||||
return 1;
|
||||
}
|
||||
data = (struct infra_data*)e->data;
|
||||
}
|
||||
/* add 999 to round up the timeout value from msec to sec,
|
||||
* then add a whole second so it is certain that this probe
|
||||
* has timed out before the next is allowed */
|
||||
data->probedelay = timenow + ((*to)+1999)/1000;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** hash lameness key */
|
||||
static hashvalue_t
|
||||
hash_lameness(uint8_t* name)
|
||||
{
|
||||
return dname_query_hash(name, 0xab);
|
||||
}
|
||||
|
||||
int
|
||||
infra_lookup_lame(struct infra_host_data* host,
|
||||
uint8_t* name, size_t namelen, uint32_t timenow,
|
||||
int* dlame, int* rlame, int* alame, int* olame)
|
||||
infra_set_lame(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* nm, size_t nmlen, uint32_t timenow,
|
||||
int dnsseclame, int reclame, uint16_t qtype)
|
||||
{
|
||||
struct lruhash_entry* e;
|
||||
struct infra_lame_key k;
|
||||
struct infra_lame_data *d;
|
||||
if(!host->lameness)
|
||||
return 0;
|
||||
k.entry.hash = hash_lameness(name);
|
||||
k.zonename = name;
|
||||
k.namelen = namelen;
|
||||
k.entry.key = (void*)&k;
|
||||
k.entry.data = NULL;
|
||||
e = lruhash_lookup(host->lameness, k.entry.hash, &k, 0);
|
||||
if(!e)
|
||||
return 0;
|
||||
d = (struct infra_lame_data*)e->data;
|
||||
if(d->ttl < timenow) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 0;
|
||||
}
|
||||
*dlame = d->isdnsseclame;
|
||||
*rlame = d->rec_lame;
|
||||
*alame = d->lame_type_A;
|
||||
*olame = d->lame_other;
|
||||
lock_rw_unlock(&e->lock);
|
||||
return *dlame || *rlame || *alame || *olame;
|
||||
}
|
||||
|
||||
size_t
|
||||
infra_lame_sizefunc(void* k, void* ATTR_UNUSED(d))
|
||||
{
|
||||
struct infra_lame_key* key = (struct infra_lame_key*)k;
|
||||
return sizeof(*key) + sizeof(struct infra_lame_data)
|
||||
+ key->namelen + lock_get_mem(&key->entry.lock);
|
||||
}
|
||||
|
||||
int
|
||||
infra_lame_compfunc(void* key1, void* key2)
|
||||
{
|
||||
struct infra_lame_key* k1 = (struct infra_lame_key*)key1;
|
||||
struct infra_lame_key* k2 = (struct infra_lame_key*)key2;
|
||||
if(k1->namelen != k2->namelen) {
|
||||
if(k1->namelen < k2->namelen)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
return query_dname_compare(k1->zonename, k2->zonename);
|
||||
}
|
||||
|
||||
void
|
||||
infra_lame_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct infra_lame_key* key = (struct infra_lame_key*)k;
|
||||
if(!key)
|
||||
return;
|
||||
lock_rw_destroy(&key->entry.lock);
|
||||
free(key->zonename);
|
||||
free(key);
|
||||
}
|
||||
|
||||
void
|
||||
infra_lame_deldatafunc(void* d, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
if(!d)
|
||||
return;
|
||||
free(d);
|
||||
}
|
||||
|
||||
int
|
||||
infra_set_lame(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* name, size_t namelen, uint32_t timenow, int dnsseclame,
|
||||
int reclame, uint16_t qtype)
|
||||
{
|
||||
struct infra_host_data* data;
|
||||
struct infra_data* data;
|
||||
struct lruhash_entry* e;
|
||||
int needtoinsert = 0;
|
||||
struct infra_lame_key* k;
|
||||
struct infra_lame_data* d;
|
||||
/* allocate at start, easier cleanup (no locks held) */
|
||||
k = (struct infra_lame_key*)malloc(sizeof(*k));
|
||||
if(!k) {
|
||||
log_err("set_lame: malloc failure");
|
||||
return 0;
|
||||
}
|
||||
d = (struct infra_lame_data*)malloc(sizeof(*d));
|
||||
if(!d) {
|
||||
free(k);
|
||||
log_err("set_lame: malloc failure");
|
||||
return 0;
|
||||
}
|
||||
k->zonename = memdup(name, namelen);
|
||||
if(!k->zonename) {
|
||||
free(d);
|
||||
free(k);
|
||||
log_err("set_lame: malloc failure");
|
||||
return 0;
|
||||
}
|
||||
lock_rw_init(&k->entry.lock);
|
||||
k->entry.hash = hash_lameness(name);
|
||||
k->entry.key = (void*)k;
|
||||
k->entry.data = (void*)d;
|
||||
d->ttl = timenow + infra->lame_ttl;
|
||||
d->isdnsseclame = dnsseclame;
|
||||
d->rec_lame = reclame;
|
||||
d->lame_type_A = (!dnsseclame && !reclame && qtype == LDNS_RR_TYPE_A);
|
||||
d->lame_other = (!dnsseclame && !reclame && qtype != LDNS_RR_TYPE_A);
|
||||
k->namelen = namelen;
|
||||
e = infra_lookup_host_nottl(infra, addr, addrlen, 1);
|
||||
e = infra_lookup_nottl(infra, addr, addrlen, nm, nmlen, 1);
|
||||
if(!e) {
|
||||
/* insert it */
|
||||
if(!(e = new_host_entry(infra, addr, addrlen, timenow))) {
|
||||
free(k->zonename);
|
||||
free(k);
|
||||
free(d);
|
||||
if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow))) {
|
||||
log_err("set_lame: malloc failure");
|
||||
return 0;
|
||||
}
|
||||
needtoinsert = 1;
|
||||
} else if( ((struct infra_data*)e->data)->ttl < timenow) {
|
||||
/* expired, reuse existing entry */
|
||||
data_entry_init(infra, e, timenow);
|
||||
}
|
||||
/* got an entry, now set the zone lame */
|
||||
data = (struct infra_host_data*)e->data;
|
||||
if(!data->lameness) {
|
||||
/* create hash table if not there already */
|
||||
data->lameness = lruhash_create(INFRA_LAME_STARTSIZE,
|
||||
infra->max_lame_size, infra_lame_sizefunc,
|
||||
infra_lame_compfunc, infra_lame_delkeyfunc,
|
||||
infra_lame_deldatafunc, NULL);
|
||||
if(!data->lameness) {
|
||||
log_err("set_lame: malloc failure");
|
||||
if(needtoinsert) slabhash_insert(infra->hosts,
|
||||
e->hash, e, e->data, NULL);
|
||||
else { lock_rw_unlock(&e->lock); }
|
||||
free(k->zonename);
|
||||
free(k);
|
||||
free(d);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* lookup existing lameness entry (if any) and merge data */
|
||||
int dlame, rlame, alame, olame;
|
||||
if(infra_lookup_lame(data, name, namelen, timenow,
|
||||
&dlame, &rlame, &alame, &olame)) {
|
||||
/* merge data into new structure */
|
||||
if(dlame) d->isdnsseclame = 1;
|
||||
if(rlame) d->rec_lame = 1;
|
||||
if(alame) d->lame_type_A = 1;
|
||||
if(olame) d->lame_other = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* inserts new entry, or updates TTL of older entry */
|
||||
lruhash_insert(data->lameness, k->entry.hash, &k->entry, d, NULL);
|
||||
|
||||
data = (struct infra_data*)e->data;
|
||||
/* merge data (if any) */
|
||||
if(dnsseclame)
|
||||
data->isdnsseclame = 1;
|
||||
if(reclame)
|
||||
data->rec_lame = 1;
|
||||
if(!dnsseclame && !reclame && qtype == LDNS_RR_TYPE_A)
|
||||
data->lame_type_A = 1;
|
||||
if(!dnsseclame && !reclame && qtype != LDNS_RR_TYPE_A)
|
||||
data->lame_other = 1;
|
||||
/* done */
|
||||
if(needtoinsert)
|
||||
slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
|
||||
else { lock_rw_unlock(&e->lock); }
|
||||
@@ -439,46 +355,66 @@ infra_set_lame(struct infra_cache* infra,
|
||||
|
||||
void
|
||||
infra_update_tcp_works(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* nm,
|
||||
size_t nmlen)
|
||||
{
|
||||
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
||||
addrlen, 1);
|
||||
struct infra_host_data* data;
|
||||
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
|
||||
nm, nmlen, 1);
|
||||
struct infra_data* data;
|
||||
if(!e)
|
||||
return; /* doesn't exist */
|
||||
data = (struct infra_host_data*)e->data;
|
||||
data = (struct infra_data*)e->data;
|
||||
if(data->rtt.rto >= RTT_MAX_TIMEOUT)
|
||||
/* do not disqualify this server altogether, it is better
|
||||
* than nothing */
|
||||
data->rtt.rto = RTT_MAX_TIMEOUT-1;
|
||||
data->rtt.rto = RTT_MAX_TIMEOUT-1000;
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
|
||||
int
|
||||
infra_rtt_update(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
int roundtrip, int orig_rtt, uint32_t timenow)
|
||||
infra_rtt_update(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* nm, size_t nmlen, int qtype,
|
||||
int roundtrip, int orig_rtt, uint32_t timenow)
|
||||
{
|
||||
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
||||
addrlen, 1);
|
||||
struct infra_host_data* data;
|
||||
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
|
||||
nm, nmlen, 1);
|
||||
struct infra_data* data;
|
||||
int needtoinsert = 0;
|
||||
int rto = 1;
|
||||
if(!e) {
|
||||
if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
|
||||
if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow)))
|
||||
return 0;
|
||||
needtoinsert = 1;
|
||||
} else if(((struct infra_data*)e->data)->ttl < timenow) {
|
||||
data_entry_init(infra, e, timenow);
|
||||
}
|
||||
/* have an entry, update the rtt, and the ttl */
|
||||
data = (struct infra_host_data*)e->data;
|
||||
data->ttl = timenow + infra->host_ttl;
|
||||
/* have an entry, update the rtt */
|
||||
data = (struct infra_data*)e->data;
|
||||
if(roundtrip == -1) {
|
||||
rtt_lost(&data->rtt, orig_rtt);
|
||||
if(data->num_timeouts<255)
|
||||
data->num_timeouts++;
|
||||
if(qtype == LDNS_RR_TYPE_A) {
|
||||
if(data->timeout_A < TIMEOUT_COUNT_MAX)
|
||||
data->timeout_A++;
|
||||
} else if(qtype == LDNS_RR_TYPE_AAAA) {
|
||||
if(data->timeout_AAAA < TIMEOUT_COUNT_MAX)
|
||||
data->timeout_AAAA++;
|
||||
} else {
|
||||
if(data->timeout_other < TIMEOUT_COUNT_MAX)
|
||||
data->timeout_other++;
|
||||
}
|
||||
} else {
|
||||
/* if we got a reply, but the old timeout was above server
|
||||
* selection height, delete the timeout so the server is
|
||||
* fully available again */
|
||||
if(rtt_unclamped(&data->rtt) >= USEFUL_SERVER_TOP_TIMEOUT)
|
||||
rtt_init(&data->rtt);
|
||||
rtt_update(&data->rtt, roundtrip);
|
||||
data->num_timeouts = 0;
|
||||
data->probedelay = 0;
|
||||
if(qtype == LDNS_RR_TYPE_A)
|
||||
data->timeout_A = 0;
|
||||
else if(qtype == LDNS_RR_TYPE_AAAA)
|
||||
data->timeout_AAAA = 0;
|
||||
else data->timeout_other = 0;
|
||||
}
|
||||
if(data->rtt.rto > 0)
|
||||
rto = data->rtt.rto;
|
||||
@@ -489,25 +425,55 @@ infra_rtt_update(struct infra_cache* infra,
|
||||
return rto;
|
||||
}
|
||||
|
||||
int
|
||||
infra_edns_update(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
int edns_version, uint32_t timenow)
|
||||
int infra_get_host_rto(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* nm,
|
||||
size_t nmlen, struct rtt_info* rtt, int* delay, uint32_t timenow,
|
||||
int* tA, int* tAAAA, int* tother)
|
||||
{
|
||||
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
||||
addrlen, 1);
|
||||
struct infra_host_data* data;
|
||||
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
|
||||
nm, nmlen, 0);
|
||||
struct infra_data* data;
|
||||
int ttl = -2;
|
||||
if(!e) return -1;
|
||||
data = (struct infra_data*)e->data;
|
||||
if(data->ttl >= timenow) {
|
||||
ttl = (int)(data->ttl - timenow);
|
||||
memmove(rtt, &data->rtt, sizeof(*rtt));
|
||||
if(timenow < data->probedelay)
|
||||
*delay = (int)(data->probedelay - timenow);
|
||||
else *delay = 0;
|
||||
}
|
||||
*tA = (int)data->timeout_A;
|
||||
*tAAAA = (int)data->timeout_AAAA;
|
||||
*tother = (int)data->timeout_other;
|
||||
lock_rw_unlock(&e->lock);
|
||||
return ttl;
|
||||
}
|
||||
|
||||
int
|
||||
infra_edns_update(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* nm, size_t nmlen, int edns_version,
|
||||
uint32_t timenow)
|
||||
{
|
||||
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
|
||||
nm, nmlen, 1);
|
||||
struct infra_data* data;
|
||||
int needtoinsert = 0;
|
||||
if(!e) {
|
||||
if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
|
||||
if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow)))
|
||||
return 0;
|
||||
needtoinsert = 1;
|
||||
} else if(((struct infra_data*)e->data)->ttl < timenow) {
|
||||
data_entry_init(infra, e, timenow);
|
||||
}
|
||||
/* have an entry, update the rtt, and the ttl */
|
||||
data = (struct infra_host_data*)e->data;
|
||||
data->ttl = timenow + infra->host_ttl;
|
||||
data->edns_version = edns_version;
|
||||
data->edns_lame_known = 1;
|
||||
data = (struct infra_data*)e->data;
|
||||
/* do not update if noEDNS and stored is yesEDNS */
|
||||
if(!(edns_version == -1 && (data->edns_version != -1 &&
|
||||
data->edns_lame_known))) {
|
||||
data->edns_version = edns_version;
|
||||
data->edns_lame_known = 1;
|
||||
}
|
||||
|
||||
if(needtoinsert)
|
||||
slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
|
||||
@@ -515,96 +481,89 @@ infra_edns_update(struct infra_cache* infra,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
infra_get_lame_rtt(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* name, size_t namelen, uint16_t qtype,
|
||||
int* lame, int* dnsseclame, int* reclame, int* rtt, int* lost,
|
||||
uint32_t timenow)
|
||||
int* lame, int* dnsseclame, int* reclame, int* rtt, uint32_t timenow)
|
||||
{
|
||||
struct infra_host_data* host;
|
||||
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
||||
addrlen, 0);
|
||||
int dlm, rlm, alm, olm;
|
||||
struct infra_data* host;
|
||||
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
|
||||
name, namelen, 0);
|
||||
if(!e)
|
||||
return 0;
|
||||
host = (struct infra_host_data*)e->data;
|
||||
host = (struct infra_data*)e->data;
|
||||
*rtt = rtt_unclamped(&host->rtt);
|
||||
*lost = (int)host->num_timeouts;
|
||||
/* check lameness first, if so, ttl on host does not matter anymore */
|
||||
if(infra_lookup_lame(host, name, namelen, timenow,
|
||||
&dlm, &rlm, &alm, &olm)) {
|
||||
if(alm && qtype == LDNS_RR_TYPE_A) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*lame = 1;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 0;
|
||||
return 1;
|
||||
} else if(olm && qtype != LDNS_RR_TYPE_A) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*lame = 1;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 0;
|
||||
return 1;
|
||||
} else if(dlm) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*lame = 0;
|
||||
*dnsseclame = 1;
|
||||
*reclame = 0;
|
||||
return 1;
|
||||
} else if(rlm) {
|
||||
if(host->rtt.rto >= PROBE_MAXRTO && timenow < host->probedelay
|
||||
&& rtt_notimeout(&host->rtt)*4 <= host->rtt.rto) {
|
||||
/* single probe for this domain, and we are not probing */
|
||||
/* unless the query type allows a probe to happen */
|
||||
if(qtype == LDNS_RR_TYPE_A) {
|
||||
if(host->timeout_A >= TIMEOUT_COUNT_MAX)
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
|
||||
else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
||||
} else if(qtype == LDNS_RR_TYPE_AAAA) {
|
||||
if(host->timeout_AAAA >= TIMEOUT_COUNT_MAX)
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
|
||||
else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
||||
} else {
|
||||
if(host->timeout_other >= TIMEOUT_COUNT_MAX)
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
|
||||
else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
||||
}
|
||||
}
|
||||
if(timenow > host->ttl) {
|
||||
/* expired entry */
|
||||
/* see if this can be a re-probe of an unresponsive server */
|
||||
/* minus 1000 because that is outside of the RTTBAND, so
|
||||
* blacklisted servers stay blacklisted if this is chosen */
|
||||
if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
||||
*lame = 0;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 1;
|
||||
*reclame = 0;
|
||||
return 1;
|
||||
}
|
||||
/* no lameness for this type of query */
|
||||
}
|
||||
*lame = 0;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 0;
|
||||
if(timenow > host->ttl) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 0;
|
||||
}
|
||||
/* check lameness first */
|
||||
if(host->lame_type_A && qtype == LDNS_RR_TYPE_A) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*lame = 1;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 0;
|
||||
return 1;
|
||||
} else if(host->lame_other && qtype != LDNS_RR_TYPE_A) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*lame = 1;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 0;
|
||||
return 1;
|
||||
} else if(host->isdnsseclame) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*lame = 0;
|
||||
*dnsseclame = 1;
|
||||
*reclame = 0;
|
||||
return 1;
|
||||
} else if(host->rec_lame) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*lame = 0;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 1;
|
||||
return 1;
|
||||
}
|
||||
/* no lameness for this type of query */
|
||||
lock_rw_unlock(&e->lock);
|
||||
*lame = 0;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** helper memory count for a host lame cache */
|
||||
static size_t
|
||||
count_host_lame(struct lruhash_entry* e)
|
||||
{
|
||||
struct infra_host_data* host_data = (struct infra_host_data*)e->data;
|
||||
if(!host_data->lameness)
|
||||
return 0;
|
||||
return lruhash_get_mem(host_data->lameness);
|
||||
}
|
||||
|
||||
size_t
|
||||
infra_get_mem(struct infra_cache* infra)
|
||||
{
|
||||
size_t i, bin;
|
||||
size_t s = sizeof(*infra) +
|
||||
slabhash_get_mem(infra->hosts);
|
||||
struct lruhash_entry* e;
|
||||
for(i=0; i<infra->hosts->size; i++) {
|
||||
lock_quick_lock(&infra->hosts->array[i]->lock);
|
||||
for(bin=0; bin<infra->hosts->array[i]->size; bin++) {
|
||||
lock_quick_lock(&infra->hosts->array[i]->
|
||||
array[bin].lock);
|
||||
/* count data size in bin items. */
|
||||
for(e = infra->hosts->array[i]->array[bin].
|
||||
overflow_list; e; e = e->overflow_next) {
|
||||
lock_rw_rdlock(&e->lock);
|
||||
s += count_host_lame(e);
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
lock_quick_unlock(&infra->hosts->array[i]->
|
||||
array[bin].lock);
|
||||
}
|
||||
lock_quick_unlock(&infra->hosts->array[i]->lock);
|
||||
}
|
||||
return s;
|
||||
return sizeof(*infra) + slabhash_get_mem(infra->hosts);
|
||||
}
|
||||
|
||||
Vendored
+80
-90
@@ -47,65 +47,57 @@ struct slabhash;
|
||||
struct config_file;
|
||||
|
||||
/**
|
||||
* Host information kept for every server.
|
||||
* Host information kept for every server, per zone.
|
||||
*/
|
||||
struct infra_host_key {
|
||||
struct infra_key {
|
||||
/** the host address. */
|
||||
struct sockaddr_storage addr;
|
||||
/** length of addr. */
|
||||
socklen_t addrlen;
|
||||
/** hash table entry, data of type infra_host_data. */
|
||||
/** zone name in wireformat */
|
||||
uint8_t* zonename;
|
||||
/** length of zonename */
|
||||
size_t namelen;
|
||||
/** hash table entry, data of type infra_data. */
|
||||
struct lruhash_entry entry;
|
||||
};
|
||||
|
||||
/**
|
||||
* Host information encompasses host capabilities and retransmission timeouts.
|
||||
* And lameness information (notAuthoritative, noEDNS, Recursive)
|
||||
*/
|
||||
struct infra_host_data {
|
||||
struct infra_data {
|
||||
/** TTL value for this entry. absolute time. */
|
||||
uint32_t ttl;
|
||||
|
||||
/** time in seconds (absolute) when probing re-commences, 0 disabled */
|
||||
uint32_t probedelay;
|
||||
/** round trip times for timeout calculation */
|
||||
struct rtt_info rtt;
|
||||
/** Names of the zones that are lame. NULL=no lame zones. */
|
||||
struct lruhash* lameness;
|
||||
|
||||
/** edns version that the host supports, -1 means no EDNS */
|
||||
int edns_version;
|
||||
/** if the EDNS lameness is already known or not.
|
||||
* EDNS lame is when EDNS queries or replies are dropped,
|
||||
* and cause a timeout */
|
||||
uint8_t edns_lame_known;
|
||||
/** Number of consequtive timeouts; reset when reply arrives OK. */
|
||||
uint8_t num_timeouts;
|
||||
};
|
||||
|
||||
/**
|
||||
* Lameness information, per host, per zone.
|
||||
*/
|
||||
struct infra_lame_key {
|
||||
/** key is zone name in wireformat */
|
||||
uint8_t* zonename;
|
||||
/** length of zonename */
|
||||
size_t namelen;
|
||||
/** lruhash entry */
|
||||
struct lruhash_entry entry;
|
||||
};
|
||||
|
||||
/**
|
||||
* Lameness information. Expires.
|
||||
* This host is lame because it is in the cache.
|
||||
*/
|
||||
struct infra_lame_data {
|
||||
/** TTL of this entry. absolute time. */
|
||||
uint32_t ttl;
|
||||
/** is the host lame (does not serve the zone authoritatively),
|
||||
* or is the host dnssec lame (does not serve DNSSEC data) */
|
||||
int isdnsseclame;
|
||||
uint8_t isdnsseclame;
|
||||
/** is the host recursion lame (not AA, but RA) */
|
||||
int rec_lame;
|
||||
uint8_t rec_lame;
|
||||
/** the host is lame (not authoritative) for A records */
|
||||
int lame_type_A;
|
||||
uint8_t lame_type_A;
|
||||
/** the host is lame (not authoritative) for other query types */
|
||||
int lame_other;
|
||||
uint8_t lame_other;
|
||||
|
||||
/** timeouts counter for type A */
|
||||
uint8_t timeout_A;
|
||||
/** timeouts counter for type AAAA */
|
||||
uint8_t timeout_AAAA;
|
||||
/** timeouts counter for others */
|
||||
uint8_t timeout_other;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -116,16 +108,12 @@ struct infra_cache {
|
||||
struct slabhash* hosts;
|
||||
/** TTL value for host information, in seconds */
|
||||
int host_ttl;
|
||||
/** TTL for Lameness information, in seconds */
|
||||
int lame_ttl;
|
||||
/** infra lame cache max memory per host, in bytes */
|
||||
size_t max_lame_size;
|
||||
};
|
||||
|
||||
/** infra host cache default hash lookup size */
|
||||
#define INFRA_HOST_STARTSIZE 32
|
||||
/** infra lame cache default hash lookup size */
|
||||
#define INFRA_LAME_STARTSIZE 2
|
||||
/** bytes per zonename reserved in the hostcache, dnamelen(zonename.com.) */
|
||||
#define INFRA_BYTES_NAME 14
|
||||
|
||||
/**
|
||||
* Create infra cache.
|
||||
@@ -152,26 +140,30 @@ struct infra_cache* infra_adjust(struct infra_cache* infra,
|
||||
struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Lookup host data
|
||||
* Plain find infra data function (used by the the other functions)
|
||||
* @param infra: infrastructure cache.
|
||||
* @param addr: host address.
|
||||
* @param addrlen: length of addr.
|
||||
* @param wr: set to true to get a writelock on the entry.
|
||||
* @param timenow: what time it is now.
|
||||
* @param key: the key for the host, returned so caller can unlock when done.
|
||||
* @return: host data or NULL if not found or expired.
|
||||
* @param name: domain name of zone.
|
||||
* @param namelen: length of domain name.
|
||||
* @param wr: if true, writelock, else readlock.
|
||||
* @return the entry, could be expired (this is not checked) or NULL.
|
||||
*/
|
||||
struct infra_host_data* infra_lookup_host(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int wr,
|
||||
uint32_t timenow, struct infra_host_key** key);
|
||||
struct lruhash_entry* infra_lookup_nottl(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name,
|
||||
size_t namelen, int wr);
|
||||
|
||||
/**
|
||||
* Find host information to send a packet. Creates new entry if not found.
|
||||
* Lameness is empty. EDNS is 0 (try with first), and rtt is returned for
|
||||
* the first message to it.
|
||||
* Use this to send a packet only, because it also locks out others when
|
||||
* probing is restricted.
|
||||
* @param infra: infrastructure cache.
|
||||
* @param addr: host address.
|
||||
* @param addrlen: length of addr.
|
||||
* @param name: domain name of zone.
|
||||
* @param namelen: length of domain name.
|
||||
* @param timenow: what time it is now.
|
||||
* @param edns_vs: edns version it supports, is returned.
|
||||
* @param edns_lame_known: if EDNS lame (EDNS is dropped in transit) has
|
||||
@@ -180,25 +172,8 @@ struct infra_host_data* infra_lookup_host(struct infra_cache* infra,
|
||||
* @return: 0 on error.
|
||||
*/
|
||||
int infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint32_t timenow, int* edns_vs,
|
||||
uint8_t* edns_lame_known, int* to);
|
||||
|
||||
/**
|
||||
* Check for lameness of this server for a particular zone.
|
||||
* You must have a lock on the host structure.
|
||||
* @param host: infrastructure cache data for the host. Caller holds lock.
|
||||
* @param name: domain name of zone apex.
|
||||
* @param namelen: length of domain name.
|
||||
* @param timenow: what time it is now.
|
||||
* @param dlame: if the function returns true, is set true if dnssec lame.
|
||||
* @param rlame: if the function returns true, is set true if recursion lame.
|
||||
* @param alame: if the function returns true, is set true if qtype A lame.
|
||||
* @param olame: if the function returns true, is set true if qtype other lame.
|
||||
* @return: 0 if not lame or unknown or timed out, 1 if lame
|
||||
*/
|
||||
int infra_lookup_lame(struct infra_host_data* host,
|
||||
uint8_t* name, size_t namelen, uint32_t timenow,
|
||||
int* dlame, int* rlame, int* alame, int* olame);
|
||||
socklen_t addrlen, uint8_t* name, size_t namelen,
|
||||
uint32_t timenow, int* edns_vs, uint8_t* edns_lame_known, int* to);
|
||||
|
||||
/**
|
||||
* Set a host to be lame for the given zone.
|
||||
@@ -225,6 +200,9 @@ int infra_set_lame(struct infra_cache* infra,
|
||||
* @param infra: infrastructure cache.
|
||||
* @param addr: host address.
|
||||
* @param addrlen: length of addr.
|
||||
* @param name: zone name
|
||||
* @param namelen: zone name length
|
||||
* @param qtype: query type.
|
||||
* @param roundtrip: estimate of roundtrip time in milliseconds or -1 for
|
||||
* timeout.
|
||||
* @param orig_rtt: original rtt for the query that timed out (roundtrip==-1).
|
||||
@@ -232,8 +210,8 @@ int infra_set_lame(struct infra_cache* infra,
|
||||
* @param timenow: what time it is now.
|
||||
* @return: 0 on error. new rto otherwise.
|
||||
*/
|
||||
int infra_rtt_update(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
int infra_rtt_update(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* name, size_t namelen, int qtype,
|
||||
int roundtrip, int orig_rtt, uint32_t timenow);
|
||||
|
||||
/**
|
||||
@@ -241,25 +219,32 @@ int infra_rtt_update(struct infra_cache* infra,
|
||||
* @param infra: infrastructure cache.
|
||||
* @param addr: host address.
|
||||
* @param addrlen: length of addr.
|
||||
* @param name: name of zone
|
||||
* @param namelen: length of name
|
||||
*/
|
||||
void infra_update_tcp_works(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen);
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* name, size_t namelen);
|
||||
|
||||
/**
|
||||
* Update edns information for the host.
|
||||
* @param infra: infrastructure cache.
|
||||
* @param addr: host address.
|
||||
* @param addrlen: length of addr.
|
||||
* @param name: name of zone
|
||||
* @param namelen: length of name
|
||||
* @param edns_version: the version that it publishes.
|
||||
* If it is known to support EDNS then no-EDNS is not stored over it.
|
||||
* @param timenow: what time it is now.
|
||||
* @return: 0 on error.
|
||||
*/
|
||||
int infra_edns_update(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
int edns_version, uint32_t timenow);
|
||||
uint8_t* name, size_t namelen, int edns_version, uint32_t timenow);
|
||||
|
||||
/**
|
||||
* Get Lameness information and average RTT if host is in the cache.
|
||||
* This information is to be used for server selection.
|
||||
* @param infra: infrastructure cache.
|
||||
* @param addr: host address.
|
||||
* @param addrlen: length of addr.
|
||||
@@ -272,16 +257,34 @@ int infra_edns_update(struct infra_cache* infra,
|
||||
* @param reclame: if function returns true, this is if it is recursion lame.
|
||||
* @param rtt: if function returns true, this returns avg rtt of the server.
|
||||
* The rtt value is unclamped and reflects recent timeouts.
|
||||
* @param lost: number of queries lost in a row. Reset to 0 when an answer
|
||||
* gets back. Gives a connectivity number.
|
||||
* @param timenow: what time it is now.
|
||||
* @return if found in cache, or false if not (or TTL bad).
|
||||
*/
|
||||
int infra_get_lame_rtt(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* name, size_t namelen, uint16_t qtype,
|
||||
int* lame, int* dnsseclame, int* reclame, int* rtt, int* lost,
|
||||
uint32_t timenow);
|
||||
int* lame, int* dnsseclame, int* reclame, int* rtt, uint32_t timenow);
|
||||
|
||||
/**
|
||||
* Get additional (debug) info on timing.
|
||||
* @param infra: infra cache.
|
||||
* @param addr: host address.
|
||||
* @param addrlen: length of addr.
|
||||
* @param name: zone name
|
||||
* @param namelen: zone name length
|
||||
* @param rtt: the rtt_info is copied into here (caller alloced return struct).
|
||||
* @param delay: probe delay (if any).
|
||||
* @param timenow: what time it is now.
|
||||
* @param tA: timeout counter on type A.
|
||||
* @param tAAAA: timeout counter on type AAAA.
|
||||
* @param tother: timeout counter on type other.
|
||||
* @return TTL the infra host element is valid for. If -1: not found in cache.
|
||||
* TTL -2: found but expired.
|
||||
*/
|
||||
int infra_get_host_rto(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name,
|
||||
size_t namelen, struct rtt_info* rtt, int* delay, uint32_t timenow,
|
||||
int* tA, int* tAAAA, int* tother);
|
||||
|
||||
/**
|
||||
* Get memory used by the infra cache.
|
||||
@@ -292,28 +295,15 @@ size_t infra_get_mem(struct infra_cache* infra);
|
||||
|
||||
/** calculate size for the hashtable, does not count size of lameness,
|
||||
* so the hashtable is a fixed number of items */
|
||||
size_t infra_host_sizefunc(void* k, void* d);
|
||||
size_t infra_sizefunc(void* k, void* d);
|
||||
|
||||
/** compare two addresses, returns -1, 0, or +1 */
|
||||
int infra_host_compfunc(void* key1, void* key2);
|
||||
int infra_compfunc(void* key1, void* key2);
|
||||
|
||||
/** delete key, and destroy the lock */
|
||||
void infra_host_delkeyfunc(void* k, void* arg);
|
||||
void infra_delkeyfunc(void* k, void* arg);
|
||||
|
||||
/** delete data and destroy the lameness hashtable */
|
||||
void infra_host_deldatafunc(void* d, void* arg);
|
||||
|
||||
/** calculate size, which is fixed, zonename does not count so that
|
||||
* a fixed number of items is stored */
|
||||
size_t infra_lame_sizefunc(void* k, void* d);
|
||||
|
||||
/** compare zone names, returns -1, 0, +1 */
|
||||
int infra_lame_compfunc(void* key1, void* key2);
|
||||
|
||||
/** free key, lock and zonename */
|
||||
void infra_lame_delkeyfunc(void* k, void* arg);
|
||||
|
||||
/** free the lameness data */
|
||||
void infra_lame_deldatafunc(void* d, void* arg);
|
||||
void infra_deldatafunc(void* d, void* arg);
|
||||
|
||||
#endif /* SERVICES_CACHE_INFRA_H */
|
||||
|
||||
Vendored
+28
-9
@@ -120,7 +120,7 @@ rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key,
|
||||
|
||||
/** see if rrset needs to be updated in the cache */
|
||||
static int
|
||||
need_to_update_rrset(void* nd, void* cd, uint32_t timenow, int equal)
|
||||
need_to_update_rrset(void* nd, void* cd, uint32_t timenow, int equal, int ns)
|
||||
{
|
||||
struct packed_rrset_data* newd = (struct packed_rrset_data*)nd;
|
||||
struct packed_rrset_data* cached = (struct packed_rrset_data*)cd;
|
||||
@@ -145,10 +145,22 @@ need_to_update_rrset(void* nd, void* cd, uint32_t timenow, int equal)
|
||||
/* o item in cache has expired */
|
||||
if( cached->ttl < timenow )
|
||||
return 1;
|
||||
/* o same trust, but different in data - insert it */
|
||||
if( newd->trust == cached->trust && !equal )
|
||||
return 1;
|
||||
return 0;
|
||||
/* o same trust, but different in data - insert it */
|
||||
if( newd->trust == cached->trust && !equal ) {
|
||||
/* if this is type NS, do not 'stick' to owner that changes
|
||||
* the NS RRset, but use the old TTL for the new data, and
|
||||
* update to fetch the latest data. ttl is not expired, because
|
||||
* that check was before this one. */
|
||||
if(ns) {
|
||||
size_t i;
|
||||
newd->ttl = cached->ttl;
|
||||
for(i=0; i<(newd->count+newd->rrsig_count); i++)
|
||||
if(newd->rr_ttl[i] > newd->ttl)
|
||||
newd->rr_ttl[i] = newd->ttl;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Update RRSet special key ID */
|
||||
@@ -191,10 +203,11 @@ rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
|
||||
equal = rrsetdata_equal((struct packed_rrset_data*)k->entry.
|
||||
data, (struct packed_rrset_data*)e->data);
|
||||
if(!need_to_update_rrset(k->entry.data, e->data, timenow,
|
||||
equal)) {
|
||||
equal, (rrset_type==LDNS_RR_TYPE_NS))) {
|
||||
/* cache is superior, return that value */
|
||||
lock_rw_unlock(&e->lock);
|
||||
ub_packed_rrset_parsedelete(k, alloc);
|
||||
if(equal) return 2;
|
||||
return 1;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
@@ -338,9 +351,15 @@ rrset_update_sec_status(struct rrset_cache* r,
|
||||
if(updata->trust > cachedata->trust)
|
||||
cachedata->trust = updata->trust;
|
||||
cachedata->security = updata->security;
|
||||
cachedata->ttl = updata->ttl + now;
|
||||
for(i=0; i<cachedata->count+cachedata->rrsig_count; i++)
|
||||
cachedata->rr_ttl[i] = updata->rr_ttl[i]+now;
|
||||
/* for NS records only shorter TTLs, other types: update it */
|
||||
if(ntohs(rrset->rk.type) != LDNS_RR_TYPE_NS ||
|
||||
updata->ttl+now < cachedata->ttl ||
|
||||
cachedata->ttl < now ||
|
||||
updata->security == sec_status_bogus) {
|
||||
cachedata->ttl = updata->ttl + now;
|
||||
for(i=0; i<cachedata->count+cachedata->rrsig_count; i++)
|
||||
cachedata->rr_ttl[i] = updata->rr_ttl[i]+now;
|
||||
}
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
|
||||
Vendored
+4
@@ -125,6 +125,10 @@ void rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key,
|
||||
* @param alloc: how to allocate (and deallocate) the special rrset key.
|
||||
* @param timenow: current time (to see if ttl in cache is expired).
|
||||
* @return: true if the passed reference is updated, false if it is unchanged.
|
||||
* 0: reference unchanged, inserted in cache.
|
||||
* 1: reference updated, item is inserted in cache.
|
||||
* 2: reference updated, item in cache is considered superior.
|
||||
* also the rdata is equal (but other parameters in cache are superior).
|
||||
*/
|
||||
int rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
|
||||
struct alloc_cache* alloc, uint32_t timenow);
|
||||
|
||||
+189
-66
@@ -39,6 +39,10 @@
|
||||
* This file has functions to get queries from clients.
|
||||
*/
|
||||
#include "config.h"
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "services/outside_network.h"
|
||||
#include "util/netevent.h"
|
||||
@@ -46,9 +50,6 @@
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
@@ -89,7 +90,8 @@ verbose_print_addr(struct addrinfo *addr)
|
||||
|
||||
int
|
||||
create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
socklen_t addrlen, int v6only, int* inuse, int* noproto, int rcv)
|
||||
socklen_t addrlen, int v6only, int* inuse, int* noproto,
|
||||
int rcv, int snd)
|
||||
{
|
||||
int s;
|
||||
#if defined(IPV6_USE_MIN_MTU)
|
||||
@@ -101,6 +103,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
#if !defined(SO_RCVBUFFORCE) && !defined(SO_RCVBUF)
|
||||
(void)rcv;
|
||||
#endif
|
||||
#if !defined(SO_SNDBUFFORCE) && !defined(SO_SNDBUF)
|
||||
(void)snd;
|
||||
#endif
|
||||
#ifndef IPV6_V6ONLY
|
||||
(void)v6only;
|
||||
#endif
|
||||
@@ -181,6 +186,65 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
}
|
||||
# endif
|
||||
#endif /* SO_RCVBUF */
|
||||
}
|
||||
/* first do RCVBUF as the receive buffer is more important */
|
||||
if(snd) {
|
||||
#ifdef SO_SNDBUF
|
||||
int got;
|
||||
socklen_t slen = (socklen_t)sizeof(got);
|
||||
# ifdef SO_SNDBUFFORCE
|
||||
/* Linux specific: try to use root permission to override
|
||||
* system limits on sndbuf. The limit is stored in
|
||||
* /proc/sys/net/core/wmem_max or sysctl net.core.wmem_max */
|
||||
if(setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd,
|
||||
(socklen_t)sizeof(snd)) < 0) {
|
||||
if(errno != EPERM) {
|
||||
# ifndef USE_WINSOCK
|
||||
log_err("setsockopt(..., SO_SNDBUFFORCE, "
|
||||
"...) failed: %s", strerror(errno));
|
||||
close(s);
|
||||
# else
|
||||
log_err("setsockopt(..., SO_SNDBUFFORCE, "
|
||||
"...) failed: %s",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
closesocket(s);
|
||||
# endif
|
||||
*noproto = 0;
|
||||
*inuse = 0;
|
||||
return -1;
|
||||
}
|
||||
# endif /* SO_SNDBUFFORCE */
|
||||
if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd,
|
||||
(socklen_t)sizeof(snd)) < 0) {
|
||||
# ifndef USE_WINSOCK
|
||||
log_err("setsockopt(..., SO_SNDBUF, "
|
||||
"...) failed: %s", strerror(errno));
|
||||
close(s);
|
||||
# else
|
||||
log_err("setsockopt(..., SO_SNDBUF, "
|
||||
"...) failed: %s",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
closesocket(s);
|
||||
# endif
|
||||
*noproto = 0;
|
||||
*inuse = 0;
|
||||
return -1;
|
||||
}
|
||||
/* check if we got the right thing or if system
|
||||
* reduced to some system max. Warn if so */
|
||||
if(getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&got,
|
||||
&slen) >= 0 && got < snd/2) {
|
||||
log_warn("so-sndbuf %u was not granted. "
|
||||
"Got %u. To fix: start with "
|
||||
"root permissions(linux) or sysctl "
|
||||
"bigger net.core.wmem_max(linux) or "
|
||||
"kern.ipc.maxsockbuf(bsd) values.",
|
||||
(unsigned)snd, (unsigned)got);
|
||||
}
|
||||
# ifdef SO_SNDBUFFORCE
|
||||
}
|
||||
# endif
|
||||
#endif /* SO_SNDBUF */
|
||||
}
|
||||
if(family == AF_INET6) {
|
||||
# if defined(IPV6_V6ONLY)
|
||||
@@ -259,6 +323,11 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
log_err("setsockopt(..., IP_MTU_DISCOVER, "
|
||||
"IP_PMTUDISC_DONT...) failed: %s",
|
||||
strerror(errno));
|
||||
# ifndef USE_WINSOCK
|
||||
close(s);
|
||||
# else
|
||||
closesocket(s);
|
||||
# endif
|
||||
return -1;
|
||||
}
|
||||
# elif defined(IP_DONTFRAG)
|
||||
@@ -267,6 +336,11 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
&off, (socklen_t)sizeof(off)) < 0) {
|
||||
log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s",
|
||||
strerror(errno));
|
||||
# ifndef USE_WINSOCK
|
||||
close(s);
|
||||
# else
|
||||
closesocket(s);
|
||||
# endif
|
||||
return -1;
|
||||
}
|
||||
# endif /* IPv4 MTU */
|
||||
@@ -279,15 +353,21 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
/* detect freebsd jail with no ipv6 permission */
|
||||
if(family==AF_INET6 && errno==EINVAL)
|
||||
*noproto = 1;
|
||||
else if(errno != EADDRINUSE)
|
||||
else if(errno != EADDRINUSE) {
|
||||
log_err("can't bind socket: %s", strerror(errno));
|
||||
log_addr(0, "failed address",
|
||||
(struct sockaddr_storage*)addr, addrlen);
|
||||
}
|
||||
#endif /* EADDRINUSE */
|
||||
close(s);
|
||||
#else /* USE_WINSOCK */
|
||||
if(WSAGetLastError() != WSAEADDRINUSE &&
|
||||
WSAGetLastError() != WSAEADDRNOTAVAIL)
|
||||
WSAGetLastError() != WSAEADDRNOTAVAIL) {
|
||||
log_err("can't bind socket: %s",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
log_addr(0, "failed address",
|
||||
(struct sockaddr_storage*)addr, addrlen);
|
||||
}
|
||||
closesocket(s);
|
||||
#endif
|
||||
return -1;
|
||||
@@ -338,9 +418,11 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto)
|
||||
#ifndef USE_WINSOCK
|
||||
log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
|
||||
strerror(errno));
|
||||
close(s);
|
||||
#else
|
||||
log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
closesocket(s);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
@@ -352,9 +434,11 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto)
|
||||
#ifndef USE_WINSOCK
|
||||
log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
|
||||
strerror(errno));
|
||||
close(s);
|
||||
#else
|
||||
log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
closesocket(s);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
@@ -367,21 +451,38 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto)
|
||||
/* detect freebsd jail with no ipv6 permission */
|
||||
if(addr->ai_family==AF_INET6 && errno==EINVAL)
|
||||
*noproto = 1;
|
||||
else log_err("can't bind socket: %s", strerror(errno));
|
||||
else {
|
||||
log_err("can't bind socket: %s", strerror(errno));
|
||||
log_addr(0, "failed address",
|
||||
(struct sockaddr_storage*)addr->ai_addr,
|
||||
addr->ai_addrlen);
|
||||
}
|
||||
close(s);
|
||||
#else
|
||||
log_err("can't bind socket: %s",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
log_addr(0, "failed address",
|
||||
(struct sockaddr_storage*)addr->ai_addr,
|
||||
addr->ai_addrlen);
|
||||
closesocket(s);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
if(!fd_set_nonblock(s)) {
|
||||
#ifndef USE_WINSOCK
|
||||
close(s);
|
||||
#else
|
||||
closesocket(s);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
if(listen(s, TCP_BACKLOG) == -1) {
|
||||
#ifndef USE_WINSOCK
|
||||
log_err("can't listen: %s", strerror(errno));
|
||||
close(s);
|
||||
#else
|
||||
log_err("can't listen: %s", wsa_strerror(WSAGetLastError()));
|
||||
closesocket(s);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
@@ -393,7 +494,7 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto)
|
||||
*/
|
||||
static int
|
||||
make_sock(int stype, const char* ifname, const char* port,
|
||||
struct addrinfo *hints, int v6only, int* noip6, size_t rcv)
|
||||
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd)
|
||||
{
|
||||
struct addrinfo *res = NULL;
|
||||
int r, s, inuse, noproto;
|
||||
@@ -419,8 +520,8 @@ make_sock(int stype, const char* ifname, const char* port,
|
||||
if(stype == SOCK_DGRAM) {
|
||||
verbose_print_addr(res);
|
||||
s = create_udp_sock(res->ai_family, res->ai_socktype,
|
||||
(struct sockaddr*)res->ai_addr,
|
||||
res->ai_addrlen, v6only, &inuse, &noproto, (int)rcv);
|
||||
(struct sockaddr*)res->ai_addr, res->ai_addrlen,
|
||||
v6only, &inuse, &noproto, (int)rcv, (int)snd);
|
||||
if(s == -1 && inuse) {
|
||||
log_err("bind: address already in use");
|
||||
} else if(s == -1 && noproto && hints->ai_family == AF_INET6){
|
||||
@@ -439,7 +540,7 @@ make_sock(int stype, const char* ifname, const char* port,
|
||||
/** make socket and first see if ifname contains port override info */
|
||||
static int
|
||||
make_sock_port(int stype, const char* ifname, const char* port,
|
||||
struct addrinfo *hints, int v6only, int* noip6, size_t rcv)
|
||||
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd)
|
||||
{
|
||||
char* s = strchr(ifname, '@');
|
||||
if(s) {
|
||||
@@ -460,9 +561,10 @@ make_sock_port(int stype, const char* ifname, const char* port,
|
||||
newif[s-ifname] = 0;
|
||||
strncpy(p, s+1, sizeof(p));
|
||||
p[strlen(s+1)]=0;
|
||||
return make_sock(stype, newif, p, hints, v6only, noip6, rcv);
|
||||
return make_sock(stype, newif, p, hints, v6only, noip6,
|
||||
rcv, snd);
|
||||
}
|
||||
return make_sock(stype, ifname, port, hints, v6only, noip6, rcv);
|
||||
return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -490,7 +592,7 @@ port_insert(struct listen_port** list, int s, enum listen_type ftype)
|
||||
static int
|
||||
set_recvpktinfo(int s, int family)
|
||||
{
|
||||
#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) || defined(IP_RECVDSTADDR) || defined(IP_PKTINFO)
|
||||
#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR)) || defined(IP_PKTINFO)
|
||||
int on = 1;
|
||||
#else
|
||||
(void)s;
|
||||
@@ -517,22 +619,22 @@ set_recvpktinfo(int s, int family)
|
||||
# endif /* defined IPV6_RECVPKTINFO */
|
||||
|
||||
} else if(family == AF_INET) {
|
||||
# ifdef IP_RECVDSTADDR
|
||||
if(setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR,
|
||||
(void*)&on, (socklen_t)sizeof(on)) < 0) {
|
||||
log_err("setsockopt(..., IP_RECVDSTADDR, ...) failed: %s",
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
# elif defined(IP_PKTINFO)
|
||||
# ifdef IP_PKTINFO
|
||||
if(setsockopt(s, IPPROTO_IP, IP_PKTINFO,
|
||||
(void*)&on, (socklen_t)sizeof(on)) < 0) {
|
||||
log_err("setsockopt(..., IP_PKTINFO, ...) failed: %s",
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
# elif defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR)
|
||||
if(setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR,
|
||||
(void*)&on, (socklen_t)sizeof(on)) < 0) {
|
||||
log_err("setsockopt(..., IP_RECVDSTADDR, ...) failed: %s",
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
# else
|
||||
log_err("no IP_RECVDSTADDR or IP_PKTINFO option, please disable "
|
||||
log_err("no IP_SENDSRCADDR or IP_PKTINFO option, please disable "
|
||||
"interface-automatic in config");
|
||||
return 0;
|
||||
# endif /* IP_PKTINFO */
|
||||
@@ -552,19 +654,21 @@ set_recvpktinfo(int s, int family)
|
||||
* @param port: Port number to use (as string).
|
||||
* @param list: list of open ports, appended to, changed to point to list head.
|
||||
* @param rcv: receive buffer size for UDP
|
||||
* @param snd: send buffer size for UDP
|
||||
* @param ssl_port: ssl service port number
|
||||
* @return: returns false on error.
|
||||
*/
|
||||
static int
|
||||
ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
struct addrinfo *hints, const char* port, struct listen_port** list,
|
||||
size_t rcv)
|
||||
size_t rcv, size_t snd, int ssl_port)
|
||||
{
|
||||
int s, noip6=0;
|
||||
if(!do_udp && !do_tcp)
|
||||
return 0;
|
||||
if(do_auto) {
|
||||
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
|
||||
&noip6, rcv)) == -1) {
|
||||
&noip6, rcv, snd)) == -1) {
|
||||
if(noip6) {
|
||||
log_warn("IPv6 protocol not available");
|
||||
return 1;
|
||||
@@ -572,8 +676,14 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
return 0;
|
||||
}
|
||||
/* getting source addr packet info is highly non-portable */
|
||||
if(!set_recvpktinfo(s, hints->ai_family))
|
||||
if(!set_recvpktinfo(s, hints->ai_family)) {
|
||||
#ifndef USE_WINSOCK
|
||||
close(s);
|
||||
#else
|
||||
closesocket(s);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
if(!port_insert(list, s, listen_type_udpancil)) {
|
||||
#ifndef USE_WINSOCK
|
||||
close(s);
|
||||
@@ -585,7 +695,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
} else if(do_udp) {
|
||||
/* regular udp socket */
|
||||
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
|
||||
&noip6, rcv)) == -1) {
|
||||
&noip6, rcv, snd)) == -1) {
|
||||
if(noip6) {
|
||||
log_warn("IPv6 protocol not available");
|
||||
return 1;
|
||||
@@ -602,15 +712,21 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
}
|
||||
}
|
||||
if(do_tcp) {
|
||||
int is_ssl = ((strchr(ifname, '@') &&
|
||||
atoi(strchr(ifname, '@')+1) == ssl_port) ||
|
||||
(!strchr(ifname, '@') && atoi(port) == ssl_port));
|
||||
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
|
||||
&noip6, 0)) == -1) {
|
||||
&noip6, 0, 0)) == -1) {
|
||||
if(noip6) {
|
||||
/*log_warn("IPv6 protocol not available");*/
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if(!port_insert(list, s, listen_type_tcp)) {
|
||||
if(is_ssl)
|
||||
verbose(VERB_ALGO, "setup TCP for SSL service");
|
||||
if(!port_insert(list, s, is_ssl?listen_type_ssl:
|
||||
listen_type_tcp)) {
|
||||
#ifndef USE_WINSOCK
|
||||
close(s);
|
||||
#else
|
||||
@@ -643,7 +759,7 @@ listen_cp_insert(struct comm_point* c, struct listen_dnsport* front)
|
||||
|
||||
struct listen_dnsport*
|
||||
listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
size_t bufsize, int tcp_accept_count,
|
||||
size_t bufsize, int tcp_accept_count, void* sslctx,
|
||||
comm_point_callback_t* cb, void *cb_arg)
|
||||
{
|
||||
struct listen_dnsport* front = (struct listen_dnsport*)
|
||||
@@ -656,7 +772,7 @@ listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
free(front);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* create comm points as needed */
|
||||
while(ports) {
|
||||
struct comm_point* cp = NULL;
|
||||
@@ -666,7 +782,11 @@ listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
else if(ports->ftype == listen_type_tcp)
|
||||
cp = comm_point_create_tcp(base, ports->fd,
|
||||
tcp_accept_count, bufsize, cb, cb_arg);
|
||||
else if(ports->ftype == listen_type_udpancil)
|
||||
else if(ports->ftype == listen_type_ssl) {
|
||||
cp = comm_point_create_tcp(base, ports->fd,
|
||||
tcp_accept_count, bufsize, cb, cb_arg);
|
||||
cp->ssl = sslctx;
|
||||
} else if(ports->ftype == listen_type_udpancil)
|
||||
cp = comm_point_create_udp_ancil(base, ports->fd,
|
||||
front->udp_buff, cb, cb_arg);
|
||||
if(!cp) {
|
||||
@@ -714,32 +834,6 @@ listen_delete(struct listen_dnsport* front)
|
||||
free(front);
|
||||
}
|
||||
|
||||
void listen_pushback(struct listen_dnsport* listen)
|
||||
{
|
||||
struct listen_list *p;
|
||||
log_assert(listen);
|
||||
for(p = listen->cps; p; p = p->next)
|
||||
{
|
||||
if(p->com->type != comm_udp &&
|
||||
p->com->type != comm_tcp_accept)
|
||||
continue;
|
||||
comm_point_stop_listening(p->com);
|
||||
}
|
||||
}
|
||||
|
||||
void listen_resume(struct listen_dnsport* listen)
|
||||
{
|
||||
struct listen_list *p;
|
||||
log_assert(listen);
|
||||
for(p = listen->cps; p; p = p->next)
|
||||
{
|
||||
if(p->com->type != comm_udp &&
|
||||
p->com->type != comm_tcp_accept)
|
||||
continue;
|
||||
comm_point_start_listening(p->com, -1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
struct listen_port*
|
||||
listening_ports_open(struct config_file* cfg)
|
||||
{
|
||||
@@ -769,17 +863,15 @@ listening_ports_open(struct config_file* cfg)
|
||||
if(!do_ip4 && !do_ip6) {
|
||||
return NULL;
|
||||
}
|
||||
if(do_auto && (!do_ip4 || !do_ip6)) {
|
||||
log_warn("interface_automatic option does not work when either do-ip4 or do-ip6 is not enabled. Disabling option.");
|
||||
do_auto = 0;
|
||||
}
|
||||
/* create ip4 and ip6 ports so that return addresses are nice. */
|
||||
if(do_auto || cfg->num_ifs == 0) {
|
||||
if(do_ip6) {
|
||||
hints.ai_family = AF_INET6;
|
||||
if(!ports_create_if(do_auto?"::0":"::1",
|
||||
do_auto, cfg->do_udp, do_tcp,
|
||||
&hints, portbuf, &list, cfg->socket_rcvbuf)) {
|
||||
&hints, portbuf, &list,
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -788,7 +880,9 @@ listening_ports_open(struct config_file* cfg)
|
||||
hints.ai_family = AF_INET;
|
||||
if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1",
|
||||
do_auto, cfg->do_udp, do_tcp,
|
||||
&hints, portbuf, &list, cfg->socket_rcvbuf)) {
|
||||
&hints, portbuf, &list,
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -800,7 +894,8 @@ listening_ports_open(struct config_file* cfg)
|
||||
hints.ai_family = AF_INET6;
|
||||
if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
|
||||
do_tcp, &hints, portbuf, &list,
|
||||
cfg->socket_rcvbuf)) {
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -810,7 +905,8 @@ listening_ports_open(struct config_file* cfg)
|
||||
hints.ai_family = AF_INET;
|
||||
if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
|
||||
do_tcp, &hints, portbuf, &list,
|
||||
cfg->socket_rcvbuf)) {
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -848,3 +944,30 @@ size_t listen_get_mem(struct listen_dnsport* listen)
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void listen_stop_accept(struct listen_dnsport* listen)
|
||||
{
|
||||
/* do not stop the ones that have no tcp_free list
|
||||
* (they have already stopped listening) */
|
||||
struct listen_list* p;
|
||||
for(p=listen->cps; p; p=p->next) {
|
||||
if(p->com->type == comm_tcp_accept &&
|
||||
p->com->tcp_free != NULL) {
|
||||
comm_point_stop_listening(p->com);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void listen_start_accept(struct listen_dnsport* listen)
|
||||
{
|
||||
/* do not start the ones that have no tcp_free list, it is no
|
||||
* use to listen to them because they have no free tcp handlers */
|
||||
struct listen_list* p;
|
||||
for(p=listen->cps; p; p=p->next) {
|
||||
if(p->com->type == comm_tcp_accept &&
|
||||
p->com->tcp_free != NULL) {
|
||||
comm_point_start_listening(p->com, -1, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+20
-22
@@ -82,7 +82,9 @@ enum listen_type {
|
||||
/** tcp type */
|
||||
listen_type_tcp,
|
||||
/** udp ipv6 (v4mapped) for use with ancillary data */
|
||||
listen_type_udpancil
|
||||
listen_type_udpancil,
|
||||
/** ssl over tcp type */
|
||||
listen_type_ssl
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -121,6 +123,7 @@ void listening_ports_free(struct listen_port* list);
|
||||
* @param bufsize: size of datagram buffer.
|
||||
* @param tcp_accept_count: max number of simultaneous TCP connections
|
||||
* from clients.
|
||||
* @param sslctx: nonNULL if ssl context.
|
||||
* @param cb: callback function when a request arrives. It is passed
|
||||
* the packet and user argument. Return true to send a reply.
|
||||
* @param cb_arg: user data argument for callback function.
|
||||
@@ -128,26 +131,7 @@ void listening_ports_free(struct listen_port* list);
|
||||
*/
|
||||
struct listen_dnsport* listen_create(struct comm_base* base,
|
||||
struct listen_port* ports, size_t bufsize, int tcp_accept_count,
|
||||
comm_point_callback_t* cb, void* cb_arg);
|
||||
|
||||
/**
|
||||
* Stop listening to the dnsports. Ports are still open but not checked
|
||||
* for readability - performs pushback of the load.
|
||||
* @param listen: the listening structs to stop listening on. Note that
|
||||
* udp and tcp-accept handlers stop, but ongoing tcp-handlers are kept
|
||||
* going, since its rude to 'reset connection by peer' them, instead,
|
||||
* we keep them and the callback will be called when its ready. It can
|
||||
* be dropped at that time. New tcp and udp queries can be served by
|
||||
* other threads.
|
||||
*/
|
||||
void listen_pushback(struct listen_dnsport* listen);
|
||||
|
||||
/**
|
||||
* Start listening again to the dnsports.
|
||||
* Call after the listen_pushback has been called.
|
||||
* @param listen: the listening structs to stop listening on.
|
||||
*/
|
||||
void listen_resume(struct listen_dnsport* listen);
|
||||
void* sslctx, comm_point_callback_t* cb, void* cb_arg);
|
||||
|
||||
/**
|
||||
* delete the listening structure
|
||||
@@ -169,6 +153,18 @@ void listen_list_delete(struct listen_list* list);
|
||||
*/
|
||||
size_t listen_get_mem(struct listen_dnsport* listen);
|
||||
|
||||
/**
|
||||
* stop accept handlers for TCP (until enabled again)
|
||||
* @param listen: listening structure.
|
||||
*/
|
||||
void listen_stop_accept(struct listen_dnsport* listen);
|
||||
|
||||
/**
|
||||
* start accept handlers for TCP (was stopped before)
|
||||
* @param listen: listening structure.
|
||||
*/
|
||||
void listen_start_accept(struct listen_dnsport* listen);
|
||||
|
||||
/**
|
||||
* Create and bind nonblocking UDP socket
|
||||
* @param family: for socket call.
|
||||
@@ -181,10 +177,12 @@ size_t listen_get_mem(struct listen_dnsport* listen);
|
||||
* @param noproto: on error, this is set true if cause is that the
|
||||
IPv6 proto (family) is not available.
|
||||
* @param rcv: set size on rcvbuf with socket option, if 0 it is not set.
|
||||
* @param snd: set size on sndbuf with socket option, if 0 it is not set.
|
||||
* @return: the socket. -1 on error.
|
||||
*/
|
||||
int create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
socklen_t addrlen, int v6only, int* inuse, int* noproto, int rcv);
|
||||
socklen_t addrlen, int v6only, int* inuse, int* noproto, int rcv,
|
||||
int snd);
|
||||
|
||||
/**
|
||||
* Create and bind TCP listening socket
|
||||
|
||||
+22
-6
@@ -39,6 +39,8 @@
|
||||
* This file contains functions to enable local zone authority service.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <ldns/dname.h>
|
||||
#include <ldns/host2wire.h>
|
||||
#include "services/localzone.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/config_file.h"
|
||||
@@ -50,7 +52,7 @@
|
||||
#include "util/data/msgparse.h"
|
||||
|
||||
struct local_zones*
|
||||
local_zones_create()
|
||||
local_zones_create(void)
|
||||
{
|
||||
struct local_zones* zones = (struct local_zones*)calloc(1,
|
||||
sizeof(*zones));
|
||||
@@ -288,7 +290,7 @@ get_rr_nameclass(const char* str, uint8_t** nm, uint16_t* dclass)
|
||||
* @param type: type to look for (host order).
|
||||
* @return rrset pointer or NULL if not found.
|
||||
*/
|
||||
struct local_rrset*
|
||||
static struct local_rrset*
|
||||
local_data_find_type(struct local_data* data, uint16_t type)
|
||||
{
|
||||
struct local_rrset* p;
|
||||
@@ -610,6 +612,8 @@ lz_enter_defaults(struct local_zones* zones, struct config_file* cfg,
|
||||
{
|
||||
struct local_zone* z;
|
||||
|
||||
/* this list of zones is from RFC 6303 */
|
||||
|
||||
/* localhost. zone */
|
||||
if(!lz_exists(zones, "localhost.") &&
|
||||
!lz_nodefault(cfg, "localhost.")) {
|
||||
@@ -687,6 +691,8 @@ lz_enter_defaults(struct local_zones* zones, struct config_file* cfg,
|
||||
!add_as112_default(zones, cfg, buf, "0.in-addr.arpa.") ||
|
||||
!add_as112_default(zones, cfg, buf, "254.169.in-addr.arpa.") ||
|
||||
!add_as112_default(zones, cfg, buf, "2.0.192.in-addr.arpa.") ||
|
||||
!add_as112_default(zones, cfg, buf, "100.51.198.in-addr.arpa.") ||
|
||||
!add_as112_default(zones, cfg, buf, "113.0.203.in-addr.arpa.") ||
|
||||
!add_as112_default(zones, cfg, buf, "255.255.255.255.in-addr.arpa.") ||
|
||||
!add_as112_default(zones, cfg, buf, "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.0.ip6.arpa.") ||
|
||||
!add_as112_default(zones, cfg, buf, "d.f.ip6.arpa.") ||
|
||||
@@ -963,6 +969,10 @@ void local_zones_print(struct local_zones* zones)
|
||||
log_nametypeclass(0, "transparent zone",
|
||||
z->name, 0, z->dclass);
|
||||
break;
|
||||
case local_zone_typetransparent:
|
||||
log_nametypeclass(0, "typetransparent zone",
|
||||
z->name, 0, z->dclass);
|
||||
break;
|
||||
case local_zone_static:
|
||||
log_nametypeclass(0, "static zone",
|
||||
z->name, 0, z->dclass);
|
||||
@@ -1038,10 +1048,10 @@ local_data_answer(struct local_zone* z, struct query_info* qinfo,
|
||||
if(!lr)
|
||||
return 0;
|
||||
if(z->type == local_zone_redirect) {
|
||||
/* convert rrset name to zone name; like a wildcard */
|
||||
/* convert rrset name to query name; like a wildcard */
|
||||
struct ub_packed_rrset_key r = *lr->rrset;
|
||||
r.rk.dname = z->name;
|
||||
r.rk.dname_len = z->namelen;
|
||||
r.rk.dname = qinfo->qname;
|
||||
r.rk.dname_len = qinfo->qname_len;
|
||||
return local_encode(qinfo, edns, buf, temp, &r, 1,
|
||||
LDNS_RCODE_NOERROR);
|
||||
}
|
||||
@@ -1091,7 +1101,10 @@ lz_zone_answer(struct local_zone* z, struct query_info* qinfo,
|
||||
*(uint16_t*)ldns_buffer_begin(buf),
|
||||
ldns_buffer_read_u16_at(buf, 2), edns);
|
||||
return 1;
|
||||
}
|
||||
} else if(z->type == local_zone_typetransparent) {
|
||||
/* no NODATA or NXDOMAINS for this zone type */
|
||||
return 0;
|
||||
}
|
||||
/* else z->type == local_zone_transparent */
|
||||
|
||||
/* if the zone is transparent and the name exists, but the type
|
||||
@@ -1148,6 +1161,7 @@ const char* local_zone_type2str(enum localzone_type t)
|
||||
case local_zone_refuse: return "refuse";
|
||||
case local_zone_redirect: return "redirect";
|
||||
case local_zone_transparent: return "transparent";
|
||||
case local_zone_typetransparent: return "typetransparent";
|
||||
case local_zone_static: return "static";
|
||||
case local_zone_nodefault: return "nodefault";
|
||||
}
|
||||
@@ -1164,6 +1178,8 @@ int local_zone_str2type(const char* type, enum localzone_type* t)
|
||||
*t = local_zone_static;
|
||||
else if(strcmp(type, "transparent") == 0)
|
||||
*t = local_zone_transparent;
|
||||
else if(strcmp(type, "typetransparent") == 0)
|
||||
*t = local_zone_typetransparent;
|
||||
else if(strcmp(type, "redirect") == 0)
|
||||
*t = local_zone_redirect;
|
||||
else return 0;
|
||||
|
||||
@@ -63,6 +63,8 @@ enum localzone_type {
|
||||
local_zone_static,
|
||||
/** resolve normally */
|
||||
local_zone_transparent,
|
||||
/** do not block types at localdata names */
|
||||
local_zone_typetransparent,
|
||||
/** answer with data at zone apex */
|
||||
local_zone_redirect,
|
||||
/** remove default AS112 blocking contents for zone
|
||||
@@ -149,7 +151,7 @@ struct local_rrset {
|
||||
* Create local zones storage
|
||||
* @return new struct or NULL on error.
|
||||
*/
|
||||
struct local_zones* local_zones_create();
|
||||
struct local_zones* local_zones_create(void);
|
||||
|
||||
/**
|
||||
* Delete local zones storage
|
||||
|
||||
+131
-43
@@ -43,6 +43,7 @@
|
||||
* send back to clients.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <ldns/wire2host.h>
|
||||
#include "services/mesh.h"
|
||||
#include "services/outbound_list.h"
|
||||
#include "services/cache/dns.h"
|
||||
@@ -161,7 +162,8 @@ mesh_create(struct module_stack* stack, struct module_env* env)
|
||||
return NULL;
|
||||
}
|
||||
mesh->histogram = timehist_setup();
|
||||
if(!mesh->histogram) {
|
||||
mesh->qbuf_bak = ldns_buffer_new(env->cfg->msg_buffer_size);
|
||||
if(!mesh->histogram || !mesh->qbuf_bak) {
|
||||
free(mesh);
|
||||
log_err("mesh area alloc: out of memory");
|
||||
return NULL;
|
||||
@@ -208,6 +210,7 @@ mesh_delete(struct mesh_area* mesh)
|
||||
while(mesh->all.count)
|
||||
mesh_delete_helper(mesh->all.root);
|
||||
timehist_delete(mesh->histogram);
|
||||
ldns_buffer_free(mesh->qbuf_bak);
|
||||
free(mesh);
|
||||
}
|
||||
|
||||
@@ -231,9 +234,9 @@ mesh_delete_all(struct mesh_area* mesh)
|
||||
mesh->jostle_last = NULL;
|
||||
}
|
||||
|
||||
int mesh_make_new_space(struct mesh_area* mesh)
|
||||
int mesh_make_new_space(struct mesh_area* mesh, ldns_buffer* qbuf)
|
||||
{
|
||||
struct mesh_state* m = mesh->jostle_last;
|
||||
struct mesh_state* m = mesh->jostle_first;
|
||||
/* free space is available */
|
||||
if(mesh->num_reply_states < mesh->max_reply_states)
|
||||
return 1;
|
||||
@@ -249,6 +252,8 @@ int mesh_make_new_space(struct mesh_area* mesh)
|
||||
"make space for a new one",
|
||||
m->s.qinfo.qname, m->s.qinfo.qtype,
|
||||
m->s.qinfo.qclass);
|
||||
/* backup the query */
|
||||
if(qbuf) ldns_buffer_copy(mesh->qbuf_bak, qbuf);
|
||||
/* notify supers */
|
||||
if(m->super_set.count > 0) {
|
||||
verbose(VERB_ALGO, "notify supers of failure");
|
||||
@@ -258,6 +263,9 @@ int mesh_make_new_space(struct mesh_area* mesh)
|
||||
}
|
||||
mesh->stats_jostled ++;
|
||||
mesh_state_delete(&m->s);
|
||||
/* restore the query - note that the qinfo ptr to
|
||||
* the querybuffer is then correct again. */
|
||||
if(qbuf) ldns_buffer_copy(qbuf, mesh->qbuf_bak);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -269,24 +277,41 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, struct edns_data* edns, struct comm_reply* rep,
|
||||
uint16_t qid)
|
||||
{
|
||||
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags, 0);
|
||||
/* do not use CD flag from user for mesh state, we want the CD-query
|
||||
* to receive validation anyway, to protect out cache contents and
|
||||
* avoid bad-data in this cache that a downstream validator cannot
|
||||
* remove from this cache */
|
||||
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&BIT_RD, 0);
|
||||
int was_detached = 0;
|
||||
int was_noreply = 0;
|
||||
int added = 0;
|
||||
/* does this create a new reply state? */
|
||||
if(!s || s->list_select == mesh_no_list) {
|
||||
if(!mesh_make_new_space(mesh)) {
|
||||
if(!mesh_make_new_space(mesh, rep->c->buffer)) {
|
||||
verbose(VERB_ALGO, "Too many queries. dropping "
|
||||
"incoming query.");
|
||||
comm_point_drop_reply(rep);
|
||||
mesh->stats_dropped ++;
|
||||
return;
|
||||
}
|
||||
/* for this new reply state, the reply address is free,
|
||||
* so the limit of reply addresses does not stop reply states*/
|
||||
} else {
|
||||
/* protect our memory usage from storing reply addresses */
|
||||
if(mesh->num_reply_addrs > mesh->max_reply_states*16) {
|
||||
verbose(VERB_ALGO, "Too many requests queued. "
|
||||
"dropping incoming query.");
|
||||
mesh->stats_dropped++;
|
||||
comm_point_drop_reply(rep);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* see if it already exists, if not, create one */
|
||||
if(!s) {
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_t* n;
|
||||
s = mesh_state_create(mesh->env, qinfo, qflags, 0);
|
||||
#endif
|
||||
s = mesh_state_create(mesh->env, qinfo, qflags&BIT_RD, 0);
|
||||
if(!s) {
|
||||
log_err("mesh_state_create: out of memory; SERVFAIL");
|
||||
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
@@ -294,7 +319,10 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
comm_point_send_reply(rep);
|
||||
return;
|
||||
}
|
||||
n = rbtree_insert(&mesh->all, &s->node);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#endif
|
||||
rbtree_insert(&mesh->all, &s->node);
|
||||
log_assert(n != NULL);
|
||||
/* set detached (it is now) */
|
||||
mesh->num_detached_states++;
|
||||
@@ -345,7 +373,7 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, struct edns_data* edns, ldns_buffer* buf,
|
||||
uint16_t qid, mesh_cb_func_t cb, void* cb_arg)
|
||||
{
|
||||
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags, 0);
|
||||
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&BIT_RD, 0);
|
||||
int was_detached = 0;
|
||||
int was_noreply = 0;
|
||||
int added = 0;
|
||||
@@ -353,12 +381,17 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
|
||||
/* see if it already exists, if not, create one */
|
||||
if(!s) {
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_t* n;
|
||||
s = mesh_state_create(mesh->env, qinfo, qflags, 0);
|
||||
#endif
|
||||
s = mesh_state_create(mesh->env, qinfo, qflags&BIT_RD, 0);
|
||||
if(!s) {
|
||||
return 0;
|
||||
}
|
||||
n = rbtree_insert(&mesh->all, &s->node);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#endif
|
||||
rbtree_insert(&mesh->all, &s->node);
|
||||
log_assert(n != NULL);
|
||||
/* set detached (it is now) */
|
||||
mesh->num_detached_states++;
|
||||
@@ -391,8 +424,10 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, uint32_t leeway)
|
||||
{
|
||||
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags, 0);
|
||||
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&BIT_RD, 0);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_t* n;
|
||||
#endif
|
||||
/* already exists, and for a different purpose perhaps.
|
||||
* if mesh_no_list, keep it that way. */
|
||||
if(s) {
|
||||
@@ -403,17 +438,20 @@ void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
s->s.prefetch_leeway = leeway;
|
||||
return;
|
||||
}
|
||||
if(!mesh_make_new_space(mesh)) {
|
||||
if(!mesh_make_new_space(mesh, NULL)) {
|
||||
verbose(VERB_ALGO, "Too many queries. dropped prefetch.");
|
||||
mesh->stats_dropped ++;
|
||||
return;
|
||||
}
|
||||
s = mesh_state_create(mesh->env, qinfo, qflags, 0);
|
||||
s = mesh_state_create(mesh->env, qinfo, qflags&BIT_RD, 0);
|
||||
if(!s) {
|
||||
log_err("prefetch mesh_state_create: out of memory");
|
||||
return;
|
||||
}
|
||||
n = rbtree_insert(&mesh->all, &s->node);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#endif
|
||||
rbtree_insert(&mesh->all, &s->node);
|
||||
log_assert(n != NULL);
|
||||
/* set detached (it is now) */
|
||||
mesh->num_detached_states++;
|
||||
@@ -512,22 +550,24 @@ mesh_state_cleanup(struct mesh_state* mstate)
|
||||
int i;
|
||||
if(!mstate)
|
||||
return;
|
||||
mesh = mstate->s.env->mesh;
|
||||
/* drop unsent replies */
|
||||
if(!mstate->replies_sent) {
|
||||
struct mesh_reply* rep;
|
||||
struct mesh_cb* cb;
|
||||
for(rep=mstate->reply_list; rep; rep=rep->next) {
|
||||
comm_point_drop_reply(&rep->query_reply);
|
||||
mesh->num_reply_addrs--;
|
||||
}
|
||||
for(cb=mstate->cb_list; cb; cb=cb->next) {
|
||||
fptr_ok(fptr_whitelist_mesh_cb(cb->cb));
|
||||
(*cb->cb)(cb->cb_arg, LDNS_RCODE_SERVFAIL, NULL,
|
||||
sec_status_unchecked, NULL);
|
||||
mesh->num_reply_addrs--;
|
||||
}
|
||||
}
|
||||
|
||||
/* de-init modules */
|
||||
mesh = mstate->s.env->mesh;
|
||||
for(i=0; i<mesh->mods.num; i++) {
|
||||
fptr_ok(fptr_whitelist_mod_clear(mesh->mods.mod[i]->clear));
|
||||
(*mesh->mods.mod[i]->clear)(&mstate->s, i);
|
||||
@@ -575,15 +615,50 @@ mesh_state_delete(struct module_qstate* qstate)
|
||||
mesh_state_cleanup(mstate);
|
||||
}
|
||||
|
||||
/** helper recursive rbtree find routine */
|
||||
static int
|
||||
find_in_subsub(struct mesh_state* m, struct mesh_state* tofind, size_t *c)
|
||||
{
|
||||
struct mesh_state_ref* r;
|
||||
if((*c)++ > MESH_MAX_SUBSUB)
|
||||
return 1;
|
||||
RBTREE_FOR(r, struct mesh_state_ref*, &m->sub_set) {
|
||||
if(r->s == tofind || find_in_subsub(r->s, tofind, c))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** find cycle for already looked up mesh_state */
|
||||
static int
|
||||
mesh_detect_cycle_found(struct module_qstate* qstate, struct mesh_state* dep_m)
|
||||
{
|
||||
struct mesh_state* cyc_m = qstate->mesh_info;
|
||||
size_t counter = 0;
|
||||
if(!dep_m)
|
||||
return 0;
|
||||
if(dep_m == cyc_m || find_in_subsub(dep_m, cyc_m, &counter)) {
|
||||
if(counter > MESH_MAX_SUBSUB)
|
||||
return 2;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mesh_detach_subs(struct module_qstate* qstate)
|
||||
{
|
||||
struct mesh_area* mesh = qstate->env->mesh;
|
||||
struct mesh_state_ref* ref, lookup;
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_t* n;
|
||||
#endif
|
||||
lookup.node.key = &lookup;
|
||||
lookup.s = qstate->mesh_info;
|
||||
RBTREE_FOR(ref, struct mesh_state_ref*, &qstate->mesh_info->sub_set) {
|
||||
n = rbtree_delete(&ref->s->super_set, &lookup);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#endif
|
||||
rbtree_delete(&ref->s->super_set, &lookup);
|
||||
log_assert(n != NULL); /* must have been present */
|
||||
if(!ref->s->reply_list && !ref->s->cb_list
|
||||
&& ref->s->super_set.count == 0) {
|
||||
@@ -601,27 +676,43 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
/* find it, if not, create it */
|
||||
struct mesh_area* mesh = qstate->env->mesh;
|
||||
struct mesh_state* sub = mesh_area_find(mesh, qinfo, qflags, prime);
|
||||
int was_detached;
|
||||
if(mesh_detect_cycle_found(qstate, sub)) {
|
||||
verbose(VERB_ALGO, "attach failed, cycle detected");
|
||||
return 0;
|
||||
}
|
||||
if(!sub) {
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_t* n;
|
||||
#endif
|
||||
/* create a new one */
|
||||
sub = mesh_state_create(qstate->env, qinfo, qflags, prime);
|
||||
if(!sub) {
|
||||
log_err("mesh_attach_sub: out of memory");
|
||||
return 0;
|
||||
}
|
||||
n = rbtree_insert(&mesh->all, &sub->node);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#endif
|
||||
rbtree_insert(&mesh->all, &sub->node);
|
||||
log_assert(n != NULL);
|
||||
/* set detached (it is now) */
|
||||
mesh->num_detached_states++;
|
||||
/* set new query state to run */
|
||||
n = rbtree_insert(&mesh->run, &sub->run_node);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#endif
|
||||
rbtree_insert(&mesh->run, &sub->run_node);
|
||||
log_assert(n != NULL);
|
||||
*newq = &sub->s;
|
||||
} else
|
||||
*newq = NULL;
|
||||
was_detached = (sub->super_set.count == 0);
|
||||
if(!mesh_state_attachment(qstate->mesh_info, sub))
|
||||
return 0;
|
||||
if(!sub->reply_list && !sub->cb_list && sub->super_set.count == 1) {
|
||||
/* if it was a duplicate attachment, the count was not zero before */
|
||||
if(!sub->reply_list && !sub->cb_list && was_detached &&
|
||||
sub->super_set.count == 1) {
|
||||
/* it used to be detached, before this one got added */
|
||||
log_assert(mesh->num_detached_states > 0);
|
||||
mesh->num_detached_states--;
|
||||
@@ -632,7 +723,9 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
|
||||
int mesh_state_attachment(struct mesh_state* super, struct mesh_state* sub)
|
||||
{
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_t* n;
|
||||
#endif
|
||||
struct mesh_state_ref* subref; /* points to sub, inserted in super */
|
||||
struct mesh_state_ref* superref; /* points to super, inserted in sub */
|
||||
if( !(subref = regional_alloc(super->s.region,
|
||||
@@ -646,10 +739,20 @@ int mesh_state_attachment(struct mesh_state* super, struct mesh_state* sub)
|
||||
superref->s = super;
|
||||
subref->node.key = subref;
|
||||
subref->s = sub;
|
||||
n = rbtree_insert(&sub->super_set, &superref->node);
|
||||
log_assert(n != NULL);
|
||||
n = rbtree_insert(&super->sub_set, &subref->node);
|
||||
log_assert(n != NULL);
|
||||
if(!rbtree_insert(&sub->super_set, &superref->node)) {
|
||||
/* this should not happen, iterator and validator do not
|
||||
* attach subqueries that are identical. */
|
||||
/* already attached, we are done, nothing todo.
|
||||
* since superref and subref already allocated in region,
|
||||
* we cannot free them */
|
||||
return 1;
|
||||
}
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#endif
|
||||
rbtree_insert(&super->sub_set, &subref->node);
|
||||
log_assert(n != NULL); /* we checked above if statement, the reverse
|
||||
administration should not fail now, unless they are out of sync */
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -722,7 +825,8 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
struct timeval duration;
|
||||
int secure;
|
||||
/* examine security status */
|
||||
if(m->s.env->need_to_validate && !(r->qflags&BIT_CD) && rep &&
|
||||
if(m->s.env->need_to_validate && (!(r->qflags&BIT_CD) ||
|
||||
m->s.env->cfg->ignore_cd) && rep &&
|
||||
rep->security <= sec_status_bogus) {
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
if(m->s.env->cfg->stat_extended)
|
||||
@@ -1048,7 +1152,8 @@ mesh_get_mem(struct mesh_area* mesh)
|
||||
{
|
||||
struct mesh_state* m;
|
||||
size_t s = sizeof(*mesh) + sizeof(struct timehist) +
|
||||
sizeof(struct th_buck)*mesh->histogram->num;
|
||||
sizeof(struct th_buck)*mesh->histogram->num +
|
||||
sizeof(ldns_buffer) + ldns_buffer_capacity(mesh->qbuf_bak);
|
||||
RBTREE_FOR(m, struct mesh_state*, &mesh->all) {
|
||||
/* all, including m itself allocated in qstate region */
|
||||
s += regional_get_mem(m->s.region);
|
||||
@@ -1056,30 +1161,13 @@ mesh_get_mem(struct mesh_area* mesh)
|
||||
return s;
|
||||
}
|
||||
|
||||
/** helper recursive rbtree find routine */
|
||||
static int
|
||||
find_in_subsub(struct mesh_state* m, struct mesh_state* tofind)
|
||||
{
|
||||
struct mesh_state_ref* r;
|
||||
RBTREE_FOR(r, struct mesh_state_ref*, &m->sub_set) {
|
||||
if(r->s == tofind || find_in_subsub(r->s, tofind))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
uint16_t flags, int prime)
|
||||
{
|
||||
struct mesh_area* mesh = qstate->env->mesh;
|
||||
struct mesh_state* cyc_m = qstate->mesh_info;
|
||||
struct mesh_state* dep_m = mesh_area_find(mesh, qinfo, flags, prime);
|
||||
if(!dep_m)
|
||||
return 0;
|
||||
if(dep_m == cyc_m || find_in_subsub(dep_m, cyc_m))
|
||||
return 1;
|
||||
return 0;
|
||||
return mesh_detect_cycle_found(qstate, dep_m);
|
||||
}
|
||||
|
||||
void mesh_list_insert(struct mesh_state* m, struct mesh_state** fp,
|
||||
|
||||
+27
-4
@@ -63,7 +63,14 @@ struct timehist;
|
||||
* Maximum number of mesh state activations. Any more is likely an
|
||||
* infinite loop in the module. It is then terminated.
|
||||
*/
|
||||
#define MESH_MAX_ACTIVATION 1000
|
||||
#define MESH_MAX_ACTIVATION 3000
|
||||
|
||||
/**
|
||||
* Max number of references-to-references-to-references.. search size.
|
||||
* Any more is treated like 'too large', and the creation of a new
|
||||
* dependency is failed (so that no loops can be created).
|
||||
*/
|
||||
#define MESH_MAX_SUBSUB 1024
|
||||
|
||||
/**
|
||||
* Mesh of query states
|
||||
@@ -116,6 +123,10 @@ struct mesh_area {
|
||||
/** (extended stats) rcode nodata in replies */
|
||||
size_t ans_nodata;
|
||||
|
||||
/** backup of query if other operations recurse and need the
|
||||
* network buffers */
|
||||
ldns_buffer* qbuf_bak;
|
||||
|
||||
/** double linked list of the run-to-completion query states.
|
||||
* These are query states with a reply */
|
||||
struct mesh_state* forever_first;
|
||||
@@ -326,6 +337,8 @@ void mesh_detach_subs(struct module_qstate* qstate);
|
||||
* Attach subquery.
|
||||
* Creates it if it does not exist already.
|
||||
* Keeps sub and super references correct.
|
||||
* Performs a cycle detection - for double check - and fails if there is one.
|
||||
* Also fails if the sub-sub-references become too large.
|
||||
* Updates stat items in mesh_area structure.
|
||||
* Pass if it is priming query or not.
|
||||
* return:
|
||||
@@ -368,7 +381,8 @@ void mesh_query_done(struct mesh_state* mstate);
|
||||
* results from this query state. These can then be changed for error
|
||||
* or results.
|
||||
* Called when a module is module_finished or returns module_error.
|
||||
* The super query states become runnable with event module_event_pass.
|
||||
* The super query states become runnable with event module_event_pass,
|
||||
* it calls the current module for the super with the inform_super event.
|
||||
*
|
||||
* @param mesh: mesh area to add newly runnable modules to.
|
||||
* @param mstate: the state that has results, used to find mesh state.
|
||||
@@ -503,13 +517,15 @@ size_t mesh_get_mem(struct mesh_area* mesh);
|
||||
/**
|
||||
* Find cycle; see if the given mesh is in the targets sub, or sub-sub, ...
|
||||
* trees.
|
||||
* If the sub-sub structure is too large, it returns 'a cycle'=2.
|
||||
* @param qstate: given mesh querystate.
|
||||
* @param qinfo: query info for dependency.
|
||||
* @param flags: query flags of dependency.
|
||||
* @param prime: if dependency is a priming query or not.
|
||||
* @return true if the name,type,class exists and the given qstate mesh exists
|
||||
* as a dependency of that name. Thus if qstate becomes dependent on
|
||||
* name,type,class then a cycle is created.
|
||||
* name,type,class then a cycle is created, this is return value 1.
|
||||
* Too large to search is value 2 (also true).
|
||||
*/
|
||||
int mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
uint16_t flags, int prime);
|
||||
@@ -523,9 +539,16 @@ int mesh_state_ref_compare(const void* ap, const void* bp);
|
||||
/**
|
||||
* Make space for another recursion state for a reply in the mesh
|
||||
* @param mesh: mesh area
|
||||
* @param qbuf: query buffer to save if recursion is invoked to make space.
|
||||
* This buffer is necessary, because the following sequence in calls
|
||||
* can result in an overwrite of the incoming query:
|
||||
* delete_other_mesh_query - iter_clean - serviced_delete - waiting
|
||||
* udp query is sent - on error callback - callback sends SERVFAIL reply
|
||||
* over the same network channel, and shared UDP buffer is overwritten.
|
||||
* You can pass NULL if there is no buffer that must be backed up.
|
||||
* @return false if no space is available.
|
||||
*/
|
||||
int mesh_make_new_space(struct mesh_area* mesh);
|
||||
int mesh_make_new_space(struct mesh_area* mesh, ldns_buffer* qbuf);
|
||||
|
||||
/**
|
||||
* Insert mesh state into a double linked list. Inserted at end.
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
* This file contains functions to help maintain a stack of modules.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <ctype.h>
|
||||
#include "services/modstack.h"
|
||||
#include "util/module.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
* queries it has outstanding to authoritative servers.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <sys/time.h>
|
||||
#include "services/outbound_list.h"
|
||||
#include "services/outside_network.h"
|
||||
|
||||
|
||||
+309
-98
@@ -40,6 +40,12 @@
|
||||
* wait for the pending answer events.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <ctype.h>
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
#include <ldns/wire2host.h>
|
||||
#include "services/outside_network.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "services/cache/infra.h"
|
||||
@@ -52,10 +58,8 @@
|
||||
#include "util/net_help.h"
|
||||
#include "util/random.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
@@ -127,6 +131,65 @@ waiting_tcp_delete(struct waiting_tcp* w)
|
||||
free(w);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick random outgoing-interface of that family, and bind it.
|
||||
* port set to 0 so OS picks a port number for us.
|
||||
* if it is the ANY address, do not bind.
|
||||
* @param w: tcp structure with destination address.
|
||||
* @param s: socket fd.
|
||||
* @return false on error, socket closed.
|
||||
*/
|
||||
static int
|
||||
pick_outgoing_tcp(struct waiting_tcp* w, int s)
|
||||
{
|
||||
struct port_if* pi = NULL;
|
||||
int num;
|
||||
#ifdef INET6
|
||||
if(addr_is_ip6(&w->addr, w->addrlen))
|
||||
num = w->outnet->num_ip6;
|
||||
else
|
||||
#endif
|
||||
num = w->outnet->num_ip4;
|
||||
if(num == 0) {
|
||||
log_err("no TCP outgoing interfaces of family");
|
||||
log_addr(VERB_OPS, "for addr", &w->addr, w->addrlen);
|
||||
#ifndef USE_WINSOCK
|
||||
close(s);
|
||||
#else
|
||||
closesocket(s);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#ifdef INET6
|
||||
if(addr_is_ip6(&w->addr, w->addrlen))
|
||||
pi = &w->outnet->ip6_ifs[ub_random_max(w->outnet->rnd, num)];
|
||||
else
|
||||
#endif
|
||||
pi = &w->outnet->ip4_ifs[ub_random_max(w->outnet->rnd, num)];
|
||||
log_assert(pi);
|
||||
if(addr_is_any(&pi->addr, pi->addrlen)) {
|
||||
/* binding to the ANY interface is for listening sockets */
|
||||
return 1;
|
||||
}
|
||||
/* set port to 0 */
|
||||
if(addr_is_ip6(&pi->addr, pi->addrlen))
|
||||
((struct sockaddr_in6*)&pi->addr)->sin6_port = 0;
|
||||
else ((struct sockaddr_in*)&pi->addr)->sin_port = 0;
|
||||
if(bind(s, (struct sockaddr*)&pi->addr, pi->addrlen) != 0) {
|
||||
#ifndef USE_WINSOCK
|
||||
log_err("outgoing tcp: bind: %s", strerror(errno));
|
||||
close(s);
|
||||
#else
|
||||
log_err("outgoing tcp: bind: %s",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
closesocket(s);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
log_addr(VERB_ALGO, "tcp bound to src", &pi->addr, pi->addrlen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** use next free buffer to service a tcp query */
|
||||
static int
|
||||
outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
|
||||
@@ -153,6 +216,9 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
|
||||
log_addr(0, "failed address", &w->addr, w->addrlen);
|
||||
return 0;
|
||||
}
|
||||
if(!pick_outgoing_tcp(w, s))
|
||||
return 0;
|
||||
|
||||
fd_set_nonblock(s);
|
||||
if(connect(s, (struct sockaddr*)&w->addr, w->addrlen) == -1) {
|
||||
#ifndef USE_WINSOCK
|
||||
@@ -161,7 +227,10 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
|
||||
#else
|
||||
if(1) {
|
||||
#endif
|
||||
log_err("outgoing tcp: connect: %s", strerror(errno));
|
||||
if(tcp_connect_errno_needs_log(
|
||||
(struct sockaddr*)&w->addr, w->addrlen))
|
||||
log_err("outgoing tcp: connect: %s",
|
||||
strerror(errno));
|
||||
close(s);
|
||||
#else /* USE_WINSOCK */
|
||||
if(WSAGetLastError() != WSAEINPROGRESS &&
|
||||
@@ -172,6 +241,18 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if(w->outnet->sslctx && w->ssl_upstream) {
|
||||
pend->c->ssl = outgoing_ssl_fd(w->outnet->sslctx, s);
|
||||
if(!pend->c->ssl) {
|
||||
pend->c->fd = s;
|
||||
comm_point_close(pend->c);
|
||||
return 0;
|
||||
}
|
||||
#ifdef USE_WINSOCK
|
||||
comm_point_tcp_win_bio_cb(pend->c, pend->c->ssl);
|
||||
#endif
|
||||
pend->c->ssl_shake_state = comm_ssl_shake_write;
|
||||
}
|
||||
w->pkt = NULL;
|
||||
w->next_waiting = (void*)pend;
|
||||
pend->id = LDNS_ID_WIRE(pkt);
|
||||
@@ -215,6 +296,13 @@ static void
|
||||
decomission_pending_tcp(struct outside_network* outnet,
|
||||
struct pending_tcp* pend)
|
||||
{
|
||||
if(pend->c->ssl) {
|
||||
#ifdef HAVE_SSL
|
||||
SSL_shutdown(pend->c->ssl);
|
||||
SSL_free(pend->c->ssl);
|
||||
pend->c->ssl = NULL;
|
||||
#endif
|
||||
}
|
||||
comm_point_close(pend->c);
|
||||
pend->next_free = outnet->tcp_free;
|
||||
outnet->tcp_free = pend;
|
||||
@@ -470,7 +558,8 @@ outside_network_create(struct comm_base *base, size_t bufsize,
|
||||
int do_ip6, size_t num_tcp, struct infra_cache* infra,
|
||||
struct ub_randstate* rnd, int use_caps_for_id, int* availports,
|
||||
int numavailports, size_t unwanted_threshold,
|
||||
void (*unwanted_action)(void*), void* unwanted_param, int do_udp)
|
||||
void (*unwanted_action)(void*), void* unwanted_param, int do_udp,
|
||||
void* sslctx)
|
||||
{
|
||||
struct outside_network* outnet = (struct outside_network*)
|
||||
calloc(1, sizeof(struct outside_network));
|
||||
@@ -484,6 +573,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
|
||||
outnet->num_tcp = num_tcp;
|
||||
outnet->infra = infra;
|
||||
outnet->rnd = rnd;
|
||||
outnet->sslctx = sslctx;
|
||||
outnet->svcd_overhead = 0;
|
||||
outnet->want_to_quit = 0;
|
||||
outnet->unwanted_threshold = unwanted_threshold;
|
||||
@@ -604,6 +694,7 @@ serviced_node_del(rbnode_t* node, void* ATTR_UNUSED(arg))
|
||||
struct serviced_query* sq = (struct serviced_query*)node;
|
||||
struct service_callback* p = sq->cblist, *np;
|
||||
free(sq->qbuf);
|
||||
free(sq->zone);
|
||||
while(p) {
|
||||
np = p->next;
|
||||
free(p);
|
||||
@@ -755,12 +846,14 @@ udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int port,
|
||||
struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
|
||||
sa->sin6_port = (in_port_t)htons((uint16_t)port);
|
||||
fd = create_udp_sock(AF_INET6, SOCK_DGRAM,
|
||||
(struct sockaddr*)addr, addrlen, 1, inuse, &noproto, 0);
|
||||
(struct sockaddr*)addr, addrlen, 1, inuse, &noproto,
|
||||
0, 0);
|
||||
} else {
|
||||
struct sockaddr_in* sa = (struct sockaddr_in*)addr;
|
||||
sa->sin_port = (in_port_t)htons((uint16_t)port);
|
||||
fd = create_udp_sock(AF_INET, SOCK_DGRAM,
|
||||
(struct sockaddr*)addr, addrlen, 1, inuse, &noproto, 0);
|
||||
(struct sockaddr*)addr, addrlen, 1, inuse, &noproto,
|
||||
0, 0);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
@@ -807,9 +900,9 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
|
||||
log_assert(outnet->unused_fds);
|
||||
tries = 0;
|
||||
while(1) {
|
||||
my_if = ub_random(outnet->rnd) % num_if;
|
||||
my_if = ub_random_max(outnet->rnd, num_if);
|
||||
pif = &ifs[my_if];
|
||||
my_port = ub_random(outnet->rnd) % pif->avail_total;
|
||||
my_port = ub_random_max(outnet->rnd, pif->avail_total);
|
||||
if(my_port < pif->inuse) {
|
||||
/* port already open */
|
||||
pend->pc = pif->out[my_port];
|
||||
@@ -987,7 +1080,7 @@ outnet_tcptimer(void* arg)
|
||||
struct waiting_tcp*
|
||||
pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int timeout,
|
||||
comm_point_callback_t* callback, void* callback_arg)
|
||||
comm_point_callback_t* callback, void* callback_arg, int ssl_upstream)
|
||||
{
|
||||
struct pending_tcp* pend = outnet->tcp_free;
|
||||
struct waiting_tcp* w;
|
||||
@@ -1012,6 +1105,7 @@ pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet,
|
||||
w->outnet = outnet;
|
||||
w->cb = callback;
|
||||
w->cb_arg = callback_arg;
|
||||
w->ssl_upstream = ssl_upstream;
|
||||
#ifndef S_SPLINT_S
|
||||
tv.tv_sec = timeout;
|
||||
tv.tv_usec = 0;
|
||||
@@ -1075,10 +1169,14 @@ lookup_serviced(struct outside_network* outnet, ldns_buffer* buff, int dnssec,
|
||||
/** Create new serviced entry */
|
||||
static struct serviced_query*
|
||||
serviced_create(struct outside_network* outnet, ldns_buffer* buff, int dnssec,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
int want_dnssec, int tcp_upstream, int ssl_upstream,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, int qtype)
|
||||
{
|
||||
struct serviced_query* sq = (struct serviced_query*)malloc(sizeof(*sq));
|
||||
#ifdef UNBOUND_DEBUG
|
||||
rbnode_t* ins;
|
||||
#endif
|
||||
if(!sq)
|
||||
return NULL;
|
||||
sq->node.key = sq;
|
||||
@@ -1088,7 +1186,18 @@ serviced_create(struct outside_network* outnet, ldns_buffer* buff, int dnssec,
|
||||
return NULL;
|
||||
}
|
||||
sq->qbuflen = ldns_buffer_limit(buff);
|
||||
sq->zone = memdup(zone, zonelen);
|
||||
if(!sq->zone) {
|
||||
free(sq->qbuf);
|
||||
free(sq);
|
||||
return NULL;
|
||||
}
|
||||
sq->zonelen = zonelen;
|
||||
sq->qtype = qtype;
|
||||
sq->dnssec = dnssec;
|
||||
sq->want_dnssec = want_dnssec;
|
||||
sq->tcp_upstream = tcp_upstream;
|
||||
sq->ssl_upstream = ssl_upstream;
|
||||
memcpy(&sq->addr, addr, addrlen);
|
||||
sq->addrlen = addrlen;
|
||||
sq->outnet = outnet;
|
||||
@@ -1097,7 +1206,10 @@ serviced_create(struct outside_network* outnet, ldns_buffer* buff, int dnssec,
|
||||
sq->status = serviced_initial;
|
||||
sq->retry = 0;
|
||||
sq->to_be_deleted = 0;
|
||||
ins = rbtree_insert(outnet->serviced, &sq->node);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
ins =
|
||||
#endif
|
||||
rbtree_insert(outnet->serviced, &sq->node);
|
||||
log_assert(ins != NULL); /* must not be already present */
|
||||
return sq;
|
||||
}
|
||||
@@ -1130,7 +1242,9 @@ serviced_delete(struct serviced_query* sq)
|
||||
/* clear up the pending query */
|
||||
if(sq->status == serviced_query_UDP_EDNS ||
|
||||
sq->status == serviced_query_UDP ||
|
||||
sq->status == serviced_query_PROBE_EDNS) {
|
||||
sq->status == serviced_query_PROBE_EDNS ||
|
||||
sq->status == serviced_query_UDP_EDNS_FRAG ||
|
||||
sq->status == serviced_query_UDP_EDNS_fallback) {
|
||||
struct pending* p = (struct pending*)sq->pending;
|
||||
if(p->pc)
|
||||
portcomm_loweruse(sq->outnet, p->pc);
|
||||
@@ -1211,7 +1325,19 @@ serviced_encode(struct serviced_query* sq, ldns_buffer* buff, int with_edns)
|
||||
edns.edns_present = 1;
|
||||
edns.ext_rcode = 0;
|
||||
edns.edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
if(sq->status == serviced_query_UDP_EDNS_FRAG) {
|
||||
if(addr_is_ip6(&sq->addr, sq->addrlen)) {
|
||||
if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE)
|
||||
edns.udp_size = EDNS_FRAG_SIZE_IP6;
|
||||
else edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
} else {
|
||||
if(EDNS_FRAG_SIZE_IP4 < EDNS_ADVERTISED_SIZE)
|
||||
edns.udp_size = EDNS_FRAG_SIZE_IP4;
|
||||
else edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
}
|
||||
} else {
|
||||
edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
}
|
||||
edns.bits = 0;
|
||||
if(sq->dnssec & EDNS_DO)
|
||||
edns.bits = EDNS_DO;
|
||||
@@ -1235,17 +1361,19 @@ serviced_udp_send(struct serviced_query* sq, ldns_buffer* buff)
|
||||
uint8_t edns_lame_known;
|
||||
uint32_t now = *sq->outnet->now_secs;
|
||||
|
||||
if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen, now, &vs,
|
||||
&edns_lame_known, &rtt))
|
||||
if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen, sq->zone,
|
||||
sq->zonelen, now, &vs, &edns_lame_known, &rtt))
|
||||
return 0;
|
||||
sq->last_rtt = rtt;
|
||||
verbose(VERB_ALGO, "EDNS lookup known=%d vs=%d", edns_lame_known, vs);
|
||||
if(sq->status == serviced_initial) {
|
||||
if((vs != -1 || edns_lame_known == 0) &&
|
||||
rtt > 5000 && rtt < 10001) {
|
||||
if(edns_lame_known == 0 && rtt > 5000 && rtt < 10001) {
|
||||
/* perform EDNS lame probe - check if server is
|
||||
* EDNS lame (EDNS queries to it are dropped) */
|
||||
verbose(VERB_ALGO, "serviced query: send probe to see "
|
||||
" if use of EDNS causes timeouts");
|
||||
rtt /= 10;
|
||||
/* even 700 msec may be too small */
|
||||
rtt = 1000;
|
||||
sq->status = serviced_query_PROBE_EDNS;
|
||||
} else if(vs != -1) {
|
||||
sq->status = serviced_query_UDP_EDNS;
|
||||
@@ -1253,9 +1381,9 @@ serviced_udp_send(struct serviced_query* sq, ldns_buffer* buff)
|
||||
sq->status = serviced_query_UDP;
|
||||
}
|
||||
}
|
||||
serviced_encode(sq, buff, sq->status == serviced_query_UDP_EDNS);
|
||||
serviced_encode(sq, buff, (sq->status == serviced_query_UDP_EDNS) ||
|
||||
(sq->status == serviced_query_UDP_EDNS_FRAG));
|
||||
sq->last_sent_time = *sq->outnet->now_tv;
|
||||
sq->last_rtt = rtt;
|
||||
sq->edns_lame_known = (int)edns_lame_known;
|
||||
verbose(VERB_ALGO, "serviced query UDP timeout=%d msec", rtt);
|
||||
sq->pending = pending_udp_query(sq->outnet, buff, &sq->addr,
|
||||
@@ -1313,15 +1441,17 @@ static void
|
||||
serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c,
|
||||
struct comm_reply* rep)
|
||||
{
|
||||
struct service_callback* p = sq->cblist, *n;
|
||||
struct service_callback* p;
|
||||
int dobackup = (sq->cblist && sq->cblist->next); /* >1 cb*/
|
||||
uint8_t *backup_p = NULL;
|
||||
size_t backlen = 0;
|
||||
rbnode_t* rem;
|
||||
#ifdef UNBOUND_DEBUG
|
||||
rbnode_t* rem =
|
||||
#endif
|
||||
/* remove from tree, and schedule for deletion, so that callbacks
|
||||
* can safely deregister themselves and even create new serviced
|
||||
* queries that are identical to this one. */
|
||||
rem = rbtree_delete(sq->outnet->serviced, sq);
|
||||
rbtree_delete(sq->outnet->serviced, sq);
|
||||
log_assert(rem); /* should have been present */
|
||||
sq->to_be_deleted = 1;
|
||||
verbose(VERB_ALGO, "svcd callbacks start");
|
||||
@@ -1370,8 +1500,9 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c,
|
||||
}
|
||||
sq->outnet->svcd_overhead = backlen;
|
||||
}
|
||||
while(p) {
|
||||
n = p->next;
|
||||
/* test the actual sq->cblist, because the next elem could be deleted*/
|
||||
while((p=sq->cblist) != NULL) {
|
||||
sq->cblist = p->next; /* remove this element */
|
||||
if(dobackup && c) {
|
||||
ldns_buffer_clear(c->buffer);
|
||||
ldns_buffer_write(c->buffer, backup_p, backlen);
|
||||
@@ -1379,7 +1510,7 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c,
|
||||
}
|
||||
fptr_ok(fptr_whitelist_serviced_query(p->cb));
|
||||
(void)(*p->cb)(c, p->cb_arg, error, rep);
|
||||
p = n;
|
||||
free(p);
|
||||
}
|
||||
if(backup_p) {
|
||||
free(backup_p);
|
||||
@@ -1402,17 +1533,51 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
|
||||
&sq->addr, sq->addrlen);
|
||||
if(error==NETEVENT_NOERROR)
|
||||
infra_update_tcp_works(sq->outnet->infra, &sq->addr,
|
||||
sq->addrlen);
|
||||
sq->addrlen, sq->zone, sq->zonelen);
|
||||
if(error==NETEVENT_NOERROR && sq->status == serviced_query_TCP_EDNS &&
|
||||
(LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) ==
|
||||
LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE(ldns_buffer_begin(
|
||||
c->buffer)) == LDNS_RCODE_NOTIMPL) ) {
|
||||
if(!infra_edns_update(sq->outnet->infra, &sq->addr,
|
||||
sq->addrlen, -1, *sq->outnet->now_secs))
|
||||
log_err("Out of memory caching no edns for host");
|
||||
sq->status = serviced_query_TCP;
|
||||
/* attempt to fallback to nonEDNS */
|
||||
sq->status = serviced_query_TCP_EDNS_fallback;
|
||||
serviced_tcp_initiate(sq->outnet, sq, c->buffer);
|
||||
return 0;
|
||||
} else if(error==NETEVENT_NOERROR &&
|
||||
sq->status == serviced_query_TCP_EDNS_fallback &&
|
||||
(LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) ==
|
||||
LDNS_RCODE_NOERROR || LDNS_RCODE_WIRE(
|
||||
ldns_buffer_begin(c->buffer)) == LDNS_RCODE_NXDOMAIN
|
||||
|| LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer))
|
||||
== LDNS_RCODE_YXDOMAIN)) {
|
||||
/* the fallback produced a result that looks promising, note
|
||||
* that this server should be approached without EDNS */
|
||||
/* only store noEDNS in cache if domain is noDNSSEC */
|
||||
if(!sq->want_dnssec)
|
||||
if(!infra_edns_update(sq->outnet->infra, &sq->addr,
|
||||
sq->addrlen, sq->zone, sq->zonelen, -1,
|
||||
*sq->outnet->now_secs))
|
||||
log_err("Out of memory caching no edns for host");
|
||||
sq->status = serviced_query_TCP;
|
||||
}
|
||||
if(sq->tcp_upstream || sq->ssl_upstream) {
|
||||
struct timeval now = *sq->outnet->now_tv;
|
||||
if(now.tv_sec > sq->last_sent_time.tv_sec ||
|
||||
(now.tv_sec == sq->last_sent_time.tv_sec &&
|
||||
now.tv_usec > sq->last_sent_time.tv_usec)) {
|
||||
/* convert from microseconds to milliseconds */
|
||||
int roundtime = ((int)now.tv_sec - (int)sq->last_sent_time.tv_sec)*1000
|
||||
+ ((int)now.tv_usec - (int)sq->last_sent_time.tv_usec)/1000;
|
||||
verbose(VERB_ALGO, "measured TCP-time at %d msec", roundtime);
|
||||
log_assert(roundtime >= 0);
|
||||
/* only store if less then AUTH_TIMEOUT seconds, it could be
|
||||
* huge due to system-hibernated and we woke up */
|
||||
if(roundtime < TCP_AUTH_QUERY_TIMEOUT*1000) {
|
||||
if(!infra_rtt_update(sq->outnet->infra, &sq->addr,
|
||||
sq->addrlen, sq->zone, sq->zonelen, sq->qtype,
|
||||
roundtime, sq->last_rtt, (uint32_t)now.tv_sec))
|
||||
log_err("out of memory noting rtt.");
|
||||
}
|
||||
}
|
||||
}
|
||||
/* insert address into reply info */
|
||||
if(!rep) {
|
||||
@@ -1433,9 +1598,10 @@ serviced_tcp_initiate(struct outside_network* outnet,
|
||||
verbose(VERB_ALGO, "initiate TCP query %s",
|
||||
sq->status==serviced_query_TCP_EDNS?"EDNS":"");
|
||||
serviced_encode(sq, buff, sq->status == serviced_query_TCP_EDNS);
|
||||
sq->last_sent_time = *sq->outnet->now_tv;
|
||||
sq->pending = pending_tcp_query(outnet, buff, &sq->addr,
|
||||
sq->addrlen, TCP_AUTH_QUERY_TIMEOUT, serviced_tcp_callback,
|
||||
sq);
|
||||
sq, sq->ssl_upstream);
|
||||
if(!sq->pending) {
|
||||
/* delete from tree so that a retry by above layer does not
|
||||
* clash with this entry */
|
||||
@@ -1450,16 +1616,18 @@ serviced_tcp_send(struct serviced_query* sq, ldns_buffer* buff)
|
||||
{
|
||||
int vs, rtt;
|
||||
uint8_t edns_lame_known;
|
||||
if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen,
|
||||
*sq->outnet->now_secs, &vs, &edns_lame_known, &rtt))
|
||||
if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen, sq->zone,
|
||||
sq->zonelen, *sq->outnet->now_secs, &vs, &edns_lame_known,
|
||||
&rtt))
|
||||
return 0;
|
||||
if(vs != -1)
|
||||
sq->status = serviced_query_TCP_EDNS;
|
||||
else sq->status = serviced_query_TCP;
|
||||
serviced_encode(sq, buff, sq->status == serviced_query_TCP_EDNS);
|
||||
sq->last_sent_time = *sq->outnet->now_tv;
|
||||
sq->pending = pending_tcp_query(sq->outnet, buff, &sq->addr,
|
||||
sq->addrlen, TCP_AUTH_QUERY_TIMEOUT, serviced_tcp_callback,
|
||||
sq);
|
||||
sq, sq->ssl_upstream);
|
||||
return sq->pending != NULL;
|
||||
}
|
||||
|
||||
@@ -1476,16 +1644,29 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
if(error == NETEVENT_TIMEOUT) {
|
||||
int rto = 0;
|
||||
if(sq->status == serviced_query_PROBE_EDNS) {
|
||||
/* non-EDNS probe failed; not an EDNS lame server */
|
||||
if(!infra_edns_update(outnet->infra, &sq->addr,
|
||||
sq->addrlen, 0, (uint32_t)now.tv_sec)) {
|
||||
log_err("Out of memory caching edns works");
|
||||
/* non-EDNS probe failed; we do not know its status,
|
||||
* keep trying with EDNS, timeout may not be caused
|
||||
* by EDNS. */
|
||||
sq->status = serviced_query_UDP_EDNS;
|
||||
}
|
||||
if(sq->status == serviced_query_UDP_EDNS && sq->last_rtt < 5000) {
|
||||
/* fallback to 1480/1280 */
|
||||
sq->status = serviced_query_UDP_EDNS_FRAG;
|
||||
log_name_addr(VERB_ALGO, "try edns1xx0", sq->qbuf+10,
|
||||
&sq->addr, sq->addrlen);
|
||||
if(!serviced_udp_send(sq, c->buffer)) {
|
||||
serviced_callbacks(sq, NETEVENT_CLOSED, c, rep);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if(sq->status == serviced_query_UDP_EDNS_FRAG) {
|
||||
/* fragmentation size did not fix it */
|
||||
sq->status = serviced_query_UDP_EDNS;
|
||||
}
|
||||
sq->retry++;
|
||||
if(!(rto=infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
-1, sq->last_rtt, (uint32_t)now.tv_sec)))
|
||||
sq->zone, sq->zonelen, sq->qtype, -1, sq->last_rtt,
|
||||
(uint32_t)now.tv_sec)))
|
||||
log_err("out of memory in UDP exponential backoff");
|
||||
if(sq->retry < OUTBOUND_UDP_RETRY) {
|
||||
log_name_addr(VERB_ALGO, "retry query", sq->qbuf+10,
|
||||
@@ -1502,54 +1683,71 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
serviced_callbacks(sq, NETEVENT_TIMEOUT, c, rep);
|
||||
return 0;
|
||||
}
|
||||
} else if(error != NETEVENT_NOERROR) {
|
||||
/* udp returns error (due to no ID or interface available) */
|
||||
serviced_callbacks(sq, error, c, rep);
|
||||
return 0;
|
||||
}
|
||||
if(error == NETEVENT_NOERROR && sq->status == serviced_query_UDP_EDNS
|
||||
if(!fallback_tcp) {
|
||||
if( (sq->status == serviced_query_UDP_EDNS
|
||||
||sq->status == serviced_query_UDP_EDNS_FRAG)
|
||||
&& (LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer))
|
||||
== LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE(
|
||||
ldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOTIMPL)) {
|
||||
/* note no EDNS, fallback without EDNS */
|
||||
if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
-1, (uint32_t)now.tv_sec)) {
|
||||
log_err("Out of memory caching no edns for host");
|
||||
}
|
||||
sq->status = serviced_query_UDP;
|
||||
/* try to get an answer by falling back without EDNS */
|
||||
verbose(VERB_ALGO, "serviced query: attempt without EDNS");
|
||||
sq->status = serviced_query_UDP_EDNS_fallback;
|
||||
sq->retry = 0;
|
||||
if(!serviced_udp_send(sq, c->buffer)) {
|
||||
serviced_callbacks(sq, NETEVENT_CLOSED, c, rep);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if(LDNS_TC_WIRE(ldns_buffer_begin(c->buffer)) ||
|
||||
(error != NETEVENT_NOERROR && fallback_tcp) ) {
|
||||
/* fallback to TCP */
|
||||
/* this discards partial UDP contents */
|
||||
if(sq->status == serviced_query_UDP_EDNS)
|
||||
sq->status = serviced_query_TCP_EDNS;
|
||||
else sq->status = serviced_query_TCP;
|
||||
serviced_tcp_initiate(outnet, sq, c->buffer);
|
||||
return 0;
|
||||
}
|
||||
/* yay! an answer */
|
||||
if(sq->status == serviced_query_PROBE_EDNS) {
|
||||
} else if(sq->status == serviced_query_PROBE_EDNS) {
|
||||
/* probe without EDNS succeeds, so we conclude that this
|
||||
* host likely has EDNS packets dropped */
|
||||
log_addr(VERB_DETAIL, "timeouts, concluded that connection to "
|
||||
"host drops EDNS packets", &sq->addr, sq->addrlen);
|
||||
if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
-1, (uint32_t)now.tv_sec)) {
|
||||
/* only store noEDNS in cache if domain is noDNSSEC */
|
||||
if(!sq->want_dnssec)
|
||||
if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
sq->zone, sq->zonelen, -1, (uint32_t)now.tv_sec)) {
|
||||
log_err("Out of memory caching no edns for host");
|
||||
}
|
||||
}
|
||||
sq->status = serviced_query_UDP;
|
||||
} else if(sq->status == serviced_query_UDP_EDNS &&
|
||||
} else if(sq->status == serviced_query_UDP_EDNS &&
|
||||
!sq->edns_lame_known) {
|
||||
/* now we know that edns queries received answers store that */
|
||||
log_addr(VERB_ALGO, "serviced query: EDNS works for",
|
||||
&sq->addr, sq->addrlen);
|
||||
if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
0, (uint32_t)now.tv_sec)) {
|
||||
sq->zone, sq->zonelen, 0, (uint32_t)now.tv_sec)) {
|
||||
log_err("Out of memory caching edns works");
|
||||
}
|
||||
sq->edns_lame_known = 1;
|
||||
}
|
||||
if(now.tv_sec > sq->last_sent_time.tv_sec ||
|
||||
} else if(sq->status == serviced_query_UDP_EDNS_fallback &&
|
||||
!sq->edns_lame_known && (LDNS_RCODE_WIRE(
|
||||
ldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOERROR ||
|
||||
LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) ==
|
||||
LDNS_RCODE_NXDOMAIN || LDNS_RCODE_WIRE(ldns_buffer_begin(
|
||||
c->buffer)) == LDNS_RCODE_YXDOMAIN)) {
|
||||
/* the fallback produced a result that looks promising, note
|
||||
* that this server should be approached without EDNS */
|
||||
/* only store noEDNS in cache if domain is noDNSSEC */
|
||||
if(!sq->want_dnssec) {
|
||||
log_addr(VERB_ALGO, "serviced query: EDNS fails for",
|
||||
&sq->addr, sq->addrlen);
|
||||
if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
sq->zone, sq->zonelen, -1, (uint32_t)now.tv_sec)) {
|
||||
log_err("Out of memory caching no edns for host");
|
||||
}
|
||||
} else {
|
||||
log_addr(VERB_ALGO, "serviced query: EDNS fails, but "
|
||||
"not stored because need DNSSEC for", &sq->addr,
|
||||
sq->addrlen);
|
||||
}
|
||||
sq->status = serviced_query_UDP;
|
||||
}
|
||||
if(now.tv_sec > sq->last_sent_time.tv_sec ||
|
||||
(now.tv_sec == sq->last_sent_time.tv_sec &&
|
||||
now.tv_usec > sq->last_sent_time.tv_usec)) {
|
||||
/* convert from microseconds to milliseconds */
|
||||
@@ -1557,59 +1755,67 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
+ ((int)now.tv_usec - (int)sq->last_sent_time.tv_usec)/1000;
|
||||
verbose(VERB_ALGO, "measured roundtrip at %d msec", roundtime);
|
||||
log_assert(roundtime >= 0);
|
||||
if(!infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
roundtime, sq->last_rtt, (uint32_t)now.tv_sec))
|
||||
/* in case the system hibernated, do not enter a huge value,
|
||||
* above this value gives trouble with server selection */
|
||||
if(roundtime < 60000) {
|
||||
if(!infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
sq->zone, sq->zonelen, sq->qtype, roundtime,
|
||||
sq->last_rtt, (uint32_t)now.tv_sec))
|
||||
log_err("out of memory noting rtt.");
|
||||
}
|
||||
}
|
||||
} /* end of if_!fallback_tcp */
|
||||
/* perform TC flag check and TCP fallback after updating our
|
||||
* cache entries for EDNS status and RTT times */
|
||||
if(LDNS_TC_WIRE(ldns_buffer_begin(c->buffer)) || fallback_tcp) {
|
||||
/* fallback to TCP */
|
||||
/* this discards partial UDP contents */
|
||||
if(sq->status == serviced_query_UDP_EDNS ||
|
||||
sq->status == serviced_query_UDP_EDNS_FRAG ||
|
||||
sq->status == serviced_query_UDP_EDNS_fallback)
|
||||
/* if we have unfinished EDNS_fallback, start again */
|
||||
sq->status = serviced_query_TCP_EDNS;
|
||||
else sq->status = serviced_query_TCP;
|
||||
serviced_tcp_initiate(outnet, sq, c->buffer);
|
||||
return 0;
|
||||
}
|
||||
/* yay! an answer */
|
||||
serviced_callbacks(sq, error, c, rep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** find callback in list */
|
||||
static struct service_callback*
|
||||
callback_list_find(struct serviced_query* sq, void* cb_arg,
|
||||
int (*arg_compare)(void*,void*))
|
||||
{
|
||||
struct service_callback* p;
|
||||
for(p = sq->cblist; p; p = p->next) {
|
||||
if(arg_compare(p->cb_arg, cb_arg))
|
||||
return p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct serviced_query*
|
||||
outnet_serviced_query(struct outside_network* outnet,
|
||||
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
|
||||
uint16_t flags, int dnssec, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, comm_point_callback_t* callback,
|
||||
void* callback_arg, ldns_buffer* buff,
|
||||
int (*arg_compare)(void*,void*))
|
||||
uint16_t flags, int dnssec, int want_dnssec, int tcp_upstream,
|
||||
int ssl_upstream, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, comm_point_callback_t* callback,
|
||||
void* callback_arg, ldns_buffer* buff)
|
||||
{
|
||||
struct serviced_query* sq;
|
||||
struct service_callback* cb;
|
||||
serviced_gen_query(buff, qname, qnamelen, qtype, qclass, flags);
|
||||
sq = lookup_serviced(outnet, buff, dnssec, addr, addrlen);
|
||||
if(sq) {
|
||||
/* see if it is a duplicate notification request for cb_arg */
|
||||
if(callback_list_find(sq, callback_arg, arg_compare)) {
|
||||
return sq;
|
||||
}
|
||||
}
|
||||
/* duplicate entries are included in the callback list, because
|
||||
* there is a counterpart registration by our caller that needs to
|
||||
* be doubly-removed (with callbacks perhaps). */
|
||||
if(!(cb = (struct service_callback*)malloc(sizeof(*cb))))
|
||||
return NULL;
|
||||
if(!sq) {
|
||||
/* make new serviced query entry */
|
||||
sq = serviced_create(outnet, buff, dnssec, addr, addrlen);
|
||||
sq = serviced_create(outnet, buff, dnssec, want_dnssec,
|
||||
tcp_upstream, ssl_upstream, addr, addrlen, zone,
|
||||
zonelen, (int)qtype);
|
||||
if(!sq) {
|
||||
free(cb);
|
||||
return NULL;
|
||||
}
|
||||
/* perform first network action */
|
||||
if(outnet->do_udp) {
|
||||
if(outnet->do_udp && !(tcp_upstream || ssl_upstream)) {
|
||||
if(!serviced_udp_send(sq, buff)) {
|
||||
(void)rbtree_delete(outnet->serviced, sq);
|
||||
free(sq->qbuf);
|
||||
free(sq->zone);
|
||||
free(sq);
|
||||
free(cb);
|
||||
return NULL;
|
||||
@@ -1618,6 +1824,7 @@ outnet_serviced_query(struct outside_network* outnet,
|
||||
if(!serviced_tcp_send(sq, buff)) {
|
||||
(void)rbtree_delete(outnet->serviced, sq);
|
||||
free(sq->qbuf);
|
||||
free(sq->zone);
|
||||
free(sq);
|
||||
free(cb);
|
||||
return NULL;
|
||||
@@ -1655,8 +1862,10 @@ void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg)
|
||||
callback_list_remove(sq, cb_arg);
|
||||
/* if callbacks() routine scheduled deletion, let it do that */
|
||||
if(!sq->cblist && !sq->to_be_deleted) {
|
||||
rbnode_t* rem;
|
||||
rem = rbtree_delete(sq->outnet->serviced, sq);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
rbnode_t* rem =
|
||||
#endif
|
||||
rbtree_delete(sq->outnet->serviced, sq);
|
||||
log_assert(rem); /* should be present */
|
||||
serviced_delete(sq);
|
||||
}
|
||||
@@ -1752,7 +1961,9 @@ serviced_get_mem(struct serviced_query* sq)
|
||||
s += sizeof(*sb);
|
||||
if(sq->status == serviced_query_UDP_EDNS ||
|
||||
sq->status == serviced_query_UDP ||
|
||||
sq->status == serviced_query_PROBE_EDNS) {
|
||||
sq->status == serviced_query_PROBE_EDNS ||
|
||||
sq->status == serviced_query_UDP_EDNS_FRAG ||
|
||||
sq->status == serviced_query_UDP_EDNS_fallback) {
|
||||
s += sizeof(struct pending);
|
||||
s += comm_timer_get_mem(NULL);
|
||||
} else {
|
||||
|
||||
@@ -118,6 +118,8 @@ struct outside_network {
|
||||
struct infra_cache* infra;
|
||||
/** where to get random numbers */
|
||||
struct ub_randstate* rnd;
|
||||
/** ssl context to create ssl wrapped TCP with DNS connections */
|
||||
void* sslctx;
|
||||
|
||||
/**
|
||||
* Array of tcp pending used for outgoing TCP connections.
|
||||
@@ -260,6 +262,8 @@ struct waiting_tcp {
|
||||
comm_point_callback_t* cb;
|
||||
/** callback user argument */
|
||||
void* cb_arg;
|
||||
/** if it uses ssl upstream */
|
||||
int ssl_upstream;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -274,6 +278,11 @@ struct service_callback {
|
||||
void* cb_arg;
|
||||
};
|
||||
|
||||
/** fallback size for fragmentation for EDNS in IPv4 */
|
||||
#define EDNS_FRAG_SIZE_IP4 1472
|
||||
/** fallback size for EDNS in IPv6, fits one fragment with ip6-tunnel-ids */
|
||||
#define EDNS_FRAG_SIZE_IP6 1232
|
||||
|
||||
/**
|
||||
* Query service record.
|
||||
* Contains query and destination. UDP, TCP, EDNS are all tried.
|
||||
@@ -291,10 +300,20 @@ struct serviced_query {
|
||||
size_t qbuflen;
|
||||
/** If an EDNS section is included, the DO/CD bit will be turned on. */
|
||||
int dnssec;
|
||||
/** We want signatures, or else the answer is likely useless */
|
||||
int want_dnssec;
|
||||
/** tcp upstream used, use tcp, or ssl_upstream for SSL */
|
||||
int tcp_upstream, ssl_upstream;
|
||||
/** where to send it */
|
||||
struct sockaddr_storage addr;
|
||||
/** length of addr field in use. */
|
||||
socklen_t addrlen;
|
||||
/** zone name, uncompressed domain name in wireformat */
|
||||
uint8_t* zone;
|
||||
/** length of zone name */
|
||||
size_t zonelen;
|
||||
/** qtype */
|
||||
int qtype;
|
||||
/** current status */
|
||||
enum serviced_query_status {
|
||||
/** initial status */
|
||||
@@ -308,7 +327,13 @@ struct serviced_query {
|
||||
/** TCP without EDNS sent */
|
||||
serviced_query_TCP,
|
||||
/** probe to test EDNS lameness (EDNS is dropped) */
|
||||
serviced_query_PROBE_EDNS
|
||||
serviced_query_PROBE_EDNS,
|
||||
/** probe to test noEDNS0 (EDNS gives FORMERRorNOTIMP) */
|
||||
serviced_query_UDP_EDNS_fallback,
|
||||
/** probe to test TCP noEDNS0 (EDNS gives FORMERRorNOTIMP) */
|
||||
serviced_query_TCP_EDNS_fallback,
|
||||
/** send UDP query with EDNS1480 (or 1280) */
|
||||
serviced_query_UDP_EDNS_FRAG
|
||||
}
|
||||
/** variable with current status */
|
||||
status;
|
||||
@@ -350,6 +375,7 @@ struct serviced_query {
|
||||
* @param unwanted_action: the action to take.
|
||||
* @param unwanted_param: user parameter to action.
|
||||
* @param do_udp: if udp is done.
|
||||
* @param sslctx: context to create outgoing connections with (if enabled).
|
||||
* @return: the new structure (with no pending answers) or NULL on error.
|
||||
*/
|
||||
struct outside_network* outside_network_create(struct comm_base* base,
|
||||
@@ -357,7 +383,8 @@ struct outside_network* outside_network_create(struct comm_base* base,
|
||||
int do_ip4, int do_ip6, size_t num_tcp, struct infra_cache* infra,
|
||||
struct ub_randstate* rnd, int use_caps_for_id, int* availports,
|
||||
int numavailports, size_t unwanted_threshold,
|
||||
void (*unwanted_action)(void*), void* unwanted_param, int do_udp);
|
||||
void (*unwanted_action)(void*), void* unwanted_param, int do_udp,
|
||||
void* sslctx);
|
||||
|
||||
/**
|
||||
* Delete outside_network structure.
|
||||
@@ -400,12 +427,13 @@ struct pending* pending_udp_query(struct outside_network* outnet,
|
||||
* without any query been sent to the server yet.
|
||||
* @param callback: function to call on error, timeout or reply.
|
||||
* @param callback_arg: user argument for callback function.
|
||||
* @param ssl_upstream: if the tcp connection must use SSL.
|
||||
* @return: false on error for malloc or socket. Else the pending TCP object.
|
||||
*/
|
||||
struct waiting_tcp* pending_tcp_query(struct outside_network* outnet,
|
||||
ldns_buffer* packet, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int timeout, comm_point_callback_t* callback,
|
||||
void* callback_arg);
|
||||
void* callback_arg, int ssl_upstream);
|
||||
|
||||
/**
|
||||
* Delete pending answer.
|
||||
@@ -427,22 +455,28 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
|
||||
* @param dnssec: if set, DO bit is set in EDNS queries.
|
||||
* If the value includes BIT_CD, CD bit is set when in EDNS queries.
|
||||
* If the value includes BIT_DO, DO bit is set when in EDNS queries.
|
||||
* @param want_dnssec: signatures are needed, without EDNS the answer is
|
||||
* likely to be useless.
|
||||
* @param tcp_upstream: use TCP for upstream queries.
|
||||
* @param ssl_upstream: use SSL for upstream queries.
|
||||
* @param callback: callback function.
|
||||
* @param callback_arg: user argument to callback function.
|
||||
* @param addr: to which server to send the query.
|
||||
* @param addrlen: length of addr.
|
||||
* @param zone: name of the zone of the delegation point. wireformat dname.
|
||||
This is the delegation point name for which the server is deemed
|
||||
authoritative.
|
||||
* @param zonelen: length of zone.
|
||||
* @param buff: scratch buffer to create query contents in. Empty on exit.
|
||||
* @param arg_compare: function to compare callback args, return true if
|
||||
* identical. It is given the callback_arg and args that are listed.
|
||||
* @return 0 on error, or pointer to serviced query that is used to answer
|
||||
* this serviced query may be shared with other callbacks as well.
|
||||
*/
|
||||
struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
|
||||
uint16_t flags, int dnssec, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, comm_point_callback_t* callback,
|
||||
void* callback_arg, ldns_buffer* buff,
|
||||
int (*arg_compare)(void*,void*));
|
||||
uint16_t flags, int dnssec, int want_dnssec, int tcp_upstream,
|
||||
int ssl_upstream, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, comm_point_callback_t* callback,
|
||||
void* callback_arg, ldns_buffer* buff);
|
||||
|
||||
/**
|
||||
* Remove service query callback.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -50,8 +50,12 @@
|
||||
#include "util/regional.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
#include "validator/validator.h"
|
||||
#include "services/localzone.h"
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
#ifdef HAVE_PWD_H
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
@@ -154,7 +158,7 @@ interfacechecks(struct config_file* cfg)
|
||||
socklen_t alen;
|
||||
int i, j;
|
||||
for(i=0; i<cfg->num_ifs; i++) {
|
||||
if(!ipstrtoaddr(cfg->ifs[i], UNBOUND_DNS_PORT, &a, &alen)) {
|
||||
if(!extstrtoaddr(cfg->ifs[i], &a, &alen)) {
|
||||
fatal_exit("cannot parse interface specified as '%s'",
|
||||
cfg->ifs[i]);
|
||||
}
|
||||
@@ -315,7 +319,7 @@ morechecks(struct config_file* cfg, const char* fname)
|
||||
|
||||
if(cfg->verbosity < 0)
|
||||
fatal_exit("verbosity value < 0");
|
||||
if(cfg->num_threads < 0 || cfg->num_threads > 10000)
|
||||
if(cfg->num_threads <= 0 || cfg->num_threads > 10000)
|
||||
fatal_exit("num_threads value weird");
|
||||
if(!cfg->do_ip4 && !cfg->do_ip6)
|
||||
fatal_exit("ip4 and ip6 are both disabled, pointless");
|
||||
@@ -431,6 +435,17 @@ check_fwd(struct config_file* cfg)
|
||||
forwards_delete(fwd);
|
||||
}
|
||||
|
||||
/** check hints */
|
||||
static void
|
||||
check_hints(struct config_file* cfg)
|
||||
{
|
||||
struct iter_hints* hints = hints_create();
|
||||
if(!hints || !hints_apply_cfg(hints, cfg)) {
|
||||
fatal_exit("Could not set root or stub hints");
|
||||
}
|
||||
hints_delete(hints);
|
||||
}
|
||||
|
||||
/** check config file */
|
||||
static void
|
||||
checkconf(const char* cfgfile, const char* opt)
|
||||
@@ -451,6 +466,7 @@ checkconf(const char* cfgfile, const char* opt)
|
||||
check_mod(cfg, pythonmod_get_funcblock());
|
||||
#endif
|
||||
check_fwd(cfg);
|
||||
check_hints(cfg);
|
||||
if(opt) print_option(cfg, opt);
|
||||
else printf("unbound-checkconf: no errors in %s\n", cfgfile);
|
||||
config_delete(cfg);
|
||||
@@ -467,9 +483,15 @@ int main(int argc, char* argv[])
|
||||
int c;
|
||||
const char* f;
|
||||
const char* opt = NULL;
|
||||
const char* cfgfile = CONFIGFILE;
|
||||
log_ident_set("unbound-checkconf");
|
||||
log_init(NULL, 0, NULL);
|
||||
checklock_start();
|
||||
#ifdef USE_WINSOCK
|
||||
/* use registry config file in preference to compiletime location */
|
||||
if(!(cfgfile=w_lookup_reg_str("Software\\Unbound", "ConfigFile")))
|
||||
cfgfile = CONFIGFILE;
|
||||
#endif /* USE_WINSOCK */
|
||||
/* parse the options */
|
||||
while( (c=getopt(argc, argv, "ho:")) != -1) {
|
||||
switch(c) {
|
||||
@@ -488,7 +510,7 @@ int main(int argc, char* argv[])
|
||||
usage();
|
||||
if(argc == 1)
|
||||
f = argv[0];
|
||||
else f = CONFIGFILE;
|
||||
else f = cfgfile;
|
||||
checkconf(f, opt);
|
||||
checklock_stop();
|
||||
return 0;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user