mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
Compare commits
613
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
4642bcb0bc | ||
|
|
698b9df9de | ||
|
|
ae83a2b706 | ||
|
|
6cf3327d8d | ||
|
|
62298b8bfc | ||
|
|
c12752d6fc | ||
|
|
0f90647174 | ||
|
|
d1df3df96a | ||
|
|
6b5f246343 | ||
|
|
b1c920bc8a | ||
|
|
6f1c044381 | ||
|
|
46df44f321 | ||
|
|
0000843c32 | ||
|
|
99eb762c24 | ||
|
|
18b9d266d5 | ||
|
|
53e29fb8b4 | ||
|
|
4f325d281b | ||
|
|
867dfc0563 | ||
|
|
e4ba18f3f2 | ||
|
|
27d8ffb0f3 | ||
|
|
c73dc79252 | ||
|
|
9d5b202720 | ||
|
|
831864df59 | ||
|
|
ecc77998fd | ||
|
|
130f5e4ad1 | ||
|
|
7a7487b094 | ||
|
|
0615e05e6d | ||
|
|
38fe29b9fd | ||
|
|
fcdfcbe82e | ||
|
|
67624a8ee0 | ||
|
|
3c2fe2fe5e | ||
|
|
51cc8aadd6 | ||
|
|
23f95e7cb7 | ||
|
|
5dcbb54e63 | ||
|
|
2bda842014 | ||
|
|
6003dcc291 | ||
|
|
423b4d8893 | ||
|
|
e8e24d3810 | ||
|
|
366e8c4477 | ||
|
|
eeefe9ac45 | ||
|
|
38c6664caf | ||
|
|
36ccd87840 | ||
|
|
8adc2929e8 | ||
|
|
a4f769e214 | ||
|
|
6888c78e1e | ||
|
|
67a4310b36 | ||
|
|
6f8d6c0df4 | ||
|
|
9de8eb6882 | ||
|
|
23077d5a2b | ||
|
|
003aebc9fe | ||
|
|
8e96826ca8 | ||
|
|
acfe235c37 | ||
|
|
9d4983eb00 | ||
|
|
c18b201463 | ||
|
|
7f41877b41 | ||
|
|
f07c72f8d7 | ||
|
|
27090c3ea7 | ||
|
|
48c0528720 | ||
|
|
1ec79bc23f | ||
|
|
b9c39a46b4 | ||
|
|
6d62769b03 | ||
|
|
e84f5ee7dc | ||
|
|
e7da8f089e | ||
|
|
f437de11a6 | ||
|
|
be7105336a | ||
|
|
28af5566b2 | ||
|
|
2bd83fd0cf | ||
|
|
fc3f9a1b96 | ||
|
|
0b41b77549 | ||
|
|
7b9969f8e4 | ||
|
|
bcd1ac7599 | ||
|
|
36785a154b | ||
|
|
5b0fd59e76 | ||
|
|
9a9df2478d | ||
|
|
1314b95ce7 | ||
|
|
43d228c5bc | ||
|
|
d11d56b0b3 | ||
|
|
8e447003fd | ||
|
|
a66bad688b | ||
|
|
f555a5c6a0 | ||
|
|
8bda8efb99 | ||
|
|
1d7e299c27 | ||
|
|
2480336ef3 | ||
|
|
9a9d6bdf0c | ||
|
|
0e248f9000 | ||
|
|
da50c48599 | ||
|
|
7094eab574 | ||
|
|
ab9bd76768 | ||
|
|
72926a9f8c | ||
|
|
47e7b5fb51 | ||
|
|
d3dc108dd9 | ||
|
|
e43b2c9338 | ||
|
|
1d2c4f70fa | ||
|
|
c68aebb3d7 | ||
|
|
90da0cc2e8 | ||
|
|
c88952d4e0 | ||
|
|
59c529bada | ||
|
|
eeb6bf49d0 | ||
|
|
fd9c8a700e | ||
|
|
1ce514a384 | ||
|
|
408079e49f | ||
|
|
4d1c4c8002 | ||
|
|
c253c24202 | ||
|
|
15e5041086 | ||
|
|
836f0358ea | ||
|
|
039f276b0c | ||
|
|
44a28f4343 | ||
|
|
cffd76e6e4 | ||
|
|
54046475e7 | ||
|
|
caeebbf4fa | ||
|
|
521bd29041 | ||
|
|
9abe770f9e | ||
|
|
41a5b9efca | ||
|
|
980f3f10b7 | ||
|
|
83cf9d20c8 | ||
|
|
a4c7a739d9 | ||
|
|
c0093acd97 | ||
|
|
62ab524058 | ||
|
|
c56fdce932 | ||
|
|
502a542820 | ||
|
|
23af66982c | ||
|
|
a4a7894f79 | ||
|
|
5423af1836 | ||
|
|
e19f71ffa0 | ||
|
|
009b2d7c0b | ||
|
|
eb6253aa6c | ||
|
|
5bc9a80e40 | ||
|
|
6e8e4e87b7 | ||
|
|
ff33e077de | ||
|
|
9890caff91 | ||
|
|
45c07da4a0 | ||
|
|
7617c18be1 | ||
|
|
463d7e09c5 | ||
|
|
b3caa5ab37 | ||
|
|
479bebfff4 | ||
|
|
586893d761 | ||
|
|
07f5b21b7b | ||
|
|
4f1a72bb75 | ||
|
|
aa8a6eeadf | ||
|
|
bf8bc06860 | ||
|
|
1727bfc34e | ||
|
|
1d8013c67a | ||
|
|
5b66f07e38 | ||
|
|
81cfcd8053 | ||
|
|
8171793d2a | ||
|
|
9a08ad419e | ||
|
|
3b78d84a7e | ||
|
|
d3bc6d6b5a | ||
|
|
9bb3fdd547 | ||
|
|
f42d27e1a2 | ||
|
|
d7868e4077 | ||
|
|
2c33330994 | ||
|
|
7782cf2b97 | ||
|
|
a909fa9a3a | ||
|
|
e0b639accd | ||
|
|
ce45cbda6d | ||
|
|
6f37df3b92 | ||
|
|
b07370a4c2 | ||
|
|
1a02ab895b | ||
|
|
989a6f4f89 | ||
|
|
5ff6b1c5fb | ||
|
|
4d49d792c3 | ||
|
|
5d2e8e8e97 | ||
|
|
455c3d130d | ||
|
|
c43987e8e1 | ||
|
|
0679bf6502 | ||
|
|
35f077bc06 | ||
|
|
71959c05df | ||
|
|
1c75281303 | ||
|
|
5007a44e52 | ||
|
|
2043463b6a | ||
|
|
d59a8baec2 | ||
|
|
c467aabbf1 | ||
|
|
430a6bd697 | ||
|
|
ee1c4c1cce | ||
|
|
44e2f9b0d9 | ||
|
|
1f7304d146 | ||
|
|
9dc9f0a8e8 | ||
|
|
19ab8e1429 | ||
|
|
aff6654685 | ||
|
|
d0cef76cff | ||
|
|
82b8ddc9bb | ||
|
|
2588d76522 | ||
|
|
5d4249a6b0 | ||
|
|
2c134eb981 | ||
|
|
c4cfcdab6b | ||
|
|
75fbd42ca3 | ||
|
|
aae91da6d2 | ||
|
|
90b4b1dae9 | ||
|
|
795a25c117 | ||
|
|
45acda0535 | ||
|
|
9c822ebc9e | ||
|
|
165a235f4d | ||
|
|
46d341b036 | ||
|
|
7923a28c13 | ||
|
|
2e02003687 | ||
|
|
c611bbba3f | ||
|
|
b322353d8b | ||
|
|
7ccf79d42d | ||
|
|
d7dafa112b | ||
|
|
dcb11b2ee4 | ||
|
|
30d0bf14eb | ||
|
|
1f45bbbd63 | ||
|
|
3f68f01313 | ||
|
|
18e9cbb39f | ||
|
|
ca9c1fa2a8 | ||
|
|
310cbbc372 | ||
|
|
3bca178111 | ||
|
|
4774b8b129 | ||
|
|
e46441787c | ||
|
|
cd3a1ff351 | ||
|
|
e80d0936f3 | ||
|
|
41a29b050b | ||
|
|
37d8551a7a | ||
|
|
17ffb78b10 | ||
|
|
51ba9a4856 | ||
|
|
0fc43d4a62 | ||
|
|
e5cab7b264 | ||
|
|
8e2ef1caeb | ||
|
|
c7bea9d33a | ||
|
|
415236c002 | ||
|
|
0a35d358ee | ||
|
|
544b3f8428 | ||
|
|
9f9edf9ce6 | ||
|
|
eb3eb4f250 | ||
|
|
de7808f2e0 | ||
|
|
4f2461a124 | ||
|
|
a24f9ff9ea | ||
|
|
dafe1ae21b | ||
|
|
b8c4d7088d | ||
|
|
f974f7880b | ||
|
|
bad061a35a | ||
|
|
ba47856946 | ||
|
|
a1a71348bf | ||
|
|
e3b8b9bcea | ||
|
|
902323da2f | ||
|
|
b422db1c80 | ||
|
|
568253e4ff | ||
|
|
6b959f8043 | ||
|
|
ea36edbc03 | ||
|
|
0e7ff77cd2 | ||
|
|
012d05073b | ||
|
|
b93f679049 | ||
|
|
6770898042 | ||
|
|
e89cbd00fa | ||
|
|
b8a2dfb2c9 | ||
|
|
7d90b75ce8 | ||
|
|
0210f4ae41 | ||
|
|
d8e6209a2e | ||
|
|
4e176a0aa6 | ||
|
|
78ed2ec08a | ||
|
|
6f1f6dafb5 | ||
|
|
28be658942 | ||
|
|
ca94ca57b4 | ||
|
|
1e2111f593 | ||
|
|
0deef63323 | ||
|
|
701b4ccdd6 | ||
|
|
a8dccbdd40 | ||
|
|
c42056b9aa | ||
|
|
1cd84ce84e | ||
|
|
948567bea8 | ||
|
|
ed67590f74 | ||
|
|
21e791248f | ||
|
|
a85b563d37 | ||
|
|
3251765048 | ||
|
|
5ecf670277 | ||
|
|
df59a81a56 | ||
|
|
f3579ce5f2 | ||
|
|
f015b01072 | ||
|
|
01cd1823a4 | ||
|
|
0205e3ae29 | ||
|
|
48d786dcc8 | ||
|
|
538ca28828 | ||
|
|
b6076e3b6d | ||
|
|
783178c785 | ||
|
|
1f4222aa94 | ||
|
|
74abf6ced0 | ||
|
|
870b34a8ec | ||
|
|
75611ab90d | ||
|
|
49d65b8ebf | ||
|
|
6f4522a55c | ||
|
|
b97dbd3c8f | ||
|
|
112df5ab6c | ||
|
|
a134925d91 | ||
|
|
38bc0800ee | ||
|
|
dcea0777bf | ||
|
|
894ba681f0 | ||
|
|
72aa0bad92 | ||
|
|
f73ce55c6e | ||
|
|
658e84f7a0 | ||
|
|
f1bd145b60 | ||
|
|
b5f7bf86ac | ||
|
|
56d8c3d59d | ||
|
|
2b9e9b4111 | ||
|
|
d9a6ccfb52 | ||
|
|
cd5ac9634c | ||
|
|
b5f2b7d36b | ||
|
|
91e49260a7 | ||
|
|
a0d67a87f0 | ||
|
|
43d9c09372 | ||
|
|
e33276b5c3 | ||
|
|
630e83f58b | ||
|
|
ff77c81fd1 | ||
|
|
560e1c86b3 | ||
|
|
73da11fe07 | ||
|
|
7b03403efd | ||
|
|
902cad61c6 |
+95
-51
@@ -5,8 +5,10 @@ debug_enabled=@debug_enabled@
|
||||
ifeq "$(QUIET)" ""
|
||||
ifeq ($(debug_enabled),yes)
|
||||
QUIET=yes
|
||||
LIBTOOLQUIET=yes
|
||||
else
|
||||
QUIET=no
|
||||
LIBTOOLQUIET=yes
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -35,6 +37,7 @@ doxygen=@doxygen@
|
||||
libtool=@libtool@
|
||||
ldnsdir=@ldnsdir@
|
||||
staticexe=@staticexe@
|
||||
EXEEXT=@EXEEXT@
|
||||
configfile=@ub_conf_file@
|
||||
UNBOUND_RUN_DIR=@UNBOUND_RUN_DIR@
|
||||
CHECKLOCK_SRC=@CHECKLOCK_SRC@
|
||||
@@ -46,6 +49,7 @@ PYTHON_SITE_PKG=@PYTHON_SITE_PKG@
|
||||
SWIG=@SWIG@
|
||||
YACC=@YACC@
|
||||
LEX=@LEX@
|
||||
STRIP=@STRIP@
|
||||
CC=@CC@
|
||||
CPPFLAGS=-I. @CPPFLAGS@
|
||||
ifneq "$(srcdir)" "."
|
||||
@@ -60,16 +64,24 @@ RUNTIME_PATH=@RUNTIME_PATH@
|
||||
DEPFLAG=@DEPFLAG@
|
||||
DATE=$(shell date +%Y%m%d)
|
||||
LIBTOOL=$(libtool)
|
||||
ifeq "$(QUIET)" "yes"
|
||||
ifeq "$(LIBTOOLQUIET)" "yes"
|
||||
LIBTOOL+=--quiet
|
||||
endif
|
||||
BUILD=build/
|
||||
|
||||
WINDRES=windres
|
||||
WINDRES=@WINDRES@
|
||||
LINT=splint
|
||||
LINTFLAGS=+quiet -weak -warnposix -unrecog -Din_addr_t=uint32_t -Du_int=unsigned -Du_char=uint8_t -preproc -Drlimit=rlimit64 -D__gnuc_va_list=va_list -Dglob64=glob -Dglobfree64=globfree
|
||||
# compat with openssl linux edition.
|
||||
LINTFLAGS+="-DBN_ULONG=unsigned long" -Dkrb5_int32=int "-Dkrb5_ui_4=unsigned int" -DPQ_64BIT=uint64_t -DRC4_INT=unsigned -fixedformalarray
|
||||
LINTFLAGS+="-DBN_ULONG=unsigned long" -Dkrb5_int32=int "-Dkrb5_ui_4=unsigned int" -DPQ_64BIT=uint64_t -DRC4_INT=unsigned -fixedformalarray -D"ENGINE=unsigned" -D"RSA=unsigned" -D"DSA=unsigned" -D"EVP_PKEY=unsigned" -D"EVP_MD=unsigned" -D"SSL=unsigned" -D"SSL_CTX=unsigned" -D"X509=unsigned" -D"RC4_KEY=unsigned" -D"EVP_MD_CTX=unsigned"
|
||||
# compat with NetBSD
|
||||
ifeq "$(shell uname)" "NetBSD"
|
||||
LINTFLAGS+="-D__RENAME(x)=" -D_NETINET_IN_H_
|
||||
endif
|
||||
# compat with OpenBSD
|
||||
LINTFLAGS+="-Dsigset_t=long"
|
||||
# FreeBSD8
|
||||
LINTFLAGS+="-D__uint16_t=uint16_t"
|
||||
|
||||
INSTALL=$(srcdir)/install-sh
|
||||
ifeq "$(WITH_PYTHONMODULE)" "yes"
|
||||
@@ -82,6 +94,7 @@ COMMON_SRC=$(patsubst $(srcdir)/%,%, $(wildcard $(srcdir)/services/*.c \
|
||||
$(srcdir)/iterator/*.c $(srcdir)/validator/*.c $(PYTHONMOD_SRC))) \
|
||||
util/configparser.c util/configlexer.c $(CHECKLOCK_SRC)
|
||||
COMMON_OBJ=$(addprefix $(BUILD),$(COMMON_SRC:.c=.lo))
|
||||
COMPAT_SRC=$(addprefix compat/,$(LIBOBJS:.o=.c))
|
||||
COMPAT_OBJ=$(addprefix $(BUILD)compat/,$(LIBOBJS:.o=.lo))
|
||||
UNITTEST_SRC=$(patsubst $(srcdir)/%,%, \
|
||||
$(wildcard $(srcdir)/testcode/unit*.c)) \
|
||||
@@ -96,7 +109,9 @@ CHECKCONF_OBJ=$(addprefix $(BUILD),$(CHECKCONF_SRC:.c=.lo)) $(COMPAT_OBJ)
|
||||
CONTROL_SRC=smallapp/unbound-control.c smallapp/worker_cb.c $(COMMON_SRC)
|
||||
CONTROL_OBJ=$(addprefix $(BUILD),$(CONTROL_SRC:.c=.lo)) $(COMPAT_OBJ)
|
||||
HOST_SRC=smallapp/unbound-host.c
|
||||
HOST_OBJ=$(addprefix $(BUILD),$(HOST_SRC:.c=.lo)) $(COMPAT_OBJ)
|
||||
HOST_OBJ=$(addprefix $(BUILD),$(HOST_SRC:.c=.lo)) $(filter-out $(BUILD)compat/ctime_r.lo, $(COMPAT_OBJ))
|
||||
UBANCHOR_SRC=smallapp/unbound-anchor.c
|
||||
UBANCHOR_OBJ=$(addprefix $(BUILD),$(UBANCHOR_SRC:.c=.lo)) $(filter-out $(BUILD)compat/ctime_r.lo, $(COMPAT_OBJ))
|
||||
TESTBOUND_SRC=testcode/testbound.c testcode/ldns-testpkts.c \
|
||||
daemon/worker.c daemon/acl_list.c daemon/daemon.c daemon/stats.c \
|
||||
testcode/replay.c testcode/fake_event.c $(filter-out util/netevent.c \
|
||||
@@ -104,6 +119,8 @@ TESTBOUND_SRC=testcode/testbound.c testcode/ldns-testpkts.c \
|
||||
TESTBOUND_OBJ=$(addprefix $(BUILD),$(TESTBOUND_SRC:.c=.lo)) $(COMPAT_OBJ)
|
||||
LOCKVERIFY_SRC=testcode/lock_verify.c smallapp/worker_cb.c $(COMMON_SRC)
|
||||
LOCKVERIFY_OBJ=$(addprefix $(BUILD),$(LOCKVERIFY_SRC:.c=.lo)) $(COMPAT_OBJ)
|
||||
PETAL_SRC=testcode/petal.c
|
||||
PETAL_OBJ=$(addprefix $(BUILD),$(PETAL_SRC:.c=.lo)) $(filter-out $(BUILD)compat/ctime_r.lo, $(COMPAT_OBJ))
|
||||
PKTVIEW_SRC=testcode/pktview.c testcode/readhex.c smallapp/worker_cb.c \
|
||||
$(COMMON_SRC)
|
||||
PKTVIEW_OBJ=$(addprefix $(BUILD),$(PKTVIEW_SRC:.c=.lo)) $(COMPAT_OBJ)
|
||||
@@ -128,7 +145,7 @@ ALL_SRC=$(sort $(COMMON_SRC) $(UNITTEST_SRC) $(DAEMON_SRC) \
|
||||
$(TESTBOUND_SRC) $(LOCKVERIFY_SRC) $(PKTVIEW_SRC) $(SIGNIT_SRC) \
|
||||
$(MEMSTATS_SRC) $(CHECKCONF_SRC) $(LIBUNBOUND_SRC) $(HOST_SRC) \
|
||||
$(ASYNCLOOK_SRC) $(STREAMTCP_SRC) $(PERF_SRC) $(DELAYER_SRC) \
|
||||
$(HARVEST_SRC) $(CONTROL_SRC))
|
||||
$(HARVEST_SRC) $(CONTROL_SRC) $(UBANCHOR_SRC) $(PETAL_SRC))
|
||||
ALL_OBJ=$(addprefix $(BUILD),$(ALL_SRC:.c=.lo) \
|
||||
$(addprefix compat/,$(LIBOBJS:.o=.lo))) $(COMPAT_OBJ)
|
||||
|
||||
@@ -136,18 +153,21 @@ ifeq "$(UB_ON_WINDOWS)" "yes"
|
||||
DAEMON_SRC+=winrc/win_svc.c winrc/w_inst.c
|
||||
DAEMON_OBJ+=$(BUILD)winrc/rsrc_unbound.o $(BUILD)winrc/win_svc.lo
|
||||
HOST_OBJ+=$(BUILD)winrc/rsrc_unbound_host.o
|
||||
UBANCHOR_OBJ+=$(BUILD)winrc/rsrc_unbound_anchor.o
|
||||
CONTROL_OBJ+=$(BUILD)winrc/rsrc_unbound_control.o
|
||||
CHECKCONF_OBJ+=$(BUILD)winrc/rsrc_unbound_checkconf.o
|
||||
|
||||
WINAPPS=unbound-service-install unbound-service-remove anchor-update
|
||||
WINAPPS=$(addsuffix $(EXEEXT), unbound-service-install \
|
||||
unbound-service-remove anchor-update)
|
||||
COMPAT_WINAPP=$(filter-out $(BUILD)compat/ctime_r.lo, $(COMPAT_OBJ))
|
||||
SVCINST_SRC=winrc/unbound-service-install.c winrc/w_inst.c
|
||||
SVCINST_OBJ=$(addprefix $(BUILD),$(SVCINST_SRC:.c=.lo)) $(COMPAT_OBJ) \
|
||||
SVCINST_OBJ=$(addprefix $(BUILD),$(SVCINST_SRC:.c=.lo)) $(COMPAT_WINAPP) \
|
||||
$(BUILD)winrc/rsrc_svcinst.o
|
||||
SVCUNINST_SRC=winrc/unbound-service-remove.c winrc/w_inst.c
|
||||
SVCUNINST_OBJ=$(addprefix $(BUILD),$(SVCUNINST_SRC:.c=.lo)) $(COMPAT_OBJ) \
|
||||
SVCUNINST_OBJ=$(addprefix $(BUILD),$(SVCUNINST_SRC:.c=.lo)) $(COMPAT_WINAPP) \
|
||||
$(BUILD)winrc/rsrc_svcuninst.o
|
||||
ANCHORUPD_SRC=winrc/anchor-update.c
|
||||
ANCHORUPD_OBJ=$(addprefix $(BUILD),$(ANCHORUPD_SRC:.c=.lo)) $(COMPAT_OBJ) \
|
||||
ANCHORUPD_OBJ=$(addprefix $(BUILD),$(ANCHORUPD_SRC:.c=.lo)) $(COMPAT_WINAPP) \
|
||||
$(BUILD)winrc/rsrc_anchorupd.o
|
||||
ALL_SRC:=$(sort $(ALL_SRC) $(SVCINST_SRC) $(SVCUNINST_SRC) $(ANCHORUPD_SRC))
|
||||
ALL_OBJ:=$(sort $(ALL_OBJ) $(SVCINST_OBJ) $(SVCUNINST_OBJ) $(ANCHORUPD_OBJ))
|
||||
@@ -164,108 +184,126 @@ COMPILE=$(LIBTOOL) --tag=CC --mode=compile $(CC) $(CPPFLAGS) $(CFLAGS)
|
||||
LINK=$(LIBTOOL) --tag=CC --mode=link $(strip $(CC) $(staticexe) $(RUNTIME_PATH) $(CFLAGS) $(LDFLAGS))
|
||||
LINK_LIB=$(LIBTOOL) --tag=CC --mode=link $(strip $(CC) $(RUNTIME_PATH) $(CFLAGS) $(LDFLAGS) $(staticexe) -version-number @LIBUNBOUND_CURRENT@:@LIBUNBOUND_REVISION@:@LIBUNBOUND_AGE@ -no-undefined)
|
||||
|
||||
.PHONY: clean realclean doc lint all install uninstall tests test download_ldns strip lib
|
||||
.PHONY: clean realclean doc lint all install uninstall tests test download_ldns strip lib longtest longcheck check
|
||||
|
||||
$(BUILD)%.lo: $(srcdir)/%.c
|
||||
$(INFO) Build $<
|
||||
@if test ! -z "$(ldnsdir)" -a ! -e $(ldnsdir)/include/ldns/ldns.h; \
|
||||
then (cd $(ldnsdir); $(MAKE) copy-headers); fi
|
||||
@-if test ! -d $(dir $@); then $(INSTALL) -d $(patsubst %/,%,$(dir $@)); fi
|
||||
$Q$(COMPILE) -c $< -o $@
|
||||
$Q$(COMPILE) -o $@ -c $<
|
||||
|
||||
all: $(COMMON_OBJ) unbound unbound-checkconf lib unbound-host unbound-control unbound-control-setup $(WINAPPS)
|
||||
all: $(COMMON_OBJ) unbound$(EXEEXT) unbound-checkconf$(EXEEXT) lib unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup $(WINAPPS)
|
||||
|
||||
TEST_BIN=asynclook delayer harvest lock-verify memstats perf pktview signit \
|
||||
streamtcp testbound unittest
|
||||
TEST_BIN=$(addsuffix $(EXEEXT),asynclook delayer harvest lock-verify \
|
||||
memstats perf petal pktview signit streamtcp testbound unittest)
|
||||
tests: all $(TEST_BIN)
|
||||
|
||||
test: tests
|
||||
check: test
|
||||
longcheck: longtest
|
||||
|
||||
test: unittest$(EXEEXT) testbound$(EXEEXT)
|
||||
./unittest$(EXEEXT)
|
||||
./testbound$(EXEEXT) -s
|
||||
for x in testdata/*.rpl; do if ./testbound$(EXEEXT) -p $$x >/dev/null 2>&1; then echo $$x OK; else echo $$x failed; exit 1; fi done
|
||||
@echo test OK
|
||||
|
||||
longtest: tests
|
||||
if test -x "`which bash`"; then bash testcode/do-tests.sh; else sh testcode/do-tests.sh; fi
|
||||
|
||||
lib: libunbound.la
|
||||
|
||||
libunbound.la: $(LIBUNBOUND_OBJ)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK_LIB) -export-symbols $(srcdir)/libunbound/ubsyms.def -o $@ $(sort $(LIBUNBOUND_OBJ)) -rpath $(libdir) $(LIBS)
|
||||
|
||||
ifeq ($(patsubst ldns-src%,ldns-src,$(ldnsdir)),ldns-src)
|
||||
ldnslib=$(ldnsdir)/lib/libldns.a
|
||||
$(ldnslib):
|
||||
$(ldnslib): $(ldnsdir)/lib
|
||||
$(ldnsdir)/lib:
|
||||
@if test ! -z "$(ldnsdir)"; \
|
||||
then (cd $(ldnsdir) && $(MAKE)); fi
|
||||
else
|
||||
ldnslib=
|
||||
endif
|
||||
|
||||
unbound: $(DAEMON_OBJ) $(ldnslib)
|
||||
libunbound.la: $(LIBUNBOUND_OBJ) $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK_LIB) -export-symbols $(srcdir)/libunbound/ubsyms.def -o $@ $(sort $(LIBUNBOUND_OBJ)) -rpath $(libdir) $(LIBS)
|
||||
|
||||
unbound$(EXEEXT): $(DAEMON_OBJ) $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(DAEMON_OBJ)) -lssl $(LIBS)
|
||||
|
||||
unbound-checkconf: $(CHECKCONF_OBJ) $(ldnslib)
|
||||
unbound-checkconf$(EXEEXT): $(CHECKCONF_OBJ) $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(CHECKCONF_OBJ)) $(LIBS)
|
||||
|
||||
unbound-control: $(CONTROL_OBJ) $(ldnslib)
|
||||
unbound-control$(EXEEXT): $(CONTROL_OBJ) $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(CONTROL_OBJ)) -lssl $(LIBS)
|
||||
|
||||
unbound-host: $(HOST_OBJ) libunbound.la $(ldnslib)
|
||||
unbound-host$(EXEEXT): $(HOST_OBJ) libunbound.la $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(HOST_OBJ)) -L. -L.libs -lunbound $(LIBS)
|
||||
|
||||
unbound-service-install: $(SVCINST_OBJ)
|
||||
unbound-anchor$(EXEEXT): $(UBANCHOR_OBJ) libunbound.la $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(UBANCHOR_OBJ)) -L. -L.libs -lunbound -lexpat -lssl $(LIBS)
|
||||
|
||||
unbound-service-install$(EXEEXT): $(SVCINST_OBJ)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(SVCINST_OBJ)) $(LIBS)
|
||||
|
||||
unbound-service-remove: $(SVCUNINST_OBJ)
|
||||
unbound-service-remove$(EXEEXT): $(SVCUNINST_OBJ)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(SVCUNINST_OBJ)) $(LIBS)
|
||||
|
||||
anchor-update: $(ANCHORUPD_OBJ) libunbound.la $(ldnslib)
|
||||
anchor-update$(EXEEXT): $(ANCHORUPD_OBJ) libunbound.la $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(ANCHORUPD_OBJ)) -L. -L.libs -lunbound $(LIBS)
|
||||
|
||||
unittest: $(UNITTEST_OBJ) $(ldnslib)
|
||||
unittest$(EXEEXT): $(UNITTEST_OBJ) $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(UNITTEST_OBJ)) $(LIBS)
|
||||
|
||||
testbound: $(TESTBOUND_OBJ) $(ldnslib)
|
||||
testbound$(EXEEXT): $(TESTBOUND_OBJ) $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(TESTBOUND_OBJ)) -lssl $(LIBS)
|
||||
|
||||
lock-verify: $(LOCKVERIFY_OBJ) $(ldnslib)
|
||||
lock-verify$(EXEEXT): $(LOCKVERIFY_OBJ) $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(LOCKVERIFY_OBJ)) $(LIBS)
|
||||
|
||||
pktview: $(PKTVIEW_OBJ) $(ldnslib)
|
||||
petal$(EXEEXT): $(PETAL_OBJ)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(PETAL_OBJ)) -lssl $(LIBS)
|
||||
|
||||
pktview$(EXEEXT): $(PKTVIEW_OBJ) $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(PKTVIEW_OBJ)) $(LIBS)
|
||||
|
||||
signit: $(SIGNIT_OBJ) $(ldnslib)
|
||||
signit$(EXEEXT): $(SIGNIT_OBJ) $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(SIGNIT_OBJ)) $(LIBS)
|
||||
|
||||
memstats: $(MEMSTATS_OBJ) $(ldnslib)
|
||||
memstats$(EXEEXT): $(MEMSTATS_OBJ) $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(MEMSTATS_OBJ)) $(LIBS)
|
||||
|
||||
asynclook: $(ASYNCLOOK_OBJ) $(ldnslib) libunbound.la
|
||||
asynclook$(EXEEXT): $(ASYNCLOOK_OBJ) $(ldnslib) libunbound.la
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(ASYNCLOOK_OBJ)) $(LIBS) -L. -L.libs -lunbound
|
||||
|
||||
streamtcp: $(STREAMTCP_OBJ) $(ldnslib)
|
||||
streamtcp$(EXEEXT): $(STREAMTCP_OBJ) $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(STREAMTCP_OBJ)) $(LIBS)
|
||||
|
||||
perf: $(PERF_OBJ) $(ldnslib)
|
||||
perf$(EXEEXT): $(PERF_OBJ) $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(PERF_OBJ)) $(LIBS)
|
||||
|
||||
delayer: $(DELAYER_OBJ) $(ldnslib)
|
||||
delayer$(EXEEXT): $(DELAYER_OBJ) $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(DELAYER_OBJ)) $(LIBS)
|
||||
|
||||
harvest: $(HARVEST_OBJ) $(ldnslib) libunbound.la
|
||||
harvest$(EXEEXT): $(HARVEST_OBJ) $(ldnslib) libunbound.la
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(HARVEST_OBJ)) $(LIBS) -L. -L.libs -lunbound
|
||||
|
||||
@@ -318,7 +356,7 @@ util/configparser.c util/configparser.h: $(srcdir)/util/configparser.y
|
||||
|
||||
clean:
|
||||
rm -f *.o *.d *.lo *~ tags
|
||||
rm -f unbound unbound-checkconf unbound-host unbound-control unbound-control-setup libunbound.la
|
||||
rm -f unbound$(EXEEXT) unbound-checkconf$(EXEEXT) unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup libunbound.la
|
||||
rm -rf autom4te.cache .libs build doc/html doc/xml
|
||||
|
||||
realclean: clean
|
||||
@@ -343,18 +381,21 @@ tags: $(srcdir)/*.[ch] $(srcdir)/*/*.[ch]
|
||||
doc:
|
||||
if test -n "$(doxygen)"; then \
|
||||
$(doxygen) $(srcdir)/doc/unbound.doxygen; fi
|
||||
ifeq "$(findstring yes,$(WITH_PYUNBOUND)$(WITH_PYTHONMODULE))" "yes"
|
||||
if test -x "`which sphinx-build 2>&1`"; then \
|
||||
sphinx-build -b html pythonmod/doc doc/html/pythonmod; \
|
||||
sphinx-build -b html libunbound/python/doc doc/html/pyunbound;\
|
||||
fi
|
||||
endif
|
||||
|
||||
strip:
|
||||
strip unbound
|
||||
strip unbound-checkconf
|
||||
strip unbound-control
|
||||
strip unbound-host
|
||||
$(STRIP) unbound$(EXEEXT)
|
||||
$(STRIP) unbound-checkconf$(EXEEXT)
|
||||
$(STRIP) unbound-control$(EXEEXT)
|
||||
$(STRIP) unbound-host$(EXEEXT)
|
||||
$(STRIP) unbound-anchor$(EXEEXT)
|
||||
|
||||
install:
|
||||
install: all
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(sbindir)
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man8
|
||||
@@ -363,10 +404,11 @@ install:
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man1
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(libdir)
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(includedir)
|
||||
$(LIBTOOL) --mode=install cp unbound $(DESTDIR)$(sbindir)/unbound
|
||||
$(LIBTOOL) --mode=install cp unbound-checkconf $(DESTDIR)$(sbindir)/unbound-checkconf
|
||||
$(LIBTOOL) --mode=install cp unbound-control $(DESTDIR)$(sbindir)/unbound-control
|
||||
$(LIBTOOL) --mode=install cp unbound-host $(DESTDIR)$(sbindir)/unbound-host
|
||||
$(LIBTOOL) --mode=install cp unbound$(EXEEXT) $(DESTDIR)$(sbindir)/unbound$(EXEEXT)
|
||||
$(LIBTOOL) --mode=install cp unbound-checkconf$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-checkconf$(EXEEXT)
|
||||
$(LIBTOOL) --mode=install cp unbound-control$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control$(EXEEXT)
|
||||
$(LIBTOOL) --mode=install cp unbound-host$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-host$(EXEEXT)
|
||||
$(LIBTOOL) --mode=install cp unbound-anchor$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-anchor$(EXEEXT)
|
||||
ifeq "$(WITH_PYTHONMODULE)" "yes"
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(PYTHON_SITE_PKG)
|
||||
$(INSTALL) -c -m 644 pythonmod/unboundmodule.py $(DESTDIR)$(PYTHON_SITE_PKG)/unboundmodule.py
|
||||
@@ -375,10 +417,12 @@ ifeq "$(WITH_PYUNBOUND)" "yes"
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(PYTHON_SITE_PKG)
|
||||
$(INSTALL) -c -m 644 libunbound/python/unbound.py $(DESTDIR)$(PYTHON_SITE_PKG)/unbound.py
|
||||
$(LIBTOOL) --mode=install cp _unbound.la $(DESTDIR)$(PYTHON_SITE_PKG)
|
||||
$(LIBTOOL) --mode=finish $(DESTDIR)$(PYTHON_SITE_PKG)
|
||||
endif
|
||||
$(INSTALL) -c -m 644 doc/unbound.8 $(DESTDIR)$(mandir)/man8
|
||||
$(INSTALL) -c -m 644 doc/unbound-checkconf.8 $(DESTDIR)$(mandir)/man8
|
||||
$(INSTALL) -c -m 644 doc/unbound-control.8 $(DESTDIR)$(mandir)/man8
|
||||
$(INSTALL) -c -m 644 doc/unbound-anchor.8 $(DESTDIR)$(mandir)/man8
|
||||
$(INSTALL) -c -m 644 doc/unbound.conf.5 $(DESTDIR)$(mandir)/man5
|
||||
$(INSTALL) -c -m 644 $(srcdir)/doc/unbound-host.1 $(DESTDIR)$(mandir)/man1
|
||||
$(INSTALL) -c -m 644 doc/libunbound.3 $(DESTDIR)$(mandir)/man3
|
||||
@@ -389,8 +433,8 @@ endif
|
||||
$(LIBTOOL) --mode=finish $(DESTDIR)$(libdir)
|
||||
|
||||
uninstall:
|
||||
rm -f -- $(DESTDIR)$(sbindir)/unbound $(DESTDIR)$(sbindir)/unbound-checkconf $(DESTDIR)$(sbindir)/unbound-host $(DESTDIR)$(sbindir)/unbound-control $(DESTDIR)$(sbindir)/unbound-control-setup
|
||||
rm -f -- $(DESTDIR)$(mandir)/man8/unbound.8 $(DESTDIR)$(mandir)/man8/unbound-checkconf.8 $(DESTDIR)$(mandir)/man5/unbound.conf.5 $(DESTDIR)$(mandir)/man8/unbound-control.8
|
||||
rm -f -- $(DESTDIR)$(sbindir)/unbound$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-checkconf$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-host$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-anchor$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control-setup
|
||||
rm -f -- $(DESTDIR)$(mandir)/man8/unbound.8 $(DESTDIR)$(mandir)/man8/unbound-checkconf.8 $(DESTDIR)$(mandir)/man5/unbound.conf.5 $(DESTDIR)$(mandir)/man8/unbound-control.8 $(DESTDIR)$(mandir)/man8/unbound-anchor.8
|
||||
rm -f -- $(DESTDIR)$(mandir)/man1/unbound-host.1 $(DESTDIR)$(mandir)/man3/libunbound.3
|
||||
rm -f -- $(DESTDIR)$(includedir)/unbound.h
|
||||
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/libunbound.la
|
||||
@@ -427,7 +471,7 @@ $(BUILD)%.d: $(srcdir)/%.c
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
ifneq ($(MAKECMDGOALS),realclean)
|
||||
ifeq ($(debug_enabled),yes)
|
||||
-include $(addprefix $(BUILD),$(ALL_SRC:.c=.d))
|
||||
-include $(addprefix $(BUILD),$(ALL_SRC:.c=.d) $(COMPAT_SRC:.c=.d))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
Vendored
+6
-6
@@ -1,4 +1,4 @@
|
||||
# generated automatically by aclocal 1.11 -*- Autoconf -*-
|
||||
# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||
@@ -7854,15 +7854,15 @@ m4_define([lt_dict_filter],
|
||||
|
||||
# Generated from ltversion.in.
|
||||
|
||||
# serial 3012 ltversion.m4
|
||||
# serial 3017 ltversion.m4
|
||||
# This file is part of GNU Libtool
|
||||
|
||||
m4_define([LT_PACKAGE_VERSION], [2.2.6])
|
||||
m4_define([LT_PACKAGE_REVISION], [1.3012])
|
||||
m4_define([LT_PACKAGE_VERSION], [2.2.6b])
|
||||
m4_define([LT_PACKAGE_REVISION], [1.3017])
|
||||
|
||||
AC_DEFUN([LTVERSION_VERSION],
|
||||
[macro_version='2.2.6'
|
||||
macro_revision='1.3012'
|
||||
[macro_version='2.2.6b'
|
||||
macro_revision='1.3017'
|
||||
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
|
||||
_LT_DECL(, macro_revision, 0)
|
||||
])
|
||||
|
||||
+257
-99
@@ -2,10 +2,20 @@
|
||||
# Copyright 2009, Wouter Wijngaards, NLnet Labs.
|
||||
# BSD licensed.
|
||||
#
|
||||
# Version 2
|
||||
# 2009-07-03
|
||||
# Changelog
|
||||
# - fixup LDFLAGS for empty ssl dir.
|
||||
# Version 11
|
||||
# 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
|
||||
# 2010-01-20 added AHX_COONFIG_STRLCAT
|
||||
# 2009-07-14 U_CHAR detection improved for windows crosscompile.
|
||||
# added ACX_FUNC_MALLOC
|
||||
# fixup some #if to #ifdef
|
||||
# NONBLOCKING test for mingw crosscompile.
|
||||
# 2009-07-13 added ACX_WITH_SSL_OPTIONAL
|
||||
# 2009-07-03 fixup LDFLAGS for empty ssl dir.
|
||||
#
|
||||
# Automates some of the checking constructs. Aims at portability for POSIX.
|
||||
# Documentation for functions is below.
|
||||
@@ -30,6 +40,8 @@
|
||||
# ACX_TYPE_IN_PORT_T - in_port_t type.
|
||||
# ACX_ARG_RPATH - add --disable-rpath option.
|
||||
# ACX_WITH_SSL - add --with-ssl option, link -lcrypto.
|
||||
# ACX_WITH_SSL_OPTIONAL - add --with-ssl option, link -lcrypto,
|
||||
# where --without-ssl is also accepted
|
||||
# ACX_LIB_SSL - setup to link -lssl.
|
||||
# ACX_SYS_LARGEFILE - improved sys_largefile, fseeko, >2G files.
|
||||
# ACX_CHECK_GETADDRINFO_WITH_INCLUDES - find getaddrinfo, portably.
|
||||
@@ -37,6 +49,7 @@
|
||||
# ACX_CHECK_NONBLOCKING_BROKEN - see if nonblocking sockets really work.
|
||||
# ACX_MKDIR_ONE_ARG - determine mkdir(2) number of arguments.
|
||||
# ACX_FUNC_IOCTLSOCKET - find ioctlsocket, portably.
|
||||
# ACX_FUNC_MALLOC - check malloc, define replacement .
|
||||
# AHX_CONFIG_FORMAT_ATTRIBUTE - config.h text for format.
|
||||
# AHX_CONFIG_UNUSED_ATTRIBUTE - config.h text for unused.
|
||||
# AHX_CONFIG_FSEEKO - define fseeko, ftello fallback.
|
||||
@@ -48,6 +61,7 @@
|
||||
# AHX_CONFIG_INET_NTOP - inet_ntop compat prototype
|
||||
# AHX_CONFIG_INET_ATON - inet_aton compat prototype
|
||||
# AHX_CONFIG_MEMMOVE - memmove compat prototype
|
||||
# AHX_CONFIG_STRLCAT - strlcat compat prototype
|
||||
# AHX_CONFIG_STRLCPY - strlcpy compat prototype
|
||||
# AHX_CONFIG_GMTIME_R - gmtime_r compat prototype
|
||||
# AHX_CONFIG_W32_SLEEP - w32 compat for sleep
|
||||
@@ -60,6 +74,9 @@
|
||||
# AHX_CONFIG_FLAG_OMITTED - define omitted flag
|
||||
# AHX_CONFIG_FLAG_EXT - define omitted extension flag
|
||||
# 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.
|
||||
@@ -89,7 +106,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"
|
||||
@@ -133,18 +150,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
|
||||
]
|
||||
@@ -160,8 +177,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
|
||||
@@ -480,14 +497,20 @@ AC_PROG_LIBTOOL
|
||||
|
||||
dnl Detect if u_char type is defined, otherwise define it.
|
||||
AC_DEFUN([ACX_TYPE_U_CHAR],
|
||||
[AC_CHECK_TYPE(u_char, unsigned char)])
|
||||
[AC_CHECK_TYPE([u_char], ,
|
||||
[AC_DEFINE([u_char], [unsigned char], [Define to 'unsigned char if not defined])], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
# include <winsock2.h>
|
||||
#endif
|
||||
]) ])
|
||||
|
||||
dnl Detect if rlim_t type is defined, otherwise define it.
|
||||
AC_DEFUN([ACX_TYPE_RLIM_T],
|
||||
[AC_CHECK_TYPE(rlim_t, ,
|
||||
[AC_DEFINE([rlim_t], [unsigned long], [Define to 'int' if not defined])], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#if HAVE_SYS_RESOURCE_H
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
# include <sys/resource.h>
|
||||
#endif
|
||||
]) ])
|
||||
@@ -498,31 +521,34 @@ AC_DEFUN([ACX_TYPE_SOCKLEN_T],
|
||||
AC_CHECK_TYPE(socklen_t, ,
|
||||
[AC_DEFINE([socklen_t], [int], [Define to 'int' if not defined])], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#if HAVE_SYS_SOCKET_H
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
# include <ws2tcpip.h>
|
||||
#endif
|
||||
]) ])
|
||||
|
||||
dnl Detect if socklen_t type is defined, otherwise define it.
|
||||
dnl Detect if in_addr_t type is defined, otherwise define it.
|
||||
AC_DEFUN([ACX_TYPE_IN_ADDR_T],
|
||||
[ AC_CHECK_TYPE(in_addr_t, [], [AC_DEFINE([in_addr_t], [uint32_t], [in_addr_t])], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#if HAVE_NETINET_IN_H
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
# include <netinet/in.h>
|
||||
#endif
|
||||
]) ])
|
||||
|
||||
dnl Detect if socklen_t type is defined, otherwise define it.
|
||||
dnl Detect if in_port_t type is defined, otherwise define it.
|
||||
AC_DEFUN([ACX_TYPE_IN_PORT_T],
|
||||
[ AC_CHECK_TYPE(in_port_t, [], [AC_DEFINE([in_port_t], [uint16_t], [in_port_t])], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#if HAVE_NETINET_IN_H
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
# include <netinet/in.h>
|
||||
#endif
|
||||
]) ])
|
||||
@@ -535,12 +561,14 @@ AC_ARG_ENABLE(rpath,
|
||||
[ --disable-rpath disable hardcoded rpath (default=enabled)],
|
||||
enable_rpath=$enableval, enable_rpath=yes)
|
||||
if test "x$enable_rpath" = xno; then
|
||||
AC_MSG_RESULT([Fixing libtool for -rpath problems.])
|
||||
dnl AC_MSG_RESULT([Fixing libtool for -rpath problems.])
|
||||
AC_CONFIG_COMMANDS([disable-rpath], [
|
||||
sed < libtool > libtool-2 \
|
||||
's/^hardcode_libdir_flag_spec.*$'/'hardcode_libdir_flag_spec=" -D__LIBTOOL_RPATH_SED__ "/'
|
||||
mv libtool-2 libtool
|
||||
chmod 755 libtool
|
||||
libtool="./libtool"
|
||||
])
|
||||
fi
|
||||
])
|
||||
|
||||
@@ -555,7 +583,102 @@ AC_DEFUN([ACX_RUNTIME_PATH_ADD], [
|
||||
fi
|
||||
])
|
||||
|
||||
dnl Check for SSL.
|
||||
dnl Common code for both ACX_WITH_SSL and ACX_WITH_SSL_OPTIONAL
|
||||
dnl Takes one argument; the withval checked in those 2 functions
|
||||
dnl sets up the environment for the given openssl path
|
||||
AC_DEFUN([ACX_SSL_CHECKS], [
|
||||
withval=$1
|
||||
if test x_$withval != x_no; then
|
||||
AC_MSG_CHECKING(for SSL)
|
||||
if test x_$withval = x_ -o x_$withval = x_yes; then
|
||||
withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr"
|
||||
fi
|
||||
for dir in $withval; do
|
||||
ssldir="$dir"
|
||||
if test -f "$dir/include/openssl/ssl.h"; then
|
||||
found_ssl="yes"
|
||||
AC_DEFINE_UNQUOTED([HAVE_SSL], [], [Define if you have the SSL libraries installed.])
|
||||
dnl assume /usr/include is already in the include-path.
|
||||
if test "$ssldir" != "/usr"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$ssldir/include"
|
||||
LIBSSL_CPPFLAGS="$LIBSSL_CPPFLAGS -I$ssldir/include"
|
||||
fi
|
||||
break;
|
||||
fi
|
||||
done
|
||||
if test x_$found_ssl != x_yes; then
|
||||
AC_MSG_ERROR(Cannot find the SSL libraries in $withval)
|
||||
else
|
||||
AC_MSG_RESULT(found in $ssldir)
|
||||
HAVE_SSL=yes
|
||||
dnl assume /usr is already in the lib and dynlib paths.
|
||||
if test "$ssldir" != "/usr" -a "$ssldir" != ""; then
|
||||
LDFLAGS="$LDFLAGS -L$ssldir/lib"
|
||||
LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir/lib"
|
||||
ACX_RUNTIME_PATH_ADD([$ssldir/lib])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for HMAC_CTX_init in -lcrypto])
|
||||
LIBS="$LIBS -lcrypto"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto"
|
||||
AC_TRY_LINK(, [
|
||||
int HMAC_CTX_init(void);
|
||||
(void)HMAC_CTX_init();
|
||||
], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
|
||||
[If you have HMAC_CTX_init])
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
# check if -lwsock32 or -lgdi32 are needed.
|
||||
BAKLIBS="$LIBS"
|
||||
BAKSSLLIBS="$LIBSSL_LIBS"
|
||||
LIBS="$LIBS -lgdi32"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -lgdi32])
|
||||
AC_TRY_LINK([], [
|
||||
int HMAC_CTX_init(void);
|
||||
(void)HMAC_CTX_init();
|
||||
],[
|
||||
AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
|
||||
[If you have HMAC_CTX_init])
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
LIBS="$BAKLIBS"
|
||||
LIBSSL_LIBS="$BAKSSLLIBS"
|
||||
LIBS="$LIBS -ldl"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -ldl])
|
||||
AC_TRY_LINK([], [
|
||||
int HMAC_CTX_init(void);
|
||||
(void)HMAC_CTX_init();
|
||||
],[
|
||||
AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
|
||||
[If you have HMAC_CTX_init])
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
|
||||
])
|
||||
])
|
||||
])
|
||||
fi
|
||||
AC_SUBST(HAVE_SSL)
|
||||
AC_SUBST(RUNTIME_PATH)
|
||||
# openssl engine functionality needs dlopen().
|
||||
BAKLIBS="$LIBS"
|
||||
AC_SEARCH_LIBS([dlopen], [dl])
|
||||
if test "$LIBS" != "$BAKLIBS"; then
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
|
||||
fi
|
||||
fi
|
||||
AC_CHECK_HEADERS([openssl/ssl.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([openssl/err.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([openssl/rand.h],,, [AC_INCLUDES_DEFAULT])
|
||||
])dnl End of ACX_SSL_CHECKS
|
||||
|
||||
dnl Check for SSL, where SSL is mandatory
|
||||
dnl Adds --with-ssl option, searches for openssl and defines HAVE_SSL if found
|
||||
dnl Setup of CPPFLAGS, CFLAGS. Adds -lcrypto to LIBS.
|
||||
dnl Checks main header files of SSL.
|
||||
@@ -571,83 +694,25 @@ AC_ARG_WITH(ssl, AC_HELP_STRING([--with-ssl=pathname],
|
||||
if test x_$withval = x_no; then
|
||||
AC_MSG_ERROR([Need SSL library to do digital signature cryptography])
|
||||
fi
|
||||
if test x_$withval != x_no; then
|
||||
AC_MSG_CHECKING(for SSL)
|
||||
if test x_$withval = x_ -o x_$withval = x_yes; then
|
||||
withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr"
|
||||
fi
|
||||
for dir in $withval; do
|
||||
ssldir="$dir"
|
||||
if test -f "$dir/include/openssl/ssl.h"; then
|
||||
found_ssl="yes"
|
||||
AC_DEFINE_UNQUOTED([HAVE_SSL], [], [Define if you have the SSL libraries installed.])
|
||||
dnl assume /usr/include is already in the include-path.
|
||||
if test "$ssldir" != "/usr"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$ssldir/include"
|
||||
fi
|
||||
break;
|
||||
fi
|
||||
done
|
||||
if test x_$found_ssl != x_yes; then
|
||||
AC_MSG_ERROR(Cannot find the SSL libraries in $withval)
|
||||
else
|
||||
AC_MSG_RESULT(found in $ssldir)
|
||||
HAVE_SSL=yes
|
||||
dnl assume /usr is already in the lib and dynlib paths.
|
||||
if test "$ssldir" != "/usr" -a "$ssldir" != ""; then
|
||||
LDFLAGS="$LDFLAGS -L$ssldir/lib"
|
||||
ACX_RUNTIME_PATH_ADD([$ssldir/lib])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for HMAC_CTX_init in -lcrypto])
|
||||
LIBS="$LIBS -lcrypto"
|
||||
AC_TRY_LINK(, [
|
||||
int HMAC_CTX_init(void);
|
||||
(void)HMAC_CTX_init();
|
||||
], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
|
||||
[If you have HMAC_CTX_init])
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
# check if -lwsock32 or -lgdi32 are needed.
|
||||
BAKLIBS="$LIBS"
|
||||
LIBS="$LIBS -lgdi32"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -lgdi32])
|
||||
AC_TRY_LINK([], [
|
||||
int HMAC_CTX_init(void);
|
||||
(void)HMAC_CTX_init();
|
||||
],[
|
||||
AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
|
||||
[If you have HMAC_CTX_init])
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
LIBS="$BAKLIBS"
|
||||
LIBS="$LIBS -ldl"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -ldl])
|
||||
AC_TRY_LINK([], [
|
||||
int HMAC_CTX_init(void);
|
||||
(void)HMAC_CTX_init();
|
||||
],[
|
||||
AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
|
||||
[If you have HMAC_CTX_init])
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
|
||||
])
|
||||
])
|
||||
])
|
||||
fi
|
||||
AC_SUBST(HAVE_SSL)
|
||||
AC_SUBST(RUNTIME_PATH)
|
||||
fi
|
||||
AC_CHECK_HEADERS([openssl/ssl.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([openssl/err.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([openssl/rand.h],,, [AC_INCLUDES_DEFAULT])
|
||||
ACX_SSL_CHECKS($withval)
|
||||
])dnl End of ACX_WITH_SSL
|
||||
|
||||
dnl Check for SSL, where ssl is optional (--without-ssl is allowed)
|
||||
dnl Adds --with-ssl option, searches for openssl and defines HAVE_SSL if found
|
||||
dnl Setup of CPPFLAGS, CFLAGS. Adds -lcrypto to LIBS.
|
||||
dnl Checks main header files of SSL.
|
||||
dnl
|
||||
AC_DEFUN([ACX_WITH_SSL_OPTIONAL],
|
||||
[
|
||||
AC_ARG_WITH(ssl, AC_HELP_STRING([--with-ssl=pathname],
|
||||
[enable SSL (will check /usr/local/ssl
|
||||
/usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr)]),[
|
||||
],[
|
||||
withval="yes"
|
||||
])
|
||||
ACX_SSL_CHECKS($withval)
|
||||
])dnl End of ACX_WITH_SSL_OPTIONAL
|
||||
|
||||
dnl Setup to use -lssl
|
||||
dnl To use -lcrypto, use the ACX_WITH_SSL setup (before this one).
|
||||
AC_DEFUN([ACX_LIB_SSL],
|
||||
@@ -779,6 +844,10 @@ dnl a nonblocking socket do not work, a new call to select is necessary.
|
||||
AC_DEFUN([ACX_CHECK_NONBLOCKING_BROKEN],
|
||||
[
|
||||
AC_MSG_CHECKING([if nonblocking sockets work])
|
||||
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([
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -904,6 +973,7 @@ AC_RUN_IFELSE(AC_LANG_PROGRAM([
|
||||
], [
|
||||
AC_MSG_RESULT([crosscompile(yes)])
|
||||
])
|
||||
fi
|
||||
])dnl End of ACX_CHECK_NONBLOCKING_BROKEN
|
||||
|
||||
dnl Check if mkdir has one or two arguments.
|
||||
@@ -947,6 +1017,16 @@ AC_DEFINE(HAVE_IOCTLSOCKET, 1, [if the function 'ioctlsocket' is available])
|
||||
],[AC_MSG_RESULT(no)])
|
||||
])dnl end of ACX_FUNC_IOCTLSOCKET
|
||||
|
||||
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
|
||||
])
|
||||
|
||||
dnl Define fallback for fseeko and ftello if needed.
|
||||
AC_DEFUN([AHX_CONFIG_FSEEKO],
|
||||
[
|
||||
@@ -1033,6 +1113,16 @@ void *memmove(void *dest, const void *src, size_t n);
|
||||
#endif
|
||||
])
|
||||
|
||||
dnl provide strlcat compat prototype.
|
||||
dnl $1: unique name for compat code
|
||||
AC_DEFUN([AHX_CONFIG_STRLCAT],
|
||||
[
|
||||
#ifndef HAVE_STRLCAT
|
||||
#define strlcat strlcat_$1
|
||||
size_t strlcat(char *dst, const char *src, size_t siz);
|
||||
#endif
|
||||
])
|
||||
|
||||
dnl provide strlcpy compat prototype.
|
||||
dnl $1: unique name for compat code
|
||||
AC_DEFUN([AHX_CONFIG_STRLCPY],
|
||||
@@ -1103,7 +1193,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
|
||||
])
|
||||
|
||||
@@ -1134,7 +1224,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.
|
||||
@@ -1149,4 +1239,72 @@ AHX_CONFIG_FLAG_EXT(-D_ALL_SOURCE)
|
||||
AHX_CONFIG_FLAG_EXT(-D_LARGEFILE_SOURCE=1)
|
||||
])
|
||||
|
||||
dnl check if memcmp is using signed characters and replace if so.
|
||||
AC_DEFUN([ACX_CHECK_MEMCMP_SIGNED],
|
||||
[AC_MSG_CHECKING([if memcmp compares unsigned])
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
int main(void)
|
||||
{
|
||||
char a = 255, b = 0;
|
||||
if(memcmp(&a, &b, 1) < 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
]])], [AC_MSG_RESULT([yes]) ],
|
||||
[ AC_MSG_RESULT([no])
|
||||
AC_DEFINE([MEMCMP_IS_BROKEN], [1], [Define if memcmp() does not compare unsigned bytes])
|
||||
AC_LIBOBJ([memcmp])
|
||||
], [ AC_MSG_RESULT([cross-compile no])
|
||||
AC_DEFINE([MEMCMP_IS_BROKEN], [1], [Define if memcmp() does not compare unsigned bytes])
|
||||
AC_LIBOBJ([memcmp])
|
||||
]) ])
|
||||
|
||||
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
|
||||
#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
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/* taken from ldns 1.6.1 */
|
||||
#include "config.h"
|
||||
#ifdef HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include "util/locks.h"
|
||||
|
||||
/** the lock for ctime buffer */
|
||||
static lock_basic_t ctime_lock;
|
||||
/** has it been inited */
|
||||
static int ctime_r_init = 0;
|
||||
|
||||
/** cleanup ctime_r on exit */
|
||||
static void
|
||||
ctime_r_cleanup(void)
|
||||
{
|
||||
if(ctime_r_init) {
|
||||
ctime_r_init = 0;
|
||||
lock_basic_destroy(&ctime_lock);
|
||||
}
|
||||
}
|
||||
|
||||
char *ctime_r(const time_t *timep, char *buf)
|
||||
{
|
||||
char* result;
|
||||
if(!ctime_r_init) {
|
||||
/* still small race where this init can be done twice,
|
||||
* which is mostly harmless */
|
||||
ctime_r_init = 1;
|
||||
lock_basic_init(&ctime_lock);
|
||||
atexit(&ctime_r_cleanup);
|
||||
}
|
||||
lock_basic_lock(&ctime_lock);
|
||||
result = ctime(timep);
|
||||
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;
|
||||
}
|
||||
+1
-2
@@ -3,7 +3,6 @@
|
||||
|
||||
#include "config.h"
|
||||
#undef malloc
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
void *malloc ();
|
||||
@@ -12,7 +11,7 @@ void *malloc ();
|
||||
If N is zero, allocate a 1-byte block. */
|
||||
|
||||
void *
|
||||
rpl_malloc (size_t n)
|
||||
rpl_malloc_unbound (size_t n)
|
||||
{
|
||||
if (n == 0)
|
||||
n = 1;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* memcmp.c: memcmp compat implementation.
|
||||
*
|
||||
* Copyright (c) 2010, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* See LICENSE for the license.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
int memcmp(const void *x, const void *y, size_t n);
|
||||
|
||||
int memcmp(const void *x, const void *y, size_t n)
|
||||
{
|
||||
const uint8_t* x8 = (const uint8_t*)x;
|
||||
const uint8_t* y8 = (const uint8_t*)y;
|
||||
size_t i;
|
||||
for(i=0; i<n; i++) {
|
||||
if(x8[i] < y8[i])
|
||||
return -1;
|
||||
else if(x8[i] > y8[i])
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+34
-14
@@ -40,6 +40,9 @@
|
||||
* gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
|
||||
* and run snprintf for results.
|
||||
*
|
||||
* Wouter Wijngaards(wouter@nlnetlabs.nl) 2/09/2010 for unbound.
|
||||
* Limited support for %g. Does not do the exponents for the before-dot.
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
|
||||
@@ -75,7 +78,7 @@ static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
|
||||
static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
|
||||
long value, int base, int min, int max, int flags);
|
||||
static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
|
||||
long double fvalue, int min, int max, int flags);
|
||||
long double fvalue, int min, int max, int flags, int conv);
|
||||
static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c );
|
||||
|
||||
int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
|
||||
@@ -313,7 +316,7 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
|
||||
else
|
||||
fvalue = va_arg (args, double);
|
||||
/* um, floating point? */
|
||||
fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
|
||||
fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags, 'f');
|
||||
break;
|
||||
case 'E':
|
||||
flags |= DP_F_UP;
|
||||
@@ -330,6 +333,7 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
|
||||
fvalue = va_arg (args, long double);
|
||||
else
|
||||
fvalue = va_arg (args, double);
|
||||
fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags, 'g');
|
||||
break;
|
||||
case 'c':
|
||||
dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
|
||||
@@ -554,7 +558,7 @@ static long compat_round (long double value)
|
||||
}
|
||||
|
||||
static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
|
||||
long double fvalue, int min, int max, int flags)
|
||||
long double fvalue, int min, int max, int flags, int conv)
|
||||
{
|
||||
int signvalue = 0;
|
||||
long double ufvalue;
|
||||
@@ -628,13 +632,26 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
|
||||
fconvert[fplace++] =
|
||||
(caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10];
|
||||
fracpart = (fracpart / 10);
|
||||
if(conv == 'g' && fplace == 1 && fconvert[0] == '0') {
|
||||
fplace = 0; /* skip trailing zeroes for %g */
|
||||
zpadlen ++;
|
||||
}
|
||||
} while(fracpart && (fplace < 20));
|
||||
if (fplace == 20) fplace--;
|
||||
fconvert[fplace] = 0;
|
||||
|
||||
/* -1 for decimal point, another -1 if we are printing a sign */
|
||||
padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
|
||||
zpadlen = max - fplace;
|
||||
if(conv == 'f') {
|
||||
/* -1 for decimal point, another -1 if we are printing a sign */
|
||||
padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
|
||||
zpadlen = max - fplace;
|
||||
} else if(conv == 'g') {
|
||||
/* zpadlen contains number of trailing zeroes removed */
|
||||
padlen = min - iplace - (max-zpadlen) - 1 - ((signvalue) ? 1 : 0);
|
||||
if(fplace == 0) {
|
||||
padlen += 1; /* add the decimal dot suppressed */
|
||||
zpadlen = 0;
|
||||
} else zpadlen = (max-zpadlen) - fplace;
|
||||
}
|
||||
if (zpadlen < 0)
|
||||
zpadlen = 0;
|
||||
if (padlen < 0)
|
||||
@@ -667,14 +684,14 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
|
||||
while (iplace > 0)
|
||||
dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
|
||||
|
||||
/*
|
||||
* Decimal point. This should probably use locale to find the correct
|
||||
* char to print out.
|
||||
*/
|
||||
dopr_outch (buffer, currlen, maxlen, '.');
|
||||
|
||||
while (fplace > 0)
|
||||
dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
|
||||
/* for %g do not output decimal point if no fraction is present */
|
||||
if(conv == 'f' || (conv == 'g' && fplace > 0)) {
|
||||
/*
|
||||
* Decimal point. This should probably use locale to find the correct
|
||||
* char to print out.
|
||||
*/
|
||||
dopr_outch (buffer, currlen, maxlen, '.');
|
||||
}
|
||||
|
||||
while (zpadlen > 0)
|
||||
{
|
||||
@@ -682,6 +699,9 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
|
||||
--zpadlen;
|
||||
}
|
||||
|
||||
while (fplace > 0)
|
||||
dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
|
||||
|
||||
while (padlen < 0)
|
||||
{
|
||||
dopr_outch (buffer, currlen, maxlen, ' ');
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
/** 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, alt_format, ret;
|
||||
int split_year = 0;
|
||||
|
||||
while ((c = *format) != '\0') {
|
||||
alt_format = 0;
|
||||
|
||||
/* whitespace, literal or format */
|
||||
if (isspace(c)) { /* whitespace */
|
||||
/** whitespace matches zero or more whitespace characters in the
|
||||
* 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
+90
-131
@@ -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='2008-11-15'
|
||||
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='2008-11-15'
|
||||
# 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?
|
||||
@@ -324,12 +324,18 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
case `/usr/bin/uname -p` in
|
||||
sparc) echo sparc-icl-nx7; exit ;;
|
||||
esac ;;
|
||||
s390x:SunOS:*:*)
|
||||
echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit ;;
|
||||
sun4H:SunOS:5.*:*)
|
||||
echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit ;;
|
||||
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"
|
||||
@@ -337,7 +343,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
|
||||
# This test works for both compilers.
|
||||
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
|
||||
if echo '\n#ifdef __amd64\nIS_64BIT_ARCH\n#endif' | \
|
||||
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_64BIT_ARCH >/dev/null
|
||||
then
|
||||
@@ -653,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
|
||||
@@ -804,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)
|
||||
@@ -819,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
|
||||
@@ -848,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 \
|
||||
@@ -870,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 ;;
|
||||
@@ -879,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
|
||||
@@ -959,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
|
||||
@@ -983,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
|
||||
@@ -1071,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:*:*)
|
||||
@@ -1115,8 +1048,11 @@ EOF
|
||||
pc:*:*:*)
|
||||
# Left here for compatibility:
|
||||
# uname -m prints for DJGPP always 'pc', but it prints nothing about
|
||||
# the processor, so we play safe by assuming i386.
|
||||
echo i386-pc-msdosdjgpp
|
||||
# the processor, so we play safe by assuming i586.
|
||||
# Note: whatever this is, it MUST be the same as what config.sub
|
||||
# prints for the "djgpp" host, or else GDB configury will decide that
|
||||
# this is a cross-build.
|
||||
echo i586-pc-msdosdjgpp
|
||||
exit ;;
|
||||
Intel:Mach:3*:*)
|
||||
echo i386-pc-mach3
|
||||
@@ -1154,6 +1090,16 @@ EOF
|
||||
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
|
||||
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
|
||||
&& { echo i486-ncr-sysv4; exit; } ;;
|
||||
NCR*:*:4.2:* | MPRAS*:*:4.2:*)
|
||||
OS_REL='.3'
|
||||
test -r /etc/.relid \
|
||||
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
|
||||
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
|
||||
&& { echo i486-ncr-sysv4.3${OS_REL}; exit; }
|
||||
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
|
||||
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; }
|
||||
/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
|
||||
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
|
||||
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
|
||||
echo m68k-unknown-lynxos${UNAME_RELEASE}
|
||||
exit ;;
|
||||
@@ -1166,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:*:*)
|
||||
@@ -1259,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}
|
||||
@@ -1340,6 +1296,9 @@ EOF
|
||||
i*86:rdos:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-rdos
|
||||
exit ;;
|
||||
i*86:AROS:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-aros
|
||||
exit ;;
|
||||
esac
|
||||
|
||||
#echo '(No uname command or uname output not recognized.)' 1>&2
|
||||
|
||||
+106
-26
@@ -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
|
||||
@@ -31,15 +40,23 @@
|
||||
/* Define to 1 if you have the `chroot' function. */
|
||||
#undef HAVE_CHROOT
|
||||
|
||||
/* Define to 1 if you have the `ctime_r' function. */
|
||||
#undef HAVE_CTIME_R
|
||||
|
||||
/* Define to 1 if you have the `daemon' function. */
|
||||
#undef HAVE_DAEMON
|
||||
|
||||
/* 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
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define to 1 if you have the `ENGINE_load_gost' function. */
|
||||
#undef HAVE_ENGINE_LOAD_GOST
|
||||
|
||||
/* Define to 1 if you have the `event_base_free' function. */
|
||||
#undef HAVE_EVENT_BASE_FREE
|
||||
|
||||
@@ -64,9 +81,15 @@
|
||||
/* 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
|
||||
|
||||
@@ -121,9 +144,18 @@
|
||||
/* if the function 'ioctlsocket' is available */
|
||||
#undef HAVE_IOCTLSOCKET
|
||||
|
||||
/* Define to 1 if you have the <iphlpapi.h> header file. */
|
||||
#undef HAVE_IPHLPAPI_H
|
||||
|
||||
/* 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
|
||||
|
||||
/* Define to 1 if you have the `ldns' library (-lldns). */
|
||||
#undef HAVE_LIBLDNS
|
||||
|
||||
@@ -149,6 +181,15 @@
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#undef HAVE_NETINET_IN_H
|
||||
|
||||
/* Define to 1 if you have the `OPENSSL_config' function. */
|
||||
#undef HAVE_OPENSSL_CONFIG
|
||||
|
||||
/* Define to 1 if you have the <openssl/conf.h> header file. */
|
||||
#undef HAVE_OPENSSL_CONF_H
|
||||
|
||||
/* Define to 1 if you have the <openssl/engine.h> header file. */
|
||||
#undef HAVE_OPENSSL_ENGINE_H
|
||||
|
||||
/* Define to 1 if you have the <openssl/err.h> header file. */
|
||||
#undef HAVE_OPENSSL_ERR_H
|
||||
|
||||
@@ -197,6 +238,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
|
||||
|
||||
@@ -212,6 +256,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
|
||||
|
||||
@@ -245,6 +292,9 @@
|
||||
/* 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 if you have Swig libraries and header files. */
|
||||
#undef HAVE_SWIG
|
||||
|
||||
@@ -314,6 +364,9 @@
|
||||
/* Define to 1 if you have the `_beginthreadex' function. */
|
||||
#undef HAVE__BEGINTHREADEX
|
||||
|
||||
/* if lex has yylex_destroy */
|
||||
#undef LEX_HAS_YYLEX_DESTROY
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#undef LT_OBJDIR
|
||||
@@ -321,6 +374,9 @@
|
||||
/* Define to the maximum message length to pass to syslog. */
|
||||
#undef MAXSYSLOGMSGLEN
|
||||
|
||||
/* Define if memcmp() does not compare unsigned bytes */
|
||||
#undef MEMCMP_IS_BROKEN
|
||||
|
||||
/* Define if mkdir has one argument. */
|
||||
#undef MKDIR_HAS_ONE_ARG
|
||||
|
||||
@@ -364,6 +420,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
|
||||
|
||||
@@ -377,6 +436,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
|
||||
|
||||
@@ -389,18 +454,30 @@
|
||||
/* 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
|
||||
|
||||
/* default username */
|
||||
#undef UB_USERNAME
|
||||
|
||||
/* use to enable lightweight alloc assertions, for debug use */
|
||||
#undef UNBOUND_ALLOC_LITE
|
||||
|
||||
/* use malloc not regions, for debug use */
|
||||
#undef UNBOUND_ALLOC_NONREGIONAL
|
||||
|
||||
/* use statistics for allocs and frees, for debug use */
|
||||
#undef UNBOUND_ALLOC_STATS
|
||||
|
||||
/* define this to enable debug checks. */
|
||||
#undef UNBOUND_DEBUG
|
||||
|
||||
/* Define this to enable GOST support. */
|
||||
#undef USE_GOST
|
||||
|
||||
/* Define if you want to use internal select based events */
|
||||
#undef USE_MINI_EVENT
|
||||
|
||||
@@ -494,7 +571,7 @@
|
||||
/* Define to `signed char' if <sys/types.h> does not define. */
|
||||
#undef int8_t
|
||||
|
||||
/* Define to rpl_malloc if the replacement function should be used. */
|
||||
/* Define if replacement function should be used. */
|
||||
#undef malloc
|
||||
|
||||
/* Define to `long int' if <sys/types.h> does not define. */
|
||||
@@ -515,7 +592,7 @@
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#undef ssize_t
|
||||
|
||||
/* Define to `unsigned char' if <sys/types.h> does not define. */
|
||||
/* Define to 'unsigned char if not defined */
|
||||
#undef u_char
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
@@ -619,18 +696,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_ATTR_FORMAT
|
||||
@@ -658,11 +723,6 @@
|
||||
#endif /* HAVE_FSEEKO */
|
||||
|
||||
|
||||
#ifndef RAND_MAX
|
||||
#define RAND_MAX 2147483647
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 256
|
||||
#endif
|
||||
@@ -746,8 +806,28 @@ struct tm *gmtime_r(const time_t *timep, struct tm *result);
|
||||
#endif /* IPV6_MIN_MTU */
|
||||
|
||||
|
||||
#ifdef MEMCMP_IS_BROKEN
|
||||
# ifdef memcmp
|
||||
# undef memcmp
|
||||
# endif
|
||||
#define memcmp memcmp_unbound
|
||||
int memcmp(const void *x, const void *y, size_t n);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_EVENT_H) && !defined(HAVE_EVENT_BASE_ONCE) && (defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS))
|
||||
|
||||
|
||||
#ifndef HAVE_CTIME_R
|
||||
#define ctime_r unbound_ctime_r
|
||||
char *ctime_r(const time_t *timep, char *buf);
|
||||
#endif
|
||||
|
||||
#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
|
||||
@@ -768,8 +848,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__)
|
||||
@@ -787,7 +865,9 @@ void unbound_stat_free_log(void *ptr, const char* file, int line,
|
||||
const char* func);
|
||||
void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
||||
int line, const char* func);
|
||||
#endif /* UNBOUND_ALLOC_STATS */
|
||||
#elif defined(UNBOUND_ALLOC_LITE)
|
||||
# include "util/alloc.h"
|
||||
#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */
|
||||
|
||||
/** default port for DNS traffic. */
|
||||
#define UNBOUND_DNS_PORT 53
|
||||
|
||||
Vendored
+43
-15
@@ -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='2008-09-08'
|
||||
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='2008-09-08'
|
||||
|
||||
|
||||
# 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.
|
||||
@@ -122,6 +125,7 @@ maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
|
||||
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
|
||||
kopensolaris*-gnu* | \
|
||||
storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
os=-$maybe_os
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
@@ -148,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
|
||||
@@ -249,6 +256,7 @@ case $basic_machine in
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k | iq2000 \
|
||||
| lm32 \
|
||||
| m32c | m32r | m32rle | m68000 | m68k | m88k \
|
||||
| maxq | mb | microblaze | mcore | mep | metag \
|
||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||
@@ -270,6 +278,7 @@ case $basic_machine in
|
||||
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||
| mipstx39 | mipstx39el \
|
||||
| mn10200 | mn10300 \
|
||||
| moxie \
|
||||
| mt \
|
||||
| msp430 \
|
||||
| nios | nios2 \
|
||||
@@ -278,20 +287,22 @@ case $basic_machine in
|
||||
| pdp10 | pdp11 | pj | pjl \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
||||
| pyramid \
|
||||
| rx \
|
||||
| score \
|
||||
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh64 | sh64le \
|
||||
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
|
||||
| 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
|
||||
@@ -331,9 +342,10 @@ case $basic_machine in
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
| ip2k-* | iq2000-* \
|
||||
| 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-* \
|
||||
@@ -361,8 +373,8 @@ case $basic_machine in
|
||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
||||
| pyramid-* \
|
||||
| romp-* | rs6000-* \
|
||||
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
||||
| romp-* | rs6000-* | rx-* \
|
||||
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
||||
| sparclite-* \
|
||||
@@ -370,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]-* \
|
||||
@@ -443,6 +456,10 @@ case $basic_machine in
|
||||
basic_machine=m68k-apollo
|
||||
os=-bsd
|
||||
;;
|
||||
aros)
|
||||
basic_machine=i386-pc
|
||||
os=-aros
|
||||
;;
|
||||
aux)
|
||||
basic_machine=m68k-apple
|
||||
os=-aux
|
||||
@@ -459,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
|
||||
@@ -711,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
|
||||
@@ -1182,7 +1206,7 @@ case $basic_machine in
|
||||
we32k)
|
||||
basic_machine=we32k-att
|
||||
;;
|
||||
sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
|
||||
sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
|
||||
basic_machine=sh-unknown
|
||||
;;
|
||||
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
|
||||
@@ -1232,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|'`
|
||||
;;
|
||||
@@ -1252,10 +1279,11 @@ 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* \
|
||||
| -*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* \
|
||||
| -aos* | -aros* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
|
||||
@@ -1274,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*)
|
||||
@@ -1604,7 +1632,7 @@ case $basic_machine in
|
||||
-sunos*)
|
||||
vendor=sun
|
||||
;;
|
||||
-aix*)
|
||||
-cnk*|-aix*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-beos*)
|
||||
|
||||
+302
-84
@@ -6,10 +6,10 @@ sinclude(acx_pthread.m4)
|
||||
sinclude(acx_python.m4)
|
||||
sinclude(ac_pkg_swig.m4)
|
||||
|
||||
AC_INIT(unbound, 1.3.2, unbound-bugs@nlnetlabs.nl, unbound)
|
||||
AC_INIT(unbound, 1.4.7, unbound-bugs@nlnetlabs.nl, unbound)
|
||||
|
||||
LIBUNBOUND_CURRENT=1
|
||||
LIBUNBOUND_REVISION=2
|
||||
LIBUNBOUND_CURRENT=2
|
||||
LIBUNBOUND_REVISION=7
|
||||
LIBUNBOUND_AGE=0
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@@ -21,6 +21,17 @@ LIBUNBOUND_AGE=0
|
||||
# 1.3.0 had 1:0:0 # ub_cancel and -export-symbols.
|
||||
# 1.3.1 had 1:1:0
|
||||
# 1.3.2 had 1:2:0
|
||||
# 1.3.3 had 1:3:0
|
||||
# 1.3.4 had 1:4:0
|
||||
# 1.4.0-snapshots had 1:5:0
|
||||
# 1.4.0 had 1:5:0 (not 2:0:0) # ub_result.why_bogus
|
||||
# 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
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -44,6 +55,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
|
||||
|
||||
@@ -58,7 +82,10 @@ esac
|
||||
|
||||
# are we on MinGW?
|
||||
if uname -s 2>&1 | grep MINGW32 >/dev/null; then on_mingw="yes"
|
||||
else on_mingw="no"; fi
|
||||
else
|
||||
if echo $target | grep mingw32 >/dev/null; then on_mingw="yes"
|
||||
else on_mingw="no"; fi
|
||||
fi
|
||||
|
||||
#
|
||||
# Determine configuration file
|
||||
@@ -127,6 +154,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)]),
|
||||
@@ -148,15 +203,13 @@ 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(debug, AC_HELP_STRING([--enable-debug], [Enable debug warnings, asserts, makefile-dependencies]))
|
||||
debug_enabled="$enable_debug"
|
||||
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]))
|
||||
if test "$enable_debug" = "yes"; then debug_enabled="$enable_debug";
|
||||
else debug_enabled="$enable_checking"; fi
|
||||
AC_SUBST(debug_enabled)
|
||||
case "$enable_debug" in
|
||||
case "$debug_enabled" in
|
||||
yes)
|
||||
ACX_CHECK_COMPILER_FLAG(W, [CFLAGS="$CFLAGS -W"])
|
||||
ACX_CHECK_COMPILER_FLAG(Wall, [CFLAGS="$CFLAGS -Wall"])
|
||||
@@ -177,9 +230,19 @@ if test "$srcdir" != "."; then
|
||||
CPPFLAGS="$CPPFLAGS -I$srcdir"
|
||||
fi
|
||||
|
||||
AC_DEFUN([ACX_YYLEX_DESTROY], [
|
||||
AC_MSG_CHECKING([for yylex_destroy])
|
||||
if echo %% | $LEX -t 2>&1 | grep yylex_destroy >/dev/null 2>&1; then
|
||||
AC_DEFINE(LEX_HAS_YYLEX_DESTROY, 1, [if lex has yylex_destroy])
|
||||
AC_MSG_RESULT(yes)
|
||||
else AC_MSG_RESULT(no); fi
|
||||
])
|
||||
|
||||
AC_PROG_LEX
|
||||
ACX_YYLEX_DESTROY
|
||||
AC_PROG_YACC
|
||||
AC_CHECK_PROG(doxygen, doxygen, doxygen)
|
||||
AC_CHECK_TOOL(STRIP, strip)
|
||||
ACX_LIBTOOL_C_ONLY
|
||||
|
||||
# Checks for header files.
|
||||
@@ -205,9 +268,45 @@ ACX_TYPE_RLIM_T
|
||||
ACX_TYPE_SOCKLEN_T
|
||||
ACX_TYPE_IN_ADDR_T
|
||||
ACX_TYPE_IN_PORT_T
|
||||
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 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
|
||||
|
||||
# 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_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)
|
||||
)
|
||||
|
||||
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
|
||||
@@ -249,23 +348,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,
|
||||
@@ -297,6 +380,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
|
||||
@@ -345,22 +429,51 @@ fi
|
||||
# Checks for libraries.
|
||||
ACX_WITH_SSL
|
||||
ACX_LIB_SSL
|
||||
AC_CHECK_FUNCS([EVP_sha1 EVP_sha256 EVP_sha512 ENGINE_load_gost])
|
||||
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,sk_SSL_COMP_pop_free], [], [], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
|
||||
AC_ARG_ENABLE(sha2, AC_HELP_STRING([--enable-sha2], [Enable SHA256 and SHA512 RRSIG support]))
|
||||
#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
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/evp.h>
|
||||
])
|
||||
|
||||
AC_ARG_ENABLE(sha2, AC_HELP_STRING([--disable-sha2], [Disable SHA256 and SHA512 RRSIG support]))
|
||||
case "$enable_sha2" in
|
||||
yes)
|
||||
AC_DEFINE_UNQUOTED([USE_SHA2], [], [Define this to enable SHA256 and SHA512 support.])
|
||||
no)
|
||||
;;
|
||||
no|*)
|
||||
yes|*)
|
||||
AC_DEFINE([USE_SHA2], [1], [Define this to enable SHA256 and SHA512 support.])
|
||||
;;
|
||||
esac
|
||||
|
||||
# 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(gost, AC_HELP_STRING([--disable-gost], [Disable GOST support]))
|
||||
use_gost="no"
|
||||
case "$enable_gost" in
|
||||
no)
|
||||
;;
|
||||
*)
|
||||
AC_CHECK_FUNC(EVP_PKEY_set_type_str, [:],[AC_MSG_ERROR([OpenSSL 1.0.0 is needed for GOST support])])
|
||||
AC_CHECK_FUNC(EC_KEY_new, [], [AC_MSG_ERROR([OpenSSL does not support ECC, needed for GOST support])])
|
||||
use_gost="yes"
|
||||
AC_DEFINE([USE_GOST], [1], [Define this to enable GOST support.])
|
||||
;;
|
||||
esac
|
||||
|
||||
# check for libevent
|
||||
AC_ARG_WITH(libevent, AC_HELP_STRING([--with-libevent=pathname],
|
||||
@@ -393,9 +506,9 @@ if test x_$withval = x_yes -o x_$withval != x_no; then
|
||||
mkdir build >/dev/null 2>&1
|
||||
mkdir build/libevent >/dev/null 2>&1
|
||||
mkdir build/libevent/.libs >/dev/null 2>&1
|
||||
ev_files_o=`ls $thedir/*.o | grep -v evdns\.o`
|
||||
ev_files_lo=`ls $thedir/*.lo | grep -v evdns\.lo`
|
||||
ev_files_libso=`ls $thedir/.libs/*.o | grep -v evdns\.o`
|
||||
ev_files_o=`ls $thedir/*.o | grep -v evdns\.o | grep -v bufferevent_openssl\.o`
|
||||
ev_files_lo=`ls $thedir/*.lo | grep -v evdns\.lo | grep -v bufferevent_openssl\.lo`
|
||||
ev_files_libso=`ls $thedir/.libs/*.o | grep -v evdns\.o | grep -v bufferevent_openssl\.o`
|
||||
cp $ev_files_o build/libevent
|
||||
cp $ev_files_lo build/libevent
|
||||
cp $ev_files_libso build/libevent/.libs
|
||||
@@ -418,13 +531,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
|
||||
@@ -432,6 +553,29 @@ 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=""
|
||||
@@ -442,6 +586,10 @@ if test x_$enable_static_exe = x_yes; then
|
||||
staticexe="-static"
|
||||
if test "$on_mingw" = yes; then
|
||||
staticexe="-all-static"
|
||||
# for static crosscompile, include gdi32 and zlib here.
|
||||
if test "`uname`" = "Linux"; then
|
||||
LIBS="$LIBS -lgdi32 -lz"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -457,29 +605,43 @@ fi
|
||||
|
||||
# set memory allocation checking if requested
|
||||
AC_ARG_ENABLE(alloc-checks, AC_HELP_STRING([--enable-alloc-checks],
|
||||
[ enable to check memory allocation, for debug purposes ]),
|
||||
[ 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
|
||||
AC_FUNC_MALLOC
|
||||
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"
|
||||
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])
|
||||
@@ -489,16 +651,38 @@ if test $ac_cv_func_daemon = yes; then
|
||||
])
|
||||
fi
|
||||
|
||||
# check wether strptime also works
|
||||
AC_DEFUN([AC_CHECK_STRPTIME_WORKS],
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
AC_MSG_CHECKING(whether strptime works)
|
||||
if test c${cross_compiling} = cno; then
|
||||
AC_TRY_RUN([
|
||||
#define _XOPEN_SOURCE
|
||||
#include <time.h>
|
||||
int main(void) { struct tm tm; char *res;
|
||||
res = strptime("20070207111842", "%Y%m%d%H%M%S", &tm);
|
||||
if (!res) return 1; return 0; }
|
||||
] , [eval "ac_cv_c_strptime_works=yes"], [eval "ac_cv_c_strptime_works=no"])
|
||||
else
|
||||
eval "ac_cv_c_strptime_works=maybe"
|
||||
fi
|
||||
AC_MSG_RESULT($ac_cv_c_strptime_works)
|
||||
if test $ac_cv_c_strptime_works = no; then
|
||||
AC_LIBOBJ(strptime)
|
||||
else
|
||||
AC_DEFINE_UNQUOTED([STRPTIME_WORKS], 1, [use default strptime.])
|
||||
fi
|
||||
])dnl
|
||||
AC_CHECK_FUNCS([strptime],[AC_CHECK_STRPTIME_WORKS],[AC_LIBOBJ([strptime])])
|
||||
AC_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)
|
||||
@@ -506,6 +690,7 @@ AC_REPLACE_FUNCS(snprintf)
|
||||
AC_REPLACE_FUNCS(strlcpy)
|
||||
AC_REPLACE_FUNCS(memmove)
|
||||
AC_REPLACE_FUNCS(gmtime_r)
|
||||
AC_REPLACE_FUNCS(ctime_r)
|
||||
|
||||
# check this after all other compilation checks, since the linking of the lib
|
||||
# may break checks after this.
|
||||
@@ -513,13 +698,15 @@ 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" != ""; then
|
||||
CPPFLAGS="-I$withval/include $CPPFLAGS"
|
||||
LDFLAGS="-L$withval -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],
|
||||
@@ -530,12 +717,44 @@ AC_ARG_WITH(ldns-builtin, AC_HELP_STRING([--with-ldns-builtin],
|
||||
# check if ldns is good enough
|
||||
if test "$use_ldns_builtin" = "no"; then
|
||||
AC_CHECK_LIB(ldns, ldns_buffer_copy)
|
||||
if test $ac_cv_lib_ldns_ldns_buffer_copy = 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])])
|
||||
AC_CHECK_FUNC(ldns_key_buf2rsa_raw)
|
||||
AC_CHECK_FUNC(ldns_b32_ntop_extended_hex)
|
||||
if test x$use_gost = xyes; then
|
||||
AC_CHECK_FUNC(ldns_key_EVP_load_gost_id)
|
||||
AC_CHECK_FUNCS([ldns_key_EVP_unload_gost])
|
||||
else
|
||||
use_ldns_builtin="yes"
|
||||
ac_cv_func_ldns_key_EVP_load_gost_id="yes"
|
||||
fi
|
||||
AC_CHECK_HEADERS([ldns/ldns.h],,, [AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
])
|
||||
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 \
|
||||
-a $ac_cv_func_ldns_b32_ntop_extended_hex = yes \
|
||||
-a $ac_cv_func_ldns_key_EVP_load_gost_id = yes; then
|
||||
dnl ldns was found
|
||||
:
|
||||
else
|
||||
AC_MSG_ERROR([No ldns library found (or not recent); install or update ldns library, use --with-ldns=path or --with-ldns-builtin])
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -562,7 +781,7 @@ fi dnl end of use_ldns_builtin == yes
|
||||
ACX_STRIP_EXT_FLAGS
|
||||
LDFLAGS="$LATE_LDFLAGS $LDFLAGS"
|
||||
|
||||
AC_DEFINE_UNQUOTED([MAXSYSLOGMSGLEN], [5120], [Define to the maximum message length to pass to syslog.])
|
||||
AC_DEFINE_UNQUOTED([MAXSYSLOGMSGLEN], [10240], [Define to the maximum message length to pass to syslog.])
|
||||
|
||||
AH_BOTTOM(
|
||||
dnl this must be first AH_CONFIG, to define the flags before any includes.
|
||||
@@ -617,24 +836,11 @@ 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
|
||||
]
|
||||
|
||||
AHX_CONFIG_FORMAT_ATTRIBUTE
|
||||
AHX_CONFIG_UNUSED_ATTRIBUTE
|
||||
AHX_CONFIG_FSEEKO
|
||||
AHX_CONFIG_RAND_MAX
|
||||
AHX_CONFIG_MAXHOSTNAMELEN
|
||||
AHX_CONFIG_SNPRINTF(unbound)
|
||||
AHX_CONFIG_INET_PTON(unbound)
|
||||
@@ -649,9 +855,21 @@ AHX_CONFIG_W32_RANDOM
|
||||
AHX_CONFIG_W32_SRANDOM
|
||||
AHX_CONFIG_W32_FD_SET_T
|
||||
AHX_CONFIG_IPV6_MIN_MTU
|
||||
AHX_MEMCMP_BROKEN(unbound)
|
||||
|
||||
[
|
||||
#if defined(HAVE_EVENT_H) && !defined(HAVE_EVENT_BASE_ONCE) && (defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS))
|
||||
#ifndef HAVE_CTIME_R
|
||||
#define ctime_r unbound_ctime_r
|
||||
char *ctime_r(const time_t *timep, char *buf);
|
||||
#endif
|
||||
|
||||
#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
|
||||
@@ -672,8 +890,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__)
|
||||
@@ -691,12 +907,14 @@ void unbound_stat_free_log(void *ptr, const char* file, int line,
|
||||
const char* func);
|
||||
void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
||||
int line, const char* func);
|
||||
#endif /* UNBOUND_ALLOC_STATS */
|
||||
#elif defined(UNBOUND_ALLOC_LITE)
|
||||
# include "util/alloc.h"
|
||||
#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */
|
||||
|
||||
/** default port for DNS traffic. */
|
||||
#define UNBOUND_DNS_PORT 53
|
||||
])
|
||||
|
||||
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
|
||||
|
||||
@@ -8,9 +8,13 @@ distribution but may be helpful.
|
||||
* 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.
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#/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;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
Summary: Validating, recursive, and caching DNS resolver
|
||||
Name: unbound
|
||||
Version: 1.0.1
|
||||
Version: 1.4.4
|
||||
Release: 1%{?dist}
|
||||
License: BSD
|
||||
Url: http://www.nlnetlabs.nl/unbound/
|
||||
|
||||
+41
-17
@@ -1,5 +1,5 @@
|
||||
# initial python set up
|
||||
%{?!with_python: %define with_python 0}
|
||||
# not ready yet
|
||||
%{?!with_python: %global with_python 1}
|
||||
|
||||
%if %{with_python}
|
||||
%{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
Summary: Validating, recursive, and caching DNS(SEC) resolver
|
||||
Name: unbound
|
||||
Version: 1.3.1rc2
|
||||
Version: 1.4.2
|
||||
Release: 1%{?dist}
|
||||
License: BSD
|
||||
Url: http://www.nlnetlabs.nl/unbound/
|
||||
@@ -16,8 +16,8 @@ Source: http://www.unbound.net/downloads/%{name}-%{version}.tar.gz
|
||||
Source1: unbound.init
|
||||
Source2: unbound.conf
|
||||
Source3: unbound.munin
|
||||
# See the unbound svn repository for further documentation on these
|
||||
Patch0: unbound-1.2-glob.patch
|
||||
Source4: dlv.isc.org.key
|
||||
Patch1: unbound-1.2-glob.patch
|
||||
|
||||
Group: System Environment/Daemons
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
@@ -31,7 +31,7 @@ Requires(post): chkconfig
|
||||
Requires(preun): chkconfig
|
||||
Requires(preun): initscripts
|
||||
Requires(postun): initscripts
|
||||
Requires: ldns >= 1.5.0, dnssec-conf >= 1.19
|
||||
Requires: ldns >= 1.5.0
|
||||
Requires(pre): shadow-utils
|
||||
|
||||
%description
|
||||
@@ -84,7 +84,7 @@ Python modules and extensions for unbound
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
%patch0 -p1
|
||||
%patch1 -p1
|
||||
|
||||
%build
|
||||
%configure --with-ldns= --with-libevent --with-pthreads --with-ssl \
|
||||
@@ -95,7 +95,7 @@ Python modules and extensions for unbound
|
||||
--with-pythonmodule --with-pyunbound \
|
||||
%endif
|
||||
--enable-sha2
|
||||
%{__make} CFLAGS="$RPM_OPT_FLAGS -D_GNU_SOURCE" QUIET=no %{?_smp_mflags}
|
||||
%{__make}
|
||||
|
||||
%install
|
||||
rm -rf %{buildroot}
|
||||
@@ -112,6 +112,9 @@ for plugin in unbound_munin_hits unbound_munin_queue unbound_munin_memory unboun
|
||||
ln -s unbound %{buildroot}%{_datadir}/munin/plugins/$plugin
|
||||
done
|
||||
|
||||
# install DLV key
|
||||
install -m 0644 %{SOURCE4} %{buildroot}%{_sysconfdir}/unbound/
|
||||
|
||||
# remove static library from install (fedora packaging guidelines)
|
||||
rm -rf %{buildroot}%{_libdir}/*.la
|
||||
|
||||
@@ -127,6 +130,7 @@ rm -rf ${RPM_BUILD_ROOT}
|
||||
%attr(0755,root,root) %dir %{_sysconfdir}/%{name}
|
||||
%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
|
||||
%{_sbindir}/*
|
||||
%{_mandir}/*/*
|
||||
|
||||
@@ -160,15 +164,11 @@ exit 0
|
||||
|
||||
%post
|
||||
/sbin/chkconfig --add %{name}
|
||||
# Check DNSSEC settings if this is a fresh install
|
||||
if [ "$1" -eq 1 ]; then
|
||||
if [ -r /etc/sysconfig/dnssec ]; then
|
||||
. /etc/sysconfig/dnssec
|
||||
[ -x /usr/sbin/dnssec-configure ] && \
|
||||
dnssec-configure -u --norestart --nocheck --dnssec="$DNSSEC" --dlv="$DLV" > \
|
||||
/dev/null 2>&1
|
||||
fi;
|
||||
fi
|
||||
# dnssec-conf used to contain our DLV key, but now we include it via unbound
|
||||
# If unbound had previously been configured with dnssec-configure, we need
|
||||
# to migrate the location of the DLV key file (to keep DLV enabled, and because
|
||||
# unbound won't start with a bad location for a DLV key file.
|
||||
sed -i "s:/etc/pki/dnssec-keys[/]*dlv:/etc/unbound:" %{_sysconfdir}/unbound/unbound.conf
|
||||
|
||||
%post libs -p /sbin/ldconfig
|
||||
|
||||
@@ -186,6 +186,30 @@ fi
|
||||
%postun libs -p /sbin/ldconfig
|
||||
|
||||
%changelog
|
||||
* 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
|
||||
|
||||
* Tue Jan 05 2010 Paul Wouters <paul@xelerance.com> - 1.4.1-1
|
||||
- Updated to 1.4.1
|
||||
- Changed %%define to %%global
|
||||
|
||||
* Thu Oct 08 2009 Paul Wouters <paul@xelerance.com> - 1.3.4-2
|
||||
- Bump version
|
||||
|
||||
* Thu Oct 08 2009 Paul Wouters <paul@xelerance.com> - 1.3.4-1
|
||||
- Upgraded to 1.3.4. Security fix with validating NSEC3 records
|
||||
|
||||
* Fri Aug 21 2009 Tomas Mraz <tmraz@redhat.com> - 1.3.3-2
|
||||
- rebuilt with new openssl
|
||||
|
||||
* Mon Aug 17 2009 Paul Wouters <paul@xelerance.com> - 1.3.3-1
|
||||
- Updated to 1.3.3
|
||||
|
||||
* Sun Jul 26 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.3.0-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
|
||||
|
||||
* Sat Jun 20 2009 Paul Wouters <paul@xelerance.com> - 1.3.0-2
|
||||
- Added missing glob patch to cvs
|
||||
- Place python macros within the %%with_python check
|
||||
|
||||
Binary file not shown.
@@ -235,6 +235,7 @@ if test "$1" = "config" ; then
|
||||
done
|
||||
p_config "total.num.queries" "total queries from clients"
|
||||
p_config "total.num.cachehits" "cache hits"
|
||||
p_config "total.num.prefetch" "cache prefetch"
|
||||
p_config "num.query.tcp" "TCP queries"
|
||||
p_config "num.query.ipv6" "IPv6 queries"
|
||||
p_config "unwanted.queries" "queries that failed acl"
|
||||
@@ -423,8 +424,8 @@ 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 \
|
||||
total.num.cachehits num.query.tcp num.query.ipv6 \
|
||||
unwanted.queries unwanted.replies; do
|
||||
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
|
||||
print_qps $x
|
||||
fi
|
||||
|
||||
@@ -8,7 +8,7 @@ ubhost=unbound-host
|
||||
|
||||
usage ( )
|
||||
{
|
||||
echo "usage: update-anchor [-b] <zone name> <trust anchor file>"
|
||||
echo "usage: update-anchor [-r hs] [-b] <zone name> <trust anchor file>"
|
||||
echo " performs an update of trust anchor file"
|
||||
echo " the trust anchor file is overwritten with the latest keys"
|
||||
echo " the trust anchor file should contain only keys for one zone"
|
||||
@@ -16,13 +16,15 @@ usage ( )
|
||||
echo " without -b the file is made in unbound format."
|
||||
echo " "
|
||||
echo "alternate:"
|
||||
echo " update-anchor [-b] -d directory"
|
||||
echo " update-anchor [-r hints] [-b] -d directory"
|
||||
echo " update all <zone>.anchor files in the directory."
|
||||
echo " "
|
||||
echo " name the files br.anchor se.anchor ..., and include them in"
|
||||
echo " the validating resolver config file."
|
||||
echo " put keys for the root in a file with the name root.anchor."
|
||||
echo ""
|
||||
echo "-r root.hints use different root hints. Strict option order."
|
||||
echo ""
|
||||
echo "Exit code 0 means anchors updated, 1 no changes, others are errors."
|
||||
exit 2
|
||||
}
|
||||
@@ -32,6 +34,12 @@ if test $# -eq 0; then
|
||||
fi
|
||||
bindformat="no"
|
||||
filearg='-f'
|
||||
roothints=""
|
||||
if test X"$1" = "X-r"; then
|
||||
shift
|
||||
roothints="$1"
|
||||
shift
|
||||
fi
|
||||
if test X"$1" = "X-b"; then
|
||||
shift
|
||||
bindformat="yes"
|
||||
@@ -46,10 +54,15 @@ do_update ( ) {
|
||||
# arguments: <zonename> <keyfile>
|
||||
zonename="$1"
|
||||
keyfile="$2"
|
||||
tmp2=$tmpfile.2
|
||||
|
||||
tmpfile="/tmp/update-anchor.$$"
|
||||
$ubhost -v $filearg "$keyfile" -t DNSKEY "$zonename" >$tmpfile
|
||||
tmp2=$tmpfile.2
|
||||
tmp3=$tmpfile.3
|
||||
rh=""
|
||||
if test -n "$roothints"; then
|
||||
echo "server: root-hints: '$roothints'" > $tmp3
|
||||
rh="-C $tmp3"
|
||||
fi
|
||||
$ubhost -v $rh $filearg "$keyfile" -t DNSKEY "$zonename" >$tmpfile
|
||||
if test $? -ne 0; then
|
||||
rm -f $tmpfile
|
||||
echo "Error: Could not update zone $zonename anchor file $keyfile"
|
||||
@@ -65,7 +78,7 @@ do_update ( ) {
|
||||
rm -f $tmpfile
|
||||
echo "Error: Could not update zone $zonename anchor file $keyfile"
|
||||
echo "Cause: result of lookup was not secure"
|
||||
echo " (keys too far out of date? domain changed ownership?)"
|
||||
echo " (keys too far out of date? domain changed ownership? need root hints?)"
|
||||
return 3
|
||||
fi
|
||||
|
||||
@@ -115,7 +128,7 @@ do_update ( ) {
|
||||
echo "$zonename key file $keyfile unchanged."
|
||||
fi
|
||||
|
||||
rm -f $tmpfile $tmp2
|
||||
rm -f $tmpfile $tmp2 $tmp3
|
||||
}
|
||||
|
||||
no_updated=1
|
||||
|
||||
@@ -10,9 +10,9 @@ 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://iana.org/itar/anchors.mf"
|
||||
itar_url="ftp://ftp.iana.org/itar/anchors.mf"
|
||||
# where is the itar PGP signature
|
||||
itar_sig="ftp://iana.org/itar/anchors.mf.sig"
|
||||
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"
|
||||
|
||||
+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.
|
||||
|
||||
+181
-52
@@ -40,17 +40,24 @@
|
||||
* 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"
|
||||
#include "util/data/dname.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "iterator/iter_delegpt.h"
|
||||
#include "iterator/iter_utils.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
|
||||
/** convert to ldns rr */
|
||||
static ldns_rr*
|
||||
@@ -394,17 +401,16 @@ load_rr(SSL* ssl, ldns_buffer* buf, struct regional* region,
|
||||
*go_on = 0;
|
||||
return 1;
|
||||
}
|
||||
log_info("rd %s", (char*)ldns_buffer_begin(buf));
|
||||
status = ldns_rr_new_frm_str(&rr, (char*)ldns_buffer_begin(buf),
|
||||
LDNS_DEFAULT_TTL, NULL, NULL);
|
||||
if(status != LDNS_STATUS_OK) {
|
||||
(void)ssl_printf(ssl, "error cannot parse rr :%s: %s\n",
|
||||
log_warn("error cannot parse rr: %s: %s",
|
||||
ldns_get_errorstr_by_id(status),
|
||||
(char*)ldns_buffer_begin(buf));
|
||||
return 0;
|
||||
}
|
||||
if(is_rrsig && ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
|
||||
(void)ssl_printf(ssl, "error expected rrsig but got %s\n",
|
||||
log_warn("error expected rrsig but got %s",
|
||||
(char*)ldns_buffer_begin(buf));
|
||||
return 0;
|
||||
}
|
||||
@@ -415,7 +421,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) {
|
||||
(void)ssl_printf(ssl, "error cannot rr2wire :%s\n",
|
||||
log_warn("error cannot rr2wire: %s",
|
||||
ldns_get_errorstr_by_id(status));
|
||||
ldns_rr_free(rr);
|
||||
return 0;
|
||||
@@ -428,7 +434,7 @@ load_rr(SSL* ssl, ldns_buffer* buf, struct regional* region,
|
||||
ldns_buffer_begin(buf), ldns_buffer_limit(buf));
|
||||
if(!d->rr_data[i]) {
|
||||
ldns_rr_free(rr);
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
log_warn("error out of memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -438,12 +444,18 @@ 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,
|
||||
ldns_buffer_begin(buf), ldns_buffer_limit(buf));
|
||||
if(!rk->rk.dname) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
log_warn("error out of memory");
|
||||
ldns_rr_free(rr);
|
||||
return 0;
|
||||
}
|
||||
@@ -455,7 +467,7 @@ load_rr(SSL* ssl, ldns_buffer* buf, struct regional* region,
|
||||
|
||||
/** move entry into cache */
|
||||
static int
|
||||
move_into_cache(SSL* ssl, struct ub_packed_rrset_key* k,
|
||||
move_into_cache(struct ub_packed_rrset_key* k,
|
||||
struct packed_rrset_data* d, struct worker* worker)
|
||||
{
|
||||
struct ub_packed_rrset_key* ak;
|
||||
@@ -466,7 +478,7 @@ move_into_cache(SSL* ssl, struct ub_packed_rrset_key* k,
|
||||
|
||||
ak = alloc_special_obtain(&worker->alloc);
|
||||
if(!ak) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
log_warn("error out of memory");
|
||||
return 0;
|
||||
}
|
||||
ak->entry.data = NULL;
|
||||
@@ -474,7 +486,7 @@ move_into_cache(SSL* ssl, struct ub_packed_rrset_key* k,
|
||||
ak->entry.hash = rrset_key_hash(&k->rk);
|
||||
ak->rk.dname = (uint8_t*)memdup(k->rk.dname, k->rk.dname_len);
|
||||
if(!ak->rk.dname) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
log_warn("error out of memory");
|
||||
ub_packed_rrset_parsedelete(ak, &worker->alloc);
|
||||
return 0;
|
||||
}
|
||||
@@ -484,6 +496,7 @@ move_into_cache(SSL* ssl, struct ub_packed_rrset_key* k,
|
||||
s += d->rr_len[i];
|
||||
ad = (struct packed_rrset_data*)malloc(s);
|
||||
if(!ad) {
|
||||
log_warn("error out of memory");
|
||||
ub_packed_rrset_parsedelete(ak, &worker->alloc);
|
||||
return 0;
|
||||
}
|
||||
@@ -528,13 +541,12 @@ load_rrset(SSL* ssl, ldns_buffer* buf, struct worker* worker)
|
||||
sizeof(*rk));
|
||||
d = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*d));
|
||||
if(!rk || !d) {
|
||||
(void) ssl_printf(ssl, "error out of memory\n");
|
||||
log_warn("error out of memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(strncmp(s, ";rrset", 6) != 0) {
|
||||
(void)ssl_printf(ssl, "error expected ';rrset' but got %s\n",
|
||||
s);
|
||||
log_warn("error expected ';rrset' but got %s", s);
|
||||
return 0;
|
||||
}
|
||||
s += 6;
|
||||
@@ -544,11 +556,13 @@ load_rrset(SSL* ssl, ldns_buffer* buf, struct worker* worker)
|
||||
}
|
||||
if(sscanf(s, " %u %u %u %u %u", &ttl, &rr_count, &rrsig_count,
|
||||
&trust, &security) != 5) {
|
||||
(void)ssl_printf(ssl, "error bad rrset spec %s\n", s);
|
||||
log_warn("error bad rrset spec %s", s);
|
||||
return 0;
|
||||
}
|
||||
if(rr_count == 0 && rrsig_count == 0)
|
||||
if(rr_count == 0 && rrsig_count == 0) {
|
||||
log_warn("bad rrset without contents");
|
||||
return 0;
|
||||
}
|
||||
d->count = (size_t)rr_count;
|
||||
d->rrsig_count = (size_t)rrsig_count;
|
||||
d->security = (enum sec_status)security;
|
||||
@@ -562,7 +576,7 @@ load_rrset(SSL* ssl, ldns_buffer* buf, struct worker* worker)
|
||||
d->rr_data = regional_alloc_zero(region,
|
||||
sizeof(uint8_t*)*(d->count+d->rrsig_count));
|
||||
if(!d->rr_len || !d->rr_ttl || !d->rr_data) {
|
||||
(void) ssl_printf(ssl, "error out of memory\n");
|
||||
log_warn("error out of memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -570,12 +584,14 @@ load_rrset(SSL* ssl, ldns_buffer* buf, struct worker* worker)
|
||||
for(i=0; i<rr_count; i++) {
|
||||
if(!load_rr(ssl, buf, region, rk, d, i, 0,
|
||||
&go_on, *worker->env.now)) {
|
||||
log_warn("could not read rr %u", i);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
for(i=0; i<rrsig_count; i++) {
|
||||
if(!load_rr(ssl, buf, region, rk, d, i+rr_count, 1,
|
||||
&go_on, *worker->env.now)) {
|
||||
log_warn("could not read rrsig %u", i);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -584,7 +600,7 @@ load_rrset(SSL* ssl, ldns_buffer* buf, struct worker* worker)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return move_into_cache(ssl, rk, d, worker);
|
||||
return move_into_cache(rk, d, worker);
|
||||
}
|
||||
|
||||
/** load rrset cache */
|
||||
@@ -604,7 +620,7 @@ load_rrset_cache(SSL* ssl, struct worker* worker)
|
||||
/** read qinfo from next three words */
|
||||
static char*
|
||||
load_qinfo(char* str, struct query_info* qinfo, ldns_buffer* buf,
|
||||
struct regional* region, SSL* ssl)
|
||||
struct regional* region)
|
||||
{
|
||||
/* s is part of the buf */
|
||||
char* s = str;
|
||||
@@ -616,7 +632,7 @@ load_qinfo(char* str, struct query_info* qinfo, ldns_buffer* buf,
|
||||
if(s) s = strchr(s+1, ' ');
|
||||
if(s) s = strchr(s+1, ' ');
|
||||
if(!s) {
|
||||
(void)ssl_printf(ssl, "error line too short, %s\n", str);
|
||||
log_warn("error line too short, %s", str);
|
||||
return NULL;
|
||||
}
|
||||
s[0] = 0;
|
||||
@@ -625,7 +641,7 @@ load_qinfo(char* str, struct query_info* qinfo, ldns_buffer* buf,
|
||||
/* parse them */
|
||||
status = ldns_rr_new_question_frm_str(&rr, str, NULL, NULL);
|
||||
if(status != LDNS_STATUS_OK) {
|
||||
(void)ssl_printf(ssl, "error cannot parse: %s %s\n",
|
||||
log_warn("error cannot parse: %s %s",
|
||||
ldns_get_errorstr_by_id(status), str);
|
||||
return NULL;
|
||||
}
|
||||
@@ -635,7 +651,7 @@ load_qinfo(char* str, struct query_info* qinfo, ldns_buffer* buf,
|
||||
status = ldns_dname2buffer_wire(buf, ldns_rr_owner(rr));
|
||||
ldns_rr_free(rr);
|
||||
if(status != LDNS_STATUS_OK) {
|
||||
(void)ssl_printf(ssl, "error cannot dname2wire: %s\n",
|
||||
log_warn("error cannot dname2wire: %s",
|
||||
ldns_get_errorstr_by_id(status));
|
||||
return NULL;
|
||||
}
|
||||
@@ -644,7 +660,7 @@ load_qinfo(char* str, struct query_info* qinfo, ldns_buffer* buf,
|
||||
qinfo->qname = (uint8_t*)regional_alloc_init(region,
|
||||
ldns_buffer_begin(buf), ldns_buffer_limit(buf));
|
||||
if(!qinfo->qname) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
log_warn("error out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -670,12 +686,12 @@ load_ref(SSL* ssl, ldns_buffer* buf, struct worker* worker,
|
||||
return 1;
|
||||
}
|
||||
|
||||
s = load_qinfo(s, &qinfo, buf, region, ssl);
|
||||
s = load_qinfo(s, &qinfo, buf, region);
|
||||
if(!s) {
|
||||
return 0;
|
||||
}
|
||||
if(sscanf(s, " %u", &flags) != 1) {
|
||||
(void)ssl_printf(ssl, "error cannot parse flags: %s\n", s);
|
||||
log_warn("error cannot parse flags: %s", s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -711,11 +727,11 @@ load_msg(SSL* ssl, ldns_buffer* buf, struct worker* worker)
|
||||
regional_free_all(region);
|
||||
|
||||
if(strncmp(s, "msg ", 4) != 0) {
|
||||
(void)ssl_printf(ssl, "error expected msg but got %s\n", s);
|
||||
log_warn("error expected msg but got %s", s);
|
||||
return 0;
|
||||
}
|
||||
s += 4;
|
||||
s = load_qinfo(s, &qinf, buf, region, ssl);
|
||||
s = load_qinfo(s, &qinf, buf, region);
|
||||
if(!s) {
|
||||
return 0;
|
||||
}
|
||||
@@ -723,12 +739,13 @@ load_msg(SSL* ssl, ldns_buffer* buf, struct worker* worker)
|
||||
/* read remainder of line */
|
||||
if(sscanf(s, " %u %u %u %u %u %u %u", &flags, &qdcount, &ttl,
|
||||
&security, &an, &ns, &ar) != 7) {
|
||||
(void)ssl_printf(ssl, "error cannot parse numbers: %s\n", s);
|
||||
log_warn("error cannot parse numbers: %s", s);
|
||||
return 0;
|
||||
}
|
||||
rep.flags = (uint16_t)flags;
|
||||
rep.qdcount = (uint16_t)qdcount;
|
||||
rep.ttl = (uint32_t)ttl;
|
||||
rep.prefetch_ttl = PREFETCH_TTL_CALC(rep.ttl);
|
||||
rep.security = (enum sec_status)security;
|
||||
rep.an_numrrsets = (size_t)an;
|
||||
rep.ns_numrrsets = (size_t)ns;
|
||||
@@ -748,8 +765,8 @@ 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)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0)) {
|
||||
log_warn("error out of memory");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -779,6 +796,104 @@ load_cache(SSL* ssl, struct worker* worker)
|
||||
return read_fixed(ssl, worker->env.scratch_buffer, "EOF");
|
||||
}
|
||||
|
||||
/** print details on a delegation point */
|
||||
static void
|
||||
print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp)
|
||||
{
|
||||
char buf[257];
|
||||
struct delegpt_addr* a;
|
||||
int lame, dlame, rlame, rto, edns_vs, to, delay, entry_ttl;
|
||||
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));
|
||||
if(!ssl_printf(ssl, "%-16s\t", buf))
|
||||
return;
|
||||
if(a->bogus) {
|
||||
if(!ssl_printf(ssl, "Address is BOGUS. "))
|
||||
return;
|
||||
}
|
||||
/* lookup in infra cache */
|
||||
entry_ttl = infra_get_host_rto(worker->env.infra_cache,
|
||||
&a->addr, a->addrlen, &ri, &delay, *worker->env.now);
|
||||
if(entry_ttl == -2 && ri.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
if(!ssl_printf(ssl, "expired, rto %d msec.\n", ri.rto))
|
||||
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, &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%srto %d msec, ttl %d, ping %d "
|
||||
"var %d rtt %d",
|
||||
lame?"LAME ":"", dlame?"NoDNSSEC ":"",
|
||||
a->lame?"AddrWasParentSide ":"",
|
||||
rlame?"NoAuthButRecursive ":"", rto, entry_ttl,
|
||||
ri.srtt, ri.rttvar, rtt_notimeout(&ri)))
|
||||
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)) {
|
||||
if(edns_vs == -1) {
|
||||
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":" assumed"))
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(!ssl_printf(ssl, "\n"))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/** print main dp info */
|
||||
static void
|
||||
print_dp_main(SSL* ssl, struct delegpt* dp, struct dns_msg* msg)
|
||||
{
|
||||
size_t i, n_ns, n_miss, n_addr, n_res, n_avail;
|
||||
|
||||
/* print the dp */
|
||||
if(msg)
|
||||
for(i=0; i<msg->rep->rrset_count; i++) {
|
||||
struct ub_packed_rrset_key* k = msg->rep->rrsets[i];
|
||||
struct packed_rrset_data* d =
|
||||
(struct packed_rrset_data*)k->entry.data;
|
||||
if(d->security == sec_status_bogus) {
|
||||
if(!ssl_printf(ssl, "Address is BOGUS:\n"))
|
||||
return;
|
||||
}
|
||||
if(!dump_rrset(ssl, k, d, 0))
|
||||
return;
|
||||
}
|
||||
delegpt_count_ns(dp, &n_ns, &n_miss);
|
||||
delegpt_count_addr(dp, &n_addr, &n_res, &n_avail);
|
||||
/* since dp has not been used by iterator, all are available*/
|
||||
if(!ssl_printf(ssl, "Delegation with %d names, of which %d "
|
||||
"can be examined to query further addresses.\n"
|
||||
"%sIt provides %d IP addresses.\n",
|
||||
(int)n_ns, (int)n_miss, (dp->bogus?"It is BOGUS. ":""),
|
||||
(int)n_addr))
|
||||
return;
|
||||
}
|
||||
|
||||
int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
|
||||
size_t nmlen, int ATTR_UNUSED(nmlabs))
|
||||
{
|
||||
@@ -788,18 +903,34 @@ int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
|
||||
struct regional* region = worker->scratchpad;
|
||||
char b[260];
|
||||
struct query_info qinfo;
|
||||
size_t i, n_ns, n_miss, n_addr, n_res, n_avail;
|
||||
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))
|
||||
return 0;
|
||||
|
||||
dp = forwards_lookup(worker->env.fwds, nm, qinfo.qclass);
|
||||
if(dp) {
|
||||
if(!ssl_printf(ssl, "forwarding request:\n"))
|
||||
return 0;
|
||||
print_dp_main(ssl, dp, NULL);
|
||||
print_dp_details(ssl, worker, dp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while(1) {
|
||||
dp = dns_cache_find_delegation(&worker->env, nm, nmlen,
|
||||
qinfo.qtype, qinfo.qclass, region, &msg,
|
||||
@@ -808,29 +939,10 @@ int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
|
||||
return ssl_printf(ssl, "no delegation from "
|
||||
"cache; goes to configured roots\n");
|
||||
}
|
||||
/* print the dp */
|
||||
for(i=0; i<msg->rep->rrset_count; i++) {
|
||||
struct ub_packed_rrset_key* k = msg->rep->rrsets[i];
|
||||
struct packed_rrset_data* d =
|
||||
(struct packed_rrset_data*)k->entry.data;
|
||||
if(d->security == sec_status_bogus) {
|
||||
if(!ssl_printf(ssl, "Address is BOGUS:\n"))
|
||||
return 0;
|
||||
}
|
||||
if(!dump_rrset(ssl, k, d, 0))
|
||||
return 0;
|
||||
}
|
||||
delegpt_count_ns(dp, &n_ns, &n_miss);
|
||||
delegpt_count_addr(dp, &n_addr, &n_res, &n_avail);
|
||||
/* since dp has not been used by iterator, all are available*/
|
||||
if(!ssl_printf(ssl, "Delegation with %d names, of which %d "
|
||||
"have no addresses in cache.\n"
|
||||
"It provides %d IP addresses. %s\n",
|
||||
(int)n_ns, (int)n_miss, (int)n_addr,
|
||||
(dp->bogus?"It is BOGUS":"") ))
|
||||
return 0;
|
||||
/* go up? */
|
||||
if(iter_dp_is_useless(&qinfo, BIT_RD, dp)) {
|
||||
print_dp_main(ssl, dp, msg);
|
||||
print_dp_details(ssl, worker, dp);
|
||||
if(!ssl_printf(ssl, "cache delegation was "
|
||||
"useless (no IP addresses)\n"))
|
||||
return 0;
|
||||
@@ -848,8 +960,25 @@ int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
} else
|
||||
break;
|
||||
}
|
||||
stub = hints_lookup_stub(ie->hints, nm, qinfo.qclass, dp);
|
||||
if(stub) {
|
||||
if(stub->noprime) {
|
||||
if(!ssl_printf(ssl, "The noprime stub servers "
|
||||
"are used:\n"))
|
||||
return 0;
|
||||
} else {
|
||||
if(!ssl_printf(ssl, "The stub is primed "
|
||||
"with servers:\n"))
|
||||
return 0;
|
||||
}
|
||||
print_dp_main(ssl, stub->dp, NULL);
|
||||
print_dp_details(ssl, worker, stub->dp);
|
||||
} else {
|
||||
print_dp_main(ssl, dp, msg);
|
||||
print_dp_details(ssl, worker, dp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
+60
-9
@@ -40,6 +40,22 @@
|
||||
*/
|
||||
|
||||
#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
|
||||
#include "ldns/ldns.h"
|
||||
#include "daemon/daemon.h"
|
||||
#include "daemon/worker.h"
|
||||
#include "daemon/remote.h"
|
||||
@@ -63,6 +79,15 @@ static int sig_record_quit = 0;
|
||||
/** How many reload requests happened. */
|
||||
static int sig_record_reload = 0;
|
||||
|
||||
#if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS
|
||||
/** cleaner ssl memory freeup */
|
||||
static void* comp_meth = NULL;
|
||||
#endif
|
||||
#ifdef LEX_HAS_YYLEX_DESTROY
|
||||
/** remove buffers for parsing and init */
|
||||
int ub_c_lex_destroy(void);
|
||||
#endif
|
||||
|
||||
/** used when no other sighandling happens, so we don't die
|
||||
* when multiple signals in quick succession are sent to us.
|
||||
* @param sig: signal number.
|
||||
@@ -106,7 +131,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
|
||||
@@ -144,7 +169,7 @@ signal_handling_playback(struct worker* wrk)
|
||||
}
|
||||
|
||||
struct daemon*
|
||||
daemon_init()
|
||||
daemon_init(void)
|
||||
{
|
||||
struct daemon* daemon = (struct daemon*)calloc(1,
|
||||
sizeof(struct daemon));
|
||||
@@ -165,7 +190,17 @@ daemon_init()
|
||||
checklock_start();
|
||||
ERR_load_crypto_strings();
|
||||
ERR_load_SSL_strings();
|
||||
#ifdef HAVE_OPENSSL_CONFIG
|
||||
OPENSSL_config("unbound");
|
||||
#endif
|
||||
#ifdef USE_GOST
|
||||
(void)ldns_key_EVP_load_gost_id();
|
||||
#endif
|
||||
OpenSSL_add_all_algorithms();
|
||||
#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
|
||||
(void)SSL_library_init();
|
||||
#ifdef HAVE_TZSET
|
||||
/* init timezone info while we are not chrooted yet */
|
||||
@@ -241,7 +276,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;
|
||||
@@ -257,7 +292,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,12 +339,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++)
|
||||
@@ -324,6 +360,7 @@ void close_other_pipes(struct daemon* daemon, int thr)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* THREADS_DISABLED */
|
||||
|
||||
/**
|
||||
* Function to start one thread.
|
||||
@@ -412,7 +449,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");
|
||||
@@ -426,7 +463,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");
|
||||
@@ -492,10 +529,24 @@ daemon_delete(struct daemon* daemon)
|
||||
free(daemon->pidfile);
|
||||
free(daemon->env);
|
||||
free(daemon);
|
||||
#ifdef LEX_HAS_YYLEX_DESTROY
|
||||
/* lex cleanup */
|
||||
ub_c_lex_destroy();
|
||||
#endif
|
||||
/* libcrypto cleanup */
|
||||
/* CONF_modules_unload(1); */
|
||||
#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(); */
|
||||
ENGINE_cleanup();
|
||||
CONF_modules_free();
|
||||
#endif
|
||||
CRYPTO_cleanup_all_ex_data(); /* safe, no more threads right now */
|
||||
ERR_remove_state(0);
|
||||
ERR_free_strings();
|
||||
|
||||
+1
-1
@@ -108,7 +108,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).
|
||||
|
||||
+344
-50
@@ -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"
|
||||
@@ -64,6 +70,7 @@
|
||||
#include "validator/val_kentry.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
#include "iterator/iter_delegpt.h"
|
||||
#include "services/outbound_list.h"
|
||||
#include "services/outside_network.h"
|
||||
@@ -106,9 +113,9 @@ timeval_subtract(struct timeval* d, const struct timeval* end,
|
||||
const struct timeval* start)
|
||||
{
|
||||
#ifndef S_SPLINT_S
|
||||
time_t end_usec = end->tv_usec;;
|
||||
time_t end_usec = end->tv_usec;
|
||||
d->tv_sec = end->tv_sec - start->tv_sec;
|
||||
while(end_usec < start->tv_usec) {
|
||||
if(end_usec < start->tv_usec) {
|
||||
end_usec += 1000000;
|
||||
d->tv_sec--;
|
||||
}
|
||||
@@ -311,7 +318,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);
|
||||
@@ -599,12 +606,15 @@ print_stats(SSL* ssl, const char* nm, struct stats_info* s)
|
||||
- s->svr.num_queries_missed_cache))) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.cachemiss"SQ"%u\n", nm,
|
||||
(unsigned)s->svr.num_queries_missed_cache)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.prefetch"SQ"%u\n", nm,
|
||||
(unsigned)s->svr.num_queries_prefetch)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.recursivereplies"SQ"%u\n", nm,
|
||||
(unsigned)s->mesh_replies_sent)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.requestlist.avg"SQ"%g\n", nm,
|
||||
s->svr.num_queries_missed_cache?
|
||||
(s->svr.num_queries_missed_cache+s->svr.num_queries_prefetch)?
|
||||
(double)s->svr.sum_query_list_size/
|
||||
s->svr.num_queries_missed_cache : 0.0)) return 0;
|
||||
(s->svr.num_queries_missed_cache+
|
||||
s->svr.num_queries_prefetch) : 0.0)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.requestlist.max"SQ"%u\n", nm,
|
||||
(unsigned)s->svr.max_query_list_size)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.requestlist.overwritten"SQ"%u\n", nm,
|
||||
@@ -868,6 +878,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);
|
||||
@@ -1087,6 +1098,25 @@ do_flush_stats(SSL* ssl, struct worker* worker)
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** flush infra cache */
|
||||
static void
|
||||
do_flush_infra(SSL* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t len;
|
||||
if(strcmp(arg, "all") == 0) {
|
||||
slabhash_clear(worker->env.infra_cache->hosts);
|
||||
send_ok(ssl);
|
||||
return;
|
||||
}
|
||||
if(!ipstrtoaddr(arg, UNBOUND_DNS_PORT, &addr, &len)) {
|
||||
(void)ssl_printf(ssl, "error parsing ip addr: '%s'\n", arg);
|
||||
return;
|
||||
}
|
||||
infra_remove_host(worker->env.infra_cache, &addr, len);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** flush requestlist */
|
||||
static void
|
||||
do_flush_requestlist(SSL* ssl, struct worker* worker)
|
||||
@@ -1107,6 +1137,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 */
|
||||
@@ -1127,8 +1159,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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1141,8 +1175,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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1155,8 +1191,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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1168,7 +1206,6 @@ do_flush_zone(SSL* ssl, struct worker* worker, char* arg)
|
||||
int nmlabs;
|
||||
size_t nmlen;
|
||||
struct del_info inf;
|
||||
int idx;
|
||||
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
|
||||
return;
|
||||
/* delete all RRs and key entries from zone */
|
||||
@@ -1177,6 +1214,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;
|
||||
@@ -1188,10 +1226,9 @@ do_flush_zone(SSL* ssl, struct worker* worker, char* arg)
|
||||
slabhash_traverse(worker->env.msg_cache, 1, &zone_del_msg, &inf);
|
||||
|
||||
/* and validator cache */
|
||||
idx = modstack_find(&worker->daemon->mods, "validator");
|
||||
if(idx != -1) {
|
||||
struct val_env* ve = (struct val_env*)worker->env.modinfo[idx];
|
||||
slabhash_traverse(ve->kcache->slab, 1, &zone_del_kcache, &inf);
|
||||
if(worker->env.key_cache) {
|
||||
slabhash_traverse(worker->env.key_cache->slab, 1,
|
||||
&zone_del_kcache, &inf);
|
||||
}
|
||||
|
||||
free(nm);
|
||||
@@ -1225,20 +1262,24 @@ do_flush_name(SSL* ssl, struct worker* w, char* arg)
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** print root forwards */
|
||||
/** printout a delegation point info */
|
||||
static int
|
||||
print_root_fwds(SSL* ssl, struct iter_forwards* fwds, uint8_t* root)
|
||||
ssl_print_name_dp(SSL* ssl, char* str, uint8_t* nm, uint16_t dclass,
|
||||
struct delegpt* dp)
|
||||
{
|
||||
char buf[257];
|
||||
struct delegpt* dp;
|
||||
struct delegpt_ns* ns;
|
||||
struct delegpt_addr* a;
|
||||
int f = 0;
|
||||
dp = forwards_lookup(fwds, root, LDNS_RR_CLASS_IN);
|
||||
if(!dp)
|
||||
return ssl_printf(ssl, "off (using root hints)\n");
|
||||
/* if dp is returned it must be the root */
|
||||
log_assert(query_dname_compare(dp->name, root)==0);
|
||||
if(str) { /* print header for forward, stub */
|
||||
char* c = ldns_rr_class2str(dclass);
|
||||
dname_str(nm, buf);
|
||||
if(!ssl_printf(ssl, "%s %s %s: ", buf, c, str)) {
|
||||
free(c);
|
||||
return 0;
|
||||
}
|
||||
free(c);
|
||||
}
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
dname_str(ns->name, buf);
|
||||
if(!ssl_printf(ssl, "%s%s", (f?" ":""), buf))
|
||||
@@ -1254,6 +1295,20 @@ print_root_fwds(SSL* ssl, struct iter_forwards* fwds, uint8_t* root)
|
||||
return ssl_printf(ssl, "\n");
|
||||
}
|
||||
|
||||
|
||||
/** print root forwards */
|
||||
static int
|
||||
print_root_fwds(SSL* ssl, struct iter_forwards* fwds, uint8_t* root)
|
||||
{
|
||||
struct delegpt* dp;
|
||||
dp = forwards_lookup(fwds, root, LDNS_RR_CLASS_IN);
|
||||
if(!dp)
|
||||
return ssl_printf(ssl, "off (using root hints)\n");
|
||||
/* if dp is returned it must be the root */
|
||||
log_assert(query_dname_compare(dp->name, root)==0);
|
||||
return ssl_print_name_dp(ssl, NULL, root, LDNS_RR_CLASS_IN, dp);
|
||||
}
|
||||
|
||||
/** parse args into delegpt */
|
||||
static struct delegpt*
|
||||
parse_delegpt(SSL* ssl, struct regional* region, char* args, uint8_t* root)
|
||||
@@ -1282,7 +1337,7 @@ parse_delegpt(SSL* ssl, struct regional* region, char* args, uint8_t* root)
|
||||
return NULL;
|
||||
}
|
||||
/* add address */
|
||||
if(!delegpt_add_addr(dp, region, &addr, addrlen, 0, 1)) {
|
||||
if(!delegpt_add_addr(dp, region, &addr, addrlen, 0, 0)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
@@ -1459,8 +1514,214 @@ 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;
|
||||
/** ipstr */
|
||||
char* ipstr;
|
||||
};
|
||||
|
||||
/** callback for every lame element in the infra cache */
|
||||
static void
|
||||
dump_infra_lame(struct lruhash_entry* e, void* arg)
|
||||
{
|
||||
struct infra_arg* a = (struct infra_arg*)arg;
|
||||
struct infra_lame_key* k = (struct infra_lame_key*)e->key;
|
||||
struct infra_lame_data* d = (struct infra_lame_data*)e->data;
|
||||
ldns_rdf* rdf;
|
||||
size_t pos = 0;
|
||||
char* nm;
|
||||
/* skip expired */
|
||||
if(d->ttl < a->now) {
|
||||
return;
|
||||
}
|
||||
/* use ldns print for domain name */
|
||||
if(ldns_wire2dname(&rdf, k->zonename, k->namelen, &pos)
|
||||
!= LDNS_STATUS_OK)
|
||||
return;
|
||||
nm = ldns_rdf2str(rdf);
|
||||
ldns_rdf_deep_free(rdf);
|
||||
if(!ssl_printf(a->ssl, "%s lame %s ttl %d dnssec %d rec %d "
|
||||
"A %d other %d\n", a->ipstr, nm, (int)(d->ttl - a->now),
|
||||
d->isdnsseclame, d->rec_lame, d->lame_type_A, d->lame_other)) {
|
||||
free(nm);
|
||||
return;
|
||||
}
|
||||
free(nm);
|
||||
}
|
||||
|
||||
/** callback for every host element in the infra cache */
|
||||
static void
|
||||
dump_infra_host(struct lruhash_entry* e, void* arg)
|
||||
{
|
||||
struct infra_arg* a = (struct infra_arg*)arg;
|
||||
struct infra_host_key* k = (struct infra_host_key*)e->key;
|
||||
struct infra_host_data* d = (struct infra_host_data*)e->data;
|
||||
char ip_str[1024];
|
||||
addr_to_str(&k->addr, k->addrlen, ip_str, sizeof(ip_str));
|
||||
a->ipstr = ip_str;
|
||||
/* skip expired stuff (only backed off) */
|
||||
if(d->ttl < a->now) {
|
||||
if(d->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
if(!ssl_printf(a->ssl, "%s expired rto %d\n", ip_str,
|
||||
d->rtt.rto)) return;
|
||||
}
|
||||
if(d->lameness)
|
||||
lruhash_traverse(d->lameness, 0, &dump_infra_lame, arg);
|
||||
return;
|
||||
}
|
||||
if(!ssl_printf(a->ssl, "%s ttl %d ping %d var %d rtt %d rto %d "
|
||||
"ednsknown %d edns %d delay %d\n",
|
||||
ip_str, (int)(d->ttl - a->now),
|
||||
d->rtt.srtt, d->rtt.rttvar, rtt_notimeout(&d->rtt), d->rtt.rto,
|
||||
(int)d->edns_lame_known, (int)d->edns_version,
|
||||
(int)(a->now<d->probedelay?d->probedelay-a->now:0)))
|
||||
return;
|
||||
if(d->lameness)
|
||||
lruhash_traverse(d->lameness, 0, &dump_infra_lame, arg);
|
||||
}
|
||||
|
||||
/** 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)
|
||||
{
|
||||
struct config_file* cfg = worker->env.cfg;
|
||||
send_ok(ssl);
|
||||
log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
|
||||
}
|
||||
|
||||
/** do the set_option command */
|
||||
static void
|
||||
do_set_option(SSL* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
char* arg2;
|
||||
if(!find_arg2(ssl, arg, &arg2))
|
||||
return;
|
||||
if(!config_set_option(worker->env.cfg, arg, arg2)) {
|
||||
(void)ssl_printf(ssl, "error setting option\n");
|
||||
return;
|
||||
}
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/* routine to printout option values over SSL */
|
||||
void remote_get_opt_ssl(char* line, void* arg)
|
||||
{
|
||||
SSL* ssl = (SSL*)arg;
|
||||
(void)ssl_printf(ssl, "%s\n", line);
|
||||
}
|
||||
|
||||
/** do the get_option command */
|
||||
static void
|
||||
do_get_option(SSL* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
int r;
|
||||
r = config_get_option(worker->env.cfg, arg, remote_get_opt_ssl, ssl);
|
||||
if(!r) {
|
||||
(void)ssl_printf(ssl, "error unknown option\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/** do the list_forwards command */
|
||||
static void
|
||||
do_list_forwards(SSL* ssl, struct worker* worker)
|
||||
{
|
||||
/* since its a per-worker structure no locks needed */
|
||||
struct iter_forwards* fwds = worker->env.fwds;
|
||||
struct iter_forward_zone* z;
|
||||
RBTREE_FOR(z, struct iter_forward_zone*, fwds->tree) {
|
||||
if(!z->dp) continue; /* skip empty marker for stub */
|
||||
if(!ssl_print_name_dp(ssl, "forward", z->name, z->dclass,
|
||||
z->dp))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/** do the list_stubs command */
|
||||
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) {
|
||||
if(!ssl_print_name_dp(ssl,
|
||||
z->noprime?"stub noprime":"stub prime", z->node.name,
|
||||
z->node.dclass, z->dp))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/** do the list_local_zones command */
|
||||
static void
|
||||
do_list_local_zones(SSL* ssl, struct worker* worker)
|
||||
{
|
||||
struct local_zones* zones = worker->daemon->local_zones;
|
||||
struct local_zone* z;
|
||||
char buf[257];
|
||||
lock_quick_lock(&zones->lock);
|
||||
RBTREE_FOR(z, struct local_zone*, &zones->ztree) {
|
||||
lock_rw_rdlock(&z->lock);
|
||||
dname_str(z->name, buf);
|
||||
(void)ssl_printf(ssl, "%s %s\n", buf,
|
||||
local_zone_type2str(z->type));
|
||||
lock_rw_unlock(&z->lock);
|
||||
}
|
||||
lock_quick_unlock(&zones->lock);
|
||||
}
|
||||
|
||||
/** do the list_local_data command */
|
||||
static void
|
||||
do_list_local_data(SSL* ssl, struct worker* worker)
|
||||
{
|
||||
struct local_zones* zones = worker->daemon->local_zones;
|
||||
struct local_zone* z;
|
||||
struct local_data* d;
|
||||
struct local_rrset* p;
|
||||
lock_quick_lock(&zones->lock);
|
||||
RBTREE_FOR(z, struct local_zone*, &zones->ztree) {
|
||||
lock_rw_rdlock(&z->lock);
|
||||
RBTREE_FOR(d, struct local_data*, &z->data) {
|
||||
for(p = d->rrsets; p; p = p->next) {
|
||||
ldns_rr_list* rr = packed_rrset_to_rr_list(
|
||||
p->rrset, worker->env.scratch_buffer);
|
||||
char* str = ldns_rr_list2str(rr);
|
||||
(void)ssl_printf(ssl, "%s", str);
|
||||
free(str);
|
||||
ldns_rr_list_free(rr);
|
||||
}
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
}
|
||||
lock_quick_unlock(&zones->lock);
|
||||
}
|
||||
|
||||
/** tell other processes to execute the command */
|
||||
void
|
||||
static void
|
||||
distribute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd)
|
||||
{
|
||||
int i;
|
||||
@@ -1478,50 +1739,69 @@ 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, "forward", 7) == 0) {
|
||||
} else if(cmdcmp(p, "list_forwards", 13)) {
|
||||
do_list_forwards(ssl, worker);
|
||||
return;
|
||||
} else if(cmdcmp(p, "list_stubs", 10)) {
|
||||
do_list_stubs(ssl, worker);
|
||||
return;
|
||||
} else if(cmdcmp(p, "list_local_zones", 16)) {
|
||||
do_list_local_zones(ssl, worker);
|
||||
return;
|
||||
} else if(cmdcmp(p, "list_local_data", 15)) {
|
||||
do_list_local_data(ssl, worker);
|
||||
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;
|
||||
}
|
||||
@@ -1534,24 +1814,34 @@ 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(cmdcmp(p, "dump_infra", 10)) {
|
||||
do_dump_infra(ssl, worker);
|
||||
} else if(cmdcmp(p, "log_reopen", 10)) {
|
||||
do_log_reopen(ssl, worker);
|
||||
} else if(cmdcmp(p, "set_option", 10)) {
|
||||
do_set_option(ssl, worker, skipwhite(p+10));
|
||||
} else if(cmdcmp(p, "get_option", 10)) {
|
||||
do_get_option(ssl, worker, skipwhite(p+10));
|
||||
} else {
|
||||
(void)ssl_printf(ssl, "error unknown command '%s'\n", p);
|
||||
}
|
||||
@@ -1626,8 +1916,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;
|
||||
@@ -1635,7 +1925,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;
|
||||
@@ -1644,6 +1934,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;
|
||||
@@ -171,4 +174,7 @@ int ssl_printf(SSL* ssl, const char* format, ...)
|
||||
*/
|
||||
int ssl_read_line(SSL* ssl, char* buf, size_t max);
|
||||
|
||||
/** routine to printout option values over SSL */
|
||||
void remote_get_opt_ssl(char* line, void* arg);
|
||||
|
||||
#endif /* DAEMON_REMOTE_H */
|
||||
|
||||
+18
-5
@@ -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"
|
||||
@@ -58,7 +59,7 @@ timeval_add(struct timeval* d, const struct timeval* add)
|
||||
#ifndef S_SPLINT_S
|
||||
d->tv_sec += add->tv_sec;
|
||||
d->tv_usec += add->tv_usec;
|
||||
while(d->tv_usec > 1000000 ) {
|
||||
if(d->tv_usec > 1000000) {
|
||||
d->tv_usec -= 1000000;
|
||||
d->tv_sec++;
|
||||
}
|
||||
@@ -79,20 +80,31 @@ void server_stats_querymiss(struct server_stats* stats, struct worker* worker)
|
||||
stats->max_query_list_size = worker->env.mesh->all.count;
|
||||
}
|
||||
|
||||
void server_stats_prefetch(struct server_stats* stats, struct worker* worker)
|
||||
{
|
||||
stats->num_queries_prefetch++;
|
||||
/* changes the query list size so account that, like a querymiss */
|
||||
stats->sum_query_list_size += worker->env.mesh->all.count;
|
||||
if(worker->env.mesh->all.count > stats->max_query_list_size)
|
||||
stats->max_query_list_size = worker->env.mesh->all.count;
|
||||
}
|
||||
|
||||
void server_stats_log(struct server_stats* stats, struct worker* worker,
|
||||
int threadnum)
|
||||
{
|
||||
log_info("server stats for thread %d: %u queries, "
|
||||
"%u answers from cache, %u recursions",
|
||||
"%u answers from cache, %u recursions, %u prefetch",
|
||||
threadnum, (unsigned)stats->num_queries,
|
||||
(unsigned)(stats->num_queries -
|
||||
stats->num_queries_missed_cache),
|
||||
(unsigned)stats->num_queries_missed_cache);
|
||||
(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,
|
||||
stats->num_queries_missed_cache?
|
||||
(stats->num_queries_missed_cache+stats->num_queries_prefetch)?
|
||||
(double)stats->sum_query_list_size/
|
||||
stats->num_queries_missed_cache : 0.0,
|
||||
(stats->num_queries_missed_cache+
|
||||
stats->num_queries_prefetch) : 0.0,
|
||||
(unsigned)worker->env.mesh->stats_dropped);
|
||||
}
|
||||
|
||||
@@ -187,6 +199,7 @@ void server_stats_add(struct stats_info* total, struct stats_info* a)
|
||||
{
|
||||
total->svr.num_queries += a->svr.num_queries;
|
||||
total->svr.num_queries_missed_cache += a->svr.num_queries_missed_cache;
|
||||
total->svr.num_queries_prefetch += a->svr.num_queries_prefetch;
|
||||
total->svr.sum_query_list_size += a->svr.sum_query_list_size;
|
||||
/* the max size reached is upped to higher of both */
|
||||
if(a->svr.max_query_list_size > total->svr.max_query_list_size)
|
||||
|
||||
@@ -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;
|
||||
@@ -64,6 +65,8 @@ struct server_stats {
|
||||
size_t num_queries;
|
||||
/** number of queries that had a cache-miss. */
|
||||
size_t num_queries_missed_cache;
|
||||
/** number of prefetch queries - cachehits with prefetch */
|
||||
size_t num_queries_prefetch;
|
||||
|
||||
/**
|
||||
* Sum of the querylistsize of the worker for
|
||||
@@ -166,6 +169,9 @@ void server_stats_init(struct server_stats* stats, struct config_file* cfg);
|
||||
/** add query if it missed the cache */
|
||||
void server_stats_querymiss(struct server_stats* stats, struct worker* worker);
|
||||
|
||||
/** add query if was cached and also resulted in a prefetch */
|
||||
void server_stats_prefetch(struct server_stats* stats, struct worker* worker);
|
||||
|
||||
/** display the stats to the log */
|
||||
void server_stats_log(struct server_stats* stats, struct worker* worker,
|
||||
int threadnum);
|
||||
|
||||
+108
-28
@@ -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"
|
||||
@@ -85,10 +89,59 @@
|
||||
/** 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,24 +155,28 @@ 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(),
|
||||
#endif
|
||||
ldns_version(),
|
||||
get_event_sys(&evnm, &evsys, &evmethod);
|
||||
printf("linked libs: %s %s (it uses %s), ldns %s, %s\n",
|
||||
evnm, evsys, evmethod, ldns_version(),
|
||||
SSLeay_version(SSLEAY_VERSION));
|
||||
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);
|
||||
}
|
||||
|
||||
#ifndef unbound_testbound
|
||||
int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** check file descriptor count */
|
||||
static void
|
||||
checkrlimits(struct config_file* cfg)
|
||||
@@ -148,6 +205,35 @@ checkrlimits(struct config_file* cfg)
|
||||
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;
|
||||
@@ -158,8 +244,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,
|
||||
@@ -171,27 +261,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 */
|
||||
@@ -305,7 +381,7 @@ detach(void)
|
||||
if(daemon(1, 0) != 0)
|
||||
fatal_exit("daemon failed: %s", strerror(errno));
|
||||
#else /* no HAVE_DAEMON */
|
||||
#ifdef HAVE_WORKING_FORK
|
||||
#ifdef HAVE_FORK
|
||||
int fd;
|
||||
/* Take off... */
|
||||
switch (fork()) {
|
||||
@@ -329,7 +405,7 @@ detach(void)
|
||||
if (fd > 2)
|
||||
(void)close(fd);
|
||||
}
|
||||
#endif /* HAVE_WORKING_FORK */
|
||||
#endif /* HAVE_FORK */
|
||||
#endif /* HAVE_DAEMON */
|
||||
}
|
||||
|
||||
@@ -407,7 +483,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));
|
||||
}
|
||||
@@ -599,7 +675,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 */
|
||||
@@ -612,7 +690,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 ++;
|
||||
|
||||
+109
-53
@@ -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,6 +67,7 @@
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "util/tube.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "validator/autotrust.h"
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
@@ -81,6 +83,18 @@
|
||||
/** Size of an UDP datagram */
|
||||
#define NORMAL_UDP_SIZE 512 /* bytes */
|
||||
|
||||
/**
|
||||
* seconds to add to prefetch leeway. This is a TTL that expires old rrsets
|
||||
* earlier than they should in order to put the new update into the cache.
|
||||
* This additional value is to make sure that if not all TTLs are equal in
|
||||
* the message to be updated(and replaced), that rrsets with up to this much
|
||||
* extra TTL are also replaced. This means that the resulting new message
|
||||
* will have (most likely) this TTL at least, avoiding very small 'split
|
||||
* second' TTLs due to operators choosing relative primes for TTLs (or so).
|
||||
* Also has to be at least one to break ties (and overwrite cached entry).
|
||||
*/
|
||||
#define PREFETCH_EXPIRY_ADD 60
|
||||
|
||||
#ifdef UNBOUND_ALLOC_STATS
|
||||
/** measure memory leakage */
|
||||
static void
|
||||
@@ -127,7 +141,7 @@ 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))
|
||||
{
|
||||
@@ -164,6 +178,8 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
|
||||
+ sizeof(*worker->env.scratch_buffer)
|
||||
+ ldns_buffer_capacity(worker->env.scratch_buffer)
|
||||
+ forwards_get_mem(worker->env.fwds);
|
||||
if(worker->thread_num == 0)
|
||||
me += acl_list_get_mem(worker->daemon->acl);
|
||||
if(cur_serv) {
|
||||
me += serviced_get_mem(cur_serv);
|
||||
}
|
||||
@@ -269,9 +285,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)
|
||||
@@ -588,6 +605,24 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Reply to client and perform prefetch to keep cache up to date */
|
||||
static void
|
||||
reply_and_prefetch(struct worker* worker, struct query_info* qinfo,
|
||||
uint16_t flags, struct comm_reply* repinfo, uint32_t leeway)
|
||||
{
|
||||
/* first send answer to client to keep its latency
|
||||
* as small as a cachereply */
|
||||
comm_point_send_reply(repinfo);
|
||||
server_stats_prefetch(&worker->stats, worker);
|
||||
|
||||
/* create the prefetch in the mesh as a normal lookup without
|
||||
* client addrs waiting, which has the cache blacklisted (to bypass
|
||||
* the cache and go to the network for the data). */
|
||||
/* this (potentially) runs the mesh for the new query */
|
||||
mesh_new_prefetch(worker->env.mesh, qinfo, flags, leeway +
|
||||
PREFETCH_EXPIRY_ADD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill CH class answer into buffer. Keeps query.
|
||||
* @param pkt: buffer
|
||||
@@ -805,6 +840,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
}
|
||||
if(local_zones_answer(worker->daemon->local_zones, &qinfo, &edns,
|
||||
c->buffer, worker->scratchpad)) {
|
||||
regional_free_all(worker->scratchpad);
|
||||
if(ldns_buffer_limit(c->buffer) == 0) {
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
@@ -834,6 +870,17 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
*(uint16_t*)ldns_buffer_begin(c->buffer),
|
||||
ldns_buffer_read_u16_at(c->buffer, 2), repinfo,
|
||||
&edns)) {
|
||||
/* prefetch it if the prefetch TTL expired */
|
||||
if(worker->env.cfg->prefetch && *worker->env.now >=
|
||||
((struct reply_info*)e->data)->prefetch_ttl) {
|
||||
uint32_t leeway = ((struct reply_info*)e->
|
||||
data)->ttl - *worker->env.now;
|
||||
lock_rw_unlock(&e->lock);
|
||||
reply_and_prefetch(worker, &qinfo,
|
||||
ldns_buffer_read_u16_at(c->buffer, 2),
|
||||
repinfo, leeway);
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 1;
|
||||
}
|
||||
@@ -862,14 +909,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));
|
||||
@@ -921,8 +960,10 @@ worker_restart_timer(struct worker* worker)
|
||||
{
|
||||
if(worker->env.cfg->stat_interval > 0) {
|
||||
struct timeval tv;
|
||||
#ifndef S_SPLINT_S
|
||||
tv.tv_sec = worker->env.cfg->stat_interval;
|
||||
tv.tv_usec = 0;
|
||||
#endif
|
||||
comm_timer_set(worker->stat_timer, &tv);
|
||||
}
|
||||
}
|
||||
@@ -940,9 +981,22 @@ void worker_stat_timer_cb(void* arg)
|
||||
worker_restart_timer(worker);
|
||||
}
|
||||
|
||||
void worker_probe_timer_cb(void* arg)
|
||||
{
|
||||
struct worker* worker = (struct worker*)arg;
|
||||
struct timeval tv;
|
||||
#ifndef S_SPLINT_S
|
||||
tv.tv_sec = (time_t)autr_probe_timer(&worker->env);
|
||||
tv.tv_usec = 0;
|
||||
#endif
|
||||
if(tv.tv_sec != 0)
|
||||
comm_timer_set(worker->env.probe_timer, &tv);
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -960,6 +1014,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;
|
||||
}
|
||||
|
||||
@@ -967,7 +1034,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) {
|
||||
@@ -1012,16 +1078,6 @@ 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);
|
||||
@@ -1036,7 +1092,8 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
cfg->do_tcp?cfg->outgoing_num_tcp:0,
|
||||
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->unwanted_threshold, &worker_alloc_cleanup, worker,
|
||||
cfg->do_udp);
|
||||
if(!worker->back) {
|
||||
log_err("could not create outgoing sockets");
|
||||
worker_delete(worker);
|
||||
@@ -1063,7 +1120,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,
|
||||
@@ -1074,7 +1130,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;
|
||||
@@ -1091,6 +1146,24 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
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
|
||||
&& worker->thread_num == 0
|
||||
#endif
|
||||
) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
worker->env.probe_timer = comm_timer_create(worker->base,
|
||||
worker_probe_timer_cb, worker);
|
||||
if(!worker->env.probe_timer) {
|
||||
log_err("could not create 5011-probe timer");
|
||||
} else {
|
||||
/* let timer fire, then it can reset itself */
|
||||
comm_timer_set(worker->env.probe_timer, &tv);
|
||||
}
|
||||
}
|
||||
if(!worker->env.mesh || !worker->env.scratch_buffer) {
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
@@ -1130,6 +1203,7 @@ worker_delete(struct worker* worker)
|
||||
comm_signal_delete(worker->comsig);
|
||||
tube_delete(worker->cmd);
|
||||
comm_timer_delete(worker->stat_timer);
|
||||
comm_timer_delete(worker->env.probe_timer);
|
||||
free(worker->ports);
|
||||
if(worker->thread_num == 0) {
|
||||
log_set_time(NULL);
|
||||
@@ -1144,19 +1218,6 @@ 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)
|
||||
@@ -1170,7 +1231,7 @@ outbound_entry_compare(void* a, void* b)
|
||||
|
||||
struct outbound_entry*
|
||||
worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
|
||||
uint16_t qclass, uint16_t flags, int dnssec,
|
||||
uint16_t qclass, uint16_t flags, int dnssec, int want_dnssec,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct module_qstate* q)
|
||||
{
|
||||
@@ -1181,9 +1242,9 @@ 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,
|
||||
addr, addrlen, worker_handle_service_reply, e,
|
||||
worker->back->udp_buff, &outbound_entry_compare);
|
||||
if(!e->qsent) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -1206,19 +1267,11 @@ void worker_stats_clear(struct worker* worker)
|
||||
}
|
||||
|
||||
/* --- 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))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -1249,13 +1302,15 @@ void libworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube),
|
||||
}
|
||||
|
||||
void libworker_fg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
|
||||
ldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s))
|
||||
ldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s),
|
||||
char* ATTR_UNUSED(why_bogus))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void libworker_bg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
|
||||
ldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s))
|
||||
ldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s),
|
||||
char* ATTR_UNUSED(why_bogus))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
@@ -1277,3 +1332,4 @@ int codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+5
-18
@@ -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,6 +172,7 @@ 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 q: wich query state to reactivate upon return.
|
||||
@@ -197,7 +181,7 @@ int worker_send_packet(ldns_buffer* pkt, struct sockaddr_storage* addr,
|
||||
*/
|
||||
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,
|
||||
int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct module_qstate* q);
|
||||
|
||||
/**
|
||||
@@ -236,4 +220,7 @@ void worker_stats_clear(struct worker* worker);
|
||||
/** statistics timer callback handler */
|
||||
void worker_stat_timer_cb(void* arg);
|
||||
|
||||
/** probe timer callback handler */
|
||||
void worker_probe_timer_cb(void* arg);
|
||||
|
||||
#endif /* DAEMON_WORKER_H */
|
||||
|
||||
@@ -16,3 +16,5 @@ Alexander Gall - multihomed, anycast testing of unbound resolver server.
|
||||
Zdenek Vasicek and Marek Vavrusa - python module.
|
||||
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.
|
||||
|
||||
+1009
File diff suppressed because it is too large
Load Diff
+48
-4
@@ -28,10 +28,16 @@ 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
|
||||
altogether, or, on Solaris, also use --with(out)-solaris-threads.
|
||||
* --enable-checking
|
||||
This enables assertions in the code that guard against a variety of
|
||||
programming errors, among which buffer overflows. The program exits
|
||||
with an error if an assertion fails (but the buffer did not overflow).
|
||||
* --enable-static-exe
|
||||
This enables a debug option to statically link, against ldns and
|
||||
libevent libraries.
|
||||
@@ -55,6 +61,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.
|
||||
@@ -63,11 +76,12 @@ This software is under BSD license, see LICENSE for details.
|
||||
Needs python-devel and swig development tools.
|
||||
* --with-pythonmodule
|
||||
Compile the python module that processes responses in the server.
|
||||
* --enable-sha2
|
||||
Enable draft support for RSASHA256 and RSASHA512.
|
||||
* --disable-sha2
|
||||
Disable support for RSASHA256 and RSASHA512 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
|
||||
------------
|
||||
@@ -91,10 +105,14 @@ 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
|
||||
unbound daemon and unbound-control.
|
||||
o Crosscompile seems to hang. You tried to install unbound under wine.
|
||||
wine regedit and remove all the unbound entries from the registry or
|
||||
delete .wine/drive_c.
|
||||
|
||||
Acknowledgements
|
||||
----------------
|
||||
@@ -106,4 +124,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 BDS 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.
|
||||
|
||||
|
||||
@@ -62,169 +62,15 @@ o infra and lame cache: easier size config (in Mb), show usage in graphs.
|
||||
- store time of dump in cachedumps, so that on a load the ttls can be
|
||||
compared to the absolute time, and now-expired items can be dealt with.
|
||||
|
||||
1.3.x:
|
||||
- spoofed delegpt fixes - if DNSKEY prime fails
|
||||
- set DNSKEY bogus and DNSKEY query msg bogus.
|
||||
- make NS set bogus too - if not validated as secure.
|
||||
- check where queries go - otherwise reduce TTL on NS.
|
||||
- also make DS NSEC bogus. Also DS msg cache entry.
|
||||
- mark bogus under stringent conditions
|
||||
- if DS at parent and validly signed. Then DNSKEY must exist.
|
||||
- Also for trust anchor points themselves. DNSKEY must exist.
|
||||
- so if then DNSKEY keyprime fails
|
||||
- then it is not simply a server that only answers qtype A.
|
||||
- then parent is agreeing (somewhat) with the DS record
|
||||
- but it could still be a lame domain, these exist
|
||||
The objective is to keep tries for genuinely lame domains to a
|
||||
minimum, while detecting forgeries quickly. exponential backoff.
|
||||
- for unbound we can check if we got something to verify while
|
||||
building that chain of trust. If so - not lame, agressive retry.
|
||||
- but security-lame zones also exist and should not pose
|
||||
too high a burden. Exponential backoff again.
|
||||
(fe. badly signed or dnskey reply too large fails).
|
||||
- the delegation NS for the domain is bogus.
|
||||
The referral retried, with exponential backoff.
|
||||
This exponential backoff should go towards values which are close
|
||||
to the TTLs that are used now (on lame delegations for example).
|
||||
so that the extra traffic is manageable.
|
||||
- for unbound, reset the TTL on the NS rrset. Let it timeout.
|
||||
Set NS rrset bogus - no more queries to the domain are done.
|
||||
Also set DNSKEY and DS (rrset, NSEC, msg) bogus and ttl like that.
|
||||
(to the same absolute value, so a clean retry is done).
|
||||
TTL of NS is (rounddown) timeout in seconds.
|
||||
Until the NS times out and referral is done again.
|
||||
Make sure multiple validations for chains of trust do not result
|
||||
in a flood of queries or backoff too quickly.
|
||||
- bogus exponential backoff cache. hash(name,t,c), size(1M, 5%).
|
||||
TTL of 24h. Backoff from 200msec to 24h.
|
||||
x2 on bogus(18 tries), x8 backoff on lameness(6 tries),
|
||||
when servfail for DNSKEY.
|
||||
remove entry when validated as secure.
|
||||
delegptspoofrecheck on lameness when harden-referral-path NS
|
||||
query has servfail, then build chain of trust down (check DS,
|
||||
then perform DNSKEY query) if that DNSKEY query fails servfail,
|
||||
perform the x8 lameness retry fallback.
|
||||
|
||||
* keep a list of guilty IP addresses in the qstate, which contains both
|
||||
the child side guilty IPs and the parent guilty IPs. Valid signed DSes
|
||||
are not made guilty in the global cache. The child IP is made guilty
|
||||
in the global cache.
|
||||
* Retry to higher trust anchors.
|
||||
* option not to retry to higher from this ta.
|
||||
* keep longest must-be-secure name. Do no accept insecure above this point.
|
||||
* if failed ta, blame all lower tas for their DNSKEY (get IP from cached
|
||||
rrset), if failure is insecure - nothing, if at bogus - blame that too.
|
||||
lower tas have isdata=false, so the IP address for the dnskeyrrset in
|
||||
the cache is set to avoid in qstate. Nothing in infracache, no childretry.
|
||||
|
||||
Retry harder to get valid DNSSEC data.
|
||||
Triggered by a trust anchor or by a signed DS record for a zone.
|
||||
* If data is fetched and validation fails for it
|
||||
or DNSKEY is fetched and validated into chain-of-trust fails for it
|
||||
or DS is fetched and validated into chain-of-trust fails for it
|
||||
Then
|
||||
blame(signer zone, IP origin of the data/DNSKEY/DS, x2, isdata)
|
||||
* If data was not fetched (SERVFAIL, lame, ...), and the data
|
||||
is under a signed DS then:
|
||||
blame(thatDSname, IP origin of the data/DNSKEY/DS, x8)
|
||||
x8 because the zone may be lame.
|
||||
This means a chain of trust is built also for unfetched data, to
|
||||
determine if a signed DS is present. If insecure, nothing is done.
|
||||
* If DNSKEY was not fetched for chain of trust (SERVFAIL, lame, ...),
|
||||
Then
|
||||
blame(DNSKEYname, IP origin of the data/DNSKEY/DS, x8)
|
||||
x8 because the zone may be lame.
|
||||
* blame(zonename, guiltyIP, multiplier, isdata):
|
||||
* if isdata:
|
||||
Set the guiltyIP,zonename as DNSSEC-bogus-data=true in lameness cache.
|
||||
Thusly marked servers are avoided if possible, used as last resort.
|
||||
The guilt TTL is the infra cache ttl (15 minutes).
|
||||
The dnssec retry scheme works without this cache entry.
|
||||
* If the key cache entry 'being-backed-off' is true and isdata then:
|
||||
The parent is backedoff, it must be the childs fault. Retry to child.
|
||||
Perform a child-retry - purge dataonly, childside, mark
|
||||
data-IPaddress from child as to avoid-forquery. counterperquery,
|
||||
max is 3, if reached, set this data element RRset&msg to the
|
||||
current backoff TTL end-time or bogus-ttl(60 seconds) whichever is less
|
||||
and done.
|
||||
* if no retry entry exists for the zone key, create one with 24h TTL, 10 ms.
|
||||
else the backoff *= multiplier.
|
||||
* If the backoff is less than a second, remove entries from cache and
|
||||
restart query. Else set the TTL for the entries to that value.
|
||||
* Entries to set or remove: DNSKEY RRset&msg, DS RRset&msg, NS RRset&msg,
|
||||
in-zone glue (A and AAAA) RRset&msg, and key-cache-entry TTL.
|
||||
The the data element RRset&msg to the backoff TTL or bogusttl.
|
||||
If TTL>1sec set key-cache-entry flag 'being-backed-off' to true.
|
||||
when entry times out that flag is reset to false again.
|
||||
* Storage extra is:
|
||||
IP address per RRset and message. A lot of memory really, since that is
|
||||
132 bytes per RRset and per message. Store plain IP: 4/16 bytes, len byte.
|
||||
port number 2bytes. +19bytes per RRset, per msg.
|
||||
guilt flag in infra(lameness) cache.
|
||||
being-backed-off flag for key cache, also backoff time value and its TTL.
|
||||
child-retry-count and guilty-ip-list in qstate.
|
||||
* Load on authorities:
|
||||
For lame servers: 7 tries per day (one per three hours on average).
|
||||
Others get up to 23 tries per day (one per hour on average).
|
||||
+1 for original try makes 8/24 hours and 24/24 hours.
|
||||
Unless the cache entry falls out of the cache due to memory. In that
|
||||
case it can be tried more often, this is similar to the NS entry falling
|
||||
out of the cache due to memory, in that case it also has to be retried.
|
||||
* Performance analysis:
|
||||
* domain is sold. Unbound sees invalid signature (expired) or the old
|
||||
servers refuse the queries. Retry within the second, if parent has
|
||||
new DS and NS available instantly works again (no downtime).
|
||||
* domain is bogus signed. Parent gets 1 query per hour.
|
||||
Domain itself gets couple tries per queryname, per minute.
|
||||
* domain partly bogus. Parent gets 1 query per hour.
|
||||
Domain itself gets couple tries per bogus queryname, per minute.
|
||||
* spoof attempt. Unbound tries a couple times. If not spoofed again,
|
||||
it works, if spoofed every time unbound backs off and stops trying.
|
||||
But childretry is attempted more often, once per minute.
|
||||
* parent has inconsistently signed DS records. Together with a subzone that
|
||||
is badly managed. Unbound backs up to the root once per hour.
|
||||
* parent has bad DS records, different sets on different servers, but they
|
||||
are signed ok. Works as for every query a list of bad nameserver, parent
|
||||
and child side is kept, walks through them. But as backoff increases
|
||||
and becomes bigger than the TTL on the DS records, unbound will blackout.
|
||||
The parent really has to be fixed...
|
||||
The issue is that it is validly signed, but bad data. Unbound will very
|
||||
conservatively retry it.
|
||||
* domain is sold, but decommission is faster than the setup of new server.
|
||||
Unbound does exponential backoff, if new setup is fast, it'll pickup the
|
||||
new data fast.
|
||||
* key rollover failed. The zone has bad keys. Like it was bogus signed.
|
||||
* one nameserver has bad data. Unbound goes back to the parent but also
|
||||
marks that server as guilty. Picks data from other server right after,
|
||||
retry without blackout for the user.
|
||||
When parent starts to get backed off, if the nameserver is childside,
|
||||
queryretries for childservers are made when queries fail.
|
||||
* domain was sold, but unbound has old entries in the cache. These somehow
|
||||
need (re)validation (were queried with +cd, now -cd). The entries are
|
||||
bogus.
|
||||
Unbound performs childretry for these entries. Works once the keys
|
||||
have been successfully reprimed with parentretry.
|
||||
* unbound is configured to talk to upstream caches. These caches have
|
||||
inconsistent bad data. If one is bad, it is marked bad for that zone.
|
||||
If all are bad, there may not be any way for unbound to remove the
|
||||
bad entries from the upstream caches. It simply fails.
|
||||
Recommendation: make the upstream caches validate as well.
|
||||
* Old data that was valid with a long TTL remains in the cache.
|
||||
Valid data has a TTL and this is the protocol.
|
||||
* listing bad servers and trying again may not be good enough, since
|
||||
a combinatorial explosion for DSxDNSKEYxdata is possible for every
|
||||
signature validation (using different nameservers for DS, DNSKEY and
|
||||
data, assuming only the right combination has a chain of trust to data).
|
||||
The parentretries perform DS and DNSKEY searching.
|
||||
childretries perform data searching.
|
||||
|
||||
|
||||
later
|
||||
- selective verbosity; ubcontrol trace example.com
|
||||
- option to log only bogus domainname encountered, for demos
|
||||
- cache fork-dump, pre-load
|
||||
- for fwds, send queries to N servers in fwd-list, use first reply.
|
||||
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
|
||||
|
||||
|
||||
@@ -62,5 +62,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.
|
||||
|
||||
+47
-6
@@ -32,10 +32,11 @@ server:
|
||||
# specify the interfaces to answer queries from by ip-address.
|
||||
# The default is to listen to localhost (127.0.0.1 and ::1).
|
||||
# specify 0.0.0.0 and ::0 to bind to all available interfaces.
|
||||
# specify every interface on a new 'interface:' labelled line.
|
||||
# specify every interface[@port] on a new 'interface:' labelled line.
|
||||
# The listen interfaces are not changed on reload, only on restart.
|
||||
# interface: 192.0.2.153
|
||||
# interface: 192.0.2.154
|
||||
# interface: 192.0.2.154@5003
|
||||
# interface: 2001:DB8::5
|
||||
|
||||
# enable this feature to copy the source address of queries to reply.
|
||||
@@ -53,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.
|
||||
@@ -73,6 +75,14 @@ server:
|
||||
# number of incoming simultaneous tcp buffers to hold per thread.
|
||||
# incoming-num-tcp: 10
|
||||
|
||||
# buffer size for UDP port 53 incoming (SO_RCVBUF socket option).
|
||||
# 0 is system default. Use 4m to catch query spikes for busy servers.
|
||||
# so-rcvbuf: 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
|
||||
|
||||
# buffer size for handling DNS data. No messages larger than this
|
||||
# size can be sent or received, by UDP or TCP. In bytes.
|
||||
# msg-buffer-size: 65552
|
||||
@@ -261,7 +271,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
|
||||
|
||||
@@ -285,10 +295,24 @@ server:
|
||||
# if no, localhost can be queried (for testing and debugging).
|
||||
# do-not-query-localhost: yes
|
||||
|
||||
# if yes, perform prefetching of almost expired message cache entries.
|
||||
# prefetch: no
|
||||
|
||||
# if yes, perform key lookups adjacent to normal lookups.
|
||||
# prefetch-key: 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:
|
||||
# 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
|
||||
@@ -297,10 +321,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: ""
|
||||
|
||||
|
||||
# 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"
|
||||
@@ -309,6 +335,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.
|
||||
@@ -324,7 +351,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
|
||||
@@ -342,11 +369,25 @@ server:
|
||||
# replies if the message is found secure. The default is off.
|
||||
# val-permissive-mode: 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
|
||||
|
||||
# It is possible to configure NSEC3 maximum iteration counts per
|
||||
# keysize. Keep this table very short, as linear search is done.
|
||||
# A message with an NSEC3 with larger count is marked insecure.
|
||||
# List in ascending order the keysize and count values.
|
||||
# val-nsec3-keysize-iterations: "1024 150 2048 500 4096 2500"
|
||||
|
||||
# instruct the auto-trust-anchor-file probing to add anchors after ttl.
|
||||
# add-holddown: 2592000 # 30 days
|
||||
|
||||
# instruct the auto-trust-anchor-file probing to del anchors after ttl.
|
||||
# del-holddown: 2592000 # 30 days
|
||||
|
||||
# auto-trust-anchor-file probing removes missing anchors after ttl.
|
||||
# If the value 0 is given, missing anchors are not removed.
|
||||
# keep-missing: 31622400 # 366 days
|
||||
|
||||
# the amount of memory to use for the key cache.
|
||||
# plain value in bytes or you can append k, m or G. default is "4Mb".
|
||||
|
||||
+19
-11
@@ -17,6 +17,7 @@
|
||||
.B ub_ctx_create,
|
||||
.B ub_ctx_delete,
|
||||
.B ub_ctx_set_option,
|
||||
.B ub_ctx_get_option,
|
||||
.B ub_ctx_config,
|
||||
.B ub_ctx_set_fwd,
|
||||
.B ub_ctx_resolvconf,
|
||||
@@ -56,6 +57,9 @@
|
||||
\fBub_ctx_set_option\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR opt, \fIchar*\fR val);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_get_option\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR opt, \fIchar**\fR val);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_config\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
|
||||
.LP
|
||||
\fIint\fR
|
||||
@@ -100,9 +104,7 @@
|
||||
\fIint\fR
|
||||
\fBub_resolve\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR name,
|
||||
.br
|
||||
\fIint\fR rrtype, \fIint\fR rrclass, \fIint*\fR secure,
|
||||
.br
|
||||
\fIint*\fR data, \fIstruct ub_result**\fR result);
|
||||
\fIint\fR rrtype, \fIint\fR rrclass, \fIstruct ub_result**\fR result);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_resolve_async\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR name,
|
||||
@@ -180,6 +182,11 @@ config file format, see \fIunbound.conf\fR(5). Not all options are
|
||||
relevant. For some specific options, such as adding trust anchors, special
|
||||
routines exist. Pass the option name with the trailing ':'.
|
||||
.TP
|
||||
.B ub_ctx_get_option
|
||||
A power\-user interface that gets an option value. Some options cannot be
|
||||
gotten, and others return a newline separated list. Pass the option name
|
||||
without trailing ':'. The returned value must be free(2)d by the caller.
|
||||
.TP
|
||||
.B ub_ctx_config
|
||||
A power\-user interface that lets you specify an unbound config file, see
|
||||
\fIunbound.conf\fR(5), which is read for configuration. Not all options are
|
||||
@@ -201,14 +208,16 @@ 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
|
||||
settings from \fIresolv.conf\fR(5) are ignored.
|
||||
If fname NULL is passed, "/etc/resolv.conf" is used.
|
||||
If fname NULL is passed, "/etc/resolv.conf" is used (if on Windows,
|
||||
the system\-wide configured nameserver is picked instead).
|
||||
At this time it is only possible to set configuration before the
|
||||
first resolve is done.
|
||||
.TP
|
||||
.B ub_ctx_hosts
|
||||
Read list of hosts from the filename given.
|
||||
Usually "/etc/hosts". When queried for, these addresses are not marked
|
||||
DNSSEC secure. If fname NULL is passed, "/etc/hosts" is used.
|
||||
DNSSEC secure. If fname NULL is passed, "/etc/hosts" is used
|
||||
(if on Windows, etc/hosts from WINDIR is picked instead).
|
||||
At this time it is only possible to set configuration before the
|
||||
first resolve is done.
|
||||
.TP
|
||||
@@ -217,7 +226,7 @@ ub_ctx_add_ta
|
||||
Add a trust anchor to the given context.
|
||||
At this time it is only possible to add trusted keys before the
|
||||
first resolve is done.
|
||||
The format is a string, similar to the zone-file format,
|
||||
The format is a string, similar to the zone\-file format,
|
||||
[domainname] [type] [rdata contents]. Both DS and DNSKEY records are accepted.
|
||||
.TP
|
||||
.B ub_ctx_add_ta_file
|
||||
@@ -228,13 +237,13 @@ first resolve is done.
|
||||
.TP
|
||||
.B ub_ctx_trustedkeys
|
||||
Add trust anchors to the given context.
|
||||
Pass the name of a bind-style config file with trusted-keys{}.
|
||||
Pass the name of a bind\-style config file with trusted\-keys{}.
|
||||
At this time it is only possible to add trusted keys before the
|
||||
first resolve is done.
|
||||
.TP
|
||||
.B ub_ctx_debugout
|
||||
Set debug and error log output to the given stream. Pass NULL to disable
|
||||
output. Default is stderr. File-names or using syslog can be enabled
|
||||
output. Default is stderr. File\-names or using syslog can be enabled
|
||||
using config options, this routine is for using your own stream.
|
||||
.TP
|
||||
.B ub_ctx_debuglevel
|
||||
@@ -281,8 +290,6 @@ Will perform necessary callbacks.
|
||||
Perform resolution and validation of the target name.
|
||||
The name is a domain name in a zero terminated text string.
|
||||
The rrtype and rrclass are DNS type and class codes.
|
||||
The value secure returns true if the answer validated securely.
|
||||
The value data returns true if there was data.
|
||||
The result structure is newly allocated with the resulting data.
|
||||
.TP
|
||||
.B ub_resolve_async
|
||||
@@ -349,6 +356,7 @@ The result of the DNS resolution and validation is returned as
|
||||
int nxdomain; /* true if nodata because name does not exist */
|
||||
int secure; /* true if result is secure */
|
||||
int bogus; /* true if a security failure happened */
|
||||
char* why_bogus; /* string with error if bogus */
|
||||
};
|
||||
.fi
|
||||
.P
|
||||
@@ -366,7 +374,7 @@ returns NULL on an error (a malloc failure).
|
||||
.B ub_poll
|
||||
returns true if some information may be available, false otherwise.
|
||||
.B ub_fd
|
||||
returns a file descriptor or -1 on error.
|
||||
returns a file descriptor or \-1 on error.
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound\fR(8).
|
||||
|
||||
@@ -260,3 +260,35 @@ o NXDOMAIN and SOA serial numbers.
|
||||
updated more carefully. If one of the NSEC records in an NXDOMAIN is
|
||||
updated from another query, the NXDOMAIN is dropped from the cache,
|
||||
and queried for again, so that its proof can be checked again.
|
||||
|
||||
o SOA records in negative cached answers for DS queries.
|
||||
The current unbound code uses a negative cache for queries for type DS.
|
||||
This speeds up building chains of trust, and uses NSEC and NSEC3
|
||||
(optout) information to speed up lookups. When used internally,
|
||||
the bare NSEC(3) information is sufficient, probably picked up from
|
||||
a referral. When answering to clients, a SOA record is needed for
|
||||
the correct message format, a SOA record is picked from the cache
|
||||
(and may not actually match the serial number of the SOA for which the
|
||||
NSEC and NSEC3 records were obtained) if available otherwise network
|
||||
queries are performed to get the data.
|
||||
|
||||
o Parent and child with different nameserver information.
|
||||
A misconfiguration that sometimes happens is where the parent and child
|
||||
have different NS, glue information. The child is authoritative, and
|
||||
unbound will not trust information from the parent nameservers as the
|
||||
final answer. To help lookups, unbound will however use the parent-side
|
||||
version of the glue as a last resort lookup. This resolves lookups for
|
||||
those misconfigured domains where the servers reported by the parent
|
||||
are the only ones working, and servers reported by the child do not.
|
||||
|
||||
o Failure of validation and probing.
|
||||
Retries on a validation failure are now 5x to a different nameserver IP
|
||||
(if possible), and then it gives up, for one name, type, class entry in
|
||||
the message cache. If a DNSKEY or DS fails in the chain of trust in the
|
||||
key cache additionally, after the probing, a bad key entry is created that
|
||||
makes the entire zone bogus for 900 seconds. This is a fixed value at
|
||||
this time and is conservative in sending probes. It makes the compound
|
||||
effect of many resolvers less and easier to handle, but penalizes
|
||||
individual resolvers by having less probes and a longer time before fixes
|
||||
are picked up.
|
||||
|
||||
|
||||
@@ -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@"
|
||||
# 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
|
||||
If 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.
|
||||
.TP
|
||||
.B \-v
|
||||
More verbose. Prints output detailing what happens.
|
||||
.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).
|
||||
@@ -9,16 +9,16 @@
|
||||
.\"
|
||||
.SH "NAME"
|
||||
.LP
|
||||
unbound-checkconf
|
||||
unbound\-checkconf
|
||||
\- Check unbound configuration file for errors.
|
||||
.SH "SYNOPSIS"
|
||||
.B unbound-checkconf
|
||||
.B unbound\-checkconf
|
||||
.RB [ \-h ]
|
||||
.RB [ \-o
|
||||
.IR option ]
|
||||
.RI [ cfgfile ]
|
||||
.SH "DESCRIPTION"
|
||||
.B Unbound-checkconf
|
||||
.B Unbound\-checkconf
|
||||
checks the configuration file for the
|
||||
\fIunbound\fR(8)
|
||||
DNS resolver for syntax and other errors.
|
||||
@@ -38,7 +38,7 @@ printed to stdout. For "" (disabled) options an empty line is printed.
|
||||
The config file to read with settings for unbound. It is checked.
|
||||
If omitted, the config file at the default location is checked.
|
||||
.SH "EXIT CODE"
|
||||
The unbound-checkconf program exits with status code 1 on error,
|
||||
The unbound\-checkconf program exits with status code 1 on error,
|
||||
0 for a correct config file.
|
||||
.SH "FILES"
|
||||
.TP
|
||||
|
||||
+66
-13
@@ -9,10 +9,11 @@
|
||||
.\"
|
||||
.SH "NAME"
|
||||
.LP
|
||||
unbound-control
|
||||
.B unbound\-control,
|
||||
.B unbound\-control\-setup
|
||||
\- Unbound remote server control utility.
|
||||
.SH "SYNOPSIS"
|
||||
.B unbound-control
|
||||
.B unbound\-control
|
||||
.RB [ \-h ]
|
||||
.RB [ \-c
|
||||
.IR cfgfile ]
|
||||
@@ -20,7 +21,7 @@ unbound-control
|
||||
.IR server ]
|
||||
.IR command
|
||||
.SH "DESCRIPTION"
|
||||
.B Unbound-control
|
||||
.B Unbound\-control
|
||||
performs remote administration on the \fIunbound\fR(8) DNS server.
|
||||
It reads the configuration file, contacts the unbound server over SSL
|
||||
sends the command and displays the result.
|
||||
@@ -56,6 +57,11 @@ Change verbosity value for logging. Same values as \fBverbosity\fR keyword in
|
||||
\fIunbound.conf\fR(5). This new setting lasts until the server is issued
|
||||
a reload (taken from config file again), or the next verbosity control command.
|
||||
.TP
|
||||
.B log_reopen
|
||||
Reopen the logfile, close and open it. Useful for logrotation to make the
|
||||
daemon release the file it is logging to. If you are using syslog it will
|
||||
attempt to close and open the syslog (which may not work if chrooted).
|
||||
.TP
|
||||
.B stats
|
||||
Print statistics. Resets the internal counters to zero, this can be
|
||||
controlled using the \fBstatistics\-cumulative\fR config statement.
|
||||
@@ -98,7 +104,8 @@ redirect it to a file to store the cache in a file.
|
||||
.B load_cache
|
||||
The contents of the cache is loaded from stdin. Uses the same format as
|
||||
dump_cache uses. Loading the cache with old, or wrong data can result
|
||||
in old or wrong data returned to clients.
|
||||
in old or wrong data returned to clients. Loading data into the cache
|
||||
in this way is supported in order to aid with debugging.
|
||||
.TP
|
||||
.B lookup \fIname
|
||||
Print to stdout the name servers that would be used to look up the
|
||||
@@ -135,17 +142,51 @@ 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 forward [off | addr ... ]
|
||||
.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.
|
||||
.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.
|
||||
.TP
|
||||
.B list_stubs
|
||||
List the stub zones in use. These are printed one by one to the output.
|
||||
This includes the root hints in use.
|
||||
.TP
|
||||
.B list_forwards
|
||||
List the forward zones in use. These are printed zone by zone to the output.
|
||||
.TP
|
||||
.B list_local_zones
|
||||
List the local zones in use. These are printed one per line with zone type.
|
||||
.TP
|
||||
.B list_local_data
|
||||
List the local data RRs in use. The resource records are printed.
|
||||
.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
|
||||
the current config. You could pass the nameservers after a DHCP update.
|
||||
.IP
|
||||
Without arguments the current list of addresses used to forward all queries
|
||||
to is printed. On startup this is from the forward-zone "." configuration.
|
||||
to is printed. On startup this is from the forward\-zone "." configuration.
|
||||
Afterwards it shows the status. It prints off when no forwarding is used.
|
||||
.IP
|
||||
If \fIoff\fR is passed, forwarding is disabled and the root nameservers
|
||||
are used. This can be used to avoid to avoid buggy or non-DNSSEC supporting
|
||||
are used. This can be used to avoid to avoid buggy or non\-DNSSEC supporting
|
||||
nameservers returned from DHCP. But may not work in hotels or hotspots.
|
||||
.IP
|
||||
If one or more IPv4 or IPv6 addresses are given, those are then used to forward
|
||||
@@ -156,13 +197,15 @@ By default the forwarder information from the config file for the root "." is
|
||||
used. The config file is not changed, so after a reload these changes are
|
||||
gone. Other forward zones from the config file are not affected by this command.
|
||||
.SH "EXIT CODE"
|
||||
The unbound-control program exits with status code 1 on error, 0 on success.
|
||||
The unbound\-control program exits with status code 1 on error, 0 on success.
|
||||
.SH "SET UP"
|
||||
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
|
||||
@@ -170,7 +213,7 @@ If you have not configured
|
||||
a username in unbound.conf, the keys need read permission for the user
|
||||
credentials under which the daemon is started.
|
||||
The script preserves private keys present in the directory.
|
||||
After running the script as root, turn on \fBcontrol-enable\fR in
|
||||
After running the script as root, turn on \fBcontrol\-enable\fR in
|
||||
\fIunbound.conf\fR.
|
||||
.SH "STATISTIC COUNTERS"
|
||||
The \fIstats\fR command shows a number of statistic counters.
|
||||
@@ -184,6 +227,13 @@ number of queries that were successfully answered using a cache lookup
|
||||
.I threadX.num.cachemiss
|
||||
number of queries that needed recursive processing
|
||||
.TP
|
||||
.I threadX.num.prefetch
|
||||
number of cache prefetches performed. This number is included in
|
||||
cachehits, as the original query had the unprefetched answer from cache,
|
||||
and resulted in recursive processing, taking a slot in the requestlist.
|
||||
Not part of the recursivereplies (or the histogram thereof) or cachemiss,
|
||||
as a cache response was sent.
|
||||
.TP
|
||||
.I threadX.num.recursivereplies
|
||||
The number of replies sent to queries that needed recursive processing. Could be smaller than threadX.num.cachemiss if due to timeouts no replies were sent for some queries.
|
||||
.TP
|
||||
@@ -225,6 +275,9 @@ summed over threads.
|
||||
.I total.num.cachemiss
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.prefetch
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.recursivereplies
|
||||
summed over threads.
|
||||
.TP
|
||||
@@ -284,13 +337,13 @@ Printed for the other query types as well, but only for the types for which
|
||||
queries were received, thus =0 entries are omitted for brevity.
|
||||
.TP
|
||||
.I num.query.type.other
|
||||
Number of queries with query types 256-65535.
|
||||
Number of queries with query types 256\-65535.
|
||||
.TP
|
||||
.I num.query.class.IN
|
||||
The total number of queries over all threads with query class IN (internet).
|
||||
Also printed for other classes (such as CH (CHAOS) sometimes used for
|
||||
debugging), or NONE, ANY, used by dynamic update.
|
||||
num.query.class.other is printed for classes 256-65535.
|
||||
num.query.class.other is printed for classes 256\-65535.
|
||||
.TP
|
||||
.I num.query.opcode.QUERY
|
||||
The total number of queries over all threads with query opcode QUERY.
|
||||
@@ -356,7 +409,7 @@ unbound configuration file.
|
||||
.TP
|
||||
.I @UNBOUND_RUN_DIR@
|
||||
directory with private keys (unbound_server.key and unbound_control.key) and
|
||||
self-signed certificates (unbound_server.pem and unbound_control.pem).
|
||||
self\-signed certificates (unbound_server.pem and unbound_control.pem).
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound\fR(8).
|
||||
|
||||
+136
-39
@@ -52,8 +52,8 @@ server:
|
||||
username: unbound
|
||||
# make sure unbound can access entropy from inside the chroot.
|
||||
# e.g. on linux the use these commands (on BSD, devfs(8) is used):
|
||||
# mount --bind -n /dev/random /etc/unbound/dev/random
|
||||
# and mount --bind -n /dev/log /etc/unbound/dev/log
|
||||
# mount \-\-bind \-n /dev/random /etc/unbound/dev/random
|
||||
# and mount \-\-bind \-n /dev/log /etc/unbound/dev/log
|
||||
chroot: "/etc/unbound"
|
||||
# logfile: "/etc/unbound/unbound.log" #uncomment to use logfile.
|
||||
pidfile: "/etc/unbound/unbound.pid"
|
||||
@@ -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.
|
||||
@@ -108,18 +112,20 @@ The number of threads to create to serve clients. Use 1 for no threading.
|
||||
.B port: \fI<port number>
|
||||
The port number, default 53, on which the server responds to queries.
|
||||
.TP
|
||||
.B interface: \fI<ip address>
|
||||
.B interface: \fI<ip address[@port]>
|
||||
Interface to use to connect to the network. This interface is listened to
|
||||
for queries from clients, and answers to clients are given from it.
|
||||
Can be given multiple times to work on several interfaces. If none are
|
||||
given the default is to listen to localhost.
|
||||
The interfaces are not changed on a reload (kill \-HUP) but only on restart.
|
||||
A port number can be specified with @port (without spaces between
|
||||
interface and port number), if not specified the default port (from
|
||||
\fBport\fR) is used.
|
||||
.TP
|
||||
.B interface-automatic: \fI<yes or no>
|
||||
.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
|
||||
@@ -134,15 +140,16 @@ 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.
|
||||
A larger number of permitted outgoing ports increases resilience against
|
||||
spoofing attempts. Make sure these ports are not needed by other daemons.
|
||||
By default only ports above 1024 that have not been assigned by IANA are used.
|
||||
Give a port number or a range of the form "low-high", without spaces.
|
||||
Give a port number or a range of the form "low\-high", without spaces.
|
||||
.IP
|
||||
The \fBoutgoing\-port\-permit\fR and \fBoutgoing\-port\-avoid\fR statements
|
||||
are processed in the line order of the config file, adding the permitted ports
|
||||
@@ -155,7 +162,7 @@ Do not permit unbound to open this port or range of ports for use to send
|
||||
queries. Use this to make sure unbound does not grab a port that another
|
||||
daemon needs. The port is avoided on all outgoing interfaces, both IP4 and IP6.
|
||||
By default only ports above 1024 that have not been assigned by IANA are used.
|
||||
Give a port number or a range of the form "low-high", without spaces.
|
||||
Give a port number or a range of the form "low\-high", without spaces.
|
||||
.TP
|
||||
.B outgoing\-num\-tcp: \fI<number>
|
||||
Number of outgoing TCP buffers to allocate per thread. Default is 10. If set
|
||||
@@ -165,6 +172,17 @@ to 0, or if do_tcp is "no", no TCP queries to authoritative servers are done.
|
||||
Number of incoming TCP buffers to allocate per thread. Default is 10. If set
|
||||
to 0, or if do_tcp is "no", no TCP queries from clients are accepted.
|
||||
.TP
|
||||
.B edns\-buffer\-size: \fI<number>
|
||||
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.
|
||||
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
|
||||
of TCP fallback generated is excessive (probably also for this resolver,
|
||||
consider tuning the outgoing tcp number).
|
||||
.TP
|
||||
.B msg\-buffer\-size: \fI<number>
|
||||
Number of bytes size of the message buffers. Default is 65552 bytes, enough
|
||||
for 64 Kb packets, the maximum DNS message size. No message larger than this
|
||||
@@ -187,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
|
||||
@@ -196,6 +214,22 @@ 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
|
||||
space on UDP port 53 incoming queries. So that short spikes on busy
|
||||
servers do not drop packets (see counter in netstat \-su). Default is
|
||||
0 (use system value). Otherwise, the number of bytes to ask for, try
|
||||
"4m" on a 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.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 rrset\-cache\-size: \fI<number>
|
||||
Number of bytes size of the RRset cache. Default is 4 megabytes.
|
||||
@@ -430,9 +464,11 @@ 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.
|
||||
Use 0x20\-encoded random bits in the query to foil spoof attempts.
|
||||
This perturbs the lowercase and uppercase of query names sent to
|
||||
authority servers and checks if the reply still has the correct casing.
|
||||
Disabled by default.
|
||||
@@ -443,7 +479,7 @@ Give IPv4 of IPv6 addresses or classless subnets. These are addresses
|
||||
on your private network, and are not allowed to be returned for public
|
||||
internet names. Any occurence of such addresses are removed from
|
||||
DNS answers. Additionally, the DNSSEC validator may mark the answers
|
||||
bogus. This protects against so-called DNS Rebinding, where a user browser
|
||||
bogus. This protects against so\-called DNS Rebinding, where a user browser
|
||||
is turned into a network proxy, allowing remote access through the browser
|
||||
to other parts of your private network. Some names can be allowed to
|
||||
contain your private addresses, by default all the \fBlocal\-data\fR
|
||||
@@ -451,7 +487,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.
|
||||
@@ -478,6 +514,17 @@ If yes, localhost is added to the do\-not\-query\-address entries, both
|
||||
IP6 ::1 and IP4 127.0.0.1/8. If no, then localhost can be used to send
|
||||
queries to. Default is yes.
|
||||
.TP
|
||||
.B prefetch: \fI<yes or no>
|
||||
If yes, message cache elements are prefetched before they expire to
|
||||
keep the cache up to date. Default is no. Turning it on gives about
|
||||
10 percent more traffic and load on the machine, but popular items do
|
||||
not expire from the cache.
|
||||
.TP
|
||||
.B prefetch-key: \fI<yes or no>
|
||||
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 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.
|
||||
@@ -491,6 +538,13 @@ File with trusted keys for validation. Both DS and DNSKEY entries can appear
|
||||
in the file. The format of the file is the standard DNS Zone file format.
|
||||
Default is "", or no trust anchor file.
|
||||
.TP
|
||||
.B auto\-trust\-anchor\-file: \fI<filename>
|
||||
File with trust anchor for one zone, which is tracked with RFC5011 probes.
|
||||
The probes are several times per month, thus the machine must be online
|
||||
frequently. The initial file can be one with contents as described in
|
||||
\fBtrust\-anchor\-file\fR. The file is written to when the anchor is updated,
|
||||
so the unbound user must have write permission.
|
||||
.TP
|
||||
.B trust\-anchor: \fI<"Resource Record">
|
||||
A DS or DNSKEY RR for a key to use for validation. Multiple entries can be
|
||||
given to specify multiple trusted keys, in addition to the trust\-anchor\-files.
|
||||
@@ -538,17 +592,19 @@ you are debugging signature inception and expiration.
|
||||
.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;
|
||||
@@ -563,6 +619,15 @@ indeterminate or unchecked are not affected. Default is yes. Use this setting
|
||||
to protect the users that rely on this validator for authentication from
|
||||
protentially bad data in the additional section.
|
||||
.TP
|
||||
.B val\-log\-level: \fI<number>
|
||||
Have the validator print validation failures to the log. Regardless of
|
||||
the verbosity setting. Default is 0, off. At 1, for every user query
|
||||
that fails a line is printed to the logs. This way you can monitor what
|
||||
happens with validation. Use a diagnosis tool, such as dig or drill,
|
||||
to find out why validation is failing for these queries. At 2, not only
|
||||
the query that failed is printed but also the reason why unbound thought
|
||||
it was wrong and which server sent the faulty data.
|
||||
.TP
|
||||
.B val\-permissive\-mode: \fI<yes or no>
|
||||
Instruct the validator to mark bogus messages as indeterminate. The security
|
||||
checks are performed, but if the result is bogus (failed security), the
|
||||
@@ -580,6 +645,26 @@ be in ascending order and have at least one entry. If you set it to
|
||||
"1024 65535" there is no restriction to NSEC3 iteration values.
|
||||
This table must be kept short; a very long list could cause slower operation.
|
||||
.TP
|
||||
.B add\-holddown: \fI<seconds>
|
||||
Instruct the \fBauto\-trust\-anchor\-file\fR probe mechanism for RFC5011
|
||||
autotrust updates to add new trust anchors only after they have been
|
||||
visible for this time. Default is 30 days as per the RFC.
|
||||
.TP
|
||||
.B del\-holddown: \fI<seconds>
|
||||
Instruct the \fBauto\-trust\-anchor\-file\fR probe mechanism for RFC5011
|
||||
autotrust updates to remove revoked trust anchors after they have been
|
||||
kept in the revoked list for this long. Default is 30 days as per
|
||||
the RFC.
|
||||
.TP
|
||||
.B keep\-missing: \fI<seconds>
|
||||
Instruct the \fBauto\-trust\-anchor\-file\fR probe mechanism for RFC5011
|
||||
autotrust updates to remove missing trust anchors after they have been
|
||||
unseen for this long. This cleans up the state file if the target zone
|
||||
does not perform trust anchor revocation, so this makes the auto probe
|
||||
mechanism work with zones that perform regular (non\-5011) rollovers.
|
||||
The default is 366 days. The value 0 does not remove missing anchors,
|
||||
as per the RFC.
|
||||
.TP
|
||||
.B key\-cache\-size: \fI<number>
|
||||
Number of bytes size of the key cache. Default is 4 megabytes.
|
||||
A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes
|
||||
@@ -629,14 +714,16 @@ If no local\-zone is given local\-data causes a transparent zone
|
||||
to be created by default.
|
||||
.TP 10
|
||||
\h'5'\fIredirect\fR
|
||||
The query is answered from the local data for the zone name.
|
||||
The query is answered from the local data for the zone name.
|
||||
There may be no local data beneath the zone name.
|
||||
This answers queries for the zone, and all subdomains of the zone
|
||||
with the local data for the zone.
|
||||
It can be used to redirect a domain to a different address, with
|
||||
It can be used to redirect a domain to return a different address record
|
||||
to the end user, with
|
||||
local\-zone: "example.com." redirect and
|
||||
local\-data: "example.com. A 127.0.0.1"
|
||||
queries for www.example.com and www.foo.example.com are redirected.
|
||||
queries for www.example.com and www.foo.example.com are redirected, so
|
||||
that users with web browsers cannot access sites with suffix example.com.
|
||||
.TP 10
|
||||
\h'5'\fInodefault\fR
|
||||
Used to turn off default contents for AS112 zones. The other types
|
||||
@@ -699,7 +786,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
|
||||
@@ -718,8 +806,10 @@ Reverse data for zones 8.E.F.ip6.arpa to B.E.F.ip6.arpa.
|
||||
Reverse data for zone 8.B.D.0.1.0.0.2.ip6.arpa. This zone is used for
|
||||
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
|
||||
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
|
||||
@@ -748,7 +838,7 @@ enabled, the \fIunbound\-control\fR(8) utility can be used to send
|
||||
commands to the running unbound server. The server uses these clauses
|
||||
to setup SSLv3 / TLSv1 security for the connection. The
|
||||
\fIunbound\-control\fR(8) utility also reads the \fBremote\-control\fR
|
||||
section for options. To setup the correct self-signed certificates use the
|
||||
section for options. To setup the correct self\-signed certificates use the
|
||||
\fIunbound\-control\-setup\fR(8) utility.
|
||||
.TP 5
|
||||
.B control\-enable: \fI<yes or no>
|
||||
@@ -792,6 +882,8 @@ There may be multiple
|
||||
.B stub\-zone:
|
||||
clauses. Each with a name: and zero or more hostnames or IP addresses.
|
||||
For the stub zone this list of nameservers is used. Class IN is assumed.
|
||||
The servers should be authority servers, not recursors; unbound performs
|
||||
the recursive processing itself for stub zones.
|
||||
.P
|
||||
The stub zone can be used to configure authoritative data to be used
|
||||
by the resolver that cannot be accessed using the public internet servers.
|
||||
@@ -830,11 +922,16 @@ the resolver picks up a correct list online.
|
||||
.LP
|
||||
There may be multiple
|
||||
.B forward\-zone:
|
||||
clauses. Each with a name: and zero or more hostnames or IP addresses.
|
||||
For the forward zone this list of nameservers is used to forward the queries
|
||||
to. The servers have to handle further recursion for the query. Class IN is
|
||||
assumed. A forward\-zone entry with name "." and a forward\-addr target will
|
||||
forward all queries to that other server (unless it can answer from the cache).
|
||||
clauses. Each with a \fBname:\fR and zero or more hostnames or IP
|
||||
addresses. For the forward zone this list of nameservers is used to
|
||||
forward the queries to. The servers listed as \fBforward\-host:\fR and
|
||||
\fBforward\-addr:\fR have to handle further recursion for the query. Thus,
|
||||
those servers are not authority servers, but are (just like unbound is)
|
||||
recursive servers too; unbound does not perform recursion itself for the
|
||||
forward zone, it lets the remote server do it. Class IN is assumed.
|
||||
A forward\-zone entry with name "." and a forward\-addr target will
|
||||
forward all queries to that other server (unless it can answer from
|
||||
the cache).
|
||||
.TP
|
||||
.B name: \fI<domain name>
|
||||
Name of the forward zone.
|
||||
@@ -852,7 +949,7 @@ The
|
||||
clause gives the settings for the \fIpython\fR(1) script module. This module
|
||||
acts like the iterator and validator modules do, on queries and answers.
|
||||
To enable the script module it has to be compiled into the daemon,
|
||||
and the word "python" has to be put in the \fBmodule\-conf:\fR option
|
||||
and the word "python" has to be put in the \fBmodule\-config:\fR option
|
||||
(usually first, or between the validator and iterator).
|
||||
.TP
|
||||
.B python\-script: \fI<python file>\fR
|
||||
@@ -864,7 +961,7 @@ supported. Very large data and high TCP loads are exceptional for the DNS.
|
||||
DNSSEC validation is enabled, just add trust anchors.
|
||||
If you do not have to worry about programs using more than 3 Mb of memory,
|
||||
the below example is not for you. Use the defaults to receive full service,
|
||||
which on BSD-32bit tops out at 30-40 Mb after heavy usage.
|
||||
which on BSD\-32bit tops out at 30\-40 Mb after heavy usage.
|
||||
.P
|
||||
.nf
|
||||
# example settings that reduce memory usage
|
||||
@@ -872,7 +969,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
|
||||
|
||||
+929
-549
File diff suppressed because it is too large
Load Diff
+3
-2
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2006-12-25.00
|
||||
scriptversion=2009-04-28.21; # UTC
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
@@ -515,5 +515,6 @@ done
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
|
||||
+74
-36
@@ -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, 0))
|
||||
a->bogus, a->lame))
|
||||
return NULL;
|
||||
}
|
||||
return copy;
|
||||
@@ -93,7 +96,8 @@ delegpt_set_name(struct delegpt* dp, struct regional* region, uint8_t* name)
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -113,6 +117,9 @@ delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name)
|
||||
ns->resolved = 0;
|
||||
ns->got4 = 0;
|
||||
ns->got6 = 0;
|
||||
ns->lame = (uint8_t)lame;
|
||||
ns->done_pside4 = 0;
|
||||
ns->done_pside6 = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -147,32 +154,36 @@ 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 nodup)
|
||||
socklen_t addrlen, int bogus, int lame)
|
||||
{
|
||||
struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen);
|
||||
if(!ns) {
|
||||
/* ignore it */
|
||||
return 1;
|
||||
}
|
||||
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(dp, region, addr, addrlen, bogus, nodup);
|
||||
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(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 nodup)
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int bogus,
|
||||
int lame)
|
||||
{
|
||||
struct delegpt_addr* a;
|
||||
if(nodup) {
|
||||
if((a = delegpt_find_addr(dp, addr, addrlen))) {
|
||||
if(bogus)
|
||||
a->bogus = bogus;
|
||||
return 1;
|
||||
}
|
||||
/* 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,
|
||||
@@ -188,6 +199,7 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region,
|
||||
a->addrlen = addrlen;
|
||||
a->attempts = 0;
|
||||
a->bogus = bogus;
|
||||
a->lame = lame;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -239,21 +251,26 @@ 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) {
|
||||
if(a->bogus)
|
||||
log_addr(VERB_ALGO, " BOGUS ",
|
||||
&a->addr, a->addrlen);
|
||||
else log_addr(VERB_ALGO, " ", &a->addr, a->addrlen);
|
||||
const char* str = " ";
|
||||
if(a->bogus && a->lame) str = " BOGUS ADDR_LAME ";
|
||||
else if(a->bogus) str = " BOGUS ";
|
||||
else if(a->lame) str = " ADDR_LAME ";
|
||||
log_addr(VERB_ALGO, str, &a->addr, a->addrlen);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -270,6 +287,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)
|
||||
{
|
||||
@@ -318,9 +345,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 */
|
||||
@@ -344,7 +372,7 @@ 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;
|
||||
@@ -357,7 +385,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;
|
||||
@@ -365,7 +393,7 @@ 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 nodup)
|
||||
struct ub_packed_rrset_key* ak, int lame)
|
||||
{
|
||||
struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data;
|
||||
size_t i;
|
||||
@@ -380,7 +408,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), nodup))
|
||||
len, (d->security==sec_status_bogus), lame))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -388,7 +416,7 @@ 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 nodup)
|
||||
struct ub_packed_rrset_key* ak, int lame)
|
||||
{
|
||||
struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data;
|
||||
size_t i;
|
||||
@@ -403,7 +431,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), nodup))
|
||||
len, (d->security==sec_status_bogus), lame))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -411,16 +439,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);
|
||||
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);
|
||||
return delegpt_add_rrset_AAAA(dp, region, rrset, lame);
|
||||
log_warn("Unknown rrset type added to delegpt");
|
||||
return 1;
|
||||
}
|
||||
@@ -444,3 +472,13 @@ void delegpt_add_neg_msg(struct delegpt* dp, struct msgreply_entry* msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void delegpt_no_ipv6(struct delegpt* dp)
|
||||
{
|
||||
struct delegpt_ns* ns;
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
/* no ipv6, so only ipv4 is enough to resolve a nameserver */
|
||||
if(ns->got4)
|
||||
ns->resolved = 1;
|
||||
}
|
||||
}
|
||||
|
||||
+46
-14
@@ -74,6 +74,11 @@ 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;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -90,13 +95,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;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -121,6 +139,8 @@ struct delegpt_addr {
|
||||
/** if true, the A or AAAA RR was bogus, so this address is bad.
|
||||
* Also check the dp->bogus to see if everything is bogus. */
|
||||
int bogus;
|
||||
/** if true, this address is dispreferred: it is a lame IP address */
|
||||
int lame;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -153,20 +173,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.
|
||||
@@ -178,35 +200,34 @@ int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* regional,
|
||||
* @param addr: the address.
|
||||
* @param addrlen: the length of addr.
|
||||
* @param bogus: security status for the address, pass true if bogus.
|
||||
* @param nodup: if true, no address duplicates are made by this add.
|
||||
* name duplicates are always filtered.
|
||||
* @param lame: address is lame.
|
||||
* @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 nodup);
|
||||
socklen_t addrlen, int bogus, int lame);
|
||||
|
||||
/**
|
||||
* Add A RRset to delegpt.
|
||||
* @param dp: delegation point.
|
||||
* @param regional: where to allocate the info.
|
||||
* @param rrset: RRset A to add.
|
||||
* @param nodup: if true, no duplicates are made by this add. takes time.
|
||||
* @param lame: rrset is lame, disprefer it.
|
||||
* @return 0 on alloc error.
|
||||
*/
|
||||
int delegpt_add_rrset_A(struct delegpt* dp, struct regional* regional,
|
||||
struct ub_packed_rrset_key* rrset, int nodup);
|
||||
struct ub_packed_rrset_key* rrset, int lame);
|
||||
|
||||
/**
|
||||
* Add AAAA RRset to delegpt.
|
||||
* @param dp: delegation point.
|
||||
* @param regional: where to allocate the info.
|
||||
* @param rrset: RRset AAAA to add.
|
||||
* @param nodup: if true, no duplicates are made by this add. takes time.
|
||||
* @param lame: rrset is lame, disprefer it.
|
||||
* @return 0 on alloc error.
|
||||
*/
|
||||
int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* regional,
|
||||
struct ub_packed_rrset_key* rrset, int nodup);
|
||||
struct ub_packed_rrset_key* rrset, int lame);
|
||||
|
||||
/**
|
||||
* Add any RRset to delegpt.
|
||||
@@ -214,10 +235,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.
|
||||
@@ -226,11 +248,11 @@ int delegpt_add_rrset(struct delegpt* dp, struct regional* regional,
|
||||
* @param addr: the address.
|
||||
* @param addrlen: the length of addr.
|
||||
* @param bogus: if address is bogus.
|
||||
* @param nodup: if true, no duplicates are made by this add. takes time.
|
||||
* @param lame: if address is lame.
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_addr(struct delegpt* dp, struct regional* regional,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int nodup);
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int lame);
|
||||
|
||||
/**
|
||||
* Find NS record in name list of delegation point.
|
||||
@@ -279,6 +301,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
|
||||
*
|
||||
@@ -307,4 +332,11 @@ struct delegpt* delegpt_from_message(struct dns_msg* msg,
|
||||
*/
|
||||
void delegpt_add_neg_msg(struct delegpt* dp, struct msgreply_entry* msg);
|
||||
|
||||
/**
|
||||
* Register the fact that there is no ipv6 and thus AAAAs are not going
|
||||
* to be queried for or be useful.
|
||||
* @param dp: the delegation point. Updated to reflect no ipv6.
|
||||
*/
|
||||
void delegpt_no_ipv6(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.
|
||||
|
||||
+66
-3
@@ -40,6 +40,9 @@
|
||||
* 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"
|
||||
@@ -64,7 +67,7 @@ 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));
|
||||
@@ -187,7 +190,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(dp, fwd->region, ldns_rdf_data(rdf), 0)) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
@@ -212,7 +215,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, 1)) {
|
||||
if(!delegpt_add_addr(dp, fwd->region, &addr, addrlen, 0, 0)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
@@ -231,6 +234,9 @@ read_forwards(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
/* set flag that parent side NS information is included.
|
||||
* Asking a (higher up) server on the internet is not useful */
|
||||
dp->has_parent_side_NS = 1;
|
||||
if(!read_fwds_name(fwd, s, dp) ||
|
||||
!read_fwds_host(fwd, s, dp) ||
|
||||
!read_fwds_addr(fwd, s, dp))
|
||||
@@ -345,6 +351,63 @@ forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct delegpt*
|
||||
forwards_lookup_root(struct iter_forwards* fwd, uint16_t qclass)
|
||||
{
|
||||
uint8_t root = 0;
|
||||
return forwards_lookup(fwd, &root, qclass);
|
||||
}
|
||||
|
||||
int
|
||||
forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass)
|
||||
{
|
||||
struct iter_forward_zone key;
|
||||
rbnode_t* n;
|
||||
struct iter_forward_zone* p;
|
||||
if(*dclass == 0) {
|
||||
/* first root item is first item in tree */
|
||||
n = rbtree_first(fwd->tree);
|
||||
if(n == RBTREE_NULL)
|
||||
return 0;
|
||||
p = (struct iter_forward_zone*)n;
|
||||
if(dname_is_root(p->name)) {
|
||||
*dclass = p->dclass;
|
||||
return 1;
|
||||
}
|
||||
/* root not first item? search for higher items */
|
||||
*dclass = p->dclass + 1;
|
||||
return forwards_next_root(fwd, dclass);
|
||||
}
|
||||
/* find class n in tree, we may get a direct hit, or if we don't
|
||||
* this is the last item of the previous class so rbtree_next() takes
|
||||
* us to the next root (if any) */
|
||||
key.node.key = &key;
|
||||
key.name = (uint8_t*)"\000";
|
||||
key.namelen = 1;
|
||||
key.namelabs = 0;
|
||||
key.dclass = *dclass;
|
||||
n = NULL;
|
||||
if(rbtree_find_less_equal(fwd->tree, &key, &n)) {
|
||||
/* exact */
|
||||
return 1;
|
||||
} else {
|
||||
/* smaller element */
|
||||
if(!n || n == RBTREE_NULL)
|
||||
return 0; /* nothing found */
|
||||
n = rbtree_next(n);
|
||||
if(n == RBTREE_NULL)
|
||||
return 0; /* no higher */
|
||||
p = (struct iter_forward_zone*)n;
|
||||
if(dname_is_root(p->name)) {
|
||||
*dclass = p->dclass;
|
||||
return 1;
|
||||
}
|
||||
/* not a root node, return next higher item */
|
||||
*dclass = p->dclass+1;
|
||||
return forwards_next_root(fwd, dclass);
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
forwards_get_mem(struct iter_forwards* fwd)
|
||||
{
|
||||
|
||||
+19
-2
@@ -55,7 +55,7 @@ struct iter_forwards {
|
||||
struct regional* region;
|
||||
/**
|
||||
* Zones are stored in this tree. Sort order is specially chosen.
|
||||
* first sorted on qtype. Then on dname in nsec-like order, so that
|
||||
* first sorted on qclass. Then on dname in nsec-like order, so that
|
||||
* a lookup on class, name will return an exact match or the closest
|
||||
* match which gives the ancestor needed.
|
||||
* contents of type iter_forward_zone.
|
||||
@@ -89,7 +89,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.
|
||||
@@ -119,6 +119,23 @@ int forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg);
|
||||
struct delegpt* forwards_lookup(struct iter_forwards* fwd,
|
||||
uint8_t* qname, uint16_t qclass);
|
||||
|
||||
/**
|
||||
* Same as forwards_lookup, but for the root only
|
||||
* @param fwd: forward storage.
|
||||
* @param qclass: The qclass of the query.
|
||||
* @return: A delegation point if root forward exists, otherwise null.
|
||||
*/
|
||||
struct delegpt* forwards_lookup_root(struct iter_forwards* fwd,
|
||||
uint16_t qclass);
|
||||
|
||||
/**
|
||||
* Find next root item in forwards lookup tree.
|
||||
* @param fwd: the forward storage
|
||||
* @param qclass: class to look at next, or higher.
|
||||
* @return false if none found, or if true stored in qclass.
|
||||
*/
|
||||
int forwards_next_root(struct iter_forwards* fwd, uint16_t* qclass);
|
||||
|
||||
/**
|
||||
* Get memory in use by forward storage
|
||||
* @param fwd: forward storage.
|
||||
|
||||
+27
-9
@@ -40,6 +40,8 @@
|
||||
* 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"
|
||||
@@ -49,7 +51,7 @@
|
||||
#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));
|
||||
@@ -83,10 +85,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(dp, r, 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, 1)) {
|
||||
&addr, addrlen, 0, 0)) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
return 0;
|
||||
}
|
||||
@@ -105,11 +107,12 @@ 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);
|
||||
if(!dp)
|
||||
return NULL;
|
||||
dp->has_parent_side_NS = 1;
|
||||
if(!delegpt_set_name(dp, r, (uint8_t*)"\000"))
|
||||
return NULL;
|
||||
if(do_ip4) {
|
||||
@@ -131,6 +134,7 @@ compile_time_root_prime(struct regional* r, int do_ip4, int 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, "I.ROOT-SERVERS.NET.", "2001:7fe::53")) return 0;
|
||||
if(!ah(dp, r, "J.ROOT-SERVERS.NET.", "2001:503:c27::2:30")) return 0;
|
||||
if(!ah(dp, r, "K.ROOT-SERVERS.NET.", "2001:7fd::1")) return 0;
|
||||
if(!ah(dp, r, "L.ROOT-SERVERS.NET.", "2001:500:3::42")) return 0;
|
||||
@@ -200,7 +204,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(dp, hints->region, ldns_rdf_data(rdf), 0)) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
@@ -225,7 +229,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, 1)) {
|
||||
if(!delegpt_add_addr(dp, hints->region, &addr, addrlen, 0, 0)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
@@ -244,6 +248,7 @@ read_stubs(struct iter_hints* hints, struct config_file* cfg)
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
dp->has_parent_side_NS = 1;
|
||||
if(!read_stubs_name(hints, s, dp) ||
|
||||
!read_stubs_host(hints, s, dp) ||
|
||||
!read_stubs_addr(hints, s, dp))
|
||||
@@ -280,6 +285,7 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
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,7 +300,7 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
}
|
||||
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)))) {
|
||||
ldns_rdf_data(ldns_rr_rdf(rr, 0)), 0)) {
|
||||
log_err("out of memory reading root hints");
|
||||
goto stop_read;
|
||||
}
|
||||
@@ -318,7 +324,7 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
ldns_rdf_data(ldns_rr_owner(rr)),
|
||||
ldns_rdf_size(ldns_rr_owner(rr)),
|
||||
(struct sockaddr_storage*)&sa, len,
|
||||
0, 1)) {
|
||||
0, 0)) {
|
||||
log_err("out of memory reading root hints");
|
||||
goto stop_read;
|
||||
}
|
||||
@@ -334,7 +340,7 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
ldns_rdf_data(ldns_rr_owner(rr)),
|
||||
ldns_rdf_size(ldns_rr_owner(rr)),
|
||||
(struct sockaddr_storage*)&sa, len,
|
||||
0, 1)) {
|
||||
0, 0)) {
|
||||
log_err("out of memory reading root hints");
|
||||
goto stop_read;
|
||||
}
|
||||
@@ -445,6 +451,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.
|
||||
@@ -461,6 +474,11 @@ hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int hints_next_root(struct iter_hints* hints, uint16_t* qclass)
|
||||
{
|
||||
return name_tree_next_root(&hints->tree, qclass);
|
||||
}
|
||||
|
||||
size_t
|
||||
hints_get_mem(struct iter_hints* hints)
|
||||
{
|
||||
|
||||
+14
-2
@@ -56,7 +56,7 @@ struct iter_hints {
|
||||
struct regional* region;
|
||||
/**
|
||||
* Hints are stored in this tree. Sort order is specially chosen.
|
||||
* first sorted on qtype. Then on dname in nsec-like order, so that
|
||||
* first sorted on qclass. Then on dname in nsec-like order, so that
|
||||
* a lookup on class, name will return an exact match or the closest
|
||||
* match which gives the ancestor needed.
|
||||
* contents of type iter_hints_stub. The class IN root is in here.
|
||||
@@ -81,7 +81,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.
|
||||
@@ -105,6 +105,18 @@ int hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg);
|
||||
*/
|
||||
struct delegpt* hints_lookup_root(struct iter_hints* hints, uint16_t qclass);
|
||||
|
||||
/**
|
||||
* Find next root hints (to cycle through all root hints).
|
||||
* @param hints: hint storage
|
||||
* @param qclass: class for which root hints are sought.
|
||||
* 0 means give the first available root hints class.
|
||||
* x means, give class x or a higher class if any.
|
||||
* returns the found class in this variable.
|
||||
* @return true if a root hint class is found.
|
||||
* false if not root hint class is found (qclass may have been changed).
|
||||
*/
|
||||
int hints_next_root(struct iter_hints* hints, uint16_t* qclass);
|
||||
|
||||
/**
|
||||
* Given a qname/qclass combination, and the delegation point from the cache
|
||||
* for this qname/qclass, determine if this combination indicates that a
|
||||
|
||||
@@ -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"
|
||||
@@ -105,7 +106,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)
|
||||
@@ -129,7 +129,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 +141,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,
|
||||
@@ -226,14 +225,21 @@ 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
|
||||
* the same zone), then the server is 'lame'. */
|
||||
if(dname_subdomain_c(origzone, s->rk.dname)) {
|
||||
if(rdset) /* forward or reclame not LAME */
|
||||
return RESPONSE_TYPE_THROWAWAY;
|
||||
return RESPONSE_TYPE_LAME;
|
||||
}
|
||||
/* If the NS set is below the delegation point we
|
||||
|
||||
+44
-2
@@ -303,6 +303,15 @@ pkt_sub(ldns_buffer* pkt, uint8_t* comprname, uint8_t* zone)
|
||||
return dname_subdomain_c(buf, zone);
|
||||
}
|
||||
|
||||
/** check subdomain with decompression, compressed is parent */
|
||||
static int
|
||||
sub_of_pkt(ldns_buffer* pkt, uint8_t* zone, uint8_t* comprname)
|
||||
{
|
||||
uint8_t buf[LDNS_MAX_DOMAINLEN+1];
|
||||
dname_pkt_copy(pkt, buf, comprname);
|
||||
return dname_subdomain_c(zone, buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine normalizes a response. This includes removing "irrelevant"
|
||||
* records from the answer and additional sections and (re)synthesizing
|
||||
@@ -437,6 +446,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 {
|
||||
@@ -518,6 +533,18 @@ store_rrset(ldns_buffer* pkt, struct msg_parse* msg, struct module_env* env,
|
||||
env->alloc, now);
|
||||
}
|
||||
|
||||
/** Check if there are SOA records in the authority section (negative) */
|
||||
static int
|
||||
soa_in_auth(struct msg_parse* msg)
|
||||
{
|
||||
struct rrset_parse* rrset;
|
||||
for(rrset = msg->rrset_first; rrset; rrset = rrset->rrset_all_next)
|
||||
if(rrset->type == LDNS_RR_TYPE_SOA &&
|
||||
rrset->section == LDNS_SECTION_AUTHORITY)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if right hand name in NSEC is within zone
|
||||
* @param rrset: the NSEC rrset
|
||||
@@ -534,7 +561,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;
|
||||
}
|
||||
@@ -566,6 +593,8 @@ scrub_sanitize(ldns_buffer* pkt, struct msg_parse* msg,
|
||||
struct query_info* qinfo, uint8_t* zonename, struct module_env* env,
|
||||
struct iter_env* ie)
|
||||
{
|
||||
int del_addi = 0; /* if additional-holding rrsets are deleted, we
|
||||
do not trust the normalized additional-A-AAAA any more */
|
||||
struct rrset_parse* rrset, *prev;
|
||||
prev = NULL;
|
||||
rrset = msg->rrset_first;
|
||||
@@ -590,6 +619,7 @@ scrub_sanitize(ldns_buffer* pkt, struct msg_parse* msg,
|
||||
* Remainders of CNAME chains are cut off and resolved by iterator. */
|
||||
while(rrset && rrset->section == LDNS_SECTION_ANSWER) {
|
||||
if(dname_pkt_compare(pkt, qinfo->qname, rrset->dname) != 0) {
|
||||
if(has_additional(rrset->type)) del_addi = 1;
|
||||
remove_rrset("sanitize: removing extraneous answer "
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
@@ -633,10 +663,15 @@ scrub_sanitize(ldns_buffer* pkt, struct msg_parse* msg,
|
||||
rrset->type == LDNS_RR_TYPE_NS &&
|
||||
rrset->section == LDNS_SECTION_AUTHORITY &&
|
||||
FLAGS_GET_RCODE(msg->flags) ==
|
||||
LDNS_RCODE_NOERROR) {
|
||||
LDNS_RCODE_NOERROR && !soa_in_auth(msg) &&
|
||||
sub_of_pkt(pkt, zonename, rrset->dname)) {
|
||||
/* noerror, nodata and this NS rrset is above
|
||||
* the zone. This is LAME!
|
||||
* Leave in the NS for lame classification. */
|
||||
/* remove everything from the additional
|
||||
* (we dont want its glue that was approved
|
||||
* during the normalize action) */
|
||||
del_addi = 1;
|
||||
} else if(!env->cfg->harden_glue) {
|
||||
/* store in cache! Since it is relevant
|
||||
* (from normalize) it will be picked up
|
||||
@@ -646,11 +681,17 @@ scrub_sanitize(ldns_buffer* pkt, struct msg_parse* msg,
|
||||
"poison RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
} else {
|
||||
if(has_additional(rrset->type)) del_addi = 1;
|
||||
remove_rrset("sanitize: removing potential "
|
||||
"poison RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(del_addi && rrset->section == LDNS_SECTION_ADDITIONAL) {
|
||||
remove_rrset("sanitize: removing potential "
|
||||
"poison reference RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
/* check if right hand side of NSEC is within zone */
|
||||
if(rrset->type == LDNS_RR_TYPE_NSEC &&
|
||||
sanitize_nsec_is_overreach(rrset, zonename)) {
|
||||
@@ -676,6 +717,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;
|
||||
|
||||
+401
-44
@@ -60,6 +60,13 @@
|
||||
#include "util/random.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "validator/val_anchor.h"
|
||||
#include "validator/val_kcache.h"
|
||||
#include "validator/val_kentry.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*4)
|
||||
|
||||
/** fillup fetch policy array */
|
||||
static void
|
||||
@@ -151,13 +158,19 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
* values 0 .. 49 are not used, unless that is changed.
|
||||
* USEFUL_SERVER_TOP_TIMEOUT
|
||||
* This value exactly is given for unresponsive blacklisted.
|
||||
* USEFUL_SERVER_TOP_TIMEOUT ..
|
||||
* dnsseclame servers get penalty
|
||||
* USEFUL_SERVER_TOP_TIMEOUT+1
|
||||
* For non-blacklisted servers: huge timeout, but has traffic.
|
||||
* 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*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).
|
||||
@@ -174,6 +187,8 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
|
||||
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)) {
|
||||
@@ -184,22 +199,28 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
|
||||
name, namelen, qtype, &lame, &dnsseclame, &reclame,
|
||||
&rtt, now)) {
|
||||
log_addr(VERB_ALGO, "servselect", &a->addr, a->addrlen);
|
||||
verbose(VERB_ALGO, " rtt=%d%s%s%s", rtt,
|
||||
verbose(VERB_ALGO, " rtt=%d%s%s%s%s", rtt,
|
||||
lame?" LAME":"",
|
||||
dnsseclame?" DNSSEC_LAME":"",
|
||||
reclame?" REC_LAME":"");
|
||||
reclame?" REC_LAME":"",
|
||||
a->lame?" ADDR_LAME":"");
|
||||
if(lame)
|
||||
return -1; /* server is lame */
|
||||
else if(rtt >= USEFUL_SERVER_TOP_TIMEOUT)
|
||||
/* server is unresponsive */
|
||||
return USEFUL_SERVER_TOP_TIMEOUT;
|
||||
/* server is unresponsive */
|
||||
return USEFUL_SERVER_TOP_TIMEOUT;
|
||||
/* select remainder from worst to best */
|
||||
else if(reclame)
|
||||
return rtt+USEFUL_SERVER_TOP_TIMEOUT*2; /* nonpref */
|
||||
return rtt+USEFUL_SERVER_TOP_TIMEOUT*3; /* nonpref */
|
||||
else if(dnsseclame )
|
||||
return rtt+USEFUL_SERVER_TOP_TIMEOUT; /* nonpref */
|
||||
return rtt+USEFUL_SERVER_TOP_TIMEOUT*2; /* nonpref */
|
||||
else if(a->lame)
|
||||
return rtt+USEFUL_SERVER_TOP_TIMEOUT+1; /* nonpref */
|
||||
else return rtt;
|
||||
}
|
||||
/* no server information present */
|
||||
if(a->lame)
|
||||
return USEFUL_SERVER_TOP_TIMEOUT+1+UNKNOWN_SERVER_NICENESS; /* nonpref */
|
||||
return UNKNOWN_SERVER_NICENESS;
|
||||
}
|
||||
|
||||
@@ -207,7 +228,7 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
|
||||
static int
|
||||
iter_fill_rtt(struct iter_env* iter_env, struct module_env* env,
|
||||
uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now,
|
||||
struct delegpt* dp, int* best_rtt)
|
||||
struct delegpt* dp, int* best_rtt, struct sock_list* blacklist)
|
||||
{
|
||||
int got_it = 0;
|
||||
struct delegpt_addr* a;
|
||||
@@ -217,6 +238,9 @@ iter_fill_rtt(struct iter_env* iter_env, struct module_env* env,
|
||||
a->sel_rtt = iter_filter_unsuitable(iter_env, env,
|
||||
name, namelen, qtype, now, a);
|
||||
if(a->sel_rtt != -1) {
|
||||
if(sock_list_find(blacklist, &a->addr, a->addrlen))
|
||||
a->sel_rtt += BLACKLIST_PENALTY;
|
||||
|
||||
if(!got_it) {
|
||||
*best_rtt = a->sel_rtt;
|
||||
got_it = 1;
|
||||
@@ -233,20 +257,23 @@ iter_fill_rtt(struct iter_env* iter_env, struct module_env* env,
|
||||
static int
|
||||
iter_filter_order(struct iter_env* iter_env, struct module_env* env,
|
||||
uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now,
|
||||
struct delegpt* dp, int* selected_rtt)
|
||||
struct delegpt* dp, int* selected_rtt, int open_target,
|
||||
struct sock_list* blacklist)
|
||||
{
|
||||
int got_num = 0, low_rtt = 0, swap_to_front;
|
||||
struct delegpt_addr* a, *n, *prev=NULL;
|
||||
|
||||
/* fillup sel_rtt and find best rtt in the bunch */
|
||||
got_num = iter_fill_rtt(iter_env, env, name, namelen, qtype, now, dp,
|
||||
&low_rtt);
|
||||
&low_rtt, blacklist);
|
||||
if(got_num == 0)
|
||||
return 0;
|
||||
if(low_rtt >= USEFUL_SERVER_TOP_TIMEOUT &&
|
||||
delegpt_count_missing_targets(dp) > 0)
|
||||
(delegpt_count_missing_targets(dp) > 0 || open_target > 0)) {
|
||||
verbose(VERB_ALGO, "Bad choices, trying to get more choice");
|
||||
return 0; /* we want more choice. The best choice is a bad one.
|
||||
return 0 to force the caller to fetch more */
|
||||
}
|
||||
|
||||
got_num = 0;
|
||||
a = dp->result_list;
|
||||
@@ -285,32 +312,40 @@ 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,
|
||||
int* chase_to_rd)
|
||||
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;
|
||||
int selrtt;
|
||||
struct delegpt_addr* a, *prev;
|
||||
int num = iter_filter_order(iter_env, env, name, namelen, qtype,
|
||||
*env->now, dp, &selrtt);
|
||||
*env->now, dp, &selrtt, open_target, blacklist);
|
||||
|
||||
if(num == 0)
|
||||
return NULL;
|
||||
verbose(VERB_ALGO, "selrtt %d", selrtt);
|
||||
if(selrtt > USEFUL_SERVER_TOP_TIMEOUT*2) {
|
||||
verbose(VERB_ALGO, "chase to recursion lame server");
|
||||
*chase_to_rd = 1;
|
||||
}
|
||||
if(selrtt > USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
verbose(VERB_ALGO, "chase to dnssec lame server");
|
||||
*dnssec_expected = 0;
|
||||
}
|
||||
if(selrtt == USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
verbose(VERB_ALGO, "chase to blacklisted lame server");
|
||||
/* the best choice is a blacklisted, unresponsive server,
|
||||
* we need to throttle down our traffic towards it */
|
||||
if(ub_random(env->rnd) % 100 != 1) {
|
||||
/* 99% of the time, drop query */
|
||||
if(selrtt > BLACKLIST_PENALTY) {
|
||||
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*3) {
|
||||
verbose(VERB_ALGO, "chase to recursion lame server");
|
||||
*chase_to_rd = 1;
|
||||
}
|
||||
if(selrtt > USEFUL_SERVER_TOP_TIMEOUT*2) {
|
||||
verbose(VERB_ALGO, "chase to dnssec lame server");
|
||||
*dnssec_lame = 1;
|
||||
}
|
||||
if(selrtt == USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
verbose(VERB_ALGO, "chase to blacklisted lame server");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -325,9 +360,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) {
|
||||
@@ -380,9 +415,9 @@ dns_copy_msg(struct dns_msg* from, struct regional* region)
|
||||
|
||||
int
|
||||
iter_dns_store(struct module_env* env, struct query_info* msgqinf,
|
||||
struct reply_info* msgrep, int is_referral)
|
||||
struct reply_info* msgrep, int is_referral, uint32_t leeway)
|
||||
{
|
||||
return dns_cache_store(env, msgqinf, msgrep, is_referral);
|
||||
return dns_cache_store(env, msgqinf, msgrep, is_referral, leeway);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -393,7 +428,7 @@ 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);
|
||||
}
|
||||
|
||||
@@ -435,25 +470,50 @@ 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 on.
|
||||
* o no addresses are provided.
|
||||
* o all NS items are required glue.
|
||||
* o no addresses are provided.
|
||||
* o RD qflag is on.
|
||||
* OR
|
||||
* o no addresses are provided.
|
||||
* 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.
|
||||
*/
|
||||
if(!(qflags&BIT_RD))
|
||||
return 0;
|
||||
/* either available or unused targets */
|
||||
if(dp->usable_list || dp->result_list)
|
||||
if(dp->usable_list || dp->result_list)
|
||||
return 0;
|
||||
|
||||
/* see if query is for one of the nameservers, which is glue */
|
||||
@@ -476,18 +536,38 @@ int
|
||||
iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
|
||||
struct dns_msg* msg, uint16_t dclass)
|
||||
{
|
||||
struct trust_anchor* a;
|
||||
/* information not available, !env->anchors can be common */
|
||||
if(!env || !env->anchors || !dp || !dp->name)
|
||||
return 0;
|
||||
/* a trust anchor exists with this name, RRSIGs expected */
|
||||
if(anchor_find(env->anchors, dp->name, dp->namelabs, dp->namelen,
|
||||
dclass))
|
||||
if((a=anchor_find(env->anchors, dp->name, dp->namelabs, dp->namelen,
|
||||
dclass))) {
|
||||
lock_basic_unlock(&a->lock);
|
||||
return 1;
|
||||
}
|
||||
/* see if DS rrset was given, in AUTH section */
|
||||
if(msg && msg->rep &&
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -546,6 +626,11 @@ int iter_msg_from_zone(struct dns_msg* msg, struct delegpt* dp,
|
||||
reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen,
|
||||
LDNS_RR_TYPE_NS, dclass))
|
||||
return 1;
|
||||
/* a DNSKEY set is expected at the zone apex as well */
|
||||
/* this is for 'minimal responses' for DNSKEYs */
|
||||
if(reply_find_rrset_section_an(msg->rep, dp->name, dp->namelen,
|
||||
LDNS_RR_TYPE_DNSKEY, dclass))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -587,12 +672,13 @@ 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 ||
|
||||
p->qdcount != q->qdcount ||
|
||||
p->ttl != q->ttl ||
|
||||
p->prefetch_ttl != q->prefetch_ttl ||
|
||||
p->security != q->security ||
|
||||
p->an_numrrsets != q->an_numrrsets ||
|
||||
p->ns_numrrsets != q->ns_numrrsets ||
|
||||
@@ -600,8 +686,279 @@ 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_parentside_rrset(struct module_env* env,
|
||||
struct ub_packed_rrset_key* rrset)
|
||||
{
|
||||
struct rrset_ref ref;
|
||||
rrset = packed_rrset_copy_alloc(rrset, env->alloc, *env->now);
|
||||
if(!rrset) {
|
||||
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: 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_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, dp->name,
|
||||
dp->namelen, LDNS_RR_TYPE_NS, qinfo->qclass,
|
||||
PACKED_RRSET_PARENT_SIDE, *env->now, 0);
|
||||
if(akey) {
|
||||
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)
|
||||
{
|
||||
uint16_t c1 = *c, c2 = *c;
|
||||
int r1 = hints_next_root(hints, &c1);
|
||||
int r2 = forwards_next_root(fwd, &c2);
|
||||
if(!r1 && !r2) /* got none, end of list */
|
||||
return 0;
|
||||
else if(!r1) /* got one, return that */
|
||||
*c = c2;
|
||||
else if(!r2)
|
||||
*c = c1;
|
||||
else if(c1 < c2) /* got both take smallest */
|
||||
*c = c1;
|
||||
else *c = c2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
iter_scrub_ds(struct dns_msg* msg, struct ub_packed_rrset_key* ns, uint8_t* z)
|
||||
{
|
||||
/* Only the DS record for the delegation itself is expected.
|
||||
* We allow DS for everything between the bailiwick and the
|
||||
* zonecut, thus DS records must be at or above the zonecut.
|
||||
* And the DS records must be below the server authority zone.
|
||||
* The answer section is already scrubbed. */
|
||||
size_t i = msg->rep->an_numrrsets;
|
||||
while(i < (msg->rep->an_numrrsets + msg->rep->ns_numrrsets)) {
|
||||
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_DS &&
|
||||
(!ns || !dname_subdomain_c(ns->rk.dname, s->rk.dname)
|
||||
|| query_dname_compare(z, s->rk.dname) == 0)) {
|
||||
log_nametypeclass(VERB_ALGO, "removing irrelevant DS",
|
||||
s->rk.dname, ntohs(s->rk.type),
|
||||
ntohs(s->rk.rrset_class));
|
||||
memmove(msg->rep->rrsets+i, msg->rep->rrsets+i+1,
|
||||
sizeof(struct ub_packed_rrset_key*) *
|
||||
(msg->rep->rrset_count-i-1));
|
||||
msg->rep->ns_numrrsets--;
|
||||
msg->rep->rrset_count--;
|
||||
/* stay at same i, but new record */
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
+119
-5
@@ -43,7 +43,10 @@
|
||||
#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;
|
||||
struct config_file;
|
||||
struct module_env;
|
||||
struct delegpt_addr;
|
||||
@@ -54,6 +57,8 @@ struct ub_randstate;
|
||||
struct query_info;
|
||||
struct reply_info;
|
||||
struct module_qstate;
|
||||
struct sock_list;
|
||||
struct ub_packed_rrset_key;
|
||||
|
||||
/**
|
||||
* Process config options and set iterator module state.
|
||||
@@ -75,17 +80,20 @@ 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.
|
||||
* @param open_target: number of currently outstanding target queries.
|
||||
* If we wait for these, perhaps more server addresses become available.
|
||||
* @param blacklist: the IP blacklist to use.
|
||||
* @return best target or NULL if no target.
|
||||
* if not null, that target is removed from the result list in the dp.
|
||||
*/
|
||||
struct delegpt_addr* iter_server_selection(struct iter_env* iter_env,
|
||||
struct module_env* env, struct delegpt* dp, uint8_t* name,
|
||||
size_t namelen, uint16_t qtype, int* dnssec_expected,
|
||||
int* chase_to_rd);
|
||||
size_t namelen, uint16_t qtype, int* dnssec_lame,
|
||||
int* chase_to_rd, int open_target, struct sock_list* blacklist);
|
||||
|
||||
/**
|
||||
* Allocate dns_msg from parsed msg, in regional.
|
||||
@@ -112,10 +120,11 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);
|
||||
* @param rep: reply in dns_msg from dns_alloc_msg for example.
|
||||
* @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).
|
||||
*/
|
||||
int iter_dns_store(struct module_env* env, struct query_info* qinf,
|
||||
struct reply_info* rep, int is_referral);
|
||||
struct reply_info* rep, int is_referral, uint32_t leeway);
|
||||
|
||||
/**
|
||||
* Select randomly with n/m probability.
|
||||
@@ -135,12 +144,22 @@ int iter_ns_probability(struct ub_randstate* rnd, int n, int m);
|
||||
*/
|
||||
void iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void iter_mark_pside_cycle_targets(struct module_qstate* qstate,
|
||||
struct delegpt* dp);
|
||||
|
||||
/**
|
||||
* See if delegation is useful or offers immediately no targets for
|
||||
* further recursion.
|
||||
* @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);
|
||||
@@ -189,8 +208,103 @@ 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 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 rrset: the rrset to store (copied).
|
||||
* Failure to store is logged, but otherwise ignored.
|
||||
*/
|
||||
void iter_store_parentside_rrset(struct module_env* env,
|
||||
struct ub_packed_rrset_key* rrset);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
* @param hints: the hints.
|
||||
* @param fwd: the forwards.
|
||||
* @param c: the class to start searching at. 0 means find first one.
|
||||
* @return false if no classes found, true if found and returned in c.
|
||||
*/
|
||||
int iter_get_next_root(struct iter_hints* hints, struct iter_forwards* fwd,
|
||||
uint16_t* c);
|
||||
|
||||
/**
|
||||
* Remove DS records that are inappropriate before they are cached.
|
||||
* @param msg: the response to scrub.
|
||||
* @param ns: RRSET that is the NS record for the referral.
|
||||
* if NULL, then all DS records are removed from the authority section.
|
||||
* @param z: zone name that the response is from.
|
||||
*/
|
||||
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);
|
||||
|
||||
#endif /* ITERATOR_ITER_UTILS_H */
|
||||
|
||||
+617
-89
File diff suppressed because it is too large
Load Diff
+38
-2
@@ -55,7 +55,7 @@ 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
|
||||
/** how nice is a server without further information, in msec
|
||||
* Equals rtt initial timeout value.
|
||||
*/
|
||||
@@ -65,12 +65,18 @@ struct iter_priv;
|
||||
* Equals RTT_MAX_TIMEOUT
|
||||
*/
|
||||
#define USEFUL_SERVER_TOP_TIMEOUT 120000
|
||||
/** Number of lost messages in a row that get a host blacklisted.
|
||||
* With 16, a couple different queries have to time out and no working
|
||||
* queries are happening */
|
||||
#define USEFUL_SERVER_MAX_LOST 16
|
||||
/** number of retries on outgoing queries */
|
||||
#define OUTBOUND_MSG_RETRY 5
|
||||
/** RTT band, within this amount from the best, servers are chosen randomly.
|
||||
* 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.
|
||||
@@ -146,6 +152,10 @@ enum iter_state {
|
||||
/** Responses to priming queries finish at this state. */
|
||||
PRIME_RESP_STATE,
|
||||
|
||||
/** Collecting query class information, for qclass=ANY, when
|
||||
* it spawns off queries for every class, it returns here. */
|
||||
COLLECT_CLASS_STATE,
|
||||
|
||||
/** Responses that are to be returned upstream end at this state.
|
||||
* As well as responses to target queries. */
|
||||
FINISHED_STATE
|
||||
@@ -239,6 +249,26 @@ struct iter_qstate {
|
||||
/** the number of times this query as followed a referral. */
|
||||
int referral_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;
|
||||
|
||||
/**
|
||||
* expected dnssec information for this iteration step.
|
||||
* If dnssec rrsigs are expected and not given, the server is marked
|
||||
@@ -246,6 +276,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.
|
||||
@@ -280,7 +316,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.
+28
-6
@@ -288,20 +288,27 @@ context_serialize_answer(struct ctx_query* q, int err, ldns_buffer* pkt,
|
||||
* o uint32 id
|
||||
* o uint32 error_code
|
||||
* o uint32 msg_security
|
||||
* o uint32 length of why_bogus string (+1 for eos); 0 absent.
|
||||
* o why_bogus_string
|
||||
* o the remainder is the answer msg from resolver lookup.
|
||||
* remainder can be length 0.
|
||||
*/
|
||||
size_t pkt_len = pkt?ldns_buffer_remaining(pkt):0;
|
||||
size_t wlen = (pkt&&q->res->why_bogus)?strlen(q->res->why_bogus)+1:0;
|
||||
uint8_t* p;
|
||||
*len = sizeof(uint32_t)*4 + pkt_len;
|
||||
*len = sizeof(uint32_t)*5 + pkt_len + wlen;
|
||||
p = (uint8_t*)malloc(*len);
|
||||
if(!p) return NULL;
|
||||
ldns_write_uint32(p, UB_LIBCMD_ANSWER);
|
||||
ldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum);
|
||||
ldns_write_uint32(p+2*sizeof(uint32_t), (uint32_t)err);
|
||||
ldns_write_uint32(p+3*sizeof(uint32_t), (uint32_t)q->msg_security);
|
||||
ldns_write_uint32(p+4*sizeof(uint32_t), (uint32_t)wlen);
|
||||
if(wlen > 0)
|
||||
memmove(p+5*sizeof(uint32_t), q->res->why_bogus, wlen);
|
||||
if(pkt_len > 0)
|
||||
memmove(p+4*sizeof(uint32_t), ldns_buffer_begin(pkt), pkt_len);
|
||||
memmove(p+5*sizeof(uint32_t)+wlen,
|
||||
ldns_buffer_begin(pkt), pkt_len);
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -311,16 +318,31 @@ context_deserialize_answer(struct ub_ctx* ctx,
|
||||
{
|
||||
struct ctx_query* q = NULL ;
|
||||
int id;
|
||||
if(len < 4*sizeof(uint32_t)) return NULL;
|
||||
size_t wlen;
|
||||
if(len < 5*sizeof(uint32_t)) return NULL;
|
||||
log_assert( ldns_read_uint32(p) == UB_LIBCMD_ANSWER);
|
||||
id = (int)ldns_read_uint32(p+sizeof(uint32_t));
|
||||
q = (struct ctx_query*)rbtree_search(&ctx->queries, &id);
|
||||
if(!q) return NULL;
|
||||
*err = (int)ldns_read_uint32(p+2*sizeof(uint32_t));
|
||||
q->msg_security = ldns_read_uint32(p+3*sizeof(uint32_t));
|
||||
if(len > 4*sizeof(uint32_t)) {
|
||||
q->msg_len = len - 4*sizeof(uint32_t);
|
||||
q->msg = (uint8_t*)memdup(p+4*sizeof(uint32_t), q->msg_len);
|
||||
wlen = (size_t)ldns_read_uint32(p+4*sizeof(uint32_t));
|
||||
if(len > 5*sizeof(uint32_t) && wlen > 0) {
|
||||
if(len >= 5*sizeof(uint32_t)+wlen)
|
||||
q->res->why_bogus = (char*)memdup(
|
||||
p+5*sizeof(uint32_t), wlen);
|
||||
if(!q->res->why_bogus) {
|
||||
/* pass malloc failure to the user callback */
|
||||
q->msg_len = 0;
|
||||
*err = UB_NOMEM;
|
||||
return q;
|
||||
}
|
||||
q->res->why_bogus[wlen-1] = 0; /* zero terminated for sure */
|
||||
}
|
||||
if(len > 5*sizeof(uint32_t)+wlen) {
|
||||
q->msg_len = len - 5*sizeof(uint32_t) - wlen;
|
||||
q->msg = (uint8_t*)memdup(p+5*sizeof(uint32_t)+wlen,
|
||||
q->msg_len);
|
||||
if(!q->msg) {
|
||||
/* pass malloc failure to the user callback */
|
||||
q->msg_len = 0;
|
||||
|
||||
+88
-3
@@ -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"
|
||||
@@ -60,8 +61,13 @@
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/cache/rrset.h"
|
||||
|
||||
#if defined(UB_ON_WINDOWS) && defined (HAVE_WINDOWS_H)
|
||||
#include <windows.h>
|
||||
#include <iphlpapi.h>
|
||||
#endif /* UB_ON_WINDOWS */
|
||||
|
||||
struct ub_ctx*
|
||||
ub_ctx_create()
|
||||
ub_ctx_create(void)
|
||||
{
|
||||
struct ub_ctx* ctx;
|
||||
unsigned int seed;
|
||||
@@ -238,6 +244,19 @@ ub_ctx_set_option(struct ub_ctx* ctx, char* opt, char* val)
|
||||
return UB_NOERROR;
|
||||
}
|
||||
|
||||
int
|
||||
ub_ctx_get_option(struct ub_ctx* ctx, char* opt, char** str)
|
||||
{
|
||||
int r;
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
r = config_get_option_collate(ctx->env->cfg, opt, str);
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
if(r == 0) r = UB_NOERROR;
|
||||
else if(r == 1) r = UB_SYNTAX;
|
||||
else if(r == 2) r = UB_NOMEM;
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
ub_ctx_config(struct ub_ctx* ctx, char* fname)
|
||||
{
|
||||
@@ -262,6 +281,7 @@ ub_ctx_add_ta(struct ub_ctx* ctx, char* ta)
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
if(ctx->finalized) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
free(dup);
|
||||
return UB_AFTERFINAL;
|
||||
}
|
||||
if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_list, dup)) {
|
||||
@@ -281,6 +301,7 @@ ub_ctx_add_ta_file(struct ub_ctx* ctx, char* fname)
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
if(ctx->finalized) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
free(dup);
|
||||
return UB_AFTERFINAL;
|
||||
}
|
||||
if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_file_list, dup)) {
|
||||
@@ -300,6 +321,7 @@ ub_ctx_trustedkeys(struct ub_ctx* ctx, char* fname)
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
if(ctx->finalized) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
free(dup);
|
||||
return UB_AFTERFINAL;
|
||||
}
|
||||
if(!cfg_strlist_insert(&ctx->env->cfg->trusted_keys_file_list, dup)) {
|
||||
@@ -686,6 +708,7 @@ ub_resolve_free(struct ub_result* result)
|
||||
free(result->data);
|
||||
free(result->len);
|
||||
free(result->answer_packet);
|
||||
free(result->why_bogus);
|
||||
free(result);
|
||||
}
|
||||
|
||||
@@ -788,8 +811,47 @@ ub_ctx_resolvconf(struct ub_ctx* ctx, char* fname)
|
||||
char buf[1024];
|
||||
char* parse, *addr;
|
||||
int r;
|
||||
if(fname == NULL)
|
||||
|
||||
if(fname == NULL) {
|
||||
#if !defined(UB_ON_WINDOWS) || !defined(HAVE_WINDOWS_H)
|
||||
fname = "/etc/resolv.conf";
|
||||
#else
|
||||
FIXED_INFO *info;
|
||||
ULONG buflen = sizeof(*info);
|
||||
IP_ADDR_STRING *ptr;
|
||||
|
||||
info = (FIXED_INFO *) malloc(sizeof (FIXED_INFO));
|
||||
if (info == NULL)
|
||||
return UB_READFILE;
|
||||
|
||||
if (GetNetworkParams(info, &buflen) == ERROR_BUFFER_OVERFLOW) {
|
||||
free(info);
|
||||
info = (FIXED_INFO *) malloc(buflen);
|
||||
if (info == NULL)
|
||||
return UB_READFILE;
|
||||
}
|
||||
|
||||
if (GetNetworkParams(info, &buflen) == NO_ERROR) {
|
||||
int retval=0;
|
||||
ptr = &(info->DnsServerList);
|
||||
while (ptr) {
|
||||
numserv++;
|
||||
if((retval=ub_ctx_set_fwd(ctx,
|
||||
ptr->IpAddress.String)!=0)) {
|
||||
free(info);
|
||||
return retval;
|
||||
}
|
||||
ptr = ptr->Next;
|
||||
}
|
||||
free(info);
|
||||
if (numserv==0)
|
||||
return UB_READFILE;
|
||||
return UB_NOERROR;
|
||||
}
|
||||
free(info);
|
||||
return UB_READFILE;
|
||||
#endif /* WINDOWS */
|
||||
}
|
||||
in = fopen(fname, "r");
|
||||
if(!in) {
|
||||
/* error in errno! perror(fname) */
|
||||
@@ -840,8 +902,31 @@ ub_ctx_hosts(struct ub_ctx* ctx, char* fname)
|
||||
return UB_AFTERFINAL;
|
||||
}
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
if(fname == NULL)
|
||||
if(fname == NULL) {
|
||||
#if defined(UB_ON_WINDOWS) && defined(HAVE_WINDOWS_H)
|
||||
/*
|
||||
* If this is Windows NT/XP/2K it's in
|
||||
* %WINDIR%\system32\drivers\etc\hosts.
|
||||
* If this is Windows 95/98/Me it's in %WINDIR%\hosts.
|
||||
*/
|
||||
name = getenv("WINDIR");
|
||||
if (name != NULL) {
|
||||
int retval=0;
|
||||
snprintf(buf, sizeof(buf), "%s%s", name,
|
||||
"\\system32\\drivers\\etc\\hosts");
|
||||
if((retval=ub_ctx_hosts(ctx, buf)) !=0 ) {
|
||||
snprintf(buf, sizeof(buf), "%s%s", name,
|
||||
"\\hosts");
|
||||
retval=ub_ctx_hosts(ctx, buf);
|
||||
}
|
||||
free(name);
|
||||
return retval;
|
||||
}
|
||||
return UB_READFILE;
|
||||
#else
|
||||
fname = "/etc/hosts";
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
in = fopen(fname, "r");
|
||||
if(!in) {
|
||||
/* error in errno! perror(fname) */
|
||||
|
||||
+53
-38
@@ -42,6 +42,8 @@
|
||||
* returns from the procedure when done.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <ldns/dname.h>
|
||||
#include <ldns/wire2host.h>
|
||||
#include "libunbound/libworker.h"
|
||||
#include "libunbound/context.h"
|
||||
#include "libunbound/unbound.h"
|
||||
@@ -130,6 +132,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg)
|
||||
return NULL;
|
||||
}
|
||||
w->env->worker = (struct worker*)w;
|
||||
w->env->probe_timer = NULL;
|
||||
seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^
|
||||
(((unsigned int)w->thread_num)<<17);
|
||||
seed ^= (unsigned int)w->env->alloc->next_id;
|
||||
@@ -168,7 +171,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);
|
||||
&libworker_alloc_cleanup, w, cfg->do_udp);
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
}
|
||||
@@ -182,7 +185,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;
|
||||
@@ -437,8 +439,10 @@ libworker_enter_result(struct ub_result* res, ldns_buffer* buf,
|
||||
/** fillup fg results */
|
||||
static void
|
||||
libworker_fillup_fg(struct ctx_query* q, int rcode, ldns_buffer* buf,
|
||||
enum sec_status s)
|
||||
enum sec_status s, char* why_bogus)
|
||||
{
|
||||
if(why_bogus)
|
||||
q->res->why_bogus = strdup(why_bogus);
|
||||
if(rcode != 0) {
|
||||
q->res->rcode = rcode;
|
||||
q->msg_security = s;
|
||||
@@ -459,13 +463,14 @@ libworker_fillup_fg(struct ctx_query* q, int rcode, ldns_buffer* buf,
|
||||
}
|
||||
|
||||
void
|
||||
libworker_fg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s)
|
||||
libworker_fg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s,
|
||||
char* why_bogus)
|
||||
{
|
||||
struct ctx_query* q = (struct ctx_query*)arg;
|
||||
/* fg query is done; exit comm base */
|
||||
comm_base_exit(q->w->base);
|
||||
|
||||
libworker_fillup_fg(q, rcode, buf, s);
|
||||
libworker_fillup_fg(q, rcode, buf, s, why_bogus);
|
||||
}
|
||||
|
||||
/** setup qinfo and edns */
|
||||
@@ -480,8 +485,15 @@ setup_qinfo_edns(struct libworker* w, struct ctx_query* q,
|
||||
if(!rdf) {
|
||||
return 0;
|
||||
}
|
||||
#ifdef UNBOUND_ALLOC_LITE
|
||||
qinfo->qname = memdup(ldns_rdf_data(rdf), ldns_rdf_size(rdf));
|
||||
qinfo->qname_len = ldns_rdf_size(rdf);
|
||||
ldns_rdf_deep_free(rdf);
|
||||
rdf = 0;
|
||||
#else
|
||||
qinfo->qname = ldns_rdf_data(rdf);
|
||||
qinfo->qname_len = ldns_rdf_size(rdf);
|
||||
#endif
|
||||
edns->edns_present = 1;
|
||||
edns->ext_rcode = 0;
|
||||
edns->edns_version = 0;
|
||||
@@ -514,8 +526,9 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
|
||||
ldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags);
|
||||
if(local_zones_answer(ctx->local_zones, &qinfo, &edns,
|
||||
w->back->udp_buff, w->env->scratch)) {
|
||||
regional_free_all(w->env->scratch);
|
||||
libworker_fillup_fg(q, LDNS_RCODE_NOERROR,
|
||||
w->back->udp_buff, sec_status_insecure);
|
||||
w->back->udp_buff, sec_status_insecure, NULL);
|
||||
libworker_delete(w);
|
||||
free(qinfo.qname);
|
||||
return UB_NOERROR;
|
||||
@@ -538,7 +551,7 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
|
||||
/** add result to the bg worker result queue */
|
||||
static void
|
||||
add_bg_result(struct libworker* w, struct ctx_query* q, ldns_buffer* pkt,
|
||||
int err)
|
||||
int err, char* reason)
|
||||
{
|
||||
uint8_t* msg = NULL;
|
||||
uint32_t len = 0;
|
||||
@@ -546,6 +559,8 @@ add_bg_result(struct libworker* w, struct ctx_query* q, ldns_buffer* pkt,
|
||||
/* serialize and delete unneeded q */
|
||||
if(w->is_bg_thread) {
|
||||
lock_basic_lock(&w->ctx->cfglock);
|
||||
if(reason)
|
||||
q->res->why_bogus = strdup(reason);
|
||||
if(pkt) {
|
||||
q->msg_len = ldns_buffer_remaining(pkt);
|
||||
q->msg = memdup(ldns_buffer_begin(pkt), q->msg_len);
|
||||
@@ -557,6 +572,8 @@ add_bg_result(struct libworker* w, struct ctx_query* q, ldns_buffer* pkt,
|
||||
} else msg = context_serialize_answer(q, err, NULL, &len);
|
||||
lock_basic_unlock(&w->ctx->cfglock);
|
||||
} else {
|
||||
if(reason)
|
||||
q->res->why_bogus = strdup(reason);
|
||||
msg = context_serialize_answer(q, err, pkt, &len);
|
||||
(void)rbtree_delete(&w->ctx->queries, q->node.key);
|
||||
w->ctx->num_async--;
|
||||
@@ -574,7 +591,8 @@ add_bg_result(struct libworker* w, struct ctx_query* q, ldns_buffer* pkt,
|
||||
}
|
||||
|
||||
void
|
||||
libworker_bg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s)
|
||||
libworker_bg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s,
|
||||
char* why_bogus)
|
||||
{
|
||||
struct ctx_query* q = (struct ctx_query*)arg;
|
||||
|
||||
@@ -595,7 +613,7 @@ libworker_bg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s)
|
||||
if(rcode != 0) {
|
||||
error_encode(buf, rcode, NULL, 0, BIT_RD, NULL);
|
||||
}
|
||||
add_bg_result(q->w, q, buf, UB_NOERROR);
|
||||
add_bg_result(q->w, q, buf, UB_NOERROR, why_bogus);
|
||||
}
|
||||
|
||||
|
||||
@@ -620,7 +638,7 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
|
||||
return;
|
||||
}
|
||||
if(!setup_qinfo_edns(w, q, &qinfo, &edns)) {
|
||||
add_bg_result(w, q, NULL, UB_SYNTAX);
|
||||
add_bg_result(w, q, NULL, UB_SYNTAX, NULL);
|
||||
return;
|
||||
}
|
||||
qid = 0;
|
||||
@@ -630,8 +648,9 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
|
||||
ldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags);
|
||||
if(local_zones_answer(w->ctx->local_zones, &qinfo, &edns,
|
||||
w->back->udp_buff, w->env->scratch)) {
|
||||
regional_free_all(w->env->scratch);
|
||||
q->msg_security = sec_status_insecure;
|
||||
add_bg_result(w, q, w->back->udp_buff, UB_NOERROR);
|
||||
add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL);
|
||||
free(qinfo.qname);
|
||||
return;
|
||||
}
|
||||
@@ -639,7 +658,7 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
|
||||
/* process new query */
|
||||
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
|
||||
w->back->udp_buff, qid, libworker_bg_done_cb, q)) {
|
||||
add_bg_result(w, q, NULL, UB_NOMEM);
|
||||
add_bg_result(w, q, NULL, UB_NOMEM, NULL);
|
||||
}
|
||||
free(qinfo.qname);
|
||||
}
|
||||
@@ -651,18 +670,6 @@ 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)
|
||||
@@ -676,7 +683,7 @@ outbound_entry_compare(void* a, void* b)
|
||||
|
||||
struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
|
||||
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct module_qstate* q)
|
||||
{
|
||||
struct libworker* w = (struct libworker*)q->env->worker;
|
||||
@@ -686,9 +693,9 @@ 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,
|
||||
addr, addrlen, libworker_handle_service_reply, e,
|
||||
w->back->udp_buff, &outbound_entry_compare);
|
||||
if(!e->qsent) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -803,19 +810,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);
|
||||
@@ -833,6 +832,11 @@ void worker_stat_timer_cb(void* ATTR_UNUSED(arg))
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void worker_probe_timer_cb(void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
int order_lock_cmp(const void* ATTR_UNUSED(e1), const void* ATTR_UNUSED(e2))
|
||||
{
|
||||
log_assert(0);
|
||||
@@ -846,6 +850,17 @@ codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||
return 0;
|
||||
}
|
||||
|
||||
int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
#ifdef UB_ON_WINDOWS
|
||||
void
|
||||
worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void*
|
||||
|
||||
+4
-17
@@ -107,20 +107,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,6 +115,7 @@ 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 q: wich query state to reactivate upon return.
|
||||
@@ -137,7 +124,7 @@ int libworker_send_packet(ldns_buffer* pkt, struct sockaddr_storage* addr,
|
||||
*/
|
||||
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,
|
||||
int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct module_qstate* q);
|
||||
|
||||
/** process incoming replies from the network */
|
||||
@@ -158,11 +145,11 @@ void libworker_handle_result_write(struct tube* tube, uint8_t* msg, size_t len,
|
||||
|
||||
/** mesh callback with fg results */
|
||||
void libworker_fg_done_cb(void* arg, int rcode, ldns_buffer* buf,
|
||||
enum sec_status s);
|
||||
enum sec_status s, char* why_bogus);
|
||||
|
||||
/** mesh callback with bg results */
|
||||
void libworker_bg_done_cb(void* arg, int rcode, ldns_buffer* buf,
|
||||
enum sec_status s);
|
||||
enum sec_status s, char* why_bogus);
|
||||
|
||||
/**
|
||||
* fill result from parsed message, on error fills servfail
|
||||
|
||||
@@ -56,9 +56,9 @@ clean:
|
||||
rm -f _unbound.so libunbound_wrap.o
|
||||
$(MAKE) -C ../.. clean
|
||||
|
||||
testenv: ../../.libs/libunbound.so.1 ../../ldns-src/lib/libldns.so ../../.libs/_unbound.so
|
||||
testenv: ../../.libs/libunbound.so.2 ../../ldns-src/lib/libldns.so ../../.libs/_unbound.so
|
||||
rm -rdf examples/unbound
|
||||
cd examples && mkdir unbound && ln -s ../../unbound.py unbound/__init__.py && ln -s ../../_unbound.so unbound/_unbound.so && ln -s ../../../../.libs/libunbound.so.1 unbound/libunbound.so.1 && ln -s ../../../../ldns-src/lib/libldns.so.1 unbound/libldns.so.1 && ls -la
|
||||
cd examples && mkdir unbound && ln -s ../../unbound.py unbound/__init__.py && ln -s ../../_unbound.so unbound/_unbound.so && ln -s ../../../../.libs/libunbound.so.2 unbound/libunbound.so.2 && ln -s ../../../../ldns-src/lib/libldns.so.1 unbound/libldns.so.1 && ls -la
|
||||
cd examples && if test -f ../../../.libs/_unbound.so; then cp ../../../.libs/_unbound.so . ; fi
|
||||
@echo "Run a script by typing ./script_name.py"
|
||||
cd examples && LD_LIBRARY_PATH=unbound bash
|
||||
|
||||
@@ -5,22 +5,18 @@ Installation
|
||||
|
||||
Python 2.4 or higher, SWIG 1.3 or higher, GNU make
|
||||
|
||||
**Download**
|
||||
|
||||
You can download the source codes `here`_.
|
||||
The latest release is 1.1.1, Jan 15, 2009.
|
||||
|
||||
.. _here: unbound-1.1.1-py.tar.gz
|
||||
|
||||
**Compiling**
|
||||
|
||||
After downloading, you can compile the pyUnbound library by doing::
|
||||
|
||||
> tar -xzf unbound-1.1.1-py.tar.gz
|
||||
> cd unbound-1.1.1
|
||||
> tar -xzf unbound-x.x.x-py.tar.gz
|
||||
> cd unbound-x.x.x
|
||||
> ./configure --with-pyunbound
|
||||
> make
|
||||
|
||||
You may want to --with-pythonmodule as well if you want to use python as
|
||||
a module in the resolver.
|
||||
|
||||
You need GNU make to compile sources; SWIG and Python devel libraries to compile extension module.
|
||||
|
||||
|
||||
@@ -32,4 +28,4 @@ If the compilation is successfull, you can test the python LDNS extension module
|
||||
> make testenv
|
||||
> ./dns-lookup.py
|
||||
|
||||
In contrib/examples you can find simple applications written in Python using the Unbound extension.
|
||||
You may want to make install in the main directory since make testenv is for debugging. In contrib/examples you can find simple applications written in Python using the Unbound extension.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
ub_ctx_create
|
||||
ub_ctx_delete
|
||||
ub_ctx_get_option
|
||||
ub_ctx_set_option
|
||||
ub_ctx_config
|
||||
ub_ctx_set_fwd
|
||||
|
||||
+33
-1
@@ -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,
|
||||
@@ -181,6 +185,14 @@ struct ub_result {
|
||||
* This means the data is from a domain where data is not signed.
|
||||
*/
|
||||
int bogus;
|
||||
|
||||
/**
|
||||
* If the result is bogus this contains a string (zero terminated)
|
||||
* that describes the failure. There may be other errors as well
|
||||
* as the one described, the description may not be perfectly accurate.
|
||||
* Is NULL if the result is not bogus.
|
||||
*/
|
||||
char* why_bogus;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -219,7 +231,7 @@ void ub_ctx_delete(struct ub_ctx* ctx);
|
||||
* @param ctx: context.
|
||||
* @param opt: option name from the unbound.conf config file format.
|
||||
* (not all settings applicable). The name includes the trailing ':'
|
||||
* for example ub_ctx_set_option("logfile:", "mylog.txt");
|
||||
* for example ub_ctx_set_option(ctx, "logfile:", "mylog.txt");
|
||||
* This is a power-users interface that lets you specify all sorts
|
||||
* of options.
|
||||
* For some specific options, such as adding trust anchors, special
|
||||
@@ -229,6 +241,22 @@ void ub_ctx_delete(struct ub_ctx* ctx);
|
||||
*/
|
||||
int ub_ctx_set_option(struct ub_ctx* ctx, char* opt, char* val);
|
||||
|
||||
/**
|
||||
* Get an option from the context.
|
||||
* @param ctx: context.
|
||||
* @param opt: option name from the unbound.conf config file format.
|
||||
* (not all settings applicable). The name excludes the trailing ':'
|
||||
* for example ub_ctx_get_option(ctx, "logfile", &result);
|
||||
* This is a power-users interface that lets you specify all sorts
|
||||
* of options.
|
||||
* @param str: the string is malloced and returned here. NULL on error.
|
||||
* The caller must free() the string. In cases with multiple
|
||||
* entries (auto-trust-anchor-file), a newline delimited list is
|
||||
* returned in the string.
|
||||
* @return 0 if OK else an error code (malloc failure, syntax error).
|
||||
*/
|
||||
int ub_ctx_get_option(struct ub_ctx* ctx, char* opt, char** str);
|
||||
|
||||
/**
|
||||
* setup configuration for the given context.
|
||||
* @param ctx: context.
|
||||
@@ -515,4 +543,8 @@ int ub_ctx_data_add(struct ub_ctx* ctx, char *data);
|
||||
*/
|
||||
int ub_ctx_data_remove(struct ub_ctx* ctx, char *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _UB_UNBOUND_H */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Generated from ltmain.m4sh.
|
||||
|
||||
# ltmain.sh (GNU libtool) 2.2.6
|
||||
# ltmain.sh (GNU libtool) 2.2.6b
|
||||
# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
|
||||
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc.
|
||||
@@ -65,7 +65,7 @@
|
||||
# compiler: $LTCC
|
||||
# compiler flags: $LTCFLAGS
|
||||
# linker: $LD (gnu? $with_gnu_ld)
|
||||
# $progname: (GNU libtool) 2.2.6
|
||||
# $progname: (GNU libtool) 2.2.6b
|
||||
# automake: $automake_version
|
||||
# autoconf: $autoconf_version
|
||||
#
|
||||
@@ -73,9 +73,9 @@
|
||||
|
||||
PROGRAM=ltmain.sh
|
||||
PACKAGE=libtool
|
||||
VERSION=2.2.6
|
||||
VERSION=2.2.6b
|
||||
TIMESTAMP=""
|
||||
package_revision=1.3012
|
||||
package_revision=1.3017
|
||||
|
||||
# Be Bourne compatible
|
||||
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
|
||||
|
||||
+123
-31
@@ -54,6 +54,8 @@ 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.
|
||||
-w ... Build windows binary dist. last args passed to configure.
|
||||
EOF
|
||||
exit 1
|
||||
@@ -107,11 +109,34 @@ replace_all () {
|
||||
replace_text "$1" "@date@" "`date +'%b %e, %Y'`"
|
||||
}
|
||||
|
||||
check_svn_root () {
|
||||
# Check if SVNROOT is specified.
|
||||
if [ -z "$SVNROOT" ]; then
|
||||
if test -f .svn/entries; then
|
||||
eval `svn info | grep 'URL:' | sed -e 's/URL: /url=/' | head -1`
|
||||
SVNROOT="$url"
|
||||
fi
|
||||
if test -z "$SVNROOT"; then
|
||||
error "SVNROOT must be specified (using -d)"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
create_temp_dir () {
|
||||
# Creating temp directory
|
||||
info "Creating temporary working directory"
|
||||
temp_dir=`mktemp -d unbound-dist-XXXXXX`
|
||||
info "Directory '$temp_dir' created."
|
||||
cd $temp_dir
|
||||
}
|
||||
|
||||
|
||||
SNAPSHOT="no"
|
||||
RC="no"
|
||||
LDNSDIR=""
|
||||
DOWIN="no"
|
||||
WINSSL=""
|
||||
WINEXPAT=""
|
||||
|
||||
# Parse the command line arguments.
|
||||
while [ "$1" ]; do
|
||||
@@ -126,6 +151,14 @@ while [ "$1" ]; do
|
||||
"-s")
|
||||
SNAPSHOT="yes"
|
||||
;;
|
||||
"-wssl")
|
||||
WINSSL="$2"
|
||||
shift
|
||||
;;
|
||||
"-wxp")
|
||||
WINEXPAT="$2"
|
||||
shift
|
||||
;;
|
||||
"-w")
|
||||
DOWIN="yes"
|
||||
shift
|
||||
@@ -147,6 +180,71 @@ while [ "$1" ]; do
|
||||
done
|
||||
|
||||
if [ "$DOWIN" = "yes" ]; then
|
||||
# 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
|
||||
# in crosscompile no installed ldns, use builtin (not linux-ldns)
|
||||
cross_flag="--with-ldns-builtin"
|
||||
|
||||
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 "$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"
|
||||
|
||||
# on a re-configure the cache may no longer be valid...
|
||||
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
|
||||
fi
|
||||
|
||||
# version gets compiled into source, edit the configure to set it
|
||||
version=`./configure --version | head -1 | awk '{ print $3 }'` \
|
||||
|| error_cleanup "Cannot determine version number."
|
||||
if [ "$RC" != "no" -o "$SNAPSHOT" != "no" ]; then
|
||||
@@ -168,8 +266,8 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
# 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"
|
||||
@@ -180,46 +278,42 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
rm -f $file
|
||||
info "Creating $file"
|
||||
mkdir tmp.$$
|
||||
strip unbound.exe
|
||||
strip anchor-update.exe
|
||||
strip unbound-control.exe
|
||||
strip unbound-host.exe
|
||||
strip unbound-checkconf.exe
|
||||
strip unbound-service-install.exe
|
||||
strip unbound-service-remove.exe
|
||||
$strip unbound.exe
|
||||
$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
|
||||
info "Creating installer"
|
||||
quadversion=`cat ../config.h | grep RSRC_PACKAGE_VERSION | sed -e 's/#define RSRC_PACKAGE_VERSION //' -e 's/,/\\./g'`
|
||||
cat ../winrc/setup.nsi | sed -e 's/define VERSION.*$/define VERSION "'$version'"/' -e 's/define QUADVERSION.*$/define QUADVERSION "'$quadversion'"/' > ../winrc/setup_ed.nsi
|
||||
# get tool from http://nsis.sf.net
|
||||
c:/Program\ Files/NSIS/makensis.exe ../winrc/setup_ed.nsi
|
||||
"$makensis" ../winrc/setup_ed.nsi
|
||||
info "Created installer"
|
||||
cd ..
|
||||
rm -rf tmp.$$
|
||||
mv winrc/unbound_setup_$version.exe .
|
||||
if test "$cross" = "yes"; then
|
||||
mv unbound_setup_$version.exe $cwd/.
|
||||
mv unbound-$version.zip $cwd/.
|
||||
cleanup
|
||||
fi
|
||||
ls -lG unbound_setup_$version.exe
|
||||
ls -lG unbound-$version.zip
|
||||
info "Done"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if SVNROOT is specified.
|
||||
if [ -z "$SVNROOT" ]; then
|
||||
if test -f .svn/entries; then
|
||||
eval `svn info | grep 'URL:' | sed -e 's/URL: /url=/' | head -1`
|
||||
SVNROOT="$url"
|
||||
fi
|
||||
if test -z "$SVNROOT"; then
|
||||
error "SVNROOT must be specified (using -d)"
|
||||
fi
|
||||
fi
|
||||
check_svn_root
|
||||
# Check if LDNSDIR is specified.
|
||||
if test -z "$LDNSDIR"; then
|
||||
# try to autodetect from Makefile (if present)
|
||||
@@ -237,12 +331,7 @@ info "SNAPSHOT is $SNAPSHOT"
|
||||
|
||||
#question "Do you wish to continue with these settings?" || error "User abort."
|
||||
|
||||
|
||||
# Creating temp directory
|
||||
info "Creating temporary working directory"
|
||||
temp_dir=`mktemp -d unbound-dist-XXXXXX`
|
||||
info "Directory '$temp_dir' created."
|
||||
cd $temp_dir
|
||||
create_temp_dir
|
||||
|
||||
info "Exporting source from SVN."
|
||||
svn export "$SVNROOT" unbound || error_cleanup "SVN command failed"
|
||||
@@ -258,9 +347,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 ../..
|
||||
@@ -317,6 +408,7 @@ 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/libunbound.3.in
|
||||
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@
|
||||
|
||||
SUEXEC = sudo
|
||||
UNBOUND = ../unbound
|
||||
SCRIPT = ./test-dict.conf
|
||||
SCRIPT = ./test-resip.conf
|
||||
|
||||
UNBOUND_OPTS = -dv -c $(SCRIPT)
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
'''
|
||||
resip.py: This example shows how to generate authoritative response
|
||||
and how to find out the IP address of a client
|
||||
|
||||
Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
|
||||
Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz)
|
||||
|
||||
This software is open source.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the organization nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
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 REGENTS 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.
|
||||
|
||||
|
||||
Usage:
|
||||
|
||||
dig @127.0.0.1 -t TXT what.is.my.ip.
|
||||
'''
|
||||
|
||||
def init(id, cfg): return True
|
||||
|
||||
def deinit(id): return True
|
||||
|
||||
def inform_super(id, qstate, superqstate, qdata): return True
|
||||
|
||||
def operate(id, event, qstate, qdata):
|
||||
print "Operate", event,"state:",qstate
|
||||
|
||||
# Please note that if this module blocks, by moving to the validator
|
||||
# to validate or iterator to lookup or spawn a subquery to look up,
|
||||
# then, other incoming queries are queued up onto this module and
|
||||
# all of them receive the same reply.
|
||||
# You can inspect the cache.
|
||||
|
||||
if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS):
|
||||
if (qstate.qinfo.qname_str.endswith("what.is.my.ip.")): #query name ends with localdomain
|
||||
#create instance of DNS message (packet) with given parameters
|
||||
msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_TXT, RR_CLASS_IN, PKT_QR | PKT_RA | PKT_AA)
|
||||
#append RR
|
||||
if (qstate.qinfo.qtype == RR_TYPE_TXT) or (qstate.qinfo.qtype == RR_TYPE_ANY):
|
||||
rl = qstate.mesh_info.reply_list
|
||||
while (rl):
|
||||
if rl.query_reply:
|
||||
q = rl.query_reply
|
||||
# The TTL of 0 is mandatory, otherwise it ends up in
|
||||
# the cache, and is returned to other IP addresses.
|
||||
msg.answer.append("%s 0 IN TXT \"%s %d (%s)\"" % (qstate.qinfo.qname_str, q.addr,q.port,q.family))
|
||||
rl = rl.next
|
||||
|
||||
#set qstate.return_msg
|
||||
if not msg.set_return_msg(qstate):
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
||||
|
||||
#we don't need validation, result is valid
|
||||
qstate.return_msg.rep.security = 2
|
||||
|
||||
qstate.return_rcode = RCODE_NOERROR
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
else:
|
||||
#pass the query to validator
|
||||
qstate.ext_state[id] = MODULE_WAIT_MODULE
|
||||
return True
|
||||
|
||||
if event == MODULE_EVENT_MODDONE:
|
||||
log_info("pythonmod: iterator module done")
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
|
||||
log_err("pythonmod: bad event")
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
||||
+79
-10
@@ -17,6 +17,7 @@
|
||||
#include "config.h"
|
||||
#include "util/log.h"
|
||||
#include "util/module.h"
|
||||
#include "util/netevent.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/msgreply.h"
|
||||
@@ -24,6 +25,7 @@
|
||||
#include "util/data/dname.h"
|
||||
#include "util/storage/lruhash.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/mesh.h"
|
||||
%}
|
||||
|
||||
%include "stdint.i" // uint_16_t can be known type now
|
||||
@@ -343,6 +345,7 @@ struct reply_info {
|
||||
uint16_t flags;
|
||||
uint16_t qdcount;
|
||||
uint32_t ttl;
|
||||
uint32_t prefetch_ttl;
|
||||
|
||||
uint16_t authoritative;
|
||||
enum sec_status security;
|
||||
@@ -408,6 +411,68 @@ struct dns_msg {
|
||||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
Structure mesh_state
|
||||
* ************************************************************************************ */
|
||||
struct mesh_state {
|
||||
struct mesh_reply* reply_list;
|
||||
};
|
||||
|
||||
struct mesh_reply {
|
||||
struct mesh_reply* next;
|
||||
struct comm_reply query_reply;
|
||||
};
|
||||
|
||||
struct comm_reply {
|
||||
|
||||
};
|
||||
|
||||
%inline %{
|
||||
|
||||
PyObject* _comm_reply_addr_get(struct comm_reply* reply) {
|
||||
char dest[64];
|
||||
reply_addr2str(reply, dest, 64);
|
||||
if (dest[0] == 0)
|
||||
return Py_None;
|
||||
return PyString_FromString(dest);
|
||||
}
|
||||
|
||||
PyObject* _comm_reply_family_get(struct comm_reply* reply) {
|
||||
|
||||
int af = (int)((struct sockaddr_in*) &(reply->addr))->sin_family;
|
||||
|
||||
switch(af) {
|
||||
case AF_INET: return PyString_FromString("ip4");
|
||||
case AF_INET6: return PyString_FromString("ip6");
|
||||
case AF_UNIX: return PyString_FromString("unix");
|
||||
}
|
||||
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject* _comm_reply_port_get(struct comm_reply* reply) {
|
||||
uint16_t port;
|
||||
port = ntohs(((struct sockaddr_in*)&(reply->addr))->sin_port);
|
||||
return PyInt_FromLong(port);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%extend comm_reply {
|
||||
%pythoncode %{
|
||||
def _addr_get(self): return _comm_reply_addr_get(self)
|
||||
__swig_getmethods__["addr"] = _addr_get
|
||||
if _newclass:addr = _swig_property(_addr_get)
|
||||
|
||||
def _port_get(self): return _comm_reply_port_get(self)
|
||||
__swig_getmethods__["port"] = _port_get
|
||||
if _newclass:port = _swig_property(_port_get)
|
||||
|
||||
def _family_get(self): return _comm_reply_family_get(self)
|
||||
__swig_getmethods__["family"] = _family_get
|
||||
if _newclass:family = _swig_property(_family_get)
|
||||
%}
|
||||
}
|
||||
/* ************************************************************************************ *
|
||||
Structure module_qstate
|
||||
* ************************************************************************************ */
|
||||
@@ -715,7 +780,7 @@ int set_return_msg(struct module_qstate* qstate,
|
||||
{
|
||||
ldns_pkt* pkt = 0;
|
||||
ldns_status status;
|
||||
ldns_rr_list* rr_list1 = 0,*rr_list2 = 0,*rr_list3 = 0,*rr_list4 = 0;
|
||||
ldns_rr_list* rr_list = 0;
|
||||
ldns_buffer *qb = 0;
|
||||
int res = 1;
|
||||
|
||||
@@ -726,14 +791,18 @@ int set_return_msg(struct module_qstate* qstate,
|
||||
if ((status != LDNS_STATUS_OK) || (pkt == 0))
|
||||
return 0;
|
||||
|
||||
rr_list1 = createRRList(question, default_ttl);
|
||||
if ((rr_list1) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_QUESTION, rr_list1);
|
||||
rr_list2 = createRRList(answer, default_ttl);
|
||||
if ((rr_list2) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_ANSWER, rr_list2);
|
||||
rr_list3 = createRRList(authority, default_ttl);
|
||||
if ((rr_list3) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_AUTHORITY, rr_list3);
|
||||
rr_list4 = createRRList(additional, default_ttl);
|
||||
if ((rr_list4) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_ADDITIONAL, rr_list4);
|
||||
rr_list = createRRList(question, default_ttl);
|
||||
if ((rr_list) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_QUESTION, rr_list);
|
||||
ldns_rr_list_free(rr_list);
|
||||
rr_list = createRRList(answer, default_ttl);
|
||||
if ((rr_list) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_ANSWER, rr_list);
|
||||
ldns_rr_list_free(rr_list);
|
||||
rr_list = createRRList(authority, default_ttl);
|
||||
if ((rr_list) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_AUTHORITY, rr_list);
|
||||
ldns_rr_list_free(rr_list);
|
||||
rr_list = createRRList(additional, default_ttl);
|
||||
if ((rr_list) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_ADDITIONAL, rr_list);
|
||||
ldns_rr_list_free(rr_list);
|
||||
|
||||
if ((res) && ((qb = ldns_buffer_new(LDNS_MIN_BUFLEN)) == 0)) res = 0;
|
||||
if ((res) && (ldns_pkt2buffer_wire(qb, pkt) != LDNS_STATUS_OK)) res = 0;
|
||||
@@ -742,7 +811,7 @@ int set_return_msg(struct module_qstate* qstate,
|
||||
|
||||
if (qb) ldns_buffer_free(qb);
|
||||
|
||||
ldns_pkt_free(pkt); //this function dealocates pkt as well as rr_lists
|
||||
ldns_pkt_free(pkt); //this function dealocates pkt as well as rrs
|
||||
return res;
|
||||
}
|
||||
%}
|
||||
|
||||
+29
-19
@@ -44,6 +44,7 @@
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include "ldns/ldns.h"
|
||||
|
||||
#undef _POSIX_C_SOURCE
|
||||
#undef _XOPEN_SOURCE
|
||||
@@ -56,6 +57,8 @@
|
||||
|
||||
#ifdef S_SPLINT_S
|
||||
typedef struct PyObject PyObject;
|
||||
typedef struct PyThreadState PyThreadState;
|
||||
typedef void* PyGILState_STATE;
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -66,6 +69,8 @@ struct pythonmod_env {
|
||||
/** Python script filename. */
|
||||
const char* fname;
|
||||
|
||||
/** Python main thread */
|
||||
PyThreadState* mainthr;
|
||||
/** Python module. */
|
||||
PyObject* module;
|
||||
|
||||
@@ -107,6 +112,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 +136,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");
|
||||
@@ -150,7 +156,7 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
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 +164,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 +180,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 +189,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 +221,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 +236,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,9 +248,14 @@ 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);
|
||||
|
||||
/* Module is deallocated in Python */
|
||||
env->modinfo[id] = NULL;
|
||||
@@ -255,6 +266,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);
|
||||
@@ -262,7 +274,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);
|
||||
|
||||
@@ -282,7 +293,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,
|
||||
@@ -291,6 +302,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)
|
||||
{
|
||||
@@ -302,9 +314,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,
|
||||
@@ -323,8 +332,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)
|
||||
@@ -338,7 +346,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);
|
||||
}
|
||||
@@ -365,7 +375,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);
|
||||
|
||||
+40
-23
@@ -40,6 +40,7 @@
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "util/module.h"
|
||||
#include "util/netevent.h"
|
||||
#include "util/net_help.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/cache/rrset.h"
|
||||
@@ -52,22 +53,23 @@
|
||||
#undef _XOPEN_SOURCE
|
||||
#include <Python.h>
|
||||
|
||||
/** Store the reply_info and query_info pair in message cache (qstate->msg_cache) */
|
||||
/* Store the reply_info and query_info pair in message cache (qstate->msg_cache) */
|
||||
int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, struct reply_info* msgrep, int is_referral)
|
||||
{
|
||||
if (!msgrep)
|
||||
return 0;
|
||||
|
||||
if (msgrep->authoritative) //authoritative answer can't be stored in cache
|
||||
if (msgrep->authoritative) /*authoritative answer can't be stored in cache*/
|
||||
{
|
||||
PyErr_SetString(PyExc_ValueError, "Authoritative answer can't be stored");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return dns_cache_store(qstate->env, qinfo, msgrep, is_referral);
|
||||
return dns_cache_store(qstate->env, qinfo, msgrep, is_referral,
|
||||
qstate->prefetch_leeway);
|
||||
}
|
||||
|
||||
/** Invalidate the message associated with query_info stored in message cache */
|
||||
/* Invalidate the message associated with query_info stored in message cache */
|
||||
void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qinfo)
|
||||
{
|
||||
hashvalue_t h;
|
||||
@@ -78,10 +80,10 @@ void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qin
|
||||
h = query_info_hash(qinfo);
|
||||
if ((e=slabhash_lookup(qstate->env->msg_cache, h, qinfo, 0)))
|
||||
{
|
||||
r = (struct reply_info*)(e->data);
|
||||
if (r)
|
||||
{
|
||||
r->ttl = 0;
|
||||
r = (struct reply_info*)(e->data);
|
||||
if (r)
|
||||
{
|
||||
r->ttl = 0;
|
||||
if(rrset_array_lock(r->ref, r->rrset_count, *qstate->env->now)) {
|
||||
for(i=0; i< r->rrset_count; i++)
|
||||
{
|
||||
@@ -96,14 +98,14 @@ void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qin
|
||||
}
|
||||
rrset_array_unlock(r->ref, r->rrset_count);
|
||||
}
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
} else {
|
||||
log_info("invalidateQueryInCache: qinfo is not in cache");
|
||||
log_info("invalidateQueryInCache: qinfo is not in cache");
|
||||
}
|
||||
}
|
||||
|
||||
/** Create response according to the ldns packet content */
|
||||
/* Create response according to the ldns packet content */
|
||||
int createResponse(struct module_qstate* qstate, ldns_buffer* pkt)
|
||||
{
|
||||
struct msg_parse* prs;
|
||||
@@ -112,8 +114,8 @@ int createResponse(struct module_qstate* qstate, ldns_buffer* pkt)
|
||||
/* parse message */
|
||||
prs = (struct msg_parse*) regional_alloc(qstate->env->scratch, sizeof(struct msg_parse));
|
||||
if (!prs) {
|
||||
log_err("storeResponse: out of memory on incoming message");
|
||||
return 0;
|
||||
log_err("storeResponse: out of memory on incoming message");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(prs, 0, sizeof(*prs));
|
||||
@@ -121,12 +123,12 @@ int createResponse(struct module_qstate* qstate, ldns_buffer* pkt)
|
||||
|
||||
ldns_buffer_set_position(pkt, 0);
|
||||
if (parse_packet(pkt, prs, qstate->env->scratch) != LDNS_RCODE_NOERROR) {
|
||||
verbose(VERB_ALGO, "storeResponse: parse error on reply packet");
|
||||
return 0;
|
||||
verbose(VERB_ALGO, "storeResponse: parse error on reply packet");
|
||||
return 0;
|
||||
}
|
||||
/* edns is not examined, but removed from message to help cache */
|
||||
if(parse_extract_edns(prs, &edns) != LDNS_RCODE_NOERROR)
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
/* remove CD-bit, we asked for in case we handle validation ourself */
|
||||
prs->flags &= ~BIT_CD;
|
||||
@@ -138,23 +140,38 @@ int createResponse(struct module_qstate* qstate, ldns_buffer* pkt)
|
||||
|
||||
memset(qstate->return_msg, 0, sizeof(*qstate->return_msg));
|
||||
if(!parse_create_msg(pkt, prs, NULL, &(qstate->return_msg)->qinfo, &(qstate->return_msg)->rep, qstate->region)) {
|
||||
log_err("storeResponse: malloc failure: allocating incoming dns_msg");
|
||||
return 0;
|
||||
log_err("storeResponse: malloc failure: allocating incoming dns_msg");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make sure that the RA flag is set (since the presence of
|
||||
* this module means that recursion is available) */
|
||||
//qstate->return_msg->rep->flags |= BIT_RA;
|
||||
/* qstate->return_msg->rep->flags |= BIT_RA; */
|
||||
|
||||
/* Clear the AA flag */
|
||||
/* FIXME: does this action go here or in some other module? */
|
||||
//qstate->return_msg->rep->flags &= ~BIT_AA;
|
||||
/*qstate->return_msg->rep->flags &= ~BIT_AA; */
|
||||
|
||||
/* make sure QR flag is on */
|
||||
//qstate->return_msg->rep->flags |= BIT_QR;
|
||||
/*qstate->return_msg->rep->flags |= BIT_QR; */
|
||||
|
||||
if(verbosity >= VERB_ALGO)
|
||||
log_dns_msg("storeResponse: packet:", &qstate->return_msg->qinfo, qstate->return_msg->rep);
|
||||
log_dns_msg("storeResponse: packet:", &qstate->return_msg->qinfo, qstate->return_msg->rep);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Convert reply->addr to string */
|
||||
void reply_addr2str(struct comm_reply* reply, char* dest, int maxlen)
|
||||
{
|
||||
int af = (int)((struct sockaddr_in*) &(reply->addr))->sin_family;
|
||||
void* sinaddr = &((struct sockaddr_in*) &(reply->addr))->sin_addr;
|
||||
|
||||
if(af == AF_INET6)
|
||||
sinaddr = &((struct sockaddr_in6*)&(reply->addr))->sin6_addr;
|
||||
dest[0] = 0;
|
||||
if (inet_ntop(af, sinaddr, dest, (socklen_t)maxlen) == 0)
|
||||
return;
|
||||
dest[maxlen-1] = 0;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,16 @@ 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);
|
||||
|
||||
/**
|
||||
* Convert reply->addr to string
|
||||
* @param reply: comm reply with address in it.
|
||||
* @param dest: destination string.
|
||||
* @param maxlen: length of string buffer.
|
||||
*/
|
||||
void reply_addr2str(struct comm_reply* reply, char* dest, int maxlen);
|
||||
|
||||
#endif /* PYTHONMOD_UTILS_H */
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Example configuration file for resip.py
|
||||
server:
|
||||
verbosity: 1
|
||||
#interface: 0.0.0.0
|
||||
do-daemonize: no
|
||||
#access-control: 0.0.0.0/0 allow
|
||||
chroot: ""
|
||||
username: ""
|
||||
directory: ""
|
||||
logfile: ""
|
||||
pidfile: "unbound.pid"
|
||||
module-config: "validator python iterator"
|
||||
|
||||
# Python config section
|
||||
python:
|
||||
# Script file to load
|
||||
python-script: "./examples/resip.py"
|
||||
|
||||
Vendored
+25
-13
@@ -71,7 +71,7 @@ store_rrsets(struct module_env* env, struct reply_info* rep, uint32_t now)
|
||||
|
||||
void
|
||||
dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
hashvalue_t hash, struct reply_info* rep)
|
||||
hashvalue_t hash, struct reply_info* rep, uint32_t leeway)
|
||||
{
|
||||
struct msgreply_entry* e;
|
||||
uint32_t ttl = rep->ttl;
|
||||
@@ -84,7 +84,7 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
}
|
||||
reply_info_sortref(rep);
|
||||
reply_info_set_ttls(rep, *env->now);
|
||||
store_rrsets(env, rep, *env->now);
|
||||
store_rrsets(env, rep, *env->now+leeway);
|
||||
if(ttl == 0) {
|
||||
/* we do not store the message, but we did store the RRs,
|
||||
* which could be useful for delegation information */
|
||||
@@ -227,12 +227,10 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
|
||||
struct ub_packed_rrset_key* akey;
|
||||
uint32_t now = *env->now;
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
if(ns->resolved)
|
||||
continue;
|
||||
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, 1)) {
|
||||
if(!delegpt_add_rrset_A(dp, region, akey, (int)ns->lame)) {
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
@@ -250,7 +248,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, 1)) {
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, akey, (int)ns->lame)) {
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
@@ -380,7 +378,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) */
|
||||
@@ -432,6 +430,9 @@ tomsg(struct module_env* env, struct msgreply_entry* e, struct reply_info* r,
|
||||
msg->rep->flags = r->flags;
|
||||
msg->rep->qdcount = r->qdcount;
|
||||
msg->rep->ttl = r->ttl - now;
|
||||
if(r->prefetch_ttl > now)
|
||||
msg->rep->prefetch_ttl = r->prefetch_ttl - now;
|
||||
else msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->security = r->security;
|
||||
msg->rep->an_numrrsets = r->an_numrrsets;
|
||||
msg->rep->ns_numrrsets = r->ns_numrrsets;
|
||||
@@ -482,6 +483,7 @@ rrset_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
msg->rep->authoritative = 0; /* reply stored in cache can't be authoritative */
|
||||
msg->rep->qdcount = 1;
|
||||
msg->rep->ttl = d->ttl - now;
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->security = sec_status_unchecked;
|
||||
msg->rep->an_numrrsets = 1;
|
||||
msg->rep->ns_numrrsets = 0;
|
||||
@@ -517,6 +519,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
msg->rep->authoritative = 0; /* reply stored in cache can't be authoritative */
|
||||
msg->rep->qdcount = 1;
|
||||
msg->rep->ttl = d->ttl - now;
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->security = sec_status_unchecked;
|
||||
msg->rep->an_numrrsets = 1;
|
||||
msg->rep->ns_numrrsets = 0;
|
||||
@@ -574,6 +577,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
packed_rrset_ptr_fixup(newd);
|
||||
newd->rr_ttl[0] = newd->ttl;
|
||||
msg->rep->ttl = newd->ttl;
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(newd->ttl);
|
||||
ldns_write_uint16(newd->rr_data[0], newlen);
|
||||
memmove(newd->rr_data[0] + sizeof(uint16_t), newname, newlen);
|
||||
msg->rep->an_numrrsets ++;
|
||||
@@ -626,8 +630,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) {
|
||||
@@ -652,7 +658,10 @@ dns_cache_lookup(struct module_env* env,
|
||||
struct packed_rrset_data *d = (struct packed_rrset_data*)
|
||||
rrset->entry.data;
|
||||
if(d->trust != rrset_trust_add_noAA &&
|
||||
d->trust != rrset_trust_add_AA) {
|
||||
d->trust != rrset_trust_add_AA &&
|
||||
(qtype == LDNS_RR_TYPE_DS ||
|
||||
(d->trust != rrset_trust_auth_noAA
|
||||
&& d->trust != rrset_trust_auth_AA) )) {
|
||||
struct dns_msg* msg = rrset_msg(rrset, region, now, &k);
|
||||
if(msg) {
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
@@ -666,13 +675,16 @@ dns_cache_lookup(struct module_env* env,
|
||||
|
||||
int
|
||||
dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
struct reply_info* msgrep, int is_referral)
|
||||
struct reply_info* msgrep, int is_referral, uint32_t leeway)
|
||||
{
|
||||
struct reply_info* rep = NULL;
|
||||
/* alloc, malloc properly (not in region, like msg is) */
|
||||
rep = reply_info_copy(msgrep, env->alloc, NULL);
|
||||
if(!rep)
|
||||
return 0;
|
||||
/* ttl must be relative ;i.e. 0..86400 not time(0)+86400.
|
||||
* the env->now is added to message and RRsets in this routine. */
|
||||
/* the leeway is used to invalidate other rrsets earlier */
|
||||
|
||||
if(is_referral) {
|
||||
/* store rrsets */
|
||||
@@ -685,7 +697,7 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
ref.id = rep->rrsets[i]->id;
|
||||
/*ignore ret: it was in the cache, ref updated */
|
||||
(void)rrset_cache_update(env->rrset_cache, &ref,
|
||||
env->alloc, *env->now);
|
||||
env->alloc, *env->now + leeway);
|
||||
}
|
||||
free(rep);
|
||||
return 1;
|
||||
@@ -706,7 +718,7 @@ 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);
|
||||
dns_cache_store_msg(env, &qinf, h, rep, leeway);
|
||||
/* 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
+6
-2
@@ -72,10 +72,12 @@ struct dns_msg {
|
||||
* @param is_referral: If true, then the given message to be stored is a
|
||||
* referral. The cache implementation may use this as a hint.
|
||||
* 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.
|
||||
* @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);
|
||||
struct reply_info* rep, int is_referral, uint32_t leeway);
|
||||
|
||||
/**
|
||||
* Store message in the cache. Stores in message cache and rrset cache.
|
||||
@@ -88,9 +90,11 @@ int dns_cache_store(struct module_env* env, struct query_info* qinf,
|
||||
* @param hash: hash over qinfo.
|
||||
* @param rep: reply info, together with qinfo makes up the message.
|
||||
* 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.
|
||||
*/
|
||||
void dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
hashvalue_t hash, struct reply_info* rep);
|
||||
hashvalue_t hash, struct reply_info* rep, uint32_t leeway);
|
||||
|
||||
/**
|
||||
* Find a delegation from the cache.
|
||||
|
||||
Vendored
+109
-19
@@ -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,6 +47,10 @@
|
||||
#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 */
|
||||
|
||||
size_t
|
||||
infra_host_sizefunc(void* k, void* ATTR_UNUSED(d))
|
||||
@@ -100,6 +105,7 @@ infra_create(struct config_file* cfg)
|
||||
infra->host_ttl = cfg->host_ttl;
|
||||
infra->lame_ttl = cfg->lame_ttl;
|
||||
infra->max_lame_size = cfg->infra_cache_lame_size;
|
||||
infra->jostle = cfg->jostle_time;
|
||||
return infra;
|
||||
}
|
||||
|
||||
@@ -121,6 +127,7 @@ infra_adjust(struct infra_cache* infra, struct config_file* cfg)
|
||||
infra->host_ttl = cfg->host_ttl;
|
||||
infra->lame_ttl = cfg->lame_ttl;
|
||||
infra->max_lame_size = cfg->infra_cache_lame_size;
|
||||
infra->jostle = cfg->jostle_time;
|
||||
maxmem = cfg->infra_cache_numhosts *
|
||||
(sizeof(struct infra_host_key)+sizeof(struct infra_host_data));
|
||||
if(maxmem != slabhash_get_size(infra->hosts) ||
|
||||
@@ -151,6 +158,19 @@ hash_addr(struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
return h;
|
||||
}
|
||||
|
||||
void
|
||||
infra_remove_host(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
{
|
||||
struct infra_host_key k;
|
||||
k.addrlen = addrlen;
|
||||
memcpy(&k.addr, addr, addrlen);
|
||||
k.entry.hash = hash_addr(addr, addrlen);
|
||||
k.entry.key = (void*)&k;
|
||||
k.entry.data = NULL;
|
||||
slabhash_remove(infra->hosts, k.entry.hash, &k);
|
||||
}
|
||||
|
||||
/** lookup version that does not check host ttl (you check it) */
|
||||
static struct lruhash_entry*
|
||||
infra_lookup_host_nottl(struct infra_cache* infra,
|
||||
@@ -186,6 +206,19 @@ infra_lookup_host(struct infra_cache* infra,
|
||||
return data;
|
||||
}
|
||||
|
||||
/** init the host elements (not lame elems) */
|
||||
static void
|
||||
host_entry_init(struct infra_cache* infra, struct lruhash_entry* e,
|
||||
uint32_t timenow)
|
||||
{
|
||||
struct infra_host_data* data = (struct infra_host_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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and init a new entry for a host
|
||||
* @param infra: infra structure with config parameters.
|
||||
@@ -215,11 +248,8 @@ new_host_entry(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
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;
|
||||
rtt_init(&data->rtt);
|
||||
host_entry_init(infra, &key->entry, tm);
|
||||
return &key->entry;
|
||||
}
|
||||
|
||||
@@ -231,19 +261,21 @@ infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
||||
addrlen, 0);
|
||||
struct infra_host_data* data;
|
||||
int wr = 0;
|
||||
if(e && ((struct infra_host_data*)e->data)->ttl < timenow) {
|
||||
/* it expired, try to reuse existing entry */
|
||||
int old = ((struct infra_host_data*)e->data)->rtt.rto;
|
||||
lock_rw_unlock(&e->lock);
|
||||
e = infra_lookup_host_nottl(infra, addr, addrlen, 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;
|
||||
host_entry_init(infra, e, timenow);
|
||||
wr = 1;
|
||||
/* TOP_TIMEOUT remains on reuse */
|
||||
if(old >= USEFUL_SERVER_TOP_TIMEOUT)
|
||||
((struct infra_host_data*)e->data)->rtt.rto=old;
|
||||
}
|
||||
}
|
||||
if(!e) {
|
||||
@@ -262,6 +294,22 @@ infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||
*to = rtt_timeout(&data->rtt);
|
||||
*edns_vs = data->edns_version;
|
||||
*edns_lame_known = data->edns_lame_known;
|
||||
if(*to >= PROBE_MAXRTO && rtt_notimeout(&data->rtt)*4 <= *to) {
|
||||
/* delay other queries, this is the probe query */
|
||||
if(!wr) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
e = infra_lookup_host_nottl(infra, addr, addrlen, 1);
|
||||
if(!e) { /* flushed from cache real fast, no use to
|
||||
allocate just for the probedelay */
|
||||
return 1;
|
||||
}
|
||||
data = (struct infra_host_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;
|
||||
}
|
||||
@@ -449,7 +497,7 @@ infra_update_tcp_works(struct infra_cache* infra,
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -467,13 +515,17 @@ infra_rtt_update(struct infra_cache* infra,
|
||||
if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
|
||||
return 0;
|
||||
needtoinsert = 1;
|
||||
}
|
||||
/* have an entry, update the rtt, and the ttl */
|
||||
} else if(((struct infra_host_data*)e->data)->ttl < timenow) {
|
||||
host_entry_init(infra, e, timenow);
|
||||
}
|
||||
/* have an entry, update the rtt */
|
||||
data = (struct infra_host_data*)e->data;
|
||||
data->ttl = timenow + infra->host_ttl;
|
||||
if(roundtrip == -1)
|
||||
if(roundtrip == -1) {
|
||||
rtt_lost(&data->rtt, orig_rtt);
|
||||
else rtt_update(&data->rtt, roundtrip);
|
||||
} else {
|
||||
rtt_update(&data->rtt, roundtrip);
|
||||
data->probedelay = 0;
|
||||
}
|
||||
if(data->rtt.rto > 0)
|
||||
rto = data->rtt.rto;
|
||||
|
||||
@@ -483,6 +535,27 @@ infra_rtt_update(struct infra_cache* infra,
|
||||
return rto;
|
||||
}
|
||||
|
||||
int infra_get_host_rto(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct rtt_info* rtt, int* delay, uint32_t timenow)
|
||||
{
|
||||
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
||||
addrlen, 0);
|
||||
struct infra_host_data* data;
|
||||
int ttl = -2;
|
||||
if(!e) return -1;
|
||||
data = (struct infra_host_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;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
return ttl;
|
||||
}
|
||||
|
||||
int
|
||||
infra_edns_update(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
@@ -496,12 +569,16 @@ infra_edns_update(struct infra_cache* infra,
|
||||
if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
|
||||
return 0;
|
||||
needtoinsert = 1;
|
||||
}
|
||||
} else if(((struct infra_host_data*)e->data)->ttl < timenow) {
|
||||
host_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;
|
||||
/* do not update if noEDNS and stored is yesEDNS */
|
||||
if(!(edns_version == -1 && data->edns_version != -1)) {
|
||||
data->edns_version = edns_version;
|
||||
data->edns_lame_known = 1;
|
||||
}
|
||||
|
||||
if(needtoinsert)
|
||||
slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
|
||||
@@ -523,6 +600,10 @@ infra_get_lame_rtt(struct infra_cache* infra,
|
||||
return 0;
|
||||
host = (struct infra_host_data*)e->data;
|
||||
*rtt = rtt_unclamped(&host->rtt);
|
||||
if(host->rtt.rto >= PROBE_MAXRTO && timenow < host->probedelay
|
||||
&& rtt_notimeout(&host->rtt)*4 <= host->rtt.rto)
|
||||
/* single probe for this domain, and we are not probing */
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
|
||||
/* check lameness first, if so, ttl on host does not matter anymore */
|
||||
if(infra_lookup_lame(host, name, namelen, timenow,
|
||||
&dlm, &rlm, &alm, &olm)) {
|
||||
@@ -557,6 +638,15 @@ infra_get_lame_rtt(struct infra_cache* infra,
|
||||
*dnsseclame = 0;
|
||||
*reclame = 0;
|
||||
if(timenow > host->ttl) {
|
||||
/* expired entry */
|
||||
/* see if this can be a re-probe of an unresponsive server */
|
||||
/* minus 1000 because that is outside of the RTTBAND, so
|
||||
* blacklisted servers stay blacklisted if this is chosen */
|
||||
if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 1;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Vendored
+27
@@ -64,6 +64,8 @@ struct infra_host_key {
|
||||
struct infra_host_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. */
|
||||
@@ -118,6 +120,8 @@ struct infra_cache {
|
||||
int lame_ttl;
|
||||
/** infra lame cache max memory per host, in bytes */
|
||||
size_t max_lame_size;
|
||||
/** jostle timeout in msec */
|
||||
size_t jostle;
|
||||
};
|
||||
|
||||
/** infra host cache default hash lookup size */
|
||||
@@ -138,6 +142,10 @@ struct infra_cache* infra_create(struct config_file* cfg);
|
||||
*/
|
||||
void infra_delete(struct infra_cache* infra);
|
||||
|
||||
/** explicitly delete an infra host element */
|
||||
void infra_remove_host(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Adjust infra cache to use updated configuration settings.
|
||||
* This may clean the cache. Operates a bit like realloc.
|
||||
@@ -167,6 +175,8 @@ struct infra_host_data* infra_lookup_host(struct infra_cache* infra,
|
||||
* 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.
|
||||
@@ -249,6 +259,7 @@ void infra_update_tcp_works(struct infra_cache* infra,
|
||||
* @param addr: host address.
|
||||
* @param addrlen: length of addr.
|
||||
* @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.
|
||||
*/
|
||||
@@ -258,6 +269,7 @@ int infra_edns_update(struct infra_cache* infra,
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -278,6 +290,21 @@ int infra_get_lame_rtt(struct infra_cache* infra,
|
||||
uint8_t* name, size_t namelen, uint16_t qtype,
|
||||
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 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.
|
||||
* @return TTL the infra host element is valid for. If -1: not found in cache.
|
||||
* TTL -2: found but expired.
|
||||
*/
|
||||
int infra_get_host_rto(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct rtt_info* rtt, int* delay, uint32_t timenow);
|
||||
|
||||
/**
|
||||
* Get memory used by the infra cache.
|
||||
* @param infra: infrastructure cache.
|
||||
|
||||
+142
-58
@@ -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,7 @@ 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)
|
||||
socklen_t addrlen, int v6only, int* inuse, int* noproto, int rcv)
|
||||
{
|
||||
int s;
|
||||
#if defined(IPV6_USE_MIN_MTU)
|
||||
@@ -98,6 +99,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
#ifdef IPV6_MTU
|
||||
int mtu = IPV6_MIN_MTU;
|
||||
#endif
|
||||
#if !defined(SO_RCVBUFFORCE) && !defined(SO_RCVBUF)
|
||||
(void)rcv;
|
||||
#endif
|
||||
#ifndef IPV6_V6ONLY
|
||||
(void)v6only;
|
||||
#endif
|
||||
@@ -121,6 +125,64 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
*noproto = 0;
|
||||
return -1;
|
||||
}
|
||||
if(rcv) {
|
||||
#ifdef SO_RCVBUF
|
||||
int got;
|
||||
socklen_t slen = (socklen_t)sizeof(got);
|
||||
# ifdef SO_RCVBUFFORCE
|
||||
/* Linux specific: try to use root permission to override
|
||||
* system limits on rcvbuf. The limit is stored in
|
||||
* /proc/sys/net/core/rmem_max or sysctl net.core.rmem_max */
|
||||
if(setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void*)&rcv,
|
||||
(socklen_t)sizeof(rcv)) < 0) {
|
||||
if(errno != EPERM) {
|
||||
# ifndef USE_WINSOCK
|
||||
log_err("setsockopt(..., SO_RCVBUFFORCE, "
|
||||
"...) failed: %s", strerror(errno));
|
||||
close(s);
|
||||
# else
|
||||
log_err("setsockopt(..., SO_RCVBUFFORCE, "
|
||||
"...) failed: %s",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
closesocket(s);
|
||||
# endif
|
||||
*noproto = 0;
|
||||
*inuse = 0;
|
||||
return -1;
|
||||
}
|
||||
# endif /* SO_RCVBUFFORCE */
|
||||
if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv,
|
||||
(socklen_t)sizeof(rcv)) < 0) {
|
||||
# ifndef USE_WINSOCK
|
||||
log_err("setsockopt(..., SO_RCVBUF, "
|
||||
"...) failed: %s", strerror(errno));
|
||||
close(s);
|
||||
# else
|
||||
log_err("setsockopt(..., SO_RCVBUF, "
|
||||
"...) 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_RCVBUF, (void*)&got,
|
||||
&slen) >= 0 && got < rcv/2) {
|
||||
log_warn("so-rcvbuf %u was not granted. "
|
||||
"Got %u. To fix: start with "
|
||||
"root permissions(linux) or sysctl "
|
||||
"bigger net.core.rmem_max(linux) or "
|
||||
"kern.ipc.maxsockbuf(bsd) values.",
|
||||
(unsigned)rcv, (unsigned)got);
|
||||
}
|
||||
# ifdef SO_RCVBUFFORCE
|
||||
}
|
||||
# endif
|
||||
#endif /* SO_RCVBUF */
|
||||
}
|
||||
if(family == AF_INET6) {
|
||||
# if defined(IPV6_V6ONLY)
|
||||
if(v6only) {
|
||||
@@ -190,6 +252,25 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
return -1;
|
||||
}
|
||||
# endif /* IPv6 MTU */
|
||||
} else if(family == AF_INET) {
|
||||
# if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
|
||||
int action = IP_PMTUDISC_DONT;
|
||||
if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER,
|
||||
&action, (socklen_t)sizeof(action)) < 0) {
|
||||
log_err("setsockopt(..., IP_MTU_DISCOVER, "
|
||||
"IP_PMTUDISC_DONT...) failed: %s",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
# elif defined(IP_DONTFRAG)
|
||||
int off = 0;
|
||||
if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG,
|
||||
&off, (socklen_t)sizeof(off)) < 0) {
|
||||
log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
# endif /* IPv4 MTU */
|
||||
}
|
||||
if(bind(s, (struct sockaddr*)addr, addrlen) != 0) {
|
||||
*noproto = 0;
|
||||
@@ -313,7 +394,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)
|
||||
struct addrinfo *hints, int v6only, int* noip6, size_t rcv)
|
||||
{
|
||||
struct addrinfo *res = NULL;
|
||||
int r, s, inuse, noproto;
|
||||
@@ -339,8 +420,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);
|
||||
(struct sockaddr*)res->ai_addr,
|
||||
res->ai_addrlen, v6only, &inuse, &noproto, (int)rcv);
|
||||
if(s == -1 && inuse) {
|
||||
log_err("bind: address already in use");
|
||||
} else if(s == -1 && noproto && hints->ai_family == AF_INET6){
|
||||
@@ -356,6 +437,35 @@ make_sock(int stype, const char* ifname, const char* port,
|
||||
return s;
|
||||
}
|
||||
|
||||
/** 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)
|
||||
{
|
||||
char* s = strchr(ifname, '@');
|
||||
if(s) {
|
||||
/* override port with ifspec@port */
|
||||
char p[16];
|
||||
char newif[128];
|
||||
if((size_t)(s-ifname) >= sizeof(newif)) {
|
||||
log_err("ifname too long: %s", ifname);
|
||||
*noip6 = 0;
|
||||
return -1;
|
||||
}
|
||||
if(strlen(s+1) >= sizeof(p)) {
|
||||
log_err("portnumber too long: %s", ifname);
|
||||
*noip6 = 0;
|
||||
return -1;
|
||||
}
|
||||
strncpy(newif, ifname, sizeof(newif));
|
||||
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, ifname, port, hints, v6only, noip6, rcv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add port to open ports list.
|
||||
* @param list: list head. changed.
|
||||
@@ -381,7 +491,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;
|
||||
@@ -408,22 +518,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 */
|
||||
@@ -442,18 +552,20 @@ set_recvpktinfo(int s, int family)
|
||||
* @param hints: for getaddrinfo. family and flags have to be set by caller.
|
||||
* @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
|
||||
* @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)
|
||||
struct addrinfo *hints, const char* port, struct listen_port** list,
|
||||
size_t rcv)
|
||||
{
|
||||
int s, noip6=0;
|
||||
if(!do_udp && !do_tcp)
|
||||
return 0;
|
||||
if(do_auto) {
|
||||
if((s = make_sock(SOCK_DGRAM, ifname, port, hints, 1,
|
||||
&noip6)) == -1) {
|
||||
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
|
||||
&noip6, rcv)) == -1) {
|
||||
if(noip6) {
|
||||
log_warn("IPv6 protocol not available");
|
||||
return 1;
|
||||
@@ -473,8 +585,8 @@ 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(SOCK_DGRAM, ifname, port, hints, 1,
|
||||
&noip6)) == -1) {
|
||||
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
|
||||
&noip6, rcv)) == -1) {
|
||||
if(noip6) {
|
||||
log_warn("IPv6 protocol not available");
|
||||
return 1;
|
||||
@@ -491,8 +603,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
}
|
||||
}
|
||||
if(do_tcp) {
|
||||
if((s = make_sock(SOCK_STREAM, ifname, port, hints, 1,
|
||||
&noip6)) == -1) {
|
||||
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
|
||||
&noip6, 0)) == -1) {
|
||||
if(noip6) {
|
||||
/*log_warn("IPv6 protocol not available");*/
|
||||
return 1;
|
||||
@@ -603,32 +715,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)
|
||||
{
|
||||
@@ -658,17 +744,13 @@ 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)) {
|
||||
&hints, portbuf, &list, cfg->socket_rcvbuf)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -677,7 +759,7 @@ 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)) {
|
||||
&hints, portbuf, &list, cfg->socket_rcvbuf)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -688,7 +770,8 @@ listening_ports_open(struct config_file* cfg)
|
||||
continue;
|
||||
hints.ai_family = AF_INET6;
|
||||
if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
|
||||
do_tcp, &hints, portbuf, &list)) {
|
||||
do_tcp, &hints, portbuf, &list,
|
||||
cfg->socket_rcvbuf)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -697,7 +780,8 @@ listening_ports_open(struct config_file* cfg)
|
||||
continue;
|
||||
hints.ai_family = AF_INET;
|
||||
if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
|
||||
do_tcp, &hints, portbuf, &list)) {
|
||||
do_tcp, &hints, portbuf, &list,
|
||||
cfg->socket_rcvbuf)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -130,25 +130,6 @@ 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);
|
||||
|
||||
/**
|
||||
* delete the listening structure
|
||||
* @param listen: listening structure.
|
||||
@@ -180,10 +161,11 @@ size_t listen_get_mem(struct listen_dnsport* listen);
|
||||
* @param inuse: on error, this is set true if the port was in use.
|
||||
* @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.
|
||||
* @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);
|
||||
socklen_t addrlen, int v6only, int* inuse, int* noproto, int rcv);
|
||||
|
||||
/**
|
||||
* Create and bind TCP listening socket
|
||||
|
||||
+31
-12
@@ -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;
|
||||
@@ -687,6 +689,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.") ||
|
||||
@@ -1038,10 +1042,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);
|
||||
}
|
||||
@@ -1141,6 +1145,19 @@ local_zones_answer(struct local_zones* zones, struct query_info* qinfo,
|
||||
return r;
|
||||
}
|
||||
|
||||
const char* local_zone_type2str(enum localzone_type t)
|
||||
{
|
||||
switch(t) {
|
||||
case local_zone_deny: return "deny";
|
||||
case local_zone_refuse: return "refuse";
|
||||
case local_zone_redirect: return "redirect";
|
||||
case local_zone_transparent: return "transparent";
|
||||
case local_zone_static: return "static";
|
||||
case local_zone_nodefault: return "nodefault";
|
||||
}
|
||||
return "badtyped";
|
||||
}
|
||||
|
||||
int local_zone_str2type(const char* type, enum localzone_type* t)
|
||||
{
|
||||
if(strcmp(type, "deny") == 0)
|
||||
@@ -1309,14 +1326,16 @@ void local_zones_del_data(struct local_zones* zones,
|
||||
|
||||
/* find the domain */
|
||||
d = lz_find_node(z, name, len, labs);
|
||||
/* no memory recycling for zone deletions ... */
|
||||
d->rrsets = NULL;
|
||||
/* did we delete the soa record ? */
|
||||
if(query_dname_compare(d->name, z->name) == 0)
|
||||
z->soa = NULL;
|
||||
if(d) {
|
||||
/* no memory recycling for zone deletions ... */
|
||||
d->rrsets = NULL;
|
||||
/* did we delete the soa record ? */
|
||||
if(query_dname_compare(d->name, z->name) == 0)
|
||||
z->soa = NULL;
|
||||
|
||||
/* cleanup the empty nonterminals for this name */
|
||||
del_empty_term(z, d, name, len, labs);
|
||||
/* cleanup the empty nonterminals for this name */
|
||||
del_empty_term(z, d, name, len, labs);
|
||||
}
|
||||
|
||||
lock_rw_unlock(&z->lock);
|
||||
}
|
||||
|
||||
@@ -149,7 +149,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
|
||||
@@ -233,6 +233,14 @@ int local_zones_answer(struct local_zones* zones, struct query_info* qinfo,
|
||||
*/
|
||||
int local_zone_str2type(const char* str, enum localzone_type* t);
|
||||
|
||||
/**
|
||||
* Print localzone type to a string. Pointer to a constant string.
|
||||
*
|
||||
* @param t: local zone type.
|
||||
* @return constant string that describes type.
|
||||
*/
|
||||
const char* local_zone_type2str(enum localzone_type t);
|
||||
|
||||
/**
|
||||
* Find zone that with exactly given name, class.
|
||||
* User must lock the tree or result zone.
|
||||
|
||||
+121
-29
@@ -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"
|
||||
@@ -61,9 +62,9 @@ static void
|
||||
timeval_subtract(struct timeval* d, const struct timeval* end, const struct timeval* start)
|
||||
{
|
||||
#ifndef S_SPLINT_S
|
||||
time_t end_usec = end->tv_usec;;
|
||||
time_t end_usec = end->tv_usec;
|
||||
d->tv_sec = end->tv_sec - start->tv_sec;
|
||||
while(end_usec < start->tv_usec) {
|
||||
if(end_usec < start->tv_usec) {
|
||||
end_usec += 1000000;
|
||||
d->tv_sec--;
|
||||
}
|
||||
@@ -78,7 +79,7 @@ timeval_add(struct timeval* d, const struct timeval* add)
|
||||
#ifndef S_SPLINT_S
|
||||
d->tv_sec += add->tv_sec;
|
||||
d->tv_usec += add->tv_usec;
|
||||
while(d->tv_usec > 1000000 ) {
|
||||
if(d->tv_usec > 1000000 ) {
|
||||
d->tv_usec -= 1000000;
|
||||
d->tv_sec++;
|
||||
}
|
||||
@@ -233,7 +234,7 @@ mesh_delete_all(struct mesh_area* mesh)
|
||||
|
||||
int mesh_make_new_space(struct mesh_area* mesh)
|
||||
{
|
||||
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;
|
||||
@@ -282,11 +283,22 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
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) {
|
||||
struct rbnode_t* n;
|
||||
s = mesh_state_create(mesh->env,qinfo, qflags, 0);
|
||||
s = mesh_state_create(mesh->env, qinfo, qflags, 0);
|
||||
if(!s) {
|
||||
log_err("mesh_state_create: out of memory; SERVFAIL");
|
||||
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
@@ -354,7 +366,7 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
/* see if it already exists, if not, create one */
|
||||
if(!s) {
|
||||
struct rbnode_t* n;
|
||||
s = mesh_state_create(mesh->env,qinfo, qflags, 0);
|
||||
s = mesh_state_create(mesh->env, qinfo, qflags, 0);
|
||||
if(!s) {
|
||||
return 0;
|
||||
}
|
||||
@@ -388,6 +400,55 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
return 1;
|
||||
}
|
||||
|
||||
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 rbnode_t* n;
|
||||
/* already exists, and for a different purpose perhaps.
|
||||
* if mesh_no_list, keep it that way. */
|
||||
if(s) {
|
||||
/* make it ignore the cache from now on */
|
||||
if(!s->s.blacklist)
|
||||
sock_list_insert(&s->s.blacklist, NULL, 0, s->s.region);
|
||||
if(s->s.prefetch_leeway < leeway)
|
||||
s->s.prefetch_leeway = leeway;
|
||||
return;
|
||||
}
|
||||
if(!mesh_make_new_space(mesh)) {
|
||||
verbose(VERB_ALGO, "Too many queries. dropped prefetch.");
|
||||
mesh->stats_dropped ++;
|
||||
return;
|
||||
}
|
||||
s = mesh_state_create(mesh->env, qinfo, qflags, 0);
|
||||
if(!s) {
|
||||
log_err("prefetch mesh_state_create: out of memory");
|
||||
return;
|
||||
}
|
||||
n = rbtree_insert(&mesh->all, &s->node);
|
||||
log_assert(n != NULL);
|
||||
/* set detached (it is now) */
|
||||
mesh->num_detached_states++;
|
||||
/* make it ignore the cache */
|
||||
sock_list_insert(&s->s.blacklist, NULL, 0, s->s.region);
|
||||
s->s.prefetch_leeway = leeway;
|
||||
|
||||
if(s->list_select == mesh_no_list) {
|
||||
/* move to either the forever or the jostle_list */
|
||||
if(mesh->num_forever_states < mesh->max_forever_states) {
|
||||
mesh->num_forever_states ++;
|
||||
mesh_list_insert(s, &mesh->forever_first,
|
||||
&mesh->forever_last);
|
||||
s->list_select = mesh_forever_list;
|
||||
} else {
|
||||
mesh_list_insert(s, &mesh->jostle_first,
|
||||
&mesh->jostle_last);
|
||||
s->list_select = mesh_jostle_list;
|
||||
}
|
||||
}
|
||||
mesh_run(mesh, s, module_event_new, NULL);
|
||||
}
|
||||
|
||||
void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e,
|
||||
struct comm_reply* reply, int what)
|
||||
{
|
||||
@@ -447,6 +508,7 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
|
||||
mstate->s.return_rcode = LDNS_RCODE_NOERROR;
|
||||
mstate->s.env = env;
|
||||
mstate->s.mesh_info = mstate;
|
||||
mstate->s.prefetch_leeway = 0;
|
||||
/* init modules */
|
||||
for(i=0; i<env->mesh->mods.num; i++) {
|
||||
mstate->s.minfo[i] = NULL;
|
||||
@@ -472,7 +534,7 @@ mesh_state_cleanup(struct mesh_state* mstate)
|
||||
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);
|
||||
sec_status_unchecked, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -525,6 +587,36 @@ 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;
|
||||
@@ -551,6 +643,10 @@ 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);
|
||||
if(mesh_detect_cycle_found(qstate, sub)) {
|
||||
verbose(VERB_ALGO, "attach failed, cycle detected");
|
||||
return 0;
|
||||
}
|
||||
if(!sub) {
|
||||
struct rbnode_t* n;
|
||||
/* create a new one */
|
||||
@@ -615,6 +711,7 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
struct mesh_cb* r)
|
||||
{
|
||||
int secure;
|
||||
char* reason = NULL;
|
||||
/* bogus messages are not made into servfail, sec_status passed
|
||||
* to the callback function */
|
||||
if(rep && rep->security == sec_status_secure)
|
||||
@@ -622,10 +719,14 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
else secure = 0;
|
||||
if(!rep && rcode == LDNS_RCODE_NOERROR)
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
if(!rcode && rep->security == sec_status_bogus) {
|
||||
if(!(reason = errinf_to_str(&m->s)))
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
}
|
||||
/* send the reply */
|
||||
if(rcode) {
|
||||
fptr_ok(fptr_whitelist_mesh_cb(r->cb));
|
||||
(*r->cb)(r->cb_arg, rcode, r->buf, sec_status_unchecked);
|
||||
(*r->cb)(r->cb_arg, rcode, r->buf, sec_status_unchecked, NULL);
|
||||
} else {
|
||||
size_t udp_size = r->edns.udp_size;
|
||||
ldns_buffer_clear(r->buf);
|
||||
@@ -640,13 +741,14 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
{
|
||||
fptr_ok(fptr_whitelist_mesh_cb(r->cb));
|
||||
(*r->cb)(r->cb_arg, LDNS_RCODE_SERVFAIL, r->buf,
|
||||
sec_status_unchecked);
|
||||
sec_status_unchecked, NULL);
|
||||
} else {
|
||||
fptr_ok(fptr_whitelist_mesh_cb(r->cb));
|
||||
(*r->cb)(r->cb_arg, LDNS_RCODE_NOERROR, r->buf,
|
||||
rep->security);
|
||||
rep->security, reason);
|
||||
}
|
||||
}
|
||||
free(reason);
|
||||
m->s.env->mesh->num_reply_addrs--;
|
||||
}
|
||||
|
||||
@@ -851,7 +953,7 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
|
||||
&mstate->s.qinfo);
|
||||
s = module_error;
|
||||
}
|
||||
if(s == module_wait_module) {
|
||||
if(s == module_wait_module || s == module_restart_next) {
|
||||
/* start next module */
|
||||
mstate->s.curmod++;
|
||||
if(mesh->mods.num == mstate->s.curmod) {
|
||||
@@ -861,6 +963,13 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
|
||||
mstate->s.curmod--;
|
||||
return mesh_continue(mesh, mstate, module_error, ev);
|
||||
}
|
||||
if(s == module_restart_next) {
|
||||
fptr_ok(fptr_whitelist_mod_clear(
|
||||
mesh->mods.mod[mstate->s.curmod]->clear));
|
||||
(*mesh->mods.mod[mstate->s.curmod]->clear)
|
||||
(&mstate->s, mstate->s.curmod);
|
||||
mstate->s.minfo[mstate->s.curmod] = NULL;
|
||||
}
|
||||
*ev = module_event_pass;
|
||||
return 1;
|
||||
}
|
||||
@@ -993,30 +1102,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,
|
||||
|
||||
+29
-5
@@ -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
|
||||
@@ -206,9 +213,10 @@ struct mesh_reply {
|
||||
|
||||
/**
|
||||
* Mesh result callback func.
|
||||
* called as func(cb_arg, rcode, buffer_with_reply, security);
|
||||
* */
|
||||
typedef void (*mesh_cb_func_t)(void*, int, ldns_buffer*, enum sec_status);
|
||||
* called as func(cb_arg, rcode, buffer_with_reply, security, why_bogus);
|
||||
*/
|
||||
typedef void (*mesh_cb_func_t)(void*, int, ldns_buffer*, enum sec_status,
|
||||
char*);
|
||||
|
||||
/**
|
||||
* Callback to result routine
|
||||
@@ -285,6 +293,18 @@ int 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);
|
||||
|
||||
/**
|
||||
* New prefetch message. Create new query state if needed.
|
||||
* Will run the mesh area queries to process if a new query state is created.
|
||||
*
|
||||
* @param mesh: the mesh.
|
||||
* @param qinfo: query from client.
|
||||
* @param qflags: flags from client query.
|
||||
* @param leeway: TTL leeway what to expire earlier for this update.
|
||||
*/
|
||||
void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, uint32_t leeway);
|
||||
|
||||
/**
|
||||
* Handle new event from the wire. A serviced query has returned.
|
||||
* The query state will be made runnable, and the mesh_area will process
|
||||
@@ -313,6 +333,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:
|
||||
@@ -490,13 +512,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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
+197
-60
@@ -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"
|
||||
@@ -53,9 +59,6 @@
|
||||
#include "util/random.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
@@ -127,6 +130,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 +215,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
|
||||
@@ -470,7 +535,7 @@ 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)
|
||||
void (*unwanted_action)(void*), void* unwanted_param, int do_udp)
|
||||
{
|
||||
struct outside_network* outnet = (struct outside_network*)
|
||||
calloc(1, sizeof(struct outside_network));
|
||||
@@ -490,6 +555,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
|
||||
outnet->unwanted_action = unwanted_action;
|
||||
outnet->unwanted_param = unwanted_param;
|
||||
outnet->use_caps_for_id = use_caps_for_id;
|
||||
outnet->do_udp = do_udp;
|
||||
if(numavailports == 0) {
|
||||
log_err("no outgoing ports available");
|
||||
outside_network_delete(outnet);
|
||||
@@ -754,12 +820,12 @@ 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);
|
||||
(struct sockaddr*)addr, addrlen, 1, inuse, &noproto, 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);
|
||||
(struct sockaddr*)addr, addrlen, 1, inuse, &noproto, 0);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
@@ -806,9 +872,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];
|
||||
@@ -892,8 +958,10 @@ randomize_and_send_udp(struct outside_network* outnet, struct pending* pend,
|
||||
|
||||
/* system calls to set timeout after sending UDP to make roundtrip
|
||||
smaller. */
|
||||
#ifndef S_SPLINT_S
|
||||
tv.tv_sec = timeout/1000;
|
||||
tv.tv_usec = (timeout%1000)*1000;
|
||||
#endif
|
||||
comm_timer_set(pend->timer, &tv);
|
||||
return 1;
|
||||
}
|
||||
@@ -1009,8 +1077,10 @@ pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet,
|
||||
w->outnet = outnet;
|
||||
w->cb = callback;
|
||||
w->cb_arg = callback_arg;
|
||||
#ifndef S_SPLINT_S
|
||||
tv.tv_sec = timeout;
|
||||
tv.tv_usec = 0;
|
||||
#endif
|
||||
comm_timer_set(w->timer, &tv);
|
||||
if(pend) {
|
||||
/* we have a buffer available right now */
|
||||
@@ -1070,7 +1140,7 @@ 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, struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
{
|
||||
struct serviced_query* sq = (struct serviced_query*)malloc(sizeof(*sq));
|
||||
rbnode_t* ins;
|
||||
@@ -1084,6 +1154,7 @@ serviced_create(struct outside_network* outnet, ldns_buffer* buff, int dnssec,
|
||||
}
|
||||
sq->qbuflen = ldns_buffer_limit(buff);
|
||||
sq->dnssec = dnssec;
|
||||
sq->want_dnssec = want_dnssec;
|
||||
memcpy(&sq->addr, addr, addrlen);
|
||||
sq->addrlen = addrlen;
|
||||
sq->outnet = outnet;
|
||||
@@ -1125,7 +1196,8 @@ 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_fallback) {
|
||||
struct pending* p = (struct pending*)sq->pending;
|
||||
if(p->pc)
|
||||
portcomm_loweruse(sq->outnet, p->pc);
|
||||
@@ -1233,14 +1305,15 @@ serviced_udp_send(struct serviced_query* sq, ldns_buffer* buff)
|
||||
if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen, now, &vs,
|
||||
&edns_lame_known, &rtt))
|
||||
return 0;
|
||||
sq->last_rtt = rtt;
|
||||
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;
|
||||
@@ -1250,7 +1323,6 @@ serviced_udp_send(struct serviced_query* sq, ldns_buffer* buff)
|
||||
}
|
||||
serviced_encode(sq, buff, sq->status == serviced_query_UDP_EDNS);
|
||||
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,
|
||||
@@ -1402,12 +1474,25 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
|
||||
(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,
|
||||
/* 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, -1, *sq->outnet->now_secs))
|
||||
log_err("Out of memory caching no edns for host");
|
||||
sq->status = serviced_query_TCP;
|
||||
serviced_tcp_initiate(sq->outnet, sq, c->buffer);
|
||||
return 0;
|
||||
}
|
||||
/* insert address into reply info */
|
||||
if(!rep) {
|
||||
@@ -1425,6 +1510,8 @@ static void
|
||||
serviced_tcp_initiate(struct outside_network* outnet,
|
||||
struct serviced_query* sq, ldns_buffer* buff)
|
||||
{
|
||||
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->pending = pending_tcp_query(outnet, buff, &sq->addr,
|
||||
sq->addrlen, TCP_AUTH_QUERY_TIMEOUT, serviced_tcp_callback,
|
||||
@@ -1437,6 +1524,25 @@ serviced_tcp_initiate(struct outside_network* outnet,
|
||||
}
|
||||
}
|
||||
|
||||
/** Send serviced query over TCP return false on initial failure */
|
||||
static int
|
||||
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))
|
||||
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->pending = pending_tcp_query(sq->outnet, buff, &sq->addr,
|
||||
sq->addrlen, TCP_AUTH_QUERY_TIMEOUT, serviced_tcp_callback,
|
||||
sq);
|
||||
return sq->pending != NULL;
|
||||
}
|
||||
|
||||
int
|
||||
serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
struct comm_reply* rep)
|
||||
@@ -1450,11 +1556,9 @@ 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;
|
||||
}
|
||||
sq->retry++;
|
||||
@@ -1476,45 +1580,36 @@ 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
|
||||
&& (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 */
|
||||
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,
|
||||
/* only store noEDNS in cache if domain is noDNSSEC */
|
||||
if(!sq->want_dnssec)
|
||||
if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
-1, (uint32_t)now.tv_sec)) {
|
||||
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 */
|
||||
if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
@@ -1522,19 +1617,49 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
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)
|
||||
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;
|
||||
}
|
||||
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 = (now.tv_sec - sq->last_sent_time.tv_sec)*1000
|
||||
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 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))
|
||||
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_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;
|
||||
}
|
||||
@@ -1555,10 +1680,10 @@ callback_list_find(struct serviced_query* sq, void* cb_arg,
|
||||
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,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
comm_point_callback_t* callback, void* callback_arg,
|
||||
ldns_buffer* buff, int (*arg_compare)(void*,void*))
|
||||
{
|
||||
struct serviced_query* sq;
|
||||
struct service_callback* cb;
|
||||
@@ -1574,18 +1699,29 @@ outnet_serviced_query(struct outside_network* outnet,
|
||||
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,
|
||||
addr, addrlen);
|
||||
if(!sq) {
|
||||
free(cb);
|
||||
return NULL;
|
||||
}
|
||||
/* perform first network action */
|
||||
if(!serviced_udp_send(sq, buff)) {
|
||||
(void)rbtree_delete(outnet->serviced, sq);
|
||||
free(sq->qbuf);
|
||||
free(sq);
|
||||
free(cb);
|
||||
return NULL;
|
||||
if(outnet->do_udp) {
|
||||
if(!serviced_udp_send(sq, buff)) {
|
||||
(void)rbtree_delete(outnet->serviced, sq);
|
||||
free(sq->qbuf);
|
||||
free(sq);
|
||||
free(cb);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if(!serviced_tcp_send(sq, buff)) {
|
||||
(void)rbtree_delete(outnet->serviced, sq);
|
||||
free(sq->qbuf);
|
||||
free(sq);
|
||||
free(cb);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* add callback to list of callbacks */
|
||||
@@ -1716,7 +1852,8 @@ 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_fallback) {
|
||||
s += sizeof(struct pending);
|
||||
s += comm_timer_get_mem(NULL);
|
||||
} else {
|
||||
|
||||
@@ -92,6 +92,8 @@ struct outside_network {
|
||||
/** linked list of available commpoints, unused file descriptors,
|
||||
* for use as outgoing UDP ports. cp.fd=-1 in them. */
|
||||
struct port_comm* unused_fds;
|
||||
/** if udp is done */
|
||||
int do_udp;
|
||||
|
||||
/** array of outgoing IP4 interfaces */
|
||||
struct port_if* ip4_ifs;
|
||||
@@ -289,6 +291,8 @@ 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;
|
||||
/** where to send it */
|
||||
struct sockaddr_storage addr;
|
||||
/** length of addr field in use. */
|
||||
@@ -306,7 +310,11 @@ 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
|
||||
}
|
||||
/** variable with current status */
|
||||
status;
|
||||
@@ -347,6 +355,7 @@ struct serviced_query {
|
||||
* @param unwanted_threshold: when to take defensive action.
|
||||
* @param unwanted_action: the action to take.
|
||||
* @param unwanted_param: user parameter to action.
|
||||
* @param do_udp: if udp is done.
|
||||
* @return: the new structure (with no pending answers) or NULL on error.
|
||||
*/
|
||||
struct outside_network* outside_network_create(struct comm_base* base,
|
||||
@@ -354,7 +363,7 @@ 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);
|
||||
void (*unwanted_action)(void*), void* unwanted_param, int do_udp);
|
||||
|
||||
/**
|
||||
* Delete outside_network structure.
|
||||
@@ -424,6 +433,8 @@ 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 callback: callback function.
|
||||
* @param callback_arg: user argument to callback function.
|
||||
* @param addr: to which server to send the query.
|
||||
@@ -436,10 +447,10 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
|
||||
*/
|
||||
struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
|
||||
uint16_t flags, int dnssec, 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,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
comm_point_callback_t* callback, void* callback_arg,
|
||||
ldns_buffer* buff, int (*arg_compare)(void*,void*));
|
||||
|
||||
/**
|
||||
* Remove service query callback.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user