mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
Compare commits
1229
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 | ||
|
|
82f83d8d06 | ||
|
|
fa842c30de | ||
|
|
506af05011 | ||
|
|
f644c06516 | ||
|
|
9755c94372 | ||
|
|
f0138c1cca | ||
|
|
374a7f45c2 | ||
|
|
f3b66c177b | ||
|
|
d535e6919e | ||
|
|
0c7b289051 | ||
|
|
5decb468c2 | ||
|
|
5e90d568eb | ||
|
|
9e8a5100ad | ||
|
|
1dc1ffabb4 | ||
|
|
c299e49384 | ||
|
|
8595d94e0f | ||
|
|
bfceac5b2e | ||
|
|
b794eb84ac | ||
|
|
1cf8bdae51 | ||
|
|
1bc4092127 | ||
|
|
1e97b85e45 | ||
|
|
edae0ad954 | ||
|
|
d453b4a43b | ||
|
|
7bd415ffdd | ||
|
|
d232dbd4a5 | ||
|
|
373758092f | ||
|
|
b6406cae1e | ||
|
|
298aff3ad2 | ||
|
|
efee0803d0 | ||
|
|
ec30ae3ca6 | ||
|
|
4ead61eb63 | ||
|
|
206a6bb539 | ||
|
|
fb5fa2bdb1 | ||
|
|
8b2f5dcaf0 | ||
|
|
4d97a3a400 | ||
|
|
368dc659ea | ||
|
|
e49e0539d8 | ||
|
|
aec8f4644f | ||
|
|
6f745bc49e | ||
|
|
ef564b5a29 | ||
|
|
c1b2364d1d | ||
|
|
790fe91662 | ||
|
|
819f9d817a | ||
|
|
e0bc4f2c97 | ||
|
|
efcb61fb22 | ||
|
|
d94c548dab | ||
|
|
a18c4eaebc | ||
|
|
e92fd4ff33 | ||
|
|
7bd75483e1 | ||
|
|
573fd6652b | ||
|
|
13d2817b62 | ||
|
|
f39e5fe3a8 | ||
|
|
a569062627 | ||
|
|
a40ec4b935 | ||
|
|
427ddba6d7 | ||
|
|
b757b29910 | ||
|
|
3898abde02 | ||
|
|
8466ac7e7f | ||
|
|
80f6ed2ff0 | ||
|
|
19d72a41cb | ||
|
|
07411c16a9 | ||
|
|
5ca6d8c50b | ||
|
|
16e920f416 | ||
|
|
89f0fd7252 | ||
|
|
a40ec010be | ||
|
|
1b8519e619 | ||
|
|
add0079981 | ||
|
|
2c56564e4e | ||
|
|
baaaae857a | ||
|
|
b6099d5f55 | ||
|
|
8c36960c29 | ||
|
|
3c5c0b2727 | ||
|
|
6dd6542f04 | ||
|
|
6451748967 | ||
|
|
b2ff49e4c4 | ||
|
|
38ec4f4777 | ||
|
|
413d579e58 | ||
|
|
3494191250 | ||
|
|
4b449309e5 | ||
|
|
71b6537666 | ||
|
|
886721c060 | ||
|
|
cdb2726e68 | ||
|
|
caaa90a200 | ||
|
|
5e2189bb35 | ||
|
|
7758098250 | ||
|
|
b86b9f7fdc | ||
|
|
daf63c7e89 | ||
|
|
578c1632ce | ||
|
|
37f403955b | ||
|
|
dd42c84b5e | ||
|
|
ffe442608c | ||
|
|
21389820a7 | ||
|
|
1562a13332 | ||
|
|
ea0148caf8 | ||
|
|
8cc8261947 | ||
|
|
7c2813eb82 | ||
|
|
81023e116d | ||
|
|
5cacd20a6e | ||
|
|
1aedf47ebe | ||
|
|
d75777ec63 | ||
|
|
d1a27b6d34 | ||
|
|
dd7f5cc718 | ||
|
|
718e235a47 | ||
|
|
9f1ee24abb | ||
|
|
6a152952bf | ||
|
|
f3d98d17f4 | ||
|
|
9ea5b16bae | ||
|
|
f32d07786a | ||
|
|
7138a4cf42 | ||
|
|
53a026eb4e | ||
|
|
768c4b2643 | ||
|
|
3eda6e26ff | ||
|
|
54bd0fff06 | ||
|
|
4ad2eb2549 | ||
|
|
bfe96b89f0 | ||
|
|
3b386055c7 | ||
|
|
5a9dcd323d | ||
|
|
3ee3492095 | ||
|
|
1e1ac9900a | ||
|
|
397985b2c8 | ||
|
|
93f6117ab2 | ||
|
|
f46febcc97 | ||
|
|
d745581dbd | ||
|
|
62fca9e1fb | ||
|
|
ac9c3b84b1 | ||
|
|
49913a1c9e | ||
|
|
5445bf72ba | ||
|
|
1fa1c9d1b1 | ||
|
|
af102d24ce | ||
|
|
a5c428bb8d | ||
|
|
445f8a4e22 | ||
|
|
a5c76d0579 | ||
|
|
db94e389da | ||
|
|
c3bf9f1bb3 | ||
|
|
3322c9e141 | ||
|
|
2e20c86309 | ||
|
|
0b4fe963d5 | ||
|
|
7ad28caa41 | ||
|
|
c6da8de517 | ||
|
|
c1f4b92026 | ||
|
|
f9aeb8904d | ||
|
|
64e3db1f04 | ||
|
|
a12dcdcdc4 | ||
|
|
d369a1ac48 | ||
|
|
3a7f86982e | ||
|
|
6803b9461f | ||
|
|
868df9f584 | ||
|
|
7dcca025f4 | ||
|
|
e0cd16b38c | ||
|
|
ebd14d9f35 | ||
|
|
31ec67fcce | ||
|
|
11f11a5377 | ||
|
|
0799d77798 | ||
|
|
910167b38c | ||
|
|
60f4826ff7 | ||
|
|
a87d222547 | ||
|
|
25467d37e3 | ||
|
|
faf17d6e86 | ||
|
|
0f3e00e3a6 | ||
|
|
eaff1bdeb5 | ||
|
|
d8b8eabeac | ||
|
|
e5c414355e | ||
|
|
dbf9f42142 | ||
|
|
a30d1f9f20 | ||
|
|
ee8465d887 | ||
|
|
00170dfa41 | ||
|
|
912db8d277 | ||
|
|
d0c6177f44 | ||
|
|
5069af975f | ||
|
|
b0ef703c1b | ||
|
|
c154c6b7b4 | ||
|
|
2978e72596 | ||
|
|
6e9d768c6c | ||
|
|
d8392b01d3 | ||
|
|
f861f19843 | ||
|
|
97a73402fc | ||
|
|
41e589b08b | ||
|
|
cfd739e2eb | ||
|
|
bcd6fee1f4 | ||
|
|
6355d45e70 | ||
|
|
76c0cb3913 | ||
|
|
116e9d9d8d | ||
|
|
61135d1456 | ||
|
|
5f27e00a19 | ||
|
|
0d575036cb | ||
|
|
afe9d4bb67 | ||
|
|
159d59a3dc | ||
|
|
ac4535d4e5 | ||
|
|
8c2d5d42d9 | ||
|
|
363a4712b2 | ||
|
|
c02fd13138 | ||
|
|
e4c5af61c6 | ||
|
|
254e6ec34f | ||
|
|
47d7fd59ca | ||
|
|
6015524e34 | ||
|
|
80ef8e2f7e | ||
|
|
157c7cde0d | ||
|
|
1947f8cbb1 | ||
|
|
541ca65c9c | ||
|
|
53b51dbdef | ||
|
|
7de3900654 | ||
|
|
208e698306 | ||
|
|
eafa979e0f | ||
|
|
97a3830515 | ||
|
|
2bf8d9b4b2 | ||
|
|
a9754e0727 | ||
|
|
1811270c68 | ||
|
|
f30fc9133c | ||
|
|
7a2c1c8d47 | ||
|
|
fef17eadb6 | ||
|
|
840d7fd34f | ||
|
|
ae866b00a9 | ||
|
|
0acf55404c | ||
|
|
ffe0bd51d8 | ||
|
|
c2261b63f1 | ||
|
|
23ab46e3a5 | ||
|
|
84edc1428b | ||
|
|
e6fbf88b59 | ||
|
|
4b2d6d20af | ||
|
|
f6b2f66311 | ||
|
|
b67ed83149 | ||
|
|
ce71720093 | ||
|
|
8b31d0b2e0 | ||
|
|
cf068986ff | ||
|
|
c699ba2c40 | ||
|
|
340eb440da | ||
|
|
a2dcd9c019 | ||
|
|
dfef08c21f | ||
|
|
df8005ff3c | ||
|
|
8148211e53 | ||
|
|
ca09b7014b | ||
|
|
e5a5749603 | ||
|
|
95f5b577d4 | ||
|
|
205f6d1afc | ||
|
|
cf64f7ae9e | ||
|
|
5f6eb6d58e | ||
|
|
5c0e815e73 | ||
|
|
b182b66e0e | ||
|
|
b58159d34b | ||
|
|
36b3f6e254 | ||
|
|
e00e0ddd2f | ||
|
|
e0a3873245 | ||
|
|
81d095149c | ||
|
|
63d3cb7ff4 | ||
|
|
0007337afe | ||
|
|
c53328dd07 | ||
|
|
cb925371ef | ||
|
|
fb436db87a | ||
|
|
2b873f1b57 | ||
|
|
2705aaaad9 | ||
|
|
00fe7f1b87 | ||
|
|
a63515ba51 | ||
|
|
46a9e9cba4 | ||
|
|
b22145d504 | ||
|
|
6e0d34659b | ||
|
|
80fa6c037a | ||
|
|
af9c45effc | ||
|
|
78600ddee1 | ||
|
|
dfcbd8cb48 | ||
|
|
b59ec4d4d3 | ||
|
|
eb408dcbc8 | ||
|
|
87603429a1 | ||
|
|
cc6375e909 | ||
|
|
d1e812a4af | ||
|
|
7ac31bc1d5 | ||
|
|
37c3bef544 | ||
|
|
7ca106cc8c | ||
|
|
45abfa8720 | ||
|
|
ce2067ec6b | ||
|
|
0b04be414e | ||
|
|
c90fd40a5e | ||
|
|
bea2b17277 | ||
|
|
dee84257a1 | ||
|
|
b33f5f66ec | ||
|
|
a46c9197c4 | ||
|
|
bfc64ade3c | ||
|
|
900142fb79 | ||
|
|
5aa65f431b | ||
|
|
f8655d2f5b | ||
|
|
a3ff369cfd | ||
|
|
c76429ab57 | ||
|
|
0a9116f856 | ||
|
|
9f4a9249c6 | ||
|
|
8b860e8f12 | ||
|
|
c41e1a09ab | ||
|
|
59c1ec5a95 | ||
|
|
0b39c4232f | ||
|
|
bcb13a174b | ||
|
|
d525f6ab69 | ||
|
|
f89c4c4774 | ||
|
|
5326670faf | ||
|
|
244a09bfa3 | ||
|
|
2b7969bc84 | ||
|
|
f3d116387d | ||
|
|
e6c5255466 | ||
|
|
6e9d214816 | ||
|
|
c1ae463da5 | ||
|
|
865852d3f7 | ||
|
|
4eb2bdf2b1 | ||
|
|
062ad0eb69 | ||
|
|
ca89f7290c | ||
|
|
33ae9fd843 | ||
|
|
4c76f1c003 | ||
|
|
ccdc0e3c53 | ||
|
|
9cb69874f6 | ||
|
|
12aae4fd6f | ||
|
|
1bdf2b2b6a | ||
|
|
159c7e4d6c | ||
|
|
38d57b0f80 | ||
|
|
666b066bf6 | ||
|
|
d714dfe8d8 | ||
|
|
340a6185d2 | ||
|
|
d00c045084 | ||
|
|
d090698555 | ||
|
|
11f61b6b26 | ||
|
|
4b00c5f76b | ||
|
|
31ffc5a6a9 | ||
|
|
aa1b565b41 | ||
|
|
3d3b875a70 | ||
|
|
3d42b1fffa | ||
|
|
3e8ccb027f | ||
|
|
05643589cf | ||
|
|
b616c4f833 | ||
|
|
cb4985f527 | ||
|
|
098f932df8 | ||
|
|
4ac7881829 | ||
|
|
bcf49eaf96 | ||
|
|
9e96c6e3aa | ||
|
|
9a9f012352 | ||
|
|
386ff5debe | ||
|
|
d7ee842525 | ||
|
|
ea1f00ebad | ||
|
|
b1ed30d5f4 | ||
|
|
aa0f26e3fa | ||
|
|
9e21fb7fac | ||
|
|
8b919a3780 | ||
|
|
32f6afbb48 | ||
|
|
576fe7d4c8 | ||
|
|
27f450e8fa | ||
|
|
ecad71c519 | ||
|
|
8726449421 | ||
|
|
fcf7df71d6 | ||
|
|
4ea644f5a2 | ||
|
|
e25608d1be | ||
|
|
d1b2324429 | ||
|
|
be6bbb470a | ||
|
|
59e74885b7 | ||
|
|
2b6c544f69 | ||
|
|
632234b5e4 | ||
|
|
8bc54c4380 | ||
|
|
bbbbb3c533 | ||
|
|
75cf6d0f86 | ||
|
|
c653b8424b | ||
|
|
9548455690 | ||
|
|
bbf446f1a1 | ||
|
|
9fa2964d95 | ||
|
|
d0eb5cad47 | ||
|
|
e9d742c16d | ||
|
|
2547a0a9bb | ||
|
|
3bdd807610 | ||
|
|
7fc590cda5 | ||
|
|
9525cdb01b | ||
|
|
21a64ef247 | ||
|
|
5cfd778608 | ||
|
|
3973cd8f26 | ||
|
|
c12bf8692c | ||
|
|
327e1f4b10 | ||
|
|
847107403f | ||
|
|
d469081eda | ||
|
|
345e5e82d3 | ||
|
|
c6541a2def | ||
|
|
3708097870 | ||
|
|
69af0f10e9 | ||
|
|
747dc4e3ab | ||
|
|
6c7416128c | ||
|
|
515b892024 | ||
|
|
3af6fd7980 | ||
|
|
0d01be50bc | ||
|
|
8a32f9003b | ||
|
|
7bf176eeba | ||
|
|
c6af78bfd3 | ||
|
|
8eb31df3d0 | ||
|
|
7176710b7f | ||
|
|
1b1694a959 | ||
|
|
6cebdd2baf | ||
|
|
60d8b26ba1 | ||
|
|
83a017d3d1 | ||
|
|
18b09fe9c1 | ||
|
|
f59b1a96b1 | ||
|
|
8fb41f5c00 | ||
|
|
64959c8097 | ||
|
|
2a6846f30c | ||
|
|
00f301d35f | ||
|
|
f4ad52dffd | ||
|
|
a50b796a40 | ||
|
|
e5c52a7032 | ||
|
|
a0d9d48d8f | ||
|
|
1275afa125 | ||
|
|
371b9f08ef | ||
|
|
265c199445 | ||
|
|
bf659c8362 | ||
|
|
3dc4715109 | ||
|
|
b3dd2b5b98 | ||
|
|
5a1e91af35 | ||
|
|
a21136cf66 | ||
|
|
ebb63767cd | ||
|
|
07efa0f4ea | ||
|
|
1b8d87e202 | ||
|
|
1e37e00a27 | ||
|
|
628c970ecc | ||
|
|
f59885053a | ||
|
|
dbaa5194a6 | ||
|
|
5b7a514119 | ||
|
|
b6696c1342 | ||
|
|
bfb4e20f43 | ||
|
|
c73c662fce | ||
|
|
45afaf3e08 | ||
|
|
c04451cc58 | ||
|
|
6d721dd6bd | ||
|
|
408a0cfd31 | ||
|
|
939fabd809 | ||
|
|
3ddabf26f3 | ||
|
|
e2277ca9d1 | ||
|
|
351ef6e252 | ||
|
|
620c85ee32 | ||
|
|
7d242d400f | ||
|
|
cb659ab13b | ||
|
|
74909b66b4 | ||
|
|
896e4fea2a | ||
|
|
3385bcc255 | ||
|
|
5e1193f19d | ||
|
|
2e5c620f2c | ||
|
|
13a68aac89 | ||
|
|
d4fadf55a8 | ||
|
|
a2b261f8b2 | ||
|
|
556d5407e2 | ||
|
|
66dcc95a78 | ||
|
|
16734a0e04 | ||
|
|
91138fc32a | ||
|
|
cfceb6487d | ||
|
|
de0f903d37 | ||
|
|
67bec33e20 | ||
|
|
46e50e861f | ||
|
|
b479dfd33d | ||
|
|
cf4b56d883 | ||
|
|
c77be35670 | ||
|
|
763431c059 | ||
|
|
089261572a | ||
|
|
055ebe3d0b | ||
|
|
33bc592a83 | ||
|
|
076fb3bc53 | ||
|
|
10316f091f | ||
|
|
a14c4fa6e5 | ||
|
|
9d6df1964b | ||
|
|
897bb0c0e6 | ||
|
|
50b728aa08 | ||
|
|
25c1232d22 | ||
|
|
5814e0f5b6 | ||
|
|
3ca6d2e5a2 | ||
|
|
d4151219a2 | ||
|
|
e0d36e6561 | ||
|
|
7a1ba7785d | ||
|
|
370236cb65 | ||
|
|
91972c229d | ||
|
|
144978d633 | ||
|
|
62fc91f7f1 | ||
|
|
636f742ef0 | ||
|
|
f0b77ed022 | ||
|
|
0b3c133dd3 | ||
|
|
757eff88f5 | ||
|
|
3137c88a43 | ||
|
|
08e0563483 | ||
|
|
9157324788 | ||
|
|
f918da13d2 | ||
|
|
e8e30550df | ||
|
|
5dbc854a48 | ||
|
|
af57e5163d | ||
|
|
56b91454ba | ||
|
|
121cb15d67 | ||
|
|
265eedb0d3 | ||
|
|
26429c9457 | ||
|
|
72904a3366 | ||
|
|
ff1a7ec42e | ||
|
|
05cd134de9 | ||
|
|
960da40475 | ||
|
|
01cabbebc1 | ||
|
|
a66e16cb31 | ||
|
|
49d295755d | ||
|
|
b858018446 | ||
|
|
71a535a6f2 | ||
|
|
28a388b517 | ||
|
|
51d548563c | ||
|
|
21cd9936d8 | ||
|
|
e474ca2619 | ||
|
|
f809bfa145 | ||
|
|
4993c646e7 | ||
|
|
53fed5315c | ||
|
|
21895f6013 | ||
|
|
82ce090a35 | ||
|
|
fcbc34bd7f | ||
|
|
0720031ce0 | ||
|
|
23db41c292 | ||
|
|
d60b281055 | ||
|
|
a7cfe2bf65 | ||
|
|
d9cd60a41c | ||
|
|
a39a7704af | ||
|
|
a61d10f715 | ||
|
|
a4e4f424d1 | ||
|
|
bcec1a7593 | ||
|
|
38396319c7 | ||
|
|
ee874fab01 | ||
|
|
8cbb13f251 | ||
|
|
87fe8871b0 | ||
|
|
55f7bbc051 | ||
|
|
8e39c9c1cb | ||
|
|
7549bddfda | ||
|
|
44f5800da9 | ||
|
|
4cf4659a1d | ||
|
|
080d9d6540 | ||
|
|
77b79fde5d | ||
|
|
1e4e8cb68a | ||
|
|
0d8ce6f075 | ||
|
|
23ac4b02e3 | ||
|
|
8b93a85a7d | ||
|
|
4fe0d98ff4 | ||
|
|
a30026a7d8 | ||
|
|
9d068a12f5 | ||
|
|
144d35120c | ||
|
|
014cc821ba | ||
|
|
428524a8c8 | ||
|
|
2d49dd1494 | ||
|
|
995b01a9b7 | ||
|
|
665a98e47b | ||
|
|
fe106d38b2 | ||
|
|
75ac5e0fe0 | ||
|
|
d452ba59b5 | ||
|
|
c2c5b5522c | ||
|
|
34d75b1994 | ||
|
|
b61f24e8d3 | ||
|
|
072142cfa2 | ||
|
|
afe9b3e83c | ||
|
|
e4ef5a6156 | ||
|
|
ad041b9b8e | ||
|
|
45dd63d7c8 | ||
|
|
8ab18cb0f7 | ||
|
|
4e2ca85842 | ||
|
|
71d292580b | ||
|
|
d4b612e48b | ||
|
|
3d7ad2de3c | ||
|
|
24cb32dc6b | ||
|
|
4263f2a692 | ||
|
|
8459b5f55f | ||
|
|
6acc20abf4 | ||
|
|
498039108b | ||
|
|
d165625c4d | ||
|
|
af6cbba475 | ||
|
|
14f657933c | ||
|
|
1808c93e15 | ||
|
|
8078891a28 | ||
|
|
9a102eed3e | ||
|
|
02c493bd2d | ||
|
|
e2f8a1cb82 | ||
|
|
78a3c4e93d | ||
|
|
5eb7ff35ca | ||
|
|
4e1eab891b | ||
|
|
31a3035c60 | ||
|
|
aaab8cb352 | ||
|
|
fc0dcf12c3 | ||
|
|
4664c66f06 | ||
|
|
56f3cd33ec | ||
|
|
a64adc395f | ||
|
|
66f896ddbf | ||
|
|
ee5ee20071 | ||
|
|
fc3fc7a1f3 | ||
|
|
7be0e5b814 | ||
|
|
d4cfee1f00 | ||
|
|
f7059107b3 | ||
|
|
7a528cdf53 | ||
|
|
f90f5a2583 | ||
|
|
76ee7a352a | ||
|
|
148e8a69c9 | ||
|
|
39e4ba0e78 | ||
|
|
afda1a8bcc | ||
|
|
092a325270 | ||
|
|
cc6322ac0f | ||
|
|
2487f435f6 | ||
|
|
423e1a95a8 | ||
|
|
8ffff3c0a3 | ||
|
|
39e01091e7 | ||
|
|
8527bd4aff | ||
|
|
1dec098624 | ||
|
|
283f2a5edb | ||
|
|
0db56d8a0d | ||
|
|
065d2ad96f | ||
|
|
d7f2306161 | ||
|
|
66c8bd4ad1 | ||
|
|
725929734e | ||
|
|
60f51c1197 | ||
|
|
85abd17e90 | ||
|
|
ef69508048 | ||
|
|
97854e6bc5 | ||
|
|
01af814844 | ||
|
|
6de373e04c | ||
|
|
4a6d702edf | ||
|
|
0bad5716d4 | ||
|
|
55fe583de8 | ||
|
|
55aefcad19 | ||
|
|
fa07056f79 | ||
|
|
5990dde29b | ||
|
|
f9074eb440 | ||
|
|
54318b8c35 | ||
|
|
3bbe7a2e0b | ||
|
|
0f56fd3042 | ||
|
|
0d3ecd25df | ||
|
|
96d4800692 | ||
|
|
d13686227c |
+243
-85
@@ -2,10 +2,14 @@
|
||||
# See the file LICENSE for the license
|
||||
|
||||
debug_enabled=@debug_enabled@
|
||||
ifeq "$(QUIET)" ""
|
||||
ifeq ($(debug_enabled),yes)
|
||||
QUIET=yes
|
||||
LIBTOOLQUIET=yes
|
||||
else
|
||||
QUIET=no
|
||||
LIBTOOLQUIET=yes
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq "$(QUIET)" "yes"
|
||||
@@ -33,182 +37,306 @@ doxygen=@doxygen@
|
||||
libtool=@libtool@
|
||||
ldnsdir=@ldnsdir@
|
||||
staticexe=@staticexe@
|
||||
EXEEXT=@EXEEXT@
|
||||
configfile=@ub_conf_file@
|
||||
UNBOUND_RUN_DIR=@UNBOUND_RUN_DIR@
|
||||
CHECKLOCK_SRC=@CHECKLOCK_SRC@
|
||||
UB_ON_WINDOWS=@UB_ON_WINDOWS@
|
||||
WITH_PYTHONMODULE=@WITH_PYTHONMODULE@
|
||||
WITH_PYUNBOUND=@WITH_PYUNBOUND@
|
||||
PYTHON_SITE_PKG=@PYTHON_SITE_PKG@
|
||||
|
||||
SWIG=@SWIG@
|
||||
YACC=@YACC@
|
||||
LEX=@LEX@
|
||||
STRIP=@STRIP@
|
||||
CC=@CC@
|
||||
CPPFLAGS=-I$(srcdir) -I. @CPPFLAGS@ @DEFS@
|
||||
CPPFLAGS=-I. @CPPFLAGS@
|
||||
ifneq "$(srcdir)" "."
|
||||
CPPFLAGS:=-I$(srcdir) $(CPPFLAGS)
|
||||
endif
|
||||
CPPFLAGS:=$(strip $(CPPFLAGS))
|
||||
CFLAGS=@CFLAGS@
|
||||
LDFLAGS=@LDFLAGS@
|
||||
LIBS=@LIBS@
|
||||
LIBS=$(strip @LIBS@)
|
||||
LIBOBJS=@LIBOBJS@
|
||||
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@
|
||||
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
|
||||
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
|
||||
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"
|
||||
PYTHONMOD_SRC=$(srcdir)/pythonmod/*.c
|
||||
endif
|
||||
|
||||
COMMON_SRC=$(patsubst $(srcdir)/%,%, $(wildcard $(srcdir)/services/*.c \
|
||||
$(srcdir)/services/cache/*.c $(srcdir)/util/*.c \
|
||||
$(srcdir)/util/data/*.c $(srcdir)/util/storage/*.c \
|
||||
$(srcdir)/iterator/*.c $(srcdir)/validator/*.c)) \
|
||||
util/configparser.c util/configlexer.c testcode/checklocks.c
|
||||
COMMON_OBJ=$(addprefix $(BUILD),$(COMMON_SRC:.c=.o))
|
||||
COMPAT_OBJ=$(addprefix $(BUILD)compat/,$(LIBOBJS))
|
||||
$(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)) \
|
||||
testcode/readhex.c testcode/ldns-testpkts.c smallapp/worker_cb.c \
|
||||
$(COMMON_SRC)
|
||||
UNITTEST_OBJ=$(addprefix $(BUILD),$(UNITTEST_SRC:.c=.o)) $(COMPAT_OBJ)
|
||||
UNITTEST_OBJ=$(addprefix $(BUILD),$(UNITTEST_SRC:.c=.lo)) $(COMPAT_OBJ)
|
||||
DAEMON_SRC=$(patsubst $(srcdir)/%,%, $(wildcard $(srcdir)/daemon/*.c)) \
|
||||
$(COMMON_SRC)
|
||||
DAEMON_OBJ=$(addprefix $(BUILD),$(DAEMON_SRC:.c=.o)) $(COMPAT_OBJ)
|
||||
DAEMON_OBJ=$(addprefix $(BUILD),$(DAEMON_SRC:.c=.lo)) $(COMPAT_OBJ)
|
||||
CHECKCONF_SRC=smallapp/unbound-checkconf.c smallapp/worker_cb.c $(COMMON_SRC)
|
||||
CHECKCONF_OBJ=$(addprefix $(BUILD),$(CHECKCONF_SRC:.c=.o)) $(COMPAT_OBJ)
|
||||
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=.o)) $(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 \
|
||||
services/listen_dnsport.c services/outside_network.c, $(COMMON_SRC))
|
||||
TESTBOUND_OBJ=$(addprefix $(BUILD),$(TESTBOUND_SRC:.c=.o)) $(COMPAT_OBJ)
|
||||
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=.o)) $(COMPAT_OBJ)
|
||||
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=.o)) $(COMPAT_OBJ)
|
||||
PKTVIEW_OBJ=$(addprefix $(BUILD),$(PKTVIEW_SRC:.c=.lo)) $(COMPAT_OBJ)
|
||||
SIGNIT_SRC=testcode/signit.c smallapp/worker_cb.c $(COMMON_SRC)
|
||||
SIGNIT_OBJ=$(addprefix $(BUILD),$(SIGNIT_SRC:.c=.o)) $(COMPAT_OBJ)
|
||||
SIGNIT_OBJ=$(addprefix $(BUILD),$(SIGNIT_SRC:.c=.lo)) $(COMPAT_OBJ)
|
||||
MEMSTATS_SRC=testcode/memstats.c smallapp/worker_cb.c $(COMMON_SRC)
|
||||
MEMSTATS_OBJ=$(addprefix $(BUILD),$(MEMSTATS_SRC:.c=.o)) $(COMPAT_OBJ)
|
||||
ASYNCLOOK_SRC=testcode/asynclook.c
|
||||
ASYNCLOOK_OBJ=$(addprefix $(BUILD),$(ASYNCLOOK_SRC:.c=.o)) $(COMPAT_OBJ)
|
||||
MEMSTATS_OBJ=$(addprefix $(BUILD),$(MEMSTATS_SRC:.c=.lo)) $(COMPAT_OBJ)
|
||||
ASYNCLOOK_SRC=testcode/asynclook.c util/log.c util/locks.c
|
||||
ASYNCLOOK_OBJ=$(addprefix $(BUILD),$(ASYNCLOOK_SRC:.c=.lo)) $(COMPAT_OBJ)
|
||||
STREAMTCP_SRC=testcode/streamtcp.c smallapp/worker_cb.c $(COMMON_SRC)
|
||||
STREAMTCP_OBJ=$(addprefix $(BUILD),$(STREAMTCP_SRC:.c=.o)) $(COMPAT_OBJ)
|
||||
STREAMTCP_OBJ=$(addprefix $(BUILD),$(STREAMTCP_SRC:.c=.lo)) $(COMPAT_OBJ)
|
||||
PERF_SRC=testcode/perf.c smallapp/worker_cb.c $(COMMON_SRC)
|
||||
PERF_OBJ=$(addprefix $(BUILD),$(PERF_SRC:.c=.o)) $(COMPAT_OBJ)
|
||||
PERF_OBJ=$(addprefix $(BUILD),$(PERF_SRC:.c=.lo)) $(COMPAT_OBJ)
|
||||
DELAYER_SRC=testcode/delayer.c smallapp/worker_cb.c $(COMMON_SRC)
|
||||
DELAYER_OBJ=$(addprefix $(BUILD),$(DELAYER_SRC:.c=.o)) $(COMPAT_OBJ)
|
||||
DELAYER_OBJ=$(addprefix $(BUILD),$(DELAYER_SRC:.c=.lo)) $(COMPAT_OBJ)
|
||||
HARVEST_SRC=testcode/harvest.c
|
||||
HARVEST_OBJ=$(addprefix $(BUILD),$(HARVEST_SRC:.c=.o)) $(COMPAT_OBJ)
|
||||
HARVEST_OBJ=$(addprefix $(BUILD),$(HARVEST_SRC:.c=.lo)) $(COMPAT_OBJ)
|
||||
LIBUNBOUND_SRC=$(patsubst $(srcdir)/%,%, \
|
||||
$(wildcard $(srcdir)/libunbound/*.c) $(COMMON_SRC))
|
||||
LIBUNBOUND_OBJ=$(addprefix $(BUILD),$(LIBUNBOUND_SRC:.c=.o)) $(COMPAT_OBJ)
|
||||
LIBUNBOUND_OBJ=$(addprefix $(BUILD),$(LIBUNBOUND_SRC:.c=.lo)) $(COMPAT_OBJ)
|
||||
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) )
|
||||
ALL_OBJ=$(addprefix $(BUILD),$(ALL_SRC:.c=.o) \
|
||||
$(addprefix compat/,$(LIBOBJS))) $(COMPAT_OBJ)
|
||||
$(HARVEST_SRC) $(CONTROL_SRC) $(UBANCHOR_SRC) $(PETAL_SRC))
|
||||
ALL_OBJ=$(addprefix $(BUILD),$(ALL_SRC:.c=.lo) \
|
||||
$(addprefix compat/,$(LIBOBJS:.o=.lo))) $(COMPAT_OBJ)
|
||||
|
||||
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=$(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_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_WINAPP) \
|
||||
$(BUILD)winrc/rsrc_svcuninst.o
|
||||
ANCHORUPD_SRC=winrc/anchor-update.c
|
||||
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))
|
||||
|
||||
$(BUILD)%.o: $(srcdir)/%.rc $(srcdir)/config.h
|
||||
$(INFO) Resource $<
|
||||
@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$(WINDRES) $(CPPFLAGS) $< $@
|
||||
endif
|
||||
|
||||
COMPILE=$(LIBTOOL) --tag=CC --mode=compile $(CC) $(CPPFLAGS) $(CFLAGS)
|
||||
LINK=$(LIBTOOL) --tag=CC --mode=link $(CC) $(staticexe) $(RUNTIME_PATH) $(CFLAGS) $(LDFLAGS)
|
||||
LINK_LIB=$(LIBTOOL) --tag=CC --mode=link $(CC) $(RUNTIME_PATH) $(CFLAGS) $(LDFLAGS) $(staticexe) -version-number @LIBUNBOUND_CURRENT@:@LIBUNBOUND_REVISION@:@LIBUNBOUND_AGE@ -no-undefined
|
||||
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)%.o: $(srcdir)/%.c
|
||||
$(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
|
||||
all: $(COMMON_OBJ) unbound$(EXEEXT) unbound-checkconf$(EXEEXT) lib unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup $(WINAPPS)
|
||||
|
||||
tests: all unittest testbound lock-verify pktview signit memstats \
|
||||
asynclook streamtcp perf delayer harvest
|
||||
TEST_BIN=$(addsuffix $(EXEEXT),asynclook delayer harvest lock-verify \
|
||||
memstats perf petal pktview signit streamtcp testbound unittest)
|
||||
tests: all $(TEST_BIN)
|
||||
|
||||
test: tests
|
||||
bash testcode/do-tests.sh
|
||||
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:.o=.lo)) -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) -o $@ $(sort $(DAEMON_OBJ)) $(LIBS)
|
||||
$Q$(LINK_LIB) -export-symbols $(srcdir)/libunbound/ubsyms.def -o $@ $(sort $(LIBUNBOUND_OBJ)) -rpath $(libdir) $(LIBS)
|
||||
|
||||
unbound-checkconf: $(CHECKCONF_OBJ) $(ldnslib)
|
||||
unbound$(EXEEXT): $(DAEMON_OBJ) $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(DAEMON_OBJ)) -lssl $(LIBS)
|
||||
|
||||
unbound-checkconf$(EXEEXT): $(CHECKCONF_OBJ) $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(CHECKCONF_OBJ)) $(LIBS)
|
||||
|
||||
unbound-host: $(HOST_OBJ) libunbound.la $(ldnslib)
|
||||
unbound-control$(EXEEXT): $(CONTROL_OBJ) $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(CONTROL_OBJ)) -lssl $(LIBS)
|
||||
|
||||
unbound-host$(EXEEXT): $(HOST_OBJ) libunbound.la $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(HOST_OBJ)) -L. -L.libs -lunbound $(LIBS)
|
||||
|
||||
unittest: $(UNITTEST_OBJ) $(ldnslib)
|
||||
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$(EXEEXT): $(SVCUNINST_OBJ)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(SVCUNINST_OBJ)) $(LIBS)
|
||||
|
||||
anchor-update$(EXEEXT): $(ANCHORUPD_OBJ) libunbound.la $(ldnslib)
|
||||
$(INFO) Link $@
|
||||
$Q$(LINK) -o $@ $(sort $(ANCHORUPD_OBJ)) -L. -L.libs -lunbound $(LIBS)
|
||||
|
||||
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)) $(LIBS)
|
||||
$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
|
||||
|
||||
unbound-control-setup: $(srcdir)/smallapp/unbound-control-setup.sh
|
||||
$(INFO) Sed $@
|
||||
$Qsed -e 's:^DESTDIR=.*$$:DESTDIR=$(UNBOUND_RUN_DIR):' < $< > $@
|
||||
$Q-chmod +x $@
|
||||
|
||||
#testcode/ldns-testpkts.c: $(ldnsdir)/examples/ldns-testpkts.c \
|
||||
# $(ldnsdir)/examples/ldns-testpkts.h
|
||||
# cp $(ldnsdir)/examples/ldns-testpkts.c testcode/ldns-testpkts.c
|
||||
# cp $(ldnsdir)/examples/ldns-testpkts.h testcode/ldns-testpkts.h
|
||||
|
||||
ifeq "$(WITH_PYTHONMODULE)" "yes"
|
||||
$(srcdir)/pythonmod/pythonmod.c: pythonmod/interface.h
|
||||
%.h: $(srcdir)/%.i $(srcdir)/config.h
|
||||
@-if test ! -d $(dir $@); then $(INSTALL) -d $(patsubst %/,%,$(dir $@)); fi
|
||||
$(INFO) Swig $<
|
||||
$Q$(SWIG) $(CPPFLAGS) -o $@ -python $<
|
||||
endif
|
||||
|
||||
ifeq "$(WITH_PYUNBOUND)" "yes"
|
||||
libunbound/python/libunbound_wrap.c: $(srcdir)/libunbound/python/libunbound.i $(srcdir)/libunbound/unbound.h
|
||||
@-if test ! -d $(dir $@); then $(INSTALL) -d $(patsubst %/,%,$(dir $@)); fi
|
||||
$(INFO) Swig $<
|
||||
$Q$(SWIG) -python -o $@ $(CPPFLAGS) $<
|
||||
|
||||
all: _unbound.la
|
||||
_unbound.la: $(BUILD)libunbound/python/libunbound_wrap.lo libunbound.la
|
||||
$(INFO) Link $@
|
||||
$Q$(LIBTOOL) --tag=CC --mode=link $(strip $(CC) $(RUNTIME_PATH) $(CFLAGS) $(LDFLAGS) -module -version-number @LIBUNBOUND_CURRENT@:@LIBUNBOUND_REVISION@:@LIBUNBOUND_AGE@ -no-undefined) -o $@ $< -rpath $(PYTHON_SITE_PKG) L. -L.libs -lunbound $(LIBS)
|
||||
endif
|
||||
|
||||
util/config_file.c: util/configparser.h
|
||||
util/configlexer.c: $(srcdir)/util/configlexer.lex util/configparser.h
|
||||
$(INFO) Lex $<
|
||||
@@ -216,7 +344,8 @@ ifeq "$(strip $(LEX))" ":"
|
||||
$Qecho "rebuild lexer, but no lex program, skipped"
|
||||
else
|
||||
@-if test ! -d util; then $(INSTALL) -d util; fi
|
||||
$Qecho "#include \"util/configyyrename.h\"" > $@
|
||||
$Qecho "#include \"config.h\"" > $@
|
||||
$Qecho "#include \"util/configyyrename.h\"" >> $@
|
||||
$Q$(LEX) -t $< >> $@
|
||||
endif
|
||||
|
||||
@@ -227,13 +356,14 @@ util/configparser.c util/configparser.h: $(srcdir)/util/configparser.y
|
||||
|
||||
clean:
|
||||
rm -f *.o *.d *.lo *~ tags
|
||||
rm -f unbound unbound-checkconf unbound-host
|
||||
rm -rf autom4te.cache .libs build doc/html
|
||||
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
|
||||
rm -f config.status config.log config.h.in config.h
|
||||
rm -f configure config.sub config.guess ltmain.sh aclocal.m4 libtool
|
||||
rm -f util/configlexer.c util/configparser.c util/configparser.h
|
||||
rm -f $(TEST_BIN)
|
||||
if test -d ldns-src; then rm -rf ldns-src; fi
|
||||
rm -f Makefile
|
||||
|
||||
@@ -251,13 +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-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
|
||||
@@ -266,37 +404,59 @@ 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-host $(DESTDIR)$(sbindir)/unbound-host
|
||||
$(INSTALL) -c -m 644 $(srcdir)/doc/unbound.8 $(DESTDIR)$(mandir)/man8
|
||||
$(INSTALL) -c -m 644 $(srcdir)/doc/unbound-checkconf.8 $(DESTDIR)$(mandir)/man8
|
||||
$(INSTALL) -c -m 644 $(srcdir)/doc/unbound.conf.5 $(DESTDIR)$(mandir)/man5
|
||||
$(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
|
||||
endif
|
||||
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 $(srcdir)/doc/libunbound.3 $(DESTDIR)$(mandir)/man3
|
||||
if test ! -e $(DESTDIR)$(configfile); then $(INSTALL) -d `dirname $(DESTDIR)$(configfile)`; $(INSTALL) -c -m 644 $(srcdir)/doc/example.conf $(DESTDIR)$(configfile); fi
|
||||
$(INSTALL) -c -m 644 doc/libunbound.3 $(DESTDIR)$(mandir)/man3
|
||||
$(INSTALL) -c -m 755 unbound-control-setup $(DESTDIR)$(sbindir)/unbound-control-setup
|
||||
if test ! -e $(DESTDIR)$(configfile); then $(INSTALL) -d `dirname $(DESTDIR)$(configfile)`; $(INSTALL) -c -m 644 doc/example.conf $(DESTDIR)$(configfile); fi
|
||||
$(LIBTOOL) --mode=install cp $(srcdir)/libunbound/unbound.h $(DESTDIR)$(includedir)/unbound.h
|
||||
$(LIBTOOL) --mode=install cp libunbound.la $(DESTDIR)$(libdir)
|
||||
$(LIBTOOL) --mode=finish $(DESTDIR)$(libdir)
|
||||
|
||||
uninstall:
|
||||
rm -f -- $(DESTDIR)$(sbindir)/unbound $(DESTDIR)$(sbindir)/unbound-checkconf $(DESTDIR)$(sbindir)/unbound-host
|
||||
rm -f -- $(DESTDIR)$(mandir)/man8/unbound.8 $(DESTDIR)$(mandir)/man8/unbound-checkconf.8 $(DESTDIR)$(mandir)/man5/unbound.conf.5
|
||||
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
|
||||
ifeq "$(WITH_PYTHONMODULE)" "yes"
|
||||
rm -f -- $(DESTDIR)$(PYTHON_SITE_PKG)/unboundmodule.py
|
||||
endif
|
||||
ifeq "$(WITH_PYUNBOUND)" "yes"
|
||||
rm -f -- $(DESTDIR)$(PYTHON_SITE_PKG)/unbound.py
|
||||
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(PYTHON_SITE_PKG)/_unbound.la
|
||||
endif
|
||||
@echo
|
||||
@echo "You still need to remove "`dirname $(DESTDIR)$(configfile)`" , $(DESTDIR)$(configfile) by hand"
|
||||
|
||||
download_ldns:
|
||||
svn export https://www.nlnetlabs.nl/ldns/svn/trunk/makedist.sh ldns_makedist.sh
|
||||
./ldns_makedist.sh -s -d https://www.nlnetlabs.nl/ldns/svn/trunk
|
||||
mv ldns-*_pre_*.tar.gz ldns-src.tar.gz
|
||||
rm ldns-*_pre_*.tar.gz.sha1 ldns_makedist.sh
|
||||
svn export https://www.nlnetlabs.nl/svn/ldns/trunk/makedist.sh ldns_makedist.sh
|
||||
./ldns_makedist.sh -s -d https://www.nlnetlabs.nl/svn/ldns/trunk
|
||||
mv ldns-[0-9]*.tar.gz ldns-src.tar.gz
|
||||
rm ldns-*.tar.gz.sha1 ldns_makedist.sh
|
||||
|
||||
iana_update:
|
||||
curl -o port-numbers.tmp http://www.iana.org/assignments/port-numbers
|
||||
egrep -v "Unassigned|Reserved" port-numbers.tmp | awk '{ match($$0, "[0-9]+/udp"); if (RLENGTH > 0) print substr($$0, RSTART, RLENGTH - 4) ","}' | sort -nu > portslist.tmp
|
||||
awk '/Unassigned|Reserved/ {next;} { match($$0, "[0-9]+/udp"); if (RLENGTH > 0) print substr($$0, RSTART, RLENGTH - 4) ","}' port-numbers.tmp | sort -nu > portslist.tmp
|
||||
cat portslist.tmp > util/iana_ports.inc
|
||||
rm -f port-numbers.tmp portslist.tmp
|
||||
|
||||
@@ -306,14 +466,12 @@ $(BUILD)%.d: $(srcdir)/%.c
|
||||
@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$(SHELL) -ec '$(CC) -MM $(CPPFLAGS) $(CFLAGS) $< \
|
||||
| sed '\''s!\(.*\)\.o[ :]*!$(dir $@)\1.o $@ : !g'\'' > $@; \
|
||||
[ -s $@ ] || rm -f $@'
|
||||
$Q$(SHELL) -ec '$(CC) $(DEPFLAG) $(CPPFLAGS) $(CFLAGS) $< | sed '\''s!\(.*\)\.o[ :]*!$(dir $@)\1.lo $@ : !g'\'' > $@; [ -s $@ ] || rm -f $@'
|
||||
|
||||
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
|
||||
|
||||
@@ -2,8 +2,9 @@ Unbound README
|
||||
* ./configure && make && make install
|
||||
* on BSDs and Solaris use gmake (GNU make).
|
||||
* You can use libevent if you want. libevent is useful when using
|
||||
many (10000) outgoing ports. By default 16 ports are used and the
|
||||
builtin alternative is equally capable and a little faster.
|
||||
many (10000) outgoing ports. By default max 256 ports are opened at
|
||||
the same time and the builtin alternative is equally capable and a
|
||||
little faster.
|
||||
* More detailed README, README.svn, README.tests in doc directory
|
||||
* manual pages can be found in doc directory, and are installed, unbound(8).
|
||||
* example configuration file doc/example.conf
|
||||
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
# ===========================================================================
|
||||
# http://autoconf-archive.cryp.to/ac_pkg_swig.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AC_PROG_SWIG([major.minor.micro])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This macro searches for a SWIG installation on your system. If found you
|
||||
# should call SWIG via $(SWIG). You can use the optional first argument to
|
||||
# check if the version of the available SWIG is greater than or equal to
|
||||
# the value of the argument. It should have the format: N[.N[.N]] (N is a
|
||||
# number between 0 and 999. Only the first N is mandatory.)
|
||||
#
|
||||
# If the version argument is given (e.g. 1.3.17), AC_PROG_SWIG checks that
|
||||
# the swig package is this version number or higher.
|
||||
#
|
||||
# In configure.in, use as:
|
||||
#
|
||||
# AC_PROG_SWIG(1.3.17)
|
||||
# SWIG_ENABLE_CXX
|
||||
# SWIG_MULTI_MODULE_SUPPORT
|
||||
# SWIG_PYTHON
|
||||
#
|
||||
# LAST MODIFICATION
|
||||
#
|
||||
# 2008-04-12
|
||||
#
|
||||
# COPYLEFT
|
||||
#
|
||||
# Copyright (c) 2008 Sebastian Huber <sebastian-huber@web.de>
|
||||
# Copyright (c) 2008 Alan W. Irwin <irwin@beluga.phys.uvic.ca>
|
||||
# Copyright (c) 2008 Rafael Laboissiere <rafael@laboissiere.net>
|
||||
# Copyright (c) 2008 Andrew Collier <colliera@ukzn.ac.za>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation; either version 2 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Macro Archive. When you make and
|
||||
# distribute a modified version of the Autoconf Macro, you may extend this
|
||||
# special exception to the GPL to apply to your modified version as well.
|
||||
|
||||
AC_DEFUN([AC_PROG_SWIG],[
|
||||
AC_PATH_PROG([SWIG],[swig])
|
||||
if test -z "$SWIG" ; then
|
||||
AC_MSG_WARN([cannot find 'swig' program. You should look at http://www.swig.org])
|
||||
SWIG='echo "Error: SWIG is not installed. You should look at http://www.swig.org" ; false'
|
||||
elif test -n "$1" ; then
|
||||
AC_MSG_CHECKING([for SWIG version])
|
||||
[swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`]
|
||||
AC_MSG_RESULT([$swig_version])
|
||||
if test -n "$swig_version" ; then
|
||||
# Calculate the required version number components
|
||||
[required=$1]
|
||||
[required_major=`echo $required | sed 's/[^0-9].*//'`]
|
||||
if test -z "$required_major" ; then
|
||||
[required_major=0]
|
||||
fi
|
||||
[required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
|
||||
[required_minor=`echo $required | sed 's/[^0-9].*//'`]
|
||||
if test -z "$required_minor" ; then
|
||||
[required_minor=0]
|
||||
fi
|
||||
[required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
|
||||
[required_patch=`echo $required | sed 's/[^0-9].*//'`]
|
||||
if test -z "$required_patch" ; then
|
||||
[required_patch=0]
|
||||
fi
|
||||
# Calculate the available version number components
|
||||
[available=$swig_version]
|
||||
[available_major=`echo $available | sed 's/[^0-9].*//'`]
|
||||
if test -z "$available_major" ; then
|
||||
[available_major=0]
|
||||
fi
|
||||
[available=`echo $available | sed 's/[0-9]*[^0-9]//'`]
|
||||
[available_minor=`echo $available | sed 's/[^0-9].*//'`]
|
||||
if test -z "$available_minor" ; then
|
||||
[available_minor=0]
|
||||
fi
|
||||
[available=`echo $available | sed 's/[0-9]*[^0-9]//'`]
|
||||
[available_patch=`echo $available | sed 's/[^0-9].*//'`]
|
||||
if test -z "$available_patch" ; then
|
||||
[available_patch=0]
|
||||
fi
|
||||
if test $available_major -ne $required_major \
|
||||
-o $available_minor -ne $required_minor \
|
||||
-o $available_patch -lt $required_patch ; then
|
||||
AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version. You should look at http://www.swig.org])
|
||||
SWIG='echo "Error: SWIG version >= $1 is required. You have '"$swig_version"'. You should look at http://www.swig.org" ; false'
|
||||
else
|
||||
AC_MSG_NOTICE([SWIG executable is '$SWIG'])
|
||||
SWIG_LIB=`$SWIG -swiglib`
|
||||
AC_MSG_NOTICE([SWIG library directory is '$SWIG_LIB'])
|
||||
fi
|
||||
else
|
||||
AC_MSG_WARN([cannot determine SWIG version])
|
||||
SWIG='echo "Error: Cannot determine SWIG version. You should look at http://www.swig.org" ; false'
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([SWIG_LIB])
|
||||
])
|
||||
Vendored
+5320
-3767
File diff suppressed because it is too large
Load Diff
+1310
File diff suppressed because it is too large
Load Diff
+200
@@ -0,0 +1,200 @@
|
||||
AC_DEFUN([AC_PYTHON_DEVEL],[
|
||||
#
|
||||
# Allow the use of a (user set) custom python version
|
||||
#
|
||||
AC_ARG_VAR([PYTHON_VERSION],[The installed Python
|
||||
version to use, for example '2.3'. This string
|
||||
will be appended to the Python interpreter
|
||||
canonical name.])
|
||||
|
||||
AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]])
|
||||
if test -z "$PYTHON"; then
|
||||
AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path])
|
||||
PYTHON_VERSION=""
|
||||
fi
|
||||
|
||||
if test -z "$PYTHON_VERSION"; then
|
||||
PYTHON_VERSION=`$PYTHON -c "import sys, string; \
|
||||
print string.split(sys.version)[[0]]"`
|
||||
fi
|
||||
|
||||
#
|
||||
# Check for a version of Python >= 2.1.0
|
||||
#
|
||||
AC_MSG_CHECKING([for a version of Python >= '2.1.0'])
|
||||
ac_supports_python_ver=`$PYTHON -c "import sys, string; \
|
||||
ver = string.split(sys.version)[[0]]; \
|
||||
print ver >= '2.1.0'"`
|
||||
if test "$ac_supports_python_ver" != "True"; then
|
||||
if test -z "$PYTHON_NOVERSIONCHECK"; then
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_FAILURE([
|
||||
This version of the AC@&t@_PYTHON_DEVEL macro
|
||||
doesn't work properly with versions of Python before
|
||||
2.1.0. You may need to re-run configure, setting the
|
||||
variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG,
|
||||
PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand.
|
||||
Moreover, to disable this check, set PYTHON_NOVERSIONCHECK
|
||||
to something else than an empty string.
|
||||
])
|
||||
else
|
||||
AC_MSG_RESULT([skip at user request])
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
|
||||
#
|
||||
# if the macro parameter ``version'' is set, honour it
|
||||
#
|
||||
if test -n "$1"; then
|
||||
AC_MSG_CHECKING([for a version of Python $1])
|
||||
ac_supports_python_ver=`$PYTHON -c "import sys, string; \
|
||||
ver = string.split(sys.version)[[0]]; \
|
||||
print ver $1"`
|
||||
if test "$ac_supports_python_ver" = "True"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([this package requires Python $1.
|
||||
If you have it installed, but it isn't the default Python
|
||||
interpreter in your system path, please pass the PYTHON_VERSION
|
||||
variable to configure. See ``configure --help'' for reference.
|
||||
])
|
||||
PYTHON_VERSION=""
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# Check if you have distutils, else fail
|
||||
#
|
||||
AC_MSG_CHECKING([for the distutils Python package])
|
||||
ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`
|
||||
if test -z "$ac_distutils_result"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([cannot import Python module "distutils".
|
||||
Please check your Python installation. The error was:
|
||||
$ac_distutils_result])
|
||||
PYTHON_VERSION=""
|
||||
fi
|
||||
|
||||
#
|
||||
# Check for Python include path
|
||||
#
|
||||
AC_MSG_CHECKING([for Python include path])
|
||||
if test -z "$PYTHON_CPPFLAGS"; then
|
||||
python_path=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print distutils.sysconfig.get_python_inc();"`
|
||||
if test -n "${python_path}"; then
|
||||
python_path="-I$python_path"
|
||||
fi
|
||||
PYTHON_CPPFLAGS=$python_path
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_CPPFLAGS])
|
||||
AC_SUBST([PYTHON_CPPFLAGS])
|
||||
|
||||
#
|
||||
# Check for Python library path
|
||||
#
|
||||
AC_MSG_CHECKING([for Python library path])
|
||||
if test -z "$PYTHON_LDFLAGS"; then
|
||||
# (makes two attempts to ensure we've got a version number
|
||||
# from the interpreter)
|
||||
py_version=`$PYTHON -c "from distutils.sysconfig import *; \
|
||||
from string import join; \
|
||||
print join(get_config_vars('VERSION'))"`
|
||||
if test "$py_version" = "[None]"; then
|
||||
if test -n "$PYTHON_VERSION"; then
|
||||
py_version=$PYTHON_VERSION
|
||||
else
|
||||
py_version=`$PYTHON -c "import sys; \
|
||||
print sys.version[[:3]]"`
|
||||
fi
|
||||
fi
|
||||
|
||||
PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \
|
||||
from string import join; \
|
||||
print '-L' + get_python_lib(0,1), \
|
||||
'-L' + os.path.dirname(get_python_lib(0,1)), \
|
||||
'-lpython';"`$py_version
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_LDFLAGS])
|
||||
AC_SUBST([PYTHON_LDFLAGS])
|
||||
|
||||
#
|
||||
# Check for site packages
|
||||
#
|
||||
AC_MSG_CHECKING([for Python site-packages path])
|
||||
if test -z "$PYTHON_SITE_PKG"; then
|
||||
PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print distutils.sysconfig.get_python_lib(0,0);"`
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_SITE_PKG])
|
||||
AC_SUBST([PYTHON_SITE_PKG])
|
||||
|
||||
#
|
||||
# libraries which must be linked in when embedding
|
||||
#
|
||||
AC_MSG_CHECKING(python extra libraries)
|
||||
if test -z "$PYTHON_EXTRA_LIBS"; then
|
||||
PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \
|
||||
conf = distutils.sysconfig.get_config_var; \
|
||||
print conf('LOCALMODLIBS'), conf('LIBS')"`
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_EXTRA_LIBS])
|
||||
AC_SUBST(PYTHON_EXTRA_LIBS)
|
||||
|
||||
#
|
||||
# linking flags needed when embedding
|
||||
#
|
||||
AC_MSG_CHECKING(python extra linking flags)
|
||||
if test -z "$PYTHON_EXTRA_LDFLAGS"; then
|
||||
PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \
|
||||
conf = distutils.sysconfig.get_config_var; \
|
||||
print conf('LINKFORSHARED')"`
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS])
|
||||
AC_SUBST(PYTHON_EXTRA_LDFLAGS)
|
||||
|
||||
#
|
||||
# final check to see if everything compiles alright
|
||||
#
|
||||
AC_MSG_CHECKING([consistency of all components of python development environment])
|
||||
AC_LANG_PUSH([C])
|
||||
# save current global flags
|
||||
LIBS="$ac_save_LIBS $PYTHON_LDFLAGS"
|
||||
CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS"
|
||||
AC_TRY_LINK([
|
||||
#include <Python.h>
|
||||
],[
|
||||
Py_Initialize();
|
||||
],[pythonexists=yes],[pythonexists=no])
|
||||
|
||||
AC_MSG_RESULT([$pythonexists])
|
||||
|
||||
if test ! "$pythonexists" = "yes"; then
|
||||
AC_MSG_ERROR([
|
||||
Could not link test program to Python. Maybe the main Python library has been
|
||||
installed in some non-standard library path. If so, pass it to configure,
|
||||
via the LDFLAGS environment variable.
|
||||
Example: ./configure LDFLAGS="-L/usr/non-standard-path/python/lib"
|
||||
============================================================================
|
||||
ERROR!
|
||||
You probably have to install the development version of the Python package
|
||||
for your distribution. The exact name of this package varies among them.
|
||||
============================================================================
|
||||
])
|
||||
PYTHON_VERSION=""
|
||||
fi
|
||||
AC_LANG_POP
|
||||
# turn back to default flags
|
||||
CPPFLAGS="$ac_save_CPPFLAGS"
|
||||
LIBS="$ac_save_LIBS"
|
||||
|
||||
#
|
||||
# all done!
|
||||
#
|
||||
])
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -149,23 +149,23 @@ struct addrinfo {
|
||||
#ifdef getaddrinfo
|
||||
# undef getaddrinfo
|
||||
#endif
|
||||
#define getaddrinfo(a,b,c,d) (ssh_getaddrinfo(a,b,c,d))
|
||||
#define getaddrinfo(a,b,c,d) (getaddrinfo_unbound(a,b,c,d))
|
||||
int getaddrinfo(const char *, const char *,
|
||||
const struct addrinfo *, struct addrinfo **);
|
||||
#endif /* !HAVE_GETADDRINFO */
|
||||
|
||||
#if !defined(HAVE_GAI_STRERROR) && !defined(HAVE_CONST_GAI_STRERROR_PROTO)
|
||||
#define gai_strerror(a) (ssh_gai_strerror(a))
|
||||
#define gai_strerror(a) (gai_strerror_unbound(a))
|
||||
char *gai_strerror(int);
|
||||
#endif /* !HAVE_GAI_STRERROR */
|
||||
|
||||
#ifndef HAVE_FREEADDRINFO
|
||||
#define freeaddrinfo(a) (ssh_freeaddrinfo(a))
|
||||
#define freeaddrinfo(a) (freeaddrinfo_unbound(a))
|
||||
void freeaddrinfo(struct addrinfo *);
|
||||
#endif /* !HAVE_FREEADDRINFO */
|
||||
|
||||
#ifndef HAVE_GETNAMEINFO
|
||||
#define getnameinfo(a,b,c,d,e,f,g) (ssh_getnameinfo(a,b,c,d,e,f,g))
|
||||
#define getnameinfo(a,b,c,d,e,f,g) (getnameinfo_unbound(a,b,c,d,e,f,g))
|
||||
int getnameinfo(const struct sockaddr *, size_t, char *, size_t,
|
||||
char *, size_t, int);
|
||||
#endif /* !HAVE_GETNAMEINFO */
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Taken from FreeBSD src / lib / libc / stdtime / localtime.c 1.43 revision.
|
||||
* localtime.c 7.78.
|
||||
* tzfile.h 1.8
|
||||
* adapted to be replacement gmtime_r.
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#define MONSPERYEAR 12
|
||||
#define DAYSPERNYEAR 365
|
||||
#define DAYSPERLYEAR 366
|
||||
#define SECSPERMIN 60
|
||||
#define SECSPERHOUR (60*60)
|
||||
#define SECSPERDAY (24*60*60)
|
||||
#define DAYSPERWEEK 7
|
||||
#define TM_SUNDAY 0
|
||||
#define TM_MONDAY 1
|
||||
#define TM_TUESDAY 2
|
||||
#define TM_WEDNESDAY 3
|
||||
#define TM_THURSDAY 4
|
||||
#define TM_FRIDAY 5
|
||||
#define TM_SATURDAY 6
|
||||
|
||||
#define TM_YEAR_BASE 1900
|
||||
|
||||
#define EPOCH_YEAR 1970
|
||||
#define EPOCH_WDAY TM_THURSDAY
|
||||
|
||||
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
|
||||
|
||||
static const int mon_lengths[2][MONSPERYEAR] = {
|
||||
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
|
||||
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
||||
};
|
||||
|
||||
static const int year_lengths[2] = {
|
||||
DAYSPERNYEAR, DAYSPERLYEAR
|
||||
};
|
||||
|
||||
static void
|
||||
timesub(timep, offset, tmp)
|
||||
const time_t * const timep;
|
||||
const long offset;
|
||||
struct tm * const tmp;
|
||||
{
|
||||
long days;
|
||||
long rem;
|
||||
long y;
|
||||
int yleap;
|
||||
const int * ip;
|
||||
|
||||
days = *timep / SECSPERDAY;
|
||||
rem = *timep % SECSPERDAY;
|
||||
rem += (offset);
|
||||
while (rem < 0) {
|
||||
rem += SECSPERDAY;
|
||||
--days;
|
||||
}
|
||||
while (rem >= SECSPERDAY) {
|
||||
rem -= SECSPERDAY;
|
||||
++days;
|
||||
}
|
||||
tmp->tm_hour = (int) (rem / SECSPERHOUR);
|
||||
rem = rem % SECSPERHOUR;
|
||||
tmp->tm_min = (int) (rem / SECSPERMIN);
|
||||
/*
|
||||
** A positive leap second requires a special
|
||||
** representation. This uses "... ??:59:60" et seq.
|
||||
*/
|
||||
tmp->tm_sec = (int) (rem % SECSPERMIN) ;
|
||||
tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
|
||||
if (tmp->tm_wday < 0)
|
||||
tmp->tm_wday += DAYSPERWEEK;
|
||||
y = EPOCH_YEAR;
|
||||
#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
|
||||
while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
|
||||
long newy;
|
||||
|
||||
newy = y + days / DAYSPERNYEAR;
|
||||
if (days < 0)
|
||||
--newy;
|
||||
days -= (newy - y) * DAYSPERNYEAR +
|
||||
LEAPS_THRU_END_OF(newy - 1) -
|
||||
LEAPS_THRU_END_OF(y - 1);
|
||||
y = newy;
|
||||
}
|
||||
tmp->tm_year = y - TM_YEAR_BASE;
|
||||
tmp->tm_yday = (int) days;
|
||||
ip = mon_lengths[yleap];
|
||||
for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
|
||||
days = days - (long) ip[tmp->tm_mon];
|
||||
tmp->tm_mday = (int) (days + 1);
|
||||
tmp->tm_isdst = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Re-entrant version of gmtime.
|
||||
*/
|
||||
struct tm * gmtime_r(const time_t* timep, struct tm *tm)
|
||||
{
|
||||
timesub(timep, 0L, tm);
|
||||
return tm;
|
||||
}
|
||||
@@ -56,8 +56,12 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
|
||||
#if 0
|
||||
|
||||
@@ -23,8 +23,12 @@
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
@@ -62,7 +66,11 @@ inet_ntop(int af, const void *src, char *dst, size_t size)
|
||||
case AF_INET6:
|
||||
return (inet_ntop6(src, dst, size));
|
||||
default:
|
||||
#ifdef EAFNOSUPPORT
|
||||
errno = EAFNOSUPPORT;
|
||||
#else
|
||||
errno = ENOSYS;
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
|
||||
@@ -70,7 +70,11 @@ inet_pton(af, src, dst)
|
||||
case AF_INET6:
|
||||
return (inet_pton6(src, dst));
|
||||
default:
|
||||
#ifdef EAFNOSUPPORT
|
||||
errno = EAFNOSUPPORT;
|
||||
#else
|
||||
errno = ENOSYS;
|
||||
#endif
|
||||
return (-1);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
|
||||
+2
-5
@@ -1,11 +1,8 @@
|
||||
/* Just a replacement, if the original malloc is not
|
||||
GNU-compliant. See autoconf documentation. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include "config.h"
|
||||
#undef malloc
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
void *malloc ();
|
||||
@@ -14,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
+146
-145
@@ -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 Free Software Foundation,
|
||||
# Inc.
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
# Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2006-07-02'
|
||||
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='2006-07-02'
|
||||
# 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,.*/,,'`
|
||||
|
||||
@@ -56,8 +56,8 @@ version="\
|
||||
GNU config.guess ($timestamp)
|
||||
|
||||
Originally written by Per Bothner.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
|
||||
Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@@ -161,6 +161,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
arm*) machine=arm-unknown ;;
|
||||
sh3el) machine=shl-unknown ;;
|
||||
sh3eb) machine=sh-unknown ;;
|
||||
sh5el) machine=sh5le-unknown ;;
|
||||
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
|
||||
esac
|
||||
# The Operating System including object format, if it has switched
|
||||
@@ -169,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?
|
||||
@@ -323,14 +324,33 @@ 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:SunOS:5.*:*)
|
||||
echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
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"
|
||||
# If there is a compiler, see if it is configured for 64-bit objects.
|
||||
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
|
||||
# This test works for both compilers.
|
||||
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
|
||||
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_64BIT_ARCH >/dev/null
|
||||
then
|
||||
SUN_ARCH="x86_64"
|
||||
fi
|
||||
fi
|
||||
echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit ;;
|
||||
sun4*:SunOS:6*:*)
|
||||
# According to config.sub, this is the proper way to canonicalize
|
||||
@@ -531,7 +551,7 @@ EOF
|
||||
echo rs6000-ibm-aix3.2
|
||||
fi
|
||||
exit ;;
|
||||
*:AIX:*:[45])
|
||||
*:AIX:*:[456])
|
||||
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
|
||||
if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
|
||||
IBM_ARCH=rs6000
|
||||
@@ -639,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
|
||||
@@ -780,7 +800,7 @@ EOF
|
||||
i*:CYGWIN*:*)
|
||||
echo ${UNAME_MACHINE}-pc-cygwin
|
||||
exit ;;
|
||||
i*:MINGW*:*)
|
||||
*:MINGW*:*)
|
||||
echo ${UNAME_MACHINE}-pc-mingw32
|
||||
exit ;;
|
||||
i*:windows32*:*)
|
||||
@@ -790,15 +810,24 @@ EOF
|
||||
i*:PW*:*)
|
||||
echo ${UNAME_MACHINE}-pc-pw32
|
||||
exit ;;
|
||||
x86:Interix*:[3456]*)
|
||||
echo i586-pc-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
EM64T:Interix*:[3456]*)
|
||||
echo x86_64-unknown-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:Interix*:*)
|
||||
case ${UNAME_MACHINE} in
|
||||
x86)
|
||||
echo i586-pc-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
authenticamd | genuineintel | EM64T)
|
||||
echo x86_64-unknown-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
IA64)
|
||||
echo ia64-unknown-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
esac ;;
|
||||
[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
|
||||
@@ -828,8 +857,29 @@ 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:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
eval $set_cc_for_build
|
||||
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
| grep -q __ARM_EABI__
|
||||
then
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
else
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnueabi
|
||||
fi
|
||||
exit ;;
|
||||
avr32*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
@@ -843,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 ;;
|
||||
@@ -852,74 +913,33 @@ 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
|
||||
padre:Linux:*:*)
|
||||
echo sparc-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}
|
||||
parisc64:Linux:*:* | hppa64:Linux:*:*)
|
||||
echo hppa64-unknown-linux-gnu
|
||||
exit ;;
|
||||
parisc:Linux:*:* | hppa:Linux:*:*)
|
||||
# Look for CPU level
|
||||
@@ -929,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
|
||||
@@ -950,69 +973,9 @@ EOF
|
||||
x86_64:Linux:*:*)
|
||||
echo x86_64-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 ;;
|
||||
coff-i386)
|
||||
echo "${UNAME_MACHINE}-pc-linux-gnucoff"
|
||||
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; }
|
||||
;;
|
||||
xtensa*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
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
|
||||
@@ -1041,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:*:*)
|
||||
@@ -1085,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
|
||||
@@ -1124,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 ;;
|
||||
@@ -1136,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:*:*)
|
||||
@@ -1199,6 +1175,9 @@ EOF
|
||||
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
|
||||
echo i586-pc-beos
|
||||
exit ;;
|
||||
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
|
||||
echo i586-pc-haiku
|
||||
exit ;;
|
||||
SX-4:SUPER-UX:*:*)
|
||||
echo sx4-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
@@ -1208,6 +1187,15 @@ EOF
|
||||
SX-6:SUPER-UX:*:*)
|
||||
echo sx6-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
SX-7:SUPER-UX:*:*)
|
||||
echo sx7-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
SX-8:SUPER-UX:*:*)
|
||||
echo sx8-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
SX-8R:SUPER-UX:*:*)
|
||||
echo sx8r-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
Power*:Rhapsody:*:*)
|
||||
echo powerpc-apple-rhapsody${UNAME_RELEASE}
|
||||
exit ;;
|
||||
@@ -1217,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}
|
||||
@@ -1298,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
|
||||
@@ -1458,9 +1459,9 @@ This script, last modified $timestamp, has failed to recognize
|
||||
the operating system you are using. It is advised that you
|
||||
download the most up to date version of the config scripts from
|
||||
|
||||
http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
|
||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
|
||||
and
|
||||
http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
|
||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
|
||||
|
||||
If the version you run ($0) is already up to date, please
|
||||
send the following data and any information you think might be
|
||||
|
||||
+475
-50
@@ -6,6 +6,22 @@
|
||||
/* 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
|
||||
|
||||
/* Whether daemon is deprecated */
|
||||
#undef DEPRECATED_DAEMON
|
||||
|
||||
/* Define if you want to use debug lock checking (slow). */
|
||||
#undef ENABLE_LOCK_CHECKS
|
||||
|
||||
@@ -21,6 +37,23 @@
|
||||
/* Define to 1 if your system has a working `chown' function. */
|
||||
#undef HAVE_CHOWN
|
||||
|
||||
/* 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
|
||||
|
||||
@@ -30,24 +63,69 @@
|
||||
/* Define to 1 if you have the `event_base_get_method' function. */
|
||||
#undef HAVE_EVENT_BASE_GET_METHOD
|
||||
|
||||
/* Define to 1 if you have the `event_base_new' function. */
|
||||
#undef HAVE_EVENT_BASE_NEW
|
||||
|
||||
/* Define to 1 if you have the `event_base_once' function. */
|
||||
#undef HAVE_EVENT_BASE_ONCE
|
||||
|
||||
/* Define to 1 if you have the <event.h> header file. */
|
||||
#undef HAVE_EVENT_H
|
||||
|
||||
/* Define to 1 if you have the `EVP_sha1' function. */
|
||||
#undef HAVE_EVP_SHA1
|
||||
|
||||
/* Define to 1 if you have the `EVP_sha256' function. */
|
||||
#undef HAVE_EVP_SHA256
|
||||
|
||||
/* Define to 1 if you have the `EVP_sha512' function. */
|
||||
#undef HAVE_EVP_SHA512
|
||||
|
||||
/* Define to 1 if you have the `ev_default_loop' function. */
|
||||
#undef HAVE_EV_DEFAULT_LOOP
|
||||
|
||||
/* Define to 1 if you have the `ev_loop' function. */
|
||||
#undef HAVE_EV_LOOP
|
||||
|
||||
/* Define to 1 if you have the <expat.h> header file. */
|
||||
#undef HAVE_EXPAT_H
|
||||
|
||||
/* Define to 1 if you have the `fcntl' function. */
|
||||
#undef HAVE_FCNTL
|
||||
|
||||
/* Define to 1 if you have the `fork' function. */
|
||||
#undef HAVE_FORK
|
||||
|
||||
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
|
||||
#undef HAVE_FSEEKO
|
||||
|
||||
/* Define to 1 if you have the `getaddrinfo' function. */
|
||||
/* Whether getaddrinfo is available */
|
||||
#undef HAVE_GETADDRINFO
|
||||
|
||||
/* Define to 1 if you have the <getopt.h> header file. */
|
||||
#undef HAVE_GETOPT_H
|
||||
|
||||
/* Define to 1 if you have the `getpwnam' function. */
|
||||
#undef HAVE_GETPWNAM
|
||||
|
||||
/* Define to 1 if you have the `getrlimit' function. */
|
||||
#undef HAVE_GETRLIMIT
|
||||
|
||||
/* Define to 1 if you have the `glob' function. */
|
||||
#undef HAVE_GLOB
|
||||
|
||||
/* Define to 1 if you have the <glob.h> header file. */
|
||||
#undef HAVE_GLOB_H
|
||||
|
||||
/* Define to 1 if you have the `gmtime_r' function. */
|
||||
#undef HAVE_GMTIME_R
|
||||
|
||||
/* Define to 1 if you have the <grp.h> header file. */
|
||||
#undef HAVE_GRP_H
|
||||
|
||||
/* If you have HMAC_CTX_init */
|
||||
#undef HAVE_HMAC_CTX_INIT
|
||||
|
||||
/* Define to 1 if you have the `inet_aton' function. */
|
||||
#undef HAVE_INET_ATON
|
||||
|
||||
@@ -57,15 +135,36 @@
|
||||
/* Define to 1 if you have the `inet_pton' function. */
|
||||
#undef HAVE_INET_PTON
|
||||
|
||||
/* Define to 1 if you have the `initgroups' function. */
|
||||
#undef HAVE_INITGROUPS
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the `crypto' library (-lcrypto). */
|
||||
#undef HAVE_LIBCRYPTO
|
||||
/* 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
|
||||
|
||||
/* Define to 1 if you have the `localtime_r' function. */
|
||||
#undef HAVE_LOCALTIME_R
|
||||
|
||||
/* Define to 1 if you have the <login_cap.h> header file. */
|
||||
#undef HAVE_LOGIN_CAP_H
|
||||
|
||||
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
|
||||
to 0 otherwise. */
|
||||
#undef HAVE_MALLOC
|
||||
@@ -76,9 +175,21 @@
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the <netdb.h> header file. */
|
||||
#undef HAVE_NETDB_H
|
||||
|
||||
/* 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
|
||||
|
||||
@@ -97,12 +208,63 @@
|
||||
/* Define to 1 if the system has the type `pthread_spinlock_t'. */
|
||||
#undef HAVE_PTHREAD_SPINLOCK_T
|
||||
|
||||
/* Define to 1 if you have the <pwd.h> header file. */
|
||||
#undef HAVE_PWD_H
|
||||
|
||||
/* Define if you have Python libraries and header files. */
|
||||
#undef HAVE_PYTHON
|
||||
|
||||
/* Define to 1 if you have the `random' function. */
|
||||
#undef HAVE_RANDOM
|
||||
|
||||
/* Define to 1 if you have the `recvmsg' function. */
|
||||
#undef HAVE_RECVMSG
|
||||
|
||||
/* Define to 1 if you have the `sbrk' function. */
|
||||
#undef HAVE_SBRK
|
||||
|
||||
/* Define to 1 if you have the `sendmsg' function. */
|
||||
#undef HAVE_SENDMSG
|
||||
|
||||
/* Define to 1 if you have the `setregid' function. */
|
||||
#undef HAVE_SETREGID
|
||||
|
||||
/* Define to 1 if you have the `setresgid' function. */
|
||||
#undef HAVE_SETRESGID
|
||||
|
||||
/* Define to 1 if you have the `setresuid' function. */
|
||||
#undef HAVE_SETRESUID
|
||||
|
||||
/* 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
|
||||
|
||||
/* Define to 1 if you have the `setusercontext' function. */
|
||||
#undef HAVE_SETUSERCONTEXT
|
||||
|
||||
/* Define to 1 if you have the `sigprocmask' function. */
|
||||
#undef HAVE_SIGPROCMASK
|
||||
|
||||
/* Define to 1 if you have the `sleep' function. */
|
||||
#undef HAVE_SLEEP
|
||||
|
||||
/* 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
|
||||
|
||||
/* Define to 1 if you have the `srandom' function. */
|
||||
#undef HAVE_SRANDOM
|
||||
|
||||
/* Define if you have the SSL libraries installed. */
|
||||
#undef HAVE_SSL
|
||||
|
||||
@@ -118,6 +280,9 @@
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the `strftime' function. */
|
||||
#undef HAVE_STRFTIME
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
@@ -127,6 +292,12 @@
|
||||
/* Define to 1 if you have the `strlcpy' function. */
|
||||
#undef HAVE_STRLCPY
|
||||
|
||||
/* Define to 1 if you have the `strptime' function. */
|
||||
#undef HAVE_STRPTIME
|
||||
|
||||
/* Define if you have Swig libraries and header files. */
|
||||
#undef HAVE_SWIG
|
||||
|
||||
/* Define to 1 if you have the <syslog.h> header file. */
|
||||
#undef HAVE_SYSLOG_H
|
||||
|
||||
@@ -148,27 +319,95 @@
|
||||
/* Define to 1 if you have the <sys/uio.h> header file. */
|
||||
#undef HAVE_SYS_UIO_H
|
||||
|
||||
/* Define to 1 if you have the <sys/wait.h> header file. */
|
||||
#undef HAVE_SYS_WAIT_H
|
||||
|
||||
/* Define to 1 if you have the <time.h> header file. */
|
||||
#undef HAVE_TIME_H
|
||||
|
||||
/* Define to 1 if you have the `tzset' function. */
|
||||
#undef HAVE_TZSET
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if you have the `usleep' function. */
|
||||
#undef HAVE_USLEEP
|
||||
|
||||
/* Define to 1 if you have the `vfork' function. */
|
||||
#undef HAVE_VFORK
|
||||
|
||||
/* Define to 1 if you have the <vfork.h> header file. */
|
||||
#undef HAVE_VFORK_H
|
||||
|
||||
/* Define to 1 if you have the <windows.h> header file. */
|
||||
#undef HAVE_WINDOWS_H
|
||||
|
||||
/* Using Windows threads */
|
||||
#undef HAVE_WINDOWS_THREADS
|
||||
|
||||
/* Define to 1 if you have the <winsock2.h> header file. */
|
||||
#undef HAVE_WINSOCK2_H
|
||||
|
||||
/* Define to 1 if `fork' works. */
|
||||
#undef HAVE_WORKING_FORK
|
||||
|
||||
/* Define to 1 if `vfork' works. */
|
||||
#undef HAVE_WORKING_VFORK
|
||||
|
||||
/* Define to 1 if you have the `writev' function. */
|
||||
#undef HAVE_WRITEV
|
||||
|
||||
/* Define to 1 if you have the <ws2tcpip.h> header file. */
|
||||
#undef HAVE_WS2TCPIP_H
|
||||
|
||||
/* 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
|
||||
|
||||
/* 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
|
||||
|
||||
/* Define if the network stack does not fully support nonblocking io (causes
|
||||
lower performance). */
|
||||
#undef NONBLOCKING_IS_BROKEN
|
||||
|
||||
/* Put -D_ALL_SOURCE define in config.h */
|
||||
#undef OMITTED__D_ALL_SOURCE
|
||||
|
||||
/* Put -D_BSD_SOURCE define in config.h */
|
||||
#undef OMITTED__D_BSD_SOURCE
|
||||
|
||||
/* Put -D_GNU_SOURCE define in config.h */
|
||||
#undef OMITTED__D_GNU_SOURCE
|
||||
|
||||
/* Put -D_LARGEFILE_SOURCE=1 define in config.h */
|
||||
#undef OMITTED__D_LARGEFILE_SOURCE_1
|
||||
|
||||
/* Put -D_POSIX_C_SOURCE=200112 define in config.h */
|
||||
#undef OMITTED__D_POSIX_C_SOURCE_200112
|
||||
|
||||
/* Put -D_XOPEN_SOURCE=600 define in config.h */
|
||||
#undef OMITTED__D_XOPEN_SOURCE_600
|
||||
|
||||
/* Put -D_XOPEN_SOURCE_EXTENDED=1 define in config.h */
|
||||
#undef OMITTED__D_XOPEN_SOURCE_EXTENDED_1
|
||||
|
||||
/* Put -D__EXTENSIONS__ define in config.h */
|
||||
#undef OMITTED__D__EXTENSIONS__
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
@@ -181,10 +420,13 @@
|
||||
/* 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
|
||||
|
||||
/* Pathname to unbound process id file */
|
||||
/* default pidfile location */
|
||||
#undef PIDFILE
|
||||
|
||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||
@@ -194,32 +436,92 @@
|
||||
/* 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
|
||||
|
||||
/* Directory to chdir to */
|
||||
#undef RUN_DIR
|
||||
|
||||
/* Shared data */
|
||||
#undef SHARE_DIR
|
||||
|
||||
/* 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
|
||||
|
||||
/* Define this to enable SHA256 and SHA512 support. */
|
||||
#undef USE_SHA2
|
||||
|
||||
/* Enable extensions on AIX 3, Interix. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# undef _ALL_SOURCE
|
||||
#endif
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# undef _GNU_SOURCE
|
||||
#endif
|
||||
/* Enable threading extensions on Solaris. */
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# undef _POSIX_PTHREAD_SEMANTICS
|
||||
#endif
|
||||
/* Enable extensions on HP NonStop. */
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# undef _TANDEM_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
#endif
|
||||
|
||||
|
||||
/* Whether the windows socket API is used */
|
||||
#undef USE_WINSOCK
|
||||
|
||||
/* the version of the windows API enabled */
|
||||
#undef WINVER
|
||||
|
||||
/* Define if you want Python module. */
|
||||
#undef WITH_PYTHONMODULE
|
||||
|
||||
/* Define if you want PyUnbound. */
|
||||
#undef WITH_PYUNBOUND
|
||||
|
||||
/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
|
||||
`char[]'. */
|
||||
#undef YYTEXT_POINTER
|
||||
|
||||
/* Define to 1 if on AIX 3.
|
||||
System headers sometimes define this.
|
||||
We just want to avoid a redefinition error message. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# undef _ALL_SOURCE
|
||||
#endif
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#undef _FILE_OFFSET_BITS
|
||||
|
||||
@@ -229,6 +531,16 @@
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#undef _LARGE_FILES
|
||||
|
||||
/* Define to 1 if on MINIX. */
|
||||
#undef _MINIX
|
||||
|
||||
/* Define to 2 if the system does not provide POSIX.1 features except with
|
||||
this defined. */
|
||||
#undef _POSIX_1_SOURCE
|
||||
|
||||
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||
#undef _POSIX_SOURCE
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#undef const
|
||||
|
||||
@@ -256,10 +568,10 @@
|
||||
/* Define to `long long' if <sys/types.h> does not define. */
|
||||
#undef int64_t
|
||||
|
||||
/* Define to `char' if <sys/types.h> does not define. */
|
||||
/* 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. */
|
||||
@@ -280,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. */
|
||||
@@ -301,6 +613,40 @@
|
||||
/* Define as `fork' if `vfork' does not work. */
|
||||
#undef vfork
|
||||
|
||||
#if defined(OMITTED__D_GNU_SOURCE) && !defined(_GNU_SOURCE)
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_BSD_SOURCE) && !defined(_BSD_SOURCE)
|
||||
#define _BSD_SOURCE 1
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D__EXTENSIONS__) && !defined(__EXTENSIONS__)
|
||||
#define __EXTENSIONS__ 1
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_POSIX_C_SOURCE_200112) && !defined(_POSIX_C_SOURCE)
|
||||
#define _POSIX_C_SOURCE 200112
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_XOPEN_SOURCE_600) && !defined(_XOPEN_SOURCE)
|
||||
#define _XOPEN_SOURCE 600
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_XOPEN_SOURCE_EXTENDED_1) && !defined(_XOPEN_SOURCE_EXTENDED)
|
||||
#define _XOPEN_SOURCE_EXTENDED 1
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_ALL_SOURCE) && !defined(_ALL_SOURCE)
|
||||
#define _ALL_SOURCE 1
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_LARGEFILE_SOURCE_1) && !defined(_LARGEFILE_SOURCE)
|
||||
#define _LARGEFILE_SOURCE 1
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef UNBOUND_DEBUG
|
||||
# define NDEBUG
|
||||
@@ -342,24 +688,24 @@
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
#include <openssl/err.h>
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_RAND_H
|
||||
#include <openssl/rand.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_ATTR_FORMAT
|
||||
# define ATTR_FORMAT(archetype, string_index, first_to_check) \
|
||||
__attribute__ ((format (archetype, string_index, first_to_check)))
|
||||
#else /* !HAVE_ATTR_FORMAT */
|
||||
# define ATTR_FORMAT(archetype, string_index, first_to_check) /* empty */
|
||||
#endif /* !HAVE_ATTR_FORMAT */
|
||||
|
||||
|
||||
#if defined(DOXYGEN)
|
||||
# define ATTR_UNUSED(x) x
|
||||
#elif defined(__cplusplus)
|
||||
@@ -369,23 +715,123 @@
|
||||
#else /* !HAVE_ATTR_UNUSED */
|
||||
# define ATTR_UNUSED(x) x
|
||||
#endif /* !HAVE_ATTR_UNUSED */
|
||||
|
||||
|
||||
#ifndef HAVE_FSEEKO
|
||||
#define fseeko fseek
|
||||
#define ftello ftell
|
||||
#endif /* HAVE_FSEEKO */
|
||||
#if defined(HAVE_EVENT_H) && !defined(HAVE_EVENT_BASE_ONCE) && (defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS))
|
||||
/* using version of libevent that is not threadsafe. */
|
||||
# define LIBEVENT_SIGNAL_PROBLEM 1
|
||||
|
||||
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 256
|
||||
#endif
|
||||
|
||||
#ifndef RAND_MAX
|
||||
#define RAND_MAX 2147483647
|
||||
|
||||
#ifndef HAVE_SNPRINTF
|
||||
#define snprintf snprintf_unbound
|
||||
#define vsnprintf vsnprintf_unbound
|
||||
#include <stdarg.h>
|
||||
int snprintf (char *str, size_t count, const char *fmt, ...);
|
||||
int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
|
||||
#endif /* HAVE_SNPRINTF */
|
||||
|
||||
|
||||
#ifndef HAVE_INET_PTON
|
||||
#define inet_pton inet_pton_unbound
|
||||
int inet_pton(int af, const char* src, void* dst);
|
||||
#endif /* HAVE_INET_PTON */
|
||||
|
||||
|
||||
#ifndef HAVE_INET_NTOP
|
||||
#define inet_ntop inet_ntop_unbound
|
||||
const char *inet_ntop(int af, const void *src, char *dst, size_t size);
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HAVE_INET_ATON
|
||||
#define inet_aton inet_aton_unbound
|
||||
int inet_aton(const char *cp, struct in_addr *addr);
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HAVE_MEMMOVE
|
||||
#define memmove memmove_unbound
|
||||
void *memmove(void *dest, const void *src, size_t n);
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
#define strlcpy strlcpy_unbound
|
||||
size_t strlcpy(char *dst, const char *src, size_t siz);
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HAVE_GMTIME_R
|
||||
#define gmtime_r gmtime_r_unbound
|
||||
struct tm *gmtime_r(const time_t *timep, struct tm *result);
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HAVE_SLEEP
|
||||
#define sleep(x) Sleep((x)*1000) /* on win32 */
|
||||
#endif /* HAVE_SLEEP */
|
||||
|
||||
|
||||
#ifndef HAVE_USLEEP
|
||||
#define usleep(x) Sleep((x)/1000 + 1) /* on win32 */
|
||||
#endif /* HAVE_USLEEP */
|
||||
|
||||
|
||||
#ifndef HAVE_RANDOM
|
||||
#define random rand /* on win32, for tests only (bad random) */
|
||||
#endif /* HAVE_RANDOM */
|
||||
|
||||
|
||||
#ifndef HAVE_SRANDOM
|
||||
#define srandom(x) srand(x) /* on win32, for tests only (bad random) */
|
||||
#endif /* HAVE_SRANDOM */
|
||||
|
||||
|
||||
/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
#define FD_SET_T (u_int)
|
||||
#else
|
||||
#define FD_SET_T
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef IPV6_MIN_MTU
|
||||
#define IPV6_MIN_MTU 1280
|
||||
#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
|
||||
|
||||
|
||||
|
||||
#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
|
||||
|
||||
#ifndef CHECKED_INET6
|
||||
# define CHECKED_INET6
|
||||
# ifdef AF_INET6
|
||||
@@ -397,34 +843,11 @@
|
||||
|
||||
/* maximum nesting of included files */
|
||||
#define MAXINCLUDES 10
|
||||
|
||||
#ifndef HAVE_SNPRINTF
|
||||
#include <stdarg.h>
|
||||
int snprintf (char *str, size_t count, const char *fmt, ...);
|
||||
int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
|
||||
#endif /* HAVE_SNPRINTF */
|
||||
#ifndef HAVE_INET_PTON
|
||||
int inet_pton(int af, const char* src, void* dst);
|
||||
#endif /* HAVE_INET_PTON */
|
||||
#ifndef HAVE_INET_NTOP
|
||||
const char *inet_ntop(int af, const void *src, char *dst, size_t size);
|
||||
#endif
|
||||
#ifndef HAVE_INET_ATON
|
||||
int inet_aton(const char *cp, struct in_addr *addr);
|
||||
#endif
|
||||
#ifndef HAVE_MEMMOVE
|
||||
void *memmove(void *dest, const void *src, size_t n);
|
||||
#endif
|
||||
#ifndef HAVE_STRLCPY
|
||||
size_t strlcpy(char *dst, const char *src, size_t siz);
|
||||
#endif
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
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__)
|
||||
@@ -442,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
+119
-30
@@ -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 Free Software Foundation,
|
||||
# Inc.
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
# Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2006-09-20'
|
||||
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='2006-09-20'
|
||||
|
||||
|
||||
# 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.
|
||||
@@ -72,8 +75,8 @@ Report bugs and patches to <config-patches@gnu.org>."
|
||||
version="\
|
||||
GNU config.sub ($timestamp)
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
|
||||
Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@@ -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
|
||||
@@ -245,17 +252,20 @@ case $basic_machine in
|
||||
| bfin \
|
||||
| c4x | clipper \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
| fr30 | frv \
|
||||
| fido | fr30 | frv \
|
||||
| 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 \
|
||||
| maxq | mb | microblaze | mcore | mep | metag \
|
||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||
| mips16 \
|
||||
| mips64 | mips64el \
|
||||
| mips64vr | mips64vrel \
|
||||
| mips64octeon | mips64octeonel \
|
||||
| mips64orion | mips64orionel \
|
||||
| mips64r5900 | mips64r5900el \
|
||||
| mips64vr | mips64vrel \
|
||||
| mips64vr4100 | mips64vr4100el \
|
||||
| mips64vr4300 | mips64vr4300el \
|
||||
| mips64vr5000 | mips64vr5000el \
|
||||
@@ -268,6 +278,7 @@ case $basic_machine in
|
||||
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||
| mipstx39 | mipstx39el \
|
||||
| mn10200 | mn10300 \
|
||||
| moxie \
|
||||
| mt \
|
||||
| msp430 \
|
||||
| nios | nios2 \
|
||||
@@ -276,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)
|
||||
| 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
|
||||
@@ -324,19 +337,22 @@ case $basic_machine in
|
||||
| clipper-* | craynv-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
|
||||
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
||||
| h8300-* | h8500-* \
|
||||
| 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-* \
|
||||
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
|
||||
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
||||
| mips16-* \
|
||||
| mips64-* | mips64el-* \
|
||||
| mips64vr-* | mips64vrel-* \
|
||||
| mips64octeon-* | mips64octeonel-* \
|
||||
| mips64orion-* | mips64orionel-* \
|
||||
| mips64r5900-* | mips64r5900el-* \
|
||||
| mips64vr-* | mips64vrel-* \
|
||||
| mips64vr4100-* | mips64vr4100el-* \
|
||||
| mips64vr4300-* | mips64vr4300el-* \
|
||||
| mips64vr5000-* | mips64vr5000el-* \
|
||||
@@ -357,21 +373,26 @@ 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-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
|
||||
| tahoe-* | thumb-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
|
||||
| tron-* \
|
||||
| ubicom32-* \
|
||||
| v850-* | v850e-* | vax-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
|
||||
| xstormy16-* | xtensa-* \
|
||||
| xstormy16-* | xtensa*-* \
|
||||
| ymp-* \
|
||||
| z8k-*)
|
||||
| z8k-* | z80-*)
|
||||
;;
|
||||
# Recognize the basic CPU types without company name, with glob match.
|
||||
xtensa*)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
# Recognize the various machine names and aliases which stand
|
||||
# for a CPU type and a company and sometimes even an OS.
|
||||
@@ -435,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
|
||||
@@ -443,10 +468,26 @@ case $basic_machine in
|
||||
basic_machine=ns32k-sequent
|
||||
os=-dynix
|
||||
;;
|
||||
blackfin)
|
||||
basic_machine=bfin-unknown
|
||||
os=-linux
|
||||
;;
|
||||
blackfin-*)
|
||||
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
bluegene*)
|
||||
basic_machine=powerpc-ibm
|
||||
os=-cnk
|
||||
;;
|
||||
c90)
|
||||
basic_machine=c90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
cegcc)
|
||||
basic_machine=arm-unknown
|
||||
os=-cegcc
|
||||
;;
|
||||
convex-c1)
|
||||
basic_machine=c1-convex
|
||||
os=-bsd
|
||||
@@ -475,8 +516,8 @@ case $basic_machine in
|
||||
basic_machine=craynv-cray
|
||||
os=-unicosmp
|
||||
;;
|
||||
cr16c)
|
||||
basic_machine=cr16c-unknown
|
||||
cr16)
|
||||
basic_machine=cr16-unknown
|
||||
os=-elf
|
||||
;;
|
||||
crds | unos)
|
||||
@@ -514,6 +555,10 @@ case $basic_machine in
|
||||
basic_machine=m88k-motorola
|
||||
os=-sysv3
|
||||
;;
|
||||
dicos)
|
||||
basic_machine=i686-pc
|
||||
os=-dicos
|
||||
;;
|
||||
djgpp)
|
||||
basic_machine=i586-pc
|
||||
os=-msdosdjgpp
|
||||
@@ -668,6 +713,14 @@ case $basic_machine in
|
||||
basic_machine=m68k-isi
|
||||
os=-sysv
|
||||
;;
|
||||
m68knommu)
|
||||
basic_machine=m68k-unknown
|
||||
os=-linux
|
||||
;;
|
||||
m68knommu-*)
|
||||
basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
m88k-omron*)
|
||||
basic_machine=m88k-omron
|
||||
;;
|
||||
@@ -679,10 +732,17 @@ case $basic_machine in
|
||||
basic_machine=ns32k-utek
|
||||
os=-sysv
|
||||
;;
|
||||
microblaze)
|
||||
basic_machine=microblaze-xilinx
|
||||
;;
|
||||
mingw32)
|
||||
basic_machine=i386-pc
|
||||
os=-mingw32
|
||||
;;
|
||||
mingw32ce)
|
||||
basic_machine=arm-unknown
|
||||
os=-mingw32ce
|
||||
;;
|
||||
miniframe)
|
||||
basic_machine=m68000-convergent
|
||||
;;
|
||||
@@ -809,6 +869,14 @@ case $basic_machine in
|
||||
basic_machine=i860-intel
|
||||
os=-osf
|
||||
;;
|
||||
parisc)
|
||||
basic_machine=hppa-unknown
|
||||
os=-linux
|
||||
;;
|
||||
parisc-*)
|
||||
basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
pbd)
|
||||
basic_machine=sparc-tti
|
||||
;;
|
||||
@@ -925,6 +993,9 @@ case $basic_machine in
|
||||
basic_machine=sh-hitachi
|
||||
os=-hms
|
||||
;;
|
||||
sh5el)
|
||||
basic_machine=sh5le-unknown
|
||||
;;
|
||||
sh64)
|
||||
basic_machine=sh64-unknown
|
||||
;;
|
||||
@@ -1014,6 +1085,10 @@ case $basic_machine in
|
||||
basic_machine=tic6x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tile*)
|
||||
basic_machine=tile-unknown
|
||||
os=-linux-gnu
|
||||
;;
|
||||
tx39)
|
||||
basic_machine=mipstx39-unknown
|
||||
;;
|
||||
@@ -1089,6 +1164,10 @@ case $basic_machine in
|
||||
basic_machine=z8k-unknown
|
||||
os=-sim
|
||||
;;
|
||||
z80-*-coff)
|
||||
basic_machine=z80-unknown
|
||||
os=-sim
|
||||
;;
|
||||
none)
|
||||
basic_machine=none-none
|
||||
os=-none
|
||||
@@ -1127,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)
|
||||
@@ -1177,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|'`
|
||||
;;
|
||||
@@ -1197,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* \
|
||||
@@ -1209,7 +1292,7 @@ case $os in
|
||||
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -chorusos* | -chorusrdb* \
|
||||
| -chorusos* | -chorusrdb* | -cegcc* \
|
||||
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
@@ -1219,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*)
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
@@ -1349,6 +1432,9 @@ case $os in
|
||||
-zvmoe)
|
||||
os=-zvmoe
|
||||
;;
|
||||
-dicos*)
|
||||
os=-dicos
|
||||
;;
|
||||
-none)
|
||||
;;
|
||||
*)
|
||||
@@ -1414,6 +1500,9 @@ case $basic_machine in
|
||||
m68*-cisco)
|
||||
os=-aout
|
||||
;;
|
||||
mep-*)
|
||||
os=-elf
|
||||
;;
|
||||
mips*-cisco)
|
||||
os=-elf
|
||||
;;
|
||||
@@ -1543,7 +1632,7 @@ case $basic_machine in
|
||||
-sunos*)
|
||||
vendor=sun
|
||||
;;
|
||||
-aix*)
|
||||
-cnk*|-aix*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-beos*)
|
||||
|
||||
+595
-526
File diff suppressed because it is too large
Load Diff
@@ -5,3 +5,16 @@ distribution but may be helpful.
|
||||
* parseunbound.pl: perl script to run from cron that parses statistics from
|
||||
the log file and stores them.
|
||||
* unbound.spec and unbound.init: RPM specfile and Linux rc.d initfile.
|
||||
* update-anchor.sh: shell script that uses unbound-host to update a set
|
||||
of trust anchor files. Run from cron twice a month.
|
||||
* update-itar.sh: shell script that updates from itar.iana.org. Run from cron.
|
||||
* split-itar.sh: shell script to split anchors.mf from itar.iana.org into
|
||||
multiple key files so it can be used with auto-trust-anchor-file.
|
||||
* unbound_munin_ : plugin for munin statistics report
|
||||
* unbound_cacti.tar.gz : setup files for cacti statistics report
|
||||
* selinux: the .fc and .te files for SElinux protection of the unbound daemon
|
||||
* unbound.plist: launchd configuration file for MacOSX.
|
||||
* build-unbound-localzone-from-hosts.pl: perl script to turn /etc/hosts into
|
||||
a local-zone and local-data include file for unbound.conf.
|
||||
* unbound-host.nagios.patch: makes unbound-host return status that fits right
|
||||
in with the nagios monitoring framework. Contributed by Migiel de Vos.
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/perl -WT
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $hostsfile = '/etc/hosts';
|
||||
my $localzonefile = '/etc/unbound/localzone.conf.new';
|
||||
|
||||
my $localzone = 'example.com';
|
||||
|
||||
open( HOSTS,"<${hostsfile}" ) or die( "Could not open ${hostsfile}: $!" );
|
||||
open( ZONE,">${localzonefile}" ) or die( "Could not open ${localzonefile}: $!" );
|
||||
|
||||
print ZONE "server:\n\n";
|
||||
print ZONE "local-zone: \"${localzone}\" transparent\n\n";
|
||||
|
||||
my %ptrhash;
|
||||
|
||||
while ( my $hostline = <HOSTS> ) {
|
||||
|
||||
# Skip comments
|
||||
if ( $hostline !~ "^#" and $hostline !~ '^\s+$' ) {
|
||||
|
||||
my @entries = split( /\s+/, $hostline );
|
||||
|
||||
my $ip;
|
||||
|
||||
my $count = 0;
|
||||
foreach my $entry ( @entries ) {
|
||||
if ( $count == 0 ) {
|
||||
$ip = $entry;
|
||||
} else {
|
||||
|
||||
if ( $count == 1) {
|
||||
|
||||
# Only return localhost for 127.0.0.1 and ::1
|
||||
if ( ($ip ne '127.0.0.1' and $ip ne '::1') or $entry =~ 'localhost' ) {
|
||||
if ( ! defined $ptrhash{$ip} ) {
|
||||
$ptrhash{$ip} = $entry;
|
||||
print ZONE "local-data-ptr: \"$ip $entry\"\n";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Use AAAA for IPv6 addresses
|
||||
my $a = 'A';
|
||||
if ( $ip =~ ':' ) {
|
||||
$a = 'AAAA';
|
||||
}
|
||||
|
||||
print ZONE "local-data: \"$entry ${a} $ip\"\n";
|
||||
|
||||
}
|
||||
$count++;
|
||||
}
|
||||
print ZONE "\n";
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
__END__
|
||||
|
||||
@@ -15,9 +15,11 @@
|
||||
name="unbound"
|
||||
rcvar=`set_rcvar`
|
||||
|
||||
load_rc_config $name
|
||||
|
||||
command="/usr/local/sbin/unbound"
|
||||
pidfile="/usr/local/etc/unbound/unbound.pid"
|
||||
pidfile=${unbound_pidfile:-"/usr/local/etc/unbound/unbound.pid"}
|
||||
command_args=${unbound_flags:-"-c /usr/local/etc/unbound/unbound.conf"}
|
||||
extra_commands="reload"
|
||||
|
||||
load_rc_config $name
|
||||
run_rc_command "$1"
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/etc/unbound(/.*)? system_u:object_r:unbound_conf_t:s0
|
||||
/etc/rc\.d/init\.d/unbound -- system_u:object_r:unbound_initrc_exec_t:s0
|
||||
/usr/sbin/unbound -- system_u:object_r:unbound_exec_t:s0
|
||||
/var/run/unbound(/.*)? system_u:object_r:unbound_var_run_t:s0
|
||||
@@ -0,0 +1,42 @@
|
||||
policy_module(unbound, 0.1.0)
|
||||
|
||||
type unbound_t;
|
||||
type unbound_conf_t;
|
||||
type unbound_exec_t;
|
||||
type unbound_initrc_exec_t;
|
||||
type unbound_var_run_t;
|
||||
|
||||
init_daemon_domain(unbound_t, unbound_exec_t)
|
||||
init_script_file(unbound_initrc_exec_t)
|
||||
|
||||
role system_r types unbound_t;
|
||||
|
||||
# XXX
|
||||
# unbound-{checkconf,control} are not protected. Do we need protect them?
|
||||
|
||||
# Unbound daemon
|
||||
|
||||
auth_use_nsswitch(unbound_t)
|
||||
dev_read_urand(unbound_t)
|
||||
corenet_all_recvfrom_unlabeled(unbound_t)
|
||||
corenet_tcp_bind_all_nodes(unbound_t)
|
||||
corenet_tcp_bind_dns_port(unbound_t)
|
||||
corenet_tcp_bind_rndc_port(unbound_t)
|
||||
corenet_udp_bind_all_nodes(unbound_t)
|
||||
corenet_udp_bind_all_unreserved_ports(unbound_t)
|
||||
corenet_udp_bind_dns_port(unbound_t)
|
||||
files_read_etc_files(unbound_t)
|
||||
files_pid_file(unbound_var_run_t)
|
||||
files_type(unbound_conf_t)
|
||||
libs_use_ld_so(unbound_t)
|
||||
libs_use_shared_libs(unbound_t)
|
||||
logging_send_syslog_msg(unbound_t)
|
||||
manage_files_pattern(unbound_t, unbound_var_run_t, unbound_var_run_t)
|
||||
miscfiles_read_localization(unbound_t)
|
||||
read_files_pattern(unbound_t, unbound_conf_t, unbound_conf_t)
|
||||
|
||||
allow unbound_t self:capability { setuid chown net_bind_service setgid dac_override };
|
||||
allow unbound_t self:tcp_socket create_stream_socket_perms;
|
||||
allow unbound_t self:udp_socket create_socket_perms;
|
||||
|
||||
###################################################
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# unbound This shell script takes care of starting and stopping
|
||||
# unbound (DNS server).
|
||||
#
|
||||
# chkconfig: - 14 86
|
||||
# description: unbound is a Domain Name Server (DNS) \
|
||||
# that is used to resolve host names to IP addresses.
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: unbound
|
||||
# Required-Start: $network $local_fs
|
||||
# Required-Stop: $network $local_fs
|
||||
# Should-Start: $syslog
|
||||
# Should-Stop: $syslog
|
||||
# Short-Description: unbound recursive Domain Name Server.
|
||||
# Description: unbound is a Domain Name Server (DNS)
|
||||
# that is used to resolve host names to IP addresses.
|
||||
### END INIT INFO
|
||||
|
||||
# Source function library.
|
||||
. /etc/rc.d/init.d/functions
|
||||
|
||||
exec="/usr/sbin/unbound"
|
||||
config="/var/lib/unbound/unbound.conf"
|
||||
rootdir="/var/lib/unbound"
|
||||
pidfile="/var/run/unbound/unbound.pid"
|
||||
|
||||
[ -e /etc/sysconfig/unbound ] && . /etc/sysconfig/unbound
|
||||
|
||||
lockfile=/var/lock/subsys/unbound
|
||||
|
||||
start() {
|
||||
[ -x $exec ] || exit 5
|
||||
[ -f $config ] || exit 6
|
||||
echo -n $"Starting unbound: "
|
||||
|
||||
if [ ! -e ${rootdir}/etc/resolv.conf ] || /usr/bin/cmp -s /etc/resolv.conf ${rootdir}/etc/resolv.conf; then
|
||||
cp -fp /etc/resolv.conf ${rootdir}/etc/resolv.conf
|
||||
fi;
|
||||
if [ ! -e ${rootdir}/etc/localtime ] || /usr/bin/cmp -s /etc/localtime ${rootdir}/etc/localtime; then
|
||||
cp -fp /etc/localtime ${rootdir}/etc/localtime
|
||||
fi;
|
||||
mount --bind -n /dev/log ${rootdir}/dev/log >/dev/null 2>&1;
|
||||
mount --bind -n /dev/random ${rootdir}/dev/random >/dev/null 2>&1;
|
||||
mount --bind -n /var/run/unbound ${rootdir}/var/run/unbound >/dev/null 2>&1;
|
||||
|
||||
# if not running, start it up here
|
||||
daemon $exec
|
||||
retval=$?
|
||||
[ $retval -eq 0 ] && touch $lockfile
|
||||
echo
|
||||
}
|
||||
|
||||
stop() {
|
||||
echo -n $"Stopping unbound: "
|
||||
# stop it here, often "killproc unbound"
|
||||
killproc -p $pidfile unbound
|
||||
retval=$?
|
||||
[ $retval -eq 0 ] && rm -f $lockfile
|
||||
for mountfile in /dev/log /dev/random /etc/localtime /etc/resolv.conf /var/run/unbound
|
||||
do
|
||||
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}''${mountfile}'' /proc/mounts; then
|
||||
umount ${rootdir}$mountfile >/dev/null 2>&1
|
||||
fi;
|
||||
done
|
||||
echo
|
||||
}
|
||||
|
||||
restart() {
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
reload() {
|
||||
kill -HUP `cat $pidfile`
|
||||
}
|
||||
|
||||
force_reload() {
|
||||
restart
|
||||
}
|
||||
|
||||
rh_status() {
|
||||
# run checks to determine if the service is running or use generic status
|
||||
status -p $pidfile unbound
|
||||
}
|
||||
|
||||
rh_status_q() {
|
||||
rh_status -p $pidfile >/dev/null 2>&1
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart)
|
||||
restart
|
||||
;;
|
||||
reload)
|
||||
reload
|
||||
;;
|
||||
force-reload)
|
||||
force_reload
|
||||
;;
|
||||
status)
|
||||
rh_status
|
||||
;;
|
||||
condrestart|try-restart)
|
||||
rh_status_q || exit 0
|
||||
restart
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
|
||||
exit 2
|
||||
esac
|
||||
exit $?
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd >
|
||||
<plist version="1.0">
|
||||
<!--
|
||||
Unbound plist file for use by MacOSX launchd(8) using launchctl(1).
|
||||
Copy this file to /Library/LaunchDaemons. Launchd keeps unbound running.
|
||||
|
||||
Setup your unbound.conf with the following additional settings.
|
||||
server:
|
||||
do-daemonize: no
|
||||
username: ""
|
||||
chroot: ""
|
||||
directory: ""
|
||||
These actions are performed by launchd (for the option values, see below).
|
||||
|
||||
-->
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>unbound</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>unbound</string>
|
||||
</array>
|
||||
|
||||
<key>UserName</key>
|
||||
<string>unbound</string>
|
||||
|
||||
<key>RootDirectory</key>
|
||||
<string>/usr/local/etc/unbound</string>
|
||||
|
||||
<key>WorkingDirectory</key>
|
||||
<string>/usr/local/etc/unbound</string>
|
||||
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,11 +1,11 @@
|
||||
Summary: Validating, recursive, and caching DNS resolver
|
||||
Name: unbound
|
||||
Version: 0.12
|
||||
Version: 1.4.4
|
||||
Release: 1%{?dist}
|
||||
License: BSD
|
||||
Url: http://www.nlnetlabs.nl/unbound/
|
||||
Source: http://www.unbound.net/downloads/%{name}-%{version}.tar.gz
|
||||
Source1: unbound.init
|
||||
#Source1: unbound.init
|
||||
Group: System Environment/Daemons
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
BuildRequires: flex, openssl-devel
|
||||
@@ -32,17 +32,18 @@ The source code is under a BSD License.
|
||||
# This is a build using libldns builtin version, the resulting binaries
|
||||
# do not require libldns and this package does not have version dependencies.
|
||||
# Could be smaller using a dependency on libldns (use --with-ldns=).
|
||||
%configure --enable-debug --with-conf-file=%{_localstatedir}/%{name}/unbound.conf --disable-static --disable-rpath
|
||||
%configure --with-conf-file=%{_localstatedir}/%{name}/unbound.conf --disable-rpath
|
||||
|
||||
%build
|
||||
%{__make} %{?_smp_mflags}
|
||||
#%{__make} %{?_smp_mflags}
|
||||
make
|
||||
|
||||
%install
|
||||
rm -rf %{buildroot}
|
||||
%{__make} DESTDIR=%{buildroot} install
|
||||
install -d 0700 %{buildroot}%{_localstatedir}/%{name}
|
||||
install -d 0755 %{buildroot}%{_initrddir}
|
||||
install -m 0755 %{SOURCE1} %{buildroot}%{_initrddir}/unbound
|
||||
install -m 0755 contrib/unbound.init %{buildroot}%{_initrddir}/unbound
|
||||
# add symbolic link from /etc/unbound.conf -> /var/unbound/unbound.conf
|
||||
ln -s %{_localstatedir}/unbound/unbound.conf %{buildroot}%{_sysconfdir}/unbound.conf
|
||||
# remove static library from install (fedora packaging guidelines)
|
||||
@@ -91,6 +92,9 @@ if [ "$1" -ge "1" ]; then
|
||||
fi
|
||||
|
||||
%changelog
|
||||
* Thu May 22 2008 Wouter Wijngaards <wouter@nlnetlabs.nl> - 1.0.0
|
||||
- contrib changes from Patrick Vande Walle.
|
||||
|
||||
* Thu Apr 25 2008 Wouter Wijngaards <wouter@nlnetlabs.nl> - 0.12
|
||||
- Using parts from ports collection entry by Jaap Akkerhuis.
|
||||
- Using Fedoraproject wiki guidelines.
|
||||
|
||||
@@ -0,0 +1,346 @@
|
||||
# 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()")}
|
||||
%{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
|
||||
%endif
|
||||
|
||||
Summary: Validating, recursive, and caching DNS(SEC) resolver
|
||||
Name: unbound
|
||||
Version: 1.4.2
|
||||
Release: 1%{?dist}
|
||||
License: BSD
|
||||
Url: http://www.nlnetlabs.nl/unbound/
|
||||
Source: http://www.unbound.net/downloads/%{name}-%{version}.tar.gz
|
||||
Source1: unbound.init
|
||||
Source2: unbound.conf
|
||||
Source3: unbound.munin
|
||||
Source4: dlv.isc.org.key
|
||||
Patch1: unbound-1.2-glob.patch
|
||||
|
||||
Group: System Environment/Daemons
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
BuildRequires: flex, openssl-devel , ldns-devel >= 1.5.0,
|
||||
BuildRequires: libevent-devel
|
||||
%if %{with_python}
|
||||
BuildRequires: python-devel
|
||||
%endif
|
||||
|
||||
Requires(post): chkconfig
|
||||
Requires(preun): chkconfig
|
||||
Requires(preun): initscripts
|
||||
Requires(postun): initscripts
|
||||
Requires: ldns >= 1.5.0
|
||||
Requires(pre): shadow-utils
|
||||
|
||||
%description
|
||||
Unbound is a validating, recursive, and caching DNS(SEC) resolver.
|
||||
|
||||
The C implementation of Unbound is developed and maintained by NLnet
|
||||
Labs. It is based on ideas and algorithms taken from a java prototype
|
||||
developed by Verisign labs, Nominet, Kirei and ep.net.
|
||||
|
||||
Unbound is designed as a set of modular components, so that also
|
||||
DNSSEC (secure DNS) validation and stub-resolvers (that do not run
|
||||
as a server, but are linked into an application) are easily possible.
|
||||
|
||||
%package munin
|
||||
Summary: Plugin for the munin / munin-node monitoring package
|
||||
Group: System Environment/Daemons
|
||||
Requires: munin-node
|
||||
Requires: %{name} = %{version}-%{release}, bc
|
||||
|
||||
%description munin
|
||||
Plugin for the munin / munin-node monitoring package
|
||||
|
||||
%package devel
|
||||
Summary: Development package that includes the unbound header files
|
||||
Group: Development/Libraries
|
||||
Requires: %{name}-libs = %{version}-%{release}, openssl-devel, ldns-devel
|
||||
|
||||
%description devel
|
||||
The devel package contains the unbound library and the include files
|
||||
|
||||
%package libs
|
||||
Summary: Libraries used by the unbound server and client applications
|
||||
Group: Applications/System
|
||||
Requires(post): /sbin/ldconfig
|
||||
Requires(postun): /sbin/ldconfig
|
||||
Requires: openssl >= 0.9.8g-12
|
||||
|
||||
%description libs
|
||||
Contains libraries used by the unbound server and client applications
|
||||
|
||||
%if %{with_python}
|
||||
%package python
|
||||
Summary: Python modules and extensions for unbound
|
||||
Group: Applications/System
|
||||
Requires: %{name}-libs = %{version}-%{release}
|
||||
|
||||
%description python
|
||||
Python modules and extensions for unbound
|
||||
%endif
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
%patch1 -p1
|
||||
|
||||
%build
|
||||
%configure --with-ldns= --with-libevent --with-pthreads --with-ssl \
|
||||
--disable-rpath --enable-debug --disable-static \
|
||||
--with-conf-file=%{_sysconfdir}/%{name}/unbound.conf \
|
||||
--with-pidfile=%{_localstatedir}/run/%{name}/%{name}.pid \
|
||||
%if %{with_python}
|
||||
--with-pythonmodule --with-pyunbound \
|
||||
%endif
|
||||
--enable-sha2
|
||||
%{__make}
|
||||
|
||||
%install
|
||||
rm -rf %{buildroot}
|
||||
%{__make} DESTDIR=%{buildroot} install
|
||||
install -d 0755 %{buildroot}%{_initrddir}
|
||||
install -m 0755 %{SOURCE1} %{buildroot}%{_initrddir}/unbound
|
||||
install -m 0755 %{SOURCE2} %{buildroot}%{_sysconfdir}/unbound
|
||||
# Install munin plugin and its softlinks
|
||||
install -d 0755 %{buildroot}%{_sysconfdir}/munin/plugin-conf.d
|
||||
install -m 0644 %{SOURCE3} %{buildroot}%{_sysconfdir}/munin/plugin-conf.d/unbound
|
||||
install -d 0755 %{buildroot}%{_datadir}/munin/plugins/
|
||||
install -m 0755 contrib/unbound_munin_ %{buildroot}%{_datadir}/munin/plugins/unbound
|
||||
for plugin in unbound_munin_hits unbound_munin_queue unbound_munin_memory unbound_munin_by_type unbound_munin_by_class unbound_munin_by_opcode unbound_munin_by_rcode unbound_munin_by_flags unbound_munin_histogram; do
|
||||
ln -s unbound %{buildroot}%{_datadir}/munin/plugins/$plugin
|
||||
done
|
||||
|
||||
# install DLV key
|
||||
install -m 0644 %{SOURCE4} %{buildroot}%{_sysconfdir}/unbound/
|
||||
|
||||
# remove static library from install (fedora packaging guidelines)
|
||||
rm -rf %{buildroot}%{_libdir}/*.la
|
||||
|
||||
mkdir -p %{buildroot}%{_localstatedir}/run/unbound
|
||||
|
||||
%clean
|
||||
rm -rf ${RPM_BUILD_ROOT}
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%doc doc/README doc/CREDITS doc/LICENSE doc/FEATURES
|
||||
%attr(0755,root,root) %{_initrddir}/%{name}
|
||||
%attr(0755,root,root) %dir %{_sysconfdir}/%{name}
|
||||
%attr(0755,unbound,unbound) %dir %{_localstatedir}/run/%{name}
|
||||
%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/%{name}/unbound.conf
|
||||
%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/%{name}/dlv.isc.org.key
|
||||
%{_sbindir}/*
|
||||
%{_mandir}/*/*
|
||||
|
||||
%if %{with_python}
|
||||
%files python
|
||||
%{python_sitelib}/*
|
||||
%endif
|
||||
|
||||
%files munin
|
||||
%defattr(-,root,root,-)
|
||||
%config(noreplace) %{_sysconfdir}/munin/plugin-conf.d/unbound
|
||||
%{_datadir}/munin/plugins/unbound*
|
||||
|
||||
%files devel
|
||||
%defattr(-,root,root,-)
|
||||
%{_libdir}/libunbound.so
|
||||
%{_includedir}/unbound.h
|
||||
%doc README
|
||||
|
||||
%files libs
|
||||
%defattr(-,root,root,-)
|
||||
%{_libdir}/libunbound.so.*
|
||||
%doc doc/README doc/LICENSE
|
||||
|
||||
%pre
|
||||
getent group unbound >/dev/null || groupadd -r unbound
|
||||
getent passwd unbound >/dev/null || \
|
||||
useradd -r -g unbound -d %{_sysconfdir}/unbound -s /sbin/nologin \
|
||||
-c "Unbound DNS resolver" unbound
|
||||
exit 0
|
||||
|
||||
%post
|
||||
/sbin/chkconfig --add %{name}
|
||||
# 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
|
||||
|
||||
%preun
|
||||
if [ "$1" -eq 0 ]; then
|
||||
/sbin/service %{name} stop >/dev/null 2>&1
|
||||
/sbin/chkconfig --del %{name}
|
||||
fi
|
||||
|
||||
%postun
|
||||
if [ "$1" -ge "1" ]; then
|
||||
/sbin/service %{name} condrestart >/dev/null 2>&1 || :
|
||||
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
|
||||
|
||||
* Sat Jun 20 2009 Paul Wouters <paul@xelerance.com> - 1.3.0-1
|
||||
- Updated to 1.3.0
|
||||
- Added unbound-python sub package. disabled for now
|
||||
- Patch from svn to fix DLV lookups
|
||||
- Patches from svn to detect wrong truncated response from BIND 9.6.1 with
|
||||
minimal-responses)
|
||||
- Added Default-Start and Default-Stop to unbound.init
|
||||
- Re-enabled --enable-sha2
|
||||
- Re-enabled glob.patch
|
||||
|
||||
* Wed May 20 2009 Paul Wouters <paul@xelerance.com> - 1.2.1-7
|
||||
- unbound-iterator.patch was not commited
|
||||
|
||||
* Wed May 20 2009 Paul Wouters <paul@xelerance.com> - 1.2.1-6
|
||||
- Fix for https://bugzilla.redhat.com/show_bug.cgi?id=499793
|
||||
|
||||
* Tue Mar 17 2009 Paul Wouters <paul@xelerance.com> - 1.2.1-5
|
||||
- Use --nocheck to avoid giving an error on missing unbound-remote certs/keys
|
||||
|
||||
* Tue Mar 10 2009 Adam Tkac <atkac redhat com> - 1.2.1-4
|
||||
- enable DNSSEC only if it is enabled in sysconfig/dnssec
|
||||
|
||||
* Mon Mar 09 2009 Adam Tkac <atkac redhat com> - 1.2.1-3
|
||||
- add DNSSEC support to initscript and enabled it per default
|
||||
- add requires dnssec-conf
|
||||
|
||||
* Wed Feb 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.2.1-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
|
||||
|
||||
* Tue Feb 10 2009 Paul Wouters <paul@xelerance.com - 1.2.1-1
|
||||
- updated to 1.2.1
|
||||
|
||||
* Sun Jan 18 2009 Tomas Mraz <tmraz@redhat.com> - 1.2.0-2
|
||||
- rebuild with new openssl
|
||||
|
||||
* Wed Jan 14 2009 Paul Wouters <paul@xelerance.com - 1.2.0-1
|
||||
- Updated to 1.2.0
|
||||
- Added dependancy on minimum SSL for CVE-2008-5077
|
||||
- Added dependancy on bc for unbound-munin
|
||||
- Added minimum requirement of libevent 1.4.5. Crashes with older versions
|
||||
(note: libevent is stale in EL-4 and not in EL-5, needs fixing there)
|
||||
- Removed dependancy on selinux-policy (will get used when available)
|
||||
- Enable options as per draft-wijngaards-dnsext-resolver-side-mitigation-00.txt
|
||||
- Enable unwanted-reply-threshold to mitigate against a Kaminsky attack
|
||||
- Enable val-clean-additional to drop addition unsigned data from signed
|
||||
response.
|
||||
- Removed patches (got merged into upstream)
|
||||
|
||||
* Mon Jan 5 2009 Paul Wouters <paul@xelerance.com> - 1.1.1-7
|
||||
- Modified scandir patch to silently fail when wildcard matches nothing
|
||||
- Patch to allow unbound-checkconf to find empty wildcard matches
|
||||
|
||||
* Mon Jan 5 2009 Paul Wouters <paul@xelerance.com> - 1.1.1-6
|
||||
- Added scandir patch for trusted-keys-file: option, which
|
||||
is used to load multiple dnssec keys in bind file format
|
||||
|
||||
* Mon Dec 8 2008 Paul Wouters <paul@xelerance.com> - 1.1.1-4
|
||||
- Added Requires: for selinux-policy >= 3.5.13-33 for proper SElinux rules.
|
||||
|
||||
* Mon Dec 1 2008 Paul Wouters <paul@xelerance.com> - 1.1.1-3
|
||||
- We did not own the /etc/unbound directory (#474020)
|
||||
- Fixed cvs anomalies
|
||||
|
||||
* Fri Nov 28 2008 Adam Tkac <atkac redhat com> - 1.1.1-2
|
||||
- removed all obsolete chroot related stuff
|
||||
- label control certs after generation correctly
|
||||
|
||||
* Thu Nov 20 2008 Paul Wouters <paul@xelerance.com> - 1.1.1-1
|
||||
- Updated to unbound 1.1.1 which fixes a crasher and
|
||||
addresses nlnetlabs bug #219
|
||||
|
||||
* Wed Nov 19 2008 Paul Wouters <paul@xelerance.com> - 1.1.0-3
|
||||
- Remove the chroot, obsoleted by SElinux
|
||||
- Add additional munin plugin links supported by unbound plugin
|
||||
- Move configuration directory from /var/lib/unbound to /etc/unbound
|
||||
- Modified unbound.init and unbound.conf to account for chroot changes
|
||||
- Updated unbound.conf with new available options
|
||||
- Enabled dns-0x20 protection per default
|
||||
|
||||
* Wed Nov 19 2008 Adam Tkac <atkac redhat com> - 1.1.0-2
|
||||
- unbound-1.1.0-log_open.patch
|
||||
- make sure log is opened before chroot call
|
||||
- tracked as http://www.nlnetlabs.nl/bugs/show_bug.cgi?id=219
|
||||
- removed /dev/log and /var/run/unbound and /etc/resolv.conf from
|
||||
chroot, not needed
|
||||
- don't mount files in chroot, it causes problems during updates
|
||||
- fixed typo in default config file
|
||||
|
||||
* Fri Nov 14 2008 Paul Wouters <paul@xelerance.com> - 1.1.0-1
|
||||
- Updated to version 1.1.0
|
||||
- Updated unbound.conf's statistics options and remote-control
|
||||
to work properly for munin
|
||||
- Added unbound-munin package
|
||||
- Generate unbound remote-control key/certs on first startup
|
||||
- Required ldns is now 1.4.0
|
||||
|
||||
* Wed Oct 22 2008 Paul Wouters <paul@xelerance.com> - 1.0.2-5
|
||||
- Only call ldconfig in -libs package
|
||||
- Move configure into build section
|
||||
- devel subpackage should only depend on libs subpackage
|
||||
|
||||
* Tue Oct 21 2008 Paul Wouters <paul@xelerance.com> - 1.0.2-4
|
||||
- Fix CFLAGS getting lost in build
|
||||
- Don't enable interface-automatic:yes because that
|
||||
causes unbound to listen on 0.0.0.0 instead of 127.0.0.1
|
||||
|
||||
* Sun Oct 19 2008 Paul Wouters <paul@xelerance.com> - 1.0.2-3
|
||||
- Split off unbound-libs, make build verbose
|
||||
|
||||
* Thu Oct 9 2008 Paul Wouters <paul@xelerance.com> - 1.0.2-2
|
||||
- FSB compliance, chroot fixes, initscript fixes
|
||||
|
||||
* Thu Sep 11 2008 Paul Wouters <paul@xelerance.com> - 1.0.2-1
|
||||
- Upgraded to 1.0.2
|
||||
|
||||
* Wed Jul 16 2008 Paul Wouters <paul@xelerance.com> - 1.0.1-1
|
||||
- upgraded to new release
|
||||
|
||||
* Wed May 21 2008 Paul Wouters <paul@xelerance.com> - 1.0.0-2
|
||||
- Build against ldns-1.3.0
|
||||
|
||||
* Wed May 21 2008 Paul Wouters <paul@xelerance.com> - 1.0.0-1
|
||||
- Split of -devel package, fixed dependancies, make rpmlint happy
|
||||
|
||||
* Thu Apr 25 2008 Wouter Wijngaards <wouter@nlnetlabs.nl> - 0.12
|
||||
- Using parts from ports collection entry by Jaap Akkerhuis.
|
||||
- Using Fedoraproject wiki guidelines.
|
||||
|
||||
* Wed Apr 23 2008 Wouter Wijngaards <wouter@nlnetlabs.nl> - 0.11
|
||||
- Initial version.
|
||||
Binary file not shown.
Executable
+553
@@ -0,0 +1,553 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# plugin for munin to monitor usage of unbound servers.
|
||||
#
|
||||
# (C) 2008 W.C.A. Wijngaards. BSD Licensed.
|
||||
#
|
||||
# To install; enable statistics and unbound-control in unbound.conf
|
||||
# server: extended-statistics: yes
|
||||
# statistics-cumulative: no
|
||||
# statistics-interval: 0
|
||||
# remote-control: control-enable: yes
|
||||
# Run the command unbound-control-setup to generate the key files.
|
||||
#
|
||||
# Environment variables for this script
|
||||
# statefile - where to put temporary statefile.
|
||||
# unbound_conf - where the unbound.conf file is located.
|
||||
# unbound_control - where to find unbound-control executable.
|
||||
# spoof_warn - what level to warn about spoofing
|
||||
# spoof_crit - what level to crit about spoofing
|
||||
#
|
||||
# You can set them in your munin/plugin-conf.d/plugins.conf file
|
||||
# with:
|
||||
# [unbound*]
|
||||
# user root
|
||||
# env.statefile /usr/local/var/munin/plugin-state/unbound-state
|
||||
# env.unbound_conf /usr/local/etc/unbound/unbound.conf
|
||||
# env.unbound_control /usr/local/sbin/unbound-control
|
||||
# env.spoof_warn 1000
|
||||
# env.spoof_crit 100000
|
||||
#
|
||||
# This plugin can create different graphs depending on what name
|
||||
# you link it as (with ln -s) into the plugins directory
|
||||
# You can link it multiple times.
|
||||
# If you are only a casual user, the _hits and _by_type are most interesting,
|
||||
# possibly followed by _by_rcode.
|
||||
#
|
||||
# unbound_munin_hits - base volume, cache hits, unwanted traffic
|
||||
# unbound_munin_queue - to monitor the internal requestlist
|
||||
# unbound_munin_memory - memory usage
|
||||
# unbound_munin_by_type - incoming queries by type
|
||||
# unbound_munin_by_class - incoming queries by class
|
||||
# unbound_munin_by_opcode - incoming queries by opcode
|
||||
# unbound_munin_by_rcode - answers by rcode, validation status
|
||||
# unbound_munin_by_flags - incoming queries by flags
|
||||
# unbound_munin_histogram - histogram of query resolving times
|
||||
#
|
||||
# Magic markers - optional - used by installation scripts and
|
||||
# munin-config:
|
||||
#
|
||||
#%# family=contrib
|
||||
#%# capabilities=autoconf suggest
|
||||
|
||||
# POD documentation
|
||||
: <<=cut
|
||||
=head1 NAME
|
||||
|
||||
unbound_munin_ - Munin plugin to monitor the Unbound DNS resolver.
|
||||
|
||||
=head1 APPLICABLE SYSTEMS
|
||||
|
||||
System with unbound daemon.
|
||||
|
||||
=head1 CONFIGURATION
|
||||
|
||||
[unbound*]
|
||||
user root
|
||||
env.statefile /usr/local/var/munin/plugin-state/unbound-state
|
||||
env.unbound_conf /usr/local/etc/unbound/unbound.conf
|
||||
env.unbound_control /usr/local/sbin/unbound-control
|
||||
env.spoof_warn 1000
|
||||
env.spoof_crit 100000
|
||||
|
||||
Use the .env settings to override the defaults.
|
||||
|
||||
=head1 USAGE
|
||||
|
||||
Can be used to present different graphs. Use ln -s for that name in
|
||||
the plugins directory to enable the graph.
|
||||
unbound_munin_hits - base volume, cache hits, unwanted traffic
|
||||
unbound_munin_queue - to monitor the internal requestlist
|
||||
unbound_munin_memory - memory usage
|
||||
unbound_munin_by_type - incoming queries by type
|
||||
unbound_munin_by_class - incoming queries by class
|
||||
unbound_munin_by_opcode - incoming queries by opcode
|
||||
unbound_munin_by_rcode - answers by rcode, validation status
|
||||
unbound_munin_by_flags - incoming queries by flags
|
||||
unbound_munin_histogram - histogram of query resolving times
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Copyright 2008 W.C.A. Wijngaards
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
BSD
|
||||
|
||||
=cut
|
||||
|
||||
state=${statefile:-/usr/local/var/munin/plugin-state/unbound-state}
|
||||
conf=${unbound_conf:-/usr/local/etc/unbound/unbound.conf}
|
||||
ctrl=${unbound_control:-/usr/local/sbin/unbound-control}
|
||||
warn=${spoof_warn:-1000}
|
||||
crit=${spoof_crit:-100000}
|
||||
lock=$state.lock
|
||||
|
||||
# number of seconds between polling attempts.
|
||||
# makes the statefile hang around for at least this many seconds,
|
||||
# so that multiple links of this script can share the results.
|
||||
lee=55
|
||||
|
||||
# to keep things within 19 characters
|
||||
ABBREV="-e s/total/t/ -e s/thread/t/ -e s/num/n/ -e s/query/q/ -e s/answer/a/ -e s/unwanted/u/ -e s/requestlist/ql/ -e s/type/t/ -e s/class/c/ -e s/opcode/o/ -e s/rcode/r/ -e s/edns/e/ -e s/mem/m/ -e s/cache/c/ -e s/mod/m/"
|
||||
|
||||
# get value from $1 into return variable $value
|
||||
get_value ( ) {
|
||||
value="`grep '^'$1'=' $state | sed -e 's/^.*=//'`"
|
||||
if test "$value"x = ""x; then
|
||||
value="0"
|
||||
fi
|
||||
}
|
||||
|
||||
# download the state from the unbound server.
|
||||
get_state ( ) {
|
||||
# obtain lock for fetching the state
|
||||
# because there is a race condition in fetching and writing to file
|
||||
|
||||
# see if the lock is stale, if so, take it
|
||||
if test -f $lock ; then
|
||||
pid="`cat $lock 2>&1`"
|
||||
kill -0 "$pid" >/dev/null 2>&1
|
||||
if test $? -ne 0 -a "$pid" != $$ ; then
|
||||
echo $$ >$lock
|
||||
fi
|
||||
fi
|
||||
|
||||
i=0
|
||||
while test ! -f $lock || test "`cat $lock 2>&1`" != $$; do
|
||||
while test -f $lock; do
|
||||
# wait
|
||||
i=`expr $i + 1`
|
||||
if test $i -gt 1000; then
|
||||
sleep 1;
|
||||
fi
|
||||
if test $i -gt 1500; then
|
||||
echo "error locking $lock" "=" `cat $lock`
|
||||
rm -f $lock
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
# try to get it
|
||||
echo $$ >$lock
|
||||
done
|
||||
# do not refetch if the file exists and only LEE seconds old
|
||||
if test -f $state; then
|
||||
now=`date +%s`
|
||||
get_value "time.now"
|
||||
value="`echo $value | sed -e 's/\..*$//'`"
|
||||
if test $now -lt `expr $value + $lee`; then
|
||||
rm -f $lock
|
||||
return
|
||||
fi
|
||||
fi
|
||||
$ctrl -c $conf stats > $state
|
||||
if test $? -ne 0; then
|
||||
echo "error retrieving data from unbound server"
|
||||
rm -f $lock
|
||||
exit 1
|
||||
fi
|
||||
rm -f $lock
|
||||
}
|
||||
|
||||
if test "$1" = "autoconf" ; then
|
||||
if test ! -f $conf; then
|
||||
echo no "($conf does not exist)"
|
||||
exit 1
|
||||
fi
|
||||
if test ! -d `dirname $state`; then
|
||||
echo no "($state directory does not exist)"
|
||||
exit 1
|
||||
fi
|
||||
echo yes
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test "$1" = "suggest" ; then
|
||||
echo "hits"
|
||||
echo "queue"
|
||||
echo "memory"
|
||||
echo "by_type"
|
||||
echo "by_class"
|
||||
echo "by_opcode"
|
||||
echo "by_rcode"
|
||||
echo "by_flags"
|
||||
echo "histogram"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# determine my type, by name
|
||||
id=`echo $0 | sed -e 's/^.*unbound_munin_//'`
|
||||
if test "$id"x = ""x; then
|
||||
# some default to keep people sane.
|
||||
id="hits"
|
||||
fi
|
||||
|
||||
# if $1 exists in statefile, config is echoed with label $2
|
||||
exist_config ( ) {
|
||||
mn=`echo $1 | sed $ABBREV | tr . _`
|
||||
if grep '^'$1'=' $state >/dev/null 2>&1; then
|
||||
echo "$mn.label $2"
|
||||
echo "$mn.min 0"
|
||||
fi
|
||||
}
|
||||
|
||||
# print label and min 0 for a name $1 in unbound format
|
||||
p_config ( ) {
|
||||
mn=`echo $1 | sed $ABBREV | tr . _`
|
||||
echo $mn.label "$2"
|
||||
echo $mn.min 0
|
||||
}
|
||||
|
||||
if test "$1" = "config" ; then
|
||||
if test ! -f $state; then
|
||||
get_state
|
||||
fi
|
||||
case $id in
|
||||
hits)
|
||||
echo "graph_title Unbound DNS traffic and cache hits"
|
||||
echo "graph_args --base 1000 -l 0"
|
||||
echo "graph_vlabel queries / second"
|
||||
echo "graph_category DNS"
|
||||
for x in thread0.num.queries thread1.num.queries \
|
||||
thread2.num.queries thread3.num.queries thread4.num.queries \
|
||||
thread5.num.queries thread6.num.queries thread7.num.queries; do
|
||||
exist_config $x "queries handled by `basename $x .num.queries`"
|
||||
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"
|
||||
p_config "unwanted.replies" "unwanted or unsolicited replies"
|
||||
echo "u_replies.warning $warn"
|
||||
echo "u_replies.critical $crit"
|
||||
echo "graph_info DNS queries to the recursive resolver. The unwanted replies could be innocent duplicate packets, late replies, or spoof threats."
|
||||
;;
|
||||
queue)
|
||||
echo "graph_title Unbound requestlist size"
|
||||
echo "graph_args --base 1000 -l 0"
|
||||
echo "graph_vlabel number of queries"
|
||||
echo "graph_category DNS"
|
||||
p_config "total.requestlist.avg" "Average size of queue on insert"
|
||||
p_config "total.requestlist.max" "Max size of queue (in 5 min)"
|
||||
p_config "total.requestlist.overwritten" "Number of queries replaced by new ones"
|
||||
p_config "total.requestlist.exceeded" "Number of queries dropped due to lack of space"
|
||||
echo "graph_info The queries that did not hit the cache and need recursion service take up space in the requestlist. If there are too many queries, first queries get overwritten, and at last resort dropped."
|
||||
;;
|
||||
memory)
|
||||
echo "graph_title Unbound memory usage"
|
||||
echo "graph_args --base 1024 -l 0"
|
||||
echo "graph_vlabel memory used in bytes"
|
||||
echo "graph_category DNS"
|
||||
p_config "mem.total.sbrk" "Total memory"
|
||||
p_config "mem.cache.rrset" "RRset cache memory"
|
||||
p_config "mem.cache.message" "Message cache memory"
|
||||
p_config "mem.mod.iterator" "Iterator module memory"
|
||||
p_config "mem.mod.validator" "Validator module and key cache memory"
|
||||
echo "graph_info The memory used by unbound."
|
||||
;;
|
||||
by_type)
|
||||
echo "graph_title Unbound DNS queries by type"
|
||||
echo "graph_args --base 1000 -l 0"
|
||||
echo "graph_vlabel queries / second"
|
||||
echo "graph_category DNS"
|
||||
for x in `grep "^num.query.type" $state`; do
|
||||
nm=`echo $x | sed -e 's/=.*$//'`
|
||||
tp=`echo $nm | sed -e s/num.query.type.//`
|
||||
p_config "$nm" "$tp"
|
||||
done
|
||||
echo "graph_info queries by DNS RR type queried for"
|
||||
;;
|
||||
by_class)
|
||||
echo "graph_title Unbound DNS queries by class"
|
||||
echo "graph_args --base 1000 -l 0"
|
||||
echo "graph_vlabel queries / second"
|
||||
echo "graph_category DNS"
|
||||
for x in `grep "^num.query.class" $state`; do
|
||||
nm=`echo $x | sed -e 's/=.*$//'`
|
||||
tp=`echo $nm | sed -e s/num.query.class.//`
|
||||
p_config "$nm" "$tp"
|
||||
done
|
||||
echo "graph_info queries by DNS RR class queried for."
|
||||
;;
|
||||
by_opcode)
|
||||
echo "graph_title Unbound DNS queries by opcode"
|
||||
echo "graph_args --base 1000 -l 0"
|
||||
echo "graph_vlabel queries / second"
|
||||
echo "graph_category DNS"
|
||||
for x in `grep "^num.query.opcode" $state`; do
|
||||
nm=`echo $x | sed -e 's/=.*$//'`
|
||||
tp=`echo $nm | sed -e s/num.query.opcode.//`
|
||||
p_config "$nm" "$tp"
|
||||
done
|
||||
echo "graph_info queries by opcode in the query packet."
|
||||
;;
|
||||
by_rcode)
|
||||
echo "graph_title Unbound DNS answers by return code"
|
||||
echo "graph_args --base 1000 -l 0"
|
||||
echo "graph_vlabel answer packets / second"
|
||||
echo "graph_category DNS"
|
||||
for x in `grep "^num.answer.rcode" $state`; do
|
||||
nm=`echo $x | sed -e 's/=.*$//'`
|
||||
tp=`echo $nm | sed -e s/num.answer.rcode.//`
|
||||
p_config "$nm" "$tp"
|
||||
done
|
||||
p_config "num.answer.secure" "answer secure"
|
||||
p_config "num.answer.bogus" "answer bogus"
|
||||
p_config "num.rrset.bogus" "num rrsets marked bogus"
|
||||
echo "graph_info answers sorted by return value. rrsets bogus is the number of rrsets marked bogus per second by the validator"
|
||||
;;
|
||||
by_flags)
|
||||
echo "graph_title Unbound DNS incoming queries by flags"
|
||||
echo "graph_args --base 1000 -l 0"
|
||||
echo "graph_vlabel queries / second"
|
||||
echo "graph_category DNS"
|
||||
p_config "num.query.flags.QR" "QR (query reply) flag"
|
||||
p_config "num.query.flags.AA" "AA (auth answer) flag"
|
||||
p_config "num.query.flags.TC" "TC (truncated) flag"
|
||||
p_config "num.query.flags.RD" "RD (recursion desired) flag"
|
||||
p_config "num.query.flags.RA" "RA (rec avail) flag"
|
||||
p_config "num.query.flags.Z" "Z (zero) flag"
|
||||
p_config "num.query.flags.AD" "AD (auth data) flag"
|
||||
p_config "num.query.flags.CD" "CD (check disabled) flag"
|
||||
p_config "num.query.edns.present" "EDNS OPT present"
|
||||
p_config "num.query.edns.DO" "DO (DNSSEC OK) flag"
|
||||
echo "graph_info This graphs plots the flags inside incoming queries. For example, if QR, AA, TC, RA, Z flags are set, the query can be rejected. RD, AD, CD and DO are legitimately set by some software."
|
||||
;;
|
||||
histogram)
|
||||
echo "graph_title Unbound DNS histogram of reply time"
|
||||
echo "graph_args --base 1000 -l 0"
|
||||
echo "graph_vlabel queries / second"
|
||||
echo "graph_category DNS"
|
||||
echo hcache.label "cache hits"
|
||||
echo hcache.min 0
|
||||
echo hcache.draw AREA
|
||||
echo hcache.colour 999999
|
||||
echo h64ms.label "0 msec - 66 msec"
|
||||
echo h64ms.min 0
|
||||
echo h64ms.draw STACK
|
||||
echo h64ms.colour 0000FF
|
||||
echo h128ms.label "66 msec - 131 msec"
|
||||
echo h128ms.min 0
|
||||
echo h128ms.colour 1F00DF
|
||||
echo h128ms.draw STACK
|
||||
echo h256ms.label "131 msec - 262 msec"
|
||||
echo h256ms.min 0
|
||||
echo h256ms.draw STACK
|
||||
echo h256ms.colour 3F00BF
|
||||
echo h512ms.label "262 msec - 524 msec"
|
||||
echo h512ms.min 0
|
||||
echo h512ms.draw STACK
|
||||
echo h512ms.colour 5F009F
|
||||
echo h1s.label "524 msec - 1 sec"
|
||||
echo h1s.min 0
|
||||
echo h1s.draw STACK
|
||||
echo h1s.colour 7F007F
|
||||
echo h2s.label "1 sec - 2 sec"
|
||||
echo h2s.min 0
|
||||
echo h2s.draw STACK
|
||||
echo h2s.colour 9F005F
|
||||
echo h4s.label "2 sec - 4 sec"
|
||||
echo h4s.min 0
|
||||
echo h4s.draw STACK
|
||||
echo h4s.colour BF003F
|
||||
echo h8s.label "4 sec - 8 sec"
|
||||
echo h8s.min 0
|
||||
echo h8s.draw STACK
|
||||
echo h8s.colour DF001F
|
||||
echo h16s.label "8 sec - ..."
|
||||
echo h16s.min 0
|
||||
echo h16s.draw STACK
|
||||
echo h16s.colour FF0000
|
||||
echo "graph_info Histogram of the reply times for queries."
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# do the stats itself
|
||||
get_state
|
||||
|
||||
# get the time elapsed
|
||||
get_value "time.elapsed"
|
||||
if test $value = 0 || test $value = "0.000000"; then
|
||||
echo "error: time elapsed 0 or could not retrieve data"
|
||||
exit 1
|
||||
fi
|
||||
elapsed="$value"
|
||||
|
||||
# print value for $1 / elapsed
|
||||
print_qps ( ) {
|
||||
mn=`echo $1 | sed $ABBREV | tr . _`
|
||||
get_value $1
|
||||
echo "$mn.value" `echo scale=6';' $value / $elapsed | bc `
|
||||
}
|
||||
|
||||
# print qps if line already found in $2
|
||||
print_qps_line ( ) {
|
||||
mn=`echo $1 | sed $ABBREV | tr . _`
|
||||
value="`echo $2 | sed -e 's/^.*=//'`"
|
||||
echo "$mn.value" `echo scale=6';' $value / $elapsed | bc `
|
||||
}
|
||||
|
||||
# print value for $1
|
||||
print_value ( ) {
|
||||
mn=`echo $1 | sed $ABBREV | tr . _`
|
||||
get_value $1
|
||||
echo "$mn.value" $value
|
||||
}
|
||||
|
||||
case $id in
|
||||
hits)
|
||||
for x in thread0.num.queries thread1.num.queries thread2.num.queries \
|
||||
thread3.num.queries thread4.num.queries thread5.num.queries \
|
||||
thread6.num.queries thread7.num.queries total.num.queries \
|
||||
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
|
||||
done
|
||||
;;
|
||||
queue)
|
||||
for x in total.requestlist.avg total.requestlist.max \
|
||||
total.requestlist.overwritten total.requestlist.exceeded; do
|
||||
print_value $x
|
||||
done
|
||||
;;
|
||||
memory)
|
||||
mn=`echo mem.total.sbrk | sed $ABBREV | tr . _`
|
||||
get_value 'mem.total.sbrk'
|
||||
if test $value -eq 0; then
|
||||
chk=`echo $ctrl | sed -e 's/-control$/-checkconf/'`
|
||||
pidf=`$chk -o pidfile $conf 2>&1`
|
||||
pid=`cat $pidf 2>&1`
|
||||
value=`ps -p "$pid" -o rss= 2>&1`
|
||||
if test "`expr $value + 1 - 1 2>&1`" -eq "$value" 2>&1; then
|
||||
value=`expr $value \* 1024`
|
||||
else
|
||||
value=0
|
||||
fi
|
||||
fi
|
||||
echo "$mn.value" $value
|
||||
for x in mem.cache.rrset mem.cache.message \
|
||||
mem.mod.iterator mem.mod.validator; do
|
||||
print_value $x
|
||||
done
|
||||
;;
|
||||
by_type)
|
||||
for x in `grep "^num.query.type" $state`; do
|
||||
nm=`echo $x | sed -e 's/=.*$//'`
|
||||
print_qps_line $nm $x
|
||||
done
|
||||
;;
|
||||
by_class)
|
||||
for x in `grep "^num.query.class" $state`; do
|
||||
nm=`echo $x | sed -e 's/=.*$//'`
|
||||
print_qps_line $nm $x
|
||||
done
|
||||
;;
|
||||
by_opcode)
|
||||
for x in `grep "^num.query.opcode" $state`; do
|
||||
nm=`echo $x | sed -e 's/=.*$//'`
|
||||
print_qps_line $nm $x
|
||||
done
|
||||
;;
|
||||
by_rcode)
|
||||
for x in `grep "^num.answer.rcode" $state`; do
|
||||
nm=`echo $x | sed -e 's/=.*$//'`
|
||||
print_qps_line $nm $x
|
||||
done
|
||||
print_qps "num.answer.secure"
|
||||
print_qps "num.answer.bogus"
|
||||
print_qps "num.rrset.bogus"
|
||||
;;
|
||||
by_flags)
|
||||
for x in num.query.flags.QR num.query.flags.AA num.query.flags.TC num.query.flags.RD num.query.flags.RA num.query.flags.Z num.query.flags.AD num.query.flags.CD num.query.edns.present num.query.edns.DO; do
|
||||
print_qps $x
|
||||
done
|
||||
;;
|
||||
histogram)
|
||||
get_value total.num.cachehits
|
||||
echo hcache.value `echo scale=6';' $value / $elapsed | bc `
|
||||
r=0
|
||||
for x in histogram.000000.000000.to.000000.000001 \
|
||||
histogram.000000.000001.to.000000.000002 \
|
||||
histogram.000000.000002.to.000000.000004 \
|
||||
histogram.000000.000004.to.000000.000008 \
|
||||
histogram.000000.000008.to.000000.000016 \
|
||||
histogram.000000.000016.to.000000.000032 \
|
||||
histogram.000000.000032.to.000000.000064 \
|
||||
histogram.000000.000064.to.000000.000128 \
|
||||
histogram.000000.000128.to.000000.000256 \
|
||||
histogram.000000.000256.to.000000.000512 \
|
||||
histogram.000000.000512.to.000000.001024 \
|
||||
histogram.000000.001024.to.000000.002048 \
|
||||
histogram.000000.002048.to.000000.004096 \
|
||||
histogram.000000.004096.to.000000.008192 \
|
||||
histogram.000000.008192.to.000000.016384 \
|
||||
histogram.000000.016384.to.000000.032768 \
|
||||
histogram.000000.032768.to.000000.065536; do
|
||||
get_value $x
|
||||
r=`expr $r + $value`
|
||||
done
|
||||
echo h64ms.value `echo scale=6';' $r / $elapsed | bc `
|
||||
get_value histogram.000000.065536.to.000000.131072
|
||||
echo h128ms.value `echo scale=6';' $value / $elapsed | bc `
|
||||
get_value histogram.000000.131072.to.000000.262144
|
||||
echo h256ms.value `echo scale=6';' $value / $elapsed | bc `
|
||||
get_value histogram.000000.262144.to.000000.524288
|
||||
echo h512ms.value `echo scale=6';' $value / $elapsed | bc `
|
||||
get_value histogram.000000.524288.to.000001.000000
|
||||
echo h1s.value `echo scale=6';' $value / $elapsed | bc `
|
||||
get_value histogram.000001.000000.to.000002.000000
|
||||
echo h2s.value `echo scale=6';' $value / $elapsed | bc `
|
||||
get_value histogram.000002.000000.to.000004.000000
|
||||
echo h4s.value `echo scale=6';' $value / $elapsed | bc `
|
||||
get_value histogram.000004.000000.to.000008.000000
|
||||
echo h8s.value `echo scale=6';' $value / $elapsed | bc `
|
||||
r=0
|
||||
for x in histogram.000008.000000.to.000016.000000 \
|
||||
histogram.000016.000000.to.000032.000000 \
|
||||
histogram.000032.000000.to.000064.000000 \
|
||||
histogram.000064.000000.to.000128.000000 \
|
||||
histogram.000128.000000.to.000256.000000 \
|
||||
histogram.000256.000000.to.000512.000000 \
|
||||
histogram.000512.000000.to.001024.000000 \
|
||||
histogram.001024.000000.to.002048.000000 \
|
||||
histogram.002048.000000.to.004096.000000 \
|
||||
histogram.004096.000000.to.008192.000000 \
|
||||
histogram.008192.000000.to.016384.000000 \
|
||||
histogram.016384.000000.to.032768.000000 \
|
||||
histogram.032768.000000.to.065536.000000 \
|
||||
histogram.065536.000000.to.131072.000000 \
|
||||
histogram.131072.000000.to.262144.000000 \
|
||||
histogram.262144.000000.to.524288.000000; do
|
||||
get_value $x
|
||||
r=`expr $r + $value`
|
||||
done
|
||||
echo h16s.value `echo scale=6';' $r / $elapsed | bc `
|
||||
;;
|
||||
esac
|
||||
Executable
+158
@@ -0,0 +1,158 @@
|
||||
#!/bin/sh
|
||||
# update-anchor.sh, update a trust anchor.
|
||||
# Copyright 2008, W.C.A. Wijngaards
|
||||
# This file is BSD licensed, see doc/LICENSE.
|
||||
|
||||
# which validating lookup to use.
|
||||
ubhost=unbound-host
|
||||
|
||||
usage ( )
|
||||
{
|
||||
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"
|
||||
echo " -b causes keyfile to be made in bind format."
|
||||
echo " without -b the file is made in unbound format."
|
||||
echo " "
|
||||
echo "alternate:"
|
||||
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
|
||||
}
|
||||
|
||||
if test $# -eq 0; then
|
||||
usage
|
||||
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"
|
||||
filearg='-F'
|
||||
fi
|
||||
if test $# -ne 2; then
|
||||
echo "arguments wrong."
|
||||
usage
|
||||
fi
|
||||
|
||||
do_update ( ) {
|
||||
# arguments: <zonename> <keyfile>
|
||||
zonename="$1"
|
||||
keyfile="$2"
|
||||
tmpfile="/tmp/update-anchor.$$"
|
||||
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"
|
||||
echo "Cause: $ubhost lookup failed"
|
||||
echo " (Is the domain decommissioned? Is connectivity lost?)"
|
||||
return 2
|
||||
fi
|
||||
|
||||
# has the lookup been DNSSEC validated?
|
||||
if grep '(secure)$' $tmpfile >/dev/null 2>&1; then
|
||||
:
|
||||
else
|
||||
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? need root hints?)"
|
||||
return 3
|
||||
fi
|
||||
|
||||
if test $bindformat = "yes"; then
|
||||
# are there any KSK keys on board?
|
||||
echo 'trusted-keys {' > "$tmp2"
|
||||
if grep ' has DNSKEY record 257' $tmpfile >/dev/null 2>&1; then
|
||||
# store KSK keys in anchor file
|
||||
grep '(secure)$' $tmpfile | \
|
||||
grep ' has DNSKEY record 257' | \
|
||||
sed -e 's/ (secure)$/";/' | \
|
||||
sed -e 's/ has DNSKEY record \([0-9]*\) \([0-9]*\) \([0-9]*\) /. \1 \2 \3 "/' | \
|
||||
sed -e 's/^\.\././' | sort >> "$tmp2"
|
||||
else
|
||||
# store all keys in the anchor file
|
||||
grep '(secure)$' $tmpfile | \
|
||||
sed -e 's/ (secure)$/";/' | \
|
||||
sed -e 's/ has DNSKEY record \([0-9]*\) \([0-9]*\) \([0-9]*\) /. \1 \2 \3 "/' | \
|
||||
sed -e 's/^\.\././' | sort >> "$tmp2"
|
||||
fi
|
||||
echo '};' >> "$tmp2"
|
||||
else #not bindformat
|
||||
# are there any KSK keys on board?
|
||||
if grep ' has DNSKEY record 257' $tmpfile >/dev/null 2>&1; then
|
||||
# store KSK keys in anchor file
|
||||
grep '(secure)$' $tmpfile | \
|
||||
grep ' has DNSKEY record 257' | \
|
||||
sed -e 's/ (secure)$//' | \
|
||||
sed -e 's/ has DNSKEY record /. IN DNSKEY /' | \
|
||||
sed -e 's/^\.\././' | sort > "$tmp2"
|
||||
else
|
||||
# store all keys in the anchor file
|
||||
grep '(secure)$' $tmpfile | \
|
||||
sed -e 's/ (secure)$//' | \
|
||||
sed -e 's/ has DNSKEY record /. IN DNSKEY /' | \
|
||||
sed -e 's/^\.\././' | sort > "$tmp2"
|
||||
fi
|
||||
fi # endif-bindformat
|
||||
|
||||
# copy over if changed
|
||||
diff $tmp2 $keyfile >/dev/null 2>&1
|
||||
if test $? -eq 1; then # 0 means no change, 2 means trouble.
|
||||
cat $tmp2 > $keyfile
|
||||
no_updated=0
|
||||
echo "$zonename key file $keyfile updated."
|
||||
else
|
||||
echo "$zonename key file $keyfile unchanged."
|
||||
fi
|
||||
|
||||
rm -f $tmpfile $tmp2 $tmp3
|
||||
}
|
||||
|
||||
no_updated=1
|
||||
if test X"$1" = "X-d"; then
|
||||
tdir="$2"
|
||||
echo "start updating in $2"
|
||||
for x in $tdir/*.anchor; do
|
||||
if test `basename "$x"` = "root.anchor"; then
|
||||
zname="."
|
||||
else
|
||||
zname=`basename "$x" .anchor`
|
||||
fi
|
||||
do_update "$zname" "$x"
|
||||
done
|
||||
echo "done updating in $2"
|
||||
else
|
||||
# regular invocation
|
||||
if test X"$1" = "X."; then
|
||||
zname="$1"
|
||||
else
|
||||
# strip trailing dot from zone name
|
||||
zname="`echo $1 | sed -e 's/\.$//'`"
|
||||
fi
|
||||
kfile="$2"
|
||||
do_update $zname $kfile
|
||||
fi
|
||||
exit $no_updated
|
||||
Executable
+128
@@ -0,0 +1,128 @@
|
||||
#!/bin/sh
|
||||
# update-itar.sh - update from the interim trust anchor repository
|
||||
# Copyright 2009, W.C.A. Wijngaards
|
||||
# This file is BSD licensed, see doc/LICENSE.
|
||||
|
||||
# --- Some settings
|
||||
|
||||
# directory where unbound works
|
||||
thedir="."
|
||||
# where is the file that unbound is going to read
|
||||
ub_ta_file="$thedir/anchors.mf"
|
||||
# where is the itar master file format
|
||||
itar_url="ftp://ftp.iana.org/itar/anchors.mf"
|
||||
# where is the itar PGP signature
|
||||
itar_sig="ftp://ftp.iana.org/itar/anchors.mf.sig"
|
||||
|
||||
# which command to fetch urls, cmd $dest $url. "wget -O" "curl -o"
|
||||
fetch_cmd="wget -O"
|
||||
# file with pgp public key
|
||||
pgp_pub_key_file="$thedir/update-itar.key"
|
||||
# our pgp keyring (goes into .gnupg directory)
|
||||
pgp_keyring_file="update-itar.ring"
|
||||
# pgp command to use
|
||||
pgp_cmd="gpg"
|
||||
|
||||
|
||||
# --- The script is below
|
||||
usage ( )
|
||||
{
|
||||
echo "usage: update-itar"
|
||||
echo " Updates the trust anchors from the interim trust"
|
||||
echo " anchor repository, https://itar.iana.org, and checks PGP sig."
|
||||
echo
|
||||
echo " Updates $ub_ta_file with the latest keys."
|
||||
echo " Read that file from the unbound config with"
|
||||
echo " trust-anchor-file: "'"'"$ub_ta_file"'"'
|
||||
echo
|
||||
echo " Exit code 0 means anchors updated, 1 no changes, "
|
||||
echo " others are errors. So, in a cronjob you can do:"
|
||||
echo " cd /usr/local/etc/unbound # your unbound work dir"
|
||||
echo " ./update-itar.sh && unbound-control reload"
|
||||
exit 2
|
||||
}
|
||||
|
||||
if test $# -ne 0; then
|
||||
usage
|
||||
fi
|
||||
tmpf="/tmp/update-itar.$$"
|
||||
|
||||
# one argument: explanation string
|
||||
error_exit ( )
|
||||
{
|
||||
if test -f $tmpf.log; then cat $tmpf.log; fi
|
||||
rm -f $tmpf $tmpf.sig $tmpf.log
|
||||
echo "Error updating trust anchors: $1"
|
||||
exit 2
|
||||
}
|
||||
|
||||
if test ! -f $pgp_pub_key_file || test ! -f $HOME/.gnupg/$pgp_keyring_file || \
|
||||
test "$pgp_pub_key_file" -nt $HOME/.gnupg/$pgp_keyring_file; then
|
||||
# default key contents right here
|
||||
if test ! -f $pgp_pub_key_file; then
|
||||
echo "creating default IANA ITAR pgp key file"
|
||||
cat >$pgp_pub_key_file <<EOF
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: GnuPG v1.4.5
|
||||
|
||||
mQGiBElr2DcRBAC+6YK6eSP7rzstvnMPQXMrpvVfuIR5FeTpGuwae9JP78V/iOXr
|
||||
N0yW8Dn6kdAztCMuRizL1Ij9IgaD7pjn8h09VgR4cN4LDv75rcQeWLzNxKy4UNRF
|
||||
aStL77RcIoTblBeCgHAK9FLzd0XfTGZCNaLNy9BYVSLyADOVDIqgBcrvBwCglz03
|
||||
QhOMIgaSx/XuRh6kYtynZ6kD/2GXx6pFs57b7rww8yOpdurCSOMB1wuEXiIXznTI
|
||||
06ARiib0G5VDvOdpy0LDU2526Q9f/WAERlhcExTgnTFigG4mRksUiDrrai4GIr+6
|
||||
JaivcGFVYdZZ4mZ088jcwujS/UY3C0ryGR9ufYUDAnfx6frhSl6o6j5is+jeGndF
|
||||
JYRAA/9B/1OXNVwFSiIxnP2aPUwsT1li1vaW8dhA/5PcuPLOVvEjPc1Pc16HGLhE
|
||||
8CRmMn66LqB1ccInE5hLKGGvV3pctjan+IOhaq3OHt/a+buDtTPgykchMZ2k1AzT
|
||||
RYk+gksxpIl6yTZsBH4hoRt8auxEJW8AiYbNtXXkNuWcoQL40bQsSUFOQSBUcnVz
|
||||
dCBBbmNob3IgUmVwb3NpdG9yeSA8aXRhckBpYW5hLm9yZz6IYAQTEQIAIAUCSWvY
|
||||
NwIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEPR9+zCB1GT0GUAAn29/TacF
|
||||
Teh87dls8pmkjxS4pKf1AKCJS/MvzR54AblO4DNMyc9q0G4frrkCDQRJa9g3EAgA
|
||||
ywoLxF4HVb9o926UIXw8JxNIzDPkt8galAcKRUmHQMNa/QA80WMl9Ia6DIxavGlV
|
||||
I5O1fvms297RV2KSSBjKWn6G+0me80A7aw0eHNg7habM5VtzDz5DhJbQFdJV9aYV
|
||||
DoTSnY6uR6iSSRrdZNaYdlCwDS8lBCnOKoGMArHzVCa2EdCBeCUY/eObOXtu8Gm3
|
||||
nDkuWeLPv08/0lvtr6d6VoDUEVPEsJAPONEYtpz/D+EZddUraF+3JscWqfRApBOz
|
||||
/8WHaeTNdzIH+h1ntktiizA6eH40EM6coQQxtIRsxg1DPTxofdovreMkcMI0EUUP
|
||||
awDn8gDtgG3g6Ud5zCdknwAEDQf/W3rxrEN6OZxJvWti8Iu6KOgxtuINiAsimPPX
|
||||
qy9KHowyEE9EMPzgADjWC9Reyusr4CwcootjWw7ryUwU0fXvVULKhg32NzLsx/Ci
|
||||
WtgCPSR58WZ1KKhnoB05+PTrwzhU+u64Cd/vJtFqGxSrANl2FAkPswHJMr8dMwAz
|
||||
uni7zzLJ+homW1T5AaixwmN3jeDHWshJH9E9JIhr5Y/8AzMl1V10r2u1c2ej0lBJ
|
||||
Y4GegI5cYAEBerS9d+mrbPlvbJ8AfuAuEf0y/PWJh0z1+Kck5qIbXMn/rpMBYvLJ
|
||||
Uj5CfqWlh8+hxqSYJDXtLm8hBiQFiMEew0jOc2Tw4F91OZ+jyYhJBBgRAgAJBQJJ
|
||||
a9g3AhsMAAoJEPR9+zCB1GT0AUwAn2ZtBwAyVxppdeTqilXufUvAkvjbAJ9dUpR1
|
||||
9a17/5BvDDJcIxSEKTJmDw==
|
||||
=zCNZ
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
EOF
|
||||
fi
|
||||
# import the new key
|
||||
$pgp_cmd --no-default-keyring --keyring $pgp_keyring_file \
|
||||
--primary-keyring $pgp_keyring_file \
|
||||
--import $pgp_pub_key_file >$tmpf.log 2>&1 \
|
||||
|| error_exit "could not import pgp public key into keyring"
|
||||
fi
|
||||
|
||||
$fetch_cmd $tmpf $itar_url >$tmpf.log 2>&1 \
|
||||
|| error_exit "fetching $itar_url failed"
|
||||
tail -2 $tmpf | grep "; End of file" >/dev/null 2>&1 || \
|
||||
error_exit "The file fetched from $itar_url was partial"
|
||||
$fetch_cmd $tmpf.sig $itar_sig >$tmpf.log 2>&1 \
|
||||
|| error_exit "fetching $itar_sig failed"
|
||||
|
||||
# check the file with pgp
|
||||
$pgp_cmd --no-default-keyring --keyring $pgp_keyring_file \
|
||||
--verify $tmpf.sig $tmpf >$tmpf.log 2>&1 \
|
||||
|| error_exit "the PGP signature failed!"
|
||||
|
||||
# check for differences
|
||||
val=1
|
||||
if diff "$ub_ta_file" $tmpf 2>/dev/null ; then
|
||||
# echo "The interim trust anchor repository did not change."
|
||||
:
|
||||
else
|
||||
echo "Updating $ub_ta_file"
|
||||
cp $tmpf $ub_ta_file
|
||||
val=0
|
||||
fi
|
||||
|
||||
rm -f $tmpf $tmpf.sig $tmpf.log
|
||||
exit $val
|
||||
+9
-83
@@ -46,23 +46,8 @@
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
|
||||
int
|
||||
acl_list_cmp(const void* k1, const void* k2)
|
||||
{
|
||||
struct acl_addr* n1 = (struct acl_addr*)k1;
|
||||
struct acl_addr* n2 = (struct acl_addr*)k2;
|
||||
int r = sockaddr_cmp_addr(&n1->addr, n1->addrlen, &n2->addr,
|
||||
n2->addrlen);
|
||||
if(r != 0) return r;
|
||||
if(n1->net < n2->net)
|
||||
return -1;
|
||||
if(n1->net > n2->net)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct acl_list*
|
||||
acl_list_create()
|
||||
acl_list_create(void)
|
||||
{
|
||||
struct acl_list* acl = (struct acl_list*)calloc(1,
|
||||
sizeof(struct acl_list));
|
||||
@@ -82,7 +67,6 @@ acl_list_delete(struct acl_list* acl)
|
||||
if(!acl)
|
||||
return;
|
||||
regional_destroy(acl->region);
|
||||
free(acl->tree);
|
||||
free(acl);
|
||||
}
|
||||
|
||||
@@ -96,13 +80,8 @@ acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr,
|
||||
sizeof(struct acl_addr));
|
||||
if(!node)
|
||||
return 0;
|
||||
node->node.key = node;
|
||||
memcpy(&node->addr, addr, addrlen);
|
||||
node->addrlen = addrlen;
|
||||
node->net = net;
|
||||
node->parent = NULL;
|
||||
node->control = control;
|
||||
if(!rbtree_insert(acl->tree, &node->node)) {
|
||||
if(!addr_tree_insert(&acl->tree, &node->node, addr, addrlen, net)) {
|
||||
if(complain_duplicates)
|
||||
verbose(VERB_QUERY, "duplicate acl address ignored.");
|
||||
}
|
||||
@@ -124,6 +103,8 @@ acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
|
||||
control = acl_deny;
|
||||
else if(strcmp(s2, "refuse") == 0)
|
||||
control = acl_refuse;
|
||||
else if(strcmp(s2, "allow_snoop") == 0)
|
||||
control = acl_allow_snoop;
|
||||
else {
|
||||
log_err("access control type %s unknown", str);
|
||||
return 0;
|
||||
@@ -153,42 +134,11 @@ read_acl_list(struct acl_list* acl, struct config_file* cfg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** initialise parent pointers in the tree */
|
||||
static void
|
||||
acl_list_init_parents(struct acl_list* acl)
|
||||
{
|
||||
struct acl_addr* node, *prev = NULL, *p;
|
||||
int m;
|
||||
RBTREE_FOR(node, struct acl_addr*, acl->tree) {
|
||||
node->parent = NULL;
|
||||
if(!prev || prev->addrlen != node->addrlen) {
|
||||
prev = node;
|
||||
continue;
|
||||
}
|
||||
m = addr_in_common(&prev->addr, prev->net, &node->addr,
|
||||
node->net, node->addrlen);
|
||||
/* sort order like: ::/0, 1::/2, 1::/4, ... 2::/2 */
|
||||
/* find the previous, or parent-parent-parent */
|
||||
for(p = prev; p; p = p->parent)
|
||||
if(p->net <= m) {
|
||||
/* ==: since prev matched m, this is closest*/
|
||||
/* <: prev matches more, but is not a parent,
|
||||
* this one is a (grand)parent */
|
||||
node->parent = p;
|
||||
break;
|
||||
}
|
||||
prev = node;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg)
|
||||
{
|
||||
regional_free_all(acl->region);
|
||||
free(acl->tree);
|
||||
acl->tree = rbtree_create(acl_list_cmp);
|
||||
if(!acl->tree)
|
||||
return 0;
|
||||
addr_tree_init(&acl->tree);
|
||||
if(!read_acl_list(acl, cfg))
|
||||
return 0;
|
||||
/* insert defaults, with '0' to ignore them if they are duplicates */
|
||||
@@ -204,7 +154,7 @@ acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg)
|
||||
if(!acl_list_str_cfg(acl, "::ffff:127.0.0.1", "allow", 0))
|
||||
return 0;
|
||||
}
|
||||
acl_list_init_parents(acl);
|
||||
addr_tree_init_parents(&acl->tree);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -212,33 +162,9 @@ enum acl_access
|
||||
acl_list_lookup(struct acl_list* acl, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
/* lookup in the tree */
|
||||
rbnode_t* res = NULL;
|
||||
struct acl_addr* result;
|
||||
struct acl_addr key;
|
||||
key.node.key = &key;
|
||||
memcpy(&key.addr, addr, addrlen);
|
||||
key.addrlen = addrlen;
|
||||
key.net = (addr_is_ip6(addr, addrlen)?128:32);
|
||||
if(rbtree_find_less_equal(acl->tree, &key, &res)) {
|
||||
/* exact */
|
||||
result = (struct acl_addr*)res;
|
||||
return result->control;
|
||||
} else {
|
||||
/* smaller element (or no element) */
|
||||
int m;
|
||||
result = (struct acl_addr*)res;
|
||||
if(!result || result->addrlen != addrlen)
|
||||
return acl_deny;
|
||||
/* count number of bits matched */
|
||||
m = addr_in_common(&result->addr, result->net, addr,
|
||||
key.net, addrlen);
|
||||
while(result) { /* go up until addr is inside netblock */
|
||||
if(result->net <= m)
|
||||
return result->control;
|
||||
result = result->parent;
|
||||
}
|
||||
}
|
||||
struct acl_addr* r = (struct acl_addr*)addr_tree_lookup(&acl->tree,
|
||||
addr, addrlen);
|
||||
if(r) return r->control;
|
||||
return acl_deny;
|
||||
}
|
||||
|
||||
|
||||
+9
-18
@@ -42,7 +42,7 @@
|
||||
|
||||
#ifndef DAEMON_ACL_LIST_H
|
||||
#define DAEMON_ACL_LIST_H
|
||||
#include "util/rbtree.h"
|
||||
#include "util/storage/dnstree.h"
|
||||
struct config_file;
|
||||
struct regional;
|
||||
|
||||
@@ -55,8 +55,10 @@ enum acl_access {
|
||||
acl_deny = 0,
|
||||
/** disallow access, send a polite 'REFUSED' reply */
|
||||
acl_refuse,
|
||||
/** allow full access */
|
||||
acl_allow
|
||||
/** allow full access for recursion (+RD) queries */
|
||||
acl_allow,
|
||||
/** allow full access for all queries, recursion and cache snooping */
|
||||
acl_allow_snoop
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -69,7 +71,7 @@ struct acl_list {
|
||||
* Tree of the addresses that are allowed/blocked.
|
||||
* contents of type acl_addr.
|
||||
*/
|
||||
rbtree_t* tree;
|
||||
rbtree_t tree;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -77,16 +79,8 @@ struct acl_list {
|
||||
* An address span with access control information
|
||||
*/
|
||||
struct acl_addr {
|
||||
/** redblacktree node, key is this structure: addr and addrlen, net */
|
||||
rbnode_t node;
|
||||
/** parent node in acl tree that encompasses this entry */
|
||||
struct acl_addr* parent;
|
||||
/** address */
|
||||
struct sockaddr_storage addr;
|
||||
/** length of addr */
|
||||
socklen_t addrlen;
|
||||
/** netblock size */
|
||||
int net;
|
||||
/** node in address tree */
|
||||
struct addr_tree_node node;
|
||||
/** access control on this netblock */
|
||||
enum acl_access control;
|
||||
};
|
||||
@@ -95,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.
|
||||
@@ -128,7 +122,4 @@ enum acl_access acl_list_lookup(struct acl_list* acl,
|
||||
*/
|
||||
size_t acl_list_get_mem(struct acl_list* acl);
|
||||
|
||||
/** compare two acl list entries */
|
||||
int acl_list_cmp(const void* k1, const void* k2);
|
||||
|
||||
#endif /* DAEMON_ACL_LIST_H */
|
||||
|
||||
@@ -0,0 +1,985 @@
|
||||
/*
|
||||
* daemon/cachedump.c - dump the cache to text format.
|
||||
*
|
||||
* Copyright (c) 2008, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains functions to read and write the cache(s)
|
||||
* 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*
|
||||
to_rr(struct ub_packed_rrset_key* k, struct packed_rrset_data* d,
|
||||
uint32_t now, size_t i, uint16_t type)
|
||||
{
|
||||
ldns_rr* rr = ldns_rr_new();
|
||||
ldns_rdf* rdf;
|
||||
ldns_status status;
|
||||
size_t pos;
|
||||
log_assert(i < d->count + d->rrsig_count);
|
||||
if(!rr) {
|
||||
return NULL;
|
||||
}
|
||||
ldns_rr_set_type(rr, type);
|
||||
ldns_rr_set_class(rr, ntohs(k->rk.rrset_class));
|
||||
if(d->rr_ttl[i] < now)
|
||||
ldns_rr_set_ttl(rr, 0);
|
||||
else ldns_rr_set_ttl(rr, d->rr_ttl[i] - now);
|
||||
pos = 0;
|
||||
status = ldns_wire2dname(&rdf, k->rk.dname, k->rk.dname_len, &pos);
|
||||
if(status != LDNS_STATUS_OK) {
|
||||
/* we drop detailed error in status */
|
||||
ldns_rr_free(rr);
|
||||
return NULL;
|
||||
}
|
||||
ldns_rr_set_owner(rr, rdf);
|
||||
pos = 0;
|
||||
status = ldns_wire2rdf(rr, d->rr_data[i], d->rr_len[i], &pos);
|
||||
if(status != LDNS_STATUS_OK) {
|
||||
/* we drop detailed error in status */
|
||||
ldns_rr_free(rr);
|
||||
return NULL;
|
||||
}
|
||||
return rr;
|
||||
}
|
||||
|
||||
/** dump one rrset zonefile line */
|
||||
static int
|
||||
dump_rrset_line(SSL* ssl, struct ub_packed_rrset_key* k,
|
||||
struct packed_rrset_data* d, uint32_t now, size_t i, uint16_t type)
|
||||
{
|
||||
char* s;
|
||||
ldns_rr* rr = to_rr(k, d, now, i, type);
|
||||
if(!rr) {
|
||||
return ssl_printf(ssl, "BADRR\n");
|
||||
}
|
||||
s = ldns_rr2str(rr);
|
||||
ldns_rr_free(rr);
|
||||
if(!s) {
|
||||
return ssl_printf(ssl, "BADRR\n");
|
||||
}
|
||||
if(!ssl_printf(ssl, "%s", s)) {
|
||||
free(s);
|
||||
return 0;
|
||||
}
|
||||
free(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** dump rrset key and data info */
|
||||
static int
|
||||
dump_rrset(SSL* ssl, struct ub_packed_rrset_key* k,
|
||||
struct packed_rrset_data* d, uint32_t now)
|
||||
{
|
||||
size_t i;
|
||||
/* rd lock held by caller */
|
||||
if(!k || !d) return 1;
|
||||
if(d->ttl < now) return 1; /* expired */
|
||||
|
||||
/* meta line */
|
||||
if(!ssl_printf(ssl, ";rrset%s %u %u %u %d %d\n",
|
||||
(k->rk.flags & PACKED_RRSET_NSEC_AT_APEX)?" nsec_apex":"",
|
||||
(unsigned)(d->ttl - now),
|
||||
(unsigned)d->count, (unsigned)d->rrsig_count,
|
||||
(int)d->trust, (int)d->security
|
||||
))
|
||||
return 0;
|
||||
for(i=0; i<d->count; i++) {
|
||||
if(!dump_rrset_line(ssl, k, d, now, i, ntohs(k->rk.type)))
|
||||
return 0;
|
||||
}
|
||||
for(i=0; i<d->rrsig_count; i++) {
|
||||
if(!dump_rrset_line(ssl, k, d, now, i+d->count,
|
||||
LDNS_RR_TYPE_RRSIG))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** dump lruhash rrset cache */
|
||||
static int
|
||||
dump_rrset_lruhash(SSL* ssl, struct lruhash* h, uint32_t now)
|
||||
{
|
||||
struct lruhash_entry* e;
|
||||
/* lruhash already locked by caller */
|
||||
/* walk in order of lru; best first */
|
||||
for(e=h->lru_start; e; e = e->lru_next) {
|
||||
lock_rw_rdlock(&e->lock);
|
||||
if(!dump_rrset(ssl, (struct ub_packed_rrset_key*)e->key,
|
||||
(struct packed_rrset_data*)e->data, now)) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** dump rrset cache */
|
||||
static int
|
||||
dump_rrset_cache(SSL* ssl, struct worker* worker)
|
||||
{
|
||||
struct rrset_cache* r = worker->env.rrset_cache;
|
||||
size_t slab;
|
||||
if(!ssl_printf(ssl, "START_RRSET_CACHE\n")) return 0;
|
||||
for(slab=0; slab<r->table.size; slab++) {
|
||||
lock_quick_lock(&r->table.array[slab]->lock);
|
||||
if(!dump_rrset_lruhash(ssl, r->table.array[slab],
|
||||
*worker->env.now)) {
|
||||
lock_quick_unlock(&r->table.array[slab]->lock);
|
||||
return 0;
|
||||
}
|
||||
lock_quick_unlock(&r->table.array[slab]->lock);
|
||||
}
|
||||
return ssl_printf(ssl, "END_RRSET_CACHE\n");
|
||||
}
|
||||
|
||||
/** dump message to rrset reference */
|
||||
static int
|
||||
dump_msg_ref(SSL* ssl, struct ub_packed_rrset_key* k)
|
||||
{
|
||||
ldns_rdf* rdf;
|
||||
ldns_status status;
|
||||
size_t pos;
|
||||
char* nm, *tp, *cl;
|
||||
|
||||
pos = 0;
|
||||
status = ldns_wire2dname(&rdf, k->rk.dname, k->rk.dname_len, &pos);
|
||||
if(status != LDNS_STATUS_OK) {
|
||||
return ssl_printf(ssl, "BADREF\n");
|
||||
}
|
||||
nm = ldns_rdf2str(rdf);
|
||||
ldns_rdf_deep_free(rdf);
|
||||
tp = ldns_rr_type2str(ntohs(k->rk.type));
|
||||
cl = ldns_rr_class2str(ntohs(k->rk.rrset_class));
|
||||
if(!nm || !cl || !tp) {
|
||||
free(nm);
|
||||
free(tp);
|
||||
free(cl);
|
||||
return ssl_printf(ssl, "BADREF\n");
|
||||
}
|
||||
if(!ssl_printf(ssl, "%s %s %s %d\n", nm, cl, tp, (int)k->rk.flags)) {
|
||||
free(nm);
|
||||
free(tp);
|
||||
free(cl);
|
||||
return 0;
|
||||
}
|
||||
free(nm);
|
||||
free(tp);
|
||||
free(cl);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** dump message entry */
|
||||
static int
|
||||
dump_msg(SSL* ssl, struct query_info* k, struct reply_info* d,
|
||||
uint32_t now)
|
||||
{
|
||||
size_t i;
|
||||
char* nm, *tp, *cl;
|
||||
ldns_rdf* rdf;
|
||||
ldns_status status;
|
||||
size_t pos;
|
||||
if(!k || !d) return 1;
|
||||
if(d->ttl < now) return 1; /* expired */
|
||||
|
||||
pos = 0;
|
||||
status = ldns_wire2dname(&rdf, k->qname, k->qname_len, &pos);
|
||||
if(status != LDNS_STATUS_OK) {
|
||||
return 1; /* skip this entry */
|
||||
}
|
||||
nm = ldns_rdf2str(rdf);
|
||||
ldns_rdf_deep_free(rdf);
|
||||
tp = ldns_rr_type2str(k->qtype);
|
||||
cl = ldns_rr_class2str(k->qclass);
|
||||
if(!nm || !tp || !cl) {
|
||||
free(nm);
|
||||
free(tp);
|
||||
free(cl);
|
||||
return 1; /* skip this entry */
|
||||
}
|
||||
if(!rrset_array_lock(d->ref, d->rrset_count, now)) {
|
||||
/* rrsets have timed out or do not exist */
|
||||
free(nm);
|
||||
free(tp);
|
||||
free(cl);
|
||||
return 1; /* skip this entry */
|
||||
}
|
||||
|
||||
/* meta line */
|
||||
if(!ssl_printf(ssl, "msg %s %s %s %d %d %u %d %u %u %u\n",
|
||||
nm, cl, tp,
|
||||
(int)d->flags, (int)d->qdcount,
|
||||
(unsigned)(d->ttl-now), (int)d->security,
|
||||
(unsigned)d->an_numrrsets,
|
||||
(unsigned)d->ns_numrrsets,
|
||||
(unsigned)d->ar_numrrsets)) {
|
||||
free(nm);
|
||||
free(tp);
|
||||
free(cl);
|
||||
rrset_array_unlock(d->ref, d->rrset_count);
|
||||
return 0;
|
||||
}
|
||||
free(nm);
|
||||
free(tp);
|
||||
free(cl);
|
||||
|
||||
for(i=0; i<d->rrset_count; i++) {
|
||||
if(!dump_msg_ref(ssl, d->rrsets[i])) {
|
||||
rrset_array_unlock(d->ref, d->rrset_count);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
rrset_array_unlock(d->ref, d->rrset_count);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** copy msg to worker pad */
|
||||
static int
|
||||
copy_msg(struct regional* region, struct lruhash_entry* e,
|
||||
struct query_info** k, struct reply_info** d)
|
||||
{
|
||||
struct reply_info* rep = (struct reply_info*)e->data;
|
||||
*d = (struct reply_info*)regional_alloc_init(region, e->data,
|
||||
sizeof(struct reply_info) +
|
||||
sizeof(struct rrset_ref) * (rep->rrset_count-1) +
|
||||
sizeof(struct ub_packed_rrset_key*) * rep->rrset_count);
|
||||
if(!*d)
|
||||
return 0;
|
||||
(*d)->rrsets = (struct ub_packed_rrset_key**)(
|
||||
(uint8_t*)(&((*d)->ref[0])) +
|
||||
sizeof(struct rrset_ref) * rep->rrset_count);
|
||||
*k = (struct query_info*)regional_alloc_init(region,
|
||||
e->key, sizeof(struct query_info));
|
||||
if(!*k)
|
||||
return 0;
|
||||
(*k)->qname = regional_alloc_init(region,
|
||||
(*k)->qname, (*k)->qname_len);
|
||||
return (*k)->qname != NULL;
|
||||
}
|
||||
|
||||
/** dump lruhash msg cache */
|
||||
static int
|
||||
dump_msg_lruhash(SSL* ssl, struct worker* worker, struct lruhash* h)
|
||||
{
|
||||
struct lruhash_entry* e;
|
||||
struct query_info* k;
|
||||
struct reply_info* d;
|
||||
|
||||
/* lruhash already locked by caller */
|
||||
/* walk in order of lru; best first */
|
||||
for(e=h->lru_start; e; e = e->lru_next) {
|
||||
regional_free_all(worker->scratchpad);
|
||||
lock_rw_rdlock(&e->lock);
|
||||
/* make copy of rrset in worker buffer */
|
||||
if(!copy_msg(worker->scratchpad, e, &k, &d)) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
/* release lock so we can lookup the rrset references
|
||||
* in the rrset cache */
|
||||
if(!dump_msg(ssl, k, d, *worker->env.now)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** dump msg cache */
|
||||
static int
|
||||
dump_msg_cache(SSL* ssl, struct worker* worker)
|
||||
{
|
||||
struct slabhash* sh = worker->env.msg_cache;
|
||||
size_t slab;
|
||||
if(!ssl_printf(ssl, "START_MSG_CACHE\n")) return 0;
|
||||
for(slab=0; slab<sh->size; slab++) {
|
||||
lock_quick_lock(&sh->array[slab]->lock);
|
||||
if(!dump_msg_lruhash(ssl, worker, sh->array[slab])) {
|
||||
lock_quick_unlock(&sh->array[slab]->lock);
|
||||
return 0;
|
||||
}
|
||||
lock_quick_unlock(&sh->array[slab]->lock);
|
||||
}
|
||||
return ssl_printf(ssl, "END_MSG_CACHE\n");
|
||||
}
|
||||
|
||||
int
|
||||
dump_cache(SSL* ssl, struct worker* worker)
|
||||
{
|
||||
if(!dump_rrset_cache(ssl, worker))
|
||||
return 0;
|
||||
if(!dump_msg_cache(ssl, worker))
|
||||
return 0;
|
||||
return ssl_printf(ssl, "EOF\n");
|
||||
}
|
||||
|
||||
/** read a line from ssl into buffer */
|
||||
static int
|
||||
ssl_read_buf(SSL* ssl, ldns_buffer* buf)
|
||||
{
|
||||
return ssl_read_line(ssl, (char*)ldns_buffer_begin(buf),
|
||||
ldns_buffer_capacity(buf));
|
||||
}
|
||||
|
||||
/** check fixed text on line */
|
||||
static int
|
||||
read_fixed(SSL* ssl, ldns_buffer* buf, const char* str)
|
||||
{
|
||||
if(!ssl_read_buf(ssl, buf)) return 0;
|
||||
return (strcmp((char*)ldns_buffer_begin(buf), str) == 0);
|
||||
}
|
||||
|
||||
/** load an RR into rrset */
|
||||
static int
|
||||
load_rr(SSL* ssl, ldns_buffer* buf, struct regional* region,
|
||||
struct ub_packed_rrset_key* rk, struct packed_rrset_data* d,
|
||||
unsigned int i, int is_rrsig, int* go_on, uint32_t now)
|
||||
{
|
||||
ldns_rr* rr;
|
||||
ldns_status status;
|
||||
|
||||
/* read the line */
|
||||
if(!ssl_read_buf(ssl, buf))
|
||||
return 0;
|
||||
if(strncmp((char*)ldns_buffer_begin(buf), "BADRR\n", 6) == 0) {
|
||||
*go_on = 0;
|
||||
return 1;
|
||||
}
|
||||
status = ldns_rr_new_frm_str(&rr, (char*)ldns_buffer_begin(buf),
|
||||
LDNS_DEFAULT_TTL, NULL, NULL);
|
||||
if(status != LDNS_STATUS_OK) {
|
||||
log_warn("error cannot parse rr: %s: %s",
|
||||
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) {
|
||||
log_warn("error expected rrsig but got %s",
|
||||
(char*)ldns_buffer_begin(buf));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* convert ldns rr into packed_rr */
|
||||
d->rr_ttl[i] = ldns_rr_ttl(rr) + now;
|
||||
ldns_buffer_clear(buf);
|
||||
ldns_buffer_skip(buf, 2);
|
||||
status = ldns_rr_rdata2buffer_wire(buf, rr);
|
||||
if(status != LDNS_STATUS_OK) {
|
||||
log_warn("error cannot rr2wire: %s",
|
||||
ldns_get_errorstr_by_id(status));
|
||||
ldns_rr_free(rr);
|
||||
return 0;
|
||||
}
|
||||
ldns_buffer_flip(buf);
|
||||
ldns_buffer_write_u16_at(buf, 0, ldns_buffer_limit(buf) - 2);
|
||||
|
||||
d->rr_len[i] = ldns_buffer_limit(buf);
|
||||
d->rr_data[i] = (uint8_t*)regional_alloc_init(region,
|
||||
ldns_buffer_begin(buf), ldns_buffer_limit(buf));
|
||||
if(!d->rr_data[i]) {
|
||||
ldns_rr_free(rr);
|
||||
log_warn("error out of memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if first entry, fill the key structure */
|
||||
if(i==0) {
|
||||
rk->rk.type = htons(ldns_rr_get_type(rr));
|
||||
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) {
|
||||
log_warn("error out of memory");
|
||||
ldns_rr_free(rr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ldns_rr_free(rr);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** move entry into cache */
|
||||
static int
|
||||
move_into_cache(struct ub_packed_rrset_key* k,
|
||||
struct packed_rrset_data* d, struct worker* worker)
|
||||
{
|
||||
struct ub_packed_rrset_key* ak;
|
||||
struct packed_rrset_data* ad;
|
||||
size_t s, i, num = d->count + d->rrsig_count;
|
||||
struct rrset_ref ref;
|
||||
uint8_t* p;
|
||||
|
||||
ak = alloc_special_obtain(&worker->alloc);
|
||||
if(!ak) {
|
||||
log_warn("error out of memory");
|
||||
return 0;
|
||||
}
|
||||
ak->entry.data = NULL;
|
||||
ak->rk = k->rk;
|
||||
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) {
|
||||
log_warn("error out of memory");
|
||||
ub_packed_rrset_parsedelete(ak, &worker->alloc);
|
||||
return 0;
|
||||
}
|
||||
s = sizeof(*ad) + (sizeof(size_t) + sizeof(uint8_t*) +
|
||||
sizeof(uint32_t))* num;
|
||||
for(i=0; i<num; i++)
|
||||
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;
|
||||
}
|
||||
p = (uint8_t*)ad;
|
||||
memmove(p, d, sizeof(*ad));
|
||||
p += sizeof(*ad);
|
||||
memmove(p, &d->rr_len[0], sizeof(size_t)*num);
|
||||
p += sizeof(size_t)*num;
|
||||
memmove(p, &d->rr_data[0], sizeof(uint8_t*)*num);
|
||||
p += sizeof(uint8_t*)*num;
|
||||
memmove(p, &d->rr_ttl[0], sizeof(uint32_t)*num);
|
||||
p += sizeof(uint32_t)*num;
|
||||
for(i=0; i<num; i++) {
|
||||
memmove(p, d->rr_data[i], d->rr_len[i]);
|
||||
p += d->rr_len[i];
|
||||
}
|
||||
packed_rrset_ptr_fixup(ad);
|
||||
|
||||
ak->entry.data = ad;
|
||||
|
||||
ref.key = ak;
|
||||
ref.id = ak->id;
|
||||
(void)rrset_cache_update(worker->env.rrset_cache, &ref,
|
||||
&worker->alloc, *worker->env.now);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** load an rrset entry */
|
||||
static int
|
||||
load_rrset(SSL* ssl, ldns_buffer* buf, struct worker* worker)
|
||||
{
|
||||
char* s = (char*)ldns_buffer_begin(buf);
|
||||
struct regional* region = worker->scratchpad;
|
||||
struct ub_packed_rrset_key* rk;
|
||||
struct packed_rrset_data* d;
|
||||
unsigned int ttl, rr_count, rrsig_count, trust, security;
|
||||
unsigned int i;
|
||||
int go_on = 1;
|
||||
regional_free_all(region);
|
||||
|
||||
rk = (struct ub_packed_rrset_key*)regional_alloc_zero(region,
|
||||
sizeof(*rk));
|
||||
d = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*d));
|
||||
if(!rk || !d) {
|
||||
log_warn("error out of memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(strncmp(s, ";rrset", 6) != 0) {
|
||||
log_warn("error expected ';rrset' but got %s", s);
|
||||
return 0;
|
||||
}
|
||||
s += 6;
|
||||
if(strncmp(s, " nsec_apex", 10) == 0) {
|
||||
s += 10;
|
||||
rk->rk.flags |= PACKED_RRSET_NSEC_AT_APEX;
|
||||
}
|
||||
if(sscanf(s, " %u %u %u %u %u", &ttl, &rr_count, &rrsig_count,
|
||||
&trust, &security) != 5) {
|
||||
log_warn("error bad rrset spec %s", s);
|
||||
return 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;
|
||||
d->trust = (enum rrset_trust)trust;
|
||||
d->ttl = (uint32_t)ttl + *worker->env.now;
|
||||
|
||||
d->rr_len = regional_alloc_zero(region,
|
||||
sizeof(size_t)*(d->count+d->rrsig_count));
|
||||
d->rr_ttl = regional_alloc_zero(region,
|
||||
sizeof(uint32_t)*(d->count+d->rrsig_count));
|
||||
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) {
|
||||
log_warn("error out of memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read the rr's themselves */
|
||||
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;
|
||||
}
|
||||
}
|
||||
if(!go_on) {
|
||||
/* skip this entry */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return move_into_cache(rk, d, worker);
|
||||
}
|
||||
|
||||
/** load rrset cache */
|
||||
static int
|
||||
load_rrset_cache(SSL* ssl, struct worker* worker)
|
||||
{
|
||||
ldns_buffer* buf = worker->env.scratch_buffer;
|
||||
if(!read_fixed(ssl, buf, "START_RRSET_CACHE")) return 0;
|
||||
while(ssl_read_buf(ssl, buf) &&
|
||||
strcmp((char*)ldns_buffer_begin(buf), "END_RRSET_CACHE")!=0) {
|
||||
if(!load_rrset(ssl, buf, worker))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read qinfo from next three words */
|
||||
static char*
|
||||
load_qinfo(char* str, struct query_info* qinfo, ldns_buffer* buf,
|
||||
struct regional* region)
|
||||
{
|
||||
/* s is part of the buf */
|
||||
char* s = str;
|
||||
ldns_rr* rr;
|
||||
ldns_status status;
|
||||
|
||||
/* skip three words */
|
||||
s = strchr(str, ' ');
|
||||
if(s) s = strchr(s+1, ' ');
|
||||
if(s) s = strchr(s+1, ' ');
|
||||
if(!s) {
|
||||
log_warn("error line too short, %s", str);
|
||||
return NULL;
|
||||
}
|
||||
s[0] = 0;
|
||||
s++;
|
||||
|
||||
/* parse them */
|
||||
status = ldns_rr_new_question_frm_str(&rr, str, NULL, NULL);
|
||||
if(status != LDNS_STATUS_OK) {
|
||||
log_warn("error cannot parse: %s %s",
|
||||
ldns_get_errorstr_by_id(status), str);
|
||||
return NULL;
|
||||
}
|
||||
qinfo->qtype = ldns_rr_get_type(rr);
|
||||
qinfo->qclass = ldns_rr_get_class(rr);
|
||||
ldns_buffer_clear(buf);
|
||||
status = ldns_dname2buffer_wire(buf, ldns_rr_owner(rr));
|
||||
ldns_rr_free(rr);
|
||||
if(status != LDNS_STATUS_OK) {
|
||||
log_warn("error cannot dname2wire: %s",
|
||||
ldns_get_errorstr_by_id(status));
|
||||
return NULL;
|
||||
}
|
||||
ldns_buffer_flip(buf);
|
||||
qinfo->qname_len = ldns_buffer_limit(buf);
|
||||
qinfo->qname = (uint8_t*)regional_alloc_init(region,
|
||||
ldns_buffer_begin(buf), ldns_buffer_limit(buf));
|
||||
if(!qinfo->qname) {
|
||||
log_warn("error out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/** load a msg rrset reference */
|
||||
static int
|
||||
load_ref(SSL* ssl, ldns_buffer* buf, struct worker* worker,
|
||||
struct regional *region, struct ub_packed_rrset_key** rrset,
|
||||
int* go_on)
|
||||
{
|
||||
char* s = (char*)ldns_buffer_begin(buf);
|
||||
struct query_info qinfo;
|
||||
unsigned int flags;
|
||||
struct ub_packed_rrset_key* k;
|
||||
|
||||
/* read line */
|
||||
if(!ssl_read_buf(ssl, buf))
|
||||
return 0;
|
||||
if(strncmp(s, "BADREF", 6) == 0) {
|
||||
*go_on = 0; /* its bad, skip it and skip message */
|
||||
return 1;
|
||||
}
|
||||
|
||||
s = load_qinfo(s, &qinfo, buf, region);
|
||||
if(!s) {
|
||||
return 0;
|
||||
}
|
||||
if(sscanf(s, " %u", &flags) != 1) {
|
||||
log_warn("error cannot parse flags: %s", s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* lookup in cache */
|
||||
k = rrset_cache_lookup(worker->env.rrset_cache, qinfo.qname,
|
||||
qinfo.qname_len, qinfo.qtype, qinfo.qclass,
|
||||
(uint32_t)flags, *worker->env.now, 0);
|
||||
if(!k) {
|
||||
/* not found or expired */
|
||||
*go_on = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* store in result */
|
||||
*rrset = packed_rrset_copy_region(k, region, *worker->env.now);
|
||||
lock_rw_unlock(&k->entry.lock);
|
||||
|
||||
return (*rrset != NULL);
|
||||
}
|
||||
|
||||
/** load a msg entry */
|
||||
static int
|
||||
load_msg(SSL* ssl, ldns_buffer* buf, struct worker* worker)
|
||||
{
|
||||
struct regional* region = worker->scratchpad;
|
||||
struct query_info qinf;
|
||||
struct reply_info rep;
|
||||
char* s = (char*)ldns_buffer_begin(buf);
|
||||
unsigned int flags, qdcount, ttl, security, an, ns, ar;
|
||||
size_t i;
|
||||
int go_on = 1;
|
||||
|
||||
regional_free_all(region);
|
||||
|
||||
if(strncmp(s, "msg ", 4) != 0) {
|
||||
log_warn("error expected msg but got %s", s);
|
||||
return 0;
|
||||
}
|
||||
s += 4;
|
||||
s = load_qinfo(s, &qinf, buf, region);
|
||||
if(!s) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read remainder of line */
|
||||
if(sscanf(s, " %u %u %u %u %u %u %u", &flags, &qdcount, &ttl,
|
||||
&security, &an, &ns, &ar) != 7) {
|
||||
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;
|
||||
rep.ar_numrrsets = (size_t)ar;
|
||||
rep.rrset_count = (size_t)an+(size_t)ns+(size_t)ar;
|
||||
rep.rrsets = (struct ub_packed_rrset_key**)regional_alloc_zero(
|
||||
region, sizeof(struct ub_packed_rrset_key*)*rep.rrset_count);
|
||||
|
||||
/* fill repinfo with references */
|
||||
for(i=0; i<rep.rrset_count; i++) {
|
||||
if(!load_ref(ssl, buf, worker, region, &rep.rrsets[i],
|
||||
&go_on)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(!go_on)
|
||||
return 1; /* skip this one, not all references satisfied */
|
||||
|
||||
if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0)) {
|
||||
log_warn("error out of memory");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** load msg cache */
|
||||
static int
|
||||
load_msg_cache(SSL* ssl, struct worker* worker)
|
||||
{
|
||||
ldns_buffer* buf = worker->env.scratch_buffer;
|
||||
if(!read_fixed(ssl, buf, "START_MSG_CACHE")) return 0;
|
||||
while(ssl_read_buf(ssl, buf) &&
|
||||
strcmp((char*)ldns_buffer_begin(buf), "END_MSG_CACHE")!=0) {
|
||||
if(!load_msg(ssl, buf, worker))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
load_cache(SSL* ssl, struct worker* worker)
|
||||
{
|
||||
if(!load_rrset_cache(ssl, worker))
|
||||
return 0;
|
||||
if(!load_msg_cache(ssl, worker))
|
||||
return 0;
|
||||
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))
|
||||
{
|
||||
/* deep links into the iterator module */
|
||||
struct delegpt* dp;
|
||||
struct dns_msg* msg;
|
||||
struct regional* region = worker->scratchpad;
|
||||
char b[260];
|
||||
struct query_info qinfo;
|
||||
struct iter_hints_stub* stub;
|
||||
struct iter_env* ie;
|
||||
regional_free_all(region);
|
||||
qinfo.qname = nm;
|
||||
qinfo.qname_len = nmlen;
|
||||
qinfo.qtype = LDNS_RR_TYPE_A;
|
||||
qinfo.qclass = LDNS_RR_CLASS_IN;
|
||||
|
||||
if(modstack_find(&worker->daemon->mods, "iterator") == -1) {
|
||||
return ssl_printf(ssl, "error: no iterator module\n");
|
||||
}
|
||||
ie = (struct iter_env*)worker->env.modinfo[modstack_find(&worker->
|
||||
daemon->mods, "iterator")];
|
||||
|
||||
dname_str(nm, b);
|
||||
if(!ssl_printf(ssl, "The following name servers are used for lookup "
|
||||
"of %s\n", b))
|
||||
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,
|
||||
*worker->env.now);
|
||||
if(!dp) {
|
||||
return ssl_printf(ssl, "no delegation from "
|
||||
"cache; goes to configured roots\n");
|
||||
}
|
||||
/* 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;
|
||||
if(dname_is_root(nm)) {
|
||||
/* goes to root config */
|
||||
return ssl_printf(ssl, "no delegation from "
|
||||
"cache; goes to configured roots\n");
|
||||
} else {
|
||||
/* useless, goes up */
|
||||
nm = dp->name;
|
||||
nmlen = dp->namelen;
|
||||
dname_remove_label(&nm, &nmlen);
|
||||
dname_str(nm, b);
|
||||
if(!ssl_printf(ssl, "going up, lookup %s\n", b))
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* daemon/cachedump.h - dump the cache to text format.
|
||||
*
|
||||
* Copyright (c) 2008, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains functions to read and write the cache(s)
|
||||
* to text format.
|
||||
*
|
||||
* The format of the file is as follows:
|
||||
* [RRset cache]
|
||||
* [Message cache]
|
||||
* EOF -- fixed string "EOF" before end of the file.
|
||||
*
|
||||
* The RRset cache is:
|
||||
* START_RRSET_CACHE
|
||||
* [rrset]*
|
||||
* END_RRSET_CACHE
|
||||
*
|
||||
* rrset is:
|
||||
* ;rrset [nsec_apex] TTL rr_count rrsig_count trust security
|
||||
* resource records, one per line, in zonefile format
|
||||
* rrsig records, one per line, in zonefile format
|
||||
* If the text conversion fails, BADRR is printed on the line.
|
||||
*
|
||||
* The Message cache is:
|
||||
* START_MSG_CACHE
|
||||
* [msg]*
|
||||
* END_MSG_CACHE
|
||||
*
|
||||
* msg is:
|
||||
* msg name class type flags qdcount ttl security an ns ar
|
||||
* list of rrset references, one per line. If conversion fails, BADREF
|
||||
* reference is:
|
||||
* name class type flags
|
||||
*
|
||||
* Expired cache entries are not printed.
|
||||
*/
|
||||
|
||||
#ifndef DAEMON_DUMPCACHE_H
|
||||
#define DAEMON_DUMPCACHE_H
|
||||
struct worker;
|
||||
|
||||
/**
|
||||
* Dump cache(s) to text
|
||||
* @param ssl: to print to
|
||||
* @param worker: worker that is available (buffers, etc) and has
|
||||
* ptrs to the caches.
|
||||
* @return false on ssl print error.
|
||||
*/
|
||||
int dump_cache(SSL* ssl, struct worker* worker);
|
||||
|
||||
/**
|
||||
* Load cache(s) from text
|
||||
* @param ssl: to read from
|
||||
* @param worker: worker that is available (buffers, etc) and has
|
||||
* ptrs to the caches.
|
||||
* @return false on ssl error.
|
||||
*/
|
||||
int load_cache(SSL* ssl, struct worker* worker);
|
||||
|
||||
/**
|
||||
* Print the delegation used to lookup for this name.
|
||||
* @param ssl: to read from
|
||||
* @param worker: worker that is available (buffers, etc) and has
|
||||
* ptrs to the caches.
|
||||
* @param nm: name to lookup
|
||||
* @param nmlen: length of name.
|
||||
* @param nmlabs: labels in name.
|
||||
* @return false on ssl error.
|
||||
*/
|
||||
int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
|
||||
size_t nmlen, int nmlabs);
|
||||
|
||||
#endif /* DAEMON_DUMPCACHE_H */
|
||||
+180
-31
@@ -40,8 +40,25 @@
|
||||
*/
|
||||
|
||||
#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"
|
||||
#include "daemon/acl_list.h"
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
@@ -54,6 +71,7 @@
|
||||
#include "services/modstack.h"
|
||||
#include "util/module.h"
|
||||
#include "util/random.h"
|
||||
#include "util/tube.h"
|
||||
#include <signal.h>
|
||||
|
||||
/** How many quit requests happened. */
|
||||
@@ -61,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.
|
||||
@@ -76,15 +103,24 @@ static RETSIGTYPE record_sigh(int sig)
|
||||
switch(sig)
|
||||
{
|
||||
case SIGTERM:
|
||||
#ifdef SIGQUIT
|
||||
case SIGQUIT:
|
||||
#endif
|
||||
#ifdef SIGBREAK
|
||||
case SIGBREAK:
|
||||
#endif
|
||||
case SIGINT:
|
||||
sig_record_quit++;
|
||||
break;
|
||||
#ifdef SIGHUP
|
||||
case SIGHUP:
|
||||
sig_record_reload++;
|
||||
break;
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
case SIGPIPE:
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
log_err("ignoring signal %d", sig);
|
||||
}
|
||||
@@ -95,13 +131,23 @@ 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
|
||||
signal(SIGQUIT, record_sigh) == SIG_ERR ||
|
||||
signal(SIGINT, record_sigh) == SIG_ERR ||
|
||||
#endif
|
||||
#ifdef SIGBREAK
|
||||
signal(SIGBREAK, record_sigh) == SIG_ERR ||
|
||||
#endif
|
||||
#ifdef SIGHUP
|
||||
signal(SIGHUP, record_sigh) == SIG_ERR ||
|
||||
signal(SIGPIPE, SIG_IGN) == SIG_ERR)
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
signal(SIGPIPE, SIG_IGN) == SIG_ERR ||
|
||||
#endif
|
||||
signal(SIGINT, record_sigh) == SIG_ERR
|
||||
)
|
||||
log_err("install sighandler: %s", strerror(errno));
|
||||
}
|
||||
|
||||
@@ -112,8 +158,10 @@ signal_handling_record()
|
||||
static void
|
||||
signal_handling_playback(struct worker* wrk)
|
||||
{
|
||||
#ifdef SIGHUP
|
||||
if(sig_record_reload)
|
||||
worker_sighandler(SIGHUP, wrk);
|
||||
#endif
|
||||
if(sig_record_quit)
|
||||
worker_sighandler(SIGTERM, wrk);
|
||||
sig_record_quit = 0;
|
||||
@@ -121,15 +169,45 @@ signal_handling_playback(struct worker* wrk)
|
||||
}
|
||||
|
||||
struct daemon*
|
||||
daemon_init()
|
||||
daemon_init(void)
|
||||
{
|
||||
struct daemon* daemon = (struct daemon*)calloc(1,
|
||||
sizeof(struct daemon));
|
||||
#ifdef USE_WINSOCK
|
||||
int r;
|
||||
WSADATA wsa_data;
|
||||
#endif
|
||||
if(!daemon)
|
||||
return NULL;
|
||||
#ifdef USE_WINSOCK
|
||||
r = WSAStartup(MAKEWORD(2,2), &wsa_data);
|
||||
if(r != 0) {
|
||||
fatal_exit("could not init winsock. WSAStartup: %s",
|
||||
wsa_strerror(r));
|
||||
}
|
||||
#endif /* USE_WINSOCK */
|
||||
signal_handling_record();
|
||||
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 */
|
||||
tzset();
|
||||
#endif
|
||||
/* open /dev/random if needed */
|
||||
ub_systemseed((unsigned)time(NULL)^(unsigned)getpid()^0xe67);
|
||||
daemon->need_to_exit = 0;
|
||||
modstack_init(&daemon->mods);
|
||||
if(!(daemon->env = (struct module_env*)calloc(1,
|
||||
@@ -144,6 +222,9 @@ daemon_init()
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
if(gettimeofday(&daemon->time_boot, NULL) < 0)
|
||||
log_err("gettimeofday: %s", strerror(errno));
|
||||
daemon->time_last_stat = daemon->time_boot;
|
||||
return daemon;
|
||||
}
|
||||
|
||||
@@ -151,12 +232,24 @@ int
|
||||
daemon_open_shared_ports(struct daemon* daemon)
|
||||
{
|
||||
log_assert(daemon);
|
||||
if(daemon->cfg->port == daemon->listening_port)
|
||||
return 1;
|
||||
listening_ports_free(daemon->ports);
|
||||
if(!(daemon->ports=listening_ports_open(daemon->cfg)))
|
||||
return 0;
|
||||
daemon->listening_port = daemon->cfg->port;
|
||||
if(daemon->cfg->port != daemon->listening_port) {
|
||||
listening_ports_free(daemon->ports);
|
||||
if(!(daemon->ports=listening_ports_open(daemon->cfg)))
|
||||
return 0;
|
||||
daemon->listening_port = daemon->cfg->port;
|
||||
}
|
||||
if(!daemon->cfg->remote_control_enable && daemon->rc_port) {
|
||||
listening_ports_free(daemon->rc_ports);
|
||||
daemon->rc_ports = NULL;
|
||||
daemon->rc_port = 0;
|
||||
}
|
||||
if(daemon->cfg->remote_control_enable &&
|
||||
daemon->cfg->control_port != daemon->rc_port) {
|
||||
listening_ports_free(daemon->rc_ports);
|
||||
if(!(daemon->rc_ports=daemon_remote_open_ports(daemon->cfg)))
|
||||
return 0;
|
||||
daemon->rc_port = daemon->cfg->control_port;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -183,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;
|
||||
@@ -199,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;
|
||||
@@ -246,26 +339,28 @@ 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++)
|
||||
if(i!=thr) {
|
||||
if(daemon->workers[i]->cmd_send_fd != -1) {
|
||||
close(daemon->workers[i]->cmd_send_fd);
|
||||
daemon->workers[i]->cmd_send_fd = -1;
|
||||
}
|
||||
if(daemon->workers[i]->cmd_recv_fd != -1) {
|
||||
close(daemon->workers[i]->cmd_recv_fd);
|
||||
daemon->workers[i]->cmd_recv_fd = -1;
|
||||
if(i==0) {
|
||||
/* only close read part, need to write stats */
|
||||
tube_close_read(daemon->workers[i]->cmd);
|
||||
} else {
|
||||
/* complete close channel to others */
|
||||
tube_delete(daemon->workers[i]->cmd);
|
||||
daemon->workers[i]->cmd = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* THREADS_DISABLED */
|
||||
|
||||
/**
|
||||
* Function to start one thread.
|
||||
@@ -278,10 +373,9 @@ thread_start(void* arg)
|
||||
struct worker* worker = (struct worker*)arg;
|
||||
log_thread_set(&worker->thread_num);
|
||||
ub_thread_blocksigs();
|
||||
#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
|
||||
#ifdef THREADS_DISABLED
|
||||
/* close pipe ends used by main */
|
||||
close(worker->cmd_send_fd);
|
||||
worker->cmd_send_fd = -1;
|
||||
tube_close_write(worker->cmd);
|
||||
close_other_pipes(worker->daemon, worker->thread_num);
|
||||
#endif
|
||||
if(!worker_init(worker, worker->daemon->cfg, worker->daemon->ports, 0))
|
||||
@@ -305,10 +399,9 @@ daemon_start_others(struct daemon* daemon)
|
||||
for(i=1; i<daemon->num; i++) {
|
||||
ub_thread_create(&daemon->workers[i]->thr_id,
|
||||
thread_start, daemon->workers[i]);
|
||||
#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
|
||||
#ifdef THREADS_DISABLED
|
||||
/* close pipe end of child */
|
||||
close(daemon->workers[i]->cmd_recv_fd);
|
||||
daemon->workers[i]->cmd_recv_fd = -1;
|
||||
tube_close_read(daemon->workers[i]->cmd);
|
||||
#endif /* no threads */
|
||||
}
|
||||
}
|
||||
@@ -326,8 +419,7 @@ daemon_stop_others(struct daemon* daemon)
|
||||
/* skip i=0, is this thread */
|
||||
/* use i=0 buffer for sending cmds; because we are #0 */
|
||||
for(i=1; i<daemon->num; i++) {
|
||||
worker_send_cmd(daemon->workers[i],
|
||||
daemon->workers[0]->front->udp_buff, worker_cmd_quit);
|
||||
worker_send_cmd(daemon->workers[i], worker_cmd_quit);
|
||||
}
|
||||
/* wait for them to quit */
|
||||
for(i=1; i<daemon->num; i++) {
|
||||
@@ -356,6 +448,12 @@ daemon_fork(struct daemon* daemon)
|
||||
* them to the newly created threads.
|
||||
*/
|
||||
daemon_create_workers(daemon);
|
||||
|
||||
#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");
|
||||
#endif
|
||||
|
||||
/* Now create the threads and init the workers.
|
||||
* By the way, this is thread #0 (the main thread).
|
||||
@@ -363,10 +461,13 @@ daemon_fork(struct daemon* daemon)
|
||||
daemon_start_others(daemon);
|
||||
|
||||
/* Special handling for the main thread. This is the thread
|
||||
* that handles signals.
|
||||
* that handles signals and remote control.
|
||||
*/
|
||||
#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");
|
||||
#endif
|
||||
signal_handling_playback(daemon->workers[0]);
|
||||
|
||||
/* Start resolver service on main thread. */
|
||||
@@ -398,6 +499,7 @@ daemon_cleanup(struct daemon* daemon)
|
||||
local_zones_delete(daemon->local_zones);
|
||||
daemon->local_zones = NULL;
|
||||
/* key cache is cleared by module desetup during next daemon_init() */
|
||||
daemon_remote_clear(daemon->rc);
|
||||
for(i=0; i<daemon->num; i++)
|
||||
worker_delete(daemon->workers[i]);
|
||||
free(daemon->workers);
|
||||
@@ -412,7 +514,9 @@ daemon_delete(struct daemon* daemon)
|
||||
if(!daemon)
|
||||
return;
|
||||
modstack_desetup(&daemon->mods, daemon->env);
|
||||
daemon_remote_delete(daemon->rc);
|
||||
listening_ports_free(daemon->ports);
|
||||
listening_ports_free(daemon->rc_ports);
|
||||
if(daemon->env) {
|
||||
slabhash_delete(daemon->env->msg_cache);
|
||||
rrset_cache_delete(daemon->env->rrset_cache);
|
||||
@@ -421,16 +525,61 @@ daemon_delete(struct daemon* daemon)
|
||||
ub_randfree(daemon->rand);
|
||||
alloc_clear(&daemon->superalloc);
|
||||
acl_list_delete(daemon->acl);
|
||||
free(daemon->chroot);
|
||||
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();
|
||||
RAND_cleanup();
|
||||
checklock_stop();
|
||||
#ifdef USE_WINSOCK
|
||||
if(WSACleanup() != 0) {
|
||||
log_err("Could not WSACleanup: %s",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg)
|
||||
{
|
||||
daemon->cfg = cfg;
|
||||
config_apply(cfg);
|
||||
if(!daemon->env->msg_cache ||
|
||||
cfg->msg_cache_size != slabhash_get_size(daemon->env->msg_cache) ||
|
||||
cfg->msg_cache_slabs != daemon->env->msg_cache->size) {
|
||||
slabhash_delete(daemon->env->msg_cache);
|
||||
daemon->env->msg_cache = slabhash_create(cfg->msg_cache_slabs,
|
||||
HASH_DEFAULT_STARTARRAY, cfg->msg_cache_size,
|
||||
msgreply_sizefunc, query_info_compare,
|
||||
query_entry_delete, reply_info_delete, NULL);
|
||||
if(!daemon->env->msg_cache) {
|
||||
fatal_exit("malloc failure updating config settings");
|
||||
}
|
||||
}
|
||||
if((daemon->env->rrset_cache = rrset_cache_adjust(
|
||||
daemon->env->rrset_cache, cfg, &daemon->superalloc)) == 0)
|
||||
fatal_exit("malloc failure updating config settings");
|
||||
if((daemon->env->infra_cache = infra_adjust(daemon->env->infra_cache,
|
||||
cfg))==0)
|
||||
fatal_exit("malloc failure updating config settings");
|
||||
}
|
||||
|
||||
+24
-1
@@ -45,6 +45,9 @@
|
||||
#include "util/locks.h"
|
||||
#include "util/alloc.h"
|
||||
#include "services/modstack.h"
|
||||
#ifdef UB_ON_WINDOWS
|
||||
# include "util/winsock_event.h"
|
||||
#endif
|
||||
struct config_file;
|
||||
struct worker;
|
||||
struct listen_port;
|
||||
@@ -54,6 +57,7 @@ struct rrset_cache;
|
||||
struct acl_list;
|
||||
struct local_zones;
|
||||
struct ub_randstate;
|
||||
struct daemon_remote;
|
||||
|
||||
/**
|
||||
* Structure holding worker list.
|
||||
@@ -62,12 +66,20 @@ struct ub_randstate;
|
||||
struct daemon {
|
||||
/** The config settings */
|
||||
struct config_file* cfg;
|
||||
/** the chroot dir in use, NULL if none */
|
||||
char* chroot;
|
||||
/** pidfile that is used */
|
||||
char* pidfile;
|
||||
/** port number that has ports opened. */
|
||||
int listening_port;
|
||||
/** listening ports, opened, to be shared by threads */
|
||||
struct listen_port* ports;
|
||||
/** port number for remote that has ports opened. */
|
||||
int rc_port;
|
||||
/** listening ports for remote control */
|
||||
struct listen_port* rc_ports;
|
||||
/** remote control connections management (for first worker) */
|
||||
struct daemon_remote* rc;
|
||||
/** num threads allocated */
|
||||
int num;
|
||||
/** the worker entries */
|
||||
@@ -86,13 +98,17 @@ struct daemon {
|
||||
struct acl_list* acl;
|
||||
/** local authority zones */
|
||||
struct local_zones* local_zones;
|
||||
/** last time of statistics printout */
|
||||
struct timeval time_last_stat;
|
||||
/** time when daemon started */
|
||||
struct timeval time_boot;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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).
|
||||
@@ -122,4 +138,11 @@ void daemon_cleanup(struct daemon* daemon);
|
||||
*/
|
||||
void daemon_delete(struct daemon* daemon);
|
||||
|
||||
/**
|
||||
* Apply config settings.
|
||||
* @param daemon: the daemon.
|
||||
* @param cfg: new config settings.
|
||||
*/
|
||||
void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg);
|
||||
|
||||
#endif /* DAEMON_H */
|
||||
|
||||
+1972
File diff suppressed because it is too large
Load Diff
+180
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* daemon/remote.h - remote control for the unbound daemon.
|
||||
*
|
||||
* Copyright (c) 2008, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains the remote control functionality for the daemon.
|
||||
* The remote control can be performed using either the commandline
|
||||
* unbound-control tool, or a SSLv3/TLS capable web browser.
|
||||
* The channel is secured using SSLv3 or TLSv1, and certificates.
|
||||
* Both the server and the client(control tool) have their own keys.
|
||||
*/
|
||||
|
||||
#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;
|
||||
struct worker;
|
||||
struct comm_reply;
|
||||
struct comm_point;
|
||||
struct daemon_remote;
|
||||
|
||||
/** number of seconds timeout on incoming remote control handshake */
|
||||
#define REMOTE_CONTROL_TCP_TIMEOUT 120
|
||||
|
||||
/**
|
||||
* a busy control command connection, SSL state
|
||||
*/
|
||||
struct rc_state {
|
||||
/** the next item in list */
|
||||
struct rc_state* next;
|
||||
/** the commpoint */
|
||||
struct comm_point* c;
|
||||
/** in the handshake part */
|
||||
enum { rc_none, rc_hs_read, rc_hs_write } shake_state;
|
||||
/** the ssl state */
|
||||
SSL* ssl;
|
||||
/** the rc this is part of */
|
||||
struct daemon_remote* rc;
|
||||
};
|
||||
|
||||
/**
|
||||
* The remote control tool state.
|
||||
* The state is only created for the first thread, other threads
|
||||
* are called from this thread. Only the first threads listens to
|
||||
* the control port. The other threads do not, but are called on the
|
||||
* command channel(pipe) from the first thread.
|
||||
*/
|
||||
struct daemon_remote {
|
||||
/** the worker for this remote control */
|
||||
struct worker* worker;
|
||||
/** commpoints for accepting remote control connections */
|
||||
struct listen_list* accept_list;
|
||||
/** number of active commpoints that are handling remote control */
|
||||
int active;
|
||||
/** max active commpoints */
|
||||
int max_active;
|
||||
/** current commpoints busy; should be a short list, malloced */
|
||||
struct rc_state* busy_list;
|
||||
/** the SSL context for creating new SSL streams */
|
||||
SSL_CTX* ctx;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create new remote control state for the daemon.
|
||||
* @param cfg: config file with key file settings.
|
||||
* @return new state, or NULL on failure.
|
||||
*/
|
||||
struct daemon_remote* daemon_remote_create(struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* remote control state to delete.
|
||||
* @param rc: state to delete.
|
||||
*/
|
||||
void daemon_remote_delete(struct daemon_remote* rc);
|
||||
|
||||
/**
|
||||
* remote control state to clear up. Busy and accept points are closed.
|
||||
* Does not delete the rc itself, or the ssl context (with its keys).
|
||||
* @param rc: state to clear.
|
||||
*/
|
||||
void daemon_remote_clear(struct daemon_remote* rc);
|
||||
|
||||
/**
|
||||
* Open and create listening ports for remote control.
|
||||
* @param cfg: config options.
|
||||
* @return list of ports or NULL on failure.
|
||||
* can be freed with listening_ports_free().
|
||||
*/
|
||||
struct listen_port* daemon_remote_open_ports(struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Setup comm points for accepting remote control connections.
|
||||
* @param rc: state
|
||||
* @param ports: already opened ports.
|
||||
* @param worker: worker with communication base. and links to command channels.
|
||||
* @return false on error.
|
||||
*/
|
||||
int daemon_remote_open_accept(struct daemon_remote* rc,
|
||||
struct listen_port* ports, struct worker* worker);
|
||||
|
||||
/**
|
||||
* Handle nonthreaded remote cmd execution.
|
||||
* @param worker: this worker (the remote worker).
|
||||
*/
|
||||
void daemon_remote_exec(struct worker* worker);
|
||||
|
||||
/** handle remote control accept callbacks */
|
||||
int remote_accept_callback(struct comm_point*, void*, int, struct comm_reply*);
|
||||
|
||||
/** handle remote control data callbacks */
|
||||
int remote_control_callback(struct comm_point*, void*, int, struct comm_reply*);
|
||||
|
||||
/**
|
||||
* Print fixed line of text over ssl connection in blocking mode
|
||||
* @param ssl: print to
|
||||
* @param text: the text.
|
||||
* @return false on connection failure.
|
||||
*/
|
||||
int ssl_print_text(SSL* ssl, const char* text);
|
||||
|
||||
/**
|
||||
* printf style printing to the ssl connection
|
||||
* @param ssl: the SSL connection to print to. Blocking.
|
||||
* @param format: printf style format string.
|
||||
* @return success or false on a network failure.
|
||||
*/
|
||||
int ssl_printf(SSL* ssl, const char* format, ...)
|
||||
ATTR_FORMAT(printf, 2, 3);
|
||||
|
||||
/**
|
||||
* Read until \n is encountered
|
||||
* If SSL signals EOF, the string up to then is returned (without \n).
|
||||
* @param ssl: the SSL connection to read from. blocking.
|
||||
* @param buf: buffer to read to.
|
||||
* @param max: size of buffer.
|
||||
* @return false on connection failure.
|
||||
*/
|
||||
int ssl_read_line(SSL* ssl, char* buf, size_t max);
|
||||
|
||||
/** routine to printout option values over SSL */
|
||||
void remote_get_opt_ssl(char* line, void* arg);
|
||||
|
||||
#endif /* DAEMON_REMOTE_H */
|
||||
+234
-7
@@ -40,13 +40,36 @@
|
||||
* 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"
|
||||
#include "services/mesh.h"
|
||||
#include "services/outside_network.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/tube.h"
|
||||
#include "util/timehist.h"
|
||||
#include "util/net_help.h"
|
||||
#include "validator/validator.h"
|
||||
|
||||
void server_stats_init(struct server_stats* stats)
|
||||
/** add timers and the values do not overflow or become negative */
|
||||
static void
|
||||
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;
|
||||
if(d->tv_usec > 1000000) {
|
||||
d->tv_usec -= 1000000;
|
||||
d->tv_sec++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void server_stats_init(struct server_stats* stats, struct config_file* cfg)
|
||||
{
|
||||
memset(stats, 0, sizeof(*stats));
|
||||
stats->extended = cfg->stat_extended;
|
||||
}
|
||||
|
||||
void server_stats_querymiss(struct server_stats* stats, struct worker* worker)
|
||||
@@ -57,18 +80,222 @@ void server_stats_querymiss(struct server_stats* stats, struct worker* worker)
|
||||
stats->max_query_list_size = worker->env.mesh->all.count;
|
||||
}
|
||||
|
||||
void server_stats_log(struct server_stats* stats, int threadnum)
|
||||
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,
|
||||
(unsigned)stats->num_query_list_exceeded);
|
||||
(stats->num_queries_missed_cache+
|
||||
stats->num_queries_prefetch) : 0.0,
|
||||
(unsigned)worker->env.mesh->stats_dropped);
|
||||
}
|
||||
|
||||
/** get rrsets bogus number from validator */
|
||||
static size_t
|
||||
get_rrset_bogus(struct worker* worker)
|
||||
{
|
||||
int m = modstack_find(&worker->env.mesh->mods, "validator");
|
||||
struct val_env* ve;
|
||||
size_t r;
|
||||
if(m == -1)
|
||||
return 0;
|
||||
ve = (struct val_env*)worker->env.modinfo[m];
|
||||
lock_basic_lock(&ve->bogus_lock);
|
||||
r = ve->num_rrset_bogus;
|
||||
if(!worker->env.cfg->stat_cumulative)
|
||||
ve->num_rrset_bogus = 0;
|
||||
lock_basic_unlock(&ve->bogus_lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
server_stats_compile(struct worker* worker, struct stats_info* s, int reset)
|
||||
{
|
||||
int i;
|
||||
|
||||
s->svr = worker->stats;
|
||||
s->mesh_num_states = worker->env.mesh->all.count;
|
||||
s->mesh_num_reply_states = worker->env.mesh->num_reply_states;
|
||||
s->mesh_jostled = worker->env.mesh->stats_jostled;
|
||||
s->mesh_dropped = worker->env.mesh->stats_dropped;
|
||||
s->mesh_replies_sent = worker->env.mesh->replies_sent;
|
||||
s->mesh_replies_sum_wait = worker->env.mesh->replies_sum_wait;
|
||||
s->mesh_time_median = timehist_quartile(worker->env.mesh->histogram,
|
||||
0.50);
|
||||
|
||||
/* add in the values from the mesh */
|
||||
s->svr.ans_secure += worker->env.mesh->ans_secure;
|
||||
s->svr.ans_bogus += worker->env.mesh->ans_bogus;
|
||||
s->svr.ans_rcode_nodata += worker->env.mesh->ans_nodata;
|
||||
for(i=0; i<16; i++)
|
||||
s->svr.ans_rcode[i] += worker->env.mesh->ans_rcode[i];
|
||||
timehist_export(worker->env.mesh->histogram, s->svr.hist,
|
||||
NUM_BUCKETS_HIST);
|
||||
/* values from outside network */
|
||||
s->svr.unwanted_replies = worker->back->unwanted_replies;
|
||||
|
||||
/* get and reset validator rrset bogus number */
|
||||
s->svr.rrset_bogus = get_rrset_bogus(worker);
|
||||
|
||||
if(reset && !worker->env.cfg->stat_cumulative) {
|
||||
worker_stats_clear(worker);
|
||||
}
|
||||
}
|
||||
|
||||
void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
struct stats_info* s, int reset)
|
||||
{
|
||||
uint8_t *reply = NULL;
|
||||
uint32_t len = 0;
|
||||
if(worker == who) {
|
||||
/* just fill it in */
|
||||
server_stats_compile(worker, s, reset);
|
||||
return;
|
||||
}
|
||||
/* communicate over tube */
|
||||
verbose(VERB_ALGO, "write stats cmd");
|
||||
if(reset)
|
||||
worker_send_cmd(who, worker_cmd_stats);
|
||||
else worker_send_cmd(who, worker_cmd_stats_noreset);
|
||||
verbose(VERB_ALGO, "wait for stats reply");
|
||||
if(!tube_read_msg(worker->cmd, &reply, &len, 0))
|
||||
fatal_exit("failed to read stats over cmd channel");
|
||||
if(len != (uint32_t)sizeof(*s))
|
||||
fatal_exit("stats on cmd channel wrong length %d %d",
|
||||
(int)len, (int)sizeof(*s));
|
||||
memcpy(s, reply, (size_t)len);
|
||||
free(reply);
|
||||
}
|
||||
|
||||
void server_stats_reply(struct worker* worker, int reset)
|
||||
{
|
||||
struct stats_info s;
|
||||
server_stats_compile(worker, &s, reset);
|
||||
verbose(VERB_ALGO, "write stats replymsg");
|
||||
if(!tube_write_msg(worker->daemon->workers[0]->cmd,
|
||||
(uint8_t*)&s, sizeof(s), 0))
|
||||
fatal_exit("could not write stat values over cmd channel");
|
||||
}
|
||||
|
||||
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)
|
||||
total->svr.max_query_list_size = a->svr.max_query_list_size;
|
||||
|
||||
if(a->svr.extended) {
|
||||
int i;
|
||||
total->svr.qtype_big += a->svr.qtype_big;
|
||||
total->svr.qclass_big += a->svr.qclass_big;
|
||||
total->svr.qtcp += a->svr.qtcp;
|
||||
total->svr.qipv6 += a->svr.qipv6;
|
||||
total->svr.qbit_QR += a->svr.qbit_QR;
|
||||
total->svr.qbit_AA += a->svr.qbit_AA;
|
||||
total->svr.qbit_TC += a->svr.qbit_TC;
|
||||
total->svr.qbit_RD += a->svr.qbit_RD;
|
||||
total->svr.qbit_RA += a->svr.qbit_RA;
|
||||
total->svr.qbit_Z += a->svr.qbit_Z;
|
||||
total->svr.qbit_AD += a->svr.qbit_AD;
|
||||
total->svr.qbit_CD += a->svr.qbit_CD;
|
||||
total->svr.qEDNS += a->svr.qEDNS;
|
||||
total->svr.qEDNS_DO += a->svr.qEDNS_DO;
|
||||
total->svr.ans_rcode_nodata += a->svr.ans_rcode_nodata;
|
||||
total->svr.ans_secure += a->svr.ans_secure;
|
||||
total->svr.ans_bogus += a->svr.ans_bogus;
|
||||
total->svr.rrset_bogus += a->svr.rrset_bogus;
|
||||
total->svr.unwanted_replies += a->svr.unwanted_replies;
|
||||
total->svr.unwanted_queries += a->svr.unwanted_queries;
|
||||
for(i=0; i<STATS_QTYPE_NUM; i++)
|
||||
total->svr.qtype[i] += a->svr.qtype[i];
|
||||
for(i=0; i<STATS_QCLASS_NUM; i++)
|
||||
total->svr.qclass[i] += a->svr.qclass[i];
|
||||
for(i=0; i<STATS_OPCODE_NUM; i++)
|
||||
total->svr.qopcode[i] += a->svr.qopcode[i];
|
||||
for(i=0; i<STATS_RCODE_NUM; i++)
|
||||
total->svr.ans_rcode[i] += a->svr.ans_rcode[i];
|
||||
for(i=0; i<NUM_BUCKETS_HIST; i++)
|
||||
total->svr.hist[i] += a->svr.hist[i];
|
||||
}
|
||||
|
||||
total->mesh_num_states += a->mesh_num_states;
|
||||
total->mesh_num_reply_states += a->mesh_num_reply_states;
|
||||
total->mesh_jostled += a->mesh_jostled;
|
||||
total->mesh_dropped += a->mesh_dropped;
|
||||
total->mesh_replies_sent += a->mesh_replies_sent;
|
||||
timeval_add(&total->mesh_replies_sum_wait, &a->mesh_replies_sum_wait);
|
||||
/* the medians are averaged together, this is not as accurate as
|
||||
* taking the median over all of the data, but is good and fast
|
||||
* added up here, division later*/
|
||||
total->mesh_time_median += a->mesh_time_median;
|
||||
}
|
||||
|
||||
void server_stats_insquery(struct server_stats* stats, struct comm_point* c,
|
||||
uint16_t qtype, uint16_t qclass, struct edns_data* edns,
|
||||
struct comm_reply* repinfo)
|
||||
{
|
||||
uint16_t flags = ldns_buffer_read_u16_at(c->buffer, 2);
|
||||
if(qtype < STATS_QTYPE_NUM)
|
||||
stats->qtype[qtype]++;
|
||||
else stats->qtype_big++;
|
||||
if(qclass < STATS_QCLASS_NUM)
|
||||
stats->qclass[qclass]++;
|
||||
else stats->qclass_big++;
|
||||
stats->qopcode[ LDNS_OPCODE_WIRE(ldns_buffer_begin(c->buffer)) ]++;
|
||||
if(c->type != comm_udp)
|
||||
stats->qtcp++;
|
||||
if(repinfo && addr_is_ip6(&repinfo->addr, repinfo->addrlen))
|
||||
stats->qipv6++;
|
||||
if( (flags&BIT_QR) )
|
||||
stats->qbit_QR++;
|
||||
if( (flags&BIT_AA) )
|
||||
stats->qbit_AA++;
|
||||
if( (flags&BIT_TC) )
|
||||
stats->qbit_TC++;
|
||||
if( (flags&BIT_RD) )
|
||||
stats->qbit_RD++;
|
||||
if( (flags&BIT_RA) )
|
||||
stats->qbit_RA++;
|
||||
if( (flags&BIT_Z) )
|
||||
stats->qbit_Z++;
|
||||
if( (flags&BIT_AD) )
|
||||
stats->qbit_AD++;
|
||||
if( (flags&BIT_CD) )
|
||||
stats->qbit_CD++;
|
||||
if(edns->edns_present) {
|
||||
stats->qEDNS++;
|
||||
if( (edns->bits & EDNS_DO) )
|
||||
stats->qEDNS_DO++;
|
||||
}
|
||||
}
|
||||
|
||||
void server_stats_insrcode(struct server_stats* stats, ldns_buffer* buf)
|
||||
{
|
||||
if(stats->extended && ldns_buffer_limit(buf) != 0) {
|
||||
int r = (int)LDNS_RCODE_WIRE( ldns_buffer_begin(buf) );
|
||||
stats->ans_rcode[r] ++;
|
||||
if(r == 0 && LDNS_ANCOUNT( ldns_buffer_begin(buf) ) == 0)
|
||||
stats->ans_rcode_nodata ++;
|
||||
}
|
||||
}
|
||||
|
||||
+162
-4
@@ -42,7 +42,22 @@
|
||||
|
||||
#ifndef DAEMON_STATS_H
|
||||
#define DAEMON_STATS_H
|
||||
#include "util/timehist.h"
|
||||
#include "ldns/buffer.h"
|
||||
struct worker;
|
||||
struct config_file;
|
||||
struct comm_point;
|
||||
struct comm_reply;
|
||||
struct edns_data;
|
||||
|
||||
/** number of qtype that is stored for in array */
|
||||
#define STATS_QTYPE_NUM 256
|
||||
/** number of qclass that is stored for in array */
|
||||
#define STATS_QCLASS_NUM 256
|
||||
/** number of rcodes in stats */
|
||||
#define STATS_RCODE_NUM 16
|
||||
/** number of opcodes in stats */
|
||||
#define STATS_OPCODE_NUM 16
|
||||
|
||||
/** per worker statistics */
|
||||
struct server_stats {
|
||||
@@ -50,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
|
||||
@@ -58,20 +75,161 @@ struct server_stats {
|
||||
size_t sum_query_list_size;
|
||||
/** max value of query list size reached. */
|
||||
size_t max_query_list_size;
|
||||
/** number of times that the query_list_size was insufficient */
|
||||
size_t num_query_list_exceeded;
|
||||
|
||||
/** Extended stats below (bool) */
|
||||
int extended;
|
||||
|
||||
/** qtype stats */
|
||||
size_t qtype[STATS_QTYPE_NUM];
|
||||
/** bigger qtype values not in array */
|
||||
size_t qtype_big;
|
||||
/** qclass stats */
|
||||
size_t qclass[STATS_QCLASS_NUM];
|
||||
/** bigger qclass values not in array */
|
||||
size_t qclass_big;
|
||||
/** query opcodes */
|
||||
size_t qopcode[STATS_OPCODE_NUM];
|
||||
/** number of queries over TCP */
|
||||
size_t qtcp;
|
||||
/** number of queries over IPv6 */
|
||||
size_t qipv6;
|
||||
/** number of queries with QR bit */
|
||||
size_t qbit_QR;
|
||||
/** number of queries with AA bit */
|
||||
size_t qbit_AA;
|
||||
/** number of queries with TC bit */
|
||||
size_t qbit_TC;
|
||||
/** number of queries with RD bit */
|
||||
size_t qbit_RD;
|
||||
/** number of queries with RA bit */
|
||||
size_t qbit_RA;
|
||||
/** number of queries with Z bit */
|
||||
size_t qbit_Z;
|
||||
/** number of queries with AD bit */
|
||||
size_t qbit_AD;
|
||||
/** number of queries with CD bit */
|
||||
size_t qbit_CD;
|
||||
/** number of queries with EDNS OPT record */
|
||||
size_t qEDNS;
|
||||
/** number of queries with EDNS with DO flag */
|
||||
size_t qEDNS_DO;
|
||||
/** answer rcodes */
|
||||
size_t ans_rcode[STATS_RCODE_NUM];
|
||||
/** answers with pseudo rcode 'nodata' */
|
||||
size_t ans_rcode_nodata;
|
||||
/** answers that were secure (AD) */
|
||||
size_t ans_secure;
|
||||
/** answers that were bogus (withheld as SERVFAIL) */
|
||||
size_t ans_bogus;
|
||||
/** rrsets marked bogus by validator */
|
||||
size_t rrset_bogus;
|
||||
/** unwanted traffic received on server-facing ports */
|
||||
size_t unwanted_replies;
|
||||
/** unwanted traffic received on client-facing ports */
|
||||
size_t unwanted_queries;
|
||||
|
||||
/** histogram data exported to array
|
||||
* if the array is the same size, no data is lost, and
|
||||
* if all histograms are same size (is so by default) then
|
||||
* adding up works well. */
|
||||
size_t hist[NUM_BUCKETS_HIST];
|
||||
};
|
||||
|
||||
/**
|
||||
* Statistics to send over the control pipe when asked
|
||||
* This struct is made to be memcpied, sent in binary.
|
||||
*/
|
||||
struct stats_info {
|
||||
/** the thread stats */
|
||||
struct server_stats svr;
|
||||
|
||||
/** mesh stats: current number of states */
|
||||
size_t mesh_num_states;
|
||||
/** mesh stats: current number of reply (user) states */
|
||||
size_t mesh_num_reply_states;
|
||||
/** mesh stats: number of reply states overwritten with a new one */
|
||||
size_t mesh_jostled;
|
||||
/** mesh stats: number of incoming queries dropped */
|
||||
size_t mesh_dropped;
|
||||
/** mesh stats: replies sent */
|
||||
size_t mesh_replies_sent;
|
||||
/** mesh stats: sum of waiting times for the replies */
|
||||
struct timeval mesh_replies_sum_wait;
|
||||
/** mesh stats: median of waiting times for replies (in sec) */
|
||||
double mesh_time_median;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize server stats to 0.
|
||||
* @param stats: what to init (this is alloced by the caller).
|
||||
* @param cfg: with extended statistics option.
|
||||
*/
|
||||
void server_stats_init(struct server_stats* stats);
|
||||
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, int threadnum);
|
||||
void server_stats_log(struct server_stats* stats, struct worker* worker,
|
||||
int threadnum);
|
||||
|
||||
/**
|
||||
* Obtain the stats info for a given thread. Uses pipe to communicate.
|
||||
* @param worker: the worker that is executing (the first worker).
|
||||
* @param who: on who to get the statistics info.
|
||||
* @param s: the stats block to fill in.
|
||||
* @param reset: if stats can be reset.
|
||||
*/
|
||||
void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
struct stats_info* s, int reset);
|
||||
|
||||
/**
|
||||
* Compile stats into structure for this thread worker.
|
||||
* Also clears the statistics counters (if that is set by config file).
|
||||
* @param worker: the worker to compile stats for, also the executing worker.
|
||||
* @param s: stats block.
|
||||
* @param reset: if true, depending on config stats are reset.
|
||||
* if false, statistics are not reset.
|
||||
*/
|
||||
void server_stats_compile(struct worker* worker, struct stats_info* s,
|
||||
int reset);
|
||||
|
||||
/**
|
||||
* Send stats over comm tube in reply to query cmd
|
||||
* @param worker: this worker.
|
||||
* @param reset: if true, depending on config stats are reset.
|
||||
* if false, statistics are not reset.
|
||||
*/
|
||||
void server_stats_reply(struct worker* worker, int reset);
|
||||
|
||||
/**
|
||||
* Addup stat blocks.
|
||||
* @param total: sum of the two entries.
|
||||
* @param a: to add to it.
|
||||
*/
|
||||
void server_stats_add(struct stats_info* total, struct stats_info* a);
|
||||
|
||||
/**
|
||||
* Add stats for this query
|
||||
* @param stats: the stats
|
||||
* @param c: commpoint with type and buffer.
|
||||
* @param qtype: query type
|
||||
* @param qclass: query class
|
||||
* @param edns: edns record
|
||||
* @param repinfo: reply info with remote address
|
||||
*/
|
||||
void server_stats_insquery(struct server_stats* stats, struct comm_point* c,
|
||||
uint16_t qtype, uint16_t qclass, struct edns_data* edns,
|
||||
struct comm_reply* repinfo);
|
||||
|
||||
/**
|
||||
* Add rcode for this query.
|
||||
* @param stats: the stats
|
||||
* @param buf: buffer with rcode. If buffer is length0: not counted.
|
||||
*/
|
||||
void server_stats_insrcode(struct server_stats* stats, ldns_buffer* buf);
|
||||
|
||||
#endif /* DAEMON_STATS_H */
|
||||
|
||||
+337
-75
@@ -41,8 +41,13 @@
|
||||
*/
|
||||
|
||||
#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"
|
||||
#include "util/config_file.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
@@ -52,24 +57,91 @@
|
||||
#include "util/module.h"
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <openssl/crypto.h>
|
||||
#ifdef HAVE_PWD_H
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
#ifdef HAVE_GRP_H
|
||||
#include <grp.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
#ifdef HAVE_LOGIN_CAP_H
|
||||
#include <login_cap.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_MINI_EVENT
|
||||
#include "util/mini_event.h"
|
||||
# ifdef USE_WINSOCK
|
||||
# include "util/winsock_event.h"
|
||||
# else
|
||||
# include "util/mini_event.h"
|
||||
# endif
|
||||
#else
|
||||
#include <event.h>
|
||||
# include <event.h>
|
||||
#endif
|
||||
|
||||
#ifdef UB_ON_WINDOWS
|
||||
# include "winrc/win_svc.h"
|
||||
#endif
|
||||
|
||||
/** global debug value to keep track of heap memory allocation */
|
||||
void* unbound_start_brk = 0;
|
||||
|
||||
#if !defined(HAVE_EVENT_BASE_GET_METHOD) && (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP))
|
||||
static const char* ev_backend2str(int b)
|
||||
{
|
||||
switch(b) {
|
||||
case EVBACKEND_SELECT: return "select";
|
||||
case EVBACKEND_POLL: return "poll";
|
||||
case EVBACKEND_EPOLL: return "epoll";
|
||||
case EVBACKEND_KQUEUE: return "kqueue";
|
||||
case EVBACKEND_DEVPOLL: return "devpoll";
|
||||
case EVBACKEND_PORT: return "evport";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
#endif
|
||||
|
||||
/** get the event system in use */
|
||||
static void get_event_sys(const char** n, const char** s, const char** m)
|
||||
{
|
||||
#ifdef USE_WINSOCK
|
||||
*n = "event";
|
||||
*s = "winsock";
|
||||
*m = "WSAWaitForMultipleEvents";
|
||||
#elif defined(USE_MINI_EVENT)
|
||||
*n = "mini-event";
|
||||
*s = "internal";
|
||||
*m = "select";
|
||||
#else
|
||||
struct event_base* b;
|
||||
*s = event_get_version();
|
||||
# ifdef HAVE_EVENT_BASE_GET_METHOD
|
||||
*n = "libevent";
|
||||
b = event_base_new();
|
||||
*m = event_base_get_method(b);
|
||||
# elif defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
|
||||
*n = "libev";
|
||||
b = (struct event_base*)ev_default_loop(EVFLAG_AUTO);
|
||||
*m = ev_backend2str(ev_backend((struct ev_loop*)b));
|
||||
# else
|
||||
*n = "unknown";
|
||||
*m = "not obtainable";
|
||||
b = NULL;
|
||||
# endif
|
||||
# ifdef HAVE_EVENT_BASE_FREE
|
||||
event_base_free(b);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/** print usage. */
|
||||
static void usage()
|
||||
{
|
||||
const char** m;
|
||||
const char *evnm="event", *evsys="", *evmethod="";
|
||||
printf("usage: unbound [options]\n");
|
||||
printf(" start unbound daemon DNS resolver.\n");
|
||||
printf("-h this help\n");
|
||||
@@ -77,22 +149,46 @@ static void usage()
|
||||
printf(" file format is described in unbound.conf(5).\n");
|
||||
printf("-d do not fork into the background.\n");
|
||||
printf("-v verbose (more times to increase verbosity)\n");
|
||||
#ifdef UB_ON_WINDOWS
|
||||
printf("-w opt windows option: \n");
|
||||
printf(" install, remove - manage the services entry\n");
|
||||
printf(" service - used to start from services control panel\n");
|
||||
#endif
|
||||
printf("Version %s\n", PACKAGE_VERSION);
|
||||
printf("libevent %s, libldns %s\n",
|
||||
event_get_version(), 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)
|
||||
{
|
||||
int list = ((cfg->do_ip4?1:0) + (cfg->do_ip6?1:0)) *
|
||||
((cfg->do_udp?1:0) + (cfg->do_tcp?1 +
|
||||
#ifdef HAVE_GETRLIMIT
|
||||
/* list has number of ports to listen to, ifs number addresses */
|
||||
int list = ((cfg->do_udp?1:0) + (cfg->do_tcp?1 +
|
||||
(int)cfg->incoming_num_tcp:0));
|
||||
size_t ifs = (size_t)(cfg->num_ifs==0?1:cfg->num_ifs);
|
||||
size_t listen_num = list*ifs;
|
||||
size_t listen_ifs = (size_t)(cfg->num_ifs==0?
|
||||
((cfg->do_ip4 && !cfg->if_automatic?1:0) +
|
||||
(cfg->do_ip6?1:0)):cfg->num_ifs);
|
||||
size_t listen_num = list*listen_ifs;
|
||||
size_t outudpnum = (size_t)cfg->outgoing_num_ports;
|
||||
size_t outtcpnum = cfg->outgoing_num_tcp;
|
||||
size_t misc = 4; /* logfile, pidfile, stdout... */
|
||||
@@ -109,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;
|
||||
@@ -119,21 +244,33 @@ 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,
|
||||
* with 15 as margin */
|
||||
if(numthread*perthread_noudp+15 > avail)
|
||||
fatal_exit("too much tcp. not enough fds.");
|
||||
cfg->outgoing_num_ports = (int)((avail
|
||||
- numthread*perthread_noudp
|
||||
- 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);
|
||||
}
|
||||
#else
|
||||
(void)cfg;
|
||||
#endif /* HAVE_GETRLIMIT */
|
||||
}
|
||||
|
||||
/** set verbosity, check rlimits, cache settings */
|
||||
@@ -142,30 +279,12 @@ apply_settings(struct daemon* daemon, struct config_file* cfg,
|
||||
int cmdline_verbose)
|
||||
{
|
||||
/* apply if they have changed */
|
||||
daemon->cfg = cfg;
|
||||
verbosity = cmdline_verbose + cfg->verbosity;
|
||||
config_apply(cfg);
|
||||
if(!daemon->env->msg_cache ||
|
||||
cfg->msg_cache_size != slabhash_get_size(daemon->env->msg_cache) ||
|
||||
cfg->msg_cache_slabs != daemon->env->msg_cache->size) {
|
||||
slabhash_delete(daemon->env->msg_cache);
|
||||
daemon->env->msg_cache = slabhash_create(cfg->msg_cache_slabs,
|
||||
HASH_DEFAULT_STARTARRAY, cfg->msg_cache_size,
|
||||
msgreply_sizefunc, query_info_compare,
|
||||
query_entry_delete, reply_info_delete, NULL);
|
||||
if(!daemon->env->msg_cache) {
|
||||
fatal_exit("malloc failure updating config settings");
|
||||
}
|
||||
}
|
||||
if((daemon->env->rrset_cache = rrset_cache_adjust(
|
||||
daemon->env->rrset_cache, cfg, &daemon->superalloc)) == 0)
|
||||
fatal_exit("malloc failure updating config settings");
|
||||
if((daemon->env->infra_cache = infra_adjust(daemon->env->infra_cache,
|
||||
cfg))==0)
|
||||
fatal_exit("malloc failure updating config settings");
|
||||
daemon_apply_cfg(daemon, cfg);
|
||||
checkrlimits(cfg);
|
||||
}
|
||||
|
||||
#ifdef HAVE_KILL
|
||||
/** Read existing pid from pidfile.
|
||||
* @param file: file name of pid file.
|
||||
* @return: the pid from the file or -1 if none.
|
||||
@@ -233,46 +352,52 @@ writepid (const char* pidfile, pid_t pid)
|
||||
|
||||
/**
|
||||
* check old pid file.
|
||||
* @param cfg: the config settings
|
||||
* @param pidfile: the file name of the pid file.
|
||||
* @param inchroot: if pidfile is inchroot and we can thus expect to
|
||||
* be able to delete it.
|
||||
*/
|
||||
static void
|
||||
checkoldpid(struct config_file* cfg)
|
||||
checkoldpid(char* pidfile, int inchroot)
|
||||
{
|
||||
pid_t old;
|
||||
char* file = cfg->pidfile;
|
||||
if(cfg->chrootdir && cfg->chrootdir[0] &&
|
||||
strncmp(file, cfg->chrootdir, strlen(cfg->chrootdir))==0) {
|
||||
file += strlen(cfg->chrootdir);
|
||||
}
|
||||
if((old = readpid(file)) != -1) {
|
||||
if((old = readpid(pidfile)) != -1) {
|
||||
/* see if it is still alive */
|
||||
if(kill(old, 0) == 0 || errno == EPERM)
|
||||
log_warn("unbound is already running as pid %u.",
|
||||
(unsigned)old);
|
||||
else log_warn("did not exit gracefully last time (%u)",
|
||||
else if(inchroot)
|
||||
log_warn("did not exit gracefully last time (%u)",
|
||||
(unsigned)old);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_KILL */
|
||||
|
||||
/** detach from command line */
|
||||
static void
|
||||
detach(struct config_file* cfg)
|
||||
detach(void)
|
||||
{
|
||||
#if defined(HAVE_DAEMON) && !defined(DEPRECATED_DAEMON)
|
||||
/* use POSIX daemon(3) function */
|
||||
if(daemon(1, 0) != 0)
|
||||
fatal_exit("daemon failed: %s", strerror(errno));
|
||||
#else /* no HAVE_DAEMON */
|
||||
#ifdef HAVE_FORK
|
||||
int fd;
|
||||
/* Take off... */
|
||||
switch (fork()) {
|
||||
case 0:
|
||||
break;
|
||||
case -1:
|
||||
unlink(cfg->pidfile);
|
||||
fatal_exit("fork failed: %s", strerror(errno));
|
||||
default:
|
||||
/* exit interactive session */
|
||||
exit(0);
|
||||
}
|
||||
/* detach */
|
||||
#ifdef HAVE_SETSID
|
||||
if(setsid() == -1)
|
||||
fatal_exit("setsid() failed: %s", strerror(errno));
|
||||
#endif
|
||||
if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
|
||||
(void)dup2(fd, STDIN_FILENO);
|
||||
(void)dup2(fd, STDOUT_FILENO);
|
||||
@@ -280,13 +405,17 @@ detach(struct config_file* cfg)
|
||||
if (fd > 2)
|
||||
(void)close(fd);
|
||||
}
|
||||
#endif /* HAVE_FORK */
|
||||
#endif /* HAVE_DAEMON */
|
||||
}
|
||||
|
||||
/** daemonize, drop user priviliges and chroot if needed */
|
||||
static void
|
||||
do_chroot(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
char** cfgfile)
|
||||
perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
const char** cfgfile)
|
||||
{
|
||||
#ifdef HAVE_GETPWNAM
|
||||
struct passwd *pwd = NULL;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
/* initialize, but not to 0 (root) */
|
||||
@@ -294,15 +423,79 @@ do_chroot(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
memset(&gid, 112, sizeof(gid));
|
||||
log_assert(cfg);
|
||||
|
||||
/* daemonize last to be able to print error to user */
|
||||
if(cfg->username && cfg->username[0]) {
|
||||
struct passwd *pwd;
|
||||
if((pwd = getpwnam(cfg->username)) == NULL)
|
||||
fatal_exit("user '%s' does not exist.", cfg->username);
|
||||
uid = pwd->pw_uid;
|
||||
gid = pwd->pw_gid;
|
||||
endpwent();
|
||||
/* endpwent below, in case we need pwd for setusercontext */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* init syslog (as root) if needed, before daemonize, otherwise
|
||||
* a fork error could not be printed since daemonize closed stderr.*/
|
||||
if(cfg->use_syslog) {
|
||||
log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
|
||||
}
|
||||
/* if using a logfile, we cannot open it because the logfile would
|
||||
* be created with the wrong permissions, we cannot chown it because
|
||||
* we cannot chown system logfiles, so we do not open at all.
|
||||
* So, using a logfile, the user does not see errors unless -d is
|
||||
* given to unbound on the commandline. */
|
||||
|
||||
/* read ssl keys while superuser and outside chroot */
|
||||
if(!(daemon->rc = daemon_remote_create(cfg)))
|
||||
fatal_exit("could not set up remote-control");
|
||||
|
||||
#ifdef HAVE_KILL
|
||||
/* check old pid file before forking */
|
||||
if(cfg->pidfile && cfg->pidfile[0]) {
|
||||
/* calculate position of pidfile */
|
||||
if(cfg->pidfile[0] == '/')
|
||||
daemon->pidfile = strdup(cfg->pidfile);
|
||||
else daemon->pidfile = fname_after_chroot(cfg->pidfile,
|
||||
cfg, 1);
|
||||
if(!daemon->pidfile)
|
||||
fatal_exit("pidfile alloc: out of memory");
|
||||
checkoldpid(daemon->pidfile,
|
||||
/* true if pidfile is inside chrootdir, or nochroot */
|
||||
!(cfg->chrootdir && cfg->chrootdir[0]) ||
|
||||
(cfg->chrootdir && cfg->chrootdir[0] &&
|
||||
strncmp(daemon->pidfile, cfg->chrootdir,
|
||||
strlen(cfg->chrootdir))==0));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* daemonize because pid is needed by the writepid func */
|
||||
if(!debug_mode && cfg->do_daemonize) {
|
||||
detach();
|
||||
}
|
||||
|
||||
/* write new pidfile (while still root, so can be outside chroot) */
|
||||
#ifdef HAVE_KILL
|
||||
if(cfg->pidfile && cfg->pidfile[0]) {
|
||||
writepid(daemon->pidfile, getpid());
|
||||
if(!(cfg->chrootdir && cfg->chrootdir[0]) ||
|
||||
(cfg->chrootdir && cfg->chrootdir[0] &&
|
||||
strncmp(daemon->pidfile, cfg->chrootdir,
|
||||
strlen(cfg->chrootdir))==0)) {
|
||||
/* delete of pidfile could potentially work,
|
||||
* chown to get permissions */
|
||||
if(cfg->username && cfg->username[0]) {
|
||||
if(chown(daemon->pidfile, uid, gid) == -1) {
|
||||
log_err("cannot chown %u.%u %s: %s",
|
||||
(unsigned)uid, (unsigned)gid,
|
||||
daemon->pidfile, strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)daemon;
|
||||
#endif
|
||||
|
||||
/* box into the chroot */
|
||||
#ifdef HAVE_CHROOT
|
||||
if(cfg->chrootdir && cfg->chrootdir[0]) {
|
||||
if(chdir(cfg->chrootdir)) {
|
||||
fatal_exit("unable to chdir to chroot %s: %s",
|
||||
@@ -316,7 +509,25 @@ do_chroot(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
if(strncmp(*cfgfile, cfg->chrootdir,
|
||||
strlen(cfg->chrootdir)) == 0)
|
||||
(*cfgfile) += strlen(cfg->chrootdir);
|
||||
|
||||
/* adjust stored pidfile for chroot */
|
||||
if(daemon->pidfile && daemon->pidfile[0] &&
|
||||
strncmp(daemon->pidfile, cfg->chrootdir,
|
||||
strlen(cfg->chrootdir))==0) {
|
||||
char* old = daemon->pidfile;
|
||||
daemon->pidfile = strdup(old+strlen(cfg->chrootdir));
|
||||
free(old);
|
||||
if(!daemon->pidfile)
|
||||
log_err("out of memory in pidfile adjust");
|
||||
}
|
||||
daemon->chroot = strdup(cfg->chrootdir);
|
||||
if(!daemon->chroot)
|
||||
log_err("out of memory in daemon chroot dir storage");
|
||||
}
|
||||
#else
|
||||
(void)cfgfile;
|
||||
#endif
|
||||
/* change to working directory inside chroot */
|
||||
if(cfg->directory && cfg->directory[0]) {
|
||||
char* dir = cfg->directory;
|
||||
if(cfg->chrootdir && cfg->chrootdir[0] &&
|
||||
@@ -331,35 +542,52 @@ do_chroot(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
verbose(VERB_QUERY, "chdir to %s", dir);
|
||||
}
|
||||
}
|
||||
|
||||
/* drop permissions after chroot, getpwnam, pidfile, syslog done*/
|
||||
#ifdef HAVE_GETPWNAM
|
||||
if(cfg->username && cfg->username[0]) {
|
||||
#ifdef HAVE_SETUSERCONTEXT
|
||||
/* setusercontext does initgroups, setuid, setgid, and
|
||||
* also resource limits from login config, but we
|
||||
* still call setresuid, setresgid to be sure to set all uid*/
|
||||
if(setusercontext(NULL, pwd, uid, LOGIN_SETALL) != 0)
|
||||
log_warn("unable to setusercontext %s: %s",
|
||||
cfg->username, strerror(errno));
|
||||
#else /* !HAVE_SETUSERCONTEXT */
|
||||
# ifdef HAVE_INITGROUPS
|
||||
if(initgroups(cfg->username, gid) != 0)
|
||||
log_warn("unable to initgroups %s: %s",
|
||||
cfg->username, strerror(errno));
|
||||
# endif /* HAVE_INITGROUPS */
|
||||
#endif /* HAVE_SETUSERCONTEXT */
|
||||
endpwent();
|
||||
|
||||
#ifdef HAVE_SETRESGID
|
||||
if(setresgid(gid,gid,gid) != 0)
|
||||
#elif defined(HAVE_SETREGID) && !defined(DARWIN_BROKEN_SETREUID)
|
||||
if(setregid(gid,gid) != 0)
|
||||
#else /* use setgid */
|
||||
if(setgid(gid) != 0)
|
||||
#endif /* HAVE_SETRESGID */
|
||||
fatal_exit("unable to set group id of %s: %s",
|
||||
cfg->username, strerror(errno));
|
||||
#ifdef HAVE_SETRESUID
|
||||
if(setresuid(uid,uid,uid) != 0)
|
||||
#elif defined(HAVE_SETREUID) && !defined(DARWIN_BROKEN_SETREUID)
|
||||
if(setreuid(uid,uid) != 0)
|
||||
#else /* use setuid */
|
||||
if(setuid(uid) != 0)
|
||||
#endif /* HAVE_SETRESUID */
|
||||
fatal_exit("unable to set user id of %s: %s",
|
||||
cfg->username, strerror(errno));
|
||||
verbose(VERB_QUERY, "drop user privileges, run as %s",
|
||||
cfg->username);
|
||||
}
|
||||
/* check old pid file before forking */
|
||||
if(cfg->pidfile && cfg->pidfile[0]) {
|
||||
checkoldpid(cfg);
|
||||
}
|
||||
|
||||
/* init logfile just before fork */
|
||||
log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
|
||||
if(!debug_mode && cfg->do_daemonize) {
|
||||
detach(cfg);
|
||||
}
|
||||
if(cfg->pidfile && cfg->pidfile[0]) {
|
||||
char* pf = cfg->pidfile;
|
||||
if(cfg->chrootdir && cfg->chrootdir[0] &&
|
||||
strncmp(pf, cfg->chrootdir, strlen(cfg->chrootdir))==0)
|
||||
pf += strlen(cfg->chrootdir);
|
||||
writepid(pf, getpid());
|
||||
if(!(daemon->pidfile = strdup(pf)))
|
||||
log_err("pidf: malloc failed");
|
||||
}
|
||||
#endif /* HAVE_GETPWNAM */
|
||||
/* file logging inited after chroot,chdir,setuid is done so that
|
||||
* it would succeed on SIGHUP as well */
|
||||
if(!cfg->use_syslog)
|
||||
log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -370,23 +598,23 @@ do_chroot(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
* @param debug_mode: if set, do not daemonize.
|
||||
*/
|
||||
static void
|
||||
run_daemon(char* cfgfile, int cmdline_verbose, int debug_mode)
|
||||
run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode)
|
||||
{
|
||||
struct config_file* cfg = NULL;
|
||||
struct daemon* daemon = NULL;
|
||||
int done_chroot = 0;
|
||||
int done_setup = 0;
|
||||
|
||||
if(!(daemon = daemon_init()))
|
||||
fatal_exit("alloc failure");
|
||||
while(!daemon->need_to_exit) {
|
||||
if(done_chroot)
|
||||
if(done_setup)
|
||||
verbose(VERB_OPS, "Restart of %s.", PACKAGE_STRING);
|
||||
else verbose(VERB_OPS, "Start of %s.", PACKAGE_STRING);
|
||||
|
||||
/* config stuff */
|
||||
if(!(cfg = config_create()))
|
||||
fatal_exit("Could not alloc config defaults");
|
||||
if(!config_read(cfg, cfgfile)) {
|
||||
if(!config_read(cfg, cfgfile, daemon->chroot)) {
|
||||
if(errno != ENOENT)
|
||||
fatal_exit("Could not read config file: %s",
|
||||
cfgfile);
|
||||
@@ -397,10 +625,14 @@ run_daemon(char* cfgfile, int cmdline_verbose, int debug_mode)
|
||||
/* prepare */
|
||||
if(!daemon_open_shared_ports(daemon))
|
||||
fatal_exit("could not open ports");
|
||||
if(!done_chroot) {
|
||||
do_chroot(daemon, cfg, debug_mode, &cfgfile);
|
||||
done_chroot = 1;
|
||||
} else log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
|
||||
if(!done_setup) {
|
||||
perform_setup(daemon, cfg, debug_mode, &cfgfile);
|
||||
done_setup = 1;
|
||||
} else {
|
||||
/* reopen log after HUP to facilitate log rotation */
|
||||
if(!cfg->use_syslog)
|
||||
log_init(cfg->logfile, 0, cfg->chrootdir);
|
||||
}
|
||||
/* work */
|
||||
daemon_fork(daemon);
|
||||
|
||||
@@ -410,8 +642,17 @@ run_daemon(char* cfgfile, int cmdline_verbose, int debug_mode)
|
||||
config_delete(cfg);
|
||||
}
|
||||
verbose(VERB_ALGO, "Exit cleanup.");
|
||||
if(daemon->pidfile)
|
||||
/* this unlink may not work if the pidfile is located outside
|
||||
* of the chroot/workdir or we no longer have permissions */
|
||||
if(daemon->pidfile) {
|
||||
int fd;
|
||||
/* truncate pidfile */
|
||||
fd = open(daemon->pidfile, O_WRONLY | O_TRUNC, 0644);
|
||||
if(fd != -1)
|
||||
close(fd);
|
||||
/* delete pidfile */
|
||||
unlink(daemon->pidfile);
|
||||
}
|
||||
daemon_delete(daemon);
|
||||
}
|
||||
|
||||
@@ -430,19 +671,28 @@ int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
int c;
|
||||
char* cfgfile = CONFIGFILE;
|
||||
const char* cfgfile = CONFIGFILE;
|
||||
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 */
|
||||
unbound_start_brk = sbrk(0);
|
||||
#endif
|
||||
|
||||
log_init(NULL, 0, NULL);
|
||||
/* parse the options */
|
||||
while( (c=getopt(argc, argv, "c:dhv")) != -1) {
|
||||
while( (c=getopt(argc, argv, "c:dhvw:")) != -1) {
|
||||
switch(c) {
|
||||
case 'c':
|
||||
cfgfile = optarg;
|
||||
#ifdef UB_ON_WINDOWS
|
||||
cmdline_cfg = 1;
|
||||
#endif
|
||||
break;
|
||||
case 'v':
|
||||
cmdline_verbose ++;
|
||||
@@ -451,6 +701,9 @@ main(int argc, char* argv[])
|
||||
case 'd':
|
||||
debug_mode = 1;
|
||||
break;
|
||||
case 'w':
|
||||
winopt = optarg;
|
||||
break;
|
||||
case '?':
|
||||
case 'h':
|
||||
default:
|
||||
@@ -461,6 +714,15 @@ main(int argc, char* argv[])
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if(winopt) {
|
||||
#ifdef UB_ON_WINDOWS
|
||||
wsvc_command_option(winopt, cfgfile, cmdline_verbose,
|
||||
cmdline_cfg);
|
||||
#else
|
||||
fatal_exit("option not supported");
|
||||
#endif
|
||||
}
|
||||
|
||||
if(argc != 0) {
|
||||
usage();
|
||||
return 1;
|
||||
|
||||
+315
-167
@@ -40,11 +40,13 @@
|
||||
* pending requests.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ldns/wire2host.h"
|
||||
#include "util/log.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/random.h"
|
||||
#include "daemon/worker.h"
|
||||
#include "daemon/daemon.h"
|
||||
#include "daemon/remote.h"
|
||||
#include "daemon/acl_list.h"
|
||||
#include "util/netevent.h"
|
||||
#include "util/config_file.h"
|
||||
@@ -63,16 +65,36 @@
|
||||
#include "util/data/msgencode.h"
|
||||
#include "util/data/dname.h"
|
||||
#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>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#ifdef UB_ON_WINDOWS
|
||||
#include "winrc/win_svc.h"
|
||||
#endif
|
||||
|
||||
/** 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
|
||||
@@ -102,6 +124,7 @@ debug_memleak(size_t accounted, size_t heap,
|
||||
static void
|
||||
debug_total_mem(size_t calctotal)
|
||||
{
|
||||
#ifdef HAVE_SBRK
|
||||
extern void* unbound_start_brk;
|
||||
extern size_t unbound_mem_alloc, unbound_mem_freed;
|
||||
void* cur = sbrk(0);
|
||||
@@ -111,11 +134,14 @@ debug_total_mem(size_t calctotal)
|
||||
(unsigned)unbound_mem_alloc, (unsigned)unbound_mem_freed);
|
||||
debug_memleak(calctotal, (size_t)total,
|
||||
unbound_mem_alloc, unbound_mem_freed);
|
||||
#else
|
||||
(void)calctotal;
|
||||
#endif /* HAVE_SBRK */
|
||||
}
|
||||
#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))
|
||||
{
|
||||
@@ -150,7 +176,10 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
|
||||
+ sizeof(worker->rndstate)
|
||||
+ regional_get_mem(worker->scratchpad)
|
||||
+ sizeof(*worker->env.scratch_buffer)
|
||||
+ ldns_buffer_capacity(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);
|
||||
}
|
||||
@@ -184,17 +213,12 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
|
||||
}
|
||||
|
||||
void
|
||||
worker_send_cmd(struct worker* worker, ldns_buffer* buffer,
|
||||
enum worker_commands cmd)
|
||||
worker_send_cmd(struct worker* worker, enum worker_commands cmd)
|
||||
{
|
||||
ldns_buffer_clear(buffer);
|
||||
/* like DNS message, length data */
|
||||
ldns_buffer_write_u16(buffer, sizeof(uint32_t));
|
||||
ldns_buffer_write_u32(buffer, (uint32_t)cmd);
|
||||
ldns_buffer_flip(buffer);
|
||||
if(!write_socket(worker->cmd_send_fd, ldns_buffer_begin(buffer),
|
||||
ldns_buffer_limit(buffer)))
|
||||
log_err("write socket: %s", strerror(errno));
|
||||
uint32_t c = (uint32_t)htonl(cmd);
|
||||
if(!tube_write_msg(worker->cmd, (uint8_t*)&c, sizeof(c), 0)) {
|
||||
log_err("worker send cmd %d failed", (int)cmd);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
@@ -208,7 +232,7 @@ worker_handle_reply(struct comm_point* c, void* arg, int error,
|
||||
e.qsent = NULL;
|
||||
|
||||
if(error != 0) {
|
||||
mesh_report_reply(worker->env.mesh, &e, 0, reply_info);
|
||||
mesh_report_reply(worker->env.mesh, &e, reply_info, error);
|
||||
worker_mem_report(worker, NULL);
|
||||
return 0;
|
||||
}
|
||||
@@ -219,11 +243,12 @@ worker_handle_reply(struct comm_point* c, void* arg, int error,
|
||||
|| LDNS_QDCOUNT(ldns_buffer_begin(c->buffer)) > 1) {
|
||||
/* error becomes timeout for the module as if this reply
|
||||
* never arrived. */
|
||||
mesh_report_reply(worker->env.mesh, &e, 0, reply_info);
|
||||
mesh_report_reply(worker->env.mesh, &e, reply_info,
|
||||
NETEVENT_TIMEOUT);
|
||||
worker_mem_report(worker, NULL);
|
||||
return 0;
|
||||
}
|
||||
mesh_report_reply(worker->env.mesh, &e, 1, reply_info);
|
||||
mesh_report_reply(worker->env.mesh, &e, reply_info, NETEVENT_NOERROR);
|
||||
worker_mem_report(worker, NULL);
|
||||
return 0;
|
||||
}
|
||||
@@ -238,7 +263,7 @@ worker_handle_service_reply(struct comm_point* c, void* arg, int error,
|
||||
|
||||
verbose(VERB_ALGO, "worker svcd callback for qstate %p", e->qstate);
|
||||
if(error != 0) {
|
||||
mesh_report_reply(worker->env.mesh, e, 0, reply_info);
|
||||
mesh_report_reply(worker->env.mesh, e, reply_info, error);
|
||||
worker_mem_report(worker, sq);
|
||||
return 0;
|
||||
}
|
||||
@@ -250,18 +275,20 @@ worker_handle_service_reply(struct comm_point* c, void* arg, int error,
|
||||
/* error becomes timeout for the module as if this reply
|
||||
* never arrived. */
|
||||
verbose(VERB_ALGO, "worker: bad reply handled as timeout");
|
||||
mesh_report_reply(worker->env.mesh, e, 0, reply_info);
|
||||
mesh_report_reply(worker->env.mesh, e, reply_info,
|
||||
NETEVENT_TIMEOUT);
|
||||
worker_mem_report(worker, sq);
|
||||
return 0;
|
||||
}
|
||||
mesh_report_reply(worker->env.mesh, e, 1, reply_info);
|
||||
mesh_report_reply(worker->env.mesh, e, reply_info, NETEVENT_NOERROR);
|
||||
worker_mem_report(worker, sq);
|
||||
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)
|
||||
@@ -312,33 +339,45 @@ worker_check_request(ldns_buffer* pkt, struct worker* worker)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
worker_handle_control_cmd(struct comm_point* c, void* arg, int error,
|
||||
struct comm_reply* ATTR_UNUSED(reply_info))
|
||||
void
|
||||
worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), uint8_t* msg,
|
||||
size_t len, int error, void* arg)
|
||||
{
|
||||
struct worker* worker = (struct worker*)arg;
|
||||
enum worker_commands cmd;
|
||||
if(error != NETEVENT_NOERROR) {
|
||||
free(msg);
|
||||
if(error == NETEVENT_CLOSED)
|
||||
comm_base_exit(worker->base);
|
||||
else log_info("control event: %d", error);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
if(ldns_buffer_limit(c->buffer) != sizeof(uint32_t)) {
|
||||
fatal_exit("bad control msg length %d",
|
||||
(int)ldns_buffer_limit(c->buffer));
|
||||
if(len != sizeof(uint32_t)) {
|
||||
fatal_exit("bad control msg length %d", (int)len);
|
||||
}
|
||||
cmd = ldns_buffer_read_u32(c->buffer);
|
||||
cmd = ldns_read_uint32(msg);
|
||||
free(msg);
|
||||
switch(cmd) {
|
||||
case worker_cmd_quit:
|
||||
verbose(VERB_ALGO, "got control cmd quit");
|
||||
comm_base_exit(worker->base);
|
||||
break;
|
||||
case worker_cmd_stats:
|
||||
verbose(VERB_ALGO, "got control cmd stats");
|
||||
server_stats_reply(worker, 1);
|
||||
break;
|
||||
case worker_cmd_stats_noreset:
|
||||
verbose(VERB_ALGO, "got control cmd stats_noreset");
|
||||
server_stats_reply(worker, 0);
|
||||
break;
|
||||
case worker_cmd_remote:
|
||||
verbose(VERB_ALGO, "got control cmd remote");
|
||||
daemon_remote_exec(worker);
|
||||
break;
|
||||
default:
|
||||
log_err("bad command %d", (int)cmd);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** check if a delegation is secure */
|
||||
@@ -434,6 +473,10 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
&msg->qinfo, id, flags, edns);
|
||||
regional_free_all(worker->scratchpad);
|
||||
if(worker->stats.extended) {
|
||||
worker->stats.ans_bogus++;
|
||||
worker->stats.ans_rcode[LDNS_RCODE_SERVFAIL]++;
|
||||
}
|
||||
return 1;
|
||||
case sec_status_secure:
|
||||
/* all rrsets are secure */
|
||||
@@ -463,42 +506,9 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
&msg->qinfo, id, flags, edns);
|
||||
}
|
||||
regional_free_all(worker->scratchpad);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** check cname chain in cache reply */
|
||||
static int
|
||||
check_cache_chain(struct reply_info* rep) {
|
||||
/* check only answer section rrs for matching cname chain.
|
||||
* the cache may return changed rdata, but owner names are untouched.*/
|
||||
size_t i;
|
||||
uint8_t* sname = rep->rrsets[0]->rk.dname;
|
||||
size_t snamelen = rep->rrsets[0]->rk.dname_len;
|
||||
for(i=0; i<rep->an_numrrsets; i++) {
|
||||
uint16_t t = ntohs(rep->rrsets[i]->rk.type);
|
||||
if(t == LDNS_RR_TYPE_DNAME)
|
||||
continue; /* skip dnames; note TTL 0 not cached */
|
||||
/* verify that owner matches current sname */
|
||||
if(query_dname_compare(sname, rep->rrsets[i]->rk.dname) != 0){
|
||||
/* cname chain broken */
|
||||
return 0;
|
||||
}
|
||||
/* if this is a cname; move on */
|
||||
if(t == LDNS_RR_TYPE_CNAME) {
|
||||
get_cname_target(rep->rrsets[i], &sname, &snamelen);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** check security status in cache reply */
|
||||
static int
|
||||
all_rrsets_secure(struct reply_info* rep) {
|
||||
size_t i;
|
||||
for(i=0; i<rep->rrset_count; i++) {
|
||||
if( ((struct packed_rrset_data*)rep->rrsets[i]->entry.data)
|
||||
->security != sec_status_secure )
|
||||
return 0;
|
||||
if(worker->stats.extended) {
|
||||
if(secure) worker->stats.ans_secure++;
|
||||
server_stats_insrcode(&worker->stats, repinfo->c->buffer);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -514,7 +524,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
int secure;
|
||||
int must_validate = !(flags&BIT_CD) && worker->env.need_to_validate;
|
||||
/* see if it is possible */
|
||||
if(rep->ttl <= timenow) {
|
||||
if(rep->ttl < timenow) {
|
||||
/* the rrsets may have been updated in the meantime.
|
||||
* we will refetch the message format from the
|
||||
* authoritative server
|
||||
@@ -528,7 +538,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
if(rep->an_numrrsets > 0 && (rep->rrsets[0]->rk.type ==
|
||||
htons(LDNS_RR_TYPE_CNAME) || rep->rrsets[0]->rk.type ==
|
||||
htons(LDNS_RR_TYPE_DNAME))) {
|
||||
if(!check_cache_chain(rep)) {
|
||||
if(!reply_check_cname_chain(rep)) {
|
||||
/* cname chain invalid, redo iterator steps */
|
||||
verbose(VERB_ALGO, "Cache reply: cname chain broken");
|
||||
bail_out:
|
||||
@@ -550,13 +560,17 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
rrset_array_unlock_touch(worker->env.rrset_cache,
|
||||
worker->scratchpad, rep->ref, rep->rrset_count);
|
||||
regional_free_all(worker->scratchpad);
|
||||
if(worker->stats.extended) {
|
||||
worker->stats.ans_bogus ++;
|
||||
worker->stats.ans_rcode[LDNS_RCODE_SERVFAIL] ++;
|
||||
}
|
||||
return 1;
|
||||
} else if( rep->security == sec_status_unchecked && must_validate) {
|
||||
verbose(VERB_ALGO, "Cache reply: unchecked entry needs "
|
||||
"validation");
|
||||
goto bail_out; /* need to validate cache entry first */
|
||||
} else if(rep->security == sec_status_secure) {
|
||||
if(all_rrsets_secure(rep))
|
||||
if(reply_all_rrsets_secure(rep))
|
||||
secure = 1;
|
||||
else {
|
||||
if(must_validate) {
|
||||
@@ -583,10 +597,32 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
rrset_array_unlock_touch(worker->env.rrset_cache, worker->scratchpad,
|
||||
rep->ref, rep->rrset_count);
|
||||
regional_free_all(worker->scratchpad);
|
||||
if(worker->stats.extended) {
|
||||
if(secure) worker->stats.ans_secure++;
|
||||
server_stats_insrcode(&worker->stats, repinfo->c->buffer);
|
||||
}
|
||||
/* go and return this buffer to the client */
|
||||
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
|
||||
@@ -697,6 +733,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
repinfo->addrlen);
|
||||
if(acl == acl_deny) {
|
||||
comm_point_drop_reply(repinfo);
|
||||
if(worker->stats.extended)
|
||||
worker->stats.unwanted_queries++;
|
||||
return 0;
|
||||
} else if(acl == acl_refuse) {
|
||||
ldns_buffer_set_limit(c->buffer, LDNS_HEADER_SIZE);
|
||||
@@ -708,10 +746,13 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
log_addr(VERB_ALGO, "refused query from",
|
||||
&repinfo->addr, repinfo->addrlen);
|
||||
log_buf(VERB_ALGO, "refuse", c->buffer);
|
||||
if(worker->stats.extended)
|
||||
worker->stats.unwanted_queries++;
|
||||
return 1;
|
||||
}
|
||||
if((ret=worker_check_request(c->buffer, worker)) != 0) {
|
||||
verbose(VERB_ALGO, "worker check request: bad query.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
if(ret != -1) {
|
||||
LDNS_QR_SET(ldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), ret);
|
||||
@@ -724,23 +765,34 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
/* see if query is in the cache */
|
||||
if(!query_info_parse(&qinfo, c->buffer)) {
|
||||
verbose(VERB_ALGO, "worker parse request: formerror.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
ldns_buffer_rewind(c->buffer);
|
||||
LDNS_QR_SET(ldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(ldns_buffer_begin(c->buffer),
|
||||
LDNS_RCODE_FORMERR);
|
||||
server_stats_insrcode(&worker->stats, c->buffer);
|
||||
return 1;
|
||||
}
|
||||
if(qinfo.qtype == LDNS_RR_TYPE_AXFR ||
|
||||
qinfo.qtype == LDNS_RR_TYPE_IXFR) {
|
||||
verbose(VERB_ALGO, "worker request: refused zone transfer.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
LDNS_QR_SET(ldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(ldns_buffer_begin(c->buffer),
|
||||
LDNS_RCODE_REFUSED);
|
||||
if(worker->stats.extended) {
|
||||
worker->stats.qtype[qinfo.qtype]++;
|
||||
server_stats_insrcode(&worker->stats, c->buffer);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if((ret=parse_edns_from_pkt(c->buffer, &edns)) != 0) {
|
||||
verbose(VERB_ALGO, "worker parse edns: formerror.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
ldns_buffer_rewind(c->buffer);
|
||||
LDNS_QR_SET(ldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), ret);
|
||||
server_stats_insrcode(&worker->stats, c->buffer);
|
||||
return 1;
|
||||
}
|
||||
if(edns.edns_present && edns.edns_version != 0) {
|
||||
@@ -749,6 +801,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns.bits &= EDNS_DO;
|
||||
verbose(VERB_ALGO, "query with bad edns version.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
error_encode(c->buffer, EDNS_RCODE_BADVERS&0xf, &qinfo,
|
||||
*(uint16_t*)ldns_buffer_begin(c->buffer),
|
||||
ldns_buffer_read_u16_at(c->buffer, 2), NULL);
|
||||
@@ -759,10 +812,12 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
worker->daemon->cfg->harden_short_bufsize) {
|
||||
verbose(VERB_QUERY, "worker request: EDNS bufsize %d ignored",
|
||||
(int)edns.udp_size);
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
edns.udp_size = NORMAL_UDP_SIZE;
|
||||
}
|
||||
if(edns.edns_present && edns.udp_size < LDNS_HEADER_SIZE) {
|
||||
verbose(VERB_ALGO, "worker request: edns is too small.");
|
||||
log_addr(VERB_CLIENT, "from", &repinfo->addr, repinfo->addrlen);
|
||||
LDNS_QR_SET(ldns_buffer_begin(c->buffer));
|
||||
LDNS_TC_SET(ldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(ldns_buffer_begin(c->buffer),
|
||||
@@ -773,15 +828,39 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
ldns_buffer_flip(c->buffer);
|
||||
return 1;
|
||||
}
|
||||
if(worker->stats.extended)
|
||||
server_stats_insquery(&worker->stats, c, qinfo.qtype,
|
||||
qinfo.qclass, &edns, repinfo);
|
||||
if(c->type != comm_udp)
|
||||
edns.udp_size = 65535; /* max size for TCP replies */
|
||||
if(qinfo.qclass == LDNS_RR_CLASS_CH && answer_chaos(worker, &qinfo,
|
||||
&edns, c->buffer)) {
|
||||
server_stats_insrcode(&worker->stats, c->buffer);
|
||||
return 1;
|
||||
}
|
||||
if(local_zones_answer(worker->daemon->local_zones, &qinfo, &edns,
|
||||
c->buffer, worker->scratchpad)) {
|
||||
return (ldns_buffer_limit(c->buffer) != 0);
|
||||
regional_free_all(worker->scratchpad);
|
||||
if(ldns_buffer_limit(c->buffer) == 0) {
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
server_stats_insrcode(&worker->stats, c->buffer);
|
||||
return 1;
|
||||
}
|
||||
if(!(LDNS_RD_WIRE(ldns_buffer_begin(c->buffer))) &&
|
||||
acl != acl_allow_snoop ) {
|
||||
ldns_buffer_set_limit(c->buffer, LDNS_HEADER_SIZE);
|
||||
ldns_buffer_write_at(c->buffer, 4,
|
||||
(uint8_t*)"\0\0\0\0\0\0\0\0", 8);
|
||||
LDNS_QR_SET(ldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(ldns_buffer_begin(c->buffer),
|
||||
LDNS_RCODE_REFUSED);
|
||||
ldns_buffer_flip(c->buffer);
|
||||
server_stats_insrcode(&worker->stats, c->buffer);
|
||||
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
|
||||
&repinfo->addr, repinfo->addrlen);
|
||||
return 1;
|
||||
}
|
||||
h = query_info_hash(&qinfo);
|
||||
if((e=slabhash_lookup(worker->env.msg_cache, h, &qinfo, 0))) {
|
||||
@@ -791,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;
|
||||
}
|
||||
@@ -810,20 +900,15 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
ldns_buffer_rewind(c->buffer);
|
||||
server_stats_querymiss(&worker->stats, worker);
|
||||
|
||||
/* grab a work request structure for this new request */
|
||||
if(worker->env.mesh->all.count > worker->request_size) {
|
||||
verbose(VERB_ALGO, "Too many requests active. "
|
||||
"dropping incoming query.");
|
||||
worker->stats.num_query_list_exceeded++;
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
} else if(worker->env.mesh->num_reply_addrs>worker->request_size*16) {
|
||||
verbose(VERB_ALGO, "Too many requests queued. "
|
||||
"dropping incoming query.");
|
||||
worker->stats.num_query_list_exceeded++;
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
if(verbosity >= VERB_CLIENT) {
|
||||
if(c->type == comm_udp)
|
||||
log_addr(VERB_CLIENT, "udp request from",
|
||||
&repinfo->addr, repinfo->addrlen);
|
||||
else log_addr(VERB_CLIENT, "tcp request from",
|
||||
&repinfo->addr, repinfo->addrlen);
|
||||
}
|
||||
|
||||
/* grab a work request structure for this new request */
|
||||
mesh_new_client(worker->env.mesh, &qinfo,
|
||||
ldns_buffer_read_u16_at(c->buffer, 2),
|
||||
&edns, repinfo, *(uint16_t*)ldns_buffer_begin(c->buffer));
|
||||
@@ -840,20 +925,24 @@ worker_sighandler(int sig, void* arg)
|
||||
* in the cause for unbound to exit */
|
||||
struct worker* worker = (struct worker*)arg;
|
||||
switch(sig) {
|
||||
#ifdef SIGHUP
|
||||
case SIGHUP:
|
||||
verbose(VERB_QUERY, "caught signal SIGHUP");
|
||||
comm_base_exit(worker->base);
|
||||
break;
|
||||
#endif
|
||||
case SIGINT:
|
||||
verbose(VERB_QUERY, "caught signal SIGINT");
|
||||
worker->need_to_exit = 1;
|
||||
comm_base_exit(worker->base);
|
||||
break;
|
||||
#ifdef SIGQUIT
|
||||
case SIGQUIT:
|
||||
verbose(VERB_QUERY, "caught signal SIGQUIT");
|
||||
worker->need_to_exit = 1;
|
||||
comm_base_exit(worker->base);
|
||||
break;
|
||||
#endif
|
||||
case SIGTERM:
|
||||
verbose(VERB_QUERY, "caught signal SIGTERM");
|
||||
worker->need_to_exit = 1;
|
||||
@@ -871,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);
|
||||
}
|
||||
}
|
||||
@@ -880,20 +971,32 @@ worker_restart_timer(struct worker* worker)
|
||||
void worker_stat_timer_cb(void* arg)
|
||||
{
|
||||
struct worker* worker = (struct worker*)arg;
|
||||
server_stats_log(&worker->stats, worker->thread_num);
|
||||
server_stats_log(&worker->stats, worker, worker->thread_num);
|
||||
mesh_stats(worker->env.mesh, "mesh has");
|
||||
worker_mem_report(worker, NULL);
|
||||
if(!worker->daemon->cfg->stat_cumulative) {
|
||||
server_stats_init(&worker->stats);
|
||||
mesh_stats_clear(worker->env.mesh);
|
||||
worker_stats_clear(worker);
|
||||
}
|
||||
/* start next timer */
|
||||
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)
|
||||
@@ -906,25 +1009,24 @@ worker_create(struct daemon* daemon, int id, int* ports, int n)
|
||||
}
|
||||
worker->daemon = daemon;
|
||||
worker->thread_num = id;
|
||||
worker->cmd_send_fd = -1;
|
||||
worker->cmd_recv_fd = -1;
|
||||
if(id != 0) {
|
||||
int sv[2];
|
||||
/* create socketpair to communicate with worker */
|
||||
if(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
|
||||
free(worker);
|
||||
log_err("socketpair: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
if(!fd_set_nonblock(sv[0]) || !fd_set_nonblock(sv[1])) {
|
||||
close(sv[0]);
|
||||
close(sv[1]);
|
||||
free(worker);
|
||||
return NULL;
|
||||
}
|
||||
worker->cmd_send_fd = sv[0];
|
||||
worker->cmd_recv_fd = sv[1];
|
||||
if(!(worker->cmd = tube_create())) {
|
||||
free(worker->ports);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -932,44 +1034,50 @@ 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();
|
||||
worker->base = comm_base_create(do_sigs);
|
||||
if(!worker->base) {
|
||||
log_err("could not create event handling base");
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
if(do_sigs) {
|
||||
#ifdef SIGHUP
|
||||
ub_thread_sig_unblock(SIGHUP);
|
||||
#endif
|
||||
ub_thread_sig_unblock(SIGINT);
|
||||
#ifdef SIGQUIT
|
||||
ub_thread_sig_unblock(SIGQUIT);
|
||||
#endif
|
||||
ub_thread_sig_unblock(SIGTERM);
|
||||
#ifndef LIBEVENT_SIGNAL_PROBLEM
|
||||
worker->comsig = comm_signal_create(worker->base,
|
||||
worker_sighandler, worker);
|
||||
if(!worker->comsig || !comm_signal_bind(worker->comsig, SIGHUP)
|
||||
|| !comm_signal_bind(worker->comsig, SIGINT)
|
||||
if(!worker->comsig
|
||||
#ifdef SIGHUP
|
||||
|| !comm_signal_bind(worker->comsig, SIGHUP)
|
||||
#endif
|
||||
#ifdef SIGQUIT
|
||||
|| !comm_signal_bind(worker->comsig, SIGQUIT)
|
||||
#endif
|
||||
|| !comm_signal_bind(worker->comsig, SIGTERM)
|
||||
|| !comm_signal_bind(worker->comsig, SIGQUIT)) {
|
||||
|| !comm_signal_bind(worker->comsig, SIGINT)) {
|
||||
log_err("could not create signal handlers");
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
#endif /* LIBEVENT_SIGNAL_PROBLEM */
|
||||
if(!daemon_remote_open_accept(worker->daemon->rc,
|
||||
worker->daemon->rc_ports, worker)) {
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
#ifdef UB_ON_WINDOWS
|
||||
wsvc_setup_worker(worker);
|
||||
#endif /* UB_ON_WINDOWS */
|
||||
} else { /* !do_sigs */
|
||||
worker->comsig = 0;
|
||||
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);
|
||||
@@ -983,21 +1091,20 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
cfg->out_ifs, cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6,
|
||||
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->use_caps_bits_for_id, worker->ports, worker->numports,
|
||||
cfg->unwanted_threshold, &worker_alloc_cleanup, worker,
|
||||
cfg->do_udp);
|
||||
if(!worker->back) {
|
||||
log_err("could not create outgoing sockets");
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
if(worker->thread_num != 0) {
|
||||
/* start listening to commands */
|
||||
if(!(worker->cmd_com=comm_point_create_local(worker->base,
|
||||
worker->cmd_recv_fd, cfg->msg_buffer_size,
|
||||
worker_handle_control_cmd, worker))) {
|
||||
log_err("could not create control compt.");
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
/* start listening to commands */
|
||||
if(!tube_setup_bg_listen(worker->cmd, worker->base,
|
||||
&worker_handle_control_cmd, worker)) {
|
||||
log_err("could not create control compt.");
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
worker->stat_timer = comm_timer_create(worker->base,
|
||||
worker_stat_timer_cb, worker);
|
||||
@@ -1013,9 +1120,8 @@ 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);
|
||||
server_stats_init(&worker->stats, cfg);
|
||||
alloc_init(&worker->alloc, &worker->daemon->superalloc,
|
||||
worker->thread_num);
|
||||
alloc_set_id_cleanup(&worker->alloc, &worker_alloc_cleanup, worker);
|
||||
@@ -1024,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;
|
||||
@@ -1035,6 +1140,30 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
worker->env.kill_sub = &mesh_state_delete;
|
||||
worker->env.detect_cycle = &mesh_detect_cycle;
|
||||
worker->env.scratch_buffer = ldns_buffer_new(cfg->msg_buffer_size);
|
||||
if(!(worker->env.fwds = forwards_create()) ||
|
||||
!forwards_apply_cfg(worker->env.fwds, cfg)) {
|
||||
log_err("Could not set forward zones");
|
||||
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;
|
||||
@@ -1061,48 +1190,34 @@ worker_delete(struct worker* worker)
|
||||
if(!worker)
|
||||
return;
|
||||
if(worker->env.mesh && verbosity >= VERB_OPS) {
|
||||
server_stats_log(&worker->stats, worker->thread_num);
|
||||
server_stats_log(&worker->stats, worker, worker->thread_num);
|
||||
mesh_stats(worker->env.mesh, "mesh has");
|
||||
worker_mem_report(worker, NULL);
|
||||
}
|
||||
outside_network_quit_prepare(worker->back);
|
||||
mesh_delete(worker->env.mesh);
|
||||
ldns_buffer_free(worker->env.scratch_buffer);
|
||||
forwards_delete(worker->env.fwds);
|
||||
listen_delete(worker->front);
|
||||
outside_network_delete(worker->back);
|
||||
comm_signal_delete(worker->comsig);
|
||||
comm_point_delete(worker->cmd_com);
|
||||
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)
|
||||
if(worker->thread_num == 0) {
|
||||
log_set_time(NULL);
|
||||
#ifdef UB_ON_WINDOWS
|
||||
wsvc_desetup_worker(worker);
|
||||
#endif /* UB_ON_WINDOWS */
|
||||
}
|
||||
comm_base_delete(worker->base);
|
||||
ub_randfree(worker->rndstate);
|
||||
/* close fds after deleting commpoints, to be sure.
|
||||
Also epoll does not like closing fd before event_del */
|
||||
if(worker->cmd_send_fd != -1)
|
||||
close(worker->cmd_send_fd);
|
||||
worker->cmd_send_fd = -1;
|
||||
if(worker->cmd_recv_fd != -1)
|
||||
close(worker->cmd_recv_fd);
|
||||
worker->cmd_recv_fd = -1;
|
||||
alloc_clear(&worker->alloc);
|
||||
regional_destroy(worker->scratchpad);
|
||||
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)
|
||||
@@ -1116,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)
|
||||
{
|
||||
@@ -1127,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;
|
||||
}
|
||||
@@ -1144,20 +1259,19 @@ worker_alloc_cleanup(void* arg)
|
||||
slabhash_clear(worker->env.msg_cache);
|
||||
}
|
||||
|
||||
/* --- fake callbacks for fptr_wlist to work --- */
|
||||
int libworker_send_packet(ldns_buffer* ATTR_UNUSED(pkt),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen), int ATTR_UNUSED(timeout),
|
||||
struct module_qstate* ATTR_UNUSED(q), int ATTR_UNUSED(use_tcp))
|
||||
void worker_stats_clear(struct worker* worker)
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
server_stats_init(&worker->stats, worker->env.cfg);
|
||||
mesh_stats_clear(worker->env.mesh);
|
||||
worker->back->unwanted_replies = 0;
|
||||
}
|
||||
|
||||
/* --- fake callbacks for fptr_wlist to work --- */
|
||||
struct outbound_entry* libworker_send_query(uint8_t* ATTR_UNUSED(qname),
|
||||
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
|
||||
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
|
||||
int ATTR_UNUSED(dnssec), struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen), struct module_qstate* ATTR_UNUSED(q))
|
||||
{
|
||||
log_assert(0);
|
||||
@@ -1180,8 +1294,42 @@ int libworker_handle_service_reply(struct comm_point* ATTR_UNUSED(c),
|
||||
return 0;
|
||||
}
|
||||
|
||||
void libworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube),
|
||||
uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len),
|
||||
int ATTR_UNUSED(error), void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void libworker_fg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
|
||||
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),
|
||||
char* ATTR_UNUSED(why_bogus))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int order_lock_cmp(const void* ATTR_UNUSED(e1), const void* ATTR_UNUSED(e2))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+32
-34
@@ -43,7 +43,6 @@
|
||||
#ifndef DAEMON_WORKER_H
|
||||
#define DAEMON_WORKER_H
|
||||
|
||||
#include "config.h"
|
||||
#include "util/netevent.h"
|
||||
#include "util/locks.h"
|
||||
#include "util/alloc.h"
|
||||
@@ -58,11 +57,19 @@ struct daemon;
|
||||
struct listen_port;
|
||||
struct ub_randstate;
|
||||
struct regional;
|
||||
struct tube;
|
||||
struct daemon_remote;
|
||||
|
||||
/** worker commands */
|
||||
enum worker_commands {
|
||||
/** make the worker quit */
|
||||
worker_cmd_quit
|
||||
worker_cmd_quit,
|
||||
/** obtain statistics */
|
||||
worker_cmd_stats,
|
||||
/** obtain statistics without statsclear */
|
||||
worker_cmd_stats_noreset,
|
||||
/** execute remote control command */
|
||||
worker_cmd_remote
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -76,10 +83,8 @@ struct worker {
|
||||
struct daemon* daemon;
|
||||
/** thread id */
|
||||
ub_thread_t thr_id;
|
||||
/** fd 0 of socketpair, write commands for worker to this one */
|
||||
int cmd_send_fd;
|
||||
/** fd 1 of socketpair, worker listens on this one */
|
||||
int cmd_recv_fd;
|
||||
/** pipe, for commands for this worker */
|
||||
struct tube* cmd;
|
||||
/** the event base this worker works with */
|
||||
struct comm_base* base;
|
||||
/** the frontside listening interface where request events come in */
|
||||
@@ -97,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) */
|
||||
@@ -151,11 +153,9 @@ void worker_delete(struct worker* worker);
|
||||
/**
|
||||
* Send a command to a worker. Uses blocking writes.
|
||||
* @param worker: worker to send command to.
|
||||
* @param buffer: an empty buffer to use.
|
||||
* @param cmd: command to send.
|
||||
*/
|
||||
void worker_send_cmd(struct worker* worker, ldns_buffer* buffer,
|
||||
enum worker_commands cmd);
|
||||
void worker_send_cmd(struct worker* worker, enum worker_commands cmd);
|
||||
|
||||
/**
|
||||
* Worker signal handler function. User argument is the worker itself.
|
||||
@@ -164,20 +164,6 @@ void worker_send_cmd(struct worker* worker, ldns_buffer* buffer,
|
||||
*/
|
||||
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)
|
||||
@@ -186,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.
|
||||
@@ -194,18 +181,20 @@ 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);
|
||||
|
||||
/**
|
||||
* process control messages from the main thread.
|
||||
* @param c: comm point to read from.
|
||||
* @param arg: worker.
|
||||
* @param error: error status of comm point.
|
||||
* @param reply_info: not used.
|
||||
* process control messages from the main thread. Frees the control
|
||||
* command message.
|
||||
* @param tube: tube control message came on.
|
||||
* @param msg: message contents. Is freed.
|
||||
* @param len: length of message.
|
||||
* @param error: if error (NETEVENT_*) happened.
|
||||
* @param arg: user argument
|
||||
*/
|
||||
int worker_handle_control_cmd(struct comm_point* c, void* arg, int error,
|
||||
struct comm_reply* reply_info);
|
||||
void worker_handle_control_cmd(struct tube* tube, uint8_t* msg, size_t len,
|
||||
int error, void* arg);
|
||||
|
||||
/** handles callbacks from listening event interface */
|
||||
int worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
@@ -222,7 +211,16 @@ int worker_handle_service_reply(struct comm_point* c, void* arg, int error,
|
||||
/** cleanup the cache to remove all rrset IDs from it, arg is worker */
|
||||
void worker_alloc_cleanup(void* arg);
|
||||
|
||||
/**
|
||||
* Init worker stats - includes server_stats_init, outside network and mesh.
|
||||
* @param worker: the worker to init
|
||||
*/
|
||||
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 */
|
||||
|
||||
+13
-5
@@ -1,12 +1,20 @@
|
||||
Unbound was developed at NLnet Labs by Wouter Wijngaards.
|
||||
|
||||
Unbound was devised by Bill Manning, David Blacka, and Matt Larson
|
||||
from the University of California and from Verisign. The Java prototype
|
||||
was made in further cooperation with Geoff Sisson and Roy Arends from Nominet.
|
||||
Unbound was architected in January of 2004 by Jakob Schlyter of Kirei
|
||||
and Roy Arends of Nominet. VeriSign and EP.Net funded development of
|
||||
the prototype, which was built by David Blacka and Matt Larson of VeriSign.
|
||||
Late in 2006, NLnet Labs joined the effort, writing an implementation in C
|
||||
based on the existing prototype and using experience NLnet Labs gained
|
||||
during the development of NSD, an authoritative DNS server.
|
||||
|
||||
At NLnet Labs, Jelte Jansen and Mark Santcroos reviewed the unbound C sources.
|
||||
At NLnet Labs, Jelte Jansen, Mark Santcroos and Matthijs Mekking
|
||||
reviewed the unbound C sources.
|
||||
|
||||
Jakob Schlyter - for advice on secure settings, random numbers and blacklists.
|
||||
|
||||
Ondřej Surý - running coverity analysis tool on 0.9 dev version.
|
||||
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.
|
||||
|
||||
+2213
File diff suppressed because it is too large
Load Diff
+77
-10
@@ -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.
|
||||
@@ -43,24 +49,51 @@ This software is under BSD license, see LICENSE for details.
|
||||
The server periodically checks if the amount of memory used fits with
|
||||
the amount of memory it thinks it should be using, and reports
|
||||
memory usage in detail.
|
||||
* --with-conf-file=filename
|
||||
Set default location of config file,
|
||||
the default is /usr/local/etc/unbound/unbound.conf.
|
||||
* --with-pidfile=filename
|
||||
Set default location of pidfile,
|
||||
the default is /usr/local/etc/unbound/unbound.pid.
|
||||
* --with-run-dir=path
|
||||
Set default working directory,
|
||||
the default is /usr/local/etc/unbound.
|
||||
* --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.
|
||||
* --with-pyunbound
|
||||
Create libunbound wrapper usable from python.
|
||||
Needs python-devel and swig development tools.
|
||||
* --with-pythonmodule
|
||||
Compile the python module that processes responses in the server.
|
||||
* --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
|
||||
------------
|
||||
o If there are no replies for a forward or stub zone, for a reverse zone,
|
||||
you may need to add a local-zone: name transparent or nodefault to the
|
||||
server: section of the config file to unblock the reverse zone.
|
||||
Only happens for (sub)zones that are blocked by default; e.g. 10.in-addr.arpa
|
||||
o If libevent is older (before 1.3c), unbound will exit instead of reload
|
||||
on sighup. On a restart 'did not exit gracefully last time' warning is
|
||||
printed. Perform ./configure --with-libevent=no or update libevent, rerun
|
||||
configure and recompile unbound to make sighup work correctly.
|
||||
It is strongly suggested to use the latest version of libevent (1.4 or more)
|
||||
on Solaris, because of fixes in the solaris event port code in libevent.
|
||||
o If you receive no answers deploying unbound on a private network.
|
||||
Check that the zone you configure as a stub zone is correct, listing working
|
||||
ip-addresses. Check that the NS data in the zone, those hostnames, are
|
||||
in fact those same, working, ip-addresses. Unbound will fetch the NS data
|
||||
from the zone and use that information in preference to the config
|
||||
information.
|
||||
It is strongly suggested to use a recent version of libevent.
|
||||
o If you are not receiving the correct source IP address on replies (e.g.
|
||||
you are running a multihomed, anycast server), the interface-automatic
|
||||
option can be enabled to set socket options to achieve the correct
|
||||
@@ -72,6 +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
|
||||
----------------
|
||||
@@ -83,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.
|
||||
|
||||
|
||||
@@ -2,9 +2,6 @@ TODO items. These are interesting todo items.
|
||||
o understand synthesized DNAMEs, so those TTL=0 packets are cached properly.
|
||||
o NSEC/NSEC3 aggressive negative caching, so that updates to NSEC/NSEC3
|
||||
will result in proper negative responses.
|
||||
o get serverselection algorithm out of local optimum.
|
||||
make subtargets to get rtt info for a couple of targets, like fetch-policy.
|
||||
or send out multiple queries to multiple servers.
|
||||
o (option) where port 53 is used for send and receive, no other ports are used.
|
||||
o (option) to not send replies to clients after a timeout of (say 5 secs) has
|
||||
passed, but keep task active for later retries by client.
|
||||
@@ -17,8 +14,6 @@ o (option) store primed key data in a overlaid keyhints file (sort of like draft
|
||||
o windows version, auto update feature, a query to check for the version.
|
||||
o command the server with TSIG inband. get-config, clearcache,
|
||||
get stats, get memstats, get ..., reload, clear one zone from cache
|
||||
o watch for spoof nearmisses. Keep counter of nearmisses and print that
|
||||
in the stats lines, operator can determine what level is a redalert.
|
||||
o NSID rfc 5001 support.
|
||||
o timers rfc 5011 support.
|
||||
o Treat YXDOMAIN from a DNAME properly, in iterator (not throwaway), validator.
|
||||
@@ -26,42 +21,56 @@ o make timeout backoffs randomized (a couple percent random) to spread traffic.
|
||||
o inspect date on executable, then warn user in log if its more than 1 year.
|
||||
o (option) proactively prime root, stubs and trust anchors, feature.
|
||||
early failure, faster on first query, but more traffic.
|
||||
o On Windows use CryptGenRandom() to get random seed for arc4random.
|
||||
o library add convenience functions for A, AAAA, PTR, getaddrinfo, libresolve.
|
||||
o library add function to validate input from app that is signed.
|
||||
o add dynamic-update requests (making a dynupd request) to libunbound api.
|
||||
o in an ipv6 connected only environment unbound cannot use outgoing IP6
|
||||
to send to ip4to6 mapped hosts, need ip4to6map of NS and disable
|
||||
V6ONLY socket option.
|
||||
o SIG(0) and TSIG.
|
||||
o support OPT record placement on recv anywhere in the additional section.
|
||||
o add local-file: config with authority features.
|
||||
o (option) to make local-data answers be secure for libunbound (default=no)
|
||||
o (option) to make chroot: copy all needed files into jail (or make jail)
|
||||
perhaps also print reminder to link /dev/random and sysloghack.
|
||||
o (option) for extended statistics. If enabled (not by default) collect print
|
||||
rcode, uptime, spoofnearmisses, cache size, qtype,
|
||||
bits(RD, CD, DO, EDNS-present, AD)query, (Secure, Bogus)reply.
|
||||
perhaps also see which slow auth servers cause >1sec values.
|
||||
stats-file possible with key: value or key=value lines in it.
|
||||
stats on SIGUSR1. addup stats over threads.
|
||||
o overhaul outside-network servicedquery to merge with udpwait and tcpwait,
|
||||
to make timers in servicedquery independent of udpwait queues.
|
||||
o 0x20 fallback so it can be enabled without trouble.
|
||||
o check into rebinding ports for efficiency, configure time test.
|
||||
o DLV is considered.
|
||||
o EVP hardware crypto support.
|
||||
o option to ignore all inception and expiration dates for rrsigs.
|
||||
o cleaner code; return and func statements on newline.
|
||||
o memcached module that sits before validator module; checks for memcached
|
||||
data (on local lan), stores recursion lookup. Provides one cache for multiple resolver machines, coherent reply content in anycast setup.
|
||||
o no openssl_add_all_algorithms, but only the ones necessary, less space.
|
||||
o listen to NOTIFY messages for zones and flush the cache for that zone
|
||||
if received. Useful when also having a stub to that auth server.
|
||||
Needs proper protection, TSIG, in place.
|
||||
o winevent - do not go more than 64 fds (by polling with select one by
|
||||
one), win95/98 have 100fd limit in the kernel, so this ruins w9x portability.
|
||||
|
||||
Features soon after 1.0.
|
||||
o EDNS fallback after timeout (firewall drops all edns traffic problem).
|
||||
*** Features features, for later
|
||||
* dTLS, TLS, look to need special port numbers, cert storage, recent libssl.
|
||||
* aggressive negative caching for NSEC, NSEC3.
|
||||
* multiple queries per question, server exploration, server selection.
|
||||
* support TSIG on queries, for validating resolver deployment.
|
||||
* retry-mode, where a bogus result triggers a retry-mode query, where a list
|
||||
of responses over a time interval is collected, and each is validated.
|
||||
or try in TCP mode. Do not 'try all servers several times', since we must
|
||||
not create packet storms with operator errors.
|
||||
o on windows version, implement that OS ancillary data capabilities for
|
||||
interface-automatic. IPPKTINFO, IP6PKTINFO for WSARecvMsg, WSASendMsg.
|
||||
o local-zone directive with authority service, full authority server
|
||||
is a non-goal.
|
||||
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.
|
||||
|
||||
For 1.x; features that have been requested during the beta test.
|
||||
o command channel for couple of tasks. Like rndc.
|
||||
o see delegation; what servers would be used to get data for a name.
|
||||
o force stats display; easier than parsing logfiles.
|
||||
stats display added over threads, displayed in rddtool easy format.
|
||||
o flush names or domains (all under a name) from the cache. Include NSes.
|
||||
And the A, AAAA for its NSes.
|
||||
o add/del static preload data to change the domain redirections.
|
||||
o and maybe also start, stop, reload.
|
||||
later
|
||||
- selective verbosity; ubcontrol trace example.com
|
||||
- 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
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
|
||||
Specification for the unbound-control protocol.
|
||||
|
||||
Server listens on 953 TCP (localhost by default). Client connects,
|
||||
SSLv3 or TLSv1 connection setup (server selfsigned certificate,
|
||||
client has cert signed by server certificate).
|
||||
|
||||
Query and Response
|
||||
------------------
|
||||
Client sends
|
||||
UBCT [commandline] \n
|
||||
fixed string UBCT, then an ascii text line, with a command,
|
||||
some whitespace allowed. Line ends with '\n'.
|
||||
|
||||
Server executes command. And sends reply in ascii text over channel,
|
||||
closes the channel when done.
|
||||
in case of error the first line of the response is:
|
||||
error <descriptive text possible> \n
|
||||
or the remainder is data of the response, for many commands the
|
||||
response is 'ok\n'.
|
||||
|
||||
Queries and responses
|
||||
---------------------
|
||||
stop
|
||||
stops the server.
|
||||
reload
|
||||
reloads the config file, and flushes the cache.
|
||||
verbosity <new value>
|
||||
Change logging verbosity to new value.
|
||||
stats
|
||||
output is a list of [name]=[value] lines.
|
||||
clears the counters.
|
||||
dump_cache
|
||||
output is a text representation of the cache contents.
|
||||
data ends with a line 'EOF' before connection close.
|
||||
load_cache
|
||||
client sends cache contents (like from dump_cache), which is stored
|
||||
in the cache. end of data indicated with a line with 'EOF' on it.
|
||||
The data is sent after the query line.
|
||||
flush <name>
|
||||
flushes some information regarding the name from the cache.
|
||||
removes the A, AAAA, NS, SOA, CNAME, DNAME, MX, PTR, SRV, NAPTR types.
|
||||
Does not remove other types.
|
||||
flush_type <name> <RR type>
|
||||
removes rrtype entry from the cache.
|
||||
flush_zone <name>
|
||||
removes name and everything below that name from the cache.
|
||||
has to search through the cache item by item, so this is slow.
|
||||
lookup <name>
|
||||
see what servers would be queried for a lookup of the given name.
|
||||
local_zone_remove <name of local-zone entry>
|
||||
the local-zone entry is removed.
|
||||
All data from the local zone is also deleted.
|
||||
If it did not exist, nothing happens.
|
||||
local_zone <name of local zone> <type>
|
||||
As the config file entry. Adds new local zone or updates
|
||||
existing zone type.
|
||||
local_data_remove <name>
|
||||
Removes local-data (all types) name.
|
||||
local_data <resource record string>
|
||||
Add new local data record (on the rest of the line).
|
||||
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.
|
||||
@@ -18,24 +18,29 @@ server:
|
||||
# print statistics to the log (for every thread) every N seconds.
|
||||
# Set to "" or 0 to disable. Default is disabled.
|
||||
# statistics-interval: 0
|
||||
|
||||
|
||||
# enable cumulative statistics, without clearing them after printing.
|
||||
# statistics-cumulative: no
|
||||
|
||||
# enable extended statistics (query types, answer codes, status)
|
||||
# printed from unbound-control. default off, because of speed.
|
||||
# extended-statistics: no
|
||||
|
||||
# number of threads to create. 1 disables threading.
|
||||
# num-threads: 1
|
||||
|
||||
# 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.
|
||||
# Socket options not be supported on all platforms. experimental.
|
||||
# Socket options are not supported on all platforms. experimental.
|
||||
# interface-automatic: no
|
||||
|
||||
# port to answer queries from
|
||||
@@ -49,9 +54,10 @@ 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.
|
||||
# outgoing-port-permit: 32768
|
||||
@@ -68,7 +74,15 @@ 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
|
||||
@@ -85,6 +99,9 @@ server:
|
||||
# the number of queries that a thread gets to service.
|
||||
# num-queries-per-thread: 1024
|
||||
|
||||
# if very busy, 50% queries run to completion, 50% get timeout in msec
|
||||
# jostle-timeout: 200
|
||||
|
||||
# the amount of memory to use for the RRset cache.
|
||||
# plain value in bytes or you can append k, m or G. default is "4Mb".
|
||||
# rrset-cache-size: 4m
|
||||
@@ -93,7 +110,11 @@ server:
|
||||
# the number of slabs must be a power of 2.
|
||||
# more slabs reduce lock contention, but fragment memory usage.
|
||||
# rrset-cache-slabs: 4
|
||||
|
||||
|
||||
# the time to live (TTL) value lower bound, in seconds. Default 0.
|
||||
# If more than an hour could easily give trouble due to stale data.
|
||||
# cache-min-ttl: 0
|
||||
|
||||
# the time to live (TTL) value cap for RRsets and messages in the
|
||||
# cache. Items are not cached for longer. In seconds.
|
||||
# cache-max-ttl: 86400
|
||||
@@ -134,13 +155,14 @@ server:
|
||||
# control which clients are allowed to make (recursive) queries
|
||||
# to this server. Specify classless netblocks with /size and action.
|
||||
# By default everything is refused, except for localhost.
|
||||
# Choose deny (drop message), refuse (polite error reply), allow.
|
||||
# Choose deny (drop message), refuse (polite error reply),
|
||||
# allow (recursive ok), allow_snoop (recursive and nonrecursive ok)
|
||||
# access-control: 0.0.0.0/0 refuse
|
||||
# access-control: 127.0.0.0/8 allow
|
||||
# access-control: ::0/0 refuse
|
||||
# access-control: ::1 allow
|
||||
# access-control: ::ffff:127.0.0.1 allow
|
||||
|
||||
|
||||
# if given, a chroot(2) is done to the given directory.
|
||||
# i.e. you can chroot to the working directory, for example,
|
||||
# for extra security, but make sure all files are in that directory.
|
||||
@@ -150,57 +172,62 @@ server:
|
||||
# chroot has been performed the now defunct portion of the config
|
||||
# file path is removed to be able to reread the config after a reload.
|
||||
#
|
||||
# All other file paths (working dir, pidfile, logfile, roothints,
|
||||
# All other file paths (working dir, logfile, roothints, and
|
||||
# key files) can be specified in several ways:
|
||||
# o as an absolute path relative to the new root.
|
||||
# o as a relative path to the working directory.
|
||||
# o as an absolute path relative to the original root.
|
||||
# In the last case the path is adjusted to remove the unused portion.
|
||||
#
|
||||
# Additionally, unbound may need to access /dev/random (for entropy)
|
||||
# and to /dev/log (if you use syslog) from inside the chroot.
|
||||
# The pid file can be absolute and outside of the chroot, it is
|
||||
# written just prior to performing the chroot and dropping permissions.
|
||||
#
|
||||
# Additionally, unbound may need to access /dev/random (for entropy).
|
||||
# How to do this is specific to your OS.
|
||||
#
|
||||
# If you give "" no chroot is performed. The path must not end in a /.
|
||||
# chroot: "/usr/local/etc/unbound"
|
||||
# chroot: "@UNBOUND_CHROOT_DIR@"
|
||||
|
||||
# if given, user privileges are dropped (after binding port),
|
||||
# and the given username is assumed. Default is user "unbound".
|
||||
# If you give "" no privileges are dropped.
|
||||
# username: "unbound"
|
||||
# username: "@UNBOUND_USERNAME@"
|
||||
|
||||
# the working directory. The relative files in this config are
|
||||
# relative to this directory. If you give "" the working directory
|
||||
# is not changed.
|
||||
# directory: "/usr/local/etc/unbound"
|
||||
# directory: "@UNBOUND_RUN_DIR@"
|
||||
|
||||
# the log file, "" means log to stderr.
|
||||
# Use of this option sets use-syslog to "no".
|
||||
# logfile: ""
|
||||
|
||||
|
||||
# Log to syslog(3) if yes. The log facility LOG_DAEMON is used to
|
||||
# log to, with identity "unbound". If yes, it overrides the logfile.
|
||||
# use-syslog: yes
|
||||
|
||||
# the pid file.
|
||||
# pidfile: "/usr/local/etc/unbound/unbound.pid"
|
||||
|
||||
# print UTC timestamp in ascii to logfile, default is epoch in seconds.
|
||||
# log-time-ascii: no
|
||||
|
||||
# the pid file. Can be an absolute path outside of chroot/work dir.
|
||||
# pidfile: "@UNBOUND_PIDFILE@"
|
||||
|
||||
# file to read root hints from.
|
||||
# get one from ftp://FTP.INTERNIC.NET/domain/named.cache
|
||||
# root-hints: ""
|
||||
|
||||
|
||||
# enable to not answer id.server and hostname.bind queries.
|
||||
# hide-identity: no
|
||||
|
||||
|
||||
# enable to not answer version.server and version.bind queries.
|
||||
# hide-version: no
|
||||
|
||||
|
||||
# the identity to report. Leave "" or default to return hostname.
|
||||
# identity: ""
|
||||
|
||||
|
||||
# the version to report. Leave "" or default to return package version.
|
||||
# version: ""
|
||||
|
||||
|
||||
# the target fetch policy.
|
||||
# series of integers describing the policy per dependency depth.
|
||||
# The number of values in the list determines the maximum dependency
|
||||
@@ -210,50 +237,96 @@ server:
|
||||
# positive value: fetch that many targets opportunistically.
|
||||
# Enclose the list of numbers between quotes ("").
|
||||
# target-fetch-policy: "3 2 1 0 0"
|
||||
|
||||
|
||||
# Harden against very small EDNS buffer sizes.
|
||||
# harden-short-bufsize: no
|
||||
|
||||
|
||||
# Harden against unseemly large queries.
|
||||
# harden-large-queries: no
|
||||
|
||||
|
||||
# Harden against out of zone rrsets, to avoid spoofing attempts.
|
||||
# harden-glue: yes
|
||||
|
||||
|
||||
# Harden against receiving dnssec-stripped data. If you turn it
|
||||
# off, failing to validate dnskey data for a trustanchor will
|
||||
# trigger insecure mode for that zone (like without a trustanchor).
|
||||
# Default on, which insists on dnssec data for trust-anchored zones.
|
||||
# harden-dnssec-stripped: yes
|
||||
|
||||
|
||||
# Harden the referral path by performing additional queries for
|
||||
# infrastructure data. Validates the replies (if possible).
|
||||
# Default off, because the lookups burden the server. Experimental
|
||||
# implementation of draft-wijngaards-dnsext-resolver-side-mitigation.
|
||||
# harden-referral-path: no
|
||||
|
||||
# Use 0x20-encoded random bits in the query to foil spoof attempts.
|
||||
# Disabled by default, because some caching forwarders may not
|
||||
# support this (if you have forward-zones). Most authority servers do.
|
||||
# This feature is an experimental implementation of draft dns-0x20.
|
||||
# It is known that some authority servers do not support 0x20, and
|
||||
# resolution will fail for them. A solution is on the TODO list.
|
||||
# use-caps-for-id: no
|
||||
|
||||
|
||||
# Enforce privacy of these addresses. Strips them away from answers.
|
||||
# It may cause DNSSEC validation to additionally mark it as bogus.
|
||||
# Protects against 'DNS Rebinding' (uses browser as network proxy).
|
||||
# Only 'private-domain' and 'local-data' names are allowed to have
|
||||
# these private addresses. No default.
|
||||
# private-address: 10.0.0.0/8
|
||||
# private-address: 172.16.0.0/12
|
||||
# private-address: 192.168.0.0/16
|
||||
# private-address: 169.254.0.0/16
|
||||
# private-address: fd00::/8
|
||||
# private-address: fe80::/10
|
||||
|
||||
# Allow the domain (and its subdomains) to contain private addresses.
|
||||
# local-data statements are allowed to contain private addresses too.
|
||||
# private-domain: "example.com"
|
||||
|
||||
# If nonzero, unwanted replies are not only reported in statistics,
|
||||
# but also a running total is kept per thread. If it reaches the
|
||||
# threshold, a warning is printed and a defensive action is taken,
|
||||
# the cache is cleared to flush potential poison out of it.
|
||||
# A suggested value is 10000000, the default is 0 (turned off).
|
||||
# unwanted-reply-threshold: 0
|
||||
|
||||
# Do not query the following addresses. No DNS queries are sent there.
|
||||
# List one address per entry. List classless netblocks with /size,
|
||||
# do-not-query-address: 127.0.0.1/8
|
||||
# do-not-query-address: ::1
|
||||
|
||||
|
||||
# if yes, the above default do-not-query-address entries are present.
|
||||
# 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
|
||||
# dlv-anchor-file: "dlv.isc.org.key"
|
||||
|
||||
# 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"
|
||||
@@ -262,35 +335,59 @@ 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.
|
||||
# domain-insecure: "example.com"
|
||||
|
||||
# Override the date for validation with a specific fixed date.
|
||||
# Do not set this unless you are debugging signature inception
|
||||
# and expiration. "" or "0" turns the feature off.
|
||||
# val-override-date: ""
|
||||
|
||||
|
||||
# The time to live for bogus data, rrsets and messages. This avoids
|
||||
# some of the revalidation, until the time interval expires. in secs.
|
||||
# val-bogus-ttl: 900
|
||||
|
||||
# val-bogus-ttl: 60
|
||||
|
||||
# The signature inception and expiration dates are allowed to be off
|
||||
# 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
|
||||
|
||||
# Should additional section of secure message also be kept clean of
|
||||
# unsecure data. Useful to shield the users of this validator from
|
||||
# potential bogus data in the additional section. All unsigned data
|
||||
# in the additional section is removed from secure messages.
|
||||
# val-clean-additional: yes
|
||||
|
||||
|
||||
# Turn permissive mode on to permit bogus messages. Thus, messages
|
||||
# for which security checks failed will be returned to clients,
|
||||
# instead of SERVFAIL. It still performs the security checks, which
|
||||
# result in interesting log files and possibly the AD bit in
|
||||
# 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".
|
||||
@@ -301,13 +398,17 @@ server:
|
||||
# more slabs reduce lock contention, but fragment memory usage.
|
||||
# key-cache-slabs: 4
|
||||
|
||||
# the amount of memory to use for the negative cache (used for DLV).
|
||||
# plain value in bytes or you can append k, m or G. default is "1Mb".
|
||||
# neg-cache-size: 1m
|
||||
|
||||
# a number of locally served zones can be configured.
|
||||
# local-zone: <zone> <type>
|
||||
# local-data: "<resource record string>"
|
||||
# o deny serves local data (if any), else, drops queries.
|
||||
# o refuse serves local data (if any), else, replies with error.
|
||||
# o static serves local data, else, nxdomain or nodata answer.
|
||||
# o transparent serves local data, else, resolves normally .
|
||||
# o transparent gives local data, but resolves normally for other names
|
||||
# o redirect serves the zone data for any subdomain in the zone.
|
||||
# o nodefault can be used to normally resolve AS112 zones.
|
||||
#
|
||||
@@ -330,15 +431,55 @@ server:
|
||||
# (this makes example.com, www.example.com, etc, all go to 192.0.2.3)
|
||||
# local-zone: "example.com" redirect
|
||||
# local-data: "example.com A 192.0.2.3"
|
||||
#
|
||||
# Shorthand to make PTR records, "IPv4 name" or "IPv6 name".
|
||||
# You can also add PTR records using local-data directly, but then
|
||||
# you need to do the reverse notation yourself.
|
||||
# local-data-ptr: "192.0.2.3 www.example.com"
|
||||
|
||||
# Python config section. To enable:
|
||||
# o use --with-pythonmodule to configure before compiling.
|
||||
# o list python in the module-config string (above) to enable.
|
||||
# o and give a python-script to run.
|
||||
python:
|
||||
# Script file to load
|
||||
# python-script: "@UNBOUND_SHARE_DIR@/ubmodule-tst.py"
|
||||
|
||||
# Remote control config section.
|
||||
remote-control:
|
||||
# Enable remote control with unbound-control(8) here.
|
||||
# set up the keys and certificates with unbound-control-setup.
|
||||
# control-enable: no
|
||||
|
||||
# what interfaces are listened to for remote control.
|
||||
# give 0.0.0.0 and ::0 to listen to all interfaces.
|
||||
# control-interface: 127.0.0.1
|
||||
# control-interface: ::1
|
||||
|
||||
# port number for remote control operations.
|
||||
# control-port: 953
|
||||
|
||||
# unbound server key file.
|
||||
# server-key-file: "@UNBOUND_RUN_DIR@/unbound_server.key"
|
||||
|
||||
# unbound server certificate file.
|
||||
# server-cert-file: "@UNBOUND_RUN_DIR@/unbound_server.pem"
|
||||
|
||||
# unbound-control key file.
|
||||
# control-key-file: "@UNBOUND_RUN_DIR@/unbound_control.key"
|
||||
|
||||
# unbound-control certificate file.
|
||||
# control-cert-file: "@UNBOUND_RUN_DIR@/unbound_control.pem"
|
||||
|
||||
# Stub zones.
|
||||
# Create entries like below, to make all queries for 'example.com' and
|
||||
# 'example.org' go to the given list of nameservers. list zero or more
|
||||
# nameservers by hostname or by ipaddress.
|
||||
# nameservers by hostname or by ipaddress. If you set stub-prime to yes,
|
||||
# the list is treated as priming hints (default is no).
|
||||
# stub-zone:
|
||||
# name: "example.com"
|
||||
# stub-addr: 192.0.2.68
|
||||
# stub-prime: no
|
||||
# stub-zone:
|
||||
# name: "example.org"
|
||||
# stub-host: ns.example.com.
|
||||
@@ -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,
|
||||
@@ -35,7 +36,12 @@
|
||||
.B ub_resolve_async,
|
||||
.B ub_cancel,
|
||||
.B ub_resolve_free,
|
||||
.B ub_strerror
|
||||
.B ub_strerror,
|
||||
.B ub_ctx_print_local_zones,
|
||||
.B ub_ctx_zone_add,
|
||||
.B ub_ctx_zone_remove,
|
||||
.B ub_ctx_data_add,
|
||||
.B ub_ctx_data_remove
|
||||
\- Unbound DNS validating resolver @version@ functions.
|
||||
.SH "SYNOPSIS"
|
||||
.LP
|
||||
@@ -51,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
|
||||
@@ -95,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,
|
||||
@@ -114,6 +121,21 @@
|
||||
.LP
|
||||
\fIconst char *\fR
|
||||
\fBub_strerror\fR(\fIint\fR err);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_print_local_zones\fR(\fIstruct ub_ctx*\fR ctx);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_zone_add\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR zone_name, \fIchar*\fR zone_type);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_zone_remove\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR zone_name);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_data_add\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR data);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_data_remove\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR data);
|
||||
.SH "DESCRIPTION"
|
||||
.LP
|
||||
.B Unbound
|
||||
@@ -160,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
|
||||
@@ -181,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
|
||||
@@ -197,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
|
||||
@@ -208,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
|
||||
@@ -261,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
|
||||
@@ -278,10 +305,13 @@ void my_callback_function(void* my_arg, int err,
|
||||
struct ub_result* result);
|
||||
.IP
|
||||
The async_id is returned so you can (at your option) decide to track it
|
||||
and cancel the request if needed.
|
||||
and cancel the request if needed. If you pass a NULL pointer the async_id
|
||||
is not returned.
|
||||
.TP
|
||||
.B ub_cancel
|
||||
Cancel an async query in progress.
|
||||
Cancel an async query in progress. This may return an error if the query
|
||||
does not exist, or the query is already being delivered, in that case you
|
||||
may still get a callback for the query.
|
||||
.TP
|
||||
.B ub_resolve_free
|
||||
Free struct ub_result contents after use.
|
||||
@@ -289,6 +319,23 @@ Free struct ub_result contents after use.
|
||||
.B ub_strerror
|
||||
Convert error value from one of the unbound library functions
|
||||
to a human readable string.
|
||||
.TP
|
||||
.B ub_ctx_print_local_zones
|
||||
Debug printout the local authority information to debug output.
|
||||
.TP
|
||||
.B ub_ctx_zone_add
|
||||
Add new zone to local authority info, like local\-zone \fIunbound.conf\fR(5)
|
||||
statement.
|
||||
.TP
|
||||
.B ub_ctx_zone_remove
|
||||
Delete zone from local authority info.
|
||||
.TP
|
||||
.B ub_ctx_data_add
|
||||
Add resource record data to local authority info, like local\-data
|
||||
\fIunbound.conf\fR(5) statement.
|
||||
.TP
|
||||
.B ub_ctx_data_remove
|
||||
Delete local authority data from the name given.
|
||||
.SH "RESULT DATA STRUCTURE"
|
||||
.LP
|
||||
The result of the DNS resolution and validation is returned as
|
||||
@@ -309,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
|
||||
@@ -326,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).
|
||||
@@ -1,324 +0,0 @@
|
||||
Plan for Unbound.
|
||||
|
||||
Split into a set of boxes. Every box will take about 3 weeks to a month
|
||||
to complete. The first set of of boxes (approx 5 months) will need coding
|
||||
by a limited set of people. But after every box, a 0.x release is done,
|
||||
which is then tested and code review is done.
|
||||
|
||||
Every box:
|
||||
* implement the features
|
||||
* documentation of those features
|
||||
* test-framework for the new features
|
||||
* tests for the new features
|
||||
* speed test of this stage
|
||||
* release of 0.x version (0.x for development only)
|
||||
* a teleconference(jabber) held to discuss.
|
||||
* code review internal couple of days, external a week or so,
|
||||
while we continue the next box.
|
||||
|
||||
Roughly the boxes are as follows:
|
||||
0.0 initial setup - results in network code that forwards queries
|
||||
and returns the reply (no cache), but also testbed, svn, maillist.
|
||||
One query at a time (nonblocking IO though).
|
||||
0.1 threads - results in threaded forwarder
|
||||
0.2 LRU hashtable, results in basic caching forwarder (no DNS parse)
|
||||
0.3 First functionality - results in caching forwarder (with DNS parse,
|
||||
query compare, RR specific updates).
|
||||
0.4 Basic resolver - module layout, iterator module, scrubber module,
|
||||
results in resolver that can service multiple queries per thread.
|
||||
This stage takes longer, due to complexity in the iterator module.
|
||||
Twice as long; one box for module layout, one box for iterator module.
|
||||
0.5 Validator - validator module.
|
||||
0.6 Bigger and better - Operational useful features (config, log, memory)
|
||||
0.7 Put to a limited audience.
|
||||
gamma/alpha core functionality test release, to a small audience.
|
||||
partial functionality. For more extensive use and testing.
|
||||
0.8 Local zones feature - localzones stubzones fwdzones, no leak rfc1918.
|
||||
views support; for selective recursive service.
|
||||
0.9 Library use - resolver validator lib (and test apps)
|
||||
0.10 Corner cases - be able to resolve in the wild. Run fuzzers.
|
||||
Run as many tests as we can think of.
|
||||
Go through logs and check for long, unresolved cases
|
||||
Use profiler.
|
||||
0.11 Beta release. Run shadow for a resolver in production for several
|
||||
weeks.
|
||||
0.12 Features features
|
||||
aggressive negative caching for NSEC, NSEC3.
|
||||
multiple queries per question, server exploration, server selection.
|
||||
option to use real entropy for randomness (mix it in once in a while).
|
||||
check query, option to enforce qdsection checking (forgery-resilience).
|
||||
NSID support.
|
||||
Be able to prime roots using several queries (only NS on first).
|
||||
|
||||
For boxes 0.5-1.0 the planning is to be revised, at the 0.5 stage external
|
||||
coders are welcome. Since the project is bigger, there is room for them.
|
||||
|
||||
This is a summary of the items. Below more detailed work items are spelled
|
||||
out with a (tentative) directory structure for the project.
|
||||
|
||||
|
||||
Styleguide:
|
||||
* write working stuff. (it starts to work with no features)
|
||||
* write tests immediately for every function, every feature.
|
||||
* document as you go. (doxygen comments, manpages and readme).
|
||||
* copyright every file BSD. comments every file. clean coding in C.
|
||||
* every day discuss state of the nation for 10 minutes.
|
||||
|
||||
*** Initial setup
|
||||
* setup svn repo. Makefile with automatic dependencies and configure script.
|
||||
* link with ldns.
|
||||
* listen_dnsport and outside_network services, (unit) tests for them.
|
||||
* use libevent to listen on fds.
|
||||
* setup test infrastructure (tpkg on checkin; testbed on labs test machines).
|
||||
* daemon version that forwards queries. (listen, send) Tests for it.
|
||||
* test by having the outside_net service grab answers from a
|
||||
file instead of network, file of id priority answerpacket.
|
||||
and what query to give this answer to, highprio matches first.
|
||||
|
||||
*** Threads
|
||||
* first simple config file reading/writing and tests on config file.
|
||||
(config option is forwarder: yes/no. Cache size. That sort of thing.)
|
||||
(very simple format)
|
||||
* First simple logging (to a file).
|
||||
* Threads
|
||||
* check if pthread lib is the one to use (sys specific is faster?).
|
||||
* make config option to have threads.
|
||||
* alloc threadable.
|
||||
* locks.c
|
||||
* Tests with and without threads.
|
||||
* alloc_service. Tests for alloc service (unit tests in internal structs).
|
||||
* threading for the network services.
|
||||
* Make sure threading/libevent starts working on all test machines.
|
||||
Use configure to turn off threading/libevent/...
|
||||
-- use libevent packaged together if not in system.
|
||||
-- maybe also for pthreads/...
|
||||
* threaded forwarder version.
|
||||
* speed test of threaded version.
|
||||
|
||||
*** LRU hashtable.
|
||||
* mini msg/reply structure for LRU hashtable test, simple replay format.
|
||||
* hashtable+LRU structure. Tests on structure.
|
||||
* tests on enter/remove, finding items.
|
||||
* tests on LRU movements.
|
||||
* Test on speed of finding items.
|
||||
* slabbed hashtable+LRU structure.
|
||||
* Test locking; perhaps by having sleeps in some threads to force
|
||||
locks to contend. helgrind.
|
||||
* daemon upgraded to be a caching forwarder. So it stores all in cache.
|
||||
Replies from cache. Tests on fake-caching forwarder functionality.
|
||||
* timeout of data test
|
||||
* finding data in cache.
|
||||
* finding data not in cache.
|
||||
* lru falloff of data.
|
||||
* Speed test of fake-caching forwarder.
|
||||
|
||||
*** First functionality
|
||||
* implement dname type and unit tests on it. (all corner cases, random cases)
|
||||
* implement rrset type and tests. (all corner cases, random cases).
|
||||
* msg-reply structure. unit tests of structure.
|
||||
* Test of those rrset pointers
|
||||
* daemon upgraded to be a caching forwarder. So it stores all in cache.
|
||||
Replies from cache. Tests on caching forwarder functionality.
|
||||
* timeout of data test
|
||||
* finding data in cache.
|
||||
* finding data not in cache.
|
||||
* lru falloff of data.
|
||||
* Test update of one rrset in cached packet.
|
||||
* Speed test of caching forwarder.
|
||||
|
||||
*** Basic Resolver
|
||||
* Create module interface and module caller algorithm.
|
||||
* Daemon config to use modules. Test the module caller.
|
||||
* Create basic iterator and scrubber modules.
|
||||
* Test every state of the iterator by passing test data into
|
||||
it.
|
||||
* And scrubber.
|
||||
* Daemon config as cache(iterator).
|
||||
* Test daemon
|
||||
* Speed test.
|
||||
|
||||
*** Validator
|
||||
* Create validator
|
||||
* Test validator on various conditions. By having stored set of
|
||||
domains and RRs in those domains to return to validator.
|
||||
* Validating resolver.
|
||||
* Test resolver.
|
||||
* Speed test.
|
||||
|
||||
*** Put to a limited audience
|
||||
* The alpha/gamma core functionality, svn access to limited audience.
|
||||
* Support features and requests as they arise.
|
||||
* Provide real-world experiences.
|
||||
|
||||
*** Bigger and Better
|
||||
* Config file syntax checker program. Tests on checker.
|
||||
* Logging first class feature with config options.
|
||||
X with logfile turnover to avoid Gbs of logs.
|
||||
* use syslog optional.
|
||||
* donotqueryaddresses with trie for blocking entire netblocks.
|
||||
* Memory overhaul, special allocators for hashtable caches, and mesh qstates.
|
||||
* keep a preallocated list of region-chunks per worker thread.
|
||||
* allocate region struct and cleanup list in region itself; use
|
||||
linked list cleanup list. unit test on this. do not call region
|
||||
to avoid name-collision with nsd regions, 'regional'.
|
||||
* read root hints from file.
|
||||
* failover to next server in 1 second, instead of 100 seconds on one server.
|
||||
X failure to return answer, w. reason (donotq, noanswer servers, cannot
|
||||
find servers, validationfail w.classification, error),
|
||||
with threadno, starttime and endtime and qname/type/class, prime/qflags,
|
||||
from-clients, from-internal, has-subrequests, a nice error report,
|
||||
so that an excerpt from those times can be made from the logs.
|
||||
logfileparsing tool that makes these excerpts and emails them.
|
||||
Not done; user can change verbosity and kill -HUP.
|
||||
* clear cache as a callback from the new-rrset-id routine.
|
||||
X make overload mode work; phase 0 all ok, phase 1 some threads close ports,
|
||||
to let other threads pick up work. phase 2, all threads closed, so all open
|
||||
the ports again and drop all non-cache-reply queries.
|
||||
Keep mutexed num-overloaded-threads counter. thread incs it when it hits
|
||||
max number of user queries serviced in mesh. threads decs it when it
|
||||
falls below 90% of the max. if incs, and not all threads closed, phase 1,
|
||||
else, phase 2 start is broadcast over command pipes. if decs, open ports
|
||||
if phase 1, start servicing, phase is 0 again. Make robust against delays.
|
||||
readme: max about 1 second worth of incoming queries, 10k perhaps,
|
||||
or 1/number of seconds it takes start up of 10k.
|
||||
Not done. Implement drop when full.
|
||||
* the source includes a copy of the ldns lib for ease of building by
|
||||
new users. Detect system installed ldns, if installed ldns is OK; use
|
||||
dynamic linking against it, otherwise static linking against packaged ldns.
|
||||
* no greedy TTL algo (and test).
|
||||
* maximum TTL, cap incoming values, and config option.
|
||||
|
||||
*** Local zones feature.
|
||||
* Build in local zone features. First the total stop for1912.
|
||||
* Then 'local content' for minimal serving of localhost.localdomain,
|
||||
and so on.
|
||||
* Remember jakob's diagram. views support, selective recursive service:
|
||||
* acl for allowed recursion (RD=1), then drop or refused query.
|
||||
like 10.0.0.0/8 allow, 0.0.0.0/0 refuse, ... in-order.
|
||||
perhaps also, same list to disallow RD=0 access, like;
|
||||
allow_recursion, drop_recursion, refuse_recursion, drop_all
|
||||
* static answers for queries, fixed RRs from cfg, option
|
||||
query for that RR returns answer with that RR.
|
||||
* blacklist (return fixed nxdomain for domain and below), option
|
||||
can be used to block AS112 traffic, option to unblock a zone.
|
||||
* after checking acl, do iter: static, blacklist, forwards, recurse.
|
||||
* Forward-local-zone to NSD.
|
||||
- in package, autoforkexec on localhost to do so.
|
||||
- not included. Not necessary for localhost and AS112 service.
|
||||
* forward local zone to remote server.
|
||||
- not included. Not necessary for localhost and AS112 service.
|
||||
* stub zones - send queries for a zone to configged nameserver.
|
||||
- Can be used for complicated setups. So, run auth server on a
|
||||
different port or pc, and stub it on the resolver. Resolver is
|
||||
not auth for zones, but resolution works. This enforces the split
|
||||
of recursive and auth servers.
|
||||
* test local zones
|
||||
* for speed
|
||||
* for correctness on corner cases
|
||||
|
||||
*** Library use
|
||||
* Create library that can do:
|
||||
* resolver
|
||||
* validator
|
||||
* validating resolver.
|
||||
* Test application that links the library. (Like /usr/bin/host+validating).
|
||||
* Test it.
|
||||
|
||||
*** Corner cases
|
||||
* Try to setup corner cases of (mis)configured DNS service/websites.
|
||||
* Resolve msoft, google, yahoo, etc weird websites.
|
||||
* Try to resolve many many different queries, perhaps compared with bind.
|
||||
* create module testers, specific for the modules
|
||||
* read a file with cache contents and settings, provide fake
|
||||
environment for module-handle-state-X functions, then check
|
||||
resulting module state structure to correct answer.
|
||||
* speed test cache responses.
|
||||
* using two servers, compare answer differences between bind and unbound.
|
||||
this gives false differences due to changes in the rest of internet.
|
||||
|
||||
*** Beta release.
|
||||
* Run shadow for a resolver in production for several weeks.
|
||||
* Check logs for errors, long queries.
|
||||
* Run in valgrind, speed profiling (as production shadow).
|
||||
|
||||
*** Features features
|
||||
* aggressive negative caching for NSEC, NSEC3.
|
||||
* multiple queries per question, server exploration, server selection.
|
||||
* NSID support.
|
||||
* support TSIG on queries, for validating resolver deployment.
|
||||
* Nicer statistics
|
||||
* private TTL, dTLS features.
|
||||
* retry-mode, where a bogus result triggers a retry-mode query, where a list
|
||||
of responses over a time interval is collected, and each is validated.
|
||||
or try in TCP mode. Do not 'try all servers several times', since we must
|
||||
not create packet storms with operator errors.
|
||||
* draft-timers, DLV features.
|
||||
|
||||
treeshrew/
|
||||
validator/ *.c *.h
|
||||
module takes qname, qtype, asks next module for answer
|
||||
and validates that answer.
|
||||
iterator/ *.c *.h
|
||||
module takes qname, qtype, iterative DNS queries
|
||||
never asks next module.
|
||||
services/
|
||||
- Routines that provide the callback services for modules.
|
||||
|
||||
alloc_service: L1, L2 alloc service
|
||||
outside_network: pending queries helpers.
|
||||
pending query structure
|
||||
listen_dnsport: listen port53 service.
|
||||
request structure
|
||||
type_caches/
|
||||
rrset_cache
|
||||
msg_cache
|
||||
rrset and msg cache check local zones.
|
||||
infra_cache
|
||||
trusted_key_cache
|
||||
util/
|
||||
- Various components from which to build the rest.
|
||||
|
||||
storage/
|
||||
rbtree: redblack tree, for L1 use.
|
||||
- copy from NSD.
|
||||
hashtable and hashfunc: for L1 use.
|
||||
locked_hashtable: for L2 use. -- not needed.
|
||||
fragment_hashtable: for L2 use.
|
||||
fragment_rbtree: for L2 use.
|
||||
slab_allocator: perhaps to support alloc service.
|
||||
|
||||
(in util/ itself)
|
||||
locks: selected lock,unlock (spinlock/mutex).
|
||||
config: reads, stores config file
|
||||
netio: register callbacks to select().
|
||||
- use libevent (!)
|
||||
- copy from NSD.
|
||||
log: error and log handling.
|
||||
module.h: module interface
|
||||
misc: time() wrapper for speed.
|
||||
|
||||
data/
|
||||
msg_reply: qname/qtype/CD/qclass/reply store.
|
||||
packed_rrset: main datatype
|
||||
dname: compare, printf, parse
|
||||
|
||||
testcode/
|
||||
main programs that do unit tests, using testdata
|
||||
testdata/
|
||||
daemon/
|
||||
unbound.c for validating caching recursive dns server.
|
||||
scheduler.c for the modules.
|
||||
|
||||
libunbound/
|
||||
app linkable. Can be configged to do whatever,
|
||||
validator, iterator, validating iterator, forwarding stub.
|
||||
libforwardbound/
|
||||
app linkable forwarding stub. Small lib.
|
||||
|
||||
ask_cachor/ *.c *.h
|
||||
module takes qname, qtype, returns answer from msgcache.
|
||||
could ask cached for answer (and wait for network, 10 ms).
|
||||
if not in cache, asks next module.
|
||||
cachord/
|
||||
main.c, simple udp proto, query or store msg in cache.
|
||||
supports option to save cache to disk (absolute time ttls).
|
||||
@@ -206,3 +206,89 @@ o Case preservation
|
||||
The casing from the query name is used in preference to the casing
|
||||
of the authority server. This is the same as BIND. RFC4343 allows either
|
||||
behaviour.
|
||||
|
||||
o Denial of service protection
|
||||
If many queries are made, and they are made to names for which the
|
||||
authority servers do not respond, then the requestlist for unbound
|
||||
fills up fast. This results in denial of service for new queries.
|
||||
To combat this the first 50% of the requestlist can run to completion.
|
||||
The last 50% of the requestlist get (200 msec) at least and are replaced
|
||||
by newer queries when older (LIFO).
|
||||
When a new query comes in, and a place in the first 50% is available, this
|
||||
is preferred. Otherwise, it can replace older queries out of the last 50%.
|
||||
Thus, even long queries get a 50% chance to be resolved. And many 'short'
|
||||
one or two round-trip resolves can be done in the last 50% of the list.
|
||||
The timeout can be configured.
|
||||
|
||||
o EDNS fallback. Is done according to the EDNS RFC (and update draft-00).
|
||||
Unbound assumes EDNS 0 support for the first query. Then it can detect
|
||||
support (if the servers replies) or non-support (on a NOTIMPL or FORMERR).
|
||||
Some middleboxes drop EDNS 0 queries, mainly when forwarding, not when
|
||||
routing packets. To detect this, when timeouts keep happening, as the
|
||||
timeout approached 5-10 seconds, and EDNS status has not been detected yet,
|
||||
a single probe query is sent. This probe has a sub-second timeout, and
|
||||
if the server responds (quickly) without EDNS, this is cached for 15 min.
|
||||
This works very well when detecting an address that you use much - like
|
||||
a forwarder address - which is where the middleboxes need to be detected.
|
||||
Otherwise, it results in a 5 second wait time before EDNS timeout is
|
||||
detected, which is slow but it works at least.
|
||||
It minimizes the chances of a dropped query making a (DNSSEC) EDNS server
|
||||
falsely EDNS-nonsupporting, and thus DNSSEC-bogus, works well with
|
||||
middleboxes, and can detect the occasional authority that drops EDNS.
|
||||
For some boxes it is necessary to probe for every failing query, a
|
||||
reassurance that the DNS server does EDNS does not mean that path can
|
||||
take large DNS answers.
|
||||
|
||||
o 0x20 backoff.
|
||||
The draft describes to back off to the next server, and go through all
|
||||
servers several times. Unbound goes on get the full list of nameserver
|
||||
addresses, and then makes 3 * number of addresses queries.
|
||||
They are sent to a random server, but no one address more than 4 times.
|
||||
It succeeds if one has 0x20 intact, or else all are equal.
|
||||
Otherwise, servfail is returned to the client.
|
||||
|
||||
o NXDOMAIN and SOA serial numbers.
|
||||
Unbound keeps TTL values for message formats, and thus rcodes, such
|
||||
as NXDOMAIN. Also it keeps the latest rrsets in the rrset cache.
|
||||
So it will faithfully negative cache for the exact TTL as originally
|
||||
specified for an NXDOMAIN message, but send a newer SOA record if
|
||||
this has been found in the mean time. In point, this could lead to a
|
||||
negative cached NXDOMAIN reply with a SOA RR where the serial number
|
||||
indicates a zone version where this domain is not any longer NXDOMAIN.
|
||||
These situations become consistent once the original TTL expires.
|
||||
If the domain is DNSSEC signed, by the way, then NSEC records are
|
||||
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,14 +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 ]
|
||||
.IR cfgfile
|
||||
.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.
|
||||
@@ -28,15 +30,19 @@ The available options are:
|
||||
.B \-h
|
||||
Show the version and commandline option help.
|
||||
.TP
|
||||
.B \-o\fI option
|
||||
If given, after checking the config file the value of this option is
|
||||
printed to stdout. For "" (disabled) options an empty line is printed.
|
||||
.TP
|
||||
.I cfgfile
|
||||
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
|
||||
.I /usr/local/etc/unbound/unbound.conf
|
||||
.I @ub_conf_file@
|
||||
unbound configuration file.
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound.conf\fR(5),
|
||||
@@ -0,0 +1,415 @@
|
||||
.TH "unbound-control" "8" "@date@" "NLnet Labs" "unbound @version@"
|
||||
.\"
|
||||
.\" unbound-control.8 -- unbound remote control manual
|
||||
.\"
|
||||
.\" Copyright (c) 2008, NLnet Labs. All rights reserved.
|
||||
.\"
|
||||
.\" See LICENSE for the license.
|
||||
.\"
|
||||
.\"
|
||||
.SH "NAME"
|
||||
.LP
|
||||
.B unbound\-control,
|
||||
.B unbound\-control\-setup
|
||||
\- Unbound remote server control utility.
|
||||
.SH "SYNOPSIS"
|
||||
.B unbound\-control
|
||||
.RB [ \-h ]
|
||||
.RB [ \-c
|
||||
.IR cfgfile ]
|
||||
.RB [ \-s
|
||||
.IR server ]
|
||||
.IR command
|
||||
.SH "DESCRIPTION"
|
||||
.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.
|
||||
.P
|
||||
The available options are:
|
||||
.TP
|
||||
.B \-h
|
||||
Show the version and commandline option help.
|
||||
.TP
|
||||
.B \-c \fIcfgfile
|
||||
The config file to read with settings. If not given the default
|
||||
config file @ub_conf_file@ is used.
|
||||
.TP
|
||||
.B \-s \fIserver[@port]
|
||||
IPv4 or IPv6 address of the server to contact. If not given, the
|
||||
address is read from the config file.
|
||||
.SH "COMMANDS"
|
||||
There are several commands that the server understands.
|
||||
.TP
|
||||
.B start
|
||||
Start the server. Simply execs \fIunbound\fR(8). The unbound executable
|
||||
is searched for in the \fBPATH\fR set in the environment. It is started
|
||||
with the config file specified using \fI\-c\fR or the default config file.
|
||||
.TP
|
||||
.B stop
|
||||
Stop the server. The server daemon exits.
|
||||
.TP
|
||||
.B reload
|
||||
Reload the server. This flushes the cache and reads the config file fresh.
|
||||
.TP
|
||||
.B verbosity \fInumber
|
||||
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.
|
||||
Statistics are printed with one [name]: [value] per line.
|
||||
.TP
|
||||
.B stats_noreset
|
||||
Peek at statistics. Prints them like the \fBstats\fR command does, but does not
|
||||
reset the internal counters to zero.
|
||||
.TP
|
||||
.B status
|
||||
Display server status. Exit code 3 if not running (the connection to the
|
||||
port is refused), 1 on error, 0 if running.
|
||||
.TP
|
||||
.B local_zone \fIname\fR \fItype
|
||||
Add new local zone with name and type. Like \fBlocal\-zone\fR config statement.
|
||||
If the zone already exists, the type is changed to the given argument.
|
||||
.TP
|
||||
.B local_zone_remove \fIname
|
||||
Remove the local zone with the given name. Removes all local data inside
|
||||
it. If the zone does not exist, the command succeeds.
|
||||
.TP
|
||||
.B local_data \fIRR data...
|
||||
Add new local data, the given resource record. Like \fBlocal\-data\fR
|
||||
config statement, except for when no covering zone exists. In that case
|
||||
this remote control command creates a transparent zone with the same
|
||||
name as this record. This command is not good at returning detailed syntax
|
||||
errors.
|
||||
.TP
|
||||
.B local_data_remove \fIname
|
||||
Remove all RR data from local name. If the name already has no items,
|
||||
nothing happens. Often results in NXDOMAIN for the name (in a static zone),
|
||||
but if the name has become an empty nonterminal (there is still data in
|
||||
domain names below the removed name), NOERROR nodata answers are the
|
||||
result for that name.
|
||||
.TP
|
||||
.B dump_cache
|
||||
The contents of the cache is printed in a text format to stdout. You can
|
||||
redirect it to a file to store the cache in a file.
|
||||
.TP
|
||||
.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. 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
|
||||
name specified.
|
||||
.TP
|
||||
.B flush \fIname
|
||||
Remove the name from the cache. Removes the types
|
||||
A, AAAA, NS, SOA, CNAME, DNAME, MX, PTR, SRV and NAPTR.
|
||||
Because that is fast to do. Other record types can be removed using
|
||||
.B flush_type
|
||||
or
|
||||
.B flush_zone\fR.
|
||||
.TP
|
||||
.B flush_type \fIname\fR \fItype
|
||||
Remove the name, type information from the cache.
|
||||
.TP
|
||||
.B flush_zone \fIname
|
||||
Remove all information at or below the name from the cache.
|
||||
The rrsets and key entries are removed so that new lookups will be performed.
|
||||
This needs to walk and inspect the entire cache, and is a slow operation.
|
||||
.TP
|
||||
.B flush_stats
|
||||
Reset statistics to zero.
|
||||
.TP
|
||||
.B flush_requestlist
|
||||
Drop the queries that are worked on. Stops working on the queries that the
|
||||
server is working on now. The cache is unaffected. No reply is sent for
|
||||
those queries, probably making those users request again later.
|
||||
Useful to make the server restart working on queries with new settings,
|
||||
such as a higher verbosity level.
|
||||
.TP
|
||||
.B dump_requestlist
|
||||
Show what is worked on. Prints all queries that the server is currently
|
||||
working on. Prints the time that users have been waiting. For internal
|
||||
requests, no time is printed. And then prints out the module status.
|
||||
.TP
|
||||
.B flush_infra \fIall|IP
|
||||
If all then entire infra cache is emptied. If a specific IP address, the
|
||||
entry for that address is removed from the cache. It contains EDNS, ping
|
||||
and lameness data.
|
||||
.TP
|
||||
.B dump_infra
|
||||
Show the contents of the infra cache.
|
||||
.TP
|
||||
.B set_option \fIopt: val
|
||||
Set the option to the given value without a reload. The cache is therefore
|
||||
not flushed. The option must end with a ':' and whitespace must be between the
|
||||
option and the value. Some values may not have an effect if set this way,
|
||||
the new values are not written to the config file, not all options are supported.
|
||||
.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.
|
||||
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
|
||||
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
|
||||
queries to. The addresses must be separated with spaces. With '@port' the
|
||||
port number can be set explicitly (default port is 53 (DNS)).
|
||||
.IP
|
||||
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.
|
||||
.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
|
||||
or as root, so that the daemon is permitted to read the files, for example with:
|
||||
.nf
|
||||
sudo \-u unbound unbound\-control\-setup
|
||||
.fi
|
||||
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
|
||||
\fIunbound.conf\fR.
|
||||
.SH "STATISTIC COUNTERS"
|
||||
The \fIstats\fR command shows a number of statistic counters.
|
||||
.TP
|
||||
.I threadX.num.queries
|
||||
number of queries received by thread
|
||||
.TP
|
||||
.I threadX.num.cachehits
|
||||
number of queries that were successfully answered using a cache lookup
|
||||
.TP
|
||||
.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
|
||||
.I threadX.requestlist.avg
|
||||
The average number of requests in the internal recursive processing request list on insert of a new incoming recursive processing query.
|
||||
.TP
|
||||
.I threadX.requestlist.max
|
||||
Maximum size attained by the internal recursive processing request list.
|
||||
.TP
|
||||
.I threadX.requestlist.overwritten
|
||||
Number of requests in the request list that were overwritten by newer entries. This happens if there is a flood of queries that recursive processing and the server has a hard time.
|
||||
.TP
|
||||
.I threadX.requestlist.exceeded
|
||||
Queries that were dropped because the request list was full. This happens if a flood of queries need recursive processing, and the server can not keep up.
|
||||
.TP
|
||||
.I threadX.requestlist.current.all
|
||||
Current size of the request list, includes internally generated queries (such
|
||||
as priming queries and glue lookups).
|
||||
.TP
|
||||
.I threadX.requestlist.current.user
|
||||
Current size of the request list, only the requests from client queries.
|
||||
.TP
|
||||
.I threadX.recursion.time.avg
|
||||
Average time it took to answer queries that needed recursive processing. Note that queries that were answered from the cache are not in this average.
|
||||
.TP
|
||||
.I threadX.recursion.time.median
|
||||
The median of the time it took to answer queries that needed recursive
|
||||
processing. The median means that 50% of the user queries were answered in
|
||||
less than this time. Because of big outliers (usually queries to non
|
||||
responsive servers), the average can be bigger than the median. This median
|
||||
has been calculated by interpolation from a histogram.
|
||||
.TP
|
||||
.I total.num.queries
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.cachehits
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.cachemiss
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.prefetch
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.recursivereplies
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.requestlist.avg
|
||||
averaged over threads.
|
||||
.TP
|
||||
.I total.requestlist.max
|
||||
the maximum of the thread requestlist.max values.
|
||||
.TP
|
||||
.I total.requestlist.overwritten
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.requestlist.exceeded
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.requestlist.current.all
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.recursion.time.median
|
||||
averaged over threads.
|
||||
.TP
|
||||
.I time.now
|
||||
current time in seconds since 1970.
|
||||
.TP
|
||||
.I time.up
|
||||
uptime since server boot in seconds.
|
||||
.TP
|
||||
.I time.elapsed
|
||||
time since last statistics printout, in seconds.
|
||||
.SH EXTENDED STATISTICS
|
||||
.TP
|
||||
.I mem.total.sbrk
|
||||
If sbrk(2) is available, an estimate of the heap size of the program in number of bytes. Close to the total memory used by the program, as reported by top and ps. Could be wrong if the OS allocates memory non\-contiguously.
|
||||
.TP
|
||||
.I mem.cache.rrset
|
||||
Memory in bytes in use by the RRset cache.
|
||||
.TP
|
||||
.I mem.cache.message
|
||||
Memory in bytes in use by the message cache.
|
||||
.TP
|
||||
.I mem.mod.iterator
|
||||
Memory in bytes in use by the iterator module.
|
||||
.TP
|
||||
.I mem.mod.validator
|
||||
Memory in bytes in use by the validator module. Includes the key cache and
|
||||
negative cache.
|
||||
.TP
|
||||
.I histogram.<sec>.<usec>.to.<sec>.<usec>
|
||||
Shows a histogram, summed over all threads. Every element counts the
|
||||
recursive queries whose reply time fit between the lower and upper bound.
|
||||
Times larger or equal to the lowerbound, and smaller than the upper bound.
|
||||
There are 40 buckets, with bucket sizes doubling.
|
||||
.TP
|
||||
.I num.query.type.A
|
||||
The total number of queries over all threads with query type A.
|
||||
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.
|
||||
.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.
|
||||
.TP
|
||||
.I num.query.opcode.QUERY
|
||||
The total number of queries over all threads with query opcode QUERY.
|
||||
Also printed for other opcodes, UPDATE, ...
|
||||
.TP
|
||||
.I num.query.tcp
|
||||
Number of queries that were made using TCP towards the unbound server.
|
||||
.TP
|
||||
.I num.query.ipv6
|
||||
Number of queries that were made using IPv6 towards the unbound server.
|
||||
.TP
|
||||
.I num.query.flags.RD
|
||||
The number of queries that had the RD flag set in the header.
|
||||
Also printed for flags QR, AA, TC, RA, Z, AD, CD.
|
||||
Note that queries with flags QR, AA or TC may have been rejected
|
||||
because of that.
|
||||
.TP
|
||||
.I num.query.edns.present
|
||||
number of queries that had an EDNS OPT record present.
|
||||
.TP
|
||||
.I num.query.edns.DO
|
||||
number of queries that had an EDNS OPT record with the DO (DNSSEC OK) bit set.
|
||||
These queries are also included in the num.query.edns.present number.
|
||||
.TP
|
||||
.I num.answer.rcode.NXDOMAIN
|
||||
The number of answers to queries, from cache or from recursion, that had the
|
||||
return code NXDOMAIN. Also printed for the other return codes.
|
||||
.TP
|
||||
.I num.answer.rcode.nodata
|
||||
The number of answers to queries that had the pseudo return code nodata.
|
||||
This means the actual return code was NOERROR, but additionally, no data was
|
||||
carried in the answer (making what is called a NOERROR/NODATA answer).
|
||||
These queries are also included in the num.answer.rcode.NOERROR number.
|
||||
Common for AAAA lookups when an A record exists, and no AAAA.
|
||||
.TP
|
||||
.I num.answer.secure
|
||||
Number of answers that were secure. The answer validated correctly.
|
||||
The AD bit might have been set in some of these answers, where the client
|
||||
signalled (with DO or AD bit in the query) that they were ready to accept
|
||||
the AD bit in the answer.
|
||||
.TP
|
||||
.I num.answer.bogus
|
||||
Number of answers that were bogus. These answers resulted in SERVFAIL
|
||||
to the client because the answer failed validation.
|
||||
.TP
|
||||
.I num.rrset.bogus
|
||||
The number of rrsets marked bogus by the validator. Increased for every
|
||||
RRset inspection that fails.
|
||||
.TP
|
||||
.I unwanted.queries
|
||||
Number of queries that were refused or dropped because they failed the
|
||||
access control settings.
|
||||
.TP
|
||||
.I unwanted.replies
|
||||
Replies that were unwanted or unsolicited. Could have been random traffic,
|
||||
delayed duplicates, very late answers, or could be spoofing attempts.
|
||||
Some low level of late answers and delayed duplicates are to be expected
|
||||
with the UDP protocol. Very high values could indicate a threat (spoofing).
|
||||
.SH "FILES"
|
||||
.TP
|
||||
.I @ub_conf_file@
|
||||
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).
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound\fR(8).
|
||||
+17
-1
@@ -14,7 +14,7 @@
|
||||
.SH "SYNOPSIS"
|
||||
.LP
|
||||
.B unbound\-host
|
||||
.RB [ \-vdh ]
|
||||
.RB [ \-vdhr46 ]
|
||||
.RB [ \-c
|
||||
.IR class ]
|
||||
.RB [ \-t
|
||||
@@ -35,6 +35,10 @@ uses the unbound validating resolver to query for the hostname and display
|
||||
results. With the \fB\-v\fR option it displays validation
|
||||
status: secure, insecure, bogus (security failure).
|
||||
.P
|
||||
By default it reads no configuration file whatsoever. It attempts to reach
|
||||
the internet root servers. With \fB\-C\fR an unbound config file and with
|
||||
\fB\-r\fR resolv.conf can be read.
|
||||
.P
|
||||
The available options are:
|
||||
.TP
|
||||
.I hostname
|
||||
@@ -81,6 +85,18 @@ are read.
|
||||
.B \-C \fIconfigfile
|
||||
Uses the specified unbound.conf to prime
|
||||
.IR libunbound (3).
|
||||
.TP
|
||||
.B \-r
|
||||
Read /etc/resolv.conf, and use the forward DNS servers from there (those could
|
||||
have been set by DHCP). More info in
|
||||
.IR resolv.conf (5).
|
||||
Breaks validation if those servers do not support DNSSEC.
|
||||
.TP
|
||||
.B \-4
|
||||
Use solely the IPv4 network for sending packets.
|
||||
.TP
|
||||
.B \-6
|
||||
Use solely the IPv6 network for sending packets.
|
||||
.SH "EXAMPLES"
|
||||
.LP
|
||||
Some examples of use. The keys shown below are fakes, thus a security failure
|
||||
|
||||
@@ -31,8 +31,8 @@ The available options are:
|
||||
Show the version and commandline option help.
|
||||
.TP
|
||||
.B \-c\fI cfgfile
|
||||
Set the config file with settings for unbound to read instead of the
|
||||
file at default location /usr/local/etc/unbound/unbound.conf. The syntax is
|
||||
Set the config file with settings for unbound to read instead of reading the
|
||||
file at the default location, @ub_conf_file@. The syntax is
|
||||
described in \fIunbound.conf\fR(5).
|
||||
.TP
|
||||
.B \-d
|
||||
@@ -49,7 +49,11 @@ example.conf file with all the options.
|
||||
# unbound.conf(5) config file for unbound(8).
|
||||
server:
|
||||
directory: "/etc/unbound"
|
||||
username: unbound # make sure it can write to pidfile.
|
||||
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
|
||||
chroot: "/etc/unbound"
|
||||
# logfile: "/etc/unbound/unbound.log" #uncomment to use logfile.
|
||||
pidfile: "/etc/unbound/unbound.pid"
|
||||
@@ -69,7 +73,10 @@ Files can be included using the
|
||||
.B include:
|
||||
directive. It can appear anywhere, and takes a single filename as an argument.
|
||||
Processing continues as if the text from the included file was copied into
|
||||
the config file at that point.
|
||||
the config file at that point. If also using chroot, using full path names
|
||||
for the included files works, relative pathnames for the included names work
|
||||
if the directory where the daemon is started equals its chroot/working
|
||||
directory.
|
||||
.SS "Server Options"
|
||||
These options are part of the
|
||||
.B server:
|
||||
@@ -79,37 +86,46 @@ clause.
|
||||
The verbosity number, level 0 means no verbosity, only errors. Level 1
|
||||
gives operational information. Level 2 gives detailed operational
|
||||
information. Level 3 gives query level information, output per query.
|
||||
Level 4 gives algorithm level information.
|
||||
Default is level 1. The verbosity can also be increased from the commandline,
|
||||
see
|
||||
\fIunbound\fR(8).
|
||||
Level 4 gives algorithm level information. Level 5 logs client
|
||||
identification for cache misses. Default is level 1.
|
||||
The verbosity can also be increased from the commandline, see \fIunbound\fR(8).
|
||||
.TP
|
||||
.B statistics-interval: \fI<seconds>
|
||||
.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>
|
||||
.B statistics\-cumulative: \fI<yes or no>
|
||||
If enabled, statistics are cumulative since starting unbound, without clearing
|
||||
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. 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.
|
||||
.TP
|
||||
.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
|
||||
@@ -124,22 +140,29 @@ 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
|
||||
and subtracting the avoided ports from the set of allowed ports. The
|
||||
processing starts with the non IANA allocated ports above 1024 in the set
|
||||
of allowed ports.
|
||||
.TP
|
||||
.B outgoing\-port\-avoid: \fI<port number or range>
|
||||
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
|
||||
@@ -149,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
|
||||
@@ -168,9 +202,34 @@ reasonable guess.
|
||||
.TP
|
||||
.B num\-queries\-per\-thread: \fI<number>
|
||||
The number of queries that every thread will service simultaneously.
|
||||
If more queries arrive that need servicing, they are dropped. This forces
|
||||
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
|
||||
results in one roundtrip to the authority servers. If too many queries
|
||||
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.
|
||||
@@ -189,6 +248,14 @@ When the internal TTL expires, the cache item has expired.
|
||||
Can be set lower to force the resolver to query for data often, and not
|
||||
trust (very large) TTL values.
|
||||
.TP
|
||||
.B cache\-min\-ttl: \fI<seconds>
|
||||
Time to live minimum for RRsets and messages in the cache. Default is 0.
|
||||
If the the minimum kicks in, the data is cached for longer than the domain
|
||||
owner intended, and thus less queries are made to look up the data.
|
||||
Zero makes sure the data in the cache is as the domain owner intended,
|
||||
higher values, especially more than an hour or so, can lead to trouble as
|
||||
the data in the cache does not match up with the actual data any more.
|
||||
.TP
|
||||
.B infra\-host\-ttl: \fI<seconds>
|
||||
Time to live for entries in the host cache. The host cache contains
|
||||
roundtrip timing and EDNS support information. Default is 900.
|
||||
@@ -228,14 +295,36 @@ a daemon. Default is yes.
|
||||
.TP
|
||||
.B access\-control: \fI<IP netblock> <action>
|
||||
The netblock is given as an IP4 or IP6 address with /size appended for a
|
||||
classless network block. The action can be deny, refuse or allow.
|
||||
Deny stops queries from hosts from that netblock.
|
||||
Refuse stops queries too, but sends a DNS rcode REFUSED error message back.
|
||||
Allow gives access to clients from that netblock.
|
||||
By default only localhost is allowed, the rest is refused.
|
||||
The default is refused, because that is protocol\-friendly. The DNS protocol
|
||||
is not designed to handle dropped packets due to policy, and dropping may
|
||||
result in (possibly excessive) retried queries.
|
||||
classless network block. The action can be \fIdeny\fR, \fIrefuse\fR,
|
||||
\fIallow\fR or \fIallow_snoop\fR.
|
||||
.IP
|
||||
The action \fIdeny\fR stops queries from hosts from that netblock.
|
||||
.IP
|
||||
The action \fIrefuse\fR stops queries too, but sends a DNS rcode REFUSED
|
||||
error message back.
|
||||
.IP
|
||||
The action \fIallow\fR gives access to clients from that netblock.
|
||||
It gives only access for recursion clients (which is
|
||||
what almost all clients need). Nonrecursive queries are refused.
|
||||
.IP
|
||||
The \fIallow\fR action does allow nonrecursive queries to access the
|
||||
local\-data that is configured. The reason is that this does not involve
|
||||
the unbound server recursive lookup algorithm, and static data is served
|
||||
in the reply. This supports normal operations where nonrecursive queries
|
||||
are made for the authoritative data. For nonrecursive queries any replies
|
||||
from the dynamic cache are refused.
|
||||
.IP
|
||||
The action \fIallow_snoop\fR gives nonrecursive access too. This give
|
||||
both recursive and non recursive access. The name \fIallow_snoop\fR refers
|
||||
to cache snooping, a technique to use nonrecursive queries to examine
|
||||
the cache contents (for malicious acts). However, nonrecursive queries can
|
||||
also be a valuable debugging tool (when you want to examine the cache
|
||||
contents). In that case use \fIallow_snoop\fR for your administration host.
|
||||
.IP
|
||||
By default only localhost is \fIallow\fRed, the rest is \fIrefuse\fRd.
|
||||
The default is \fIrefuse\fRd, because that is protocol\-friendly. The DNS
|
||||
protocol is not designed to handle dropped packets due to policy, and
|
||||
dropping may result in (possibly excessive) retried queries.
|
||||
.TP
|
||||
.B chroot: \fI<directory>
|
||||
If chroot is enabled, you should pass the configfile (from the
|
||||
@@ -243,22 +332,27 @@ commandline) as a full path from the original root. After the
|
||||
chroot has been performed the now defunct portion of the config
|
||||
file path is removed to be able to reread the config after a reload.
|
||||
.IP
|
||||
All other file paths (working dir, pidfile, logfile, roothints,
|
||||
All other file paths (working dir, logfile, roothints, and
|
||||
key files) can be specified in several ways:
|
||||
as an absolute path relative to the new root,
|
||||
as a relative path to the working directory, or
|
||||
as an absolute path relative to the original root.
|
||||
In the last case the path is adjusted to remove the unused portion.
|
||||
.IP
|
||||
The pidfile can be either a relative path to the working directory, or
|
||||
an absolute path relative to the original root. It is written just prior
|
||||
to chroot and dropping permissions. This allows the pidfile to be
|
||||
/var/run/unbound.pid and the chroot to be /var/unbound, for example.
|
||||
.IP
|
||||
Additionally, unbound may need to access /dev/random (for entropy)
|
||||
and to /dev/log (if you use syslog) from inside the chroot.
|
||||
from inside the chroot.
|
||||
.IP
|
||||
If given a chroot is done to the given directory. The default is
|
||||
"/usr/local/etc/unbound". If you give "" no chroot is performed.
|
||||
"@UNBOUND_CHROOT_DIR@". If you give "" no chroot is performed.
|
||||
.TP
|
||||
.B username: \fI<name>
|
||||
If given, after binding the port the user privileges are dropped. Default is
|
||||
"unbound". If you give username: "" no user change is performed.
|
||||
"@UNBOUND_USERNAME@". If you give username: "" no user change is performed.
|
||||
.IP
|
||||
If this user is not capable of binding the
|
||||
port, reloads (by signal HUP) will still retain the opened ports.
|
||||
@@ -266,7 +360,7 @@ If you change the port number in the config file, and that new port number
|
||||
requires privileges, then a reload will fail; a restart is needed.
|
||||
.TP
|
||||
.B directory: \fI<directory>
|
||||
Sets the working directory for the program.
|
||||
Sets the working directory for the program. Default is "@UNBOUND_RUN_DIR@".
|
||||
.TP
|
||||
.B logfile: \fI<filename>
|
||||
If "" is given, logging goes to stderr, or nowhere once daemonized.
|
||||
@@ -285,15 +379,20 @@ The log facility LOG_DAEMON is used, with identity "unbound".
|
||||
The logfile setting is overridden when use\-syslog is turned on.
|
||||
The default is to log to syslog.
|
||||
.TP
|
||||
.B log\-time\-ascii: \fI<yes or no>
|
||||
Sets logfile lines to use a timestamp in UTC ascii. Default is no, which
|
||||
prints the seconds since 1970 in brackets. No effect if using syslog, in
|
||||
that case syslog formats the timestamp printed into the log files.
|
||||
.TP
|
||||
.B pidfile: \fI<filename>
|
||||
The process id is written to the file. Default is "/usr/local/etc/unbound/unbound.pid".
|
||||
The process id is written to the file. Default is "@UNBOUND_PIDFILE@".
|
||||
So,
|
||||
.nf
|
||||
kill \-HUP `cat /usr/local/etc/unbound/unbound.pid`
|
||||
kill \-HUP `cat @UNBOUND_PIDFILE@`
|
||||
.fi
|
||||
triggers a reload,
|
||||
.nf
|
||||
kill \-QUIT `cat /usr/local/etc/unbound/unbound.pid`
|
||||
kill \-QUIT `cat @UNBOUND_PIDFILE@`
|
||||
.fi
|
||||
gracefully terminates.
|
||||
.TP
|
||||
@@ -356,15 +455,55 @@ removes DNSSEC data from packets, or a zone changes from signed to
|
||||
unsigned to badly signed often. If turned off you run the risk of a
|
||||
downgrade attack that disables security for a zone. Default is on.
|
||||
.TP
|
||||
.B harden\-referral\-path: \fI<yes or no>
|
||||
Harden the referral path by performing additional queries for
|
||||
infrastructure data. Validates the replies if trust anchors are configured
|
||||
and the zones are signed. This enforces DNSSEC validation on nameserver
|
||||
NS sets and the nameserver addresses that are encountered on the referral
|
||||
path to the answer.
|
||||
Default off, because it burdens the authority servers, and it is
|
||||
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, because some caching forwarders may not
|
||||
support this. It is known that some authority servers do not support 0x20,
|
||||
and resolution will fail for them. A solution is on the TODO list.
|
||||
Disabled by default.
|
||||
This feature is an experimental implementation of draft dns\-0x20.
|
||||
.TP
|
||||
.B private\-address: \fI<IP address or subnet>
|
||||
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
|
||||
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
|
||||
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 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.
|
||||
.TP
|
||||
.B private\-domain: \fI<domain name>
|
||||
Allow this domain, and all its subdomains to contain private addresses.
|
||||
Give multiple times to allow multiple domain names to contain private
|
||||
addresses. Default is none.
|
||||
.TP
|
||||
.B unwanted\-reply\-threshold: \fI<number>
|
||||
If set, a total number of unwanted replies is kept track of in every thread.
|
||||
When it reaches the threshold, a defensive action is taken and a warning
|
||||
is printed to the log. The defensive action is to clear the rrset and
|
||||
message caches, hopefully flushing away any poison. A value of 10 million
|
||||
is suggested. Default is 0 (turned off).
|
||||
.TP
|
||||
.B do\-not\-query\-address: \fI<IP address>
|
||||
Do not query the given IP address. Can be IP4 or IP6. Append /num to
|
||||
indicate a classless delegation netblock, for example like
|
||||
@@ -375,11 +514,23 @@ 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.
|
||||
Setting this to "iterator" will result in a non\-validating server.
|
||||
Setting this to "validator iterator" will turn on DNSSEC validation.
|
||||
The ordering of the modules is important.
|
||||
You must also set trust\-anchors for validation to be useful.
|
||||
.TP
|
||||
.B trust\-anchor\-file: \fI<filename>
|
||||
@@ -387,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.
|
||||
@@ -400,6 +558,31 @@ File with trusted keys for validation. Specify more than one file
|
||||
with several entries, one file per entry. Like \fBtrust\-anchor\-file\fR
|
||||
but has a different file format. Format is BIND\-9 style format,
|
||||
the trusted\-keys { name flag proto algo "key"; }; clauses are read.
|
||||
It is possible to use wildcards with this statement, the wildcard is
|
||||
expanded on start and on reload.
|
||||
.TP
|
||||
.B dlv\-anchor\-file: \fI<filename>
|
||||
File with trusted keys for DLV (DNSSEC Lookaside Validation). Both DS and
|
||||
DNSKEY entries can be used in the file, in the same format as for
|
||||
\fItrust\-anchor\-file:\fR statements. Only one DLV can be configured, more
|
||||
would be slow. The DLV configured is used as a root trusted DLV, this
|
||||
means that it is a lookaside for the root. Default is "", or no dlv anchor file.
|
||||
.TP
|
||||
.B dlv\-anchor: \fI<"Resource Record">
|
||||
Much like trust\-anchor, this is a DLV anchor with the DS or DNSKEY inline.
|
||||
.TP
|
||||
.B domain\-insecure: \fI<domain name>
|
||||
Sets domain name to be insecure, DNSSEC chain of trust is ignored towards
|
||||
the domain name. So a trust anchor above the domain name can not make the
|
||||
domain secure with a DS record, such a DS record is then ignored.
|
||||
Also keys from DLV are ignored for the domain. Can be given multiple times
|
||||
to specify multiple domains that are treated as if unsigned. If you set
|
||||
trust anchors for the domain they override this setting (and the domain
|
||||
is secured).
|
||||
.IP
|
||||
This can be useful if you want to make sure a trust anchor for external
|
||||
lookups does not affect an (unsigned) internal domain. A DS record
|
||||
externally can create validation failures for that internal domain.
|
||||
.TP
|
||||
.B val\-override\-date: \fI<rrsig\-style date spec>
|
||||
Default is "" or "0", which disables this debugging feature. If enabled by
|
||||
@@ -407,10 +590,26 @@ giving a RRSIG style date, that date is used for verifying RRSIG inception
|
||||
and expiration dates, instead of the current date. Do not set this unless
|
||||
you are debugging signature inception and expiration.
|
||||
.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 (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 (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;
|
||||
due to invalid signatures or other checks. The TTL from that data cannot be
|
||||
trusted, and this value is used instead. The value is in seconds, default 900.
|
||||
trusted, and this value is used instead. The value is in seconds, default 60.
|
||||
The time interval prevents repeated revalidation of bogus data.
|
||||
.TP
|
||||
.B val\-clean\-additional: \fI<yes or no>
|
||||
@@ -420,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
|
||||
@@ -437,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
|
||||
@@ -447,6 +675,11 @@ Number of slabs in the key cache. Slabs reduce lock contention by threads.
|
||||
Must be set to a power of 2. Setting (close) to the number of cpus is a
|
||||
reasonable guess.
|
||||
.TP
|
||||
.B neg\-cache\-size: \fI<number>
|
||||
Number of bytes size of the aggressive negative cache. Default is 1 megabyte.
|
||||
A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes
|
||||
or gigabytes (1024*1024 bytes in a megabyte).
|
||||
.TP
|
||||
.B local\-zone: \fI<zone> <type>
|
||||
Configure a local zone. The type determines the answer to give if there is
|
||||
no match from local\-data. The types are deny, refuse, static, transparent,
|
||||
@@ -474,19 +707,23 @@ as local\-data for the zone apex domain.
|
||||
.TP 10
|
||||
\h'5'\fItransparent\fR
|
||||
If there is a match from local data, the query is answered.
|
||||
Otherwise, the query is resolved normally.
|
||||
Otherwise if the query has a different name, the query is resolved normally.
|
||||
If the query is for a name given in localdata but no such type of data is
|
||||
given in localdata, then a noerror nodata answer is returned.
|
||||
If no local\-zone is given local\-data causes a transparent zone
|
||||
to be created by default.
|
||||
.TP 10
|
||||
\h'5'\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
|
||||
@@ -549,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
|
||||
@@ -563,6 +801,16 @@ Reverse data for zone D.F.ip6.arpa.
|
||||
.TP 10
|
||||
\h'5'\fIreverse RFC4291 IPv6 Link Local Addresses\fR
|
||||
Reverse data for zones 8.E.F.ip6.arpa to B.E.F.ip6.arpa.
|
||||
.TP 10
|
||||
\h'5'\fIreverse IPv6 Example Prefix\fR
|
||||
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
|
||||
.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
|
||||
.B local\-data: \fI"<resource record string>"
|
||||
@@ -577,12 +825,65 @@ local\-data: 'example. TXT "text"'.
|
||||
If you need more complicated authoritative data, with referrals, wildcards,
|
||||
CNAME/DNAME support, or DNSSEC authoritative service, setup a stub\-zone for
|
||||
it as detailed in the stub zone section below.
|
||||
.TP 5
|
||||
.B local\-data\-ptr: \fI"IPaddr name"
|
||||
Configure local data shorthand for a PTR record with the reversed IPv4 or
|
||||
IPv6 address and the host name. For example "192.0.2.4 www.example.com".
|
||||
TTL can be inserted like this: "2001:DB8::4 7200 www.example.com"
|
||||
.SS "Remote Control Options"
|
||||
In the
|
||||
.B remote\-control:
|
||||
clause are the declarations for the remote control facility. If this is
|
||||
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
|
||||
\fIunbound\-control\-setup\fR(8) utility.
|
||||
.TP 5
|
||||
.B control\-enable: \fI<yes or no>
|
||||
The option is used to enable remote control, default is "no".
|
||||
If turned off, the server does not listen for control commands.
|
||||
.TP 5
|
||||
.B control\-interface: <ip address>
|
||||
Give IPv4 or IPv6 addresses to listen on for control commands.
|
||||
By default localhost (127.0.0.1 and ::1) is listened to.
|
||||
Use 0.0.0.0 and ::0 to listen to all interfaces.
|
||||
.TP 5
|
||||
.B control\-port: <port number>
|
||||
The port number to listen on for control commands, default is 953
|
||||
(that is the same port number named uses to listen to rndc).
|
||||
If you change this port number, and permissions have been dropped, a
|
||||
reload is not sufficient to open the port again, you must then restart.
|
||||
.TP 5
|
||||
.B server\-key\-file: "<private key file>"
|
||||
Path to the server private key, by default unbound_server.key.
|
||||
This file is generated by the \fIunbound\-control\-setup\fR utility.
|
||||
This file is used by the unbound server, but not by \fIunbound\-control\fR.
|
||||
.TP 5
|
||||
.B server\-cert\-file: "<certificate file.pem>"
|
||||
Path to the server self signed certificate, by default unbound_server.pem.
|
||||
This file is generated by the \fIunbound\-control\-setup\fR utility.
|
||||
This file is used by the unbound server, and also by \fIunbound\-control\fR.
|
||||
.TP 5
|
||||
.B control\-key\-file: "<private key file>"
|
||||
Path to the control client private key, by default unbound_control.key.
|
||||
This file is generated by the \fIunbound\-control\-setup\fR utility.
|
||||
This file is used by \fIunbound\-control\fR.
|
||||
.TP 5
|
||||
.B control\-cert\-file: "<certificate file.pem>"
|
||||
Path to the control client certificate, by default unbound_control.pem.
|
||||
This certificate has to be signed with the server certificate.
|
||||
This file is generated by the \fIunbound\-control\-setup\fR utility.
|
||||
This file is used by \fIunbound\-control\fR.
|
||||
.SS "Stub Zone Options"
|
||||
.LP
|
||||
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.
|
||||
@@ -611,15 +912,26 @@ Name of stub zone nameserver. Is itself resolved before it is used.
|
||||
.B stub\-addr: \fI<IP address>
|
||||
IP address of stub zone nameserver. Can be IP 4 or IP 6.
|
||||
To use a nondefault port for DNS communication append '@' with the port number.
|
||||
.TP
|
||||
.B stub\-prime: \fI<yes or no>
|
||||
This option is by default off. If enabled it performs NS set priming,
|
||||
which is similar to root hints, where it starts using the list of nameservers
|
||||
currently published by the zone. Thus, if the hint list is slightly outdated,
|
||||
the resolver picks up a correct list online.
|
||||
.SS "Forward Zone Options"
|
||||
.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.
|
||||
@@ -630,6 +942,18 @@ Name of server to forward to. Is itself resolved before it is used.
|
||||
.B forward\-addr: \fI<IP address>
|
||||
IP address of server to forward to. Can be IP 4 or IP 6.
|
||||
To use a nondefault port for DNS communication append '@' with the port number.
|
||||
.SS "Python Module Options"
|
||||
.LP
|
||||
The
|
||||
.B python:
|
||||
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\-config:\fR option
|
||||
(usually first, or between the validator and iterator).
|
||||
.TP
|
||||
.B python\-script: \fI<python file>\fR
|
||||
The script file to load.
|
||||
.SH "MEMORY CONTROL EXAMPLE"
|
||||
In the example config settings below memory usage is reduced. Some service
|
||||
levels are lower, notable very large data and a high TCP load are no longer
|
||||
@@ -637,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
|
||||
@@ -645,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
|
||||
@@ -656,6 +980,7 @@ server:
|
||||
infra\-cache\-lame\-size: 1k
|
||||
key\-cache\-size: 100k
|
||||
key\-cache\-slabs: 1
|
||||
neg\-cache\-size: 10k
|
||||
num\-queries\-per\-thread: 30
|
||||
target\-fetch\-policy: "2 1 0 0 0 0"
|
||||
harden\-large\-queries: "yes"
|
||||
@@ -663,15 +988,18 @@ server:
|
||||
.fi
|
||||
.SH "FILES"
|
||||
.TP
|
||||
.I /usr/local/etc/unbound
|
||||
default unbound working directory and default
|
||||
.I @UNBOUND_RUN_DIR@
|
||||
default unbound working directory.
|
||||
.TP
|
||||
.I @UNBOUND_CHROOT_DIR@
|
||||
default
|
||||
\fIchroot\fR(2)
|
||||
location.
|
||||
.TP
|
||||
.I unbound.conf
|
||||
.I @ub_conf_file@
|
||||
unbound configuration file.
|
||||
.TP
|
||||
.I unbound.pid
|
||||
.I @UNBOUND_PIDFILE@
|
||||
default unbound pidfile with process ID of the running daemon.
|
||||
.TP
|
||||
.I unbound.log
|
||||
+930
-545
File diff suppressed because it is too large
Load Diff
+469
-200
@@ -1,251 +1,520 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# install - install a program, script, or datafile
|
||||
# This comes from X11R5 (mit/util/scripts/install.sh).
|
||||
|
||||
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
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright 1991 by the Massachusetts Institute of Technology
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission to use, copy, modify, distribute, and sell this software and its
|
||||
# documentation for any purpose is hereby granted without fee, provided that
|
||||
# the above copyright notice appear in all copies and that both that
|
||||
# copyright notice and this permission notice appear in supporting
|
||||
# documentation, and that the name of M.I.T. not be used in advertising or
|
||||
# publicity pertaining to distribution of the software without specific,
|
||||
# written prior permission. M.I.T. makes no representations about the
|
||||
# suitability of this software for any purpose. It is provided "as is"
|
||||
# without express or implied warranty.
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch. It can only install one file at a time, a restriction
|
||||
# shared with many OS's install programs.
|
||||
# from scratch.
|
||||
|
||||
nl='
|
||||
'
|
||||
IFS=" "" $nl"
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
transformbasename=""
|
||||
transform_arg=""
|
||||
instcmd="$mvprog"
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=""
|
||||
dst=""
|
||||
dir_arg=""
|
||||
|
||||
while [ x"$1" != x ]; do
|
||||
case $1 in
|
||||
-c) instcmd="$cpprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd="$stripprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
*) if [ x"$src" = x ]
|
||||
then
|
||||
src=$1
|
||||
else
|
||||
# this colon is to work around a 386BSD /bin/sh bug
|
||||
:
|
||||
dst=$1
|
||||
fi
|
||||
shift
|
||||
continue;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ x"$src" = x ]
|
||||
then
|
||||
echo "install: no input file specified"
|
||||
exit 1
|
||||
doit=${DOITPROG-}
|
||||
if test -z "$doit"; then
|
||||
doit_exec=exec
|
||||
else
|
||||
true
|
||||
doit_exec=$doit
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]; then
|
||||
dst=$src
|
||||
src=""
|
||||
|
||||
if [ -d $dst ]; then
|
||||
instcmd=:
|
||||
chmodcmd=""
|
||||
else
|
||||
instcmd=mkdir
|
||||
fi
|
||||
else
|
||||
# Put in absolute file names if you don't have them in your path;
|
||||
# or use environment vars.
|
||||
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
chgrpprog=${CHGRPPROG-chgrp}
|
||||
chmodprog=${CHMODPROG-chmod}
|
||||
chownprog=${CHOWNPROG-chown}
|
||||
cmpprog=${CMPPROG-cmp}
|
||||
cpprog=${CPPROG-cp}
|
||||
mkdirprog=${MKDIRPROG-mkdir}
|
||||
mvprog=${MVPROG-mv}
|
||||
rmprog=${RMPROG-rm}
|
||||
stripprog=${STRIPPROG-strip}
|
||||
|
||||
if [ -f $src -o -d $src ]
|
||||
then
|
||||
true
|
||||
else
|
||||
echo "install: $src does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$dst" = x ]
|
||||
then
|
||||
echo "install: no destination specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# If destination is a directory, append the input filename; if your system
|
||||
# does not like double slashes in filenames, you may need to add some logic
|
||||
|
||||
if [ -d $dst ]
|
||||
then
|
||||
dst="$dst"/`basename $src`
|
||||
else
|
||||
true
|
||||
fi
|
||||
fi
|
||||
|
||||
## this sed command emulates the dirname command
|
||||
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
# this part is taken from Noah Friedman's mkinstalldirs script
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if [ ! -d "$dstdir" ]; then
|
||||
defaultIFS='
|
||||
posix_glob='?'
|
||||
initialize_posix_glob='
|
||||
test "$posix_glob" != "?" || {
|
||||
if (set -f) 2>/dev/null; then
|
||||
posix_glob=
|
||||
else
|
||||
posix_glob=:
|
||||
fi
|
||||
}
|
||||
'
|
||||
IFS="${IFS-${defaultIFS}}"
|
||||
|
||||
oIFS="${IFS}"
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS="${oIFS}"
|
||||
posix_mkdir=
|
||||
|
||||
pathcomp=''
|
||||
# Desired mode of installed file.
|
||||
mode=0755
|
||||
|
||||
while [ $# -ne 0 ] ; do
|
||||
pathcomp="${pathcomp}${1}"
|
||||
shift
|
||||
chgrpcmd=
|
||||
chmodcmd=$chmodprog
|
||||
chowncmd=
|
||||
mvcmd=$mvprog
|
||||
rmcmd="$rmprog -f"
|
||||
stripcmd=
|
||||
|
||||
if [ ! -d "${pathcomp}" ] ;
|
||||
then
|
||||
$mkdirprog "${pathcomp}"
|
||||
else
|
||||
true
|
||||
fi
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dst_arg=
|
||||
|
||||
pathcomp="${pathcomp}/"
|
||||
copy_on_change=false
|
||||
no_target_directory=
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
Options:
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-c (ignored)
|
||||
-C install only if different (preserve the last data modification time)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||
RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test $# -ne 0; do
|
||||
case $1 in
|
||||
-c) ;;
|
||||
|
||||
-C) copy_on_change=true;;
|
||||
|
||||
-d) dir_arg=true;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift;;
|
||||
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) mode=$2
|
||||
case $mode in
|
||||
*' '* | *' '* | *'
|
||||
'* | *'*'* | *'?'* | *'['*)
|
||||
echo "$0: invalid mode: $mode" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift;;
|
||||
|
||||
-s) stripcmd=$stripprog;;
|
||||
|
||||
-t) dst_arg=$2
|
||||
shift;;
|
||||
|
||||
-T) no_target_directory=true;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
--) shift
|
||||
break;;
|
||||
|
||||
-*) echo "$0: invalid option: $1" >&2
|
||||
exit 1;;
|
||||
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||
# When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dst_arg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dst_arg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dst_arg=$arg
|
||||
done
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]
|
||||
then
|
||||
$doit $instcmd $dst &&
|
||||
if test $# -eq 0; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call `install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
|
||||
else
|
||||
if test -z "$dir_arg"; then
|
||||
trap '(exit $?); exit' 1 2 13 15
|
||||
|
||||
# If we're going to rename the final executable, determine the name now.
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
case $mode in
|
||||
# Optimize common cases.
|
||||
*644) cp_umask=133;;
|
||||
*755) cp_umask=22;;
|
||||
|
||||
if [ x"$transformarg" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
*[0-7])
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw='% 200'
|
||||
fi
|
||||
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||
*)
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw=,u+rw
|
||||
fi
|
||||
cp_umask=$mode$u_plus_rw;;
|
||||
esac
|
||||
fi
|
||||
|
||||
for src
|
||||
do
|
||||
# Protect names starting with `-'.
|
||||
case $src in
|
||||
-*) src=./$src;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
dstdir=$dst
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dst_arg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
dst=$dst_arg
|
||||
# Protect names starting with `-'.
|
||||
case $dst in
|
||||
-*) dst=./$dst;;
|
||||
esac
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test -n "$no_target_directory"; then
|
||||
echo "$0: $dst_arg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
dst=$dstdir/`basename "$src"`
|
||||
dstdir_status=0
|
||||
else
|
||||
# Prefer dirname, but fall back on a substitute if dirname fails.
|
||||
dstdir=`
|
||||
(dirname "$dst") 2>/dev/null ||
|
||||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$dst" : 'X\(//\)[^/]' \| \
|
||||
X"$dst" : 'X\(//\)$' \| \
|
||||
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
echo X"$dst" |
|
||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)[^/].*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\).*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
s/.*/./; q'
|
||||
`
|
||||
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
obsolete_mkdir_used=false
|
||||
|
||||
if test $dstdir_status != 0; then
|
||||
case $posix_mkdir in
|
||||
'')
|
||||
# Create intermediate dirs using mode 755 as modified by the umask.
|
||||
# This is like FreeBSD 'install' as of 1997-10-28.
|
||||
umask=`umask`
|
||||
case $stripcmd.$umask in
|
||||
# Optimize common cases.
|
||||
*[2367][2367]) mkdir_umask=$umask;;
|
||||
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
mkdir_umask=`expr $umask + 22 \
|
||||
- $umask % 100 % 40 + $umask % 20 \
|
||||
- $umask % 10 % 4 + $umask % 2
|
||||
`;;
|
||||
*) mkdir_umask=$umask,go-w;;
|
||||
esac
|
||||
|
||||
# With -d, create the new directory with the user-specified mode.
|
||||
# Otherwise, rely on $mkdir_umask.
|
||||
if test -n "$dir_arg"; then
|
||||
mkdir_mode=-m$mode
|
||||
else
|
||||
dstfile=`basename $dst $transformbasename |
|
||||
sed $transformarg`$transformbasename
|
||||
mkdir_mode=
|
||||
fi
|
||||
|
||||
# don't allow the sed command to completely eliminate the filename
|
||||
posix_mkdir=false
|
||||
case $umask in
|
||||
*[123567][0-7][0-7])
|
||||
# POSIX mkdir -p sets u+wx bits regardless of umask, which
|
||||
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||
;;
|
||||
*)
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
|
||||
if [ x"$dstfile" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
if (umask $mkdir_umask &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
|
||||
then
|
||||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibilities with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writeable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
d????-?r-*) different_mode=700;;
|
||||
d????-?--*) different_mode=755;;
|
||||
*) false;;
|
||||
esac &&
|
||||
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
|
||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||
}
|
||||
}
|
||||
then posix_mkdir=:
|
||||
fi
|
||||
rmdir "$tmpdir/d" "$tmpdir"
|
||||
else
|
||||
# Remove any dirs left behind by ancient mkdir implementations.
|
||||
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
|
||||
fi
|
||||
trap '' 0;;
|
||||
esac;;
|
||||
esac
|
||||
|
||||
if
|
||||
$posix_mkdir && (
|
||||
umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||
)
|
||||
then :
|
||||
else
|
||||
|
||||
# The umask is ridiculous, or mkdir does not conform to POSIX,
|
||||
# or it failed possibly due to a race condition. Create the
|
||||
# directory the slow way, step by step, checking for races as we go.
|
||||
|
||||
case $dstdir in
|
||||
/*) prefix='/';;
|
||||
-*) prefix='./';;
|
||||
*) prefix='';;
|
||||
esac
|
||||
|
||||
eval "$initialize_posix_glob"
|
||||
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
$posix_glob set -f
|
||||
set fnord $dstdir
|
||||
shift
|
||||
$posix_glob set +f
|
||||
IFS=$oIFS
|
||||
|
||||
prefixes=
|
||||
|
||||
for d
|
||||
do
|
||||
test -z "$d" && continue
|
||||
|
||||
prefix=$prefix$d
|
||||
if test -d "$prefix"; then
|
||||
prefixes=
|
||||
else
|
||||
true
|
||||
if $posix_mkdir; then
|
||||
(umask=$mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||
# Don't fail if two instances are running concurrently.
|
||||
test -d "$prefix" || exit 1
|
||||
else
|
||||
case $prefix in
|
||||
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||
*) qprefix=$prefix;;
|
||||
esac
|
||||
prefixes="$prefixes '$qprefix'"
|
||||
fi
|
||||
fi
|
||||
prefix=$prefix/
|
||||
done
|
||||
|
||||
# Make a temp file name in the proper directory.
|
||||
if test -n "$prefixes"; then
|
||||
# Don't fail if two instances are running concurrently.
|
||||
(umask $mkdir_umask &&
|
||||
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||
test -d "$dstdir" || exit 1
|
||||
obsolete_mkdir_used=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
if test -n "$dir_arg"; then
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||
else
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
$doit $instcmd $src $dsttmp &&
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
|
||||
trap "rm -f ${dsttmp}" 0 &&
|
||||
# Copy the file name to the temp name.
|
||||
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||
# If -C, don't bother to copy if it wouldn't change the file.
|
||||
if $copy_on_change &&
|
||||
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
|
||||
eval "$initialize_posix_glob" &&
|
||||
$posix_glob set -f &&
|
||||
set X $old && old=:$2:$4:$5:$6 &&
|
||||
set X $new && new=:$2:$4:$5:$6 &&
|
||||
$posix_glob set +f &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
test "$old" = "$new" &&
|
||||
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||
then
|
||||
rm -f "$dsttmp"
|
||||
else
|
||||
# Rename the file to the real destination.
|
||||
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||
|
||||
$doit $rmcmd -f $dstdir/$dstfile &&
|
||||
$doit $mvcmd $dsttmp $dstdir/$dstfile
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
{
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
test ! -f "$dst" ||
|
||||
$doit $rmcmd -f "$dst" 2>/dev/null ||
|
||||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
|
||||
} ||
|
||||
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
} &&
|
||||
|
||||
fi &&
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
fi || exit 1
|
||||
|
||||
trap '' 0
|
||||
fi
|
||||
done
|
||||
|
||||
exit 0
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
|
||||
+126
-29
@@ -68,13 +68,20 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
|
||||
return NULL;
|
||||
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))
|
||||
if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen,
|
||||
a->bogus, a->lame))
|
||||
return NULL;
|
||||
}
|
||||
return copy;
|
||||
@@ -89,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;
|
||||
@@ -107,6 +115,11 @@ delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name)
|
||||
dp->nslist = ns;
|
||||
ns->name = regional_alloc_init(region, name, ns->namelen);
|
||||
ns->resolved = 0;
|
||||
ns->got4 = 0;
|
||||
ns->got6 = 0;
|
||||
ns->lame = (uint8_t)lame;
|
||||
ns->done_pside4 = 0;
|
||||
ns->done_pside6 = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -124,25 +137,56 @@ delegpt_find_ns(struct delegpt* dp, uint8_t* name, size_t namelen)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct delegpt_addr*
|
||||
delegpt_find_addr(struct delegpt* dp, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
struct delegpt_addr* p = dp->target_list;
|
||||
while(p) {
|
||||
if(sockaddr_cmp_addr(addr, addrlen, &p->addr, p->addrlen)==0) {
|
||||
return p;
|
||||
}
|
||||
p = p->next_target;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
delegpt_add_target(struct delegpt* dp, struct regional* region,
|
||||
uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen)
|
||||
socklen_t addrlen, int bogus, int lame)
|
||||
{
|
||||
struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen);
|
||||
if(!ns) {
|
||||
/* ignore it */
|
||||
return 1;
|
||||
}
|
||||
ns->resolved = 1;
|
||||
return delegpt_add_addr(dp, region, addr, addrlen);
|
||||
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)
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int bogus,
|
||||
int lame)
|
||||
{
|
||||
struct delegpt_addr* a = (struct delegpt_addr*)regional_alloc(region,
|
||||
struct delegpt_addr* a;
|
||||
/* 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,
|
||||
sizeof(struct delegpt_addr));
|
||||
if(!a)
|
||||
return 0;
|
||||
@@ -154,11 +198,12 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region,
|
||||
memcpy(&a->addr, addr, addrlen);
|
||||
a->addrlen = addrlen;
|
||||
a->attempts = 0;
|
||||
a->bogus = bogus;
|
||||
a->lame = lame;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** count NS and number missing */
|
||||
static void
|
||||
void
|
||||
delegpt_count_ns(struct delegpt* dp, size_t* numns, size_t* missing)
|
||||
{
|
||||
struct delegpt_ns* ns;
|
||||
@@ -171,8 +216,7 @@ delegpt_count_ns(struct delegpt* dp, size_t* numns, size_t* missing)
|
||||
}
|
||||
}
|
||||
|
||||
/** count addresses, and number in result and available lists */
|
||||
static void
|
||||
void
|
||||
delegpt_count_addr(struct delegpt* dp, size_t* numaddr, size_t* numres,
|
||||
size_t* numavail)
|
||||
{
|
||||
@@ -207,16 +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", 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":""), (ns->lame?" PARENTSIDE":""),
|
||||
(ns->done_pside4?" PSIDE_A":""),
|
||||
(ns->done_pside6?" PSIDE_AAAA":""));
|
||||
}
|
||||
for(a = dp->target_list; a; a = a->next_target) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,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)
|
||||
{
|
||||
@@ -281,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 */
|
||||
@@ -295,10 +360,10 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region)
|
||||
continue;
|
||||
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_A) {
|
||||
if(!delegpt_add_rrset_A(dp, region, s))
|
||||
if(!delegpt_add_rrset_A(dp, region, s, 0))
|
||||
return NULL;
|
||||
} else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA) {
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, s))
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, s, 0))
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -307,18 +372,20 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region)
|
||||
|
||||
int
|
||||
delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region,
|
||||
struct ub_packed_rrset_key* ns_rrset)
|
||||
struct ub_packed_rrset_key* ns_rrset, int lame)
|
||||
{
|
||||
struct packed_rrset_data* nsdata = (struct packed_rrset_data*)
|
||||
ns_rrset->entry.data;
|
||||
size_t i;
|
||||
if(nsdata->security == sec_status_bogus)
|
||||
dp->bogus = 1;
|
||||
for(i=0; i<nsdata->count; i++) {
|
||||
if(nsdata->rr_len[i] < 2+1) continue; /* len + root label */
|
||||
if(dname_valid(nsdata->rr_data[i]+2, nsdata->rr_len[i]-2) !=
|
||||
(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;
|
||||
@@ -326,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)
|
||||
struct ub_packed_rrset_key* ak, int lame)
|
||||
{
|
||||
struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data;
|
||||
size_t i;
|
||||
@@ -341,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))
|
||||
len, (d->security==sec_status_bogus), lame))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -349,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)
|
||||
struct ub_packed_rrset_key* ak, int lame)
|
||||
{
|
||||
struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data;
|
||||
size_t i;
|
||||
@@ -364,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))
|
||||
len, (d->security==sec_status_bogus), lame))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -372,16 +439,46 @@ 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);
|
||||
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);
|
||||
return delegpt_add_rrset_AAAA(dp, region, rrset, lame);
|
||||
log_warn("Unknown rrset type added to delegpt");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void delegpt_add_neg_msg(struct delegpt* dp, struct msgreply_entry* msg)
|
||||
{
|
||||
struct reply_info* rep = (struct reply_info*)msg->entry.data;
|
||||
if(!rep) return;
|
||||
|
||||
/* if error or no answers */
|
||||
if(FLAGS_GET_RCODE(rep->flags) != 0 || rep->an_numrrsets == 0) {
|
||||
struct delegpt_ns* ns = delegpt_find_ns(dp, msg->key.qname,
|
||||
msg->key.qname_len);
|
||||
if(ns) {
|
||||
if(msg->key.qtype == LDNS_RR_TYPE_A)
|
||||
ns->got4 = 1;
|
||||
else if(msg->key.qtype == LDNS_RR_TYPE_AAAA)
|
||||
ns->got6 = 1;
|
||||
if(ns->got4 && ns->got6)
|
||||
ns->resolved = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
+86
-9
@@ -48,6 +48,7 @@ struct delegpt_ns;
|
||||
struct delegpt_addr;
|
||||
struct dns_msg;
|
||||
struct ub_packed_rrset_key;
|
||||
struct msgreply_entry;
|
||||
|
||||
/**
|
||||
* Delegation Point.
|
||||
@@ -70,6 +71,14 @@ struct delegpt {
|
||||
struct delegpt_addr* usable_list;
|
||||
/** the list of returned targets; subset of target_list */
|
||||
struct delegpt_addr* result_list;
|
||||
|
||||
/** 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;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -84,9 +93,28 @@ struct delegpt_ns {
|
||||
size_t namelen;
|
||||
/**
|
||||
* If the name has been resolved. false if not queried for yet.
|
||||
* true if the address is known, or marked true if failed.
|
||||
* true if the A, AAAA queries have been generated.
|
||||
* marked true if those queries fail.
|
||||
* 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;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -108,6 +136,11 @@ struct delegpt_addr {
|
||||
int attempts;
|
||||
/** rtt stored here in the selection algorithm */
|
||||
int sel_rtt;
|
||||
/** 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;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -140,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.
|
||||
@@ -164,41 +199,47 @@ int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* regional,
|
||||
* @param namelen: length of name.
|
||||
* @param addr: the address.
|
||||
* @param addrlen: the length of addr.
|
||||
* @param bogus: security status for the address, pass true if bogus.
|
||||
* @param lame: address is lame.
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_target(struct delegpt* dp, struct regional* regional,
|
||||
uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen);
|
||||
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 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);
|
||||
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 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);
|
||||
struct ub_packed_rrset_key* rrset, int lame);
|
||||
|
||||
/**
|
||||
* Add any RRset to delegpt.
|
||||
* Does not check for duplicates added.
|
||||
* @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.
|
||||
@@ -206,10 +247,12 @@ int delegpt_add_rrset(struct delegpt* dp, struct regional* regional,
|
||||
* @param regional: where to allocate the info.
|
||||
* @param addr: the address.
|
||||
* @param addrlen: the length of addr.
|
||||
* @param bogus: if address is bogus.
|
||||
* @param lame: if address is lame.
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_addr(struct delegpt* dp, struct regional* regional,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen);
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int lame);
|
||||
|
||||
/**
|
||||
* Find NS record in name list of delegation point.
|
||||
@@ -221,6 +264,16 @@ int delegpt_add_addr(struct delegpt* dp, struct regional* regional,
|
||||
struct delegpt_ns* delegpt_find_ns(struct delegpt* dp, uint8_t* name,
|
||||
size_t namelen);
|
||||
|
||||
/**
|
||||
* Find address record in total list of delegation point.
|
||||
* @param dp: delegation point.
|
||||
* @param addr: address
|
||||
* @param addrlen: length of addr
|
||||
* @return the addr structure or NULL if not found.
|
||||
*/
|
||||
struct delegpt_addr* delegpt_find_addr(struct delegpt* dp,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Print the delegation point to the log. For debugging.
|
||||
* @param v: verbosity value that is needed to emit to log.
|
||||
@@ -228,6 +281,13 @@ struct delegpt_ns* delegpt_find_ns(struct delegpt* dp, uint8_t* name,
|
||||
*/
|
||||
void delegpt_log(enum verbosity_value v, struct delegpt* dp);
|
||||
|
||||
/** count NS and number missing for logging */
|
||||
void delegpt_count_ns(struct delegpt* dp, size_t* numns, size_t* missing);
|
||||
|
||||
/** count addresses, and number in result and available lists, for logging */
|
||||
void delegpt_count_addr(struct delegpt* dp, size_t* numaddr, size_t* numres,
|
||||
size_t* numavail);
|
||||
|
||||
/**
|
||||
* Add all usable targets to the result list.
|
||||
* @param dp: delegation point.
|
||||
@@ -241,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
|
||||
*
|
||||
@@ -262,4 +325,18 @@ size_t delegpt_count_missing_targets(struct delegpt* dp);
|
||||
struct delegpt* delegpt_from_message(struct dns_msg* msg,
|
||||
struct regional* regional);
|
||||
|
||||
/**
|
||||
* Add negative message to delegation point.
|
||||
* @param dp: delegation point.
|
||||
* @param msg: the message added, marks off A or AAAA from an NS entry.
|
||||
*/
|
||||
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 */
|
||||
|
||||
+8
-85
@@ -48,23 +48,8 @@
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
|
||||
int
|
||||
donotq_cmp(const void* k1, const void* k2)
|
||||
{
|
||||
struct iter_donotq_addr* n1 = (struct iter_donotq_addr*)k1;
|
||||
struct iter_donotq_addr* n2 = (struct iter_donotq_addr*)k2;
|
||||
int r = sockaddr_cmp_addr(&n1->addr, n1->addrlen, &n2->addr,
|
||||
n2->addrlen);
|
||||
if(r != 0) return r;
|
||||
if(n1->net < n2->net)
|
||||
return -1;
|
||||
if(n1->net > n2->net)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct iter_donotq*
|
||||
donotq_create()
|
||||
donotq_create(void)
|
||||
{
|
||||
struct iter_donotq* dq = (struct iter_donotq*)calloc(1,
|
||||
sizeof(struct iter_donotq));
|
||||
@@ -84,7 +69,6 @@ donotq_delete(struct iter_donotq* dq)
|
||||
if(!dq)
|
||||
return;
|
||||
regional_destroy(dq->region);
|
||||
free(dq->tree);
|
||||
free(dq);
|
||||
}
|
||||
|
||||
@@ -93,16 +77,11 @@ static int
|
||||
donotq_insert(struct iter_donotq* dq, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int net)
|
||||
{
|
||||
struct iter_donotq_addr* node = regional_alloc(dq->region,
|
||||
sizeof(struct iter_donotq_addr));
|
||||
struct addr_tree_node* node = (struct addr_tree_node*)regional_alloc(
|
||||
dq->region, sizeof(*node));
|
||||
if(!node)
|
||||
return 0;
|
||||
node->node.key = node;
|
||||
memcpy(&node->addr, addr, addrlen);
|
||||
node->addrlen = addrlen;
|
||||
node->net = net;
|
||||
node->parent = NULL;
|
||||
if(!rbtree_insert(dq->tree, &node->node)) {
|
||||
if(!addr_tree_insert(&dq->tree, node, addr, addrlen, net)) {
|
||||
verbose(VERB_QUERY, "duplicate donotquery address ignored.");
|
||||
}
|
||||
return 1;
|
||||
@@ -140,41 +119,11 @@ read_donotq(struct iter_donotq* dq, struct config_file* cfg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** initialise parent pointers in the tree */
|
||||
static void
|
||||
donotq_init_parents(struct iter_donotq* donotq)
|
||||
{
|
||||
struct iter_donotq_addr* node, *prev = NULL, *p;
|
||||
int m;
|
||||
RBTREE_FOR(node, struct iter_donotq_addr*, donotq->tree) {
|
||||
node->parent = NULL;
|
||||
if(!prev || prev->addrlen != node->addrlen) {
|
||||
prev = node;
|
||||
continue;
|
||||
}
|
||||
m = addr_in_common(&prev->addr, prev->net, &node->addr,
|
||||
node->net, node->addrlen);
|
||||
/* sort order like: ::/0, 1::/2, 1::/4, ... 2::/2 */
|
||||
/* find the previous, or parent-parent-parent */
|
||||
for(p = prev; p; p = p->parent)
|
||||
if(p->net <= m) {
|
||||
/* ==: since prev matched m, this is closest*/
|
||||
/* <: prev matches more, but is not a parent,
|
||||
* this one is a (grand)parent */
|
||||
node->parent = p;
|
||||
break;
|
||||
}
|
||||
prev = node;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
donotq_apply_cfg(struct iter_donotq* dq, struct config_file* cfg)
|
||||
{
|
||||
free(dq->tree);
|
||||
dq->tree = rbtree_create(donotq_cmp);
|
||||
if(!dq->tree)
|
||||
return 0;
|
||||
regional_free_all(dq->region);
|
||||
addr_tree_init(&dq->tree);
|
||||
if(!read_donotq(dq, cfg))
|
||||
return 0;
|
||||
if(cfg->donotquery_localhost) {
|
||||
@@ -185,7 +134,7 @@ donotq_apply_cfg(struct iter_donotq* dq, struct config_file* cfg)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
donotq_init_parents(dq);
|
||||
addr_tree_init_parents(&dq->tree);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -193,33 +142,7 @@ int
|
||||
donotq_lookup(struct iter_donotq* donotq, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
/* lookup in the tree */
|
||||
rbnode_t* res = NULL;
|
||||
struct iter_donotq_addr* result;
|
||||
struct iter_donotq_addr key;
|
||||
key.node.key = &key;
|
||||
memcpy(&key.addr, addr, addrlen);
|
||||
key.addrlen = addrlen;
|
||||
key.net = (addr_is_ip6(addr, addrlen)?128:32);
|
||||
if(rbtree_find_less_equal(donotq->tree, &key, &res)) {
|
||||
/* exact */
|
||||
return 1;
|
||||
} else {
|
||||
/* smaller element (or no element) */
|
||||
int m;
|
||||
result = (struct iter_donotq_addr*)res;
|
||||
if(!result || result->addrlen != addrlen)
|
||||
return 0;
|
||||
/* count number of bits matched */
|
||||
m = addr_in_common(&result->addr, result->net, addr,
|
||||
key.net, addrlen);
|
||||
while(result) { /* go up until addr is inside netblock */
|
||||
if(result->net <= m)
|
||||
return 1;
|
||||
result = result->parent;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return addr_tree_lookup(&donotq->tree, addr, addrlen) != NULL;
|
||||
}
|
||||
|
||||
size_t
|
||||
|
||||
+5
-24
@@ -42,7 +42,7 @@
|
||||
|
||||
#ifndef ITERATOR_ITER_DONOTQ_H
|
||||
#define ITERATOR_ITER_DONOTQ_H
|
||||
#include "util/rbtree.h"
|
||||
#include "util/storage/dnstree.h"
|
||||
struct iter_env;
|
||||
struct config_file;
|
||||
struct regional;
|
||||
@@ -55,33 +55,17 @@ struct iter_donotq {
|
||||
struct regional* region;
|
||||
/**
|
||||
* Tree of the address spans that are blocked.
|
||||
* contents of type iter_donotq_addr.
|
||||
* contents of type addr_tree_node. Each node is an address span
|
||||
* that must not be used to send queries to.
|
||||
*/
|
||||
rbtree_t* tree;
|
||||
};
|
||||
|
||||
/**
|
||||
* Iterator donotquery address.
|
||||
* An address span that must not be used to send queries to.
|
||||
*/
|
||||
struct iter_donotq_addr {
|
||||
/** redblacktree node, key is this structure: addr and addrlen, net */
|
||||
rbnode_t node;
|
||||
/** address */
|
||||
struct sockaddr_storage addr;
|
||||
/** length of addr */
|
||||
socklen_t addrlen;
|
||||
/** netblock size */
|
||||
int net;
|
||||
/** parent node in donotq tree that encompasses this entry */
|
||||
struct iter_donotq_addr* parent;
|
||||
rbtree_t tree;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create donotqueryaddresses structure
|
||||
* @return new structure or NULL on error.
|
||||
*/
|
||||
struct iter_donotq* donotq_create();
|
||||
struct iter_donotq* donotq_create(void);
|
||||
|
||||
/**
|
||||
* Delete donotqueryaddresses structure.
|
||||
@@ -114,7 +98,4 @@ int donotq_lookup(struct iter_donotq* donotq, struct sockaddr_storage* addr,
|
||||
*/
|
||||
size_t donotq_get_mem(struct iter_donotq* donotq);
|
||||
|
||||
/** compare two donotq entries */
|
||||
int donotq_cmp(const void* k1, const void* k2);
|
||||
|
||||
#endif /* ITERATOR_ITER_DONOTQ_H */
|
||||
|
||||
+159
-9
@@ -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));
|
||||
@@ -88,9 +91,10 @@ forwards_delete(struct iter_forwards* fwd)
|
||||
free(fwd);
|
||||
}
|
||||
|
||||
/** insert new info into forward structure */
|
||||
/** insert info into forward structure */
|
||||
static int
|
||||
forwards_insert(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
|
||||
forwards_insert_data(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
|
||||
size_t nmlen, int nmlabs, struct delegpt* dp)
|
||||
{
|
||||
struct iter_forward_zone* node = regional_alloc(fwd->region,
|
||||
sizeof(struct iter_forward_zone));
|
||||
@@ -98,11 +102,11 @@ forwards_insert(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
|
||||
return 0;
|
||||
node->node.key = node;
|
||||
node->dclass = c;
|
||||
node->name = regional_alloc_init(fwd->region, dp->name, dp->namelen);
|
||||
node->name = regional_alloc_init(fwd->region, nm, nmlen);
|
||||
if(!node->name)
|
||||
return 0;
|
||||
node->namelen = dp->namelen;
|
||||
node->namelabs = dp->namelabs;
|
||||
node->namelen = nmlen;
|
||||
node->namelabs = nmlabs;
|
||||
node->dp = dp;
|
||||
if(!rbtree_insert(fwd->tree, &node->node)) {
|
||||
log_err("duplicate forward zone ignored.");
|
||||
@@ -110,6 +114,14 @@ forwards_insert(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** insert new info into forward structure given dp */
|
||||
static int
|
||||
forwards_insert(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
|
||||
{
|
||||
return forwards_insert_data(fwd, c, dp->name, dp->namelen,
|
||||
dp->namelabs, dp);
|
||||
}
|
||||
|
||||
/** initialise parent pointers in the tree */
|
||||
static void
|
||||
fwd_init_parents(struct iter_forwards* fwd)
|
||||
@@ -178,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;
|
||||
@@ -203,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)) {
|
||||
if(!delegpt_add_addr(dp, fwd->region, &addr, addrlen, 0, 0)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
@@ -222,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))
|
||||
@@ -234,10 +249,61 @@ read_forwards(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** see if zone needs to have a hole inserted */
|
||||
static int
|
||||
need_hole_insert(rbtree_t* tree, struct iter_forward_zone* zone)
|
||||
{
|
||||
struct iter_forward_zone k;
|
||||
if(rbtree_search(tree, zone))
|
||||
return 0; /* exact match exists */
|
||||
k = *zone;
|
||||
k.node.key = &k;
|
||||
/* search up the tree */
|
||||
do {
|
||||
dname_remove_label(&k.name, &k.namelen);
|
||||
k.namelabs --;
|
||||
if(rbtree_search(tree, &k))
|
||||
return 1; /* found an upper forward zone, need hole */
|
||||
} while(k.namelabs > 1);
|
||||
return 0; /* no forwards above, no holes needed */
|
||||
}
|
||||
|
||||
/** make NULL entries for stubs */
|
||||
static int
|
||||
make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
{
|
||||
struct config_stub* s;
|
||||
struct iter_forward_zone key;
|
||||
key.node.key = &key;
|
||||
key.dclass = LDNS_RR_CLASS_IN;
|
||||
for(s = cfg->stubs; s; s = s->next) {
|
||||
ldns_rdf* rdf = ldns_dname_new_frm_str(s->name);
|
||||
if(!rdf) {
|
||||
log_err("cannot parse stub name '%s'", s->name);
|
||||
return 0;
|
||||
}
|
||||
key.name = ldns_rdf_data(rdf);
|
||||
key.namelabs = dname_count_size_labels(key.name, &key.namelen);
|
||||
if(!need_hole_insert(fwd->tree, &key)) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
continue;
|
||||
}
|
||||
if(!forwards_insert_data(fwd, key.dclass, key.name,
|
||||
key.namelen, key.namelabs, NULL)) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
ldns_rdf_deep_free(rdf);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
{
|
||||
free(fwd->tree);
|
||||
regional_free_all(fwd->region);
|
||||
fwd->tree = rbtree_create(fwd_cmp);
|
||||
if(!fwd->tree)
|
||||
return 0;
|
||||
@@ -245,6 +311,8 @@ forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
/* read forward zones */
|
||||
if(!read_forwards(fwd, cfg))
|
||||
return 0;
|
||||
if(!make_stub_holes(fwd, cfg))
|
||||
return 0;
|
||||
fwd_init_parents(fwd);
|
||||
return 1;
|
||||
}
|
||||
@@ -283,10 +351,92 @@ 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)
|
||||
{
|
||||
if(!fwd)
|
||||
return 0;
|
||||
return sizeof(*fwd) + regional_get_mem(fwd->region);
|
||||
return sizeof(*fwd) + sizeof(*fwd->tree) +
|
||||
regional_get_mem(fwd->region);
|
||||
}
|
||||
|
||||
int
|
||||
forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
|
||||
{
|
||||
if(!forwards_insert(fwd, c, dp))
|
||||
return 0;
|
||||
fwd_init_parents(fwd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||
{
|
||||
struct iter_forward_zone key;
|
||||
key.node.key = &key;
|
||||
key.dclass = c;
|
||||
key.name = nm;
|
||||
key.namelabs = dname_count_size_labels(nm, &key.namelen);
|
||||
if(!rbtree_search(fwd->tree, &key))
|
||||
return; /* nothing to do */
|
||||
(void)rbtree_delete(fwd->tree, &key);
|
||||
fwd_init_parents(fwd);
|
||||
}
|
||||
|
||||
|
||||
+46
-4
@@ -43,7 +43,6 @@
|
||||
#ifndef ITERATOR_ITER_FWD_H
|
||||
#define ITERATOR_ITER_FWD_H
|
||||
#include "util/rbtree.h"
|
||||
struct iter_env;
|
||||
struct config_file;
|
||||
struct delegpt;
|
||||
struct regional;
|
||||
@@ -56,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.
|
||||
@@ -76,7 +75,9 @@ struct iter_forward_zone {
|
||||
size_t namelen;
|
||||
/** number of labels in name */
|
||||
int namelabs;
|
||||
/** delegation point with forward server information for this zone. */
|
||||
/** delegation point with forward server information for this zone.
|
||||
* If NULL then this forward entry is used to indicate that a
|
||||
* stub-zone with the same name exists, and should be used. */
|
||||
struct delegpt* dp;
|
||||
/** pointer to parent in tree (or NULL if none) */
|
||||
struct iter_forward_zone* parent;
|
||||
@@ -88,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.
|
||||
@@ -118,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.
|
||||
@@ -128,4 +146,28 @@ size_t forwards_get_mem(struct iter_forwards* fwd);
|
||||
/** compare two fwd entries */
|
||||
int fwd_cmp(const void* k1, const void* k2);
|
||||
|
||||
/**
|
||||
* Add zone to forward structure. For external use since it recalcs
|
||||
* the tree parents.
|
||||
* @param fwd: the forward data structure
|
||||
* @param c: class of zone
|
||||
* @param dp: delegation point with name and target nameservers for new
|
||||
* forward zone. This delegation point and all its data must be
|
||||
* malloced in the fwd->region. (then it is freed when the fwd is
|
||||
* deleted).
|
||||
* @return false on failure (out of memory);
|
||||
*/
|
||||
int forwards_add_zone(struct iter_forwards* fwd, uint16_t c,
|
||||
struct delegpt* dp);
|
||||
|
||||
/**
|
||||
* Remove zone from forward structure. For external use since it
|
||||
* recalcs the tree parents. Does not actually release any memory, the region
|
||||
* is unchanged.
|
||||
* @param fwd: the forward data structure
|
||||
* @param c: class of zone
|
||||
* @param nm: name of zone (in uncompressed wireformat).
|
||||
*/
|
||||
void forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm);
|
||||
|
||||
#endif /* ITERATOR_ITER_FWD_H */
|
||||
|
||||
+83
-116
@@ -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"
|
||||
@@ -48,23 +50,8 @@
|
||||
#include "util/net_help.h"
|
||||
#include "util/data/dname.h"
|
||||
|
||||
int
|
||||
stub_cmp(const void* k1, const void* k2)
|
||||
{
|
||||
int m;
|
||||
struct iter_hints_stub* n1 = (struct iter_hints_stub*)k1;
|
||||
struct iter_hints_stub* n2 = (struct iter_hints_stub*)k2;
|
||||
if(n1->hint_class != n2->hint_class) {
|
||||
if(n1->hint_class < n2->hint_class)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
return dname_lab_cmp(n1->name, n1->namelabs, n2->name, n2->namelabs,
|
||||
&m);
|
||||
}
|
||||
|
||||
struct iter_hints*
|
||||
hints_create()
|
||||
hints_create(void)
|
||||
{
|
||||
struct iter_hints* hints = (struct iter_hints*)calloc(1,
|
||||
sizeof(struct iter_hints));
|
||||
@@ -84,7 +71,6 @@ hints_delete(struct iter_hints* hints)
|
||||
if(!hints)
|
||||
return;
|
||||
regional_destroy(hints->region);
|
||||
free(hints->tree);
|
||||
free(hints);
|
||||
}
|
||||
|
||||
@@ -99,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)) {
|
||||
&addr, addrlen, 0, 0)) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
return 0;
|
||||
}
|
||||
@@ -121,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) {
|
||||
@@ -147,8 +134,10 @@ 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;
|
||||
if(!ah(dp, r, "M.ROOT-SERVERS.NET.", "2001:dc3::35")) return 0;
|
||||
}
|
||||
return dp;
|
||||
@@ -156,55 +145,26 @@ compile_time_root_prime(struct regional* r, int do_ip4, int do_ip6)
|
||||
|
||||
/** insert new hint info into hint structure */
|
||||
static int
|
||||
hints_insert(struct iter_hints* hints, uint16_t c, struct delegpt* dp)
|
||||
hints_insert(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
||||
int noprime)
|
||||
{
|
||||
struct iter_hints_stub* node = regional_alloc(hints->region,
|
||||
sizeof(struct iter_hints_stub));
|
||||
uint8_t* nm;
|
||||
if(!node)
|
||||
return 0;
|
||||
node->node.key = node;
|
||||
node->hint_class = c;
|
||||
node->name = regional_alloc_init(hints->region, dp->name, dp->namelen);
|
||||
if(!node->name)
|
||||
nm = regional_alloc_init(hints->region, dp->name, dp->namelen);
|
||||
if(!nm)
|
||||
return 0;
|
||||
node->namelen = dp->namelen;
|
||||
node->namelabs = dp->namelabs;
|
||||
node->dp = dp;
|
||||
if(!rbtree_insert(hints->tree, &node->node)) {
|
||||
node->noprime = (uint8_t)noprime;
|
||||
if(!name_tree_insert(&hints->tree, &node->node, nm, dp->namelen,
|
||||
dp->namelabs, c)) {
|
||||
log_err("second hints ignored.");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** initialise parent pointers in the tree */
|
||||
static void
|
||||
init_parents(struct iter_hints* hints)
|
||||
{
|
||||
struct iter_hints_stub* node, *prev = NULL, *p;
|
||||
int m;
|
||||
RBTREE_FOR(node, struct iter_hints_stub*, hints->tree) {
|
||||
node->parent = NULL;
|
||||
if(!prev || prev->hint_class != node->hint_class) {
|
||||
prev = node;
|
||||
continue;
|
||||
}
|
||||
(void)dname_lab_cmp(prev->name, prev->namelabs, node->name,
|
||||
node->namelabs, &m); /* we know prev is smaller */
|
||||
/* sort order like: . com. bla.com. zwb.com. net. */
|
||||
/* find the previous, or parent-parent-parent */
|
||||
for(p = prev; p; p = p->parent)
|
||||
/* looking for name with few labels, a parent */
|
||||
if(p->namelabs <= m) {
|
||||
/* ==: since prev matched m, this is closest*/
|
||||
/* <: prev matches more, but is not a parent,
|
||||
* this one is a (grand)parent */
|
||||
node->parent = p;
|
||||
break;
|
||||
}
|
||||
prev = node;
|
||||
}
|
||||
}
|
||||
|
||||
/** set stub name */
|
||||
static int
|
||||
read_stubs_name(struct iter_hints* hints, struct config_stub* s,
|
||||
@@ -244,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;
|
||||
@@ -269,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)) {
|
||||
if(!delegpt_add_addr(dp, hints->region, &addr, addrlen, 0, 0)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
@@ -288,11 +248,12 @@ 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))
|
||||
return 0;
|
||||
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp))
|
||||
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, !s->isprime))
|
||||
return 0;
|
||||
delegpt_log(VERB_QUERY, dp);
|
||||
}
|
||||
@@ -324,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);
|
||||
@@ -334,23 +296,20 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
if(status != LDNS_STATUS_OK) {
|
||||
log_err("reading root hints %s %d: %s", fname,
|
||||
lineno, ldns_get_errorstr_by_id(status));
|
||||
fclose(f);
|
||||
return 0;
|
||||
goto stop_read;
|
||||
}
|
||||
if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_NS) {
|
||||
if(!delegpt_add_ns(dp, hints->region,
|
||||
ldns_rdf_data(ldns_rr_rdf(rr, 0)))) {
|
||||
ldns_rdf_data(ldns_rr_rdf(rr, 0)), 0)) {
|
||||
log_err("out of memory reading root hints");
|
||||
fclose(f);
|
||||
return 0;
|
||||
goto stop_read;
|
||||
}
|
||||
c = ldns_rr_get_class(rr);
|
||||
if(!dp->name) {
|
||||
if(!delegpt_set_name(dp, hints->region,
|
||||
ldns_rdf_data(ldns_rr_owner(rr)))){
|
||||
log_err("out of memory.");
|
||||
fclose(f);
|
||||
return 0;
|
||||
goto stop_read;
|
||||
}
|
||||
}
|
||||
} else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_A) {
|
||||
@@ -364,10 +323,10 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
if(!delegpt_add_target(dp, hints->region,
|
||||
ldns_rdf_data(ldns_rr_owner(rr)),
|
||||
ldns_rdf_size(ldns_rr_owner(rr)),
|
||||
(struct sockaddr_storage*)&sa, len)) {
|
||||
(struct sockaddr_storage*)&sa, len,
|
||||
0, 0)) {
|
||||
log_err("out of memory reading root hints");
|
||||
fclose(f);
|
||||
return 0;
|
||||
goto stop_read;
|
||||
}
|
||||
} else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) {
|
||||
struct sockaddr_in6 sa;
|
||||
@@ -380,10 +339,10 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
if(!delegpt_add_target(dp, hints->region,
|
||||
ldns_rdf_data(ldns_rr_owner(rr)),
|
||||
ldns_rdf_size(ldns_rr_owner(rr)),
|
||||
(struct sockaddr_storage*)&sa, len)) {
|
||||
(struct sockaddr_storage*)&sa, len,
|
||||
0, 0)) {
|
||||
log_err("out of memory reading root hints");
|
||||
fclose(f);
|
||||
return 0;
|
||||
goto stop_read;
|
||||
}
|
||||
} else {
|
||||
log_warn("root hints %s:%d skipping type %d",
|
||||
@@ -392,16 +351,29 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
|
||||
ldns_rr_free(rr);
|
||||
}
|
||||
|
||||
if (origin)
|
||||
ldns_rdf_deep_free(origin);
|
||||
if (prev_rr)
|
||||
ldns_rdf_deep_free(prev_rr);
|
||||
fclose(f);
|
||||
if(!dp->name) {
|
||||
log_warn("root hints %s: no NS content", fname);
|
||||
return 1;
|
||||
}
|
||||
if(!hints_insert(hints, c, dp)) {
|
||||
if(!hints_insert(hints, c, dp, 0)) {
|
||||
return 0;
|
||||
}
|
||||
delegpt_log(VERB_QUERY, dp);
|
||||
return 1;
|
||||
|
||||
stop_read:
|
||||
if (origin)
|
||||
ldns_rdf_deep_free(origin);
|
||||
if (prev_rr)
|
||||
ldns_rdf_deep_free(prev_rr);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** read root hints list */
|
||||
@@ -427,10 +399,8 @@ read_root_hints_list(struct iter_hints* hints, struct config_file* cfg)
|
||||
int
|
||||
hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
|
||||
{
|
||||
free(hints->tree);
|
||||
hints->tree = rbtree_create(stub_cmp);
|
||||
if(!hints->tree)
|
||||
return 0;
|
||||
regional_free_all(hints->region);
|
||||
name_tree_init(&hints->tree);
|
||||
|
||||
/* read root hints */
|
||||
if(!read_root_hints_list(hints, cfg))
|
||||
@@ -447,11 +417,11 @@ hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
|
||||
verbose(VERB_ALGO, "no config, using builtin root hints.");
|
||||
if(!dp)
|
||||
return 0;
|
||||
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp))
|
||||
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0))
|
||||
return 0;
|
||||
}
|
||||
|
||||
init_parents(hints);
|
||||
name_tree_init_parents(&hints->tree);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -459,59 +429,56 @@ struct delegpt*
|
||||
hints_lookup_root(struct iter_hints* hints, uint16_t qclass)
|
||||
{
|
||||
uint8_t rootlab = 0;
|
||||
struct iter_hints_stub key, *stub;
|
||||
key.node.key = &key;
|
||||
key.hint_class = qclass;
|
||||
key.name = &rootlab;
|
||||
key.namelen = 1;
|
||||
key.namelabs = 1;
|
||||
stub = (struct iter_hints_stub*)rbtree_search(hints->tree, &key);
|
||||
struct iter_hints_stub *stub;
|
||||
stub = (struct iter_hints_stub*)name_tree_find(&hints->tree,
|
||||
&rootlab, 1, 1, qclass);
|
||||
if(!stub)
|
||||
return NULL;
|
||||
return stub->dp;
|
||||
}
|
||||
|
||||
struct delegpt*
|
||||
struct iter_hints_stub*
|
||||
hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
|
||||
uint16_t qclass, struct delegpt* cache_dp)
|
||||
{
|
||||
size_t len;
|
||||
int labs;
|
||||
struct iter_hints_stub *r;
|
||||
|
||||
/* first lookup the stub */
|
||||
rbnode_t* res = NULL;
|
||||
struct iter_hints_stub *result;
|
||||
struct iter_hints_stub key;
|
||||
key.node.key = &key;
|
||||
key.hint_class = qclass;
|
||||
key.name = qname;
|
||||
key.namelabs = dname_count_size_labels(qname, &key.namelen);
|
||||
if(rbtree_find_less_equal(hints->tree, &key, &res)) {
|
||||
/* exact */
|
||||
result = (struct iter_hints_stub*)res;
|
||||
} else {
|
||||
/* smaller element (or no element) */
|
||||
int m;
|
||||
result = (struct iter_hints_stub*)res;
|
||||
if(!result || result->hint_class != qclass)
|
||||
return NULL;
|
||||
/* count number of labels matched */
|
||||
(void)dname_lab_cmp(result->name, result->namelabs, key.name,
|
||||
key.namelabs, &m);
|
||||
while(result) { /* go up until qname is subdomain of stub */
|
||||
if(result->namelabs <= m)
|
||||
break;
|
||||
result = result->parent;
|
||||
}
|
||||
if(!result)
|
||||
return NULL;
|
||||
labs = dname_count_size_labels(qname, &len);
|
||||
r = (struct iter_hints_stub*)name_tree_lookup(&hints->tree, 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.
|
||||
*/
|
||||
if(r->noprime && query_dname_compare(cache_dp->name, r->dp->name)==0)
|
||||
return r; /* use this stub instead of cached dp */
|
||||
|
||||
/*
|
||||
* If our cached delegation point is above the hint, we need to prime.
|
||||
*/
|
||||
if(dname_strict_subdomain(result->dp->name, result->dp->namelabs,
|
||||
if(dname_strict_subdomain(r->dp->name, r->dp->namelabs,
|
||||
cache_dp->name, cache_dp->namelabs))
|
||||
return result->dp; /* need to prime this stub */
|
||||
return r; /* need to prime this stub */
|
||||
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)
|
||||
{
|
||||
|
||||
+22
-20
@@ -42,7 +42,7 @@
|
||||
|
||||
#ifndef ITERATOR_ITER_HINTS_H
|
||||
#define ITERATOR_ITER_HINTS_H
|
||||
#include "util/rbtree.h"
|
||||
#include "util/storage/dnstree.h"
|
||||
struct iter_env;
|
||||
struct config_file;
|
||||
struct delegpt;
|
||||
@@ -56,39 +56,32 @@ 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.
|
||||
* uses name_tree_node from dnstree.h.
|
||||
*/
|
||||
rbtree_t* tree;
|
||||
rbtree_t tree;
|
||||
};
|
||||
|
||||
/**
|
||||
* Iterator hints for a particular stub.
|
||||
*/
|
||||
struct iter_hints_stub {
|
||||
/** redblacktree node, key is this structure: class and name */
|
||||
rbnode_t node;
|
||||
/** name */
|
||||
uint8_t* name;
|
||||
/** length of name */
|
||||
size_t namelen;
|
||||
/** number of labels in name */
|
||||
int namelabs;
|
||||
/** tree sorted by name, class */
|
||||
struct name_tree_node node;
|
||||
/** delegation point with hint information for this stub. */
|
||||
struct delegpt* dp;
|
||||
/** pointer to parent in stub hint tree (or NULL if none) */
|
||||
struct iter_hints_stub* parent;
|
||||
/** class of hints. host order. */
|
||||
uint16_t hint_class;
|
||||
/** does the stub need to forego priming (like on other ports) */
|
||||
uint8_t noprime;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create hints
|
||||
* @return new hints or NULL on error.
|
||||
*/
|
||||
struct iter_hints* hints_create();
|
||||
struct iter_hints* hints_create(void);
|
||||
|
||||
/**
|
||||
* Delete hints.
|
||||
@@ -112,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
|
||||
@@ -124,7 +129,7 @@ struct delegpt* hints_lookup_root(struct iter_hints* hints, uint16_t qclass);
|
||||
* @return: A priming delegation point if there is a stub hint that must
|
||||
* be primed, otherwise null.
|
||||
*/
|
||||
struct delegpt* hints_lookup_stub(struct iter_hints* hints,
|
||||
struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
|
||||
uint8_t* qname, uint16_t qclass, struct delegpt* dp);
|
||||
|
||||
/**
|
||||
@@ -134,7 +139,4 @@ struct delegpt* hints_lookup_stub(struct iter_hints* hints,
|
||||
*/
|
||||
size_t hints_get_mem(struct iter_hints* hints);
|
||||
|
||||
/** compare two hint entries */
|
||||
int stub_cmp(const void* k1, const void* k2);
|
||||
|
||||
#endif /* ITERATOR_ITER_HINTS_H */
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* iterator/iter_priv.c - iterative resolver private address and domain store
|
||||
*
|
||||
* Copyright (c) 2008, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains functions to assist the iterator module.
|
||||
* Keep track of the private addresses and lookup fast.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "ldns/dname.h"
|
||||
#include "iterator/iter_priv.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/data/msgparse.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/storage/dnstree.h"
|
||||
|
||||
struct iter_priv* priv_create(void)
|
||||
{
|
||||
struct iter_priv* priv = (struct iter_priv*)calloc(1, sizeof(*priv));
|
||||
if(!priv)
|
||||
return NULL;
|
||||
priv->region = regional_create();
|
||||
if(!priv->region) {
|
||||
priv_delete(priv);
|
||||
return NULL;
|
||||
}
|
||||
addr_tree_init(&priv->a);
|
||||
name_tree_init(&priv->n);
|
||||
return priv;
|
||||
}
|
||||
|
||||
void priv_delete(struct iter_priv* priv)
|
||||
{
|
||||
if(!priv) return;
|
||||
regional_destroy(priv->region);
|
||||
free(priv);
|
||||
}
|
||||
|
||||
/** Read private-addr declarations from config */
|
||||
static int read_addrs(struct iter_priv* priv, struct config_file* cfg)
|
||||
{
|
||||
/* parse addresses, report errors, insert into tree */
|
||||
struct config_strlist* p;
|
||||
struct addr_tree_node* n;
|
||||
struct sockaddr_storage addr;
|
||||
int net;
|
||||
socklen_t addrlen;
|
||||
|
||||
for(p = cfg->private_address; p; p = p->next) {
|
||||
log_assert(p->str);
|
||||
if(!netblockstrtoaddr(p->str, UNBOUND_DNS_PORT, &addr,
|
||||
&addrlen, &net)) {
|
||||
log_err("cannot parse private-address: %s", p->str);
|
||||
return 0;
|
||||
}
|
||||
n = (struct addr_tree_node*)regional_alloc(priv->region,
|
||||
sizeof(*n));
|
||||
if(!n) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
if(!addr_tree_insert(&priv->a, n, &addr, addrlen, net)) {
|
||||
verbose(VERB_QUERY, "ignoring duplicate "
|
||||
"private-address: %s", p->str);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Read private-domain declarations from config */
|
||||
static int read_names(struct iter_priv* priv, struct config_file* cfg)
|
||||
{
|
||||
/* parse names, report errors, insert into tree */
|
||||
struct config_strlist* p;
|
||||
struct name_tree_node* n;
|
||||
uint8_t* nm;
|
||||
size_t nm_len;
|
||||
int nm_labs;
|
||||
ldns_rdf* rdf;
|
||||
|
||||
for(p = cfg->private_domain; p; p = p->next) {
|
||||
log_assert(p->str);
|
||||
rdf = ldns_dname_new_frm_str(p->str);
|
||||
if(!rdf) {
|
||||
log_err("cannot parse private-domain: %s", p->str);
|
||||
return 0;
|
||||
}
|
||||
nm = ldns_rdf_data(rdf);
|
||||
nm_labs = dname_count_size_labels(nm, &nm_len);
|
||||
nm = (uint8_t*)regional_alloc_init(priv->region, nm, nm_len);
|
||||
ldns_rdf_deep_free(rdf);
|
||||
if(!nm) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
n = (struct name_tree_node*)regional_alloc(priv->region,
|
||||
sizeof(*n));
|
||||
if(!n) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
if(!name_tree_insert(&priv->n, n, nm, nm_len, nm_labs,
|
||||
LDNS_RR_CLASS_IN)) {
|
||||
verbose(VERB_QUERY, "ignoring duplicate "
|
||||
"private-domain: %s", p->str);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int priv_apply_cfg(struct iter_priv* priv, struct config_file* cfg)
|
||||
{
|
||||
/* empty the current contents */
|
||||
regional_free_all(priv->region);
|
||||
addr_tree_init(&priv->a);
|
||||
name_tree_init(&priv->n);
|
||||
|
||||
/* read new contents */
|
||||
if(!read_addrs(priv, cfg))
|
||||
return 0;
|
||||
if(!read_names(priv, cfg))
|
||||
return 0;
|
||||
|
||||
/* prepare for lookups */
|
||||
addr_tree_init_parents(&priv->a);
|
||||
name_tree_init_parents(&priv->n);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if an address is blocked.
|
||||
* @param priv: structure for address storage.
|
||||
* @param addr: address to check
|
||||
* @param addrlen: length of addr.
|
||||
* @return: true if the address must not be queried. false if unlisted.
|
||||
*/
|
||||
static int
|
||||
priv_lookup_addr(struct iter_priv* priv, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
return addr_tree_lookup(&priv->a, addr, addrlen) != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if a name is whitelisted.
|
||||
* @param priv: structure for address storage.
|
||||
* @param pkt: the packet (for compression ptrs).
|
||||
* @param name: name to check.
|
||||
* @param name_len: uncompressed length of the name to check.
|
||||
* @param dclass: class to check.
|
||||
* @return: true if the name is OK. false if unlisted.
|
||||
*/
|
||||
static int
|
||||
priv_lookup_name(struct iter_priv* priv, ldns_buffer* pkt,
|
||||
uint8_t* name, size_t name_len, uint16_t dclass)
|
||||
{
|
||||
size_t len;
|
||||
uint8_t decomp[256];
|
||||
int labs;
|
||||
if(name_len >= sizeof(decomp))
|
||||
return 0;
|
||||
dname_pkt_copy(pkt, decomp, name);
|
||||
labs = dname_count_size_labels(decomp, &len);
|
||||
log_assert(name_len == len);
|
||||
return name_tree_lookup(&priv->n, decomp, len, labs, dclass) != NULL;
|
||||
}
|
||||
|
||||
size_t priv_get_mem(struct iter_priv* priv)
|
||||
{
|
||||
if(!priv) return 0;
|
||||
return sizeof(*priv) + regional_get_mem(priv->region);
|
||||
}
|
||||
|
||||
int priv_rrset_bad(struct iter_priv* priv, ldns_buffer* pkt,
|
||||
struct rrset_parse* rrset)
|
||||
{
|
||||
if(priv->a.count == 0)
|
||||
return 0; /* there are no blocked addresses */
|
||||
|
||||
/* see if it is a private name, that is allowed to have any */
|
||||
if(priv_lookup_name(priv, pkt, rrset->dname, rrset->dname_len,
|
||||
ntohs(rrset->rrset_class))) {
|
||||
return 0;
|
||||
} else {
|
||||
/* so its a public name, check the address */
|
||||
socklen_t len;
|
||||
struct rr_parse* rr;
|
||||
if(rrset->type == LDNS_RR_TYPE_A) {
|
||||
struct sockaddr_storage addr;
|
||||
struct sockaddr_in sa;
|
||||
|
||||
len = (socklen_t)sizeof(sa);
|
||||
memset(&sa, 0, len);
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
|
||||
for(rr = rrset->rr_first; rr; rr = rr->next) {
|
||||
if(ldns_read_uint16(rr->ttl_data+4)
|
||||
!= INET_SIZE)
|
||||
continue;
|
||||
memmove(&sa.sin_addr, rr->ttl_data+4+2,
|
||||
INET_SIZE);
|
||||
memmove(&addr, &sa, len);
|
||||
if(priv_lookup_addr(priv, &addr, len))
|
||||
return 1;
|
||||
}
|
||||
} else if(rrset->type == LDNS_RR_TYPE_AAAA) {
|
||||
struct sockaddr_storage addr;
|
||||
struct sockaddr_in6 sa;
|
||||
len = (socklen_t)sizeof(sa);
|
||||
memset(&sa, 0, len);
|
||||
sa.sin6_family = AF_INET6;
|
||||
sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
|
||||
for(rr = rrset->rr_first; rr; rr = rr->next) {
|
||||
if(ldns_read_uint16(rr->ttl_data+4)
|
||||
!= INET6_SIZE)
|
||||
continue;
|
||||
memmove(&sa.sin6_addr, rr->ttl_data+4+2,
|
||||
INET6_SIZE);
|
||||
memmove(&addr, &sa, len);
|
||||
if(priv_lookup_addr(priv, &addr, len))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* iterator/iter_priv.h - iterative resolver private address and domain store
|
||||
*
|
||||
* Copyright (c) 2008, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains functions to assist the iterator module.
|
||||
* Keep track of the private addresses and lookup fast.
|
||||
*/
|
||||
|
||||
#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;
|
||||
struct rrset_parse;
|
||||
|
||||
/**
|
||||
* Iterator priv structure
|
||||
*/
|
||||
struct iter_priv {
|
||||
/** regional for allocation */
|
||||
struct regional* region;
|
||||
/**
|
||||
* Tree of the address spans that are blocked.
|
||||
* contents of type addr_tree_node.
|
||||
* No further data need, only presence or absence.
|
||||
*/
|
||||
rbtree_t a;
|
||||
/**
|
||||
* Tree of the domains spans that are allowed to contain
|
||||
* the blocked address spans.
|
||||
* contents of type name_tree_node.
|
||||
* No further data need, only presence or absence.
|
||||
*/
|
||||
rbtree_t n;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create priv structure
|
||||
* @return new structure or NULL on error.
|
||||
*/
|
||||
struct iter_priv* priv_create(void);
|
||||
|
||||
/**
|
||||
* Delete priv structure.
|
||||
* @param priv: to delete.
|
||||
*/
|
||||
void priv_delete(struct iter_priv* priv);
|
||||
|
||||
/**
|
||||
* Process priv config.
|
||||
* @param priv: where to store.
|
||||
* @param cfg: config options.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
int priv_apply_cfg(struct iter_priv* priv, struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* See if rrset is bad.
|
||||
* @param priv: structure for private address storage.
|
||||
* @param pkt: packet to decompress rrset name in.
|
||||
* @param rrset: the rrset to examine, A or AAAA.
|
||||
* @return true if the rrset is bad and should be removed.
|
||||
*/
|
||||
int priv_rrset_bad(struct iter_priv* priv, ldns_buffer* pkt,
|
||||
struct rrset_parse* rrset);
|
||||
|
||||
/**
|
||||
* Get memory used by priv structure.
|
||||
* @param priv: structure for address storage.
|
||||
* @return bytes in use.
|
||||
*/
|
||||
size_t priv_get_mem(struct iter_priv* priv);
|
||||
|
||||
#endif /* ITERATOR_ITER_PRIV_H */
|
||||
+30
-12
@@ -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"
|
||||
@@ -104,7 +105,7 @@ response_type_from_server(int rdset,
|
||||
struct dns_msg* msg, struct query_info* request, struct delegpt* dp)
|
||||
{
|
||||
uint8_t* origzone = (uint8_t*)"\000"; /* the default */
|
||||
size_t origzonelen = 1;
|
||||
struct ub_packed_rrset_key* s;
|
||||
size_t i;
|
||||
|
||||
if(!msg || !request)
|
||||
@@ -115,7 +116,7 @@ response_type_from_server(int rdset,
|
||||
/* make sure its not recursive when we don't want it to */
|
||||
if( (msg->rep->flags&BIT_RA) &&
|
||||
!(msg->rep->flags&BIT_AA) && !rdset)
|
||||
return RESPONSE_TYPE_LAME;
|
||||
return RESPONSE_TYPE_REC_LAME;
|
||||
return RESPONSE_TYPE_ANSWER;
|
||||
}
|
||||
|
||||
@@ -128,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
|
||||
@@ -141,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,
|
||||
@@ -188,12 +188,10 @@ response_type_from_server(int rdset,
|
||||
}
|
||||
|
||||
/* Looking at the authority section, we just look and see if
|
||||
* there is a delegation NS set, turning it into a delegation.
|
||||
* Otherwise, we will have to conclude ANSWER (either it is
|
||||
* NOERROR/NODATA, or an non-authoritative answer). */
|
||||
* there is a SOA record, that means a NOERROR/NODATA */
|
||||
for(i = msg->rep->an_numrrsets; i < (msg->rep->an_numrrsets +
|
||||
msg->rep->ns_numrrsets); i++) {
|
||||
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
|
||||
s = msg->rep->rrsets[i];
|
||||
|
||||
/* The normal way of detecting NOERROR/NODATA. */
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_SOA &&
|
||||
@@ -201,27 +199,47 @@ response_type_from_server(int rdset,
|
||||
/* we do our own recursion, thank you */
|
||||
if( (msg->rep->flags&BIT_RA) &&
|
||||
!(msg->rep->flags&BIT_AA) && !rdset)
|
||||
return RESPONSE_TYPE_LAME;
|
||||
return RESPONSE_TYPE_REC_LAME;
|
||||
return RESPONSE_TYPE_ANSWER;
|
||||
}
|
||||
}
|
||||
/* Looking at the authority section, we just look and see if
|
||||
* there is a delegation NS set, turning it into a delegation.
|
||||
* Otherwise, we will have to conclude ANSWER (either it is
|
||||
* NOERROR/NODATA, or an non-authoritative answer). */
|
||||
for(i = msg->rep->an_numrrsets; i < (msg->rep->an_numrrsets +
|
||||
msg->rep->ns_numrrsets); i++) {
|
||||
s = msg->rep->rrsets[i];
|
||||
|
||||
/* Detect REFERRAL/LAME/ANSWER based on the relationship
|
||||
* of the NS set to the originating zone name. */
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_NS) {
|
||||
/* If we are getting an NS set for the zone we
|
||||
* thought we were contacting, then it is an answer.*/
|
||||
/* FIXME: is this correct? */
|
||||
if(query_dname_compare(s->rk.dname, origzone) == 0) {
|
||||
/* see if mistakenly a recursive server was
|
||||
* deployed and is responding nonAA */
|
||||
if( (msg->rep->flags&BIT_RA) &&
|
||||
!(msg->rep->flags&BIT_AA) && !rdset)
|
||||
return RESPONSE_TYPE_LAME;
|
||||
return RESPONSE_TYPE_REC_LAME;
|
||||
/* 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_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
|
||||
@@ -247,6 +265,6 @@ response_type_from_server(int rdset,
|
||||
* be an entirely empty message) */
|
||||
/* check if recursive answer; saying it has empty cache */
|
||||
if( (msg->rep->flags&BIT_RA) && !(msg->rep->flags&BIT_AA) && !rdset)
|
||||
return RESPONSE_TYPE_LAME;
|
||||
return RESPONSE_TYPE_REC_LAME;
|
||||
return RESPONSE_TYPE_ANSWER;
|
||||
}
|
||||
|
||||
@@ -81,7 +81,14 @@ enum response_type {
|
||||
* 'lame' means that this particular response indicates that
|
||||
* the nameserver knew nothing about the question.
|
||||
*/
|
||||
RESPONSE_TYPE_LAME
|
||||
RESPONSE_TYPE_LAME,
|
||||
|
||||
/**
|
||||
* Recursion lame means that the nameserver is some sort of
|
||||
* open recursor, and not authoritative for the question.
|
||||
* It may know something, but not authoritatively.
|
||||
*/
|
||||
RESPONSE_TYPE_REC_LAME
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+165
-10
@@ -41,6 +41,8 @@
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "iterator/iter_scrub.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "iterator/iter_priv.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "util/log.h"
|
||||
#include "util/net_help.h"
|
||||
@@ -99,8 +101,6 @@ has_additional(uint16_t t)
|
||||
case LDNS_RR_TYPE_NAPTR:
|
||||
/* TODO: NAPTR not supported, glue stripped off */
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -189,7 +189,11 @@ parse_get_cname_target(struct rrset_parse* rrset, uint8_t** sname,
|
||||
if(rrset->rr_count != 1) {
|
||||
verbose(VERB_ALGO, "Found CNAME rrset with "
|
||||
"size > 1: %u", (unsigned)rrset->rr_count);
|
||||
return 0;
|
||||
/* use the first CNAME! */
|
||||
rrset->rr_count = 1;
|
||||
rrset->size = rrset->rr_first->size;
|
||||
rrset->rr_last = rrset->rr_first;
|
||||
rrset->rr_first->next = NULL;
|
||||
}
|
||||
if(rrset->rr_first->size < sizeof(uint16_t)+1)
|
||||
return 0; /* CNAME rdata too small */
|
||||
@@ -299,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
|
||||
@@ -316,7 +329,7 @@ scrub_normalize(ldns_buffer* pkt, struct msg_parse* msg,
|
||||
{
|
||||
uint8_t* sname = qinfo->qname;
|
||||
size_t snamelen = qinfo->qname_len;
|
||||
struct rrset_parse* rrset, *prev;
|
||||
struct rrset_parse* rrset, *prev, *nsset=NULL;
|
||||
|
||||
if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR &&
|
||||
FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN)
|
||||
@@ -412,7 +425,10 @@ scrub_normalize(ldns_buffer* pkt, struct msg_parse* msg,
|
||||
}
|
||||
|
||||
/* Mark the additional names from relevant rrset as OK. */
|
||||
mark_additional_rrset(pkt, msg, rrset);
|
||||
/* only for RRsets that match the query name, other ones
|
||||
* will be removed by sanitize, so no additional for them */
|
||||
if(dname_pkt_compare(pkt, qinfo->qname, rrset->dname) == 0)
|
||||
mark_additional_rrset(pkt, msg, rrset);
|
||||
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
@@ -420,6 +436,30 @@ scrub_normalize(ldns_buffer* pkt, struct msg_parse* msg,
|
||||
|
||||
/* Mark additional names from AUTHORITY */
|
||||
while(rrset && rrset->section == LDNS_SECTION_AUTHORITY) {
|
||||
if(rrset->type==LDNS_RR_TYPE_DNAME ||
|
||||
rrset->type==LDNS_RR_TYPE_CNAME ||
|
||||
rrset->type==LDNS_RR_TYPE_A ||
|
||||
rrset->type==LDNS_RR_TYPE_AAAA) {
|
||||
remove_rrset("normalize: removing irrelevant "
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
/* 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 {
|
||||
remove_rrset("normalize: removing irrelevant "
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
mark_additional_rrset(pkt, msg, rrset);
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
@@ -443,6 +483,13 @@ scrub_normalize(ldns_buffer* pkt, struct msg_parse* msg,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(rrset->type==LDNS_RR_TYPE_DNAME ||
|
||||
rrset->type==LDNS_RR_TYPE_CNAME ||
|
||||
rrset->type==LDNS_RR_TYPE_NS) {
|
||||
remove_rrset("normalize: removing irrelevant "
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
}
|
||||
@@ -486,6 +533,47 @@ 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
|
||||
* @param zonename: the zone name.
|
||||
* @return true if BAD.
|
||||
*/
|
||||
static int sanitize_nsec_is_overreach(struct rrset_parse* rrset,
|
||||
uint8_t* zonename)
|
||||
{
|
||||
struct rr_parse* rr;
|
||||
uint8_t* rhs;
|
||||
size_t len;
|
||||
log_assert(rrset->type == LDNS_RR_TYPE_NSEC);
|
||||
for(rr = rrset->rr_first; rr; rr = rr->next) {
|
||||
rhs = rr->ttl_data+4+2;
|
||||
len = ldns_read_uint16(rr->ttl_data+4);
|
||||
if(!dname_valid(rhs, len)) {
|
||||
/* malformed domain name in rdata */
|
||||
return 1;
|
||||
}
|
||||
if(!dname_subdomain_c(rhs, zonename)) {
|
||||
/* overreaching */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* all NSEC RRs OK */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a response event, remove suspect RRsets from the response.
|
||||
* "Suspect" rrsets are potentially poison. Note that this routine expects
|
||||
@@ -494,18 +582,52 @@ store_rrset(ldns_buffer* pkt, struct msg_parse* msg, struct module_env* env,
|
||||
*
|
||||
* @param pkt: packet.
|
||||
* @param msg: msg to normalize.
|
||||
* @param qinfo: the question originally asked.
|
||||
* @param zonename: name of server zone.
|
||||
* @param env: module environment with config and cache.
|
||||
* @param ie: iterator environment with private address data.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
static int
|
||||
scrub_sanitize(ldns_buffer* pkt, struct msg_parse* msg, uint8_t* zonename,
|
||||
struct module_env* env)
|
||||
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;
|
||||
|
||||
/* the first DNAME is allowed to stay. It needs checking before
|
||||
* it can be used from the cache. After normalization, an initial
|
||||
* DNAME will have a correctly synthesized CNAME after it. */
|
||||
if(rrset && rrset->type == LDNS_RR_TYPE_DNAME &&
|
||||
rrset->section == LDNS_SECTION_ANSWER &&
|
||||
pkt_strict_sub(pkt, qinfo->qname, rrset->dname) &&
|
||||
pkt_sub(pkt, rrset->dname, zonename)) {
|
||||
prev = rrset; /* DNAME allowed to stay in answer section */
|
||||
rrset = rrset->rrset_all_next;
|
||||
}
|
||||
|
||||
/* remove all records from the answer section that are
|
||||
* not the same domain name as the query domain name.
|
||||
* The answer section should contain rrsets with the same name
|
||||
* as the question. For DNAMEs a CNAME has been synthesized.
|
||||
* Wildcards have the query name in answer section.
|
||||
* ANY queries get query name in answer section.
|
||||
* 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;
|
||||
}
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
}
|
||||
|
||||
/* At this point, we brutally remove ALL rrsets that aren't
|
||||
* children of the originating zone. The idea here is that,
|
||||
* as far as we know, the server that we contacted is ONLY
|
||||
@@ -513,7 +635,21 @@ scrub_sanitize(ldns_buffer* pkt, struct msg_parse* msg, uint8_t* zonename,
|
||||
* be authoriative for any other zones, and of course, MAY
|
||||
* NOT be authoritative for some subdomains of the originating
|
||||
* zone. */
|
||||
prev = NULL;
|
||||
rrset = msg->rrset_first;
|
||||
while(rrset) {
|
||||
|
||||
/* remove private addresses */
|
||||
if( (rrset->type == LDNS_RR_TYPE_A ||
|
||||
rrset->type == LDNS_RR_TYPE_AAAA) &&
|
||||
priv_rrset_bad(ie->priv, pkt, rrset)) {
|
||||
/* set servfail, so the classification becomes
|
||||
* THROWAWAY, instead of LAME or other unwanted */
|
||||
FLAGS_SET_RCODE(msg->flags, LDNS_RCODE_SERVFAIL);
|
||||
remove_rrset("sanitize: removing public name with "
|
||||
"private address", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* skip DNAME records -- they will always be followed by a
|
||||
* synthesized CNAME, which will be relevant.
|
||||
@@ -527,10 +663,15 @@ scrub_sanitize(ldns_buffer* pkt, struct msg_parse* msg, uint8_t* zonename,
|
||||
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
|
||||
@@ -540,11 +681,24 @@ scrub_sanitize(ldns_buffer* pkt, struct msg_parse* msg, uint8_t* zonename,
|
||||
"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)) {
|
||||
remove_rrset("sanitize: removing overreaching NSEC "
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
}
|
||||
@@ -554,7 +708,7 @@ scrub_sanitize(ldns_buffer* pkt, struct msg_parse* msg, uint8_t* zonename,
|
||||
int
|
||||
scrub_message(ldns_buffer* pkt, struct msg_parse* msg,
|
||||
struct query_info* qinfo, uint8_t* zonename, struct regional* region,
|
||||
struct module_env* env)
|
||||
struct module_env* env, struct iter_env* ie)
|
||||
{
|
||||
/* basic sanity checks */
|
||||
log_nametypeclass(VERB_ALGO, "scrub for", zonename, LDNS_RR_TYPE_NS,
|
||||
@@ -563,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
|
||||
@@ -585,7 +740,7 @@ scrub_message(ldns_buffer* pkt, struct msg_parse* msg,
|
||||
if(!scrub_normalize(pkt, msg, qinfo, region))
|
||||
return 0;
|
||||
/* delete all out-of-zone information */
|
||||
if(!scrub_sanitize(pkt, msg, zonename, env))
|
||||
if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -42,10 +42,12 @@
|
||||
|
||||
#ifndef ITERATOR_ITER_SCRUB_H
|
||||
#define ITERATOR_ITER_SCRUB_H
|
||||
#include "ldns/buffer.h"
|
||||
struct msg_parse;
|
||||
struct query_info;
|
||||
struct regional;
|
||||
struct module_env;
|
||||
struct iter_env;
|
||||
|
||||
/**
|
||||
* Cleanup the passed dns message.
|
||||
@@ -57,10 +59,11 @@ struct module_env;
|
||||
* Used to determine out of bailiwick information.
|
||||
* @param regional: where to allocate (new) parts of the message.
|
||||
* @param env: module environment with config settings and cache.
|
||||
* @param ie: iterator module environment data.
|
||||
* @return: false if the message is total waste. true if scrubbed with success.
|
||||
*/
|
||||
int scrub_message(ldns_buffer* pkt, struct msg_parse* msg,
|
||||
struct query_info* qinfo, uint8_t* zonename, struct regional* regional,
|
||||
struct module_env* env);
|
||||
struct module_env* env, struct iter_env* ie);
|
||||
|
||||
#endif /* ITERATOR_ITER_SCRUB_H */
|
||||
|
||||
+535
-48
@@ -46,6 +46,7 @@
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_donotq.h"
|
||||
#include "iterator/iter_delegpt.h"
|
||||
#include "iterator/iter_priv.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/cache/rrset.h"
|
||||
@@ -59,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
|
||||
@@ -111,31 +119,76 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
log_err("Could not set root or stub hints");
|
||||
return 0;
|
||||
}
|
||||
if(!iter_env->fwds)
|
||||
iter_env->fwds = forwards_create();
|
||||
if(!iter_env->fwds || !forwards_apply_cfg(iter_env->fwds, cfg)) {
|
||||
log_err("Could not set forward zones");
|
||||
return 0;
|
||||
}
|
||||
if(!iter_env->donotq)
|
||||
iter_env->donotq = donotq_create();
|
||||
if(!iter_env->donotq || !donotq_apply_cfg(iter_env->donotq, cfg)) {
|
||||
log_err("Could not set donotqueryaddresses");
|
||||
return 0;
|
||||
}
|
||||
if(!iter_env->priv)
|
||||
iter_env->priv = priv_create();
|
||||
if(!iter_env->priv || !priv_apply_cfg(iter_env->priv, cfg)) {
|
||||
log_err("Could not set private addresses");
|
||||
return 0;
|
||||
}
|
||||
iter_env->supports_ipv6 = cfg->do_ip6;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** filter out unsuitable targets, return rtt or -1 */
|
||||
/** filter out unsuitable targets
|
||||
* @param iter_env: iterator environment with ipv6-support flag.
|
||||
* @param env: module environment with infra cache.
|
||||
* @param name: zone name
|
||||
* @param namelen: length of name
|
||||
* @param qtype: query type (host order).
|
||||
* @param now: current time
|
||||
* @param a: address in delegation point we are examining.
|
||||
* @return an integer that signals the target suitability.
|
||||
* as follows:
|
||||
* -1: The address should be omitted from the list.
|
||||
* Because:
|
||||
* o The address is bogus (DNSSEC validation failure).
|
||||
* o Listed as donotquery
|
||||
* o is ipv6 but no ipv6 support (in operating system).
|
||||
* o is lame
|
||||
* Otherwise, an rtt in milliseconds.
|
||||
* 0 .. USEFUL_SERVER_TOP_TIMEOUT-1
|
||||
* The roundtrip time timeout estimate. less than 2 minutes.
|
||||
* Note that util/rtt.c has a MIN_TIMEOUT of 50 msec, thus
|
||||
* 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+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).
|
||||
* When a final value is chosen that is recursionlame; RD bit is set on query.
|
||||
* Because of the numbers this means recursionlame also have dnssec lameness
|
||||
* checking turned off.
|
||||
*/
|
||||
static int
|
||||
iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
|
||||
uint8_t* name, size_t namelen, uint32_t now, struct delegpt_addr* a)
|
||||
uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now,
|
||||
struct delegpt_addr* a)
|
||||
{
|
||||
int rtt;
|
||||
int lame;
|
||||
int dnsseclame;
|
||||
int rtt, lame, reclame, dnsseclame;
|
||||
if(a->bogus)
|
||||
return -1; /* address of server is bogus */
|
||||
if(donotq_lookup(iter_env->donotq, &a->addr, a->addrlen)) {
|
||||
log_addr(VERB_ALGO, "skip addr on the donotquery list",
|
||||
&a->addr, a->addrlen);
|
||||
return -1; /* server is on the donotquery list */
|
||||
}
|
||||
if(!iter_env->supports_ipv6 && addr_is_ip6(&a->addr, a->addrlen)) {
|
||||
@@ -143,31 +196,51 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
|
||||
}
|
||||
/* check lameness - need zone , class info */
|
||||
if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen,
|
||||
name, namelen, &lame, &dnsseclame, &rtt, now)) {
|
||||
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%s", rtt,
|
||||
lame?" LAME":"",
|
||||
dnsseclame?" DNSSEC_LAME":"",
|
||||
reclame?" REC_LAME":"",
|
||||
a->lame?" ADDR_LAME":"");
|
||||
if(lame)
|
||||
return -1; /* server is lame */
|
||||
else if(rtt >= USEFUL_SERVER_TOP_TIMEOUT)
|
||||
return -1; /* server is unresponsive */
|
||||
else if(dnsseclame)
|
||||
return rtt+USEFUL_SERVER_TOP_TIMEOUT; /* nonpref */
|
||||
/* server is unresponsive */
|
||||
return USEFUL_SERVER_TOP_TIMEOUT;
|
||||
/* select remainder from worst to best */
|
||||
else if(reclame)
|
||||
return rtt+USEFUL_SERVER_TOP_TIMEOUT*3; /* nonpref */
|
||||
else if(dnsseclame )
|
||||
return rtt+USEFUL_SERVER_TOP_TIMEOUT*2; /* nonpref */
|
||||
else if(a->lame)
|
||||
return rtt+USEFUL_SERVER_TOP_TIMEOUT+1; /* nonpref */
|
||||
else return rtt;
|
||||
}
|
||||
/* no server information present */
|
||||
if(a->lame)
|
||||
return USEFUL_SERVER_TOP_TIMEOUT+1+UNKNOWN_SERVER_NICENESS; /* nonpref */
|
||||
return UNKNOWN_SERVER_NICENESS;
|
||||
}
|
||||
|
||||
/** lookup RTT information, and also store fastest rtt (if any) */
|
||||
static int
|
||||
iter_fill_rtt(struct iter_env* iter_env, struct module_env* env,
|
||||
uint8_t* name, size_t namelen, uint32_t now, struct delegpt* dp,
|
||||
int* best_rtt)
|
||||
uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now,
|
||||
struct delegpt* dp, int* best_rtt, struct sock_list* blacklist)
|
||||
{
|
||||
int got_it = 0;
|
||||
struct delegpt_addr* a;
|
||||
if(dp->bogus)
|
||||
return 0; /* NS bogus, all bogus, nothing found */
|
||||
for(a=dp->result_list; a; a = a->next_result) {
|
||||
a->sel_rtt = iter_filter_unsuitable(iter_env, env,
|
||||
name, namelen, now, a);
|
||||
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;
|
||||
@@ -183,17 +256,24 @@ iter_fill_rtt(struct iter_env* iter_env, struct module_env* env,
|
||||
* returns number of best targets (or 0, no suitable targets) */
|
||||
static int
|
||||
iter_filter_order(struct iter_env* iter_env, struct module_env* env,
|
||||
uint8_t* name, size_t namelen, uint32_t now, struct delegpt* dp,
|
||||
int* selected_rtt)
|
||||
uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now,
|
||||
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, now, dp,
|
||||
&low_rtt);
|
||||
got_num = iter_fill_rtt(iter_env, env, name, namelen, qtype, now, dp,
|
||||
&low_rtt, blacklist);
|
||||
if(got_num == 0)
|
||||
return 0;
|
||||
if(low_rtt >= USEFUL_SERVER_TOP_TIMEOUT &&
|
||||
(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;
|
||||
@@ -232,18 +312,44 @@ 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, int* dnssec_expected)
|
||||
uint8_t* name, size_t namelen, uint16_t qtype, int* dnssec_lame,
|
||||
int* chase_to_rd, int open_target, struct sock_list* blacklist)
|
||||
{
|
||||
int sel;
|
||||
int selrtt;
|
||||
struct delegpt_addr* a, *prev;
|
||||
int num = iter_filter_order(iter_env, env, name, namelen,
|
||||
*env->now, dp, &selrtt);
|
||||
int num = iter_filter_order(iter_env, env, name, namelen, qtype,
|
||||
*env->now, dp, &selrtt, open_target, blacklist);
|
||||
|
||||
if(num == 0)
|
||||
return NULL;
|
||||
if(selrtt >= USEFUL_SERVER_TOP_TIMEOUT)
|
||||
*dnssec_expected = 0;
|
||||
verbose(VERB_ALGO, "selrtt %d", selrtt);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if(num == 1) {
|
||||
a = dp->result_list;
|
||||
if(++a->attempts < OUTBOUND_MSG_RETRY)
|
||||
@@ -251,11 +357,12 @@ iter_server_selection(struct iter_env* iter_env,
|
||||
dp->result_list = a->next_result;
|
||||
return a;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
@@ -308,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
|
||||
@@ -321,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);
|
||||
}
|
||||
|
||||
@@ -363,32 +470,57 @@ 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 module_qstate* qstate, struct delegpt* dp)
|
||||
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(!(qstate->query_flags&BIT_RD))
|
||||
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 */
|
||||
if( (qstate->qinfo.qtype == LDNS_RR_TYPE_A ||
|
||||
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) &&
|
||||
dname_subdomain_c(qstate->qinfo.qname, dp->name) &&
|
||||
delegpt_find_ns(dp, qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len))
|
||||
if( (qinfo->qtype == LDNS_RR_TYPE_A ||
|
||||
qinfo->qtype == LDNS_RR_TYPE_AAAA) &&
|
||||
dname_subdomain_c(qinfo->qname, dp->name) &&
|
||||
delegpt_find_ns(dp, qinfo->qname, qinfo->qname_len))
|
||||
return 1;
|
||||
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
@@ -404,17 +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 || !msg || !msg->rep)
|
||||
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(reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen,
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -473,5 +626,339 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* check equality of two rrsets
|
||||
* @param k1: rrset
|
||||
* @param k2: rrset
|
||||
* @return true if equal
|
||||
*/
|
||||
static int
|
||||
rrset_equal(struct ub_packed_rrset_key* k1, struct ub_packed_rrset_key* k2)
|
||||
{
|
||||
struct packed_rrset_data* d1 = (struct packed_rrset_data*)
|
||||
k1->entry.data;
|
||||
struct packed_rrset_data* d2 = (struct packed_rrset_data*)
|
||||
k2->entry.data;
|
||||
size_t i, t;
|
||||
if(k1->rk.dname_len != k2->rk.dname_len ||
|
||||
k1->rk.flags != k2->rk.flags ||
|
||||
k1->rk.type != k2->rk.type ||
|
||||
k1->rk.rrset_class != k2->rk.rrset_class ||
|
||||
query_dname_compare(k1->rk.dname, k2->rk.dname) != 0)
|
||||
return 0;
|
||||
if(d1->ttl != d2->ttl ||
|
||||
d1->count != d2->count ||
|
||||
d1->rrsig_count != d2->rrsig_count ||
|
||||
d1->trust != d2->trust ||
|
||||
d1->security != d2->security)
|
||||
return 0;
|
||||
t = d1->count + d1->rrsig_count;
|
||||
for(i=0; i<t; i++) {
|
||||
if(d1->rr_len[i] != d2->rr_len[i] ||
|
||||
d1->rr_ttl[i] != d2->rr_ttl[i] ||
|
||||
memcmp(d1->rr_data[i], d2->rr_data[i],
|
||||
d1->rr_len[i]) != 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
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 ||
|
||||
p->ar_numrrsets != q->ar_numrrsets ||
|
||||
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])) {
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
+135
-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.
|
||||
@@ -74,14 +79,21 @@ int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg);
|
||||
* @param dp: delegation point with result list.
|
||||
* @param name: zone name (for lameness check).
|
||||
* @param namelen: length of name.
|
||||
* @param dnssec_expected: set to 0, if a known dnssec-lame server is selected
|
||||
* @param qtype: query type that we want to send.
|
||||
* @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, int* dnssec_expected);
|
||||
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.
|
||||
@@ -108,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.
|
||||
@@ -131,13 +144,25 @@ 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 qstate: query state with RD flag and query name.
|
||||
* @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 module_qstate* qstate, struct delegpt* dp);
|
||||
int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
|
||||
struct delegpt* dp);
|
||||
|
||||
/**
|
||||
* See if delegation is expected to have DNSSEC information (RRSIGs) in
|
||||
@@ -177,4 +202,109 @@ int iter_msg_has_dnssec(struct dns_msg* msg);
|
||||
int iter_msg_from_zone(struct dns_msg* msg, struct delegpt* dp,
|
||||
enum response_type type, uint16_t dclass);
|
||||
|
||||
/**
|
||||
* Check if two replies are equal
|
||||
* For fallback procedures
|
||||
* @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, 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 */
|
||||
|
||||
+1010
-127
File diff suppressed because it is too large
Load Diff
+52
-6
@@ -50,11 +50,12 @@ struct iter_hints;
|
||||
struct iter_forwards;
|
||||
struct iter_donotq;
|
||||
struct iter_prep_list;
|
||||
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.
|
||||
*/
|
||||
@@ -64,12 +65,18 @@ struct iter_prep_list;
|
||||
* 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 4
|
||||
#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.
|
||||
@@ -86,12 +93,12 @@ struct iter_env {
|
||||
/** A flag to indicate whether or not we have an IPv6 route */
|
||||
int supports_ipv6;
|
||||
|
||||
/** Mapping of forwarding zones to targets. */
|
||||
struct iter_forwards* fwds;
|
||||
|
||||
/** A set of inetaddrs that should never be queried. */
|
||||
struct iter_donotq* donotq;
|
||||
|
||||
/** private address space and private domains */
|
||||
struct iter_priv* priv;
|
||||
|
||||
/** The maximum dependency depth that this resolver will pursue. */
|
||||
int max_dependency_depth;
|
||||
|
||||
@@ -145,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
|
||||
@@ -206,6 +217,8 @@ struct iter_qstate {
|
||||
struct query_info qchase;
|
||||
/** query flags to use when chasing the answer (i.e. RD flag) */
|
||||
uint16_t chase_flags;
|
||||
/** true if we set RD bit because of last resort recursion lame query*/
|
||||
int chase_to_rd;
|
||||
|
||||
/**
|
||||
* This is the current delegation point for an in-progress query. This
|
||||
@@ -214,6 +227,13 @@ struct iter_qstate {
|
||||
*/
|
||||
struct delegpt* dp;
|
||||
|
||||
/** state for 0x20 fallback when capsfail happens, 0 not a fallback */
|
||||
int caps_fallback;
|
||||
/** state for capsfail: current server number to try */
|
||||
size_t caps_server;
|
||||
/** state for capsfail: stored query for comparisons */
|
||||
struct reply_info* caps_reply;
|
||||
|
||||
/** Current delegation message - returned for non-RD queries */
|
||||
struct dns_msg* deleg_msg;
|
||||
|
||||
@@ -229,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
|
||||
@@ -236,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.
|
||||
@@ -270,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;
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "libunbound/unbound.h"
|
||||
#include "util/data/packed_rrset.h"
|
||||
struct libworker;
|
||||
struct tube;
|
||||
|
||||
/**
|
||||
* The context structure
|
||||
@@ -59,12 +60,12 @@ struct ub_ctx {
|
||||
/* --- pipes --- */
|
||||
/** mutex on query write pipe */
|
||||
lock_basic_t qqpipe_lock;
|
||||
/** the query write pipe, [0] read from, [1] write on */
|
||||
int qqpipe[2];
|
||||
/** the query write pipe */
|
||||
struct tube* qq_pipe;
|
||||
/** mutex on result read pipe */
|
||||
lock_basic_t rrpipe_lock;
|
||||
/** the result read pipe, [0] read from, [1] write on */
|
||||
int rrpipe[2];
|
||||
/** the result read pipe */
|
||||
struct tube* rr_pipe;
|
||||
|
||||
/* --- shared data --- */
|
||||
/** mutex for access to env.cfg, finalized and dothread */
|
||||
@@ -183,7 +184,9 @@ enum ub_ctx_err {
|
||||
/** error in pipe communication with async bg worker */
|
||||
UB_PIPE = -8,
|
||||
/** error reading from file (resolv.conf) */
|
||||
UB_READFILE = -9
|
||||
UB_READFILE = -9,
|
||||
/** error async_id does not exist or result already been delivered */
|
||||
UB_NOID = -10
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+255
-72
@@ -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"
|
||||
@@ -54,18 +55,36 @@
|
||||
#include "util/log.h"
|
||||
#include "util/random.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/tube.h"
|
||||
#include "services/modstack.h"
|
||||
#include "services/localzone.h"
|
||||
#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;
|
||||
#ifdef USE_WINSOCK
|
||||
int r;
|
||||
WSADATA wsa_data;
|
||||
#endif
|
||||
|
||||
log_init(NULL, 0, NULL); /* logs to stderr */
|
||||
log_ident_set("libunbound");
|
||||
#ifdef USE_WINSOCK
|
||||
if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) {
|
||||
log_err("could not init winsock. WSAStartup: %s",
|
||||
wsa_strerror(r));
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
verbosity = 0; /* errors only */
|
||||
checklock_start();
|
||||
ctx = (struct ub_ctx*)calloc(1, sizeof(*ctx));
|
||||
@@ -83,29 +102,16 @@ ub_ctx_create()
|
||||
return NULL;
|
||||
}
|
||||
seed = 0;
|
||||
if(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx->qqpipe) == -1) {
|
||||
ub_randfree(ctx->seed_rnd);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
if(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx->rrpipe) == -1) {
|
||||
if((ctx->qq_pipe = tube_create()) == NULL) {
|
||||
int e = errno;
|
||||
close(ctx->qqpipe[0]);
|
||||
close(ctx->qqpipe[1]);
|
||||
ub_randfree(ctx->seed_rnd);
|
||||
free(ctx);
|
||||
errno = e;
|
||||
return NULL;
|
||||
}
|
||||
if(!fd_set_nonblock(ctx->rrpipe[0]) ||
|
||||
!fd_set_nonblock(ctx->rrpipe[1]) ||
|
||||
!fd_set_nonblock(ctx->qqpipe[0]) ||
|
||||
!fd_set_nonblock(ctx->qqpipe[1])) {
|
||||
if((ctx->rr_pipe = tube_create()) == NULL) {
|
||||
int e = errno;
|
||||
close(ctx->rrpipe[0]);
|
||||
close(ctx->rrpipe[1]);
|
||||
close(ctx->qqpipe[0]);
|
||||
close(ctx->qqpipe[1]);
|
||||
tube_delete(ctx->qq_pipe);
|
||||
ub_randfree(ctx->seed_rnd);
|
||||
free(ctx);
|
||||
errno = e;
|
||||
@@ -116,10 +122,8 @@ ub_ctx_create()
|
||||
lock_basic_init(&ctx->cfglock);
|
||||
ctx->env = (struct module_env*)calloc(1, sizeof(*ctx->env));
|
||||
if(!ctx->env) {
|
||||
close(ctx->rrpipe[0]);
|
||||
close(ctx->rrpipe[1]);
|
||||
close(ctx->qqpipe[0]);
|
||||
close(ctx->qqpipe[1]);
|
||||
tube_delete(ctx->qq_pipe);
|
||||
tube_delete(ctx->rr_pipe);
|
||||
ub_randfree(ctx->seed_rnd);
|
||||
free(ctx);
|
||||
errno = ENOMEM;
|
||||
@@ -127,10 +131,8 @@ ub_ctx_create()
|
||||
}
|
||||
ctx->env->cfg = config_create_forlib();
|
||||
if(!ctx->env->cfg) {
|
||||
close(ctx->rrpipe[0]);
|
||||
close(ctx->rrpipe[1]);
|
||||
close(ctx->qqpipe[0]);
|
||||
close(ctx->qqpipe[1]);
|
||||
tube_delete(ctx->qq_pipe);
|
||||
tube_delete(ctx->rr_pipe);
|
||||
free(ctx->env);
|
||||
ub_randfree(ctx->seed_rnd);
|
||||
free(ctx);
|
||||
@@ -166,11 +168,11 @@ ub_ctx_delete(struct ub_ctx* ctx)
|
||||
uint32_t cmd = UB_LIBCMD_QUIT;
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
lock_basic_lock(&ctx->qqpipe_lock);
|
||||
(void)libworker_write_msg(ctx->qqpipe[1], (uint8_t*)&cmd,
|
||||
(void)tube_write_msg(ctx->qq_pipe, (uint8_t*)&cmd,
|
||||
(uint32_t)sizeof(cmd), 0);
|
||||
lock_basic_unlock(&ctx->qqpipe_lock);
|
||||
lock_basic_lock(&ctx->rrpipe_lock);
|
||||
while(libworker_read_msg(ctx->rrpipe[0], &msg, &len, 0)) {
|
||||
while(tube_read_msg(ctx->rr_pipe, &msg, &len, 0)) {
|
||||
/* discard all results except a quit confirm */
|
||||
if(context_serial_getcmd(msg, len) == UB_LIBCMD_QUIT) {
|
||||
free(msg);
|
||||
@@ -208,18 +210,8 @@ ub_ctx_delete(struct ub_ctx* ctx)
|
||||
lock_basic_destroy(&ctx->qqpipe_lock);
|
||||
lock_basic_destroy(&ctx->rrpipe_lock);
|
||||
lock_basic_destroy(&ctx->cfglock);
|
||||
if(ctx->qqpipe[0] != -1)
|
||||
close(ctx->qqpipe[0]);
|
||||
if(ctx->qqpipe[1] != -1)
|
||||
close(ctx->qqpipe[1]);
|
||||
if(ctx->rrpipe[0] != -1)
|
||||
close(ctx->rrpipe[0]);
|
||||
if(ctx->rrpipe[1] != -1)
|
||||
close(ctx->rrpipe[1]);
|
||||
ctx->qqpipe[0] = -1;
|
||||
ctx->qqpipe[1] = -1;
|
||||
ctx->rrpipe[0] = -1;
|
||||
ctx->rrpipe[1] = -1;
|
||||
tube_delete(ctx->qq_pipe);
|
||||
tube_delete(ctx->rr_pipe);
|
||||
if(ctx->env) {
|
||||
slabhash_delete(ctx->env->msg_cache);
|
||||
rrset_cache_delete(ctx->env->rrset_cache);
|
||||
@@ -231,6 +223,9 @@ ub_ctx_delete(struct ub_ctx* ctx)
|
||||
alloc_clear(&ctx->superalloc);
|
||||
traverse_postorder(&ctx->queries, delq, NULL);
|
||||
free(ctx);
|
||||
#ifdef USE_WINSOCK
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
@@ -249,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)
|
||||
{
|
||||
@@ -257,7 +265,7 @@ ub_ctx_config(struct ub_ctx* ctx, char* fname)
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
return UB_AFTERFINAL;
|
||||
}
|
||||
if(!config_read(ctx->env->cfg, fname)) {
|
||||
if(!config_read(ctx->env->cfg, fname, NULL)) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
return UB_SYNTAX;
|
||||
}
|
||||
@@ -273,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)) {
|
||||
@@ -292,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)) {
|
||||
@@ -311,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)) {
|
||||
@@ -345,7 +356,7 @@ int ub_ctx_debugout(struct ub_ctx* ctx, void* out)
|
||||
int
|
||||
ub_ctx_async(struct ub_ctx* ctx, int dothread)
|
||||
{
|
||||
#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
|
||||
#ifdef THREADS_DISABLED
|
||||
if(dothread) /* cannot do threading */
|
||||
return UB_NOERROR;
|
||||
#endif
|
||||
@@ -359,35 +370,17 @@ ub_ctx_async(struct ub_ctx* ctx, int dothread)
|
||||
return UB_NOERROR;
|
||||
}
|
||||
|
||||
/** perform a select() on the result read pipe */
|
||||
static int
|
||||
pollit(struct ub_ctx* ctx, struct timeval* t)
|
||||
{
|
||||
fd_set r;
|
||||
#ifndef S_SPLINT_S
|
||||
FD_ZERO(&r);
|
||||
FD_SET(ctx->rrpipe[0], &r);
|
||||
#endif
|
||||
if(select(ctx->rrpipe[0]+1, &r, NULL, NULL, t) == -1) {
|
||||
return 0;
|
||||
}
|
||||
errno = 0;
|
||||
return FD_ISSET(ctx->rrpipe[0], &r);
|
||||
}
|
||||
|
||||
int
|
||||
ub_poll(struct ub_ctx* ctx)
|
||||
{
|
||||
struct timeval t;
|
||||
memset(&t, 0, sizeof(t));
|
||||
/* no need to hold lock while testing for readability. */
|
||||
return pollit(ctx, &t);
|
||||
return tube_poll(ctx->rr_pipe);
|
||||
}
|
||||
|
||||
int
|
||||
ub_fd(struct ub_ctx* ctx)
|
||||
{
|
||||
return ctx->rrpipe[0];
|
||||
return tube_read_fd(ctx->rr_pipe);
|
||||
}
|
||||
|
||||
/** process answer from bg worker */
|
||||
@@ -484,12 +477,12 @@ ub_process(struct ub_ctx* ctx)
|
||||
while(1) {
|
||||
msg = NULL;
|
||||
lock_basic_lock(&ctx->rrpipe_lock);
|
||||
r = libworker_read_msg(ctx->rrpipe[0], &msg, &len, 1);
|
||||
r = tube_read_msg(ctx->rr_pipe, &msg, &len, 1);
|
||||
lock_basic_unlock(&ctx->rrpipe_lock);
|
||||
if(r == 0)
|
||||
return UB_PIPE;
|
||||
else if(r == -1)
|
||||
return UB_NOERROR;
|
||||
break;
|
||||
if(!process_answer(ctx, msg, len)) {
|
||||
free(msg);
|
||||
return UB_PIPE;
|
||||
@@ -510,7 +503,7 @@ ub_wait(struct ub_ctx* ctx)
|
||||
uint8_t* msg;
|
||||
uint32_t len;
|
||||
/* this is basically the same loop as _process(), but with changes.
|
||||
* holds the rrpipe lock and waits with pollit */
|
||||
* holds the rrpipe lock and waits with tube_wait */
|
||||
while(1) {
|
||||
lock_basic_lock(&ctx->rrpipe_lock);
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
@@ -527,9 +520,9 @@ ub_wait(struct ub_ctx* ctx)
|
||||
* o possibly decrementing num_async
|
||||
* do callback without lock
|
||||
*/
|
||||
r = pollit(ctx, NULL);
|
||||
r = tube_wait(ctx->rr_pipe);
|
||||
if(r) {
|
||||
r = libworker_read_msg(ctx->rrpipe[0], &msg, &len, 1);
|
||||
r = tube_read_msg(ctx->rr_pipe, &msg, &len, 1);
|
||||
if(r == 0) {
|
||||
lock_basic_unlock(&ctx->rrpipe_lock);
|
||||
return UB_PIPE;
|
||||
@@ -559,6 +552,7 @@ ub_resolve(struct ub_ctx* ctx, char* name, int rrtype,
|
||||
{
|
||||
struct ctx_query* q;
|
||||
int r;
|
||||
*result = NULL;
|
||||
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
if(!ctx->finalized) {
|
||||
@@ -574,7 +568,6 @@ ub_resolve(struct ub_ctx* ctx, char* name, int rrtype,
|
||||
if(!q)
|
||||
return UB_NOMEM;
|
||||
/* become a resolver thread for a bit */
|
||||
*result = NULL;
|
||||
|
||||
r = libworker_fg(ctx, q);
|
||||
if(r) {
|
||||
@@ -650,7 +643,7 @@ ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype,
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
|
||||
lock_basic_lock(&ctx->qqpipe_lock);
|
||||
if(!libworker_write_msg(ctx->qqpipe[1], msg, len, 0)) {
|
||||
if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) {
|
||||
lock_basic_unlock(&ctx->qqpipe_lock);
|
||||
free(msg);
|
||||
return UB_PIPE;
|
||||
@@ -671,7 +664,7 @@ ub_cancel(struct ub_ctx* ctx, int async_id)
|
||||
if(!q || !q->async) {
|
||||
/* it is not there, so nothing to do */
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
return UB_NOERROR;
|
||||
return UB_NOID;
|
||||
}
|
||||
log_assert(q->async);
|
||||
q->cancelled = 1;
|
||||
@@ -688,7 +681,7 @@ ub_cancel(struct ub_ctx* ctx, int async_id)
|
||||
}
|
||||
/* send cancel to background worker */
|
||||
lock_basic_lock(&ctx->qqpipe_lock);
|
||||
if(!libworker_write_msg(ctx->qqpipe[1], msg, len, 0)) {
|
||||
if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) {
|
||||
lock_basic_unlock(&ctx->qqpipe_lock);
|
||||
free(msg);
|
||||
return UB_PIPE;
|
||||
@@ -715,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);
|
||||
}
|
||||
|
||||
@@ -732,6 +726,7 @@ ub_strerror(int err)
|
||||
case UB_AFTERFINAL: return "setting change after finalize";
|
||||
case UB_PIPE: return "error in pipe communication with async";
|
||||
case UB_READFILE: return "error reading file";
|
||||
case UB_NOID: return "error async_id does not exist";
|
||||
default: return "unknown error";
|
||||
}
|
||||
}
|
||||
@@ -816,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) */
|
||||
@@ -868,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) */
|
||||
@@ -934,3 +991,129 @@ ub_ctx_hosts(struct ub_ctx* ctx, char* fname)
|
||||
fclose(in);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
|
||||
/** finalize the context, if not already finalized */
|
||||
static int ub_ctx_finalize(struct ub_ctx* ctx)
|
||||
{
|
||||
int res = 0;
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
if (!ctx->finalized) {
|
||||
res = context_finalize(ctx);
|
||||
}
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Print local zones and RR data */
|
||||
int ub_ctx_print_local_zones(struct ub_ctx* ctx)
|
||||
{
|
||||
int res = ub_ctx_finalize(ctx);
|
||||
if (res) return res;
|
||||
|
||||
local_zones_print(ctx->local_zones);
|
||||
|
||||
return UB_NOERROR;
|
||||
}
|
||||
|
||||
/* Add a new zone */
|
||||
int ub_ctx_zone_add(struct ub_ctx* ctx, char *zone_name, char *zone_type)
|
||||
{
|
||||
enum localzone_type t;
|
||||
struct local_zone* z;
|
||||
uint8_t* nm;
|
||||
int nmlabs;
|
||||
size_t nmlen;
|
||||
|
||||
int res = ub_ctx_finalize(ctx);
|
||||
if (res) return res;
|
||||
|
||||
if(!local_zone_str2type(zone_type, &t)) {
|
||||
return UB_SYNTAX;
|
||||
}
|
||||
|
||||
if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) {
|
||||
return UB_SYNTAX;
|
||||
}
|
||||
|
||||
lock_quick_lock(&ctx->local_zones->lock);
|
||||
if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs,
|
||||
LDNS_RR_CLASS_IN))) {
|
||||
/* already present in tree */
|
||||
lock_rw_wrlock(&z->lock);
|
||||
z->type = t; /* update type anyway */
|
||||
lock_rw_unlock(&z->lock);
|
||||
lock_quick_unlock(&ctx->local_zones->lock);
|
||||
free(nm);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
if(!local_zones_add_zone(ctx->local_zones, nm, nmlen, nmlabs,
|
||||
LDNS_RR_CLASS_IN, t)) {
|
||||
lock_quick_unlock(&ctx->local_zones->lock);
|
||||
return UB_NOMEM;
|
||||
}
|
||||
lock_quick_unlock(&ctx->local_zones->lock);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
|
||||
/* Remove zone */
|
||||
int ub_ctx_zone_remove(struct ub_ctx* ctx, char *zone_name)
|
||||
{
|
||||
struct local_zone* z;
|
||||
uint8_t* nm;
|
||||
int nmlabs;
|
||||
size_t nmlen;
|
||||
|
||||
int res = ub_ctx_finalize(ctx);
|
||||
if (res) return res;
|
||||
|
||||
if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) {
|
||||
return UB_SYNTAX;
|
||||
}
|
||||
|
||||
lock_quick_lock(&ctx->local_zones->lock);
|
||||
if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs,
|
||||
LDNS_RR_CLASS_IN))) {
|
||||
/* present in tree */
|
||||
local_zones_del_zone(ctx->local_zones, z);
|
||||
}
|
||||
lock_quick_unlock(&ctx->local_zones->lock);
|
||||
free(nm);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
|
||||
/* Add new RR data */
|
||||
int ub_ctx_data_add(struct ub_ctx* ctx, char *data)
|
||||
{
|
||||
ldns_buffer* buf;
|
||||
int res = ub_ctx_finalize(ctx);
|
||||
if (res) return res;
|
||||
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
buf = ldns_buffer_new(ctx->env->cfg->msg_buffer_size);
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
if(!buf) return UB_NOMEM;
|
||||
|
||||
res = local_zones_add_RR(ctx->local_zones, data, buf);
|
||||
|
||||
ldns_buffer_free(buf);
|
||||
return (!res) ? UB_NOMEM : UB_NOERROR;
|
||||
}
|
||||
|
||||
/* Remove RR data */
|
||||
int ub_ctx_data_remove(struct ub_ctx* ctx, char *data)
|
||||
{
|
||||
uint8_t* nm;
|
||||
int nmlabs;
|
||||
size_t nmlen;
|
||||
int res = ub_ctx_finalize(ctx);
|
||||
if (res) return res;
|
||||
|
||||
if(!parse_dname(data, &nm, &nmlen, &nmlabs))
|
||||
return UB_SYNTAX;
|
||||
|
||||
local_zones_del_data(ctx->local_zones, nm, nmlen, nmlabs,
|
||||
LDNS_RR_CLASS_IN);
|
||||
|
||||
free(nm);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
|
||||
+158
-315
@@ -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"
|
||||
@@ -60,6 +62,8 @@
|
||||
#include "util/data/dname.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/data/msgencode.h"
|
||||
#include "util/tube.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
|
||||
/** handle new query command for bg worker */
|
||||
static void handle_newq(struct libworker* w, uint8_t* buf, uint32_t len);
|
||||
@@ -70,18 +74,17 @@ libworker_delete(struct libworker* w)
|
||||
{
|
||||
if(!w) return;
|
||||
if(w->env) {
|
||||
outside_network_quit_prepare(w->back);
|
||||
mesh_delete(w->env->mesh);
|
||||
context_release_alloc(w->ctx, w->env->alloc,
|
||||
!w->is_bg || w->is_bg_thread);
|
||||
ldns_buffer_free(w->env->scratch_buffer);
|
||||
regional_destroy(w->env->scratch);
|
||||
forwards_delete(w->env->fwds);
|
||||
ub_randfree(w->env->rnd);
|
||||
free(w->env);
|
||||
}
|
||||
free(w->cmd_msg);
|
||||
outside_network_delete(w->back);
|
||||
comm_point_delete(w->cmd_com);
|
||||
comm_point_delete(w->res_com);
|
||||
comm_base_delete(w->base);
|
||||
free(w);
|
||||
}
|
||||
@@ -116,14 +119,20 @@ libworker_setup(struct ub_ctx* ctx, int is_bg)
|
||||
}
|
||||
w->env->scratch = regional_create_custom(cfg->msg_buffer_size);
|
||||
w->env->scratch_buffer = ldns_buffer_new(cfg->msg_buffer_size);
|
||||
w->env->fwds = forwards_create();
|
||||
if(w->env->fwds && !forwards_apply_cfg(w->env->fwds, cfg)) {
|
||||
forwards_delete(w->env->fwds);
|
||||
w->env->fwds = NULL;
|
||||
}
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
}
|
||||
if(!w->env->scratch || !w->env->scratch_buffer) {
|
||||
if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds) {
|
||||
libworker_delete(w);
|
||||
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;
|
||||
@@ -143,7 +152,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg)
|
||||
}
|
||||
seed = 0;
|
||||
|
||||
w->base = comm_base_create();
|
||||
w->base = comm_base_create(0);
|
||||
if(!w->base) {
|
||||
libworker_delete(w);
|
||||
return NULL;
|
||||
@@ -161,7 +170,8 @@ libworker_setup(struct ub_ctx* ctx, int is_bg)
|
||||
cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6,
|
||||
cfg->do_tcp?cfg->outgoing_num_tcp:0,
|
||||
w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id,
|
||||
ports, numports);
|
||||
ports, numports, cfg->unwanted_threshold,
|
||||
&libworker_alloc_cleanup, w, cfg->do_udp);
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
}
|
||||
@@ -175,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;
|
||||
@@ -230,130 +239,19 @@ libworker_do_cmd(struct libworker* w, uint8_t* msg, uint32_t len)
|
||||
}
|
||||
|
||||
/** handle control command coming into server */
|
||||
int
|
||||
libworker_handle_control_cmd(struct comm_point* c, void* arg,
|
||||
int ATTR_UNUSED(err), struct comm_reply* ATTR_UNUSED(rep))
|
||||
void
|
||||
libworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube),
|
||||
uint8_t* msg, size_t len, int err, void* arg)
|
||||
{
|
||||
struct libworker* w = (struct libworker*)arg;
|
||||
ssize_t r;
|
||||
|
||||
if(w->cmd_read < sizeof(w->cmd_len)) {
|
||||
/* complete reading the length of control msg */
|
||||
r = read(c->fd, ((uint8_t*)&w->cmd_len) + w->cmd_read,
|
||||
sizeof(w->cmd_len) - w->cmd_read);
|
||||
if(r==0) {
|
||||
/* error has happened or */
|
||||
/* parent closed pipe, must have exited somehow */
|
||||
/* it is of no use to go on, exit */
|
||||
comm_base_exit(w->base);
|
||||
return 0;
|
||||
}
|
||||
if(r==-1) {
|
||||
if(errno != EAGAIN && errno != EINTR) {
|
||||
log_err("rpipe error: %s", strerror(errno));
|
||||
}
|
||||
/* nothing to read now, try later */
|
||||
return 0;
|
||||
}
|
||||
w->cmd_read += r;
|
||||
if(w->cmd_read < sizeof(w->cmd_len)) {
|
||||
/* not complete, try later */
|
||||
return 0;
|
||||
}
|
||||
w->cmd_msg = (uint8_t*)calloc(1, w->cmd_len);
|
||||
if(!w->cmd_msg) {
|
||||
log_err("malloc failure");
|
||||
w->cmd_read = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* cmd_len has been read, read remainder */
|
||||
r = read(c->fd, w->cmd_msg + w->cmd_read - sizeof(w->cmd_len),
|
||||
w->cmd_len - (w->cmd_read - sizeof(w->cmd_len)));
|
||||
if(r==0) {
|
||||
/* error has happened or */
|
||||
/* parent closed pipe, must have exited somehow */
|
||||
if(err != 0) {
|
||||
free(msg);
|
||||
/* it is of no use to go on, exit */
|
||||
comm_base_exit(w->base);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
if(r==-1) {
|
||||
/* nothing to read now, try later */
|
||||
if(errno != EAGAIN && errno != EINTR) {
|
||||
log_err("rpipe error: %s", strerror(errno));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
w->cmd_read += r;
|
||||
if(w->cmd_read < sizeof(w->cmd_len) + w->cmd_len) {
|
||||
/* not complete, try later */
|
||||
return 0;
|
||||
}
|
||||
w->cmd_read = 0;
|
||||
libworker_do_cmd(w, w->cmd_msg, w->cmd_len); /* also frees the buf */
|
||||
w->cmd_msg = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** handle opportunity to write result back */
|
||||
int
|
||||
libworker_handle_result_write(struct comm_point* c, void* arg,
|
||||
int ATTR_UNUSED(err), struct comm_reply* ATTR_UNUSED(rep))
|
||||
{
|
||||
struct libworker* w = (struct libworker*)arg;
|
||||
struct libworker_res_list* item = w->res_list;
|
||||
ssize_t r;
|
||||
if(!item) {
|
||||
comm_point_stop_listening(c);
|
||||
return 0;
|
||||
}
|
||||
if(w->res_write < sizeof(item->len)) {
|
||||
r = write(c->fd, ((uint8_t*)&item->len) + w->res_write,
|
||||
sizeof(item->len) - w->res_write);
|
||||
if(r == -1) {
|
||||
if(errno != EAGAIN && errno != EINTR) {
|
||||
log_err("wpipe error: %s", strerror(errno));
|
||||
}
|
||||
return 0; /* try again later */
|
||||
}
|
||||
if(r == 0) {
|
||||
/* error on pipe, must have exited somehow */
|
||||
/* it is of no use to go on, exit */
|
||||
comm_base_exit(w->base);
|
||||
return 0;
|
||||
}
|
||||
w->res_write += r;
|
||||
if(w->res_write < sizeof(item->len))
|
||||
return 0;
|
||||
}
|
||||
r = write(c->fd, item->buf + w->res_write - sizeof(item->len),
|
||||
item->len - (w->res_write - sizeof(item->len)));
|
||||
if(r == -1) {
|
||||
if(errno != EAGAIN && errno != EINTR) {
|
||||
log_err("wpipe error: %s", strerror(errno));
|
||||
}
|
||||
return 0; /* try again later */
|
||||
}
|
||||
if(r == 0) {
|
||||
/* error on pipe, must have exited somehow */
|
||||
/* it is of no use to go on, exit */
|
||||
comm_base_exit(w->base);
|
||||
return 0;
|
||||
}
|
||||
w->res_write += r;
|
||||
if(w->res_write < sizeof(item->len) + item->len)
|
||||
return 0;
|
||||
/* done this result, remove it */
|
||||
free(item->buf);
|
||||
item->buf = NULL;
|
||||
w->res_list = w->res_list->next;
|
||||
free(item);
|
||||
if(!w->res_list) {
|
||||
w->res_last = NULL;
|
||||
comm_point_stop_listening(c);
|
||||
}
|
||||
w->res_write = 0;
|
||||
return 0;
|
||||
libworker_do_cmd(w, msg, len); /* also frees the buf */
|
||||
}
|
||||
|
||||
/** the background thread func */
|
||||
@@ -362,35 +260,27 @@ libworker_dobg(void* arg)
|
||||
{
|
||||
/* setup */
|
||||
uint32_t m;
|
||||
int fd;
|
||||
struct libworker* w = (struct libworker*)arg;
|
||||
struct ub_ctx* ctx = w->ctx;
|
||||
log_thread_set(&w->thread_num);
|
||||
#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
|
||||
#ifdef THREADS_DISABLED
|
||||
/* we are forked */
|
||||
w->is_bg_thread = 0;
|
||||
/* close non-used parts of the pipes */
|
||||
if(ctx->qqpipe[1] != -1) {
|
||||
close(ctx->qqpipe[1]);
|
||||
ctx->qqpipe[1] = -1;
|
||||
}
|
||||
if(ctx->rrpipe[0] != -1) {
|
||||
close(ctx->rrpipe[0]);
|
||||
ctx->rrpipe[0] = -1;
|
||||
}
|
||||
tube_close_write(ctx->qq_pipe);
|
||||
tube_close_read(ctx->rr_pipe);
|
||||
#endif
|
||||
if(!w) {
|
||||
log_err("libunbound bg worker init failed, nomem");
|
||||
return NULL;
|
||||
}
|
||||
if(!(w->cmd_com=comm_point_create_raw(w->base, ctx->qqpipe[0], 0,
|
||||
libworker_handle_control_cmd, w))) {
|
||||
log_err("libunbound bg worker init failed, no cmdcom");
|
||||
if(!tube_setup_bg_listen(ctx->qq_pipe, w->base,
|
||||
libworker_handle_control_cmd, w)) {
|
||||
log_err("libunbound bg worker init failed, no bglisten");
|
||||
return NULL;
|
||||
}
|
||||
if(!(w->res_com=comm_point_create_raw(w->base, ctx->rrpipe[1], 1,
|
||||
libworker_handle_result_write, w))) {
|
||||
log_err("libunbound bg worker init failed, no rescom");
|
||||
if(!tube_setup_bg_write(ctx->rr_pipe, w->base)) {
|
||||
log_err("libunbound bg worker init failed, no bgwrite");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -398,14 +288,17 @@ libworker_dobg(void* arg)
|
||||
comm_base_dispatch(w->base);
|
||||
|
||||
/* cleanup */
|
||||
fd = ctx->rrpipe[1];
|
||||
ctx->rrpipe[1] = -1;
|
||||
m = UB_LIBCMD_QUIT;
|
||||
tube_remove_bg_listen(w->ctx->qq_pipe);
|
||||
tube_remove_bg_write(w->ctx->rr_pipe);
|
||||
libworker_delete(w);
|
||||
close(ctx->qqpipe[0]);
|
||||
ctx->qqpipe[0] = -1;
|
||||
(void)libworker_write_msg(fd, (uint8_t*)&m, (uint32_t)sizeof(m), 0);
|
||||
close(fd);
|
||||
(void)tube_write_msg(ctx->rr_pipe, (uint8_t*)&m,
|
||||
(uint32_t)sizeof(m), 0);
|
||||
#ifdef THREADS_DISABLED
|
||||
/* close pipes from forked process before exit */
|
||||
tube_close_read(ctx->qq_pipe);
|
||||
tube_close_write(ctx->rr_pipe);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -425,15 +318,17 @@ int libworker_bg(struct ub_ctx* ctx)
|
||||
ub_thread_create(&ctx->bg_tid, libworker_dobg, w);
|
||||
} else {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
#ifndef HAVE_FORK
|
||||
/* no fork on windows */
|
||||
return UB_FORKFAIL;
|
||||
#else /* HAVE_FORK */
|
||||
switch((ctx->bg_pid=fork())) {
|
||||
case 0:
|
||||
w = libworker_setup(ctx, 1);
|
||||
if(!w) fatal_exit("out of memory");
|
||||
/* close non-used parts of the pipes */
|
||||
close(ctx->qqpipe[1]);
|
||||
close(ctx->rrpipe[0]);
|
||||
ctx->qqpipe[1] = -1;
|
||||
ctx->rrpipe[0] = -1;
|
||||
tube_close_write(ctx->qq_pipe);
|
||||
tube_close_read(ctx->rr_pipe);
|
||||
(void)libworker_dobg(w);
|
||||
exit(0);
|
||||
break;
|
||||
@@ -442,6 +337,7 @@ int libworker_bg(struct ub_ctx* ctx)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif /* HAVE_FORK */
|
||||
}
|
||||
return UB_NOERROR;
|
||||
}
|
||||
@@ -543,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;
|
||||
@@ -564,15 +462,15 @@ libworker_fillup_fg(struct ctx_query* q, int rcode, ldns_buffer* buf,
|
||||
libworker_enter_result(q->res, buf, q->w->env->scratch, s);
|
||||
}
|
||||
|
||||
/** callback with fg results */
|
||||
static void
|
||||
libworker_fg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s)
|
||||
void
|
||||
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 */
|
||||
@@ -587,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;
|
||||
@@ -621,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;
|
||||
@@ -645,22 +551,29 @@ 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;
|
||||
struct libworker_res_list* item;
|
||||
|
||||
/* serialize and delete unneeded q */
|
||||
if(w->is_bg_thread) {
|
||||
lock_basic_lock(&w->ctx->cfglock);
|
||||
q->msg_len = ldns_buffer_remaining(pkt);
|
||||
q->msg = memdup(ldns_buffer_begin(pkt), q->msg_len);
|
||||
if(!q->msg)
|
||||
msg = context_serialize_answer(q, UB_NOMEM, NULL, &len);
|
||||
else msg = context_serialize_answer(q, err, NULL, &len);
|
||||
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);
|
||||
if(!q->msg)
|
||||
msg = context_serialize_answer(q, UB_NOMEM,
|
||||
NULL, &len);
|
||||
else msg = context_serialize_answer(q, err,
|
||||
NULL, &len);
|
||||
} else msg = context_serialize_answer(q, err, NULL, &len);
|
||||
lock_basic_unlock(&w->ctx->cfglock);
|
||||
} else {
|
||||
if(reason)
|
||||
q->res->why_bogus = strdup(reason);
|
||||
msg = context_serialize_answer(q, err, pkt, &len);
|
||||
(void)rbtree_delete(&w->ctx->queries, q->node.key);
|
||||
w->ctx->num_async--;
|
||||
@@ -671,29 +584,15 @@ add_bg_result(struct libworker* w, struct ctx_query* q, ldns_buffer* pkt,
|
||||
log_err("out of memory for async answer");
|
||||
return;
|
||||
}
|
||||
item = (struct libworker_res_list*)malloc(sizeof(*item));
|
||||
if(!item) {
|
||||
free(msg);
|
||||
if(!tube_queue_item(w->ctx->rr_pipe, msg, len)) {
|
||||
log_err("out of memory for async answer");
|
||||
return;
|
||||
}
|
||||
item->buf = msg;
|
||||
item->len = len;
|
||||
item->next = NULL;
|
||||
/* add at back of list, since the first one may be partially written */
|
||||
if(w->res_last)
|
||||
w->res_last->next = item;
|
||||
else w->res_list = item;
|
||||
w->res_last = item;
|
||||
if(w->res_list == w->res_last) {
|
||||
/* first added item, start the write process */
|
||||
comm_point_start_listening(w->res_com, -1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
/** callback with bg results */
|
||||
static void
|
||||
libworker_bg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s)
|
||||
void
|
||||
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;
|
||||
|
||||
@@ -714,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -739,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;
|
||||
@@ -749,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;
|
||||
}
|
||||
@@ -758,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);
|
||||
}
|
||||
@@ -770,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)
|
||||
@@ -795,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;
|
||||
@@ -805,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;
|
||||
}
|
||||
@@ -825,7 +713,7 @@ libworker_handle_reply(struct comm_point* c, void* arg, int error,
|
||||
e.qsent = NULL;
|
||||
|
||||
if(error != 0) {
|
||||
mesh_report_reply(lw->env->mesh, &e, 0, reply_info);
|
||||
mesh_report_reply(lw->env->mesh, &e, reply_info, error);
|
||||
return 0;
|
||||
}
|
||||
/* sanity check. */
|
||||
@@ -835,10 +723,11 @@ libworker_handle_reply(struct comm_point* c, void* arg, int error,
|
||||
|| LDNS_QDCOUNT(ldns_buffer_begin(c->buffer)) > 1) {
|
||||
/* error becomes timeout for the module as if this reply
|
||||
* never arrived. */
|
||||
mesh_report_reply(lw->env->mesh, &e, 0, reply_info);
|
||||
mesh_report_reply(lw->env->mesh, &e, reply_info,
|
||||
NETEVENT_TIMEOUT);
|
||||
return 0;
|
||||
}
|
||||
mesh_report_reply(lw->env->mesh, &e, 1, reply_info);
|
||||
mesh_report_reply(lw->env->mesh, &e, reply_info, NETEVENT_NOERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -850,7 +739,7 @@ libworker_handle_service_reply(struct comm_point* c, void* arg, int error,
|
||||
struct libworker* lw = (struct libworker*)e->qstate->env->worker;
|
||||
|
||||
if(error != 0) {
|
||||
mesh_report_reply(lw->env->mesh, e, 0, reply_info);
|
||||
mesh_report_reply(lw->env->mesh, e, reply_info, error);
|
||||
return 0;
|
||||
}
|
||||
/* sanity check. */
|
||||
@@ -860,110 +749,20 @@ libworker_handle_service_reply(struct comm_point* c, void* arg, int error,
|
||||
|| LDNS_QDCOUNT(ldns_buffer_begin(c->buffer)) > 1) {
|
||||
/* error becomes timeout for the module as if this reply
|
||||
* never arrived. */
|
||||
mesh_report_reply(lw->env->mesh, e, 0, reply_info);
|
||||
mesh_report_reply(lw->env->mesh, e, reply_info,
|
||||
NETEVENT_TIMEOUT);
|
||||
return 0;
|
||||
}
|
||||
mesh_report_reply(lw->env->mesh, e, 1, reply_info);
|
||||
mesh_report_reply(lw->env->mesh, e, reply_info, NETEVENT_NOERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
libworker_write_msg(int fd, uint8_t* buf, uint32_t len, int nonblock)
|
||||
{
|
||||
ssize_t r;
|
||||
/* test */
|
||||
if(nonblock) {
|
||||
r = write(fd, &len, sizeof(len));
|
||||
if(r == -1) {
|
||||
if(errno==EINTR || errno==EAGAIN)
|
||||
return -1;
|
||||
log_err("msg write failed: %s", strerror(errno));
|
||||
return -1; /* can still continue, perhaps */
|
||||
}
|
||||
} else r = 0;
|
||||
if(!fd_set_block(fd))
|
||||
return 0;
|
||||
/* write remainder */
|
||||
if(r != (ssize_t)sizeof(len)) {
|
||||
if(write(fd, (char*)(&len)+r, sizeof(len)-r) == -1) {
|
||||
log_err("msg write failed: %s", strerror(errno));
|
||||
(void)fd_set_nonblock(fd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if(write(fd, buf, len) == -1) {
|
||||
log_err("msg write failed: %s", strerror(errno));
|
||||
(void)fd_set_nonblock(fd);
|
||||
return 0;
|
||||
}
|
||||
if(!fd_set_nonblock(fd))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
libworker_read_msg(int fd, uint8_t** buf, uint32_t* len, int nonblock)
|
||||
{
|
||||
ssize_t r;
|
||||
|
||||
/* test */
|
||||
*len = 0;
|
||||
if(nonblock) {
|
||||
r = read(fd, len, sizeof(*len));
|
||||
if(r == -1) {
|
||||
if(errno==EINTR || errno==EAGAIN)
|
||||
return -1;
|
||||
log_err("msg read failed: %s", strerror(errno));
|
||||
return -1; /* we can still continue, perhaps */
|
||||
}
|
||||
if(r == 0) /* EOF */
|
||||
return 0;
|
||||
} else r = 0;
|
||||
if(!fd_set_block(fd))
|
||||
return 0;
|
||||
/* read remainder */
|
||||
if(r != (ssize_t)sizeof(*len)) {
|
||||
if((r=read(fd, (char*)(len)+r, sizeof(*len)-r)) == -1) {
|
||||
log_err("msg read failed: %s", strerror(errno));
|
||||
(void)fd_set_nonblock(fd);
|
||||
return 0;
|
||||
}
|
||||
if(r == 0) /* EOF */ {
|
||||
(void)fd_set_nonblock(fd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*buf = (uint8_t*)malloc(*len);
|
||||
if(!*buf) {
|
||||
log_err("out of memory");
|
||||
(void)fd_set_nonblock(fd);
|
||||
return 0;
|
||||
}
|
||||
if((r=read(fd, *buf, *len)) == -1) {
|
||||
log_err("msg read failed: %s", strerror(errno));
|
||||
(void)fd_set_nonblock(fd);
|
||||
free(*buf);
|
||||
return 0;
|
||||
}
|
||||
if(r == 0) { /* EOF */
|
||||
(void)fd_set_nonblock(fd);
|
||||
free(*buf);
|
||||
return 0;
|
||||
}
|
||||
if(!fd_set_nonblock(fd)) {
|
||||
free(*buf);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* --- fake callbacks for fptr_wlist to work --- */
|
||||
int worker_handle_control_cmd(struct comm_point* ATTR_UNUSED(c),
|
||||
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
|
||||
struct comm_reply* ATTR_UNUSED(reply_info))
|
||||
void worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube),
|
||||
uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len),
|
||||
int ATTR_UNUSED(error), void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int worker_handle_request(struct comm_point* ATTR_UNUSED(c),
|
||||
@@ -990,24 +789,32 @@ int worker_handle_service_reply(struct comm_point* ATTR_UNUSED(c),
|
||||
return 0;
|
||||
}
|
||||
|
||||
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))
|
||||
int remote_accept_callback(struct comm_point* ATTR_UNUSED(c),
|
||||
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
|
||||
struct comm_reply* ATTR_UNUSED(repinfo))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int remote_control_callback(struct comm_point* ATTR_UNUSED(c),
|
||||
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
|
||||
struct comm_reply* ATTR_UNUSED(repinfo))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(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);
|
||||
@@ -1020,14 +827,50 @@ worker_alloc_cleanup(void* ATTR_UNUSED(arg))
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
int
|
||||
acl_list_cmp(const void* ATTR_UNUSED(k1), const void* ATTR_UNUSED(k2))
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void worker_stat_timer_cb(void* ATTR_UNUSED(arg))
|
||||
int
|
||||
codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||
{
|
||||
log_assert(0);
|
||||
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*
|
||||
ATTR_UNUSED(arg)) {
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void
|
||||
wsvc_cron_cb(void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
#endif /* UB_ON_WINDOWS */
|
||||
|
||||
+13
-83
@@ -55,8 +55,8 @@ struct outbound_entry;
|
||||
struct module_qstate;
|
||||
struct comm_point;
|
||||
struct comm_reply;
|
||||
struct libworker_res_list;
|
||||
struct regional;
|
||||
struct tube;
|
||||
|
||||
/**
|
||||
* The library-worker status structure
|
||||
@@ -81,37 +81,6 @@ struct libworker {
|
||||
struct outside_network* back;
|
||||
/** random() table for this worker. */
|
||||
struct ub_randstate* rndstate;
|
||||
|
||||
/** commpoint to listen to commands */
|
||||
struct comm_point* cmd_com;
|
||||
/** are we currently reading a command, 0 if not, else bytecount */
|
||||
size_t cmd_read;
|
||||
/** size of current read command, may be partially read */
|
||||
uint32_t cmd_len;
|
||||
/** the current read command content, malloced, can be partially read*/
|
||||
uint8_t* cmd_msg;
|
||||
|
||||
/** commpoint to write results back */
|
||||
struct comm_point* res_com;
|
||||
/** are we curently writing a result, 0 if not, else bytecount into
|
||||
* the res_list first entry. */
|
||||
size_t res_write;
|
||||
/** list of outstanding results to be written back */
|
||||
struct libworker_res_list* res_list;
|
||||
/** last in list */
|
||||
struct libworker_res_list* res_last;
|
||||
};
|
||||
|
||||
/**
|
||||
* List of results (arbitrary command serializations) to write back
|
||||
*/
|
||||
struct libworker_res_list {
|
||||
/** next in list */
|
||||
struct libworker_res_list* next;
|
||||
/** serialized buffer to write */
|
||||
uint8_t* buf;
|
||||
/** length to write */
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -138,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)
|
||||
@@ -160,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.
|
||||
@@ -168,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 */
|
||||
@@ -180,46 +136,20 @@ int libworker_handle_service_reply(struct comm_point* c, void* arg, int error,
|
||||
struct comm_reply* reply_info);
|
||||
|
||||
/** handle control command coming into server */
|
||||
int libworker_handle_control_cmd(struct comm_point* c, void* arg,
|
||||
int err, struct comm_reply* rep);
|
||||
void libworker_handle_control_cmd(struct tube* tube, uint8_t* msg, size_t len,
|
||||
int err, void* arg);
|
||||
|
||||
/** handle opportunity to write result back */
|
||||
int libworker_handle_result_write(struct comm_point* c, void* arg,
|
||||
int err, struct comm_reply* rep);
|
||||
void libworker_handle_result_write(struct tube* tube, uint8_t* msg, size_t len,
|
||||
int err, void* arg);
|
||||
|
||||
/**
|
||||
* Write length bytes followed by message.
|
||||
* @param fd: the socket to write on. Is nonblocking.
|
||||
* Set to blocking by the function,
|
||||
* and back to non-blocking at exit of function.
|
||||
* @param buf: the message.
|
||||
* @param len: length of message.
|
||||
* @param nonblock: if set to true, the first write is nonblocking.
|
||||
* If the first write fails the function returns -1.
|
||||
* If set false, the first write is blocking.
|
||||
* @return: all remainder writes are nonblocking.
|
||||
* return 0 on error, in that case blocking/nonblocking of socket is
|
||||
* unknown.
|
||||
* return 1 if all OK.
|
||||
*/
|
||||
int libworker_write_msg(int fd, uint8_t* buf, uint32_t len, int nonblock);
|
||||
/** mesh callback with fg results */
|
||||
void libworker_fg_done_cb(void* arg, int rcode, ldns_buffer* buf,
|
||||
enum sec_status s, char* why_bogus);
|
||||
|
||||
/**
|
||||
* Read length bytes followed by message.
|
||||
* @param fd: the socket to write on. Is nonblocking.
|
||||
* Set to blocking by the function,
|
||||
* and back to non-blocking at exit of function.
|
||||
* @param buf: the message, malloced.
|
||||
* @param len: length of message, returned.
|
||||
* @param nonblock: if set to true, the first read is nonblocking.
|
||||
* If the first read fails the function returns -1.
|
||||
* If set false, the first read is blocking.
|
||||
* @return: all remainder reads are nonblocking.
|
||||
* return 0 on error, in that case blocking/nonblocking of socket is
|
||||
* unknown. On EOF 0 is returned.
|
||||
* return 1 if all OK.
|
||||
*/
|
||||
int libworker_read_msg(int fd, uint8_t** buf, uint32_t* len, int nonblock);
|
||||
/** mesh callback with bg results */
|
||||
void libworker_bg_done_cb(void* arg, int rcode, ldns_buffer* buf,
|
||||
enum sec_status s, char* why_bogus);
|
||||
|
||||
/**
|
||||
* fill result from parsed message, on error fills servfail
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
|
||||
Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz)
|
||||
|
||||
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 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 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.
|
||||
@@ -0,0 +1,75 @@
|
||||
#
|
||||
# Makefile: compilation of pyUnbound and documentation, testing
|
||||
#
|
||||
# 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.
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " testenv to make test environment and run bash "
|
||||
@echo " usefull in case you don't want to install unbound but want to test examples"
|
||||
@echo " doc to make documentation"
|
||||
@echo " clean clean all"
|
||||
|
||||
.PHONY: testenv clean doc swig
|
||||
|
||||
#_unbound.so: ../../Makefile
|
||||
#$(MAKE) -C ../..
|
||||
|
||||
#../../.libs/libunbound.so.0: ../../Makefile
|
||||
#$(MAKE) -C ../..
|
||||
|
||||
#../../ldns-src/lib/libldns.so: ../../ldns-src/Makefile
|
||||
#$(MAKE) -C ../../ldns-src
|
||||
|
||||
clean:
|
||||
rm -rdf examples/unbound
|
||||
rm -f _unbound.so libunbound_wrap.o
|
||||
$(MAKE) -C ../.. clean
|
||||
|
||||
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.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
|
||||
rm -rdf examples/unbound examples/_unbound.so
|
||||
|
||||
doc: ../../.libs/libunbound.so.0 _unbound.so
|
||||
$(MAKE) -C docs html
|
||||
|
||||
#for development only
|
||||
swig: libunbound.i
|
||||
swig -python -o libunbound_wrap.c -I../.. libunbound.i
|
||||
gcc -c libunbound_wrap.c -O9 -fPIC -I../.. -I/usr/include/python2.5 -I. -o libunbound_wrap.o
|
||||
gcc -shared libunbound_wrap.o -L../../.libs -lunbound -o _unbound.so
|
||||
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
this directory exists to pacify sphinx-build.
|
||||
@@ -0,0 +1,181 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Unbound documentation build configuration file
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing dir.
|
||||
#
|
||||
# The contents of this file are pickled, so don't put values in the namespace
|
||||
# that aren't pickleable (module imports are okay, they're removed automatically).
|
||||
#
|
||||
# All configuration values have a default value; values that are commented out
|
||||
# serve to show the default value.
|
||||
|
||||
import sys, os
|
||||
|
||||
# If your extensions are in another directory, add it here. If the directory
|
||||
# is relative to the documentation root, use os.path.abspath to make it
|
||||
# absolute, like shown here.
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),'../')))
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),'../../../')))
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),'../../../.libs/')))
|
||||
#print sys.path
|
||||
|
||||
# General configuration
|
||||
# ---------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General substitutions.
|
||||
project = 'pyUnbound'
|
||||
copyright = '2009, Zdenek Vasicek, Marek Vavrusa'
|
||||
|
||||
# The default replacements for |version| and |release|, also used in various
|
||||
# other places throughout the built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '1.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '1.0.0'
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of documents that shouldn't be included in the build.
|
||||
#unused_docs = []
|
||||
|
||||
# List of directories, relative to source directories, that shouldn't be searched
|
||||
# for source files.
|
||||
#exclude_dirs = []
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
|
||||
# Options for HTML output
|
||||
# -----------------------
|
||||
|
||||
# The style sheet to use for HTML and HTML Help pages. A file of that name
|
||||
# must exist either in Sphinx' static/ path, or in one of the custom paths
|
||||
# given in html_static_path.
|
||||
html_style = 'default.css'
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (within the static path) to place at the top of
|
||||
# the sidebar.
|
||||
#html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
html_use_modindex = False
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, the reST sources are included in the HTML build as _sources/<name>.
|
||||
html_copy_source = False
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = ''
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'Unbounddoc'
|
||||
|
||||
|
||||
# Options for LaTeX output
|
||||
# ------------------------
|
||||
|
||||
# The paper size ('letter' or 'a4').
|
||||
#latex_paper_size = 'letter'
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#latex_font_size = '10pt'
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, document class [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'Unbound.tex', 'Unbound Documentation',
|
||||
'Zdenek Vasicek, Marek Vavrusa', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#latex_preamble = ''
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_use_modindex = True
|
||||
@@ -0,0 +1,26 @@
|
||||
.. _example_resolve_name:
|
||||
|
||||
==============================
|
||||
Resolve a name
|
||||
==============================
|
||||
|
||||
This basic example shows how to create a context and resolve a host address (DNS record of A type).
|
||||
|
||||
::
|
||||
|
||||
#!/usr/bin/python
|
||||
import unbound
|
||||
|
||||
ctx = unbound.ub_ctx()
|
||||
ctx.resolvconf("/etc/resolv.conf")
|
||||
|
||||
status, result = ctx.resolve("www.google.com")
|
||||
if status == 0 and result.havedata:
|
||||
print "Result.data:", result.data.address_list
|
||||
elif status != 0:
|
||||
print "Resolve error:", unbound.ub_strerror(status)
|
||||
|
||||
In contrast with C API, the source code is more compact while the performance of C implementation is preserved.
|
||||
The main advantage is that you need not take care about the deallocation and allocation of context and result structures; pyUnbound module do it automatically for you.
|
||||
|
||||
If only domain name is given, the :meth:`unbound.ub_ctx.resolve` looks for A records in IN class.
|
||||
@@ -0,0 +1,33 @@
|
||||
.. _example_reverse_lookup:
|
||||
|
||||
==============================
|
||||
Reverse DNS lookup
|
||||
==============================
|
||||
|
||||
Reverse DNS lookup involves determining the hostname associated with a given IP address.
|
||||
This example shows how reverse lookup can be done using unbound module.
|
||||
|
||||
For the reverse DNS records, the special domain in-addr.arpa is reserved.
|
||||
For example, a host name for the IP address 74.125.43.147 can be obtained by issuing a DNS query for the PTR record for address 147.43.125.74.in-addr.arpa.
|
||||
|
||||
::
|
||||
|
||||
#!/usr/bin/python
|
||||
import unbound
|
||||
|
||||
ctx = unbound.ub_ctx()
|
||||
ctx.resolvconf("/etc/resolv.conf")
|
||||
|
||||
status, result = ctx.resolve(unbound.reverse("74.125.43.147") + ".in-addr.arpa.", unbound.RR_TYPE_PTR, unbound.RR_CLASS_IN)
|
||||
if status == 0 and result.havedata:
|
||||
print "Result.data:", result.data.domain_list
|
||||
elif status != 0:
|
||||
print "Resolve error:", unbound.ub_strerror(status)
|
||||
|
||||
In order to simplify the python code, unbound module contains function which reverses the hostname components.
|
||||
This function is defined as follows::
|
||||
|
||||
def reverse(domain):
|
||||
return '.'.join([a for a in domain.split(".")][::-1])
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
.. _example_setup_ctx:
|
||||
|
||||
==============================
|
||||
Lookup from threads
|
||||
==============================
|
||||
|
||||
This example shows how to use unbound module from a threaded program.
|
||||
In this example, three lookup threads are created which work in background.
|
||||
Each thread resolves different DNS record.
|
||||
|
||||
::
|
||||
|
||||
#!/usr/bin/python
|
||||
from unbound import ub_ctx, RR_TYPE_A, RR_CLASS_IN
|
||||
from threading import Thread
|
||||
|
||||
ctx = ub_ctx()
|
||||
ctx.resolvconf("/etc/resolv.conf")
|
||||
|
||||
class LookupThread(Thread):
|
||||
def __init__(self,ctx, name):
|
||||
Thread.__init__(self)
|
||||
self.ctx = ctx
|
||||
self.name = name
|
||||
|
||||
def run(self):
|
||||
print "Thread lookup started:",self.name
|
||||
status, result = self.ctx.resolve(self.name, RR_TYPE_A, RR_CLASS_IN)
|
||||
if status == 0 and result.havedata:
|
||||
print " Result:",self.name,":", result.data.address_list
|
||||
|
||||
threads = []
|
||||
for name in ["www.fit.vutbr.cz","www.vutbr.cz","www.google.com"]:
|
||||
thread = LookupThread(ctx, name)
|
||||
thread.start()
|
||||
threads.append(thread)
|
||||
|
||||
for thread in threads:
|
||||
thread.join()
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
.. _example_asynch:
|
||||
|
||||
==============================
|
||||
Asynchronous lookup
|
||||
==============================
|
||||
|
||||
This example performs the name lookup in the background.
|
||||
The main program keeps running while the name is resolved.
|
||||
|
||||
::
|
||||
|
||||
#!/usr/bin/python
|
||||
import time
|
||||
import unbound
|
||||
|
||||
ctx = unbound.ub_ctx()
|
||||
ctx.resolvconf("/etc/resolv.conf")
|
||||
|
||||
def call_back(my_data,status,result):
|
||||
print "Call_back:", my_data
|
||||
if status == 0 and result.havedata:
|
||||
print "Result:", result.data.address_list
|
||||
my_data['done_flag'] = True
|
||||
|
||||
|
||||
my_data = {'done_flag':False,'arbitrary':"object"}
|
||||
status, async_id = ctx.resolve_async("www.seznam.cz", my_data, call_back, unbound.RR_TYPE_A, unbound.RR_CLASS_IN)
|
||||
|
||||
while (status == 0) and (not my_data['done_flag']):
|
||||
status = ctx.process()
|
||||
time.sleep(0.1)
|
||||
|
||||
if (status != 0):
|
||||
print "Resolve error:", unbound.ub_strerror(status)
|
||||
|
||||
The :meth:`unbound.ub_ctx.resolve_async` method is able to pass on any Python object. In this example, we used a dictionary object `my_data`.
|
||||
@@ -0,0 +1,34 @@
|
||||
.. _example_examine:
|
||||
|
||||
==============================
|
||||
DNSSEC validator
|
||||
==============================
|
||||
|
||||
This example program performs DNSSEC validation of a DNS lookup.
|
||||
|
||||
::
|
||||
|
||||
#!/usr/bin/python
|
||||
import os
|
||||
from unbound import ub_ctx,RR_TYPE_A,RR_CLASS_IN
|
||||
|
||||
ctx = ub_ctx()
|
||||
ctx.resolvconf("/etc/resolv.conf")
|
||||
if (os.path.isfile("keys")):
|
||||
ctx.add_ta_file("keys") #read public keys for DNSSEC verification
|
||||
|
||||
status, result = ctx.resolve("www.nic.cz", RR_TYPE_A, RR_CLASS_IN)
|
||||
if status == 0 and result.havedata:
|
||||
|
||||
print "Result:", result.data.address_list
|
||||
|
||||
if result.secure:
|
||||
print "Result is secure"
|
||||
elif result.bogus:
|
||||
print "Result is bogus"
|
||||
else:
|
||||
print "Result is insecure"
|
||||
|
||||
More detailed informations can be seen in libUnbound DNSSEC tutorial `here`_.
|
||||
|
||||
.. _here: http://www.unbound.net/documentation/libunbound-tutorial-6.html
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user