mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
Compare commits
1424
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e828d678ba | ||
|
|
f3c2d05728 | ||
|
|
4b73b5f299 | ||
|
|
ff7d68ca53 | ||
|
|
3fb98a72d2 | ||
|
|
6e8b4a7796 | ||
|
|
6f7eb3ea9f | ||
|
|
216747bb17 | ||
|
|
8f79119826 | ||
|
|
4106308bd5 | ||
|
|
c4c1f9e5ef | ||
|
|
b6f0b1af86 | ||
|
|
68027ab145 | ||
|
|
4a7ebfabcf | ||
|
|
9ce6119513 | ||
|
|
534eac6ae5 | ||
|
|
d3ff930b06 | ||
|
|
6c3a0b54ed | ||
|
|
2d444a5037 | ||
|
|
c99438c6a1 | ||
|
|
3f3cadd416 | ||
|
|
e183a66d60 | ||
|
|
d2eb78e871 | ||
|
|
5a66aecef9 | ||
|
|
f5e06689d1 | ||
|
|
5a00b31f86 | ||
|
|
cdbf091c0d | ||
|
|
4edb16296b | ||
|
|
aa64c58368 | ||
|
|
b4a01d6096 | ||
|
|
d63cb99649 | ||
|
|
dc0b1699e5 | ||
|
|
f82f971997 | ||
|
|
30b0fa1e8e | ||
|
|
1718a8e6b5 | ||
|
|
ebad5416d7 | ||
|
|
8833d44d01 | ||
|
|
da4d6ffee3 | ||
|
|
981fedea0e | ||
|
|
493921ef1f | ||
|
|
3a49e683ed | ||
|
|
3907876eac | ||
|
|
fcd9b34bb5 | ||
|
|
d63ec2dfcb | ||
|
|
6139943428 | ||
|
|
a76e43341f | ||
|
|
d63536289c | ||
|
|
d085a0039b | ||
|
|
3ebc480690 | ||
|
|
20dd979d00 | ||
|
|
623dba975a | ||
|
|
09707fc403 | ||
|
|
2dcc7016ac | ||
|
|
f887552763 | ||
|
|
72d348de6a | ||
|
|
7646c96259 | ||
|
|
d8809c672a | ||
|
|
7e3da817c3 | ||
|
|
c54fe82886 | ||
|
|
1fa40654d2 | ||
|
|
d79d75538b | ||
|
|
fa23ee8f31 | ||
|
|
51c23b0209 | ||
|
|
a3545867fc | ||
|
|
02080f6b18 | ||
|
|
07156bd5ea | ||
|
|
2a4e840be4 | ||
|
|
226298bbd3 | ||
|
|
5d46bb3879 | ||
|
|
a839a8ae01 | ||
|
|
79a6e9fbe2 | ||
|
|
16bbfc3461 | ||
|
|
d8090b8cae | ||
|
|
09845779d5 | ||
|
|
cb8374cce5 | ||
|
|
442e95620e | ||
|
|
af6f5a3f54 | ||
|
|
253d95a8ef | ||
|
|
57f2582790 | ||
|
|
d05d6b959a | ||
|
|
d4c904d091 | ||
|
|
5ac9bf3f9b | ||
|
|
f759fc5839 | ||
|
|
8903dc779f | ||
|
|
29b90c6e58 | ||
|
|
9b310f4084 | ||
|
|
7dfbcdf276 | ||
|
|
941b324187 | ||
|
|
21472c2393 | ||
|
|
488e4c66cd | ||
|
|
e8b8d42f8b | ||
|
|
e6a179e27a | ||
|
|
eb2283332b | ||
|
|
b2c3b4758b | ||
|
|
8bfbd81fec | ||
|
|
3d91a9fd56 | ||
|
|
facc6c6541 | ||
|
|
380b87e21a | ||
|
|
b60c4a472c | ||
|
|
82dffb1023 | ||
|
|
dc30e66ddc | ||
|
|
ec021e0d4b | ||
|
|
7963c9f463 | ||
|
|
710851e69a | ||
|
|
11f22074a9 | ||
|
|
55bb4c1275 | ||
|
|
b966dd8e06 | ||
|
|
06a91b0eaa | ||
|
|
3df64cc677 | ||
|
|
6943cab670 | ||
|
|
f635b47ade | ||
|
|
eb7f9a50f2 | ||
|
|
acdd4058d2 | ||
|
|
1b62399a6e | ||
|
|
e1e71eac3e | ||
|
|
aefd2df51f | ||
|
|
15020f7666 | ||
|
|
ae2d5276d2 | ||
|
|
ce0e9bef45 | ||
|
|
1dcc88b6e8 | ||
|
|
faa9dd7bf6 | ||
|
|
9303292b7f | ||
|
|
9f0b260c49 | ||
|
|
ab53baa6f5 | ||
|
|
554e4a939c | ||
|
|
45b3215594 | ||
|
|
3cb1cdeebd | ||
|
|
9a9d59ecaf | ||
|
|
1a4eaaabc5 | ||
|
|
ff8fd0be5c | ||
|
|
13d96540de | ||
|
|
e45e9f1ce0 | ||
|
|
05b9f4fd28 | ||
|
|
1089fd6dc1 | ||
|
|
366296ec14 | ||
|
|
7f9aa6734a | ||
|
|
9902a5f81d | ||
|
|
cd0a2b1af1 | ||
|
|
a374dfb669 | ||
|
|
79fa94834e | ||
|
|
e35d5f5a2d | ||
|
|
334e2b1e35 | ||
|
|
06847ff3be | ||
|
|
80c2c69fa7 | ||
|
|
8b752e359e | ||
|
|
d3b3d64ef3 | ||
|
|
c602ba7319 | ||
|
|
bdb6c153e4 | ||
|
|
d8a8730cac | ||
|
|
0532cdd357 | ||
|
|
e84b913585 | ||
|
|
a5027f5f56 | ||
|
|
06a58ca248 | ||
|
|
4700d79024 | ||
|
|
9d9884c442 | ||
|
|
c1c75929fa | ||
|
|
8cb3656b3e | ||
|
|
a90f173875 | ||
|
|
b266db3920 | ||
|
|
fd415d8833 | ||
|
|
b5a52f8c86 | ||
|
|
67271242bf | ||
|
|
008813f0a2 | ||
|
|
fa506e3cda | ||
|
|
df0c844eed | ||
|
|
199e6c586b | ||
|
|
21f740d313 | ||
|
|
e860d39f54 | ||
|
|
fe0b1da859 | ||
|
|
27811ffaa9 | ||
|
|
7d5ab2f4de | ||
|
|
5f5c00203e | ||
|
|
b4b0065554 | ||
|
|
c94e13220b | ||
|
|
368386c011 | ||
|
|
d5ebc63add | ||
|
|
d323e1bda8 | ||
|
|
36819adcc2 | ||
|
|
da46ea24d5 | ||
|
|
1aa1facabc | ||
|
|
78b2f1cc20 | ||
|
|
164f302011 | ||
|
|
cc39725cf3 | ||
|
|
63b2628a18 | ||
|
|
0f3eac4a0e | ||
|
|
72738471f1 | ||
|
|
c1e75c0369 | ||
|
|
b16c872a60 | ||
|
|
364441e0f5 | ||
|
|
ed95b07764 | ||
|
|
bf2307ca97 | ||
|
|
1ec96d8f07 | ||
|
|
3499d3c647 | ||
|
|
ee06aaaad9 | ||
|
|
af6c5dea43 | ||
|
|
b57771d42b | ||
|
|
6067ce6d2b | ||
|
|
081fd4fdae | ||
|
|
09a0e6ee30 | ||
|
|
a4f4d7b6ba | ||
|
|
e2a2dcdfd5 | ||
|
|
14b11384a4 | ||
|
|
a03f0a388e | ||
|
|
0b77c9d676 | ||
|
|
1c3ba0cef7 | ||
|
|
19c2ece763 | ||
|
|
310396190b | ||
|
|
a08fe8ca60 | ||
|
|
a95f5fd5cb | ||
|
|
a922a19d70 | ||
|
|
a8d0177b36 | ||
|
|
779b86fb22 | ||
|
|
e3453711e5 | ||
|
|
73484d3b36 | ||
|
|
f1c23891ab | ||
|
|
9b7843f879 | ||
|
|
5f4c9b0dfe | ||
|
|
3280e76527 | ||
|
|
46099259be | ||
|
|
56af87e2f3 | ||
|
|
bd5eeff364 | ||
|
|
2fea5663bd | ||
|
|
1a48bdebb5 | ||
|
|
f46c238552 | ||
|
|
7e300939c0 | ||
|
|
409bc229ef | ||
|
|
ee0087d5c7 | ||
|
|
d4f697f160 | ||
|
|
6e4bab2629 | ||
|
|
5c5ddbe859 | ||
|
|
ea506d0f68 | ||
|
|
27e334e813 | ||
|
|
8e48a5cf5f | ||
|
|
9bc81f31d8 | ||
|
|
c6db87d81d | ||
|
|
f90e80d3bc | ||
|
|
e60f92ea29 | ||
|
|
46b5e96c54 | ||
|
|
f5a197f96e | ||
|
|
196654efec | ||
|
|
a9c8d00d63 | ||
|
|
5e4cfcc665 | ||
|
|
193cb2fcc4 | ||
|
|
b57a2f15db | ||
|
|
8d2c08befd | ||
|
|
d9a9f73e82 | ||
|
|
e19da1b619 | ||
|
|
6ce60bcb61 | ||
|
|
ff026a1f3c | ||
|
|
a37730cee8 | ||
|
|
af11b54071 | ||
|
|
2a78803049 | ||
|
|
edf1ad369a | ||
|
|
52ea271a65 | ||
|
|
ae54e9013b | ||
|
|
8a3ae4d08a | ||
|
|
1cc54b080a | ||
|
|
63171a2522 | ||
|
|
2e023a5699 | ||
|
|
1c1fc36d76 | ||
|
|
42d7db578a | ||
|
|
d4a6380562 | ||
|
|
8133251662 | ||
|
|
5a8d314ce3 | ||
|
|
99f36a4e1e | ||
|
|
61a28c2ee5 | ||
|
|
2552a81b40 | ||
|
|
ab6f1d0fc7 | ||
|
|
c8a56bfa8f | ||
|
|
d1150541bb | ||
|
|
ead84a5a64 | ||
|
|
c6369e9ffa | ||
|
|
474afc9016 | ||
|
|
bd3c02bd59 | ||
|
|
32b1d900ff | ||
|
|
4eac399dfd | ||
|
|
c26fc84945 | ||
|
|
2b47ca080e | ||
|
|
348cbab016 | ||
|
|
a777329b7f | ||
|
|
92121f7878 | ||
|
|
ce8167a3bb | ||
|
|
937523285a | ||
|
|
8a0de6b519 | ||
|
|
e338143639 | ||
|
|
59570b0413 | ||
|
|
78adebf8ec | ||
|
|
b75c37252c | ||
|
|
48ad6477eb | ||
|
|
296f28e8d0 | ||
|
|
83e2cade5b | ||
|
|
ce0628ee55 | ||
|
|
bb5251da66 | ||
|
|
bfd0c5ec85 | ||
|
|
8092cd6331 | ||
|
|
7105ea9293 | ||
|
|
efb3697332 | ||
|
|
56a174bb0f | ||
|
|
9d2980de1a | ||
|
|
bfae29866b | ||
|
|
b248654aab | ||
|
|
7cc4ff05ad | ||
|
|
b4a9031cdb | ||
|
|
16cc196bf2 | ||
|
|
c79a99a577 | ||
|
|
a82c0eeece | ||
|
|
a62c1135fe | ||
|
|
ba0cad0bc3 | ||
|
|
7c1f9699d8 | ||
|
|
33a814683b | ||
|
|
beebe5ba0c | ||
|
|
225534e5ab | ||
|
|
3599fd9c60 | ||
|
|
5b162ead92 | ||
|
|
62428e17f6 | ||
|
|
079253670e | ||
|
|
91e863138b | ||
|
|
d1e92a0ebd | ||
|
|
3949bf2c82 | ||
|
|
a41375411e | ||
|
|
030832cf12 | ||
|
|
49a36d98bb | ||
|
|
ddae2885bd | ||
|
|
19193fd534 | ||
|
|
4e249c96e8 | ||
|
|
cae8361dcd | ||
|
|
429e130768 | ||
|
|
20d57ec58b | ||
|
|
e43c3daec2 | ||
|
|
64c4e69b07 | ||
|
|
a9e028564d | ||
|
|
99994a26b0 | ||
|
|
fe97f25b75 | ||
|
|
281030d576 | ||
|
|
8992e8c91f | ||
|
|
b34a6defc1 | ||
|
|
8cf5eae166 | ||
|
|
df8f236b62 | ||
|
|
273ff1201b | ||
|
|
91f585ed38 | ||
|
|
b9b226bdea | ||
|
|
8fffdca2a6 | ||
|
|
723845b350 | ||
|
|
31b677b35f | ||
|
|
c2e3baa81a | ||
|
|
7273b35243 | ||
|
|
dfe8e0dfa2 | ||
|
|
7ad8ffccf5 | ||
|
|
065c7c5dd8 | ||
|
|
71744b8bb2 | ||
|
|
3d2dfc4769 | ||
|
|
5e4f0d65ce | ||
|
|
aae44940c7 | ||
|
|
062c2cacfc | ||
|
|
ce65cdde71 | ||
|
|
b005fcd87b | ||
|
|
f11d6653d6 | ||
|
|
20d5e35576 | ||
|
|
3028fa50a8 | ||
|
|
e584933b2b | ||
|
|
d48abb9a84 | ||
|
|
37361a1d10 | ||
|
|
299cc0c689 | ||
|
|
707e5a915b | ||
|
|
649e265d6f | ||
|
|
9d4ca81959 | ||
|
|
68a57554a6 | ||
|
|
cc9fb69911 | ||
|
|
d3f397c686 | ||
|
|
ed8b859e31 | ||
|
|
011a7d8830 | ||
|
|
510606dd1c | ||
|
|
4e59c8344f | ||
|
|
4c8f334c15 | ||
|
|
2f52ecdd9c | ||
|
|
5d82b7c421 | ||
|
|
8ae9f26bce | ||
|
|
55f560a3ca | ||
|
|
51caffb454 | ||
|
|
ef1baf94f7 | ||
|
|
8b18d1a0a4 | ||
|
|
4481b9584c | ||
|
|
dec68aa9a9 | ||
|
|
c10712a82b | ||
|
|
d81e2c654f | ||
|
|
f5dcd84d27 | ||
|
|
7c4911c577 | ||
|
|
be4583ac84 | ||
|
|
068374740c | ||
|
|
f7d63b0927 | ||
|
|
9087b18234 | ||
|
|
19a3907657 | ||
|
|
762920232a | ||
|
|
f30fe71395 | ||
|
|
ec6f4bab46 | ||
|
|
0d2efc3f3f | ||
|
|
bb480068fa | ||
|
|
ae9fe1a10e | ||
|
|
dd19026e91 | ||
|
|
42d2c04ae1 | ||
|
|
db2557826a | ||
|
|
11d98df304 | ||
|
|
ec84fd2ca6 | ||
|
|
fe6eb5f665 | ||
|
|
90b00dfe57 | ||
|
|
023411f975 | ||
|
|
a97bfa08ec | ||
|
|
9c2a45c59e | ||
|
|
1b72e814e7 | ||
|
|
71b078611f | ||
|
|
1ef8cfcac5 | ||
|
|
6b8e316663 | ||
|
|
21d03697ca | ||
|
|
4c7f824e0a | ||
|
|
42244e1b4d | ||
|
|
2981adac66 | ||
|
|
91971db3d0 | ||
|
|
b4e8ab4254 | ||
|
|
198a7ce74d | ||
|
|
e103490376 | ||
|
|
f3658c210c | ||
|
|
1ba3682d9b | ||
|
|
39b7468bab | ||
|
|
a42e9aaaba | ||
|
|
a9b7194485 | ||
|
|
2ad55ba791 | ||
|
|
ac8dc59341 | ||
|
|
c1c1cd97e7 | ||
|
|
b23c373f4d | ||
|
|
e6da6c251c | ||
|
|
81ded6124d | ||
|
|
c417f733af | ||
|
|
63dcbe3d75 | ||
|
|
fb342b73d3 | ||
|
|
cccb5094a4 | ||
|
|
3330d5296c | ||
|
|
f95f98b12a | ||
|
|
7bb6358540 | ||
|
|
ca33c52086 | ||
|
|
aba3ba738f | ||
|
|
60da4369a4 | ||
|
|
b04e84ab9e | ||
|
|
d96de4c222 | ||
|
|
0ff5c52657 | ||
|
|
f532367412 | ||
|
|
94996b8a29 | ||
|
|
59e6f149a7 | ||
|
|
470806b097 | ||
|
|
8fcc82171a | ||
|
|
4d5b32ee59 | ||
|
|
816aa50dfc | ||
|
|
068c52d8f5 | ||
|
|
692caffe2c | ||
|
|
c97bb52d77 | ||
|
|
438634b718 | ||
|
|
d21cb609a8 | ||
|
|
668c0627c0 | ||
|
|
de0b6da9f4 | ||
|
|
5853f90076 | ||
|
|
022d5131b3 | ||
|
|
7458729d28 | ||
|
|
7acf6a4a66 | ||
|
|
04d73b9192 | ||
|
|
f7e99131b9 | ||
|
|
069b0b8c90 | ||
|
|
1ff7a89433 | ||
|
|
640d1cf929 | ||
|
|
c9955f9fdf | ||
|
|
9a877e0e9a | ||
|
|
6b49224c85 | ||
|
|
fd5e4e6019 | ||
|
|
8e2a100460 | ||
|
|
359dcc3c5c | ||
|
|
6021341118 | ||
|
|
d5922830d0 | ||
|
|
23505d30a5 | ||
|
|
0f83653e76 | ||
|
|
20f0e8ad55 | ||
|
|
140a165ab2 | ||
|
|
5fec1c8b1f | ||
|
|
6bd4060ae0 | ||
|
|
84a8415357 | ||
|
|
6429b5c298 | ||
|
|
6b5e7d78e3 | ||
|
|
a8b2c64cbf | ||
|
|
9268f0db50 | ||
|
|
02bd3e2ff1 | ||
|
|
2d28fba3bf | ||
|
|
19aed2dcb1 | ||
|
|
eed1e0789a | ||
|
|
837565c505 | ||
|
|
fece182cf5 | ||
|
|
945452bff4 | ||
|
|
1c08a2ba55 | ||
|
|
d967ceb98b | ||
|
|
a3c3e13b2f | ||
|
|
83a186f6cc | ||
|
|
2598f9bb18 | ||
|
|
ba28c48efc | ||
|
|
98234d1017 | ||
|
|
99a92b3483 | ||
|
|
c85ff492d0 | ||
|
|
b09cfb8fb1 | ||
|
|
966a958ca5 | ||
|
|
885069e1f6 | ||
|
|
077b38e2c5 | ||
|
|
9be04e6fac | ||
|
|
377d5b426a | ||
|
|
f82a128909 | ||
|
|
216759e955 | ||
|
|
9b6caf5a5b | ||
|
|
5c25bbd93f | ||
|
|
d8937492cb | ||
|
|
e91d85edb5 | ||
|
|
5089db7331 | ||
|
|
8e20d628e8 | ||
|
|
d275505df6 | ||
|
|
f7516e6b2b | ||
|
|
898d4c8dd9 | ||
|
|
2e9d09b961 | ||
|
|
8dd6efe5ed | ||
|
|
635df9c806 | ||
|
|
75b8b8c875 | ||
|
|
90f0530234 | ||
|
|
d744827f93 | ||
|
|
fe8b22caa1 | ||
|
|
9a82526b91 | ||
|
|
225a6d9c6e | ||
|
|
87c8dd5434 | ||
|
|
a09c4bbdc2 | ||
|
|
d01651c305 | ||
|
|
00982fc3db | ||
|
|
d8f890a43a | ||
|
|
a58681a718 | ||
|
|
c9d33fb9f7 | ||
|
|
254df71810 | ||
|
|
194dc32059 | ||
|
|
987c1c97e5 | ||
|
|
25c8497ba6 | ||
|
|
5577e55400 | ||
|
|
27472f1270 | ||
|
|
30a14c2716 | ||
|
|
d4a69e4d2a | ||
|
|
000e75581b | ||
|
|
2e5e31e8ac | ||
|
|
ae2653fcc5 | ||
|
|
f7118f29b9 | ||
|
|
57a5e75840 | ||
|
|
8d14e7c0a4 | ||
|
|
e0745813f4 | ||
|
|
0171d06aa2 | ||
|
|
4daf8f5bdb | ||
|
|
8893735a2d | ||
|
|
00ba747be7 | ||
|
|
504ef71975 | ||
|
|
9926fcac4b | ||
|
|
01d8dc2240 | ||
|
|
4fe427ded2 | ||
|
|
b0ca964984 | ||
|
|
e8c4f20f66 | ||
|
|
b0daf867c2 | ||
|
|
8385c462ed | ||
|
|
afd4063f20 | ||
|
|
ed24498f2e | ||
|
|
f2b12c0761 | ||
|
|
df85836b15 | ||
|
|
3f2b6828e5 | ||
|
|
1958d9fbd5 | ||
|
|
0c04b5eaf5 | ||
|
|
8e5a32f4dc | ||
|
|
efe5c8e6be | ||
|
|
1e61604aab | ||
|
|
488eaf09ce | ||
|
|
8b1012613e | ||
|
|
256ab3d935 | ||
|
|
a07337fd6d | ||
|
|
be79ffa371 | ||
|
|
c580e0e33c | ||
|
|
d2f7999b4e | ||
|
|
611e37aa2d | ||
|
|
3f2d186694 | ||
|
|
73f01304f0 | ||
|
|
77bd7d228b | ||
|
|
b97b04a9db | ||
|
|
6e4583a528 | ||
|
|
586b811b87 | ||
|
|
070019c9be | ||
|
|
ce04bcb463 | ||
|
|
cf1bfbba5d | ||
|
|
a4fd088875 | ||
|
|
27023b3f21 | ||
|
|
b2a7933045 | ||
|
|
749d1b9ebc | ||
|
|
87bdb489f9 | ||
|
|
37e9f5591a | ||
|
|
d546e7766d | ||
|
|
62f69f9b40 | ||
|
|
168bc963d3 | ||
|
|
1f148e632f | ||
|
|
c887ae1022 | ||
|
|
375d3e7520 | ||
|
|
3b171545b6 | ||
|
|
aa5efa172d | ||
|
|
a2961e50fb | ||
|
|
adc498d29d | ||
|
|
1ff3e51ee1 | ||
|
|
f9c0f359a7 | ||
|
|
cc538f4f9f | ||
|
|
900cd200a2 | ||
|
|
45e73bcc8e | ||
|
|
26eaf2d1ee | ||
|
|
2f32ef7646 | ||
|
|
b7abbd1d72 | ||
|
|
f364edafd3 | ||
|
|
e3f08cb2a2 | ||
|
|
a92b00ef3c | ||
|
|
3dbdde7fed | ||
|
|
6da37e5ecd | ||
|
|
007123ee2c | ||
|
|
10c085f81d | ||
|
|
1d315e11cf | ||
|
|
c91b657a40 | ||
|
|
60f59271d6 | ||
|
|
40abe08ac8 | ||
|
|
ae1790b8e8 | ||
|
|
aa5fb8b10b | ||
|
|
6de329359c | ||
|
|
2e34a8f643 | ||
|
|
bded93f69b | ||
|
|
38e77d50f2 | ||
|
|
f8e585f308 | ||
|
|
5bda4f9822 | ||
|
|
d2d7b987fa | ||
|
|
7579216922 | ||
|
|
330c6e1cb0 | ||
|
|
41e5a66b73 | ||
|
|
cc5ab744c5 | ||
|
|
0ae750e552 | ||
|
|
cabc120f22 | ||
|
|
c96c2d8a45 | ||
|
|
8aa53f027d | ||
|
|
4bf9d12419 | ||
|
|
f93746b1af | ||
|
|
23dc22b78d | ||
|
|
5e3c30beac | ||
|
|
86f16bef93 | ||
|
|
f2e90b0872 | ||
|
|
1249e0db3f | ||
|
|
15c4dd79f4 | ||
|
|
e324a7819a | ||
|
|
81e9f82a8d | ||
|
|
5d298ed474 | ||
|
|
82e1e3959f | ||
|
|
7181c0fa6a | ||
|
|
49f27c06af | ||
|
|
7247718e12 | ||
|
|
61acc76244 | ||
|
|
2faa4f9ee2 | ||
|
|
2beae211ee | ||
|
|
d3ff7a9333 | ||
|
|
23df700f15 | ||
|
|
755233c720 | ||
|
|
bca54a8b25 | ||
|
|
b5aab36d41 | ||
|
|
d7cfe91cb3 | ||
|
|
a31d45b13e | ||
|
|
23f475bccc | ||
|
|
025fdd0049 | ||
|
|
5bb6dbe21c | ||
|
|
c225ced1a9 | ||
|
|
3a58ad15e8 | ||
|
|
5106ad7a2c | ||
|
|
8c044a616b | ||
|
|
9ccf611954 | ||
|
|
5dfcf122d1 | ||
|
|
7b092127cb | ||
|
|
b26257248d | ||
|
|
3c7d270958 | ||
|
|
c15eae814f | ||
|
|
0e72e06886 | ||
|
|
abff4d1237 | ||
|
|
386f23334b | ||
|
|
a523683d4c | ||
|
|
b25332e1f4 | ||
|
|
a6ec2c6fc7 | ||
|
|
9cb404ba5f | ||
|
|
12251022ec | ||
|
|
00a0cabf7f | ||
|
|
d6ed0e868f | ||
|
|
700ad78f10 | ||
|
|
d65accbb23 | ||
|
|
78767f2014 | ||
|
|
21af42a281 | ||
|
|
0b0ece9db0 | ||
|
|
23edc18cac | ||
|
|
7153c94bd7 | ||
|
|
4df697b4b7 | ||
|
|
7fd32916e8 | ||
|
|
3f837bc440 | ||
|
|
f0769bed93 | ||
|
|
a1bfc07105 | ||
|
|
beba72d6db | ||
|
|
a4a5bfaa2f | ||
|
|
62ea384d19 | ||
|
|
53b1e11eba | ||
|
|
7fae96eb1e | ||
|
|
d386641820 | ||
|
|
7c5e38294a | ||
|
|
1cadc5d677 | ||
|
|
7509bf208e | ||
|
|
ec34bc9af1 | ||
|
|
8d1af17449 | ||
|
|
0db1573d34 | ||
|
|
b3c45a8edb | ||
|
|
1a0bd1a150 | ||
|
|
5a726fb61f | ||
|
|
6792d2d036 | ||
|
|
d32fb26adb | ||
|
|
d4ba7731ad | ||
|
|
b9607297e9 | ||
|
|
9ed59fdf34 | ||
|
|
8bcb44a019 | ||
|
|
6b28c8ace2 | ||
|
|
55088951c0 | ||
|
|
55a0d89f0d | ||
|
|
d532c9913c | ||
|
|
261bf354b7 | ||
|
|
50b6dc4b81 | ||
|
|
ba29a4a078 | ||
|
|
676644d8e8 | ||
|
|
f64a897cbc | ||
|
|
8b209f8f68 | ||
|
|
16b6619dfa | ||
|
|
a8c8fa6bc6 | ||
|
|
6d7e5df98f | ||
|
|
1d5d95c8cb | ||
|
|
8f886fc6dd | ||
|
|
581f975b38 | ||
|
|
d2c8bcf318 | ||
|
|
ef1ed6365c | ||
|
|
82418e2bf7 | ||
|
|
6fefbb4115 | ||
|
|
85bf0bd994 | ||
|
|
913d4537f4 | ||
|
|
4e2bafafef | ||
|
|
bffb7c52d5 | ||
|
|
38c4d3d09d | ||
|
|
2951f21dab | ||
|
|
d97a635084 | ||
|
|
2c9d9fe211 | ||
|
|
583411768d | ||
|
|
a55df65bc9 | ||
|
|
d6de848e29 | ||
|
|
649a98d855 | ||
|
|
127759b160 | ||
|
|
5b29f1b3ac | ||
|
|
755177fb4c | ||
|
|
ee9c42bee5 | ||
|
|
4d06c36342 | ||
|
|
1508d3708c | ||
|
|
ea6266f736 | ||
|
|
406a9d8350 | ||
|
|
2be0263dfa | ||
|
|
deea985a20 | ||
|
|
0d18256828 | ||
|
|
abe18e41bc | ||
|
|
716282cc1a | ||
|
|
f5a59fea5d | ||
|
|
2e70e3a0d3 | ||
|
|
7ff459af13 | ||
|
|
5bee11a6d3 | ||
|
|
0b21483b17 | ||
|
|
7444b3a8bf | ||
|
|
f39e39ed47 | ||
|
|
1989c52ca0 | ||
|
|
d8df0ddef8 | ||
|
|
7f6e3852b8 | ||
|
|
23656b2b0e | ||
|
|
c16a32d2be | ||
|
|
9d28279475 | ||
|
|
913de80cbc | ||
|
|
e4c8085408 | ||
|
|
1b055c6ca7 | ||
|
|
630600e70d | ||
|
|
4809fe1b95 | ||
|
|
2d6715878d | ||
|
|
4691979679 | ||
|
|
4e5af01354 | ||
|
|
b23b39bcfd | ||
|
|
4f974e3465 | ||
|
|
85994fb61c | ||
|
|
ad9784c5e8 | ||
|
|
c239c3f395 | ||
|
|
8d22d3c13d | ||
|
|
6ef9cafc0e | ||
|
|
471ed1befe | ||
|
|
e822adf725 | ||
|
|
d91f09896d | ||
|
|
d41cdb6ce8 | ||
|
|
fbee729c5b | ||
|
|
89ad258515 | ||
|
|
0e5abca6b7 | ||
|
|
9cd2f836bd | ||
|
|
1f9caf5805 | ||
|
|
c515215eea | ||
|
|
100cc496de | ||
|
|
0a06c5bfa2 | ||
|
|
6f4451b761 | ||
|
|
55b5227431 | ||
|
|
2be98b581a | ||
|
|
4e0128f16a | ||
|
|
3d1f9ae9d3 | ||
|
|
5fabe62e70 | ||
|
|
39f6488471 | ||
|
|
170c03f7db | ||
|
|
e5c14bfd16 | ||
|
|
4a0d32ec53 | ||
|
|
9f0d521b88 | ||
|
|
78031b37fc | ||
|
|
e1e629e592 | ||
|
|
554b8b35ae | ||
|
|
874165904f | ||
|
|
1d2d33d01a | ||
|
|
59935375a3 | ||
|
|
e784758a21 | ||
|
|
f7fe1a1093 | ||
|
|
3a287a70cd | ||
|
|
d111aaf64f | ||
|
|
cc617eadc9 | ||
|
|
54e15f5ace | ||
|
|
d1a76b55bc | ||
|
|
a48abc2f8b | ||
|
|
3a7d4d7c8d | ||
|
|
5e6c2e37ca | ||
|
|
b8c60d092f | ||
|
|
b57c76ed05 | ||
|
|
8da3f91a1d | ||
|
|
fdedd3aa38 | ||
|
|
a5fbb38fe2 | ||
|
|
3b25c475f5 | ||
|
|
babe659a64 | ||
|
|
980711e658 | ||
|
|
3a69cf5c69 | ||
|
|
5c8819f1ac | ||
|
|
f6f2ab1e4a | ||
|
|
1a7540c80a | ||
|
|
5919273709 | ||
|
|
4a3a6d1294 | ||
|
|
9407439587 | ||
|
|
d754cd3de4 | ||
|
|
9f88892190 | ||
|
|
1df2544e07 | ||
|
|
0e390bca00 | ||
|
|
8de66ab4b8 | ||
|
|
8148308cff | ||
|
|
24fc3242fc | ||
|
|
cd955fa34d | ||
|
|
28e9561a94 | ||
|
|
6905e41b57 | ||
|
|
075f470778 | ||
|
|
b8c72d7cbc | ||
|
|
b89db70821 | ||
|
|
a92e9692c1 | ||
|
|
3d57bf0a3b | ||
|
|
ec21a197ac | ||
|
|
ccf1ff8f02 | ||
|
|
76eee77b08 | ||
|
|
5b7942d197 | ||
|
|
a5df3a131e | ||
|
|
a901fc5fe7 | ||
|
|
a554c14f18 | ||
|
|
da06b1c76c | ||
|
|
b32284af57 | ||
|
|
54bd1fdd62 | ||
|
|
da961fd840 | ||
|
|
8449dc1b9d | ||
|
|
0648475a66 | ||
|
|
eff62cecac | ||
|
|
e63a4cd0fd | ||
|
|
dd2ba08f7c | ||
|
|
d19f3c8c07 | ||
|
|
427836884e | ||
|
|
1ad34fe7ae | ||
|
|
77f78152ee | ||
|
|
ad89368b4e | ||
|
|
5b41e86d51 | ||
|
|
48bd83f3b4 | ||
|
|
db766ce064 | ||
|
|
75eb720ab5 | ||
|
|
88c43a1b45 | ||
|
|
0ab8edd170 | ||
|
|
10e165c574 | ||
|
|
18aed94e0c | ||
|
|
3b87862c8a | ||
|
|
6fc79a70a3 | ||
|
|
a1b7abfb9f | ||
|
|
ff6ab04ecd | ||
|
|
bf6f33ceaf | ||
|
|
324d6e7c36 | ||
|
|
7edf4a3e75 | ||
|
|
e6b770b686 | ||
|
|
172b84f7ce | ||
|
|
dfb8fb2986 | ||
|
|
b5739f66a3 | ||
|
|
862b0b568c | ||
|
|
237e796955 | ||
|
|
1931d6e9cf | ||
|
|
b02f855df8 | ||
|
|
632ea0d02e | ||
|
|
a66fd181e5 | ||
|
|
cb28d35bd2 | ||
|
|
004609b5a7 | ||
|
|
fdd1199cb1 | ||
|
|
e95a9ac466 | ||
|
|
30891d6fff | ||
|
|
8605797002 | ||
|
|
cc9a0671f3 | ||
|
|
0b5e37dcee | ||
|
|
abeb60d511 | ||
|
|
4b9df2bae1 | ||
|
|
61d431e44f | ||
|
|
6a0b5aa8e3 | ||
|
|
392be1e787 | ||
|
|
84e819dc31 | ||
|
|
c1047e6a6c | ||
|
|
ca60143bdf | ||
|
|
c834b5eecd | ||
|
|
10cd092a78 | ||
|
|
0c4a702a39 | ||
|
|
ed002df8f5 | ||
|
|
bbcea9d913 | ||
|
|
657753aac2 | ||
|
|
7de2b4e047 | ||
|
|
f6946b9412 | ||
|
|
70f3d25173 | ||
|
|
fdd1a602d5 | ||
|
|
bea3b6b72d | ||
|
|
7d5dc75dc5 | ||
|
|
2e1f4420a8 | ||
|
|
0362614f94 | ||
|
|
208d045cf5 | ||
|
|
47909a6f2d | ||
|
|
f4ff97c297 | ||
|
|
0121427ef1 | ||
|
|
a1e63e8118 | ||
|
|
b9f4ff6e9f | ||
|
|
942ced78ed | ||
|
|
9ae592209f | ||
|
|
dc2e0ec3b6 | ||
|
|
dd77a1fb9a | ||
|
|
2ef71d6def | ||
|
|
414ed74526 | ||
|
|
01eab08c1c | ||
|
|
5fd83a85e8 | ||
|
|
093131438d | ||
|
|
603b62fdb5 | ||
|
|
ec179380f4 | ||
|
|
7eddb38162 | ||
|
|
c54dfcade9 | ||
|
|
859ca7db68 | ||
|
|
df6fbb82be | ||
|
|
4b4b1eec8b | ||
|
|
d759fdd457 | ||
|
|
fa57a0fbac | ||
|
|
2a6250e3fb | ||
|
|
be26349e37 | ||
|
|
b2943670ca | ||
|
|
7e8d3423cd | ||
|
|
0df528cc9e | ||
|
|
21d1989e05 | ||
|
|
fa90bbc07a | ||
|
|
44eb7bfd25 | ||
|
|
6cb75924d9 | ||
|
|
cb98f5896f | ||
|
|
dfba6bf690 | ||
|
|
06b80629bc | ||
|
|
87edf6497d | ||
|
|
6bae276ecb | ||
|
|
b1abc813fc | ||
|
|
1264f8cff8 | ||
|
|
3b393e0e2d | ||
|
|
a7d55a5ad8 | ||
|
|
30da6bde6f | ||
|
|
d918602521 | ||
|
|
e2aef3fa43 | ||
|
|
1ed537dc52 | ||
|
|
072347e594 | ||
|
|
743ea6815b | ||
|
|
2f69cd1765 | ||
|
|
c1e91553b9 | ||
|
|
36a54a9c9d | ||
|
|
d88bb99957 | ||
|
|
6030306d9c | ||
|
|
aeeb123b1e | ||
|
|
019d363dcd | ||
|
|
038303e6a5 | ||
|
|
635c4b5b89 | ||
|
|
975a7b1fc0 | ||
|
|
52aeaf4924 | ||
|
|
6c2fa12f10 | ||
|
|
f3304d408c | ||
|
|
05e3539856 | ||
|
|
ff384cd658 | ||
|
|
62fff935da | ||
|
|
35bd34f8e6 | ||
|
|
02fdb4c879 | ||
|
|
621b1c57a3 | ||
|
|
d905317682 | ||
|
|
9e59d5eb52 | ||
|
|
10b8997cc5 | ||
|
|
d41209512e | ||
|
|
8cf7e424e2 | ||
|
|
cba64aaaa4 | ||
|
|
31b331ca67 | ||
|
|
e13088d911 | ||
|
|
d016f85110 | ||
|
|
bcadc2b45c | ||
|
|
afb2d5f105 | ||
|
|
15d892c62d | ||
|
|
eb0f3256d9 | ||
|
|
f9add77d7b | ||
|
|
4863f45f7e | ||
|
|
6f88df1fc8 | ||
|
|
aa76ed9baf | ||
|
|
bdb6a5501a | ||
|
|
7bf7524d22 | ||
|
|
b37bc47eaa | ||
|
|
c5c2cb13d4 | ||
|
|
8752326d8c | ||
|
|
52e2331dd4 | ||
|
|
5ad3bbb27f | ||
|
|
a253d276d7 | ||
|
|
effb5c4203 | ||
|
|
64f4a0d800 | ||
|
|
5ef3663385 | ||
|
|
9a727c3c1a | ||
|
|
3e1e982625 | ||
|
|
d506659635 | ||
|
|
9247e8522b | ||
|
|
ef740d0cca | ||
|
|
ac9b95ca0c | ||
|
|
bbe5c6acf0 | ||
|
|
5e4faec554 | ||
|
|
207beff489 | ||
|
|
60beab1e8d | ||
|
|
7afdc695fe | ||
|
|
3264fa8a6f | ||
|
|
55d8fe2837 | ||
|
|
3427b992f7 | ||
|
|
ee8f07a686 | ||
|
|
a37e562079 | ||
|
|
c49226613b | ||
|
|
3ede03449c | ||
|
|
60318b18f7 | ||
|
|
32a4e9bfe6 | ||
|
|
7d17a926ac | ||
|
|
ce1f757ce0 | ||
|
|
b01f0db381 | ||
|
|
0b7d3bfd30 | ||
|
|
0042a5c5fc | ||
|
|
edd22eb36c | ||
|
|
eb25148123 | ||
|
|
0fcc88689d | ||
|
|
03d62b2e43 | ||
|
|
93b07b3526 | ||
|
|
08ceb2a737 | ||
|
|
4194c613bf | ||
|
|
6a5e7be380 | ||
|
|
e583448a6d | ||
|
|
a17400b45e | ||
|
|
a1153ba1f7 | ||
|
|
425dec3037 | ||
|
|
a270aa3c53 | ||
|
|
8a6d68e5d2 | ||
|
|
79c45131d1 | ||
|
|
fe18bbcb1f | ||
|
|
7a322130d6 | ||
|
|
41e555aadf | ||
|
|
2f270e6fbb | ||
|
|
cfcf5437f4 | ||
|
|
f5a2cb3593 | ||
|
|
1624efa939 | ||
|
|
6a8a202b71 | ||
|
|
3c3f1b42bb | ||
|
|
9a44fc5142 | ||
|
|
e3cc298ffd | ||
|
|
cd46a535cd | ||
|
|
80f310e2a4 | ||
|
|
ffc2f687cf | ||
|
|
e5b8a37a20 | ||
|
|
3dc206c721 | ||
|
|
d8960d2c55 | ||
|
|
64a5e6af4a | ||
|
|
b320c7ebd5 | ||
|
|
293e94d0ed | ||
|
|
8d1e4b3648 | ||
|
|
6e23e40a2f | ||
|
|
61605c1dfa | ||
|
|
c8cdd542dd | ||
|
|
5797c77f55 | ||
|
|
ae67923bab | ||
|
|
1159e53618 | ||
|
|
3de694be05 | ||
|
|
7b18274d7e | ||
|
|
9f49585a63 | ||
|
|
de731edc0d | ||
|
|
4f9236ae55 | ||
|
|
ff6a1cee12 | ||
|
|
6d8a924889 | ||
|
|
e396684a54 | ||
|
|
8abb85e4b2 | ||
|
|
6f4b0c4fa6 | ||
|
|
cb0e3980d8 | ||
|
|
36eeb92391 | ||
|
|
b7d9b59aa9 | ||
|
|
62e88b46cc | ||
|
|
7f6827aaae | ||
|
|
abb6cfdebd | ||
|
|
feb890564b | ||
|
|
1d3e6758b2 | ||
|
|
c52c07c086 | ||
|
|
554ff98fd5 | ||
|
|
160b70f417 | ||
|
|
c8189d1018 | ||
|
|
316f594fa5 | ||
|
|
bedac6bc28 | ||
|
|
40a4688400 | ||
|
|
399b0dd686 | ||
|
|
ecfe84702b | ||
|
|
0f4fdb6669 | ||
|
|
71788cf43a | ||
|
|
5165e14802 | ||
|
|
ead37db595 | ||
|
|
522bff52fe | ||
|
|
d514a9c709 | ||
|
|
67f54eea66 | ||
|
|
1a0bb5ad5a | ||
|
|
7e8e85459c | ||
|
|
5fba7e4339 | ||
|
|
962fea87d3 | ||
|
|
08a3461810 | ||
|
|
60d4c9bd54 | ||
|
|
7a9d8f49f4 | ||
|
|
50b7b2113e | ||
|
|
0b8117df2f | ||
|
|
0393f598d5 | ||
|
|
5573d7508b | ||
|
|
542162b4e0 | ||
|
|
e7260518ea | ||
|
|
82258dff59 | ||
|
|
a2f8946764 | ||
|
|
171a7a107e | ||
|
|
6195229d76 | ||
|
|
062515d9bc | ||
|
|
311264b960 | ||
|
|
bdd2cd248d | ||
|
|
1f6a7da0b0 | ||
|
|
71d2d60b85 | ||
|
|
4e66465e22 | ||
|
|
2288777334 | ||
|
|
cf0429f3e1 | ||
|
|
dff6c5ff7a | ||
|
|
df78cb7ccb | ||
|
|
acada5a8f6 | ||
|
|
20f8dafcd4 | ||
|
|
7bb1d8a8d1 | ||
|
|
39b5f5bbc6 | ||
|
|
7ebe1fe115 | ||
|
|
843bd4156e | ||
|
|
ca8d0a0e92 | ||
|
|
5989d675ce | ||
|
|
c4869780d1 | ||
|
|
998793998d | ||
|
|
e2459be7e1 | ||
|
|
33de42e729 | ||
|
|
b3b854072b | ||
|
|
54eabdde58 | ||
|
|
6e6ff89972 | ||
|
|
0992621839 | ||
|
|
7e9d37acae | ||
|
|
bfddc0dc64 | ||
|
|
b9196d48d2 | ||
|
|
75cb40edd1 | ||
|
|
124f8d57ab | ||
|
|
f78e04a12c | ||
|
|
b93fd4e0c9 | ||
|
|
401e456a17 | ||
|
|
69828ed94b | ||
|
|
627299f5e4 | ||
|
|
e4c60435d2 | ||
|
|
486edb10db | ||
|
|
8c4e7ffb14 | ||
|
|
dd0da65da9 | ||
|
|
75395a12e5 | ||
|
|
8b2397542e | ||
|
|
6132c9f8d5 | ||
|
|
ca57014bf2 | ||
|
|
3304a4f622 | ||
|
|
6538b82928 | ||
|
|
aa1b0fca72 | ||
|
|
aa9365446b | ||
|
|
632c1e83f8 | ||
|
|
115c8f8dd5 | ||
|
|
b8f4099e55 | ||
|
|
6c899d8947 | ||
|
|
3b5b21d29f | ||
|
|
65dde0c965 | ||
|
|
eb3144bacb | ||
|
|
efd19f766f | ||
|
|
4c8fb76a72 | ||
|
|
37c1739483 | ||
|
|
71fba3d221 | ||
|
|
1a44a8402e | ||
|
|
f8000b355e | ||
|
|
1329ff5f36 | ||
|
|
658c759b3d | ||
|
|
6e0ba733f3 | ||
|
|
0b10c8da28 | ||
|
|
0d271cbb09 | ||
|
|
a40e8ae321 | ||
|
|
95544096bf | ||
|
|
58fc4b8ea8 | ||
|
|
cf2da96a28 | ||
|
|
e1b6145e5c | ||
|
|
903fe8db7e | ||
|
|
39be1377e2 | ||
|
|
de4c7bd317 | ||
|
|
f78acf53fb | ||
|
|
92d625b648 | ||
|
|
305f6f0295 | ||
|
|
7641f23f87 | ||
|
|
491b0a26e4 | ||
|
|
5febdd39a1 | ||
|
|
c5cfa6c09c | ||
|
|
d0d6e34746 | ||
|
|
1db056b19c | ||
|
|
893159454f | ||
|
|
ce54c45394 | ||
|
|
4e502fd624 | ||
|
|
ad2e157763 | ||
|
|
d42090d63b | ||
|
|
1d181f0ade | ||
|
|
93d1d33f3f | ||
|
|
9649cc8c50 | ||
|
|
cb26ca2ce7 | ||
|
|
657948dd0c | ||
|
|
7e8d548d24 | ||
|
|
4770bfbb5b | ||
|
|
3018dc636a | ||
|
|
f610f40558 | ||
|
|
eb67febcc4 | ||
|
|
3676f20923 | ||
|
|
7940e854e6 | ||
|
|
cb253fafe7 | ||
|
|
33001c8c4b | ||
|
|
a511d5d95e | ||
|
|
619b808b31 | ||
|
|
56bde1ceca | ||
|
|
7925a98141 | ||
|
|
461c8c97db | ||
|
|
593949c88e | ||
|
|
73873da0c0 | ||
|
|
dae84a96fb | ||
|
|
89c2383c71 | ||
|
|
582a7f449e | ||
|
|
8d853b7eb6 | ||
|
|
a482b5cf12 | ||
|
|
0f8b560bd5 | ||
|
|
8466ee1c62 | ||
|
|
d4e0116ba8 | ||
|
|
16f2e53d5f | ||
|
|
17dd3370fc | ||
|
|
710778dfdd | ||
|
|
ef589f8981 | ||
|
|
16428ccbd2 | ||
|
|
c9e5433a70 | ||
|
|
4b39a9eaf8 | ||
|
|
1c02193ddb | ||
|
|
2be864c218 | ||
|
|
22339c9ba9 | ||
|
|
a8bfa02af1 | ||
|
|
8fedcffc02 | ||
|
|
5a0ae9a055 | ||
|
|
4d7d32c846 | ||
|
|
e3058de235 | ||
|
|
d7304e7c75 | ||
|
|
bde9269510 | ||
|
|
a5c7c469ee | ||
|
|
4e0787dcf3 | ||
|
|
7e59ef65e6 | ||
|
|
06e794898f | ||
|
|
5591fdff8d | ||
|
|
ae31233b19 | ||
|
|
b96a41d19e | ||
|
|
a416f30459 | ||
|
|
a2bc93547f | ||
|
|
bdac428d79 | ||
|
|
f7595c3348 | ||
|
|
a5abaed4ce | ||
|
|
7338c1b892 | ||
|
|
4321a363a4 | ||
|
|
d30ae35c62 | ||
|
|
292a337dad | ||
|
|
897635b32b | ||
|
|
e56c63172c | ||
|
|
3f7af974a3 | ||
|
|
d8272d4010 | ||
|
|
1163c6345b | ||
|
|
b7a9969e73 | ||
|
|
4fb762f6e4 | ||
|
|
78fecfe558 | ||
|
|
02282ba679 | ||
|
|
553544feac | ||
|
|
b0fd814975 | ||
|
|
80029d63f0 | ||
|
|
f0bf15d2cb | ||
|
|
fadd01e93e | ||
|
|
29ac62d7b0 | ||
|
|
01697a9ab8 | ||
|
|
d1cbf19798 | ||
|
|
451e1900a9 | ||
|
|
86f0baf146 | ||
|
|
7c9584e408 | ||
|
|
f952ac1dee | ||
|
|
52dd15dd87 | ||
|
|
984c6c33bc | ||
|
|
84be084384 | ||
|
|
91bafce012 | ||
|
|
77b328475a | ||
|
|
cc31f2f6e9 | ||
|
|
a83c7764f5 | ||
|
|
f374268521 | ||
|
|
ca48de34e9 | ||
|
|
2042facc8b | ||
|
|
df947d4056 | ||
|
|
3d6783e38c | ||
|
|
6c456aa15e | ||
|
|
bf1b3c1166 | ||
|
|
45517ad616 | ||
|
|
6d57b0ddb7 | ||
|
|
038550c889 | ||
|
|
2b9d47ff01 | ||
|
|
bc64aa2cf2 | ||
|
|
a6fba1b8a6 | ||
|
|
05215e8e7d | ||
|
|
fdbac8e51d | ||
|
|
e3385174c3 | ||
|
|
94ce9cad2a | ||
|
|
6ac9904ee5 | ||
|
|
4a429c11d5 | ||
|
|
cbf8c632dc | ||
|
|
578fc220ad | ||
|
|
cae9809e11 | ||
|
|
570564a375 | ||
|
|
5058406b84 | ||
|
|
7e6e9a0155 | ||
|
|
6137f1b0b2 | ||
|
|
689fdc1d0b | ||
|
|
791767d62f | ||
|
|
7455717359 | ||
|
|
3289d8482c | ||
|
|
8ce59e67d5 | ||
|
|
5f48fa3a6e | ||
|
|
0fff8a32b5 | ||
|
|
975c915632 | ||
|
|
307c1b3321 | ||
|
|
37da5dcdb6 | ||
|
|
35ae8ef313 | ||
|
|
14ec958b8f | ||
|
|
5b34bde1a4 | ||
|
|
44cfd1d49b | ||
|
|
7b1687ac0e | ||
|
|
648c15fbac | ||
|
|
34fd9dd88d | ||
|
|
37799b8560 | ||
|
|
64adf68436 | ||
|
|
f97dcc8e40 | ||
|
|
86dcdaae33 | ||
|
|
9fb526d554 | ||
|
|
e338cb00f3 | ||
|
|
d3edcc3fab | ||
|
|
e6a54f732e | ||
|
|
2e7c9ad2f3 | ||
|
|
367c3f034e | ||
|
|
901d83fcff | ||
|
|
4b22dcb7ad | ||
|
|
86c28f2d57 | ||
|
|
41fccf9fe4 | ||
|
|
4c17395deb | ||
|
|
240a012bd8 | ||
|
|
929b623e59 | ||
|
|
709d8223f5 | ||
|
|
8746283787 | ||
|
|
ff1b857f90 | ||
|
|
c010e93d4a | ||
|
|
5d522b0017 | ||
|
|
42c2282f12 | ||
|
|
8e23542b85 | ||
|
|
ef80a99397 | ||
|
|
ba11247f93 | ||
|
|
e5431ca7e5 | ||
|
|
b019a6aad9 | ||
|
|
3a1ffe4c69 | ||
|
|
9b4b0de746 | ||
|
|
a3441215f1 | ||
|
|
5adb2dc4cf | ||
|
|
3f7248fa11 | ||
|
|
5839981255 | ||
|
|
cd7db58ce3 | ||
|
|
3d74d8e95b | ||
|
|
3869421258 | ||
|
|
b4b2c18909 | ||
|
|
95d5334783 | ||
|
|
6f757b28f3 | ||
|
|
db2cf53e7b | ||
|
|
33ba1f38d6 | ||
|
|
3d680a6d82 | ||
|
|
c9bcf1b3f7 | ||
|
|
242b255aac | ||
|
|
5351f69e49 | ||
|
|
631d2b4214 | ||
|
|
235e1399eb | ||
|
|
163e7046cb | ||
|
|
41d174b7f6 |
+18
-1
@@ -1,12 +1,15 @@
|
||||
*.lo
|
||||
*.o
|
||||
/.libs/
|
||||
/.source
|
||||
/Makefile
|
||||
/autom4te.cache/
|
||||
/config.h
|
||||
/config.h.in~
|
||||
/config.log
|
||||
/config.status
|
||||
/dnstap/dnstap_config.h
|
||||
/dnscrypt/dnscrypt_config.h
|
||||
/doc/example.conf
|
||||
/doc/libunbound.3
|
||||
/doc/unbound-anchor.8
|
||||
@@ -17,6 +20,7 @@
|
||||
/doc/unbound.conf.5
|
||||
/libtool
|
||||
/libunbound.la
|
||||
/_unbound.la
|
||||
/smallapp/unbound-control-setup.sh
|
||||
/unbound
|
||||
/unbound-anchor
|
||||
@@ -35,4 +39,17 @@
|
||||
/streamtcp
|
||||
/testbound
|
||||
/unittest
|
||||
|
||||
/contrib/libunbound.pc
|
||||
/contrib/unbound.service
|
||||
/contrib/unbound.socket
|
||||
/dnstap/dnstap.pb-c.c
|
||||
/dnstap/dnstap.pb-c.h
|
||||
/libunbound/python/libunbound_wrap.c
|
||||
/libunbound/python/unbound.py
|
||||
/pythonmod/interface.h
|
||||
/pythonmod/unboundmodule.py
|
||||
/testdata/result.*
|
||||
/testdata/.done-*
|
||||
/testdata/.perfstats.txt
|
||||
/doc/html
|
||||
/doc/xml
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
sudo: false
|
||||
language: c
|
||||
compiler:
|
||||
- gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libssl-dev
|
||||
- libevent-dev
|
||||
- libexpat-dev
|
||||
- clang
|
||||
script:
|
||||
- ./configure --enable-debug --disable-flto
|
||||
- make
|
||||
- make test
|
||||
- (cd testdata/clang-analysis.tdir; bash clang-analysis.test)
|
||||
+533
-296
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,38 @@
|
||||
# Unbound
|
||||
|
||||
[](https://travis-ci.org/NLnetLabs/unbound)
|
||||
[](https://repology.org/project/unbound/versions)
|
||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:unbound)
|
||||
|
||||
Unbound is a validating, recursive, caching DNS resolver. It is designed to be
|
||||
fast and lean and incorporates modern features based on open standards. If you
|
||||
have any feedback, we would love to hear from you. Don’t hesitate to
|
||||
[create an issue on Github](https://github.com/NLnetLabs/unbound/issues/new)
|
||||
or post a message on the [Unbound mailing list](https://nlnetlabs.nl/mailman/listinfo/unbound-users).
|
||||
You can lean more about Unbound by reading our
|
||||
[documentation](https://nlnetlabs.nl/documentation/unbound/).
|
||||
|
||||
## Compiling
|
||||
|
||||
Make sure you have the C toolchain, OpenSSL and its include files, and libexpat
|
||||
installed. Unbound can be compiled and installed using:
|
||||
|
||||
```
|
||||
./configure && make && make install
|
||||
```
|
||||
|
||||
You can use libevent if you want. libevent is useful when using many (10000)
|
||||
outgoing ports. By default max 256 ports are opened at the same time and the
|
||||
builtin alternative is equally capable and a little faster.
|
||||
|
||||
Use the `--with-libevent=dir` configure option to compile Unbound with libevent
|
||||
support.
|
||||
|
||||
## Unbound configuration
|
||||
|
||||
All of Unbound's configuration options are described in the man pages, which
|
||||
will be installed and are available on the Unbound
|
||||
[documentation page](https://nlnetlabs.nl/documentation/unbound/).
|
||||
|
||||
An example configuration file is located in
|
||||
[doc/example.conf](https://github.com/NLnetLabs/unbound/blob/master/doc/example.conf.in).
|
||||
+14
-3
@@ -103,9 +103,20 @@ AC_DEFUN([AC_PROG_SWIG],[
|
||||
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
|
||||
[badversion=0]
|
||||
if test $available_major -lt $required_major ; then
|
||||
[badversion=1]
|
||||
fi
|
||||
if test $available_major -eq $required_major \
|
||||
-a $available_minor -lt $required_minor ; then
|
||||
[badversion=1]
|
||||
fi
|
||||
if test $available_major -eq $required_major \
|
||||
-a $available_minor -eq $required_minor \
|
||||
-a $available_patch -lt $required_patch ; then
|
||||
[badversion=1]
|
||||
fi
|
||||
if test $badversion -eq 1 ; then
|
||||
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
|
||||
|
||||
Vendored
+396
-2
@@ -1,6 +1,6 @@
|
||||
# generated automatically by aclocal 1.15 -*- Autoconf -*-
|
||||
# generated automatically by aclocal 1.16.1 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2018 Free Software Foundation, Inc.
|
||||
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@@ -9044,3 +9044,397 @@ m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
|
||||
m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
|
||||
m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
|
||||
|
||||
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
||||
# serial 11 (pkg-config-0.29.1)
|
||||
|
||||
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
||||
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
|
||||
dnl
|
||||
dnl This program is free software; you can redistribute it and/or modify
|
||||
dnl it under the terms of the GNU General Public License as published by
|
||||
dnl the Free Software Foundation; either version 2 of the License, or
|
||||
dnl (at your option) any later version.
|
||||
dnl
|
||||
dnl This program is distributed in the hope that it will be useful, but
|
||||
dnl WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
dnl General Public License for more details.
|
||||
dnl
|
||||
dnl You should have received a copy of the GNU General Public License
|
||||
dnl along with this program; if not, write to the Free Software
|
||||
dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
dnl 02111-1307, USA.
|
||||
dnl
|
||||
dnl As a special exception to the GNU General Public License, if you
|
||||
dnl distribute this file as part of a program that contains a
|
||||
dnl configuration script generated by Autoconf, you may include it under
|
||||
dnl the same distribution terms that you use for the rest of that
|
||||
dnl program.
|
||||
|
||||
dnl PKG_PREREQ(MIN-VERSION)
|
||||
dnl -----------------------
|
||||
dnl Since: 0.29
|
||||
dnl
|
||||
dnl Verify that the version of the pkg-config macros are at least
|
||||
dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
|
||||
dnl installed version of pkg-config, this checks the developer's version
|
||||
dnl of pkg.m4 when generating configure.
|
||||
dnl
|
||||
dnl To ensure that this macro is defined, also add:
|
||||
dnl m4_ifndef([PKG_PREREQ],
|
||||
dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
|
||||
dnl
|
||||
dnl See the "Since" comment for each macro you use to see what version
|
||||
dnl of the macros you require.
|
||||
m4_defun([PKG_PREREQ],
|
||||
[m4_define([PKG_MACROS_VERSION], [0.29.1])
|
||||
m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
|
||||
[m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
|
||||
])dnl PKG_PREREQ
|
||||
|
||||
dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
|
||||
dnl ----------------------------------
|
||||
dnl Since: 0.16
|
||||
dnl
|
||||
dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
|
||||
dnl first found in the path. Checks that the version of pkg-config found
|
||||
dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
|
||||
dnl used since that's the first version where most current features of
|
||||
dnl pkg-config existed.
|
||||
AC_DEFUN([PKG_PROG_PKG_CONFIG],
|
||||
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
||||
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
|
||||
m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
|
||||
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
|
||||
AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
|
||||
AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
|
||||
|
||||
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
|
||||
AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
|
||||
fi
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
_pkg_min_version=m4_default([$1], [0.9.0])
|
||||
AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
PKG_CONFIG=""
|
||||
fi
|
||||
fi[]dnl
|
||||
])dnl PKG_PROG_PKG_CONFIG
|
||||
|
||||
dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
dnl -------------------------------------------------------------------
|
||||
dnl Since: 0.18
|
||||
dnl
|
||||
dnl Check to see whether a particular set of modules exists. Similar to
|
||||
dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
|
||||
dnl
|
||||
dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||
dnl only at the first occurence in configure.ac, so if the first place
|
||||
dnl it's called might be skipped (such as if it is within an "if", you
|
||||
dnl have to call PKG_CHECK_EXISTS manually
|
||||
AC_DEFUN([PKG_CHECK_EXISTS],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
|
||||
m4_default([$2], [:])
|
||||
m4_ifvaln([$3], [else
|
||||
$3])dnl
|
||||
fi])
|
||||
|
||||
dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
|
||||
dnl ---------------------------------------------
|
||||
dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
|
||||
dnl pkg_failed based on the result.
|
||||
m4_define([_PKG_CONFIG],
|
||||
[if test -n "$$1"; then
|
||||
pkg_cv_[]$1="$$1"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
PKG_CHECK_EXISTS([$3],
|
||||
[pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes ],
|
||||
[pkg_failed=yes])
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi[]dnl
|
||||
])dnl _PKG_CONFIG
|
||||
|
||||
dnl _PKG_SHORT_ERRORS_SUPPORTED
|
||||
dnl ---------------------------
|
||||
dnl Internal check to see if pkg-config supports short errors.
|
||||
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
_pkg_short_errors_supported=yes
|
||||
else
|
||||
_pkg_short_errors_supported=no
|
||||
fi[]dnl
|
||||
])dnl _PKG_SHORT_ERRORS_SUPPORTED
|
||||
|
||||
|
||||
dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
||||
dnl [ACTION-IF-NOT-FOUND])
|
||||
dnl --------------------------------------------------------------
|
||||
dnl Since: 0.4.0
|
||||
dnl
|
||||
dnl Note that if there is a possibility the first call to
|
||||
dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
|
||||
dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
|
||||
AC_DEFUN([PKG_CHECK_MODULES],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
|
||||
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
|
||||
|
||||
pkg_failed=no
|
||||
AC_MSG_CHECKING([for $1])
|
||||
|
||||
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
|
||||
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
|
||||
|
||||
m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
|
||||
and $1[]_LIBS to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details.])
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
AC_MSG_RESULT([no])
|
||||
_PKG_SHORT_ERRORS_SUPPORTED
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
|
||||
else
|
||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
|
||||
|
||||
m4_default([$4], [AC_MSG_ERROR(
|
||||
[Package requirements ($2) were not met:
|
||||
|
||||
$$1_PKG_ERRORS
|
||||
|
||||
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||
installed software in a non-standard prefix.
|
||||
|
||||
_PKG_TEXT])[]dnl
|
||||
])
|
||||
elif test $pkg_failed = untried; then
|
||||
AC_MSG_RESULT([no])
|
||||
m4_default([$4], [AC_MSG_FAILURE(
|
||||
[The pkg-config script could not be found or is too old. Make sure it
|
||||
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||
path to pkg-config.
|
||||
|
||||
_PKG_TEXT
|
||||
|
||||
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
|
||||
])
|
||||
else
|
||||
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
|
||||
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
|
||||
AC_MSG_RESULT([yes])
|
||||
$3
|
||||
fi[]dnl
|
||||
])dnl PKG_CHECK_MODULES
|
||||
|
||||
|
||||
dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
||||
dnl [ACTION-IF-NOT-FOUND])
|
||||
dnl ---------------------------------------------------------------------
|
||||
dnl Since: 0.29
|
||||
dnl
|
||||
dnl Checks for existence of MODULES and gathers its build flags with
|
||||
dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
|
||||
dnl and VARIABLE-PREFIX_LIBS from --libs.
|
||||
dnl
|
||||
dnl Note that if there is a possibility the first call to
|
||||
dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
|
||||
dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
|
||||
dnl configure.ac.
|
||||
AC_DEFUN([PKG_CHECK_MODULES_STATIC],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
_save_PKG_CONFIG=$PKG_CONFIG
|
||||
PKG_CONFIG="$PKG_CONFIG --static"
|
||||
PKG_CHECK_MODULES($@)
|
||||
PKG_CONFIG=$_save_PKG_CONFIG[]dnl
|
||||
])dnl PKG_CHECK_MODULES_STATIC
|
||||
|
||||
|
||||
dnl PKG_INSTALLDIR([DIRECTORY])
|
||||
dnl -------------------------
|
||||
dnl Since: 0.27
|
||||
dnl
|
||||
dnl Substitutes the variable pkgconfigdir as the location where a module
|
||||
dnl should install pkg-config .pc files. By default the directory is
|
||||
dnl $libdir/pkgconfig, but the default can be changed by passing
|
||||
dnl DIRECTORY. The user can override through the --with-pkgconfigdir
|
||||
dnl parameter.
|
||||
AC_DEFUN([PKG_INSTALLDIR],
|
||||
[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
|
||||
m4_pushdef([pkg_description],
|
||||
[pkg-config installation directory @<:@]pkg_default[@:>@])
|
||||
AC_ARG_WITH([pkgconfigdir],
|
||||
[AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
|
||||
[with_pkgconfigdir=]pkg_default)
|
||||
AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
|
||||
m4_popdef([pkg_default])
|
||||
m4_popdef([pkg_description])
|
||||
])dnl PKG_INSTALLDIR
|
||||
|
||||
|
||||
dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
|
||||
dnl --------------------------------
|
||||
dnl Since: 0.27
|
||||
dnl
|
||||
dnl Substitutes the variable noarch_pkgconfigdir as the location where a
|
||||
dnl module should install arch-independent pkg-config .pc files. By
|
||||
dnl default the directory is $datadir/pkgconfig, but the default can be
|
||||
dnl changed by passing DIRECTORY. The user can override through the
|
||||
dnl --with-noarch-pkgconfigdir parameter.
|
||||
AC_DEFUN([PKG_NOARCH_INSTALLDIR],
|
||||
[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
|
||||
m4_pushdef([pkg_description],
|
||||
[pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
|
||||
AC_ARG_WITH([noarch-pkgconfigdir],
|
||||
[AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
|
||||
[with_noarch_pkgconfigdir=]pkg_default)
|
||||
AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
|
||||
m4_popdef([pkg_default])
|
||||
m4_popdef([pkg_description])
|
||||
])dnl PKG_NOARCH_INSTALLDIR
|
||||
|
||||
|
||||
dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
|
||||
dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
dnl -------------------------------------------
|
||||
dnl Since: 0.28
|
||||
dnl
|
||||
dnl Retrieves the value of the pkg-config variable for the given module.
|
||||
AC_DEFUN([PKG_CHECK_VAR],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
|
||||
|
||||
_PKG_CONFIG([$1], [variable="][$3]["], [$2])
|
||||
AS_VAR_COPY([$1], [pkg_cv_][$1])
|
||||
|
||||
AS_VAR_IF([$1], [""], [$5], [$4])dnl
|
||||
])dnl PKG_CHECK_VAR
|
||||
|
||||
dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES,
|
||||
dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND],
|
||||
dnl [DESCRIPTION], [DEFAULT])
|
||||
dnl ------------------------------------------
|
||||
dnl
|
||||
dnl Prepare a "--with-" configure option using the lowercase
|
||||
dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and
|
||||
dnl PKG_CHECK_MODULES in a single macro.
|
||||
AC_DEFUN([PKG_WITH_MODULES],
|
||||
[
|
||||
m4_pushdef([with_arg], m4_tolower([$1]))
|
||||
|
||||
m4_pushdef([description],
|
||||
[m4_default([$5], [build with ]with_arg[ support])])
|
||||
|
||||
m4_pushdef([def_arg], [m4_default([$6], [auto])])
|
||||
m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes])
|
||||
m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no])
|
||||
|
||||
m4_case(def_arg,
|
||||
[yes],[m4_pushdef([with_without], [--without-]with_arg)],
|
||||
[m4_pushdef([with_without],[--with-]with_arg)])
|
||||
|
||||
AC_ARG_WITH(with_arg,
|
||||
AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),,
|
||||
[AS_TR_SH([with_]with_arg)=def_arg])
|
||||
|
||||
AS_CASE([$AS_TR_SH([with_]with_arg)],
|
||||
[yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)],
|
||||
[auto],[PKG_CHECK_MODULES([$1],[$2],
|
||||
[m4_n([def_action_if_found]) $3],
|
||||
[m4_n([def_action_if_not_found]) $4])])
|
||||
|
||||
m4_popdef([with_arg])
|
||||
m4_popdef([description])
|
||||
m4_popdef([def_arg])
|
||||
|
||||
])dnl PKG_WITH_MODULES
|
||||
|
||||
dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
|
||||
dnl [DESCRIPTION], [DEFAULT])
|
||||
dnl -----------------------------------------------
|
||||
dnl
|
||||
dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES
|
||||
dnl check._[VARIABLE-PREFIX] is exported as make variable.
|
||||
AC_DEFUN([PKG_HAVE_WITH_MODULES],
|
||||
[
|
||||
PKG_WITH_MODULES([$1],[$2],,,[$3],[$4])
|
||||
|
||||
AM_CONDITIONAL([HAVE_][$1],
|
||||
[test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"])
|
||||
])dnl PKG_HAVE_WITH_MODULES
|
||||
|
||||
dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
|
||||
dnl [DESCRIPTION], [DEFAULT])
|
||||
dnl ------------------------------------------------------
|
||||
dnl
|
||||
dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after
|
||||
dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make
|
||||
dnl and preprocessor variable.
|
||||
AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES],
|
||||
[
|
||||
PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4])
|
||||
|
||||
AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"],
|
||||
[AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])])
|
||||
])dnl PKG_HAVE_DEFINE_WITH_MODULES
|
||||
|
||||
# AM_CONDITIONAL -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1997-2018 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
|
||||
# -------------------------------------
|
||||
# Define a conditional.
|
||||
AC_DEFUN([AM_CONDITIONAL],
|
||||
[AC_PREREQ([2.52])dnl
|
||||
m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
|
||||
[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
|
||||
AC_SUBST([$1_TRUE])dnl
|
||||
AC_SUBST([$1_FALSE])dnl
|
||||
_AM_SUBST_NOTMAKE([$1_TRUE])dnl
|
||||
_AM_SUBST_NOTMAKE([$1_FALSE])dnl
|
||||
m4_define([_AM_COND_VALUE_$1], [$2])dnl
|
||||
if $2; then
|
||||
$1_TRUE=
|
||||
$1_FALSE='#'
|
||||
else
|
||||
$1_TRUE='#'
|
||||
$1_FALSE=
|
||||
fi
|
||||
AC_CONFIG_COMMANDS_PRE(
|
||||
[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
|
||||
AC_MSG_ERROR([[conditional "$1" was never defined.
|
||||
Usually this means the macro was only invoked conditionally.]])
|
||||
fi])])
|
||||
|
||||
# Copyright (C) 2006-2018 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# _AM_SUBST_NOTMAKE(VARIABLE)
|
||||
# ---------------------------
|
||||
# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
|
||||
# This macro is traced by Automake.
|
||||
AC_DEFUN([_AM_SUBST_NOTMAKE])
|
||||
|
||||
# AM_SUBST_NOTMAKE(VARIABLE)
|
||||
# --------------------------
|
||||
# Public sister of _AM_SUBST_NOTMAKE.
|
||||
AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
|
||||
|
||||
|
||||
+7
-3
@@ -688,8 +688,8 @@ AC_DEFUN([ACX_SSL_CHECKS], [
|
||||
# check if -lwsock32 or -lgdi32 are needed.
|
||||
BAKLIBS="$LIBS"
|
||||
BAKSSLLIBS="$LIBSSL_LIBS"
|
||||
LIBS="$LIBS -lgdi32"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32"
|
||||
LIBS="$LIBS -lgdi32 -lws2_32"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32 -lws2_32"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -lgdi32])
|
||||
AC_TRY_LINK([], [
|
||||
int HMAC_Update(void);
|
||||
@@ -839,7 +839,11 @@ dnl see if on windows
|
||||
if test "$ac_cv_header_windows_h" = "yes"; then
|
||||
AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
|
||||
USE_WINSOCK="1"
|
||||
LIBS="$LIBS -lws2_32"
|
||||
if echo $LIBS | grep 'lws2_32' >/dev/null; then
|
||||
:
|
||||
else
|
||||
LIBS="$LIBS -lws2_32"
|
||||
fi
|
||||
fi
|
||||
],
|
||||
dnl no quick getaddrinfo, try mingw32 and winsock2 library.
|
||||
|
||||
+1
-2
@@ -22,8 +22,7 @@ AC_DEFUN([AC_PYTHON_DEVEL],[
|
||||
# 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
|
||||
if ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
|
||||
+152
-33
@@ -43,6 +43,7 @@
|
||||
#include "config.h"
|
||||
#ifdef USE_CACHEDB
|
||||
#include "cachedb/cachedb.h"
|
||||
#include "cachedb/redis.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/config_file.h"
|
||||
@@ -56,11 +57,39 @@
|
||||
#include "sldns/wire2str.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
|
||||
#define CACHEDB_HASHSIZE 256 /* bit hash */
|
||||
/* header file for htobe64 */
|
||||
#ifdef HAVE_ENDIAN_H
|
||||
# include <endian.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_ENDIAN_H
|
||||
# include <sys/endian.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIBKERN_OSBYTEORDER_H
|
||||
/* In practice this is specific to MacOS X. We assume it doesn't have
|
||||
* htobe64/be64toh but has alternatives with a different name. */
|
||||
# include <libkern/OSByteOrder.h>
|
||||
# define htobe64(x) OSSwapHostToBigInt64(x)
|
||||
# define be64toh(x) OSSwapBigToHostInt64(x)
|
||||
#endif
|
||||
|
||||
/* Some compilers do not define __BYTE_ORDER__, like IBM XLC on AIX */
|
||||
#ifndef be64toh
|
||||
#if defined(__sun) || defined(_AIX)
|
||||
# if __BIG_ENDIAN__
|
||||
# define be64toh(n) (n)
|
||||
# define htobe64(n) (n)
|
||||
# else
|
||||
# define be64toh(n) (((uint64_t)htonl((n) & 0xFFFFFFFF) << 32) | htonl((n) >> 32))
|
||||
# define htobe64(n) (((uint64_t)htonl((n) & 0xFFFFFFFF) << 32) | htonl((n) >> 32))
|
||||
# endif
|
||||
#endif
|
||||
#endif /* be64toh */
|
||||
|
||||
/** the unit test testframe for cachedb, its module state contains
|
||||
* a cache for a couple queries (in memory). */
|
||||
struct testframe_moddata {
|
||||
/** lock for mutex */
|
||||
lock_basic_type lock;
|
||||
/** key for single stored data element, NULL if none */
|
||||
char* stored_key;
|
||||
/** data for single stored data element, NULL if none */
|
||||
@@ -72,14 +101,18 @@ struct testframe_moddata {
|
||||
static int
|
||||
testframe_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
{
|
||||
struct testframe_moddata* d;
|
||||
(void)env;
|
||||
verbose(VERB_ALGO, "testframe_init");
|
||||
cachedb_env->backend_data = (void*)calloc(1,
|
||||
d = (struct testframe_moddata*)calloc(1,
|
||||
sizeof(struct testframe_moddata));
|
||||
cachedb_env->backend_data = (void*)d;
|
||||
if(!cachedb_env->backend_data) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
lock_basic_init(&d->lock);
|
||||
lock_protect(&d->lock, d, sizeof(*d));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -92,6 +125,7 @@ testframe_deinit(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
verbose(VERB_ALGO, "testframe_deinit");
|
||||
if(!d)
|
||||
return;
|
||||
lock_basic_destroy(&d->lock);
|
||||
free(d->stored_key);
|
||||
free(d->stored_data);
|
||||
free(d);
|
||||
@@ -105,17 +139,22 @@ testframe_lookup(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
cachedb_env->backend_data;
|
||||
(void)env;
|
||||
verbose(VERB_ALGO, "testframe_lookup of %s", key);
|
||||
lock_basic_lock(&d->lock);
|
||||
if(d->stored_key && strcmp(d->stored_key, key) == 0) {
|
||||
if(d->stored_datalen > sldns_buffer_capacity(result_buffer))
|
||||
if(d->stored_datalen > sldns_buffer_capacity(result_buffer)) {
|
||||
lock_basic_unlock(&d->lock);
|
||||
return 0; /* too large */
|
||||
}
|
||||
verbose(VERB_ALGO, "testframe_lookup found %d bytes",
|
||||
(int)d->stored_datalen);
|
||||
sldns_buffer_clear(result_buffer);
|
||||
sldns_buffer_write(result_buffer, d->stored_data,
|
||||
d->stored_datalen);
|
||||
sldns_buffer_flip(result_buffer);
|
||||
lock_basic_unlock(&d->lock);
|
||||
return 1;
|
||||
}
|
||||
lock_basic_unlock(&d->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -126,6 +165,7 @@ testframe_store(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
struct testframe_moddata* d = (struct testframe_moddata*)
|
||||
cachedb_env->backend_data;
|
||||
(void)env;
|
||||
lock_basic_lock(&d->lock);
|
||||
verbose(VERB_ALGO, "testframe_store %s (%d bytes)", key, (int)data_len);
|
||||
|
||||
/* free old data element (if any) */
|
||||
@@ -137,6 +177,7 @@ testframe_store(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
|
||||
d->stored_data = memdup(data, data_len);
|
||||
if(!d->stored_data) {
|
||||
lock_basic_unlock(&d->lock);
|
||||
log_err("out of memory");
|
||||
return;
|
||||
}
|
||||
@@ -146,8 +187,10 @@ testframe_store(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
free(d->stored_data);
|
||||
d->stored_data = NULL;
|
||||
d->stored_datalen = 0;
|
||||
lock_basic_unlock(&d->lock);
|
||||
return;
|
||||
}
|
||||
lock_basic_unlock(&d->lock);
|
||||
/* (key,data) successfully stored */
|
||||
}
|
||||
|
||||
@@ -160,6 +203,10 @@ static struct cachedb_backend testframe_backend = { "testframe",
|
||||
static struct cachedb_backend*
|
||||
cachedb_find_backend(const char* str)
|
||||
{
|
||||
#ifdef USE_REDIS
|
||||
if(strcmp(str, redis_backend.name) == 0)
|
||||
return &redis_backend;
|
||||
#endif
|
||||
if(strcmp(str, testframe_backend.name) == 0)
|
||||
return &testframe_backend;
|
||||
/* TODO add more backends here */
|
||||
@@ -170,15 +217,17 @@ cachedb_find_backend(const char* str)
|
||||
static int
|
||||
cachedb_apply_cfg(struct cachedb_env* cachedb_env, struct config_file* cfg)
|
||||
{
|
||||
const char* backend_str = "testframe"; /* TODO get from cfg */
|
||||
if(backend_str && backend_str[0]) {
|
||||
cachedb_env->backend = cachedb_find_backend(backend_str);
|
||||
if(!cachedb_env->backend) {
|
||||
log_err("cachedb: cannot find backend name '%s",
|
||||
backend_str);
|
||||
return NULL;
|
||||
}
|
||||
const char* backend_str = cfg->cachedb_backend;
|
||||
|
||||
/* If unspecified we use the in-memory test DB. */
|
||||
if(!backend_str)
|
||||
backend_str = "testframe";
|
||||
cachedb_env->backend = cachedb_find_backend(backend_str);
|
||||
if(!cachedb_env->backend) {
|
||||
log_err("cachedb: cannot find backend name '%s'", backend_str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO see if more configuration needs to be applied or not */
|
||||
return 1;
|
||||
}
|
||||
@@ -195,6 +244,8 @@ cachedb_init(struct module_env* env, int id)
|
||||
env->modinfo[id] = (void*)cachedb_env;
|
||||
if(!cachedb_apply_cfg(cachedb_env, env->cfg)) {
|
||||
log_err("cachedb: could not apply configuration settings.");
|
||||
free(cachedb_env);
|
||||
env->modinfo[id] = NULL;
|
||||
return 0;
|
||||
}
|
||||
/* see if a backend is selected */
|
||||
@@ -203,6 +254,8 @@ cachedb_init(struct module_env* env, int id)
|
||||
if(!(*cachedb_env->backend->init)(env, cachedb_env)) {
|
||||
log_err("cachedb: could not init %s backend",
|
||||
cachedb_env->backend->name);
|
||||
free(cachedb_env);
|
||||
env->modinfo[id] = NULL;
|
||||
return 0;
|
||||
}
|
||||
cachedb_env->enabled = 1;
|
||||
@@ -276,9 +329,10 @@ calc_hash(struct module_qstate* qstate, char* buf, size_t len)
|
||||
size_t clen = 0;
|
||||
uint8_t hash[CACHEDB_HASHSIZE/8];
|
||||
const char* hex = "0123456789ABCDEF";
|
||||
const char* secret = "default"; /* TODO: from qstate->env->cfg */
|
||||
const char* secret = qstate->env->cfg->cachedb_secret ?
|
||||
qstate->env->cfg->cachedb_secret : "default";
|
||||
size_t i;
|
||||
|
||||
|
||||
/* copy the hash info into the clear buffer */
|
||||
if(clen + qstate->qinfo.qname_len < sizeof(clear)) {
|
||||
memmove(clear+clen, qstate->qinfo.qname,
|
||||
@@ -299,7 +353,11 @@ calc_hash(struct module_qstate* qstate, char* buf, size_t len)
|
||||
|
||||
/* hash the buffer */
|
||||
secalgo_hash_sha256(clear, clen, hash);
|
||||
#ifdef HAVE_EXPLICIT_BZERO
|
||||
explicit_bzero(clear, clen);
|
||||
#else
|
||||
memset(clear, 0, clen);
|
||||
#endif
|
||||
|
||||
/* hex encode output for portability (some online dbs need
|
||||
* no nulls, no control characters, and so on) */
|
||||
@@ -328,6 +386,13 @@ prep_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
|
||||
if(!qstate->return_msg || !qstate->return_msg->rep)
|
||||
return 0;
|
||||
/* We don't store the reply if its TTL is 0 unless serve-expired is
|
||||
* enabled. Such a reply won't be reusable and simply be a waste for
|
||||
* the backend. It's also compatible with the default behavior of
|
||||
* dns_cache_store_msg(). */
|
||||
if(qstate->return_msg->rep->ttl == 0 &&
|
||||
!qstate->env->cfg->serve_expired)
|
||||
return 0;
|
||||
if(verbosity >= VERB_ALGO)
|
||||
log_dns_msg("cachedb encoding", &qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
@@ -368,12 +433,48 @@ good_expiry_and_qinfo(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
&expiry, sizeof(expiry));
|
||||
expiry = be64toh(expiry);
|
||||
|
||||
if((time_t)expiry < *qstate->env->now)
|
||||
if((time_t)expiry < *qstate->env->now &&
|
||||
!qstate->env->cfg->serve_expired)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Adjust the TTL of the given RRset by 'subtract'. If 'subtract' is
|
||||
* negative, set the TTL to 0. */
|
||||
static void
|
||||
packed_rrset_ttl_subtract(struct packed_rrset_data* data, time_t subtract)
|
||||
{
|
||||
size_t i;
|
||||
size_t total = data->count + data->rrsig_count;
|
||||
if(subtract >= 0 && data->ttl > subtract)
|
||||
data->ttl -= subtract;
|
||||
else data->ttl = 0;
|
||||
for(i=0; i<total; i++) {
|
||||
if(subtract >= 0 && data->rr_ttl[i] > subtract)
|
||||
data->rr_ttl[i] -= subtract;
|
||||
else data->rr_ttl[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust the TTL of a DNS message and its RRs by 'adjust'. If 'adjust' is
|
||||
* negative, set the TTLs to 0. */
|
||||
static void
|
||||
adjust_msg_ttl(struct dns_msg* msg, time_t adjust)
|
||||
{
|
||||
size_t i;
|
||||
if(adjust >= 0 && msg->rep->ttl > adjust)
|
||||
msg->rep->ttl -= adjust;
|
||||
else msg->rep->ttl = 0;
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
|
||||
|
||||
for(i=0; i<msg->rep->rrset_count; i++) {
|
||||
packed_rrset_ttl_subtract((struct packed_rrset_data*)msg->
|
||||
rep->rrsets[i]->entry.data, adjust);
|
||||
}
|
||||
}
|
||||
|
||||
/** convert dns message in buffer to return_msg */
|
||||
static int
|
||||
parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
@@ -420,24 +521,34 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
|
||||
/* see how much of the TTL expired, and remove it */
|
||||
if(*qstate->env->now <= (time_t)timestamp) {
|
||||
verbose(VERB_ALGO, "cachedb msg adjust by zero");
|
||||
return 1; /* message from the future (clock skew?) */
|
||||
}
|
||||
adjust = *qstate->env->now - (time_t)timestamp;
|
||||
if(qstate->return_msg->rep->ttl < adjust) {
|
||||
verbose(VERB_ALGO, "cachedb msg expired");
|
||||
/* If serve-expired is enabled, we still use an expired message
|
||||
* setting the TTL to 0. */
|
||||
if(qstate->env->cfg->serve_expired)
|
||||
adjust = -1;
|
||||
else
|
||||
return 0; /* message expired */
|
||||
}
|
||||
verbose(VERB_ALGO, "cachedb msg adjusted down by %d", (int)adjust);
|
||||
/*adjust_msg(qstate->return_msg, adjust);*/
|
||||
/* TODO:
|
||||
msg->rep->ttl = r->ttl - adjust;
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
for(i=0; i<d->count + d->rrsig_count; i++) {
|
||||
if(d->rr_ttl[i] < adjust)
|
||||
d->rr_ttl[i] = 0;
|
||||
else d->rr_ttl[i] -= adjust;
|
||||
}
|
||||
if(d->ttl < adjust)
|
||||
d->ttl = 0;
|
||||
else d->ttl -= adjust;
|
||||
*/
|
||||
/* TODO */
|
||||
adjust_msg_ttl(qstate->return_msg, adjust);
|
||||
|
||||
return 0;
|
||||
/* Similar to the unbound worker, if serve-expired is enabled and
|
||||
* the msg would be considered to be expired, mark the state so a
|
||||
* refetch will be scheduled. The comparison between 'expiry' and
|
||||
* 'now' should be redundant given how these values were calculated,
|
||||
* but we check it just in case as does good_expiry_and_qinfo(). */
|
||||
if(qstate->env->cfg->serve_expired &&
|
||||
(adjust == -1 || (time_t)expiry < *qstate->env->now)) {
|
||||
qstate->need_refetch = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -497,14 +608,18 @@ cachedb_intcache_lookup(struct module_qstate* qstate)
|
||||
msg = dns_cache_lookup(qstate->env, qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len, qstate->qinfo.qtype,
|
||||
qstate->qinfo.qclass, qstate->query_flags,
|
||||
qstate->region, qstate->env->scratch);
|
||||
if(!msg && qstate->env->neg_cache) {
|
||||
qstate->region, qstate->env->scratch,
|
||||
1 /* no partial messages with only a CNAME */
|
||||
);
|
||||
if(!msg && qstate->env->neg_cache &&
|
||||
iter_qname_indicates_dnssec(qstate->env, &qstate->qinfo)) {
|
||||
/* lookup in negative cache; may result in
|
||||
* NOERROR/NODATA or NXDOMAIN answers that need validation */
|
||||
msg = val_neg_getmsg(qstate->env->neg_cache, &qstate->qinfo,
|
||||
qstate->region, qstate->env->rrset_cache,
|
||||
qstate->env->scratch_buffer,
|
||||
*qstate->env->now, 1/*add SOA*/, NULL);
|
||||
*qstate->env->now, 1/*add SOA*/, NULL,
|
||||
qstate->env->cfg);
|
||||
}
|
||||
if(!msg)
|
||||
return 0;
|
||||
@@ -520,11 +635,15 @@ cachedb_intcache_lookup(struct module_qstate* qstate)
|
||||
static void
|
||||
cachedb_intcache_store(struct module_qstate* qstate)
|
||||
{
|
||||
uint32_t store_flags = qstate->query_flags;
|
||||
|
||||
if(qstate->env->cfg->serve_expired)
|
||||
store_flags |= DNSCACHE_STORE_ZEROTTL;
|
||||
if(!qstate->return_msg)
|
||||
return;
|
||||
(void)dns_cache_store(qstate->env, &qstate->qinfo,
|
||||
qstate->return_msg->rep, 0, qstate->prefetch_leeway, 0,
|
||||
qstate->region, qstate->query_flags);
|
||||
qstate->region, store_flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -87,6 +87,8 @@ struct cachedb_backend {
|
||||
uint8_t*, size_t);
|
||||
};
|
||||
|
||||
#define CACHEDB_HASHSIZE 256 /* bit hash */
|
||||
|
||||
/** Init the cachedb module */
|
||||
int cachedb_init(struct module_env* env, int id);
|
||||
/** Deinit the cachedb module */
|
||||
|
||||
+283
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* cachedb/redis.c - cachedb redis module
|
||||
*
|
||||
* Copyright (c) 2018, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains a module that uses the redis database to cache
|
||||
* dns responses.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#ifdef USE_CACHEDB
|
||||
#include "cachedb/redis.h"
|
||||
#include "cachedb/cachedb.h"
|
||||
#include "util/alloc.h"
|
||||
#include "util/config_file.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
|
||||
#ifdef USE_REDIS
|
||||
#include "hiredis/hiredis.h"
|
||||
|
||||
struct redis_moddata {
|
||||
redisContext** ctxs; /* thread-specific redis contexts */
|
||||
int numctxs; /* number of ctx entries */
|
||||
const char* server_host; /* server's IP address or host name */
|
||||
int server_port; /* server's TCP port */
|
||||
struct timeval timeout; /* timeout for connection setup and commands */
|
||||
};
|
||||
|
||||
static redisContext*
|
||||
redis_connect(const struct redis_moddata* moddata)
|
||||
{
|
||||
redisContext* ctx;
|
||||
|
||||
ctx = redisConnectWithTimeout(moddata->server_host,
|
||||
moddata->server_port, moddata->timeout);
|
||||
if(!ctx || ctx->err) {
|
||||
const char *errstr = "out of memory";
|
||||
if(ctx)
|
||||
errstr = ctx->errstr;
|
||||
log_err("failed to connect to redis server: %s", errstr);
|
||||
goto fail;
|
||||
}
|
||||
if(redisSetTimeout(ctx, moddata->timeout) != REDIS_OK) {
|
||||
log_err("failed to set redis timeout");
|
||||
goto fail;
|
||||
}
|
||||
return ctx;
|
||||
|
||||
fail:
|
||||
if(ctx)
|
||||
redisFree(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
{
|
||||
int i;
|
||||
struct redis_moddata* moddata = NULL;
|
||||
|
||||
verbose(VERB_ALGO, "redis_init");
|
||||
|
||||
moddata = calloc(1, sizeof(struct redis_moddata));
|
||||
if(!moddata) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
moddata->numctxs = env->cfg->num_threads;
|
||||
moddata->ctxs = calloc(env->cfg->num_threads, sizeof(redisContext*));
|
||||
if(!moddata->ctxs) {
|
||||
log_err("out of memory");
|
||||
free(moddata);
|
||||
return 0;
|
||||
}
|
||||
/* note: server_host is a shallow reference to configured string.
|
||||
* we don't have to free it in this module. */
|
||||
moddata->server_host = env->cfg->redis_server_host;
|
||||
moddata->server_port = env->cfg->redis_server_port;
|
||||
moddata->timeout.tv_sec = env->cfg->redis_timeout / 1000;
|
||||
moddata->timeout.tv_usec = (env->cfg->redis_timeout % 1000) * 1000;
|
||||
for(i = 0; i < moddata->numctxs; i++)
|
||||
moddata->ctxs[i] = redis_connect(moddata);
|
||||
cachedb_env->backend_data = moddata;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
redis_deinit(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
{
|
||||
struct redis_moddata* moddata = (struct redis_moddata*)
|
||||
cachedb_env->backend_data;
|
||||
(void)env;
|
||||
|
||||
verbose(VERB_ALGO, "redis_deinit");
|
||||
|
||||
if(!moddata)
|
||||
return;
|
||||
if(moddata->ctxs) {
|
||||
int i;
|
||||
for(i = 0; i < moddata->numctxs; i++) {
|
||||
if(moddata->ctxs[i])
|
||||
redisFree(moddata->ctxs[i]);
|
||||
}
|
||||
free(moddata->ctxs);
|
||||
}
|
||||
free(moddata);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a redis command and get a reply. Unified so that it can be used for
|
||||
* both SET and GET. If 'data' is non-NULL the command is supposed to be
|
||||
* SET and GET otherwise, but the implementation of this function is agnostic
|
||||
* about the semantics (except for logging): 'command', 'data', and 'data_len'
|
||||
* are opaquely passed to redisCommand().
|
||||
* This function first checks whether a connection with a redis server has
|
||||
* been established; if not it tries to set up a new one.
|
||||
* It returns redisReply returned from redisCommand() or NULL if some low
|
||||
* level error happens. The caller is responsible to check the return value,
|
||||
* if it's non-NULL, it has to free it with freeReplyObject().
|
||||
*/
|
||||
static redisReply*
|
||||
redis_command(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
const char* command, const uint8_t* data, size_t data_len)
|
||||
{
|
||||
redisContext* ctx;
|
||||
redisReply* rep;
|
||||
struct redis_moddata* d = (struct redis_moddata*)
|
||||
cachedb_env->backend_data;
|
||||
|
||||
/* We assume env->alloc->thread_num is a unique ID for each thread
|
||||
* in [0, num-of-threads). We could treat it as an error condition
|
||||
* if the assumption didn't hold, but it seems to be a fundamental
|
||||
* assumption throughout the unbound architecture, so we simply assert
|
||||
* it. */
|
||||
log_assert(env->alloc->thread_num < d->numctxs);
|
||||
ctx = d->ctxs[env->alloc->thread_num];
|
||||
|
||||
/* If we've not established a connection to the server or we've closed
|
||||
* it on a failure, try to re-establish a new one. Failures will be
|
||||
* logged in redis_connect(). */
|
||||
if(!ctx) {
|
||||
ctx = redis_connect(d);
|
||||
d->ctxs[env->alloc->thread_num] = ctx;
|
||||
}
|
||||
if(!ctx)
|
||||
return NULL;
|
||||
|
||||
/* Send the command and get a reply, synchronously. */
|
||||
rep = (redisReply*)redisCommand(ctx, command, data, data_len);
|
||||
if(!rep) {
|
||||
/* Once an error as a NULL-reply is returned the context cannot
|
||||
* be reused and we'll need to set up a new connection. */
|
||||
log_err("redis_command: failed to receive a reply, "
|
||||
"closing connection: %s", ctx->errstr);
|
||||
redisFree(ctx);
|
||||
d->ctxs[env->alloc->thread_num] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check error in reply to unify logging in that case.
|
||||
* The caller may perform context-dependent checks and logging. */
|
||||
if(rep->type == REDIS_REPLY_ERROR)
|
||||
log_err("redis: %s resulted in an error: %s",
|
||||
data ? "set" : "get", rep->str);
|
||||
|
||||
return rep;
|
||||
}
|
||||
|
||||
static int
|
||||
redis_lookup(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
char* key, struct sldns_buffer* result_buffer)
|
||||
{
|
||||
redisReply* rep;
|
||||
char cmdbuf[4+(CACHEDB_HASHSIZE/8)*2+1]; /* "GET " + key */
|
||||
int n;
|
||||
int ret = 0;
|
||||
|
||||
verbose(VERB_ALGO, "redis_lookup of %s", key);
|
||||
|
||||
n = snprintf(cmdbuf, sizeof(cmdbuf), "GET %s", key);
|
||||
if(n < 0 || n >= (int)sizeof(cmdbuf)) {
|
||||
log_err("redis_lookup: unexpected failure to build command");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rep = redis_command(env, cachedb_env, cmdbuf, NULL, 0);
|
||||
if(!rep)
|
||||
return 0;
|
||||
switch (rep->type) {
|
||||
case REDIS_REPLY_NIL:
|
||||
verbose(VERB_ALGO, "redis_lookup: no data cached");
|
||||
break;
|
||||
case REDIS_REPLY_STRING:
|
||||
verbose(VERB_ALGO, "redis_lookup found %d bytes",
|
||||
(int)rep->len);
|
||||
if((size_t)rep->len > sldns_buffer_capacity(result_buffer)) {
|
||||
log_err("redis_lookup: replied data too long: %lu",
|
||||
(size_t)rep->len);
|
||||
break;
|
||||
}
|
||||
sldns_buffer_clear(result_buffer);
|
||||
sldns_buffer_write(result_buffer, rep->str, rep->len);
|
||||
sldns_buffer_flip(result_buffer);
|
||||
ret = 1;
|
||||
break;
|
||||
case REDIS_REPLY_ERROR:
|
||||
break; /* already logged */
|
||||
default:
|
||||
log_err("redis_lookup: unexpected type of reply for (%d)",
|
||||
rep->type);
|
||||
break;
|
||||
}
|
||||
freeReplyObject(rep);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
char* key, uint8_t* data, size_t data_len)
|
||||
{
|
||||
redisReply* rep;
|
||||
char cmdbuf[4+(CACHEDB_HASHSIZE/8)*2+3+1]; /* "SET " + key + " %b" */
|
||||
int n;
|
||||
|
||||
verbose(VERB_ALGO, "redis_store %s (%d bytes)", key, (int)data_len);
|
||||
|
||||
/* build command to set to a binary safe string */
|
||||
n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b", key);
|
||||
if(n < 0 || n >= (int)sizeof(cmdbuf)) {
|
||||
log_err("redis_store: unexpected failure to build command");
|
||||
return;
|
||||
}
|
||||
|
||||
rep = redis_command(env, cachedb_env, cmdbuf, data, data_len);
|
||||
if(rep) {
|
||||
verbose(VERB_ALGO, "redis_store set completed");
|
||||
if(rep->type != REDIS_REPLY_STATUS &&
|
||||
rep->type != REDIS_REPLY_ERROR) {
|
||||
log_err("redis_store: unexpected type of reply (%d)",
|
||||
rep->type);
|
||||
}
|
||||
freeReplyObject(rep);
|
||||
}
|
||||
}
|
||||
|
||||
struct cachedb_backend redis_backend = { "redis",
|
||||
redis_init, redis_deinit, redis_lookup, redis_store
|
||||
};
|
||||
#endif /* USE_REDIS */
|
||||
#endif /* USE_CACHEDB */
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* cachedb/redis.h - cachedb redis module
|
||||
*
|
||||
* Copyright (c) 2018, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains a module that uses the redis database to cache
|
||||
* dns responses.
|
||||
*/
|
||||
|
||||
/** the redis backend definition, contains callable functions
|
||||
* and name string */
|
||||
extern struct cachedb_backend redis_backend;
|
||||
+16
-1
@@ -33,6 +33,9 @@
|
||||
*/
|
||||
#include "config.h"
|
||||
#define LOCKRET(func) func
|
||||
#ifdef ENABLE_LOCK_CHECKS
|
||||
#undef ENABLE_LOCK_CHECKS
|
||||
#endif
|
||||
#include "util/locks.h"
|
||||
|
||||
void _ARC4_LOCK(void);
|
||||
@@ -46,9 +49,13 @@ void _ARC4_LOCK(void)
|
||||
void _ARC4_UNLOCK(void)
|
||||
{
|
||||
}
|
||||
|
||||
void _ARC4_LOCK_DESTROY(void)
|
||||
{
|
||||
}
|
||||
#else /* !THREADS_DISABLED */
|
||||
|
||||
static lock_quick_t arc4lock;
|
||||
static lock_quick_type arc4lock;
|
||||
static int arc4lockinit = 0;
|
||||
|
||||
void _ARC4_LOCK(void)
|
||||
@@ -64,4 +71,12 @@ void _ARC4_UNLOCK(void)
|
||||
{
|
||||
lock_quick_unlock(&arc4lock);
|
||||
}
|
||||
|
||||
void _ARC4_LOCK_DESTROY(void)
|
||||
{
|
||||
if(arc4lockinit) {
|
||||
arc4lockinit = 0;
|
||||
lock_quick_destroy(&arc4lock);
|
||||
}
|
||||
}
|
||||
#endif /* THREADS_DISABLED */
|
||||
|
||||
+72
-2
@@ -71,9 +71,76 @@ static struct {
|
||||
|
||||
static inline void _rs_rekey(u_char *dat, size_t datlen);
|
||||
|
||||
/*
|
||||
* Basic sanity checking; wish we could do better.
|
||||
*/
|
||||
static int
|
||||
fallback_gotdata(char *buf, size_t len)
|
||||
{
|
||||
char any_set = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
any_set |= buf[i];
|
||||
if (any_set == 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fallback for getentropy in case libc returns failure */
|
||||
static int
|
||||
fallback_getentropy_urandom(void *buf, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
int fd, flags;
|
||||
int save_errno = errno;
|
||||
|
||||
start:
|
||||
|
||||
flags = O_RDONLY;
|
||||
#ifdef O_NOFOLLOW
|
||||
flags |= O_NOFOLLOW;
|
||||
#endif
|
||||
#ifdef O_CLOEXEC
|
||||
flags |= O_CLOEXEC;
|
||||
#endif
|
||||
fd = open("/dev/urandom", flags, 0);
|
||||
if (fd == -1) {
|
||||
if (errno == EINTR)
|
||||
goto start;
|
||||
goto nodevrandom;
|
||||
}
|
||||
#ifndef O_CLOEXEC
|
||||
# ifdef HAVE_FCNTL
|
||||
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
|
||||
# endif
|
||||
#endif
|
||||
for (i = 0; i < len; ) {
|
||||
size_t wanted = len - i;
|
||||
ssize_t ret = read(fd, (char*)buf + i, wanted);
|
||||
|
||||
if (ret == -1) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
close(fd);
|
||||
goto nodevrandom;
|
||||
}
|
||||
i += ret;
|
||||
}
|
||||
close(fd);
|
||||
if (fallback_gotdata(buf, len) == 0) {
|
||||
errno = save_errno;
|
||||
return 0; /* satisfied */
|
||||
}
|
||||
nodevrandom:
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_rs_init(u_char *buf, size_t n)
|
||||
{
|
||||
assert(buf);
|
||||
if (n < KEYSZ + IVSZ)
|
||||
return;
|
||||
|
||||
@@ -114,11 +181,14 @@ _rs_stir(void)
|
||||
u_char rnd[KEYSZ + IVSZ];
|
||||
|
||||
if (getentropy(rnd, sizeof rnd) == -1) {
|
||||
if(errno != ENOSYS ||
|
||||
fallback_getentropy_urandom(rnd, sizeof rnd) == -1) {
|
||||
#ifdef SIGKILL
|
||||
raise(SIGKILL);
|
||||
raise(SIGKILL);
|
||||
#else
|
||||
exit(9); /* windows */
|
||||
exit(9); /* windows */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (!rs)
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
#include "util/locks.h"
|
||||
|
||||
/** the lock for ctime buffer */
|
||||
static lock_basic_t ctime_lock;
|
||||
static lock_basic_type ctime_lock;
|
||||
/** has it been inited */
|
||||
static int ctime_r_init = 0;
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/* $OpenBSD: getentropy_freebsd.c,v 1.3 2016/08/07 03:27:21 tb Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
* Copyright (c) 2014 Brent Cook <bcook@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Emulation of getentropy(2) as documented at:
|
||||
* http://man.openbsd.org/getentropy.2
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
* Derived from lib/libc/gen/arc4random.c from FreeBSD.
|
||||
*/
|
||||
static size_t
|
||||
getentropy_sysctl(u_char *buf, size_t size)
|
||||
{
|
||||
int mib[2];
|
||||
size_t len, done;
|
||||
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_ARND;
|
||||
done = 0;
|
||||
|
||||
do {
|
||||
len = size;
|
||||
if (sysctl(mib, 2, buf, &len, NULL, 0) == -1)
|
||||
return (done);
|
||||
done += len;
|
||||
buf += len;
|
||||
size -= len;
|
||||
} while (size > 0);
|
||||
|
||||
return (done);
|
||||
}
|
||||
|
||||
int
|
||||
getentropy(void *buf, size_t len)
|
||||
{
|
||||
if (len <= 256 && getentropy_sysctl(buf, len) == len)
|
||||
return (0);
|
||||
|
||||
errno = EIO;
|
||||
return (-1);
|
||||
}
|
||||
+63
-84
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: getentropy_linux.c,v 1.20 2014/07/12 15:43:49 beck Exp $ */
|
||||
/* $OpenBSD: getentropy_linux.c,v 1.46 2018/11/20 08:04:28 deraadt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
|
||||
@@ -15,20 +15,23 @@
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Emulation of getentropy(2) as documented at:
|
||||
* http://man.openbsd.org/getentropy.2
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include "config.h"
|
||||
/*
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
#define _GNU_SOURCE 1
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
#define _GNU_SOURCE 1
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/syscall.h>
|
||||
#ifdef HAVE_SYS_SYSCTL_H
|
||||
#include <sys/sysctl.h>
|
||||
#ifdef SYS__sysctl
|
||||
#include <linux/sysctl.h>
|
||||
#endif
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -39,6 +42,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <link.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
@@ -46,16 +50,18 @@
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#if defined(HAVE_SSL)
|
||||
#ifndef HAVE_NETTLE
|
||||
#include <openssl/sha.h>
|
||||
#elif defined(HAVE_NETTLE)
|
||||
#else
|
||||
#include <nettle/sha.h>
|
||||
#define SHA512_CTX struct sha512_ctx
|
||||
#define SHA512_Init(x) sha512_init(x)
|
||||
#define SHA512_Update(x, b, s) sha512_update(x, s, b)
|
||||
#define SHA512_Final(r, c) sha512_digest(c, SHA512_DIGEST_SIZE, r)
|
||||
#endif
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/sysctl.h>
|
||||
#ifdef HAVE_GETAUXVAL
|
||||
#include <sys/auxv.h>
|
||||
#endif
|
||||
@@ -75,29 +81,13 @@
|
||||
HD(b); \
|
||||
} while (0)
|
||||
|
||||
#if defined(HAVE_SSL)
|
||||
#define CRYPTO_SHA512_CTX SHA512_CTX
|
||||
#define CRYPTO_SHA512_INIT(x) SHA512_Init(x)
|
||||
#define CRYPTO_SHA512_FINAL(r, c) SHA512_Final(r, c)
|
||||
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
|
||||
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
|
||||
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
|
||||
#elif defined(HAVE_NETTLE)
|
||||
#define CRYPTO_SHA512_CTX struct sha512_ctx
|
||||
#define CRYPTO_SHA512_INIT(x) sha512_init(x)
|
||||
#define CRYPTO_SHA512_FINAL(r, c) sha512_digest(c, SHA512_DIGEST_SIZE, r)
|
||||
#define HR(x, l) (sha512_update(&ctx, (l), (uint8_t *)(x)))
|
||||
#define HD(x) (sha512_update(&ctx, sizeof (x), (uint8_t *)&(x)))
|
||||
#define HF(x) (sha512_update(&ctx, sizeof (void*), (uint8_t *)&(x)))
|
||||
#endif
|
||||
|
||||
int getentropy(void *buf, size_t len);
|
||||
|
||||
#ifdef CAN_REFERENCE_MAIN
|
||||
extern int main(int, char *argv[]);
|
||||
#endif
|
||||
static int gotdata(char *buf, size_t len);
|
||||
#if defined(SYS_getrandom) && defined(__NR_getrandom)
|
||||
#if defined(SYS_getrandom) && defined(GRND_NONBLOCK)
|
||||
static int getentropy_getrandom(void *buf, size_t len);
|
||||
#endif
|
||||
static int getentropy_urandom(void *buf, size_t len);
|
||||
@@ -105,6 +95,7 @@ static int getentropy_urandom(void *buf, size_t len);
|
||||
static int getentropy_sysctl(void *buf, size_t len);
|
||||
#endif
|
||||
static int getentropy_fallback(void *buf, size_t len);
|
||||
static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
|
||||
|
||||
int
|
||||
getentropy(void *buf, size_t len)
|
||||
@@ -113,18 +104,21 @@ getentropy(void *buf, size_t len)
|
||||
|
||||
if (len > 256) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#if defined(SYS_getrandom) && defined(__NR_getrandom)
|
||||
#if defined(SYS_getrandom) && defined(GRND_NONBLOCK)
|
||||
/*
|
||||
* Try descriptor-less getrandom()
|
||||
* Try descriptor-less getrandom(), in non-blocking mode.
|
||||
*
|
||||
* The design of Linux getrandom is broken. It has an
|
||||
* uninitialized phase coupled with blocking behaviour, which
|
||||
* is unacceptable from within a library at boot time without
|
||||
* possible recovery. See http://bugs.python.org/issue26839#msg267745
|
||||
*/
|
||||
ret = getentropy_getrandom(buf, len);
|
||||
if (ret != -1)
|
||||
return (ret);
|
||||
if (errno != ENOSYS)
|
||||
return (-1);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -178,7 +172,7 @@ getentropy(void *buf, size_t len)
|
||||
* - Do the best under the circumstances....
|
||||
*
|
||||
* This code path exists to bring light to the issue that Linux
|
||||
* does not provide a failsafe API for entropy collection.
|
||||
* still does not provide a failsafe API for entropy collection.
|
||||
*
|
||||
* We hope this demonstrates that Linux should either retain their
|
||||
* sysctl ABI, or consider providing a new failsafe API which
|
||||
@@ -196,23 +190,7 @@ getentropy(void *buf, size_t len)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Basic sanity checking; wish we could do better.
|
||||
*/
|
||||
static int
|
||||
gotdata(char *buf, size_t len)
|
||||
{
|
||||
char any_set = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
any_set |= buf[i];
|
||||
if (any_set == 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(SYS_getrandom) && defined(__NR_getrandom)
|
||||
#if defined(SYS_getrandom) && defined(GRND_NONBLOCK)
|
||||
static int
|
||||
getentropy_getrandom(void *buf, size_t len)
|
||||
{
|
||||
@@ -221,7 +199,7 @@ getentropy_getrandom(void *buf, size_t len)
|
||||
if (len > 256)
|
||||
return (-1);
|
||||
do {
|
||||
ret = syscall(SYS_getrandom, buf, len, 0);
|
||||
ret = syscall(SYS_getrandom, buf, len, GRND_NONBLOCK);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
|
||||
if (ret != (int)len)
|
||||
@@ -269,7 +247,7 @@ start:
|
||||
}
|
||||
for (i = 0; i < len; ) {
|
||||
size_t wanted = len - i;
|
||||
ssize_t ret = read(fd, (char*)buf + i, wanted);
|
||||
ssize_t ret = read(fd, (char *)buf + i, wanted);
|
||||
|
||||
if (ret == -1) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
@@ -280,13 +258,11 @@ start:
|
||||
i += ret;
|
||||
}
|
||||
close(fd);
|
||||
if (gotdata(buf, len) == 0) {
|
||||
errno = save_errno;
|
||||
return 0; /* satisfied */
|
||||
}
|
||||
errno = save_errno;
|
||||
return (0); /* satisfied */
|
||||
nodevrandom:
|
||||
errno = EIO;
|
||||
return -1;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#ifdef SYS__sysctl
|
||||
@@ -311,17 +287,15 @@ getentropy_sysctl(void *buf, size_t len)
|
||||
goto sysctlfailed;
|
||||
i += chunk;
|
||||
}
|
||||
if (gotdata(buf, len) == 0) {
|
||||
errno = save_errno;
|
||||
return (0); /* satisfied */
|
||||
}
|
||||
errno = save_errno;
|
||||
return (0); /* satisfied */
|
||||
sysctlfailed:
|
||||
errno = EIO;
|
||||
return -1;
|
||||
return (-1);
|
||||
}
|
||||
#endif /* SYS__sysctl */
|
||||
|
||||
static int cl[] = {
|
||||
static const int cl[] = {
|
||||
CLOCK_REALTIME,
|
||||
#ifdef CLOCK_MONOTONIC
|
||||
CLOCK_MONOTONIC,
|
||||
@@ -346,6 +320,15 @@ static int cl[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static int
|
||||
getentropy_phdr(struct dl_phdr_info *info, size_t ATTR_UNUSED(size), void *data)
|
||||
{
|
||||
SHA512_CTX *ctx = data;
|
||||
|
||||
SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
getentropy_fallback(void *buf, size_t len)
|
||||
{
|
||||
@@ -357,7 +340,7 @@ getentropy_fallback(void *buf, size_t len)
|
||||
struct rusage ru;
|
||||
sigset_t sigset;
|
||||
struct stat st;
|
||||
CRYPTO_SHA512_CTX ctx;
|
||||
SHA512_CTX ctx;
|
||||
static pid_t lastpid;
|
||||
pid_t pid;
|
||||
size_t i, ii, m;
|
||||
@@ -374,7 +357,7 @@ getentropy_fallback(void *buf, size_t len)
|
||||
}
|
||||
for (i = 0; i < len; ) {
|
||||
int j;
|
||||
CRYPTO_SHA512_INIT(&ctx);
|
||||
SHA512_Init(&ctx);
|
||||
for (j = 0; j < repeat; j++) {
|
||||
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
|
||||
if (e != -1) {
|
||||
@@ -382,6 +365,8 @@ getentropy_fallback(void *buf, size_t len)
|
||||
cnt += (int)tv.tv_usec;
|
||||
}
|
||||
|
||||
dl_iterate_phdr(getentropy_phdr, &ctx);
|
||||
|
||||
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
|
||||
HX(clock_gettime(cl[ii], &ts) == -1, ts);
|
||||
|
||||
@@ -401,9 +386,6 @@ getentropy_fallback(void *buf, size_t len)
|
||||
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
|
||||
sigset);
|
||||
|
||||
#ifdef CAN_REFERENCE_MAIN
|
||||
HF(main); /* an addr in program */
|
||||
#endif
|
||||
HF(getentropy); /* an addr in this library */
|
||||
HF(printf); /* an addr in libc */
|
||||
p = (char *)&p;
|
||||
@@ -528,33 +510,30 @@ getentropy_fallback(void *buf, size_t len)
|
||||
HD(cnt);
|
||||
}
|
||||
#ifdef HAVE_GETAUXVAL
|
||||
# ifdef AT_RANDOM
|
||||
#ifdef AT_RANDOM
|
||||
/* Not as random as you think but we take what we are given */
|
||||
p = (char *) getauxval(AT_RANDOM);
|
||||
if (p)
|
||||
HR(p, 16);
|
||||
# endif
|
||||
# ifdef AT_SYSINFO_EHDR
|
||||
#endif
|
||||
#ifdef AT_SYSINFO_EHDR
|
||||
p = (char *) getauxval(AT_SYSINFO_EHDR);
|
||||
if (p)
|
||||
HR(p, pgs);
|
||||
# endif
|
||||
# ifdef AT_BASE
|
||||
#endif
|
||||
#ifdef AT_BASE
|
||||
p = (char *) getauxval(AT_BASE);
|
||||
if (p)
|
||||
HD(p);
|
||||
# endif
|
||||
#endif /* HAVE_GETAUXVAL */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
CRYPTO_SHA512_FINAL(results, &ctx);
|
||||
memcpy((char*)buf + i, results, min(sizeof(results), len - i));
|
||||
SHA512_Final(results, &ctx);
|
||||
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
|
||||
i += min(sizeof(results), len - i);
|
||||
}
|
||||
memset(results, 0, sizeof results);
|
||||
if (gotdata(buf, len) == 0) {
|
||||
errno = save_errno;
|
||||
return 0; /* satisfied */
|
||||
}
|
||||
errno = EIO;
|
||||
return -1;
|
||||
explicit_bzero(&ctx, sizeof ctx);
|
||||
explicit_bzero(results, sizeof results);
|
||||
errno = save_errno;
|
||||
return (0); /* satisfied */
|
||||
}
|
||||
|
||||
+25
-40
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: getentropy_osx.c,v 1.3 2014/07/12 14:48:00 deraadt Exp $ */
|
||||
/* $OpenBSD: getentropy_osx.c,v 1.12 2018/11/20 08:04:28 deraadt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
|
||||
@@ -15,9 +15,12 @@
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Emulation of getentropy(2) as documented at:
|
||||
* http://man.openbsd.org/getentropy.2
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <TargetConditionals.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
@@ -43,14 +46,18 @@
|
||||
#include <mach/mach_time.h>
|
||||
#include <mach/mach_host.h>
|
||||
#include <mach/host_info.h>
|
||||
#if TARGET_OS_OSX
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/vmmeter.h>
|
||||
#endif
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#if TARGET_OS_OSX
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/tcp_var.h>
|
||||
#include <netinet/udp_var.h>
|
||||
#endif
|
||||
#include <CommonCrypto/CommonDigest.h>
|
||||
#define SHA512_Update(a, b, c) (CC_SHA512_Update((a), (b), (c)))
|
||||
#define SHA512_Init(xxx) (CC_SHA512_Init((xxx)))
|
||||
@@ -75,10 +82,6 @@
|
||||
|
||||
int getentropy(void *buf, size_t len);
|
||||
|
||||
#ifdef CAN_REFERENCE_MAIN
|
||||
extern int main(int, char *argv[]);
|
||||
#endif
|
||||
static int gotdata(char *buf, size_t len);
|
||||
static int getentropy_urandom(void *buf, size_t len);
|
||||
static int getentropy_fallback(void *buf, size_t len);
|
||||
|
||||
@@ -89,7 +92,7 @@ getentropy(void *buf, size_t len)
|
||||
|
||||
if (len > 256) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -138,22 +141,6 @@ getentropy(void *buf, size_t len)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Basic sanity checking; wish we could do better.
|
||||
*/
|
||||
static int
|
||||
gotdata(char *buf, size_t len)
|
||||
{
|
||||
char any_set = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
any_set |= buf[i];
|
||||
if (any_set == 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
getentropy_urandom(void *buf, size_t len)
|
||||
{
|
||||
@@ -188,7 +175,7 @@ start:
|
||||
}
|
||||
for (i = 0; i < len; ) {
|
||||
size_t wanted = len - i;
|
||||
ssize_t ret = read(fd, (char*)buf + i, wanted);
|
||||
ssize_t ret = read(fd, (char *)buf + i, wanted);
|
||||
|
||||
if (ret == -1) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
@@ -199,18 +186,18 @@ start:
|
||||
i += ret;
|
||||
}
|
||||
close(fd);
|
||||
if (gotdata(buf, len) == 0) {
|
||||
errno = save_errno;
|
||||
return 0; /* satisfied */
|
||||
}
|
||||
errno = save_errno;
|
||||
return (0); /* satisfied */
|
||||
nodevrandom:
|
||||
errno = EIO;
|
||||
return -1;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
static int tcpmib[] = { CTL_NET, AF_INET, IPPROTO_TCP, TCPCTL_STATS };
|
||||
static int udpmib[] = { CTL_NET, AF_INET, IPPROTO_UDP, UDPCTL_STATS };
|
||||
static int ipmib[] = { CTL_NET, AF_INET, IPPROTO_IP, IPCTL_STATS };
|
||||
#endif
|
||||
static int kmib[] = { CTL_KERN, KERN_USRSTACK };
|
||||
static int hwmib[] = { CTL_HW, HW_USERMEM };
|
||||
|
||||
@@ -230,9 +217,11 @@ getentropy_fallback(void *buf, size_t len)
|
||||
pid_t pid;
|
||||
size_t i, ii, m;
|
||||
char *p;
|
||||
#if TARGET_OS_OSX
|
||||
struct tcpstat tcpstat;
|
||||
struct udpstat udpstat;
|
||||
struct ipstat ipstat;
|
||||
#endif
|
||||
u_int64_t mach_time;
|
||||
unsigned int idata;
|
||||
void *addr;
|
||||
@@ -267,6 +256,7 @@ getentropy_fallback(void *buf, size_t len)
|
||||
HX(sysctl(hwmib, sizeof(hwmib) / sizeof(hwmib[0]),
|
||||
&idata, &ii, NULL, 0) == -1, idata);
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
ii = sizeof(tcpstat);
|
||||
HX(sysctl(tcpmib, sizeof(tcpmib) / sizeof(tcpmib[0]),
|
||||
&tcpstat, &ii, NULL, 0) == -1, tcpstat);
|
||||
@@ -278,6 +268,7 @@ getentropy_fallback(void *buf, size_t len)
|
||||
ii = sizeof(ipstat);
|
||||
HX(sysctl(ipmib, sizeof(ipmib) / sizeof(ipmib[0]),
|
||||
&ipstat, &ii, NULL, 0) == -1, ipstat);
|
||||
#endif
|
||||
|
||||
HX((pid = getpid()) == -1, pid);
|
||||
HX((pid = getsid(pid)) == -1, pid);
|
||||
@@ -295,9 +286,6 @@ getentropy_fallback(void *buf, size_t len)
|
||||
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
|
||||
sigset);
|
||||
|
||||
#ifdef CAN_REFERENCE_MAIN
|
||||
HF(main); /* an addr in program */
|
||||
#endif
|
||||
HF(getentropy); /* an addr in this library */
|
||||
HF(printf); /* an addr in libc */
|
||||
p = (char *)&p;
|
||||
@@ -419,14 +407,11 @@ getentropy_fallback(void *buf, size_t len)
|
||||
}
|
||||
|
||||
SHA512_Final(results, &ctx);
|
||||
memcpy((char*)buf + i, results, min(sizeof(results), len - i));
|
||||
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
|
||||
i += min(sizeof(results), len - i);
|
||||
}
|
||||
memset(results, 0, sizeof results);
|
||||
if (gotdata(buf, len) == 0) {
|
||||
errno = save_errno;
|
||||
return 0; /* satisfied */
|
||||
}
|
||||
errno = EIO;
|
||||
return -1;
|
||||
explicit_bzero(&ctx, sizeof ctx);
|
||||
explicit_bzero(results, sizeof results);
|
||||
errno = save_errno;
|
||||
return (0); /* satisfied */
|
||||
}
|
||||
|
||||
+29
-41
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: getentropy_solaris.c,v 1.3 2014/07/12 14:46:31 deraadt Exp $ */
|
||||
/* $OpenBSD: getentropy_solaris.c,v 1.13 2018/11/20 08:04:28 deraadt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
|
||||
@@ -15,9 +15,12 @@
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Emulation of getentropy(2) as documented at:
|
||||
* http://man.openbsd.org/getentropy.2
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include "config.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
@@ -34,6 +37,7 @@
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <link.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
@@ -67,17 +71,14 @@
|
||||
|
||||
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
|
||||
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
|
||||
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
|
||||
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
|
||||
|
||||
int getentropy(void *buf, size_t len);
|
||||
|
||||
#ifdef CAN_REFERENCE_MAIN
|
||||
extern int main(int, char *argv[]);
|
||||
#endif
|
||||
static int gotdata(char *buf, size_t len);
|
||||
static int getentropy_urandom(void *buf, size_t len, const char *path,
|
||||
int devfscheck);
|
||||
static int getentropy_fallback(void *buf, size_t len);
|
||||
static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
|
||||
|
||||
int
|
||||
getentropy(void *buf, size_t len)
|
||||
@@ -86,7 +87,7 @@ getentropy(void *buf, size_t len)
|
||||
|
||||
if (len > 256) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -153,22 +154,6 @@ getentropy(void *buf, size_t len)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Basic sanity checking; wish we could do better.
|
||||
*/
|
||||
static int
|
||||
gotdata(char *buf, size_t len)
|
||||
{
|
||||
char any_set = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
any_set |= buf[i];
|
||||
if (any_set == 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
|
||||
{
|
||||
@@ -204,7 +189,7 @@ start:
|
||||
}
|
||||
for (i = 0; i < len; ) {
|
||||
size_t wanted = len - i;
|
||||
ssize_t ret = read(fd, (char*)buf + i, wanted);
|
||||
ssize_t ret = read(fd, (char *)buf + i, wanted);
|
||||
|
||||
if (ret == -1) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
@@ -215,13 +200,11 @@ start:
|
||||
i += ret;
|
||||
}
|
||||
close(fd);
|
||||
if (gotdata(buf, len) == 0) {
|
||||
errno = save_errno;
|
||||
return 0; /* satisfied */
|
||||
}
|
||||
errno = save_errno;
|
||||
return (0); /* satisfied */
|
||||
nodevrandom:
|
||||
errno = EIO;
|
||||
return -1;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static const int cl[] = {
|
||||
@@ -249,6 +232,15 @@ static const int cl[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static int
|
||||
getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
|
||||
{
|
||||
SHA512_CTX *ctx = data;
|
||||
|
||||
SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
getentropy_fallback(void *buf, size_t len)
|
||||
{
|
||||
@@ -286,6 +278,8 @@ getentropy_fallback(void *buf, size_t len)
|
||||
cnt += (int)tv.tv_usec;
|
||||
}
|
||||
|
||||
dl_iterate_phdr(getentropy_phdr, &ctx);
|
||||
|
||||
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
|
||||
HX(clock_gettime(cl[ii], &ts) == -1, ts);
|
||||
|
||||
@@ -306,9 +300,6 @@ getentropy_fallback(void *buf, size_t len)
|
||||
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
|
||||
sigset);
|
||||
|
||||
#ifdef CAN_REFERENCE_MAIN
|
||||
HF(main); /* an addr in program */
|
||||
#endif
|
||||
HF(getentropy); /* an addr in this library */
|
||||
HF(printf); /* an addr in libc */
|
||||
p = (char *)&p;
|
||||
@@ -428,14 +419,11 @@ getentropy_fallback(void *buf, size_t len)
|
||||
HD(cnt);
|
||||
}
|
||||
SHA512_Final(results, &ctx);
|
||||
memcpy((char*)buf + i, results, min(sizeof(results), len - i));
|
||||
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
|
||||
i += min(sizeof(results), len - i);
|
||||
}
|
||||
memset(results, 0, sizeof results);
|
||||
if (gotdata(buf, len) == 0) {
|
||||
errno = save_errno;
|
||||
return 0; /* satisfied */
|
||||
}
|
||||
errno = EIO;
|
||||
return -1;
|
||||
explicit_bzero(&ctx, sizeof ctx);
|
||||
explicit_bzero(results, sizeof results);
|
||||
errno = save_errno;
|
||||
return (0); /* satisfied */
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD$ */
|
||||
/* $OpenBSD: getentropy_win.c,v 1.5 2016/08/07 03:27:21 tb Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
|
||||
@@ -15,6 +15,9 @@
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Emulation of getentropy(2) as documented at:
|
||||
* http://man.openbsd.org/getentropy.2
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
@@ -37,7 +40,7 @@ getentropy(void *buf, size_t len)
|
||||
|
||||
if (len > 256) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
|
||||
|
||||
@@ -5,7 +5,12 @@
|
||||
#undef malloc
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef USE_WINSOCK
|
||||
void *malloc ();
|
||||
#else
|
||||
/* provide a prototype */
|
||||
void *malloc (size_t n);
|
||||
#endif
|
||||
|
||||
/* Allocate an N-byte block of memory from the heap.
|
||||
If N is zero, allocate a 1-byte block. */
|
||||
|
||||
+5
-2
@@ -658,7 +658,7 @@ int vsnprintf(char* str, size_t size, const char* format, va_list arg)
|
||||
* are not their own functions. */
|
||||
|
||||
/* printout designation:
|
||||
* conversion specifier: x, d, u, s, c, n, m, p
|
||||
* conversion specifier: x, d, u, s, c, m, p
|
||||
* flags: # not supported
|
||||
* 0 zeropad (on the left)
|
||||
* - left adjust (right by default)
|
||||
@@ -798,7 +798,10 @@ int vsnprintf(char* str, size_t size, const char* format, va_list arg)
|
||||
minw, minus);
|
||||
break;
|
||||
case 'n':
|
||||
*va_arg(arg, int*) = ret;
|
||||
/* unsupported to harden against format string
|
||||
* exploitation,
|
||||
* handled like an unknown format specifier. */
|
||||
/* *va_arg(arg, int*) = ret; */
|
||||
break;
|
||||
case 'm':
|
||||
print_str(&at, &left, &ret, strerror(errno),
|
||||
|
||||
Vendored
+130
-226
@@ -1,8 +1,8 @@
|
||||
#! /bin/sh
|
||||
#!/usr/bin/sh
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright 1992-2013 Free Software Foundation, Inc.
|
||||
# Copyright 1992-2016 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2013-06-10'
|
||||
timestamp='2016-10-02'
|
||||
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
@@ -24,12 +24,12 @@ timestamp='2013-06-10'
|
||||
# program. This Exception is an additional permission under section 7
|
||||
# of the GNU General Public License, version 3 ("GPLv3").
|
||||
#
|
||||
# Originally written by Per Bothner.
|
||||
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
|
||||
#
|
||||
# You can get the latest version of this script from:
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
|
||||
#
|
||||
# Please send patches with a ChangeLog entry to config-patches@gnu.org.
|
||||
# Please send patches to <config-patches@gnu.org>.
|
||||
|
||||
|
||||
me=`echo "$0" | sed -e 's,.*/,,'`
|
||||
@@ -50,7 +50,7 @@ version="\
|
||||
GNU config.guess ($timestamp)
|
||||
|
||||
Originally written by Per Bothner.
|
||||
Copyright 1992-2013 Free Software Foundation, Inc.
|
||||
Copyright 1992-2016 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@@ -149,7 +149,7 @@ Linux|GNU|GNU/*)
|
||||
LIBC=gnu
|
||||
#endif
|
||||
EOF
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -168,19 +168,29 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
# Note: NetBSD doesn't particularly care about the vendor
|
||||
# portion of the name. We always set it to "unknown".
|
||||
sysctl="sysctl -n hw.machine_arch"
|
||||
UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
|
||||
/usr/sbin/$sysctl 2>/dev/null || echo unknown)`
|
||||
UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
|
||||
/sbin/$sysctl 2>/dev/null || \
|
||||
/usr/sbin/$sysctl 2>/dev/null || \
|
||||
echo unknown)`
|
||||
case "${UNAME_MACHINE_ARCH}" in
|
||||
armeb) machine=armeb-unknown ;;
|
||||
arm*) machine=arm-unknown ;;
|
||||
sh3el) machine=shl-unknown ;;
|
||||
sh3eb) machine=sh-unknown ;;
|
||||
sh5el) machine=sh5le-unknown ;;
|
||||
earmv*)
|
||||
arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
|
||||
endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
|
||||
machine=${arch}${endian}-unknown
|
||||
;;
|
||||
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
|
||||
esac
|
||||
# The Operating System including object format, if it has switched
|
||||
# to ELF recently, or will in the future.
|
||||
# to ELF recently (or will in the future) and ABI.
|
||||
case "${UNAME_MACHINE_ARCH}" in
|
||||
earm*)
|
||||
os=netbsdelf
|
||||
;;
|
||||
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
|
||||
eval $set_cc_for_build
|
||||
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
@@ -197,6 +207,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
os=netbsd
|
||||
;;
|
||||
esac
|
||||
# Determine ABI tags.
|
||||
case "${UNAME_MACHINE_ARCH}" in
|
||||
earm*)
|
||||
expr='s/^earmv[0-9]/-eabi/;s/eb$//'
|
||||
abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
|
||||
;;
|
||||
esac
|
||||
# The OS release
|
||||
# Debian GNU/NetBSD machines have a different userland, and
|
||||
# thus, need a distinct triplet. However, they do not need
|
||||
@@ -207,13 +224,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
release='-gnu'
|
||||
;;
|
||||
*)
|
||||
release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
||||
release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
|
||||
;;
|
||||
esac
|
||||
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
|
||||
# contains redundant information, the shorter form:
|
||||
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
|
||||
echo "${machine}-${os}${release}"
|
||||
echo "${machine}-${os}${release}${abi}"
|
||||
exit ;;
|
||||
*:Bitrig:*:*)
|
||||
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
|
||||
@@ -223,6 +240,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
|
||||
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:LibertyBSD:*:*)
|
||||
UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
|
||||
echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:ekkoBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
|
||||
exit ;;
|
||||
@@ -235,6 +256,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
*:MirBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:Sortix:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-sortix
|
||||
exit ;;
|
||||
alpha:OSF1:*:*)
|
||||
case $UNAME_RELEASE in
|
||||
*4.0)
|
||||
@@ -251,42 +275,42 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
|
||||
case "$ALPHA_CPU_TYPE" in
|
||||
"EV4 (21064)")
|
||||
UNAME_MACHINE="alpha" ;;
|
||||
UNAME_MACHINE=alpha ;;
|
||||
"EV4.5 (21064)")
|
||||
UNAME_MACHINE="alpha" ;;
|
||||
UNAME_MACHINE=alpha ;;
|
||||
"LCA4 (21066/21068)")
|
||||
UNAME_MACHINE="alpha" ;;
|
||||
UNAME_MACHINE=alpha ;;
|
||||
"EV5 (21164)")
|
||||
UNAME_MACHINE="alphaev5" ;;
|
||||
UNAME_MACHINE=alphaev5 ;;
|
||||
"EV5.6 (21164A)")
|
||||
UNAME_MACHINE="alphaev56" ;;
|
||||
UNAME_MACHINE=alphaev56 ;;
|
||||
"EV5.6 (21164PC)")
|
||||
UNAME_MACHINE="alphapca56" ;;
|
||||
UNAME_MACHINE=alphapca56 ;;
|
||||
"EV5.7 (21164PC)")
|
||||
UNAME_MACHINE="alphapca57" ;;
|
||||
UNAME_MACHINE=alphapca57 ;;
|
||||
"EV6 (21264)")
|
||||
UNAME_MACHINE="alphaev6" ;;
|
||||
UNAME_MACHINE=alphaev6 ;;
|
||||
"EV6.7 (21264A)")
|
||||
UNAME_MACHINE="alphaev67" ;;
|
||||
UNAME_MACHINE=alphaev67 ;;
|
||||
"EV6.8CB (21264C)")
|
||||
UNAME_MACHINE="alphaev68" ;;
|
||||
UNAME_MACHINE=alphaev68 ;;
|
||||
"EV6.8AL (21264B)")
|
||||
UNAME_MACHINE="alphaev68" ;;
|
||||
UNAME_MACHINE=alphaev68 ;;
|
||||
"EV6.8CX (21264D)")
|
||||
UNAME_MACHINE="alphaev68" ;;
|
||||
UNAME_MACHINE=alphaev68 ;;
|
||||
"EV6.9A (21264/EV69A)")
|
||||
UNAME_MACHINE="alphaev69" ;;
|
||||
UNAME_MACHINE=alphaev69 ;;
|
||||
"EV7 (21364)")
|
||||
UNAME_MACHINE="alphaev7" ;;
|
||||
UNAME_MACHINE=alphaev7 ;;
|
||||
"EV7.9 (21364A)")
|
||||
UNAME_MACHINE="alphaev79" ;;
|
||||
UNAME_MACHINE=alphaev79 ;;
|
||||
esac
|
||||
# A Pn.n version is a patched version.
|
||||
# A Vn.n version is a released version.
|
||||
# A Tn.n version is a released field test version.
|
||||
# A Xn.n version is an unreleased experimental baselevel.
|
||||
# 1.2 uses "1.2" for uname -r.
|
||||
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
||||
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
|
||||
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
|
||||
exitcode=$?
|
||||
trap '' 0
|
||||
@@ -359,16 +383,16 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
exit ;;
|
||||
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
|
||||
eval $set_cc_for_build
|
||||
SUN_ARCH="i386"
|
||||
SUN_ARCH=i386
|
||||
# If there is a compiler, see if it is configured for 64-bit objects.
|
||||
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
|
||||
# This test works for both compilers.
|
||||
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
|
||||
if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
|
||||
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_64BIT_ARCH >/dev/null
|
||||
then
|
||||
SUN_ARCH="x86_64"
|
||||
SUN_ARCH=x86_64
|
||||
fi
|
||||
fi
|
||||
echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
@@ -393,7 +417,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
exit ;;
|
||||
sun*:*:4.2BSD:*)
|
||||
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
|
||||
test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
|
||||
test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3
|
||||
case "`/bin/arch`" in
|
||||
sun3)
|
||||
echo m68k-sun-sunos${UNAME_RELEASE}
|
||||
@@ -579,8 +603,9 @@ EOF
|
||||
else
|
||||
IBM_ARCH=powerpc
|
||||
fi
|
||||
if [ -x /usr/bin/oslevel ] ; then
|
||||
IBM_REV=`/usr/bin/oslevel`
|
||||
if [ -x /usr/bin/lslpp ] ; then
|
||||
IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
|
||||
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
|
||||
else
|
||||
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
|
||||
fi
|
||||
@@ -617,13 +642,13 @@ EOF
|
||||
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
|
||||
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
|
||||
case "${sc_cpu_version}" in
|
||||
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
|
||||
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
|
||||
523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
|
||||
528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
|
||||
532) # CPU_PA_RISC2_0
|
||||
case "${sc_kernel_bits}" in
|
||||
32) HP_ARCH="hppa2.0n" ;;
|
||||
64) HP_ARCH="hppa2.0w" ;;
|
||||
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
|
||||
32) HP_ARCH=hppa2.0n ;;
|
||||
64) HP_ARCH=hppa2.0w ;;
|
||||
'') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
|
||||
esac ;;
|
||||
esac
|
||||
fi
|
||||
@@ -662,11 +687,11 @@ EOF
|
||||
exit (0);
|
||||
}
|
||||
EOF
|
||||
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
|
||||
(CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
|
||||
test -z "$HP_ARCH" && HP_ARCH=hppa
|
||||
fi ;;
|
||||
esac
|
||||
if [ ${HP_ARCH} = "hppa2.0w" ]
|
||||
if [ ${HP_ARCH} = hppa2.0w ]
|
||||
then
|
||||
eval $set_cc_for_build
|
||||
|
||||
@@ -679,12 +704,12 @@ EOF
|
||||
# $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
|
||||
# => hppa64-hp-hpux11.23
|
||||
|
||||
if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
|
||||
if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
|
||||
grep -q __LP64__
|
||||
then
|
||||
HP_ARCH="hppa2.0w"
|
||||
HP_ARCH=hppa2.0w
|
||||
else
|
||||
HP_ARCH="hppa64"
|
||||
HP_ARCH=hppa64
|
||||
fi
|
||||
fi
|
||||
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
|
||||
@@ -789,14 +814,14 @@ EOF
|
||||
echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
||||
exit ;;
|
||||
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
|
||||
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
||||
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
|
||||
FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
|
||||
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
|
||||
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||
exit ;;
|
||||
5000:UNIX_System_V:4.*:*)
|
||||
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
|
||||
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
|
||||
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||
exit ;;
|
||||
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
|
||||
@@ -826,7 +851,7 @@ EOF
|
||||
*:MINGW*:*)
|
||||
echo ${UNAME_MACHINE}-pc-mingw32
|
||||
exit ;;
|
||||
i*:MSYS*:*)
|
||||
*:MSYS*:*)
|
||||
echo ${UNAME_MACHINE}-pc-msys
|
||||
exit ;;
|
||||
i*:windows32*:*)
|
||||
@@ -878,7 +903,7 @@ EOF
|
||||
exit ;;
|
||||
*:GNU/*:*:*)
|
||||
# other systems with GNU libc and userland
|
||||
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
|
||||
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
|
||||
exit ;;
|
||||
i*86:Minix:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-minix
|
||||
@@ -901,7 +926,7 @@ EOF
|
||||
EV68*) UNAME_MACHINE=alphaev68 ;;
|
||||
esac
|
||||
objdump --private-headers /bin/sh | grep -q ld.so.1
|
||||
if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
|
||||
if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
arc:Linux:*:* | arceb:Linux:*:*)
|
||||
@@ -932,6 +957,9 @@ EOF
|
||||
crisv32:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
|
||||
exit ;;
|
||||
e2k:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
frv:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
@@ -944,6 +972,9 @@ EOF
|
||||
ia64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
k1om:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
m32r*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
@@ -969,10 +1000,13 @@ EOF
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
|
||||
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
|
||||
;;
|
||||
or1k:Linux:*:*)
|
||||
mips64el:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
or32:Linux:*:*)
|
||||
openrisc*:Linux:*:*)
|
||||
echo or1k-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
or32:Linux:*:* | or1k*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
padre:Linux:*:*)
|
||||
@@ -1001,6 +1035,9 @@ EOF
|
||||
ppcle:Linux:*:*)
|
||||
echo powerpcle-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
riscv32:Linux:*:* | riscv64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
s390:Linux:*:* | s390x:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
|
||||
exit ;;
|
||||
@@ -1020,7 +1057,7 @@ EOF
|
||||
echo ${UNAME_MACHINE}-dec-linux-${LIBC}
|
||||
exit ;;
|
||||
x86_64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
echo ${UNAME_MACHINE}-pc-linux-${LIBC}
|
||||
exit ;;
|
||||
xtensa*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
@@ -1099,7 +1136,7 @@ EOF
|
||||
# uname -m prints for DJGPP always 'pc', but it prints nothing about
|
||||
# the processor, so we play safe by assuming i586.
|
||||
# Note: whatever this is, it MUST be the same as what config.sub
|
||||
# prints for the "djgpp" host, or else GDB configury will decide that
|
||||
# prints for the "djgpp" host, or else GDB configure will decide that
|
||||
# this is a cross-build.
|
||||
echo i586-pc-msdosdjgpp
|
||||
exit ;;
|
||||
@@ -1248,6 +1285,9 @@ EOF
|
||||
SX-8R:SUPER-UX:*:*)
|
||||
echo sx8r-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
SX-ACE:SUPER-UX:*:*)
|
||||
echo sxace-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
Power*:Rhapsody:*:*)
|
||||
echo powerpc-apple-rhapsody${UNAME_RELEASE}
|
||||
exit ;;
|
||||
@@ -1260,22 +1300,32 @@ EOF
|
||||
if test "$UNAME_PROCESSOR" = unknown ; then
|
||||
UNAME_PROCESSOR=powerpc
|
||||
fi
|
||||
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
|
||||
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_64BIT_ARCH >/dev/null
|
||||
then
|
||||
case $UNAME_PROCESSOR in
|
||||
i386) UNAME_PROCESSOR=x86_64 ;;
|
||||
powerpc) UNAME_PROCESSOR=powerpc64 ;;
|
||||
esac
|
||||
if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
|
||||
if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
|
||||
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_64BIT_ARCH >/dev/null
|
||||
then
|
||||
case $UNAME_PROCESSOR in
|
||||
i386) UNAME_PROCESSOR=x86_64 ;;
|
||||
powerpc) UNAME_PROCESSOR=powerpc64 ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
elif test "$UNAME_PROCESSOR" = i386 ; then
|
||||
# Avoid executing cc on OS X 10.9, as it ships with a stub
|
||||
# that puts up a graphical alert prompting to install
|
||||
# developer tools. Any system running Mac OS X 10.7 or
|
||||
# later (Darwin 11 and later) is required to have a 64-bit
|
||||
# processor. This is not true of the ARM version of Darwin
|
||||
# that Apple uses in portable devices.
|
||||
UNAME_PROCESSOR=x86_64
|
||||
fi
|
||||
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:procnto*:*:* | *:QNX:[0123456789]*:*)
|
||||
UNAME_PROCESSOR=`uname -p`
|
||||
if test "$UNAME_PROCESSOR" = "x86"; then
|
||||
if test "$UNAME_PROCESSOR" = x86; then
|
||||
UNAME_PROCESSOR=i386
|
||||
UNAME_MACHINE=pc
|
||||
fi
|
||||
@@ -1306,7 +1356,7 @@ EOF
|
||||
# "uname -m" is not consistent, so use $cputype instead. 386
|
||||
# is converted to i386 for consistency with other x86
|
||||
# operating systems.
|
||||
if test "$cputype" = "386"; then
|
||||
if test "$cputype" = 386; then
|
||||
UNAME_MACHINE=i386
|
||||
else
|
||||
UNAME_MACHINE="$cputype"
|
||||
@@ -1348,7 +1398,7 @@ EOF
|
||||
echo i386-pc-xenix
|
||||
exit ;;
|
||||
i*86:skyos:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
|
||||
echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'`
|
||||
exit ;;
|
||||
i*86:rdos:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-rdos
|
||||
@@ -1359,171 +1409,25 @@ EOF
|
||||
x86_64:VMkernel:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-esx
|
||||
exit ;;
|
||||
amd64:Isilon\ OneFS:*:*)
|
||||
echo x86_64-unknown-onefs
|
||||
exit ;;
|
||||
esac
|
||||
|
||||
eval $set_cc_for_build
|
||||
cat >$dummy.c <<EOF
|
||||
#ifdef _SEQUENT_
|
||||
# include <sys/types.h>
|
||||
# include <sys/utsname.h>
|
||||
#endif
|
||||
main ()
|
||||
{
|
||||
#if defined (sony)
|
||||
#if defined (MIPSEB)
|
||||
/* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
|
||||
I don't know.... */
|
||||
printf ("mips-sony-bsd\n"); exit (0);
|
||||
#else
|
||||
#include <sys/param.h>
|
||||
printf ("m68k-sony-newsos%s\n",
|
||||
#ifdef NEWSOS4
|
||||
"4"
|
||||
#else
|
||||
""
|
||||
#endif
|
||||
); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (__arm) && defined (__acorn) && defined (__unix)
|
||||
printf ("arm-acorn-riscix\n"); exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (hp300) && !defined (hpux)
|
||||
printf ("m68k-hp-bsd\n"); exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (NeXT)
|
||||
#if !defined (__ARCHITECTURE__)
|
||||
#define __ARCHITECTURE__ "m68k"
|
||||
#endif
|
||||
int version;
|
||||
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
|
||||
if (version < 4)
|
||||
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
|
||||
else
|
||||
printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
|
||||
exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (MULTIMAX) || defined (n16)
|
||||
#if defined (UMAXV)
|
||||
printf ("ns32k-encore-sysv\n"); exit (0);
|
||||
#else
|
||||
#if defined (CMU)
|
||||
printf ("ns32k-encore-mach\n"); exit (0);
|
||||
#else
|
||||
printf ("ns32k-encore-bsd\n"); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (__386BSD__)
|
||||
printf ("i386-pc-bsd\n"); exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (sequent)
|
||||
#if defined (i386)
|
||||
printf ("i386-sequent-dynix\n"); exit (0);
|
||||
#endif
|
||||
#if defined (ns32000)
|
||||
printf ("ns32k-sequent-dynix\n"); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (_SEQUENT_)
|
||||
struct utsname un;
|
||||
|
||||
uname(&un);
|
||||
|
||||
if (strncmp(un.version, "V2", 2) == 0) {
|
||||
printf ("i386-sequent-ptx2\n"); exit (0);
|
||||
}
|
||||
if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
|
||||
printf ("i386-sequent-ptx1\n"); exit (0);
|
||||
}
|
||||
printf ("i386-sequent-ptx\n"); exit (0);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (vax)
|
||||
# if !defined (ultrix)
|
||||
# include <sys/param.h>
|
||||
# if defined (BSD)
|
||||
# if BSD == 43
|
||||
printf ("vax-dec-bsd4.3\n"); exit (0);
|
||||
# else
|
||||
# if BSD == 199006
|
||||
printf ("vax-dec-bsd4.3reno\n"); exit (0);
|
||||
# else
|
||||
printf ("vax-dec-bsd\n"); exit (0);
|
||||
# endif
|
||||
# endif
|
||||
# else
|
||||
printf ("vax-dec-bsd\n"); exit (0);
|
||||
# endif
|
||||
# else
|
||||
printf ("vax-dec-ultrix\n"); exit (0);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (alliant) && defined (i860)
|
||||
printf ("i860-alliant-bsd\n"); exit (0);
|
||||
#endif
|
||||
|
||||
exit (1);
|
||||
}
|
||||
EOF
|
||||
|
||||
$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
|
||||
{ echo "$SYSTEM_NAME"; exit; }
|
||||
|
||||
# Apollos put the system type in the environment.
|
||||
|
||||
test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
|
||||
|
||||
# Convex versions that predate uname can use getsysinfo(1)
|
||||
|
||||
if [ -x /usr/convex/getsysinfo ]
|
||||
then
|
||||
case `getsysinfo -f cpu_type` in
|
||||
c1*)
|
||||
echo c1-convex-bsd
|
||||
exit ;;
|
||||
c2*)
|
||||
if getsysinfo -f scalar_acc
|
||||
then echo c32-convex-bsd
|
||||
else echo c2-convex-bsd
|
||||
fi
|
||||
exit ;;
|
||||
c34*)
|
||||
echo c34-convex-bsd
|
||||
exit ;;
|
||||
c38*)
|
||||
echo c38-convex-bsd
|
||||
exit ;;
|
||||
c4*)
|
||||
echo c4-convex-bsd
|
||||
exit ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
cat >&2 <<EOF
|
||||
$0: unable to guess system type
|
||||
|
||||
This script, last modified $timestamp, has failed to recognize
|
||||
the operating system you are using. It is advised that you
|
||||
download the most up to date version of the config scripts from
|
||||
This script (version $timestamp), has failed to recognize the
|
||||
operating system you are using. If your script is old, overwrite
|
||||
config.guess and config.sub with the latest versions from:
|
||||
|
||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
|
||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
|
||||
and
|
||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
|
||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
|
||||
|
||||
If the version you run ($0) is already up to date, please
|
||||
send the following data and any information you think might be
|
||||
pertinent to <config-patches@gnu.org> in order to provide the needed
|
||||
information to handle your system.
|
||||
If $0 has already been updated, send the following data and any
|
||||
information you think might be pertinent to config-patches@gnu.org to
|
||||
provide the necessary information to handle your system.
|
||||
|
||||
config.guess timestamp = $timestamp
|
||||
|
||||
|
||||
+168
-5
@@ -1,11 +1,23 @@
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* apply the noreturn attribute to a function that exits the program */
|
||||
#undef ATTR_NORETURN
|
||||
|
||||
/* apply the weak attribute to a symbol */
|
||||
#undef ATTR_WEAK
|
||||
|
||||
/* Directory to chroot to */
|
||||
#undef CHROOT_DIR
|
||||
|
||||
/* Define this to enable client subnet option. */
|
||||
#undef CLIENT_SUBNET
|
||||
|
||||
/* Do sha512 definitions in config.h */
|
||||
#undef COMPAT_SHA512
|
||||
|
||||
/* Command line arguments used with configure */
|
||||
#undef CONFCMDLINE
|
||||
|
||||
/* Pathname to the Unbound configuration file */
|
||||
#undef CONFIGFILE
|
||||
|
||||
@@ -27,6 +39,9 @@
|
||||
internal symbols */
|
||||
#undef EXPORT_ALL_SYMBOLS
|
||||
|
||||
/* Define to 1 if you have the `accept4' function. */
|
||||
#undef HAVE_ACCEPT4
|
||||
|
||||
/* Define to 1 if you have the `arc4random' function. */
|
||||
#undef HAVE_ARC4RANDOM
|
||||
|
||||
@@ -39,6 +54,9 @@
|
||||
/* Whether the C compiler accepts the "format" attribute */
|
||||
#undef HAVE_ATTR_FORMAT
|
||||
|
||||
/* Whether the C compiler accepts the "noreturn" attribute */
|
||||
#undef HAVE_ATTR_NORETURN
|
||||
|
||||
/* Whether the C compiler accepts the "unused" attribute */
|
||||
#undef HAVE_ATTR_UNUSED
|
||||
|
||||
@@ -54,6 +72,9 @@
|
||||
/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
|
||||
#undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
|
||||
|
||||
/* Define to 1 if you have the `CRYPTO_THREADID_set_callback' function. */
|
||||
#undef HAVE_CRYPTO_THREADID_SET_CALLBACK
|
||||
|
||||
/* Define to 1 if you have the `ctime_r' function. */
|
||||
#undef HAVE_CTIME_R
|
||||
|
||||
@@ -68,6 +89,26 @@
|
||||
if you don't. */
|
||||
#undef HAVE_DECL_ARC4RANDOM_UNIFORM
|
||||
|
||||
/* Define to 1 if you have the declaration of `evsignal_assign', and to 0 if
|
||||
you don't. */
|
||||
#undef HAVE_DECL_EVSIGNAL_ASSIGN
|
||||
|
||||
/* Define to 1 if you have the declaration of `inet_ntop', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_INET_NTOP
|
||||
|
||||
/* Define to 1 if you have the declaration of `inet_pton', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_INET_PTON
|
||||
|
||||
/* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_NID_ED25519
|
||||
|
||||
/* Define to 1 if you have the declaration of `NID_ED448', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_NID_ED448
|
||||
|
||||
/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_NID_SECP384R1
|
||||
@@ -80,6 +121,10 @@
|
||||
don't. */
|
||||
#undef HAVE_DECL_REALLOCARRAY
|
||||
|
||||
/* Define to 1 if you have the declaration of `redisConnect', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_REDISCONNECT
|
||||
|
||||
/* Define to 1 if you have the declaration of `sk_SSL_COMP_pop_free', and to 0
|
||||
if you don't. */
|
||||
#undef HAVE_DECL_SK_SSL_COMP_POP_FREE
|
||||
@@ -128,6 +173,9 @@
|
||||
/* Define to 1 if you have the `ERR_load_crypto_strings' function. */
|
||||
#undef HAVE_ERR_LOAD_CRYPTO_STRINGS
|
||||
|
||||
/* Define to 1 if you have the `event_assign' function. */
|
||||
#undef HAVE_EVENT_ASSIGN
|
||||
|
||||
/* Define to 1 if you have the `event_base_free' function. */
|
||||
#undef HAVE_EVENT_BASE_FREE
|
||||
|
||||
@@ -143,12 +191,21 @@
|
||||
/* Define to 1 if you have the <event.h> header file. */
|
||||
#undef HAVE_EVENT_H
|
||||
|
||||
/* Define to 1 if you have the `EVP_aes_256_cbc' function. */
|
||||
#undef HAVE_EVP_AES_256_CBC
|
||||
|
||||
/* Define to 1 if you have the `EVP_cleanup' function. */
|
||||
#undef HAVE_EVP_CLEANUP
|
||||
|
||||
/* Define to 1 if you have the `EVP_DigestVerify' function. */
|
||||
#undef HAVE_EVP_DIGESTVERIFY
|
||||
|
||||
/* Define to 1 if you have the `EVP_dss1' function. */
|
||||
#undef HAVE_EVP_DSS1
|
||||
|
||||
/* Define to 1 if you have the `EVP_EncryptInit_ex' function. */
|
||||
#undef HAVE_EVP_ENCRYPTINIT_EX
|
||||
|
||||
/* Define to 1 if you have the `EVP_MD_CTX_new' function. */
|
||||
#undef HAVE_EVP_MD_CTX_NEW
|
||||
|
||||
@@ -170,6 +227,9 @@
|
||||
/* Define to 1 if you have the <expat.h> header file. */
|
||||
#undef HAVE_EXPAT_H
|
||||
|
||||
/* Define to 1 if you have the `explicit_bzero' function. */
|
||||
#undef HAVE_EXPLICIT_BZERO
|
||||
|
||||
/* Define to 1 if you have the `fcntl' function. */
|
||||
#undef HAVE_FCNTL
|
||||
|
||||
@@ -215,6 +275,12 @@
|
||||
/* Define to 1 if you have the <grp.h> header file. */
|
||||
#undef HAVE_GRP_H
|
||||
|
||||
/* Define to 1 if you have the <hiredis/hiredis.h> header file. */
|
||||
#undef HAVE_HIREDIS_HIREDIS_H
|
||||
|
||||
/* Define to 1 if you have the `HMAC_Init_ex' function. */
|
||||
#undef HAVE_HMAC_INIT_EX
|
||||
|
||||
/* If you have HMAC_Update */
|
||||
#undef HAVE_HMAC_UPDATE
|
||||
|
||||
@@ -245,6 +311,9 @@
|
||||
/* Define to 1 if you have the `kill' function. */
|
||||
#undef HAVE_KILL
|
||||
|
||||
/* Define to 1 if you have the <libkern/OSByteOrder.h> header file. */
|
||||
#undef HAVE_LIBKERN_OSBYTEORDER_H
|
||||
|
||||
/* Define if we have LibreSSL */
|
||||
#undef HAVE_LIBRESSL
|
||||
|
||||
@@ -278,6 +347,9 @@
|
||||
/* Define to 1 if you have the <nettle/dsa-compat.h> header file. */
|
||||
#undef HAVE_NETTLE_DSA_COMPAT_H
|
||||
|
||||
/* Define to 1 if you have the <nettle/eddsa.h> header file. */
|
||||
#undef HAVE_NETTLE_EDDSA_H
|
||||
|
||||
/* Use libnss for crypto */
|
||||
#undef HAVE_NSS
|
||||
|
||||
@@ -344,7 +416,7 @@
|
||||
/* Define to 1 if you have the `RAND_cleanup' function. */
|
||||
#undef HAVE_RAND_CLEANUP
|
||||
|
||||
/* Define to 1 if you have the `reallocarray' function. */
|
||||
/* If we have reallocarray(3) */
|
||||
#undef HAVE_REALLOCARRAY
|
||||
|
||||
/* Define to 1 if you have the `recvmsg' function. */
|
||||
@@ -377,6 +449,9 @@
|
||||
/* Define to 1 if you have the `SHA512_Update' function. */
|
||||
#undef HAVE_SHA512_UPDATE
|
||||
|
||||
/* Define to 1 if you have the `shmget' function. */
|
||||
#undef HAVE_SHMGET
|
||||
|
||||
/* Define to 1 if you have the `sigprocmask' function. */
|
||||
#undef HAVE_SIGPROCMASK
|
||||
|
||||
@@ -398,9 +473,21 @@
|
||||
/* Define if you have the SSL libraries installed. */
|
||||
#undef HAVE_SSL
|
||||
|
||||
/* Define to 1 if you have the `SSL_CTX_set_ciphersuites' function. */
|
||||
#undef HAVE_SSL_CTX_SET_CIPHERSUITES
|
||||
|
||||
/* Define to 1 if you have the `SSL_CTX_set_security_level' function. */
|
||||
#undef HAVE_SSL_CTX_SET_SECURITY_LEVEL
|
||||
|
||||
/* Define to 1 if you have the `SSL_CTX_set_tlsext_ticket_key_cb' function. */
|
||||
#undef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_CB
|
||||
|
||||
/* Define to 1 if you have the `SSL_get0_peername' function. */
|
||||
#undef HAVE_SSL_GET0_PEERNAME
|
||||
|
||||
/* Define to 1 if you have the `SSL_set1_host' function. */
|
||||
#undef HAVE_SSL_SET1_HOST
|
||||
|
||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||
#undef HAVE_STDARG_H
|
||||
|
||||
@@ -446,6 +533,15 @@
|
||||
/* Define to 1 if you have the <syslog.h> header file. */
|
||||
#undef HAVE_SYSLOG_H
|
||||
|
||||
/* Define to 1 if systemd should be used */
|
||||
#undef HAVE_SYSTEMD
|
||||
|
||||
/* Define to 1 if you have the <sys/endian.h> header file. */
|
||||
#undef HAVE_SYS_ENDIAN_H
|
||||
|
||||
/* Define to 1 if you have the <sys/ipc.h> header file. */
|
||||
#undef HAVE_SYS_IPC_H
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#undef HAVE_SYS_PARAM_H
|
||||
|
||||
@@ -455,6 +551,9 @@
|
||||
/* Define to 1 if you have the <sys/sha2.h> header file. */
|
||||
#undef HAVE_SYS_SHA2_H
|
||||
|
||||
/* Define to 1 if you have the <sys/shm.h> header file. */
|
||||
#undef HAVE_SYS_SHM_H
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#undef HAVE_SYS_SOCKET_H
|
||||
|
||||
@@ -515,9 +614,15 @@
|
||||
/* Define to 1 if you have the <ws2tcpip.h> header file. */
|
||||
#undef HAVE_WS2TCPIP_H
|
||||
|
||||
/* Define to 1 if you have the `X509_VERIFY_PARAM_set1_host' function. */
|
||||
#undef HAVE_X509_VERIFY_PARAM_SET1_HOST
|
||||
|
||||
/* Define to 1 if you have the `_beginthreadex' function. */
|
||||
#undef HAVE__BEGINTHREADEX
|
||||
|
||||
/* If HMAC_Init_ex() returns void */
|
||||
#undef HMAC_INIT_EX_RETURNS_VOID
|
||||
|
||||
/* if lex has yylex_destroy */
|
||||
#undef LEX_HAS_YYLEX_DESTROY
|
||||
|
||||
@@ -592,6 +697,9 @@
|
||||
/* Define as the return type of signal handlers (`int' or `void'). */
|
||||
#undef RETSIGTYPE
|
||||
|
||||
/* if REUSEPORT is enabled by default */
|
||||
#undef REUSEPORT_DEFAULT
|
||||
|
||||
/* default rootkey location */
|
||||
#undef ROOT_ANCHOR_FILE
|
||||
|
||||
@@ -607,12 +715,18 @@
|
||||
/* Shared data */
|
||||
#undef SHARE_DIR
|
||||
|
||||
/* The size of `size_t', as computed by sizeof. */
|
||||
#undef SIZEOF_SIZE_T
|
||||
|
||||
/* The size of `time_t', as computed by sizeof. */
|
||||
#undef SIZEOF_TIME_T
|
||||
|
||||
/* define if (v)snprintf does not return length needed, (but length used) */
|
||||
#undef SNPRINTF_RET_BROKEN
|
||||
|
||||
/* Define to 1 if libsodium supports sodium_set_misuse_handler */
|
||||
#undef SODIUM_MISUSE_HANDLER
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
@@ -622,6 +736,9 @@
|
||||
/* Use win32 resources and API */
|
||||
#undef UB_ON_WINDOWS
|
||||
|
||||
/* the SYSLOG_FACILITY to use, default LOG_DAEMON */
|
||||
#undef UB_SYSLOG_FACILITY
|
||||
|
||||
/* default username */
|
||||
#undef UB_USERNAME
|
||||
|
||||
@@ -640,6 +757,12 @@
|
||||
/* Define to 1 to use cachedb support */
|
||||
#undef USE_CACHEDB
|
||||
|
||||
/* Define to 1 to enable dnscrypt support */
|
||||
#undef USE_DNSCRYPT
|
||||
|
||||
/* Define to 1 to enable dnscrypt with xchacha20 support */
|
||||
#undef USE_DNSCRYPT_XCHACHA20
|
||||
|
||||
/* Define to 1 to enable dnstap support */
|
||||
#undef USE_DNSTAP
|
||||
|
||||
@@ -652,9 +775,21 @@
|
||||
/* Define this to enable an EVP workaround for older openssl */
|
||||
#undef USE_ECDSA_EVP_WORKAROUND
|
||||
|
||||
/* Define this to enable ED25519 support. */
|
||||
#undef USE_ED25519
|
||||
|
||||
/* Define this to enable ED448 support. */
|
||||
#undef USE_ED448
|
||||
|
||||
/* Define this to enable GOST support. */
|
||||
#undef USE_GOST
|
||||
|
||||
/* Define to 1 to use ipsecmod support. */
|
||||
#undef USE_IPSECMOD
|
||||
|
||||
/* Define to 1 to use ipset support */
|
||||
#undef USE_IPSET
|
||||
|
||||
/* Define if you want to use internal select based events */
|
||||
#undef USE_MINI_EVENT
|
||||
|
||||
@@ -664,6 +799,12 @@
|
||||
/* Define this to enable client TCP Fast Open. */
|
||||
#undef USE_OSX_MSG_FASTOPEN
|
||||
|
||||
/* Define this to use hiredis client. */
|
||||
#undef USE_REDIS
|
||||
|
||||
/* Define this to enable SHA1 support. */
|
||||
#undef USE_SHA1
|
||||
|
||||
/* Define this to enable SHA256 and SHA512 support. */
|
||||
#undef USE_SHA2
|
||||
|
||||
@@ -846,8 +987,14 @@
|
||||
|
||||
|
||||
|
||||
#ifndef _OPENBSD_SOURCE
|
||||
#define _OPENBSD_SOURCE 1
|
||||
#endif
|
||||
|
||||
#ifndef UNBOUND_DEBUG
|
||||
# ifndef NDEBUG
|
||||
# define NDEBUG
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/** Use small-ldns codebase */
|
||||
@@ -1061,12 +1208,29 @@ char *strsep(char **stringp, const char *delim);
|
||||
int isblank(int c);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_EXPLICIT_BZERO
|
||||
#define explicit_bzero unbound_explicit_bzero
|
||||
void explicit_bzero(void* buf, size_t len);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INET_NTOP) && !HAVE_DECL_INET_NTOP
|
||||
const char *inet_ntop(int af, const void *src, char *dst, size_t size);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INET_PTON) && !HAVE_DECL_INET_PTON
|
||||
int inet_pton(int af, const char* src, void* dst);
|
||||
#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 !HAVE_DECL_REALLOCARRAY
|
||||
void *reallocarray(void *ptr, size_t nmemb, size_t size);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBRESSL
|
||||
# if !HAVE_DECL_STRLCPY
|
||||
size_t strlcpy(char *dst, const char *src, size_t siz);
|
||||
@@ -1080,17 +1244,14 @@ uint32_t arc4random(void);
|
||||
# if !HAVE_DECL_ARC4RANDOM_UNIFORM && defined(HAVE_ARC4RANDOM_UNIFORM)
|
||||
uint32_t arc4random_uniform(uint32_t upper_bound);
|
||||
# endif
|
||||
# if !HAVE_DECL_REALLOCARRAY
|
||||
void *reallocarray(void *ptr, size_t nmemb, size_t size);
|
||||
# endif
|
||||
#endif /* HAVE_LIBRESSL */
|
||||
#ifndef HAVE_ARC4RANDOM
|
||||
void explicit_bzero(void* buf, size_t len);
|
||||
int getentropy(void* buf, size_t len);
|
||||
uint32_t arc4random(void);
|
||||
void arc4random_buf(void* buf, size_t n);
|
||||
void _ARC4_LOCK(void);
|
||||
void _ARC4_UNLOCK(void);
|
||||
void _ARC4_LOCK_DESTROY(void);
|
||||
#endif
|
||||
#ifndef HAVE_ARC4RANDOM_UNIFORM
|
||||
uint32_t arc4random_uniform(uint32_t upper_bound);
|
||||
@@ -1156,6 +1317,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
||||
|
||||
/** default port for DNS traffic. */
|
||||
#define UNBOUND_DNS_PORT 53
|
||||
/** default port for DNS over TLS traffic. */
|
||||
#define UNBOUND_DNS_OVER_TLS_PORT 853
|
||||
/** default port for unbound control traffic, registered port with IANA,
|
||||
ub-dns-control 8953/tcp unbound dns nameserver control */
|
||||
#define UNBOUND_CONTROL_PORT 8953
|
||||
|
||||
Vendored
+61
-29
@@ -1,8 +1,8 @@
|
||||
#! /bin/sh
|
||||
#!/usr/bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright 1992-2013 Free Software Foundation, Inc.
|
||||
# Copyright 1992-2016 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2013-08-10'
|
||||
timestamp='2016-09-05'
|
||||
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
@@ -25,7 +25,7 @@ timestamp='2013-08-10'
|
||||
# of the GNU General Public License, version 3 ("GPLv3").
|
||||
|
||||
|
||||
# Please send patches with a ChangeLog entry to config-patches@gnu.org.
|
||||
# Please send patches to <config-patches@gnu.org>.
|
||||
#
|
||||
# Configuration subroutine to validate and canonicalize a configuration type.
|
||||
# Supply the specified configuration type as an argument.
|
||||
@@ -33,7 +33,7 @@ timestamp='2013-08-10'
|
||||
# Otherwise, we print the canonical config type on stdout and succeed.
|
||||
|
||||
# You can get the latest version of this script from:
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
|
||||
|
||||
# This file is supposed to be the same for all GNU packages
|
||||
# and recognize all the CPU types, system types and aliases
|
||||
@@ -53,8 +53,7 @@ timestamp='2013-08-10'
|
||||
me=`echo "$0" | sed -e 's,.*/,,'`
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION] CPU-MFR-OPSYS
|
||||
$0 [OPTION] ALIAS
|
||||
Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
|
||||
|
||||
Canonicalize a configuration name.
|
||||
|
||||
@@ -68,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>."
|
||||
version="\
|
||||
GNU config.sub ($timestamp)
|
||||
|
||||
Copyright 1992-2013 Free Software Foundation, Inc.
|
||||
Copyright 1992-2016 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@@ -117,8 +116,8 @@ maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
|
||||
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
|
||||
knetbsd*-gnu* | netbsd*-gnu* | \
|
||||
kopensolaris*-gnu* | \
|
||||
knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
|
||||
kopensolaris*-gnu* | cloudabi*-eabi* | \
|
||||
storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
os=-$maybe_os
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
@@ -255,16 +254,18 @@ case $basic_machine in
|
||||
| arc | arceb \
|
||||
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
|
||||
| avr | avr32 \
|
||||
| ba \
|
||||
| be32 | be64 \
|
||||
| bfin \
|
||||
| c4x | c8051 | clipper \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
| epiphany \
|
||||
| fido | fr30 | frv \
|
||||
| e2k | epiphany \
|
||||
| fido | fr30 | frv | ft32 \
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| hexagon \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k | iq2000 \
|
||||
| k1om \
|
||||
| le32 | le64 \
|
||||
| lm32 \
|
||||
| m32c | m32r | m32rle | m68000 | m68k | m88k \
|
||||
@@ -282,8 +283,10 @@ case $basic_machine in
|
||||
| mips64vr5900 | mips64vr5900el \
|
||||
| mipsisa32 | mipsisa32el \
|
||||
| mipsisa32r2 | mipsisa32r2el \
|
||||
| mipsisa32r6 | mipsisa32r6el \
|
||||
| mipsisa64 | mipsisa64el \
|
||||
| mipsisa64r2 | mipsisa64r2el \
|
||||
| mipsisa64r6 | mipsisa64r6el \
|
||||
| mipsisa64sb1 | mipsisa64sb1el \
|
||||
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||
| mipsr5900 | mipsr5900el \
|
||||
@@ -295,14 +298,14 @@ case $basic_machine in
|
||||
| nds32 | nds32le | nds32be \
|
||||
| nios | nios2 | nios2eb | nios2el \
|
||||
| ns16k | ns32k \
|
||||
| open8 \
|
||||
| or1k | or32 \
|
||||
| open8 | or1k | or1knd | or32 \
|
||||
| pdp10 | pdp11 | pj | pjl \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle \
|
||||
| pyramid \
|
||||
| riscv32 | riscv64 \
|
||||
| rl78 | rx \
|
||||
| score \
|
||||
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh64 | sh64le \
|
||||
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
|
||||
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
|
||||
@@ -310,6 +313,7 @@ case $basic_machine in
|
||||
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
|
||||
| ubicom32 \
|
||||
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
|
||||
| visium \
|
||||
| we32k \
|
||||
| x86 | xc16x | xstormy16 | xtensa \
|
||||
| z8k | z80)
|
||||
@@ -324,7 +328,10 @@ case $basic_machine in
|
||||
c6x)
|
||||
basic_machine=tic6x-unknown
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
|
||||
leon|leon[3-9])
|
||||
basic_machine=sparc-$basic_machine
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-none
|
||||
;;
|
||||
@@ -369,18 +376,20 @@ case $basic_machine in
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
|
||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||
| avr-* | avr32-* \
|
||||
| ba-* \
|
||||
| be32-* | be64-* \
|
||||
| bfin-* | bs2000-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* \
|
||||
| c8051-* | clipper-* | craynv-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
| e2k-* | elxsi-* \
|
||||
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
||||
| h8300-* | h8500-* \
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| hexagon-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
| ip2k-* | iq2000-* \
|
||||
| k1om-* \
|
||||
| le32-* | le64-* \
|
||||
| lm32-* \
|
||||
| m32c-* | m32r-* | m32rle-* \
|
||||
@@ -400,8 +409,10 @@ case $basic_machine in
|
||||
| mips64vr5900-* | mips64vr5900el-* \
|
||||
| mipsisa32-* | mipsisa32el-* \
|
||||
| mipsisa32r2-* | mipsisa32r2el-* \
|
||||
| mipsisa32r6-* | mipsisa32r6el-* \
|
||||
| mipsisa64-* | mipsisa64el-* \
|
||||
| mipsisa64r2-* | mipsisa64r2el-* \
|
||||
| mipsisa64r6-* | mipsisa64r6el-* \
|
||||
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
||||
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
||||
| mipsr5900-* | mipsr5900el-* \
|
||||
@@ -413,16 +424,18 @@ case $basic_machine in
|
||||
| nios-* | nios2-* | nios2eb-* | nios2el-* \
|
||||
| none-* | np1-* | ns16k-* | ns32k-* \
|
||||
| open8-* \
|
||||
| or1k*-* \
|
||||
| orion-* \
|
||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
|
||||
| pyramid-* \
|
||||
| riscv32-* | riscv64-* \
|
||||
| rl78-* | romp-* | rs6000-* | rx-* \
|
||||
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
||||
| sparclite-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
|
||||
| tahoe-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||
| tile*-* \
|
||||
@@ -430,6 +443,7 @@ case $basic_machine in
|
||||
| ubicom32-* \
|
||||
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
|
||||
| vax-* \
|
||||
| visium-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* \
|
||||
| xstormy16-* | xtensa*-* \
|
||||
@@ -506,6 +520,9 @@ case $basic_machine in
|
||||
basic_machine=i386-pc
|
||||
os=-aros
|
||||
;;
|
||||
asmjs)
|
||||
basic_machine=asmjs-unknown
|
||||
;;
|
||||
aux)
|
||||
basic_machine=m68k-apple
|
||||
os=-aux
|
||||
@@ -626,6 +643,14 @@ case $basic_machine in
|
||||
basic_machine=m68k-bull
|
||||
os=-sysv3
|
||||
;;
|
||||
e500v[12])
|
||||
basic_machine=powerpc-unknown
|
||||
os=$os"spe"
|
||||
;;
|
||||
e500v[12]-*)
|
||||
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=$os"spe"
|
||||
;;
|
||||
ebmon29k)
|
||||
basic_machine=a29k-amd
|
||||
os=-ebmon
|
||||
@@ -767,6 +792,9 @@ case $basic_machine in
|
||||
basic_machine=m68k-isi
|
||||
os=-sysv
|
||||
;;
|
||||
leon-*|leon[3-9]-*)
|
||||
basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
|
||||
;;
|
||||
m68knommu)
|
||||
basic_machine=m68k-unknown
|
||||
os=-linux
|
||||
@@ -822,6 +850,10 @@ case $basic_machine in
|
||||
basic_machine=powerpc-unknown
|
||||
os=-morphos
|
||||
;;
|
||||
moxiebox)
|
||||
basic_machine=moxie-unknown
|
||||
os=-moxiebox
|
||||
;;
|
||||
msdos)
|
||||
basic_machine=i386-pc
|
||||
os=-msdos
|
||||
@@ -998,7 +1030,7 @@ case $basic_machine in
|
||||
ppc-* | ppcbe-*)
|
||||
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppcle | powerpclittle | ppc-le | powerpc-little)
|
||||
ppcle | powerpclittle)
|
||||
basic_machine=powerpcle-unknown
|
||||
;;
|
||||
ppcle-* | powerpclittle-*)
|
||||
@@ -1006,9 +1038,9 @@ case $basic_machine in
|
||||
;;
|
||||
ppc64) basic_machine=powerpc64-unknown
|
||||
;;
|
||||
ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
|
||||
ppc64le | powerpc64little)
|
||||
basic_machine=powerpc64le-unknown
|
||||
;;
|
||||
ppc64le-* | powerpc64little-*)
|
||||
@@ -1354,27 +1386,28 @@ case $os in
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
|
||||
| -sym* | -kopensolaris* | -plan9* \
|
||||
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
||||
| -aos* | -aros* \
|
||||
| -aos* | -aros* | -cloudabi* | -sortix* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
|
||||
| -bitrig* | -openbsd* | -solidbsd* \
|
||||
| -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
|
||||
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
|
||||
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -chorusos* | -chorusrdb* | -cegcc* \
|
||||
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
|
||||
| -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
|
||||
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
|
||||
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
|
||||
| -onefs* | -tirtos* | -phoenix*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
@@ -1506,6 +1539,8 @@ case $os in
|
||||
;;
|
||||
-nacl*)
|
||||
;;
|
||||
-ios)
|
||||
;;
|
||||
-none)
|
||||
;;
|
||||
*)
|
||||
@@ -1592,9 +1627,6 @@ case $basic_machine in
|
||||
mips*-*)
|
||||
os=-elf
|
||||
;;
|
||||
or1k-*)
|
||||
os=-elf
|
||||
;;
|
||||
or32-*)
|
||||
os=-coff
|
||||
;;
|
||||
|
||||
+516
-41
@@ -6,19 +6,20 @@ sinclude(ax_pthread.m4)
|
||||
sinclude(acx_python.m4)
|
||||
sinclude(ac_pkg_swig.m4)
|
||||
sinclude(dnstap/dnstap.m4)
|
||||
sinclude(dnscrypt/dnscrypt.m4)
|
||||
|
||||
# must be numbers. ac_defun because of later processing
|
||||
m4_define([VERSION_MAJOR],[1])
|
||||
m4_define([VERSION_MINOR],[6])
|
||||
m4_define([VERSION_MICRO],[0])
|
||||
AC_INIT(unbound, m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]), unbound-bugs@nlnetlabs.nl, unbound)
|
||||
m4_define([VERSION_MINOR],[9])
|
||||
m4_define([VERSION_MICRO],[6])
|
||||
AC_INIT(unbound, m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]), unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues, unbound)
|
||||
AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
|
||||
AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
|
||||
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
|
||||
|
||||
LIBUNBOUND_CURRENT=6
|
||||
LIBUNBOUND_REVISION=3
|
||||
LIBUNBOUND_AGE=4
|
||||
LIBUNBOUND_CURRENT=9
|
||||
LIBUNBOUND_REVISION=6
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
# 1.0.2 had 0:14:0
|
||||
@@ -68,6 +69,29 @@ LIBUNBOUND_AGE=4
|
||||
# 1.5.9 had 6:1:4
|
||||
# 1.5.10 had 6:2:4
|
||||
# 1.6.0 had 6:3:4
|
||||
# 1.6.1 had 7:0:5 # ub_callback_t typedef renamed to ub_callback_type
|
||||
# 1.6.2 had 7:1:5
|
||||
# 1.6.3 had 7:2:5
|
||||
# 1.6.4 had 7:3:5
|
||||
# 1.6.5 had 7:4:5
|
||||
# 1.6.6 had 7:5:5
|
||||
# 1.6.7 had 7:6:5
|
||||
# 1.6.8 had 7:7:5
|
||||
# 1.7.0 had 7:8:5
|
||||
# 1.7.1 had 7:9:5
|
||||
# 1.7.2 had 7:10:5
|
||||
# 1.7.3 had 7:11:5
|
||||
# 1.8.0 had 8:0:0 # changes the event callback function signature
|
||||
# 1.8.1 had 8:1:0
|
||||
# 1.8.2 had 8:2:0
|
||||
# 1.8.3 had 8:3:0
|
||||
# 1.9.0 had 9:0:1 # add ub_ctx_set_tls
|
||||
# 1.9.1 had 9:1:1
|
||||
# 1.9.2 had 9:2:1
|
||||
# 1.9.3 had 9:3:1
|
||||
# 1.9.4 had 9:4:1
|
||||
# 1.9.5 had 9:5:1
|
||||
# 1.9.6 had 9:6:1
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -83,7 +107,7 @@ LIBUNBOUND_AGE=4
|
||||
# Current and Age. Set Revision to 0, since this is the first
|
||||
# implementation of the new API.
|
||||
#
|
||||
# Otherwise, we're changing the binary API and breaking bakward
|
||||
# Otherwise, we're changing the binary API and breaking backward
|
||||
# compatibility with old binaries. Increment Current. Set Age to 0,
|
||||
# since we're backward compatible with no previous APIs. Set Revision
|
||||
# to 0 too.
|
||||
@@ -91,6 +115,10 @@ AC_SUBST(LIBUNBOUND_CURRENT)
|
||||
AC_SUBST(LIBUNBOUND_REVISION)
|
||||
AC_SUBST(LIBUNBOUND_AGE)
|
||||
|
||||
|
||||
cmdln="`echo $@ | sed -e 's/\\\\/\\\\\\\\/g' | sed -e 's/"/\\\\"/'g`"
|
||||
AC_DEFINE_UNQUOTED(CONFCMDLINE, ["$cmdln"], [Command line arguments used with configure])
|
||||
|
||||
CFLAGS="$CFLAGS"
|
||||
AC_AIX
|
||||
if test "$ac_cv_header_minix_config_h" = "yes"; then
|
||||
@@ -105,6 +133,11 @@ case "$prefix" in
|
||||
prefix="/usr/local"
|
||||
;;
|
||||
esac
|
||||
case "$exec_prefix" in
|
||||
NONE)
|
||||
exec_prefix="$prefix"
|
||||
;;
|
||||
esac
|
||||
|
||||
# are we on MinGW?
|
||||
if uname -s 2>&1 | grep MINGW32 >/dev/null; then on_mingw="yes"
|
||||
@@ -116,10 +149,16 @@ fi
|
||||
#
|
||||
# Determine configuration file
|
||||
# the eval is to evaluate shell expansion twice
|
||||
UNBOUND_SBIN_DIR=`eval echo "${sbindir}"`
|
||||
AC_SUBST(UNBOUND_SBIN_DIR)
|
||||
UNBOUND_SYSCONF_DIR=`eval echo "${sysconfdir}"`
|
||||
AC_SUBST(UNBOUND_SYSCONF_DIR)
|
||||
UNBOUND_LOCALSTATE_DIR=`eval echo "${localstatedir}"`
|
||||
AC_SUBST(UNBOUND_LOCALSTATE_DIR)
|
||||
if test $on_mingw = "no"; then
|
||||
ub_conf_file=`eval echo "${sysconfdir}/unbound/unbound.conf"`
|
||||
else
|
||||
ub_conf_file="C:\\Program Files (x86)\\Unbound\\service.conf"
|
||||
ub_conf_file="C:\\Program Files\\Unbound\\service.conf"
|
||||
fi
|
||||
AC_ARG_WITH([conf_file],
|
||||
AC_HELP_STRING([--with-conf-file=path],
|
||||
@@ -189,7 +228,7 @@ AC_ARG_WITH(rootkey-file,
|
||||
if test $on_mingw = no; then
|
||||
UNBOUND_ROOTKEY_FILE="$UNBOUND_RUN_DIR/root.key"
|
||||
else
|
||||
UNBOUND_ROOTKEY_FILE="C:\\Program Files (x86)\\Unbound\\root.key"
|
||||
UNBOUND_ROOTKEY_FILE="C:\\Program Files\\Unbound\\root.key"
|
||||
fi
|
||||
)
|
||||
AC_SUBST(UNBOUND_ROOTKEY_FILE)
|
||||
@@ -203,7 +242,7 @@ AC_ARG_WITH(rootcert-file,
|
||||
if test $on_mingw = no; then
|
||||
UNBOUND_ROOTCERT_FILE="$UNBOUND_RUN_DIR/icannbundle.pem"
|
||||
else
|
||||
UNBOUND_ROOTCERT_FILE="C:\\Program Files (x86)\\Unbound\\icannbundle.pem"
|
||||
UNBOUND_ROOTCERT_FILE="C:\\Program Files\\Unbound\\icannbundle.pem"
|
||||
fi
|
||||
)
|
||||
AC_SUBST(UNBOUND_ROOTCERT_FILE)
|
||||
@@ -226,9 +265,11 @@ AC_DEFINE_UNQUOTED(RSRC_PACKAGE_VERSION, [$wnvs], [version number for resource f
|
||||
AC_C_CONST
|
||||
AC_LANG_C
|
||||
# allow user to override the -g -O2 flags.
|
||||
default_cflags=no
|
||||
if test "x$CFLAGS" = "x" ; then
|
||||
ACX_CHECK_COMPILER_FLAG(g, [CFLAGS="$CFLAGS -g"])
|
||||
ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"])
|
||||
default_cflags=yes
|
||||
fi
|
||||
AC_PROG_CC
|
||||
ACX_DEPFLAG
|
||||
@@ -252,9 +293,14 @@ case "$debug_enabled" in
|
||||
# nothing to do.
|
||||
;;
|
||||
esac
|
||||
ACX_CHECK_FLTO
|
||||
ACX_CHECK_PIE
|
||||
ACX_CHECK_RELRO_NOW
|
||||
if test "$default_cflags" = "yes"; then
|
||||
# only when CFLAGS was "" at the start, if the users wants to
|
||||
# override we shouldn't add default cflags, because they wouldn't
|
||||
# be able to turn off these options and set the CFLAGS wanted.
|
||||
ACX_CHECK_FLTO
|
||||
ACX_CHECK_PIE
|
||||
ACX_CHECK_RELRO_NOW
|
||||
fi
|
||||
|
||||
AC_C_INLINE
|
||||
ACX_CHECK_FORMAT_ATTRIBUTE
|
||||
@@ -278,11 +324,36 @@ __attribute__((weak)) void f(int x) { printf("%d", x); }
|
||||
AC_MSG_RESULT($ac_cv_c_weak_attribute)
|
||||
if test $ac_cv_c_weak_attribute = yes; then
|
||||
AC_DEFINE(HAVE_ATTR_WEAK, 1, [Whether the C compiler accepts the "weak" attribute])
|
||||
AC_DEFINE(ATTR_WEAK, [__attribute__((weak))], [apply the weak attribute to a symbol])
|
||||
fi
|
||||
])dnl End of CHECK_WEAK_ATTRIBUTE
|
||||
|
||||
CHECK_WEAK_ATTRIBUTE
|
||||
|
||||
AC_DEFUN([CHECK_NORETURN_ATTRIBUTE],
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "noreturn" attribute)
|
||||
AC_CACHE_VAL(ac_cv_c_noreturn_attribute,
|
||||
[ac_cv_c_noreturn_attribute=no
|
||||
AC_TRY_COMPILE(
|
||||
[ #include <stdio.h>
|
||||
__attribute__((noreturn)) void f(int x) { printf("%d", x); }
|
||||
], [
|
||||
f(1);
|
||||
],
|
||||
[ac_cv_c_noreturn_attribute="yes"],
|
||||
[ac_cv_c_noreturn_attribute="no"])
|
||||
])
|
||||
|
||||
AC_MSG_RESULT($ac_cv_c_noreturn_attribute)
|
||||
if test $ac_cv_c_noreturn_attribute = yes; then
|
||||
AC_DEFINE(HAVE_ATTR_NORETURN, 1, [Whether the C compiler accepts the "noreturn" attribute])
|
||||
AC_DEFINE(ATTR_NORETURN, [__attribute__((__noreturn__))], [apply the noreturn attribute to a function that exits the program])
|
||||
fi
|
||||
])dnl End of CHECK_NORETURN_ATTRIBUTE
|
||||
|
||||
CHECK_NORETURN_ATTRIBUTE
|
||||
|
||||
if test "$srcdir" != "."; then
|
||||
CPPFLAGS="$CPPFLAGS -I$srcdir"
|
||||
fi
|
||||
@@ -292,18 +363,39 @@ AC_DEFUN([ACX_YYLEX_DESTROY], [
|
||||
if echo %% | $LEX -t 2>&1 | grep yylex_destroy >/dev/null 2>&1; then
|
||||
AC_DEFINE(LEX_HAS_YYLEX_DESTROY, 1, [if lex has yylex_destroy])
|
||||
AC_MSG_RESULT(yes)
|
||||
else AC_MSG_RESULT(no); fi
|
||||
else AC_MSG_RESULT(no);
|
||||
LEX=":"
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN([ACX_YYLEX_OPTION], [
|
||||
AC_MSG_CHECKING([for lex %option])
|
||||
if cat <<EOF | $LEX -t 2>&1 | grep yy_delete_buffer >/dev/null 2>&1; then
|
||||
%option nounput
|
||||
%%
|
||||
EOF
|
||||
AC_MSG_RESULT(yes)
|
||||
else AC_MSG_RESULT(no);
|
||||
LEX=":"
|
||||
fi
|
||||
])
|
||||
|
||||
AC_PROG_LEX
|
||||
if test "$LEX" != "" -a "$LEX" != ":"; then
|
||||
ACX_YYLEX_DESTROY
|
||||
fi
|
||||
if test "$LEX" != "" -a "$LEX" != ":"; then
|
||||
ACX_YYLEX_OPTION
|
||||
fi
|
||||
AC_PROG_YACC
|
||||
AC_CHECK_PROG(doxygen, doxygen, doxygen)
|
||||
AC_CHECK_TOOL(STRIP, strip)
|
||||
ACX_LIBTOOL_C_ONLY
|
||||
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
# Checks for header files.
|
||||
AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h],,, [AC_INCLUDES_DEFAULT])
|
||||
|
||||
# check for types.
|
||||
# Using own tests for int64* because autoconf builtin only give 32bit.
|
||||
@@ -340,6 +432,7 @@ AC_INCLUDES_DEFAULT
|
||||
# endif
|
||||
#endif
|
||||
])
|
||||
AC_CHECK_SIZEOF(size_t)
|
||||
|
||||
# add option to disable the evil rpath
|
||||
ACX_ARG_RPATH
|
||||
@@ -384,6 +477,17 @@ ACX_CHECK_NONBLOCKING_BROKEN
|
||||
ACX_MKDIR_ONE_ARG
|
||||
AC_CHECK_FUNCS([strptime],[AC_CHECK_STRPTIME_WORKS],[AC_LIBOBJ([strptime])])
|
||||
|
||||
# check if we can use SO_REUSEPORT
|
||||
if echo "$host" | $GREP -i -e linux -e dragonfly >/dev/null; then
|
||||
AC_DEFINE(REUSEPORT_DEFAULT, 1, [if REUSEPORT is enabled by default])
|
||||
else
|
||||
AC_DEFINE(REUSEPORT_DEFAULT, 0, [if REUSEPORT is enabled by default])
|
||||
fi
|
||||
|
||||
# Include systemd.m4 - begin
|
||||
sinclude(systemd.m4)
|
||||
# Include systemd.m4 - end
|
||||
|
||||
# set memory allocation checking if requested
|
||||
AC_ARG_ENABLE(alloc-checks, AC_HELP_STRING([--enable-alloc-checks],
|
||||
[ enable to memory allocation statistics, for debug purposes ]),
|
||||
@@ -399,6 +503,10 @@ if test x_$enable_alloc_nonregional = x_yes; then
|
||||
fi
|
||||
if test x_$enable_alloc_checks = x_yes; then
|
||||
AC_DEFINE(UNBOUND_ALLOC_STATS, 1, [use statistics for allocs and frees, for debug use])
|
||||
SLDNS_ALLOCCHECK_EXTRA_OBJ="alloc.lo log.lo"
|
||||
AC_SUBST(SLDNS_ALLOCCHECK_EXTRA_OBJ)
|
||||
ASYNCLOOK_ALLOCCHECK_EXTRA_OBJ="alloc.lo"
|
||||
AC_SUBST(ASYNCLOOK_ALLOCCHECK_EXTRA_OBJ)
|
||||
else
|
||||
if test x_$enable_alloc_lite = x_yes; then
|
||||
AC_DEFINE(UNBOUND_ALLOC_LITE, 1, [use to enable lightweight alloc assertions, for debug use])
|
||||
@@ -439,7 +547,9 @@ ub_have_pthreads=no
|
||||
if test x_$withval != x_no; then
|
||||
AX_PTHREAD([
|
||||
AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.])
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
if test -n "$PTHREAD_LIBS"; then
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
fi
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
CC="$PTHREAD_CC"
|
||||
ub_have_pthreads=yes
|
||||
@@ -500,6 +610,18 @@ fi
|
||||
|
||||
fi # end of non-mingw check of thread libraries
|
||||
|
||||
# Check for SYSLOG_FACILITY
|
||||
AC_ARG_WITH(syslog-facility, AC_HELP_STRING([--with-syslog-facility=LOCAL0 - LOCAL7], [ set SYSLOG_FACILITY, default DAEMON ]),
|
||||
[ UNBOUND_SYSLOG_FACILITY="$withval" ], [])
|
||||
case "${UNBOUND_SYSLOG_FACILITY}" in
|
||||
|
||||
LOCAL[[0-7]]) UNBOUND_SYSLOG_FACILITY="LOG_${UNBOUND_SYSLOG_FACILITY}" ;;
|
||||
|
||||
*) UNBOUND_SYSLOG_FACILITY="LOG_DAEMON" ;;
|
||||
|
||||
esac
|
||||
AC_DEFINE_UNQUOTED(UB_SYSLOG_FACILITY,${UNBOUND_SYSLOG_FACILITY},[the SYSLOG_FACILITY to use, default LOG_DAEMON])
|
||||
|
||||
# Check for PyUnbound
|
||||
AC_ARG_WITH(pyunbound,
|
||||
AC_HELP_STRING([--with-pyunbound],
|
||||
@@ -541,15 +663,30 @@ if test x_$ub_test_python != x_no; then
|
||||
AC_SUBST(PY_MAJOR_VERSION)
|
||||
# Have Python
|
||||
AC_DEFINE(HAVE_PYTHON,1,[Define if you have Python libraries and header files.])
|
||||
LIBS="$PYTHON_LDFLAGS $LIBS"
|
||||
CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS"
|
||||
if test -n "$LIBS"; then
|
||||
LIBS="$PYTHON_LDFLAGS $LIBS"
|
||||
else
|
||||
LIBS="$PYTHON_LDFLAGS"
|
||||
fi
|
||||
if test -n "$CPPFLAGS"; then
|
||||
CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS"
|
||||
else
|
||||
CPPFLAGS="$PYTHON_CPPFLAGS"
|
||||
fi
|
||||
ub_have_python=yes
|
||||
PC_PY_DEPENDENCY="python"
|
||||
PKG_CHECK_EXISTS(["python${PY_MAJOR_VERSION}"],
|
||||
[PC_PY_DEPENDENCY="python${PY_MAJOR_VERSION}"],
|
||||
[PC_PY_DEPENDENCY="python"])
|
||||
AC_SUBST(PC_PY_DEPENDENCY)
|
||||
|
||||
# Check for SWIG
|
||||
ub_have_swig=no
|
||||
AC_PROG_SWIG
|
||||
AC_ARG_ENABLE(swig-version-check, AC_HELP_STRING([--disable-swig-version-check], [Disable swig version check to build python modules with older swig even though that is unreliable]))
|
||||
if test "$enable_swig_version_check" = "yes"; then
|
||||
AC_PROG_SWIG(2.0.1)
|
||||
else
|
||||
AC_PROG_SWIG
|
||||
fi
|
||||
AC_MSG_CHECKING(SWIG)
|
||||
if test ! -x "$SWIG"; then
|
||||
AC_ERROR([failed to find swig tool, install it, or do not build Python module and PyUnbound])
|
||||
@@ -671,17 +808,17 @@ if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/
|
||||
AC_DEFINE([HAVE_LIBRESSL], [1], [Define if we have LibreSSL])
|
||||
# libressl provides these compat functions, but they may also be
|
||||
# declared by the OS in libc. See if they have been declared.
|
||||
AC_CHECK_DECLS([strlcpy,strlcat,arc4random,arc4random_uniform,reallocarray])
|
||||
AC_CHECK_DECLS([strlcpy,strlcat,arc4random,arc4random_uniform])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
AC_CHECK_HEADERS([openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify SSL_CTX_set_tlsext_ticket_key_cb EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback])
|
||||
|
||||
# these check_funcs need -lssl
|
||||
BAKLIBS="$LIBS"
|
||||
LIBS="-lssl $LIBS"
|
||||
AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level])
|
||||
AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites])
|
||||
LIBS="$BAKLIBS"
|
||||
|
||||
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
|
||||
@@ -704,10 +841,56 @@ AC_INCLUDES_DEFAULT
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/evp.h>
|
||||
])
|
||||
|
||||
if test "$ac_cv_func_HMAC_Init_ex" = "yes"; then
|
||||
# check function return type.
|
||||
AC_MSG_CHECKING(the return type of HMAC_Init_ex)
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
|
||||
#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 <openssl/ssl.h>
|
||||
#include <openssl/evp.h>
|
||||
], [
|
||||
HMAC_CTX* hmac_ctx = NULL;
|
||||
void* hmac_key = NULL;
|
||||
const EVP_MD* digest = NULL;
|
||||
int x = HMAC_Init_ex(hmac_ctx, hmac_key, 32, digest, NULL);
|
||||
(void)x;
|
||||
])], [
|
||||
AC_MSG_RESULT(int)
|
||||
], [
|
||||
AC_MSG_RESULT(void)
|
||||
AC_DEFINE([HMAC_INIT_EX_RETURNS_VOID], 1, [If HMAC_Init_ex() returns void])
|
||||
])
|
||||
fi
|
||||
|
||||
fi
|
||||
AC_SUBST(SSLLIB)
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sha1, AC_HELP_STRING([--disable-sha1], [Disable SHA1 RRSIG support, does not disable nsec3 support]))
|
||||
case "$enable_sha1" in
|
||||
no)
|
||||
;;
|
||||
yes|*)
|
||||
AC_DEFINE([USE_SHA1], [1], [Define this to enable SHA1 support.])
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sha2, AC_HELP_STRING([--disable-sha2], [Disable SHA256 and SHA512 RRSIG support]))
|
||||
case "$enable_sha2" in
|
||||
no)
|
||||
@@ -717,6 +900,19 @@ case "$enable_sha2" in
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(subnet, AC_HELP_STRING([--enable-subnet], [Enable client subnet]))
|
||||
case "$enable_subnet" in
|
||||
yes)
|
||||
AC_DEFINE([CLIENT_SUBNET], [1], [Define this to enable client subnet option.])
|
||||
SUBNET_OBJ="edns-subnet.lo subnetmod.lo addrtree.lo subnet-whitelist.lo"
|
||||
AC_SUBST(SUBNET_OBJ)
|
||||
SUBNET_HEADER='$(srcdir)/edns-subnet/subnetmod.h $(srcdir)/edns-subnet/edns-subnet.h $(srcdir)/edns-subnet/subnet-whitelist.h $(srcdir)/edns-subnet/addrtree.h'
|
||||
AC_SUBST(SUBNET_HEADER)
|
||||
;;
|
||||
no|*)
|
||||
;;
|
||||
esac
|
||||
|
||||
# check wether gost also works
|
||||
AC_DEFUN([AC_CHECK_GOST_WORKS],
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
@@ -872,13 +1068,79 @@ case "$enable_dsa" in
|
||||
;;
|
||||
*)
|
||||
# detect if DSA is supported, and turn it off if not.
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
AC_CHECK_FUNC(DSA_SIG_new, [
|
||||
AC_CHECK_TYPE(DSA_SIG*, [
|
||||
AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.])
|
||||
], [if test "x$enable_dsa" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support DSA and you used --enable-dsa.])
|
||||
fi ], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_RAND_H
|
||||
#include <openssl/rand.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_CONF_H
|
||||
#include <openssl/conf.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_ENGINE_H
|
||||
#include <openssl/engine.h>
|
||||
#endif
|
||||
])
|
||||
], [if test "x$enable_dsa" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support DSA and you used --enable-dsa.])
|
||||
fi ])
|
||||
else
|
||||
AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(ed25519, AC_HELP_STRING([--disable-ed25519], [Disable ED25519 support]))
|
||||
use_ed25519="no"
|
||||
case "$enable_ed25519" in
|
||||
no)
|
||||
;;
|
||||
*)
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
AC_CHECK_DECLS([NID_ED25519], [
|
||||
use_ed25519="yes"
|
||||
], [ if test "x$enable_ed25519" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support ED25519 and you used --enable-ed25519.])
|
||||
fi ], [AC_INCLUDES_DEFAULT
|
||||
#include <openssl/evp.h>
|
||||
])
|
||||
fi
|
||||
if test $USE_NETTLE = "yes"; then
|
||||
AC_CHECK_HEADERS([nettle/eddsa.h], use_ed25519="yes",, [AC_INCLUDES_DEFAULT])
|
||||
fi
|
||||
if test $use_ed25519 = "yes"; then
|
||||
AC_DEFINE_UNQUOTED([USE_ED25519], [1], [Define this to enable ED25519 support.])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(ed448, AC_HELP_STRING([--disable-ed448], [Disable ED448 support]))
|
||||
use_ed448="no"
|
||||
case "$enable_ed448" in
|
||||
no)
|
||||
;;
|
||||
*)
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
AC_CHECK_DECLS([NID_ED448], [
|
||||
use_ed448="yes"
|
||||
], [ if test "x$enable_ed448" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support ED448 and you used --enable-ed448.])
|
||||
fi ], [AC_INCLUDES_DEFAULT
|
||||
#include <openssl/evp.h>
|
||||
])
|
||||
fi
|
||||
if test $use_ed448 = "yes"; then
|
||||
AC_DEFINE_UNQUOTED([USE_ED448], [1], [Define this to enable ED448 support.])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(event-api, AC_HELP_STRING([--enable-event-api], [Enable (experimental) pluggable event base libunbound API installed to unbound-event.h]))
|
||||
case "$enable_event_api" in
|
||||
@@ -1003,6 +1265,14 @@ large outgoing port ranges. ])
|
||||
AC_CHECK_FUNCS([event_base_get_method]) # only in libevent 1.4.3 and later
|
||||
AC_CHECK_FUNCS([ev_loop]) # only in libev. (tested on 3.51)
|
||||
AC_CHECK_FUNCS([ev_default_loop]) # only in libev. (tested on 4.00)
|
||||
AC_CHECK_FUNCS([event_assign]) # in libevent, for thread-safety
|
||||
AC_CHECK_DECLS([evsignal_assign], [], [], [AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_EVENT_H
|
||||
# include <event.h>
|
||||
#else
|
||||
# include "event2/event.h"
|
||||
#endif
|
||||
])
|
||||
PC_LIBEVENT_DEPENDENCY="libevent"
|
||||
AC_SUBST(PC_LIBEVENT_DEPENDENCY)
|
||||
if test -n "$BAK_LDFLAGS_SET"; then
|
||||
@@ -1038,18 +1308,73 @@ AC_CHECK_DECLS([XML_StopParser], [], [], [AC_INCLUDES_DEFAULT
|
||||
#include <expat.h>
|
||||
])
|
||||
|
||||
# set static linking if requested
|
||||
# hiredis (redis C client for cachedb)
|
||||
AC_ARG_WITH(libhiredis, AC_HELP_STRING([--with-libhiredis=path],
|
||||
[specify explicit path for libhiredis.]),
|
||||
[ ],[ withval="no" ])
|
||||
found_libhiredis="no"
|
||||
if test x_$withval = x_yes -o x_$withval != x_no; then
|
||||
AC_MSG_CHECKING(for libhiredis)
|
||||
if test x_$withval = x_ -o x_$withval = x_yes; then
|
||||
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
|
||||
fi
|
||||
for dir in $withval ; do
|
||||
if test -f "$dir/include/hiredis/hiredis.h"; then
|
||||
found_libhiredis="yes"
|
||||
dnl assume /usr is in default path.
|
||||
if test "$dir" != "/usr"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$dir/include"
|
||||
LDFLAGS="$LDFLAGS -L$dir/lib"
|
||||
fi
|
||||
AC_MSG_RESULT(found in $dir)
|
||||
AC_DEFINE([USE_REDIS], [1], [Define this to use hiredis client.])
|
||||
LIBS="$LIBS -lhiredis"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
if test x_$found_libhiredis != x_yes; then
|
||||
AC_ERROR([Could not find libhiredis, hiredis.h])
|
||||
fi
|
||||
AC_CHECK_HEADERS([hiredis/hiredis.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_DECLS([redisConnect], [], [], [AC_INCLUDES_DEFAULT
|
||||
#include <hiredis/hiredis.h>
|
||||
])
|
||||
fi
|
||||
|
||||
# set static linking for uninstalled libraries if requested
|
||||
AC_SUBST(staticexe)
|
||||
staticexe=""
|
||||
AC_ARG_ENABLE(static-exe, AC_HELP_STRING([--enable-static-exe],
|
||||
[ enable to compile executables statically against (event) libs, for debug purposes ]),
|
||||
[ enable to compile executables statically against (event) uninstalled libs, for debug purposes ]),
|
||||
, )
|
||||
if test x_$enable_static_exe = x_yes; then
|
||||
staticexe="-static"
|
||||
if test "$on_mingw" = yes; then
|
||||
staticexe="-all-static"
|
||||
# for static compile, include gdi32 and zlib here.
|
||||
LIBS="$LIBS -lgdi32 -lz"
|
||||
if echo $LIBS | grep 'lgdi32' >/dev/null; then
|
||||
:
|
||||
else
|
||||
LIBS="$LIBS -lgdi32"
|
||||
fi
|
||||
LIBS="$LIBS -lz"
|
||||
fi
|
||||
fi
|
||||
|
||||
# set full static linking if requested
|
||||
AC_ARG_ENABLE(fully-static, AC_HELP_STRING([--enable-fully-static],
|
||||
[ enable to compile fully static ]),
|
||||
, )
|
||||
if test x_$enable_fully_static = x_yes; then
|
||||
staticexe="-all-static"
|
||||
if test "$on_mingw" = yes; then
|
||||
# for static compile, include gdi32 and zlib here.
|
||||
if echo $LIBS | grep 'lgdi32' >/dev/null; then
|
||||
:
|
||||
else
|
||||
LIBS="$LIBS -lgdi32"
|
||||
fi
|
||||
LIBS="$LIBS -lz"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1070,7 +1395,7 @@ if test "$USE_WINSOCK" = 1; then
|
||||
#include <windows.h>
|
||||
])
|
||||
AC_CHECK_TOOL(WINDRES, windres)
|
||||
LIBS="$LIBS -liphlpapi"
|
||||
LIBS="$LIBS -liphlpapi -lcrypt32"
|
||||
WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe"
|
||||
AC_SUBST(WINAPPS)
|
||||
WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c"
|
||||
@@ -1143,14 +1468,36 @@ AC_INCLUDES_DEFAULT
|
||||
#endif
|
||||
])
|
||||
AC_SEARCH_LIBS([setusercontext], [util])
|
||||
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync])
|
||||
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4])
|
||||
AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])])
|
||||
AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
|
||||
|
||||
# check if setreuid en setregid fail, on MacOSX10.4(darwin8).
|
||||
if echo $build_os | grep darwin8 > /dev/null; then
|
||||
if echo $target_os | grep darwin8 > /dev/null; then
|
||||
AC_DEFINE(DARWIN_BROKEN_SETREUID, 1, [Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work])
|
||||
fi
|
||||
AC_CHECK_DECLS([inet_pton,inet_ntop], [], [], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETINET_TCP_H
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
])
|
||||
AC_REPLACE_FUNCS(inet_aton)
|
||||
AC_REPLACE_FUNCS(inet_pton)
|
||||
AC_REPLACE_FUNCS(inet_ntop)
|
||||
@@ -1174,25 +1521,43 @@ AC_REPLACE_FUNCS(strlcpy)
|
||||
AC_REPLACE_FUNCS(memmove)
|
||||
AC_REPLACE_FUNCS(gmtime_r)
|
||||
AC_REPLACE_FUNCS(isblank)
|
||||
AC_REPLACE_FUNCS(explicit_bzero)
|
||||
dnl without CTIME, ARC4-functions and without reallocarray.
|
||||
LIBOBJ_WITHOUT_CTIMEARC4="$LIBOBJS"
|
||||
AC_SUBST(LIBOBJ_WITHOUT_CTIMEARC4)
|
||||
AC_REPLACE_FUNCS(reallocarray)
|
||||
AC_MSG_CHECKING([for reallocarray])
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE(AC_INCLUDES_DEFAULT
|
||||
[[
|
||||
#ifndef _OPENBSD_SOURCE
|
||||
#define _OPENBSD_SOURCE 1
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
int main(void) {
|
||||
void* p = reallocarray(NULL, 10, 100);
|
||||
free(p);
|
||||
return 0;
|
||||
}
|
||||
]])], [AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_REALLOCARRAY, 1, [If we have reallocarray(3)])
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
AC_LIBOBJ(reallocarray)
|
||||
])
|
||||
AC_CHECK_DECLS([reallocarray])
|
||||
if test "$USE_NSS" = "no"; then
|
||||
AC_REPLACE_FUNCS(arc4random)
|
||||
AC_REPLACE_FUNCS(arc4random_uniform)
|
||||
if test "$ac_cv_func_arc4random" = "no"; then
|
||||
AC_LIBOBJ(explicit_bzero)
|
||||
AC_LIBOBJ(arc4_lock)
|
||||
AC_CHECK_FUNCS([getentropy],,[
|
||||
if test "$USE_WINSOCK" = 1; then
|
||||
AC_LIBOBJ(getentropy_win)
|
||||
else
|
||||
case `uname` in
|
||||
Darwin)
|
||||
case "$host" in
|
||||
Darwin|*darwin*)
|
||||
AC_LIBOBJ(getentropy_osx)
|
||||
;;
|
||||
SunOS)
|
||||
*solaris*|*sunos*|SunOS)
|
||||
AC_LIBOBJ(getentropy_solaris)
|
||||
AC_CHECK_HEADERS([sys/sha2.h],, [
|
||||
AC_CHECK_FUNCS([SHA512_Update],,[
|
||||
@@ -1205,7 +1570,10 @@ if test "$USE_NSS" = "no"; then
|
||||
fi
|
||||
AC_SEARCH_LIBS([clock_gettime], [rt])
|
||||
;;
|
||||
Linux|*)
|
||||
*freebsd*|*FreeBSD)
|
||||
AC_LIBOBJ(getentropy_freebsd)
|
||||
;;
|
||||
*linux*|Linux|*)
|
||||
AC_LIBOBJ(getentropy_linux)
|
||||
AC_CHECK_FUNCS([SHA512_Update],,[
|
||||
AC_DEFINE([COMPAT_SHA512], [1], [Do sha512 definitions in config.h])
|
||||
@@ -1276,8 +1644,23 @@ dt_DNSTAP([$UNBOUND_RUN_DIR/dnstap.sock],
|
||||
]
|
||||
)
|
||||
|
||||
# check for dnscrypt if requested
|
||||
dnsc_DNSCRYPT([
|
||||
AC_DEFINE([USE_DNSCRYPT], [1], [Define to 1 to enable dnscrypt support])
|
||||
AC_SUBST([ENABLE_DNSCRYPT], [1])
|
||||
|
||||
AC_SUBST([DNSCRYPT_SRC], ["dnscrypt/dnscrypt.c"])
|
||||
AC_SUBST([DNSCRYPT_OBJ], ["dnscrypt.lo"])
|
||||
],
|
||||
[
|
||||
AC_SUBST([ENABLE_DNSCRYPT], [0])
|
||||
]
|
||||
)
|
||||
|
||||
# check for cachedb if requested
|
||||
AC_ARG_ENABLE(cachedb, AC_HELP_STRING([--enable-cachedb], [enable cachedb module that can use external cache storage]))
|
||||
# turn on cachedb when hiredis support is enabled.
|
||||
if test "$found_libhiredis" = "yes"; then enable_cachedb="yes"; fi
|
||||
case "$enable_cachedb" in
|
||||
yes)
|
||||
AC_DEFINE([USE_CACHEDB], [1], [Define to 1 to use cachedb support])
|
||||
@@ -1287,6 +1670,62 @@ case "$enable_cachedb" in
|
||||
;;
|
||||
esac
|
||||
|
||||
# check for ipsecmod if requested
|
||||
AC_ARG_ENABLE(ipsecmod, AC_HELP_STRING([--enable-ipsecmod], [Enable ipsecmod module that facilitates opportunistic IPsec]))
|
||||
case "$enable_ipsecmod" in
|
||||
yes)
|
||||
AC_DEFINE([USE_IPSECMOD], [1], [Define to 1 to use ipsecmod support.])
|
||||
IPSECMOD_OBJ="ipsecmod.lo ipsecmod-whitelist.lo"
|
||||
AC_SUBST(IPSECMOD_OBJ)
|
||||
IPSECMOD_HEADER='$(srcdir)/ipsecmod/ipsecmod.h $(srcdir)/ipsecmod/ipsecmod-whitelist.h'
|
||||
AC_SUBST(IPSECMOD_HEADER)
|
||||
;;
|
||||
no|*)
|
||||
# nothing
|
||||
;;
|
||||
esac
|
||||
|
||||
# check for ipset if requested
|
||||
AC_ARG_ENABLE(ipset, AC_HELP_STRING([--enable-ipset], [enable ipset module]))
|
||||
case "$enable_ipset" in
|
||||
yes)
|
||||
AC_DEFINE([USE_IPSET], [1], [Define to 1 to use ipset support])
|
||||
IPSET_SRC="ipset/ipset.c"
|
||||
AC_SUBST(IPSET_SRC)
|
||||
IPSET_OBJ="ipset.lo"
|
||||
AC_SUBST(IPSET_OBJ)
|
||||
|
||||
# mnl
|
||||
AC_ARG_WITH(libmnl, AC_HELP_STRING([--with-libmnl=path],
|
||||
[specify explicit path for libmnl.]),
|
||||
[ ],[ withval="yes" ])
|
||||
found_libmnl="no"
|
||||
AC_MSG_CHECKING(for libmnl)
|
||||
if test x_$withval = x_ -o x_$withval = x_yes; then
|
||||
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
|
||||
fi
|
||||
for dir in $withval ; do
|
||||
if test -f "$dir/include/libmnl/libmnl.h"; then
|
||||
found_libmnl="yes"
|
||||
dnl assume /usr is in default path.
|
||||
if test "$dir" != "/usr"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$dir/include"
|
||||
LDFLAGS="$LDFLAGS -L$dir/lib"
|
||||
fi
|
||||
AC_MSG_RESULT(found in $dir)
|
||||
LIBS="$LIBS -lmnl"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
if test x_$found_libmnl != x_yes; then
|
||||
AC_ERROR([Could not find libmnl, libmnl.h])
|
||||
fi
|
||||
;;
|
||||
no|*)
|
||||
# nothing
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_MSG_CHECKING([if ${MAKE:-make} supports $< with implicit rule in scope])
|
||||
# on openBSD, the implicit rule make $< work.
|
||||
# on Solaris, it does not work ($? is changed sources, $^ lists dependencies).
|
||||
@@ -1333,11 +1772,25 @@ AC_ARG_WITH(libunbound-only, AC_HELP_STRING([--with-libunbound-only],
|
||||
INSTALLTARGET="install-lib"
|
||||
fi
|
||||
])
|
||||
if test $ALLTARGET = "alltargets"; then
|
||||
if test $USE_NSS = "yes"; then
|
||||
AC_ERROR([--with-nss can only be used in combination with --with-libunbound-only.])
|
||||
fi
|
||||
if test $USE_NETTLE = "yes"; then
|
||||
AC_ERROR([--with-nettle can only be used in combination with --with-libunbound-only.])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(ALLTARGET)
|
||||
AC_SUBST(INSTALLTARGET)
|
||||
|
||||
ACX_STRIP_EXT_FLAGS
|
||||
LDFLAGS="$LATE_LDFLAGS $LDFLAGS"
|
||||
if test -n "$LATE_LDFLAGS"; then
|
||||
LDFLAGS="$LATE_LDFLAGS $LDFLAGS"
|
||||
fi
|
||||
# remove start spaces
|
||||
LDFLAGS=`echo "$LDFLAGS"|sed -e 's/^ *//'`
|
||||
LIBS=`echo "$LIBS"|sed -e 's/^ *//'`
|
||||
|
||||
AC_DEFINE_UNQUOTED([MAXSYSLOGMSGLEN], [10240], [Define to the maximum message length to pass to syslog.])
|
||||
|
||||
@@ -1347,8 +1800,14 @@ AHX_CONFIG_EXT_FLAGS
|
||||
|
||||
dnl includes
|
||||
[
|
||||
#ifndef _OPENBSD_SOURCE
|
||||
#define _OPENBSD_SOURCE 1
|
||||
#endif
|
||||
|
||||
#ifndef UNBOUND_DEBUG
|
||||
# ifndef NDEBUG
|
||||
# define NDEBUG
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/** Use small-ldns codebase */
|
||||
@@ -1463,12 +1922,29 @@ char *strsep(char **stringp, const char *delim);
|
||||
int isblank(int c);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_EXPLICIT_BZERO
|
||||
#define explicit_bzero unbound_explicit_bzero
|
||||
void explicit_bzero(void* buf, size_t len);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INET_NTOP) && !HAVE_DECL_INET_NTOP
|
||||
const char *inet_ntop(int af, const void *src, char *dst, size_t size);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INET_PTON) && !HAVE_DECL_INET_PTON
|
||||
int inet_pton(int af, const char* src, void* dst);
|
||||
#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 !HAVE_DECL_REALLOCARRAY
|
||||
void *reallocarray(void *ptr, size_t nmemb, size_t size);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBRESSL
|
||||
# if !HAVE_DECL_STRLCPY
|
||||
size_t strlcpy(char *dst, const char *src, size_t siz);
|
||||
@@ -1482,17 +1958,14 @@ uint32_t arc4random(void);
|
||||
# if !HAVE_DECL_ARC4RANDOM_UNIFORM && defined(HAVE_ARC4RANDOM_UNIFORM)
|
||||
uint32_t arc4random_uniform(uint32_t upper_bound);
|
||||
# endif
|
||||
# if !HAVE_DECL_REALLOCARRAY
|
||||
void *reallocarray(void *ptr, size_t nmemb, size_t size);
|
||||
# endif
|
||||
#endif /* HAVE_LIBRESSL */
|
||||
#ifndef HAVE_ARC4RANDOM
|
||||
void explicit_bzero(void* buf, size_t len);
|
||||
int getentropy(void* buf, size_t len);
|
||||
uint32_t arc4random(void);
|
||||
void arc4random_buf(void* buf, size_t n);
|
||||
void _ARC4_LOCK(void);
|
||||
void _ARC4_UNLOCK(void);
|
||||
void _ARC4_LOCK_DESTROY(void);
|
||||
#endif
|
||||
#ifndef HAVE_ARC4RANDOM_UNIFORM
|
||||
uint32_t arc4random_uniform(uint32_t upper_bound);
|
||||
@@ -1558,6 +2031,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
||||
|
||||
/** default port for DNS traffic. */
|
||||
#define UNBOUND_DNS_PORT 53
|
||||
/** default port for DNS over TLS traffic. */
|
||||
#define UNBOUND_DNS_OVER_TLS_PORT 853
|
||||
/** default port for unbound control traffic, registered port with IANA,
|
||||
ub-dns-control 8953/tcp unbound dns nameserver control */
|
||||
#define UNBOUND_CONTROL_PORT 8953
|
||||
@@ -1571,6 +2046,6 @@ dnl if this is a distro tarball, that was already done by makedist.sh
|
||||
AC_SUBST(version, [VERSION_MAJOR.VERSION_MINOR.VERSION_MICRO])
|
||||
AC_SUBST(date, [`date +'%b %e, %Y'`])
|
||||
|
||||
AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h contrib/libunbound.pc])
|
||||
AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h dnscrypt/dnscrypt_config.h contrib/libunbound.pc contrib/unbound.socket contrib/unbound.service])
|
||||
AC_CONFIG_HEADER([config.h])
|
||||
AC_OUTPUT
|
||||
|
||||
@@ -29,3 +29,23 @@ distribution but may be helpful.
|
||||
Patch from Stephane Lapie for ASAHI Net.
|
||||
* unbound_smf22.tar.gz: Solaris SMF installation/removal scripts.
|
||||
Contributed by Yuri Voinov.
|
||||
* unbound.socket and unbound.service: systemd files for unbound, install them
|
||||
in /usr/lib/systemd/system. Contributed by Sami Kerola and Pavel Odintsov.
|
||||
* redirect-bogus.patch: Return configured address for bogus A and AAAA answers,
|
||||
instead of SERVFAIL. Contributed by SIDN.
|
||||
* fastrpz.patch: fastrpz support from Farsight Security.
|
||||
* libunbound.so.conf: ltrace.conf file, see ltrace.conf(5), for libunbound.
|
||||
* unbound-querycachedb.py: utility to show data stored in cachedb backend
|
||||
for a particular query name and type. It requires dnspython and (for
|
||||
redis backend) redis Python modules.
|
||||
* unbound-fuzzme.patch: adds unbound-fuzzme program that parses a packet from
|
||||
stdin. Used with fuzzers, patch from Jacob Hoffman-Andrews.
|
||||
* unbound-fuzzers.tar.bz2: three programs for fuzzing, that are 1:1
|
||||
replacements for unbound-fuzzme.c that gets created after applying
|
||||
the contrib/unbound-fuzzme.patch. They are contributed by
|
||||
Eric Sesterhenn from X41 D-Sec.
|
||||
* drop-tld.diff: adds option drop-tld: yesno that drops 2 label queries,
|
||||
to stop random floods. Apply with patch -p1 < contrib/drop-tld.diff and
|
||||
compile. From Saksham Manchanda (Secure64). Please note that we think
|
||||
this will drop DNSKEY and DS lookups for tlds and hence break DNSSEC
|
||||
lookups for downstream clients.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
Index: trunk/doc/unbound.conf.5.in
|
||||
===================================================================
|
||||
--- trunk/doc/unbound.conf.5.in (revision 3587)
|
||||
--- trunk/doc/unbound.conf.5.in (revision 4357)
|
||||
+++ trunk/doc/unbound.conf.5.in (working copy)
|
||||
@@ -593,6 +593,13 @@
|
||||
possible. Best effort approach, full QNAME and original QTYPE will be sent when
|
||||
upstream replies with a RCODE other than NOERROR. Default is off.
|
||||
@@ -701,6 +701,13 @@
|
||||
this option in enabled. Only use if you know what you are doing.
|
||||
This option only has effect when qname-minimisation is enabled. Default is off.
|
||||
.TP
|
||||
+.B aaaa\-filter: \fI<yes or no>
|
||||
+Activate behavior similar to BIND's AAAA-filter.
|
||||
@@ -18,7 +18,7 @@ Index: trunk/doc/unbound.conf.5.in
|
||||
on your private network, and are not allowed to be returned for
|
||||
Index: trunk/iterator/iter_scrub.c
|
||||
===================================================================
|
||||
--- trunk/iterator/iter_scrub.c (revision 3587)
|
||||
--- trunk/iterator/iter_scrub.c (revision 4357)
|
||||
+++ trunk/iterator/iter_scrub.c (working copy)
|
||||
@@ -617,6 +617,32 @@
|
||||
}
|
||||
@@ -75,10 +75,11 @@ Index: trunk/iterator/iter_scrub.c
|
||||
/* At this point, we brutally remove ALL rrsets that aren't
|
||||
* children of the originating zone. The idea here is that,
|
||||
* as far as we know, the server that we contacted is ONLY
|
||||
@@ -681,6 +715,24 @@
|
||||
@@ -680,6 +714,24 @@
|
||||
prev = NULL;
|
||||
rrset = msg->rrset_first;
|
||||
while(rrset) {
|
||||
|
||||
+
|
||||
+ /* ASN: For AAAA records only... */
|
||||
+ if((ie->aaaa_filter) && (rrset->type == LDNS_RR_TYPE_AAAA)) {
|
||||
+ /* ASN: If this is not a AAAA query, then remove AAAA
|
||||
@@ -96,13 +97,12 @@ Index: trunk/iterator/iter_scrub.c
|
||||
+ LDNS_RR_TYPE_AAAA, qinfo->qclass);
|
||||
+ }
|
||||
+ /* ASN: End of added code */
|
||||
+
|
||||
|
||||
/* remove private addresses */
|
||||
if( (rrset->type == LDNS_RR_TYPE_A ||
|
||||
rrset->type == LDNS_RR_TYPE_AAAA)) {
|
||||
Index: trunk/iterator/iter_utils.c
|
||||
===================================================================
|
||||
--- trunk/iterator/iter_utils.c (revision 3587)
|
||||
--- trunk/iterator/iter_utils.c (revision 4357)
|
||||
+++ trunk/iterator/iter_utils.c (working copy)
|
||||
@@ -175,6 +175,7 @@
|
||||
}
|
||||
@@ -114,9 +114,9 @@ Index: trunk/iterator/iter_utils.c
|
||||
|
||||
Index: trunk/iterator/iterator.c
|
||||
===================================================================
|
||||
--- trunk/iterator/iterator.c (revision 3587)
|
||||
--- trunk/iterator/iterator.c (revision 4357)
|
||||
+++ trunk/iterator/iterator.c (working copy)
|
||||
@@ -1776,6 +1776,53 @@
|
||||
@@ -1847,6 +1847,53 @@
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -170,7 +170,7 @@ Index: trunk/iterator/iterator.c
|
||||
|
||||
/**
|
||||
* This is the request event state where the request will be sent to one of
|
||||
@@ -1823,6 +1870,13 @@
|
||||
@@ -1894,6 +1941,13 @@
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ Index: trunk/iterator/iterator.c
|
||||
/* Make sure we have a delegation point, otherwise priming failed
|
||||
* or another failure occurred */
|
||||
if(!iq->dp) {
|
||||
@@ -2922,6 +2976,61 @@
|
||||
@@ -3095,6 +3149,61 @@
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -244,9 +244,9 @@ Index: trunk/iterator/iterator.c
|
||||
+/* ASN: End of added code */
|
||||
+
|
||||
/*
|
||||
* Return priming query results to interestes super querystates.
|
||||
* Return priming query results to interested super querystates.
|
||||
*
|
||||
@@ -2941,6 +3050,9 @@
|
||||
@@ -3114,6 +3223,9 @@
|
||||
else if(super->qinfo.qtype == LDNS_RR_TYPE_DS && ((struct iter_qstate*)
|
||||
super->minfo[id])->state == DSNS_FIND_STATE)
|
||||
processDSNSResponse(qstate, id, super);
|
||||
@@ -256,7 +256,7 @@ Index: trunk/iterator/iterator.c
|
||||
else if(qstate->return_rcode != LDNS_RCODE_NOERROR)
|
||||
error_supers(qstate, id, super);
|
||||
else if(qstate->is_priming)
|
||||
@@ -2978,6 +3090,9 @@
|
||||
@@ -3151,6 +3263,9 @@
|
||||
case INIT_REQUEST_3_STATE:
|
||||
cont = processInitRequest3(qstate, iq, id);
|
||||
break;
|
||||
@@ -266,7 +266,7 @@ Index: trunk/iterator/iterator.c
|
||||
case QUERYTARGETS_STATE:
|
||||
cont = processQueryTargets(qstate, iq, ie, id);
|
||||
break;
|
||||
@@ -3270,6 +3385,8 @@
|
||||
@@ -3460,6 +3575,8 @@
|
||||
return "INIT REQUEST STATE (stage 2)";
|
||||
case INIT_REQUEST_3_STATE:
|
||||
return "INIT REQUEST STATE (stage 3)";
|
||||
@@ -275,7 +275,7 @@ Index: trunk/iterator/iterator.c
|
||||
case QUERYTARGETS_STATE :
|
||||
return "QUERY TARGETS STATE";
|
||||
case PRIME_RESP_STATE :
|
||||
@@ -3294,6 +3411,7 @@
|
||||
@@ -3484,6 +3601,7 @@
|
||||
case INIT_REQUEST_STATE :
|
||||
case INIT_REQUEST_2_STATE :
|
||||
case INIT_REQUEST_3_STATE :
|
||||
@@ -285,19 +285,19 @@ Index: trunk/iterator/iterator.c
|
||||
return 0;
|
||||
Index: trunk/iterator/iterator.h
|
||||
===================================================================
|
||||
--- trunk/iterator/iterator.h (revision 3587)
|
||||
--- trunk/iterator/iterator.h (revision 4357)
|
||||
+++ trunk/iterator/iterator.h (working copy)
|
||||
@@ -113,6 +113,9 @@
|
||||
@@ -130,6 +130,9 @@
|
||||
*/
|
||||
int* target_fetch_policy;
|
||||
|
||||
+ /** ASN: AAAA-filter flag */
|
||||
+ int aaaa_filter;
|
||||
+
|
||||
/** ip6.arpa dname in wireformat, used for qname-minimisation */
|
||||
uint8_t* ip6arpa_dname;
|
||||
};
|
||||
@@ -163,6 +166,14 @@
|
||||
/** lock on ratelimit counter */
|
||||
lock_basic_type queries_ratelimit_lock;
|
||||
/** number of queries that have been ratelimited */
|
||||
@@ -182,6 +185,14 @@
|
||||
INIT_REQUEST_3_STATE,
|
||||
|
||||
/**
|
||||
@@ -311,26 +311,26 @@ Index: trunk/iterator/iterator.h
|
||||
+ /**
|
||||
* Each time a delegation point changes for a given query or a
|
||||
* query times out and/or wakes up, this state is (re)visited.
|
||||
* This state is reponsible for iterating through a list of
|
||||
@@ -346,6 +357,13 @@
|
||||
* This state is responsible for iterating through a list of
|
||||
@@ -364,6 +375,13 @@
|
||||
* be used when creating the state. A higher one will be attempted.
|
||||
*/
|
||||
int refetch_glue;
|
||||
|
||||
+
|
||||
+ /**
|
||||
+ * ASN: This is a flag that, if true, means that this query is
|
||||
+ * for fetching A records to populate cache and determine if we must
|
||||
+ * return AAAA records or not.
|
||||
+ */
|
||||
+ int fetch_a_for_aaaa;
|
||||
+
|
||||
|
||||
/** list of pending queries to authoritative servers. */
|
||||
struct outbound_list outlist;
|
||||
|
||||
Index: trunk/pythonmod/interface.i
|
||||
===================================================================
|
||||
--- trunk/pythonmod/interface.i (revision 3587)
|
||||
--- trunk/pythonmod/interface.i (revision 4357)
|
||||
+++ trunk/pythonmod/interface.i (working copy)
|
||||
@@ -632,6 +632,7 @@
|
||||
@@ -851,6 +851,7 @@
|
||||
int harden_dnssec_stripped;
|
||||
int harden_referral_path;
|
||||
int use_caps_bits_for_id;
|
||||
@@ -340,9 +340,9 @@ Index: trunk/pythonmod/interface.i
|
||||
size_t unwanted_threshold;
|
||||
Index: trunk/util/config_file.c
|
||||
===================================================================
|
||||
--- trunk/util/config_file.c (revision 3587)
|
||||
--- trunk/util/config_file.c (revision 4357)
|
||||
+++ trunk/util/config_file.c (working copy)
|
||||
@@ -176,6 +176,7 @@
|
||||
@@ -195,6 +195,7 @@
|
||||
cfg->harden_referral_path = 0;
|
||||
cfg->harden_algo_downgrade = 0;
|
||||
cfg->use_caps_bits_for_id = 0;
|
||||
@@ -352,9 +352,9 @@ Index: trunk/util/config_file.c
|
||||
cfg->private_domain = NULL;
|
||||
Index: trunk/util/config_file.h
|
||||
===================================================================
|
||||
--- trunk/util/config_file.h (revision 3587)
|
||||
--- trunk/util/config_file.h (revision 4357)
|
||||
+++ trunk/util/config_file.h (working copy)
|
||||
@@ -179,6 +179,8 @@
|
||||
@@ -209,6 +209,8 @@
|
||||
int harden_algo_downgrade;
|
||||
/** use 0x20 bits in query as random ID bits */
|
||||
int use_caps_bits_for_id;
|
||||
@@ -365,9 +365,9 @@ Index: trunk/util/config_file.h
|
||||
/** strip away these private addrs from answers, no DNS Rebinding */
|
||||
Index: trunk/util/configlexer.lex
|
||||
===================================================================
|
||||
--- trunk/util/configlexer.lex (revision 3587)
|
||||
--- trunk/util/configlexer.lex (revision 4357)
|
||||
+++ trunk/util/configlexer.lex (working copy)
|
||||
@@ -267,6 +267,7 @@
|
||||
@@ -279,6 +279,7 @@
|
||||
use-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) }
|
||||
caps-whitelist{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
|
||||
unwanted-reply-threshold{COLON} { YDVAR(1, VAR_UNWANTED_REPLY_THRESHOLD) }
|
||||
@@ -377,9 +377,9 @@ Index: trunk/util/configlexer.lex
|
||||
prefetch-key{COLON} { YDVAR(1, VAR_PREFETCH_KEY) }
|
||||
Index: trunk/util/configparser.y
|
||||
===================================================================
|
||||
--- trunk/util/configparser.y (revision 3587)
|
||||
--- trunk/util/configparser.y (revision 4357)
|
||||
+++ trunk/util/configparser.y (working copy)
|
||||
@@ -92,6 +92,7 @@
|
||||
@@ -95,6 +95,7 @@
|
||||
%token VAR_STATISTICS_CUMULATIVE VAR_OUTGOING_PORT_PERMIT
|
||||
%token VAR_OUTGOING_PORT_AVOID VAR_DLV_ANCHOR_FILE VAR_DLV_ANCHOR
|
||||
%token VAR_NEG_CACHE_SIZE VAR_HARDEN_REFERRAL_PATH VAR_PRIVATE_ADDRESS
|
||||
@@ -387,7 +387,7 @@ Index: trunk/util/configparser.y
|
||||
%token VAR_PRIVATE_DOMAIN VAR_REMOTE_CONTROL VAR_CONTROL_ENABLE
|
||||
%token VAR_CONTROL_INTERFACE VAR_CONTROL_PORT VAR_SERVER_KEY_FILE
|
||||
%token VAR_SERVER_CERT_FILE VAR_CONTROL_KEY_FILE VAR_CONTROL_CERT_FILE
|
||||
@@ -169,6 +170,7 @@
|
||||
@@ -203,6 +204,7 @@
|
||||
server_dlv_anchor_file | server_dlv_anchor | server_neg_cache_size |
|
||||
server_harden_referral_path | server_private_address |
|
||||
server_private_domain | server_extended_statistics |
|
||||
@@ -395,10 +395,12 @@ Index: trunk/util/configparser.y
|
||||
server_local_data_ptr | server_jostle_timeout |
|
||||
server_unwanted_reply_threshold | server_log_time_ascii |
|
||||
server_domain_insecure | server_val_sig_skew_min |
|
||||
@@ -893,6 +895,15 @@
|
||||
@@ -1183,6 +1185,15 @@
|
||||
OUTYY(("P(server_caps_whitelist:%s)\n", $2));
|
||||
if(!cfg_strlist_insert(&cfg_parser->cfg->caps_whitelist, $2))
|
||||
yyerror("out of memory");
|
||||
}
|
||||
;
|
||||
+ }
|
||||
+ ;
|
||||
+server_aaaa_filter: VAR_AAAA_FILTER STRING_ARG
|
||||
+ {
|
||||
+ OUTYY(("P(server_aaaa_filter:%s)\n", $2));
|
||||
@@ -406,8 +408,6 @@ Index: trunk/util/configparser.y
|
||||
+ yyerror("expected yes or no.");
|
||||
+ else cfg_parser->cfg->aaaa_filter = (strcmp($2, "yes")==0);
|
||||
+ free($2);
|
||||
+ }
|
||||
+ ;
|
||||
}
|
||||
;
|
||||
server_private_address: VAR_PRIVATE_ADDRESS STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_private_address:%s)\n", $2));
|
||||
|
||||
@@ -9,12 +9,13 @@
|
||||
# Variables
|
||||
dst_dir="/etc/opt/csw/unbound"
|
||||
work_dir="/tmp"
|
||||
list_addr="http://pgl.yoyo.org/adservers/serverlist.php?hostformat=nohtml&showintro=1&startdate%5Bday%5D=&startdate%5Bmonth%5D=&startdate%5Byear%5D="
|
||||
list_addr="https://pgl.yoyo.org/adservers/serverlist.php?hostformat=nohtml&showintro=1&startdate%5Bday%5D=&startdate%5Bmonth%5D=&startdate%5Byear%5D="
|
||||
|
||||
# OS commands
|
||||
CAT=`which cat`
|
||||
ECHO=`which echo`
|
||||
WGET=`which wget`
|
||||
TR=`which tr`
|
||||
|
||||
# Check Wget installed
|
||||
if [ ! -f $WGET ]; then
|
||||
@@ -22,8 +23,10 @@ if [ ! -f $WGET ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# remove special characters with tr to protect unbound.conf
|
||||
$WGET -O $work_dir/yoyo_ad_servers "$list_addr" && \
|
||||
$CAT $work_dir/yoyo_ad_servers | \
|
||||
$TR -d '";$\\' | \
|
||||
while read line ; \
|
||||
do \
|
||||
$ECHO "local-zone: \"$line\" redirect" ;\
|
||||
@@ -36,4 +39,4 @@ echo "Done."
|
||||
# the unbound_ad_servers file:
|
||||
#
|
||||
# include: $dst_dir/unbound_ad_servers
|
||||
#
|
||||
#
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
diff --git a/daemon/worker.c b/daemon/worker.c
|
||||
index 263fcdd..f787b70 100644
|
||||
--- a/daemon/worker.c
|
||||
+++ b/daemon/worker.c
|
||||
@@ -1213,6 +1213,15 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
|
||||
log_query_in(ip, qinfo.qname, qinfo.qtype, qinfo.qclass);
|
||||
}
|
||||
+
|
||||
+ if(worker->env.cfg->drop_tld) {
|
||||
+ int lab = dname_count_labels(qinfo.qname);
|
||||
+ if (lab == 2) {
|
||||
+ comm_point_drop_reply(repinfo);
|
||||
+ verbose(VERB_ALGO, "Dropping one label query.");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
if(qinfo.qtype == LDNS_RR_TYPE_AXFR ||
|
||||
qinfo.qtype == LDNS_RR_TYPE_IXFR) {
|
||||
verbose(VERB_ALGO, "worker request: refused zone transfer.");
|
||||
diff --git a/util/config_file.h b/util/config_file.h
|
||||
index b3ef930..2791541 100644
|
||||
--- a/util/config_file.h
|
||||
+++ b/util/config_file.h
|
||||
@@ -274,6 +274,8 @@ struct config_file {
|
||||
int prefetch_key;
|
||||
/** deny queries of type ANY with an empty answer */
|
||||
int deny_any;
|
||||
+ /** Drop TLD queries from clients **/
|
||||
+ int drop_tld;
|
||||
|
||||
/** chrootdir, if not "" or chroot will be done */
|
||||
char* chrootdir;
|
||||
diff --git a/util/configlexer.lex b/util/configlexer.lex
|
||||
index a86ddf5..9bbedbb 100644
|
||||
--- a/util/configlexer.lex
|
||||
+++ b/util/configlexer.lex
|
||||
@@ -299,6 +299,7 @@ private-domain{COLON} { YDVAR(1, VAR_PRIVATE_DOMAIN) }
|
||||
prefetch-key{COLON} { YDVAR(1, VAR_PREFETCH_KEY) }
|
||||
prefetch{COLON} { YDVAR(1, VAR_PREFETCH) }
|
||||
deny-any{COLON} { YDVAR(1, VAR_DENY_ANY) }
|
||||
+drop-tld{COLON} { YDVAR(1, VAR_DROP_TLD) }
|
||||
stub-zone{COLON} { YDVAR(0, VAR_STUB_ZONE) }
|
||||
name{COLON} { YDVAR(1, VAR_NAME) }
|
||||
stub-addr{COLON} { YDVAR(1, VAR_STUB_ADDR) }
|
||||
diff --git a/util/configparser.y b/util/configparser.y
|
||||
index 10227a2..567d68e 100644
|
||||
--- a/util/configparser.y
|
||||
+++ b/util/configparser.y
|
||||
@@ -164,6 +164,7 @@ extern struct config_parser_state* cfg_parser;
|
||||
%token VAR_FAST_SERVER_PERMIL VAR_FAST_SERVER_NUM
|
||||
%token VAR_ALLOW_NOTIFY VAR_TLS_WIN_CERT VAR_TCP_CONNECTION_LIMIT
|
||||
%token VAR_FORWARD_NO_CACHE VAR_STUB_NO_CACHE VAR_LOG_SERVFAIL VAR_DENY_ANY
|
||||
+%token VAR_DROP_TLD
|
||||
%token VAR_UNKNOWN_SERVER_TIME_LIMIT VAR_LOG_TAG_QUERYREPLY
|
||||
%token VAR_STREAM_WAIT_SIZE VAR_TLS_CIPHERS VAR_TLS_CIPHERSUITES
|
||||
%token VAR_TLS_SESSION_TICKET_KEYS
|
||||
@@ -266,6 +267,7 @@ content_server: server_num_threads | server_verbosity | server_port |
|
||||
server_tls_cert_bundle | server_tls_additional_port | server_low_rtt |
|
||||
server_fast_server_permil | server_fast_server_num | server_tls_win_cert |
|
||||
server_tcp_connection_limit | server_log_servfail | server_deny_any |
|
||||
+ server_drop_tld |
|
||||
server_unknown_server_time_limit | server_log_tag_queryreply |
|
||||
server_stream_wait_size | server_tls_ciphers |
|
||||
server_tls_ciphersuites | server_tls_session_ticket_keys
|
||||
@@ -1466,6 +1468,16 @@ server_deny_any: VAR_DENY_ANY STRING_ARG
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
+
|
||||
+server_drop_tld: VAR_DROP_TLD STRING_ARG
|
||||
+ {
|
||||
+ OUTYY(("P(server_drop_tld:%s)\n", $2));
|
||||
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||
+ yyerror("expected yes or no.");
|
||||
+ else cfg_parser->cfg->drop_tld = (strcmp($2, "yes")==0);
|
||||
+ free($2);
|
||||
+ }
|
||||
+ ;
|
||||
server_unwanted_reply_threshold: VAR_UNWANTED_REPLY_THRESHOLD STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_unwanted_reply_threshold:%s)\n", $2));
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,8 @@ Name: unbound
|
||||
Description: Library with validating, recursive, and caching DNS resolver
|
||||
URL: http://www.unbound.net
|
||||
Version: @PACKAGE_VERSION@
|
||||
Requires: libcrypto libssl @PC_LIBEVENT_DEPENDENCY@ @PC_PY_DEPENDENCY@
|
||||
Libs: -L${libdir} -lunbound
|
||||
Requires: libcrypto libssl @PC_LIBEVENT_DEPENDENCY@
|
||||
Requires.private: @PC_PY_DEPENDENCY@
|
||||
Libs: -L${libdir} -lunbound -lssl -lcrypto
|
||||
Libs.private: @SSLLIB@ @LIBS@
|
||||
Cflags: -I${includedir}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
# See ltrace.conf(5) for description of syntax of this file.
|
||||
typedef ub_type = enum(TYPE_A=1,TYPE_NS=2,TYPE_SOA=6,TYPE_MX=15,TYPE_TXT=16,TYPE_AAAA=28,TYPE_DS=43,TYPE_DNSKEY=48,TYPE_TLSA=52,TYPE_ANY=255);
|
||||
typedef ub_class = enum(CLASS_IN=1,CLASS_CH=3,CLASS_NONE=254,CLASS_ANY=255);
|
||||
typedef ub_rcode = enum(RCODE_NOERROR,RCODE_FORMERR,RCODE_SERVFAIL,RCODE_NXDOMAIN,RCODE_NOTIMPL,RCODE_REFUSED,RCODE_YXDOMAIN,RCODE_YXRRSET,RCODE_NXRRSET,RCODE_NOTAUTH,RCODE_NOTZONE);
|
||||
typedef ub_havedata = enum(no_data, have_data);
|
||||
typedef ub_nxdomain = enum(name_exists, nxdomain);
|
||||
typedef ub_secure = enum(not_secure, secure);
|
||||
typedef ub_bogus = enum(not_bogus, bogus);
|
||||
typedef ub_result = struct(string, ub_type, ub_class, array(void*,zero)*, array(int,zero)*, string, ub_rcode, void*, int, ub_havedata, ub_nxdomain, ub_secure, ub_bogus, string, int);
|
||||
typedef ub_ctx = void;
|
||||
ub_ctx* ub_ctx_create(void);
|
||||
void ub_ctx_delete(ub_ctx*);
|
||||
int ub_ctx_set_option(ub_ctx*, string, string);
|
||||
int ub_ctx_get_option(ub_ctx*, string, +string*);
|
||||
int ub_ctx_config(ub_ctx*, string);
|
||||
int ub_ctx_set_fwd(ub_ctx*, string);
|
||||
int ub_ctx_set_tls(ub_ctx*, bool(int));
|
||||
int ub_ctx_set_stub(ub_ctx*, string, string, bool(int));
|
||||
int ub_ctx_resolvconf(ub_ctx*, string);
|
||||
int ub_ctx_hosts(ub_ctx*, string);
|
||||
int ub_ctx_add_ta(ub_ctx*, string);
|
||||
int ub_ctx_add_ta_file(ub_ctx*, string);
|
||||
int ub_ctx_add_ta_autr(ub_ctx*, string);
|
||||
int ub_ctx_trustedkeys(ub_ctx*, string);
|
||||
int ub_ctx_debugout(ub_ctx*, void*);
|
||||
int ub_ctx_debuglevel(ub_ctx*, int);
|
||||
int ub_ctx_async(ub_ctx*, bool(int));
|
||||
int ub_poll(ub_ctx*);
|
||||
int ub_wait(ub_ctx*);
|
||||
int ub_fd(ub_ctx*);
|
||||
int ub_process(ub_ctx*);
|
||||
int ub_resolve(ub_ctx*, string, ub_type, ub_class, +ub_result**);
|
||||
int ub_resolve_async(ub_ctx*, string, ub_type, ub_class, void*, void*, +int*);
|
||||
int ub_cancel(ub_ctx*, int);
|
||||
void ub_resolve_free(ub_result*);
|
||||
string ub_strerror(int);
|
||||
int ub_ctx_print_local_zones(ub_ctx*);
|
||||
int ub_ctx_zone_add(ub_ctx*, string, string);
|
||||
int ub_ctx_zone_remove(ub_ctx*, string);
|
||||
int ub_ctx_data_add(ub_ctx*, string);
|
||||
int ub_ctx_data_remove(ub_ctx*, string);
|
||||
string ub_version(void);
|
||||
@@ -91,7 +91,7 @@ while ( scalar keys %startstats < $numthreads || scalar keys %donestats < $numth
|
||||
$allstats{$inthread}->{outstandingexc} = $4;
|
||||
}
|
||||
elsif ( $line =~ m/info: average recursion processing time ([0-9\.]+) sec/ ) {
|
||||
$allstats{$inthread}->{recursionavg} = int($1 * 1000); # change sec to milisec.
|
||||
$allstats{$inthread}->{recursionavg} = int($1 * 1000); # change sec to millisec.
|
||||
}
|
||||
elsif ( $line =~ m/info: histogram of recursion processing times/ ) {
|
||||
next;
|
||||
@@ -103,7 +103,7 @@ while ( scalar keys %startstats < $numthreads || scalar keys %donestats < $numth
|
||||
}
|
||||
elsif ( $line =~ m/info: lower\(secs\) upper\(secs\) recursions/ ) {
|
||||
# since after this line we're unsure if we get these numbers
|
||||
# at all, we sould consider this marker as the end of the
|
||||
# at all, we should consider this marker as the end of the
|
||||
# block. Chances that we're parsing a file halfway written
|
||||
# at this stage are small. Bold statement.
|
||||
$donestats{$inthread} = 1;
|
||||
|
||||
@@ -0,0 +1,344 @@
|
||||
Index: daemon/worker.c
|
||||
===================================================================
|
||||
--- daemon/worker.c (revision 4191)
|
||||
+++ daemon/worker.c (working copy)
|
||||
@@ -663,8 +663,21 @@
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, rep,
|
||||
LDNS_RCODE_SERVFAIL, edns, worker->scratchpad))
|
||||
goto bail_out;
|
||||
- error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
- qinfo, id, flags, edns);
|
||||
+ if (qinfo->qtype == LDNS_RR_TYPE_A &&
|
||||
+ worker->env.cfg->redirect_bogus_ipv4) {
|
||||
+ /* BAD cached */
|
||||
+ fixed_address_encode(repinfo->c->buffer,
|
||||
+ LDNS_RCODE_NOERROR, qinfo, id, flags, edns,
|
||||
+ worker->env.cfg->redirect_bogus_ipv4);
|
||||
+ } else if (qinfo->qtype == LDNS_RR_TYPE_AAAA &&
|
||||
+ worker->env.cfg->redirect_bogus_ipv6) {
|
||||
+ fixed_address_encode(repinfo->c->buffer,
|
||||
+ LDNS_RCODE_NOERROR, qinfo, id, flags, edns,
|
||||
+ worker->env.cfg->redirect_bogus_ipv6);
|
||||
+ } else {
|
||||
+ error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
+ qinfo, id, flags, edns);
|
||||
+ }
|
||||
rrset_array_unlock_touch(worker->env.rrset_cache,
|
||||
worker->scratchpad, rep->ref, rep->rrset_count);
|
||||
if(worker->stats.extended) {
|
||||
Index: doc/unbound.conf.5.in
|
||||
===================================================================
|
||||
--- doc/unbound.conf.5.in (revision 4191)
|
||||
+++ doc/unbound.conf.5.in (working copy)
|
||||
@@ -1244,6 +1244,18 @@
|
||||
This can make ordinary queries complete (if repeatedly queried for),
|
||||
and enter the cache, whilst also mitigating the traffic flow by the
|
||||
factor given.
|
||||
+.TP 5
|
||||
+.B redirect-bogus-ipv4: \fI<IPv4 address>
|
||||
+Set a fixed address for DNSSEC failures that are cached
|
||||
+Instead of responding to A queries with SERVFAIL, respond
|
||||
+with NOERROR and the address specified here
|
||||
+The TTL of the response will be 5 seconds
|
||||
+.TP 5
|
||||
+.B redirect-bogus-ipv6: \fI<IPv4 address>
|
||||
+Set a fixed address for DNSSEC failures that are cached
|
||||
+Instead of responding to AAAA queries with SERVFAIL, respond
|
||||
+with NOERROR and the address specified here
|
||||
+The TTL of the response will be 5 seconds
|
||||
.SS "Remote Control Options"
|
||||
In the
|
||||
.B remote\-control:
|
||||
Index: services/mesh.c
|
||||
===================================================================
|
||||
--- services/mesh.c (revision 4191)
|
||||
+++ services/mesh.c (working copy)
|
||||
@@ -1006,6 +1006,7 @@
|
||||
struct timeval end_time;
|
||||
struct timeval duration;
|
||||
int secure;
|
||||
+ int bogus_override = 0;
|
||||
/* Copy the client's EDNS for later restore, to make sure the edns
|
||||
* compare is with the correct edns options. */
|
||||
struct edns_data edns_bak = r->edns;
|
||||
@@ -1016,6 +1017,7 @@
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
if(m->s.env->cfg->stat_extended)
|
||||
m->s.env->mesh->ans_bogus++;
|
||||
+ bogus_override = 1;
|
||||
}
|
||||
if(rep && rep->security == sec_status_secure)
|
||||
secure = 1;
|
||||
@@ -1047,17 +1049,34 @@
|
||||
} else if(rcode) {
|
||||
m->s.qinfo.qname = r->qname;
|
||||
m->s.qinfo.local_alias = r->local_alias;
|
||||
- if(rcode == LDNS_RCODE_SERVFAIL) {
|
||||
- if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
|
||||
- rep, rcode, &r->edns, m->s.region))
|
||||
- r->edns.opt_list = NULL;
|
||||
- } else {
|
||||
- if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode,
|
||||
- &r->edns, m->s.region))
|
||||
- r->edns.opt_list = NULL;
|
||||
+ if(bogus_override && m->s.qinfo.qtype == LDNS_RR_TYPE_A &&
|
||||
+ m->s.env->cfg->redirect_bogus_ipv4) {
|
||||
+ fixed_address_encode(r->query_reply.c->buffer,
|
||||
+ LDNS_RCODE_NOERROR, &m->s.qinfo, r->qid,
|
||||
+ r->qflags, &r->edns,
|
||||
+ m->s.env->cfg->redirect_bogus_ipv4);
|
||||
+ } else if(bogus_override &&
|
||||
+ m->s.qinfo.qtype == LDNS_RR_TYPE_AAAA &&
|
||||
+ m->s.env->cfg->redirect_bogus_ipv6) {
|
||||
+ fixed_address_encode(r->query_reply.c->buffer,
|
||||
+ LDNS_RCODE_NOERROR, &m->s.qinfo, r->qid,
|
||||
+ r->qflags, &r->edns,
|
||||
+ m->s.env->cfg->redirect_bogus_ipv6);
|
||||
+ } else {
|
||||
+ if(rcode == LDNS_RCODE_SERVFAIL) {
|
||||
+ if(!inplace_cb_reply_servfail_call(m->s.env,
|
||||
+ &m->s.qinfo, &m->s,
|
||||
+ rep, rcode, &r->edns, m->s.region))
|
||||
+ r->edns.opt_list = NULL;
|
||||
+ } else {
|
||||
+ if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo,
|
||||
+ &m->s, rep, rcode, &r->edns,
|
||||
+ m->s.region))
|
||||
+ r->edns.opt_list = NULL;
|
||||
+ }
|
||||
+ error_encode(r->query_reply.c->buffer, rcode,
|
||||
+ &m->s.qinfo, r->qid, r->qflags, &r->edns);
|
||||
}
|
||||
- error_encode(r->query_reply.c->buffer, rcode, &m->s.qinfo,
|
||||
- r->qid, r->qflags, &r->edns);
|
||||
comm_point_send_reply(&r->query_reply);
|
||||
} else {
|
||||
size_t udp_size = r->edns.udp_size;
|
||||
Index: util/config_file.c
|
||||
===================================================================
|
||||
--- util/config_file.c (revision 4191)
|
||||
+++ util/config_file.c (working copy)
|
||||
@@ -273,6 +273,8 @@
|
||||
cfg->ratelimit_factor = 10;
|
||||
cfg->qname_minimisation = 0;
|
||||
cfg->qname_minimisation_strict = 0;
|
||||
+ cfg->redirect_bogus_ipv4 = NULL;
|
||||
+ cfg->redirect_bogus_ipv6 = NULL;
|
||||
cfg->shm_enable = 0;
|
||||
cfg->shm_key = 11777;
|
||||
cfg->dnscrypt = 0;
|
||||
@@ -602,6 +604,10 @@
|
||||
}
|
||||
oi[cfg->num_out_ifs++] = d;
|
||||
cfg->out_ifs = oi;
|
||||
+ } else if (strcmp(opt, "redirect-bogus-ipv4:") == 0) {
|
||||
+ cfg->redirect_bogus_ipv4 = strdup(val);
|
||||
+ } else if (strcmp(opt, "redirect-bogus-ipv6:") == 0) {
|
||||
+ cfg->redirect_bogus_ipv6 = strdup(val);
|
||||
} else {
|
||||
/* unknown or unsupported (from the set_option interface):
|
||||
* interface, outgoing-interface, access-control,
|
||||
@@ -1250,6 +1256,12 @@
|
||||
free(cfg->dnstap_version);
|
||||
config_deldblstrlist(cfg->ratelimit_for_domain);
|
||||
config_deldblstrlist(cfg->ratelimit_below_domain);
|
||||
+ if (cfg->redirect_bogus_ipv4) {
|
||||
+ free(cfg->redirect_bogus_ipv4);
|
||||
+ }
|
||||
+ if (cfg->redirect_bogus_ipv6) {
|
||||
+ free(cfg->redirect_bogus_ipv6);
|
||||
+ }
|
||||
#ifdef USE_IPSECMOD
|
||||
free(cfg->ipsecmod_hook);
|
||||
config_delstrlist(cfg->ipsecmod_whitelist);
|
||||
Index: util/config_file.h
|
||||
===================================================================
|
||||
--- util/config_file.h (revision 4191)
|
||||
+++ util/config_file.h (working copy)
|
||||
@@ -444,6 +444,9 @@
|
||||
/** minimise QNAME in strict mode, minimise according to RFC.
|
||||
* Do not apply fallback */
|
||||
int qname_minimisation_strict;
|
||||
+ /** construct fake responses for DNSSEC failures */
|
||||
+ char *redirect_bogus_ipv4;
|
||||
+ char *redirect_bogus_ipv6;
|
||||
/** SHM data - true if shm is enabled */
|
||||
int shm_enable;
|
||||
/** SHM data - key for the shm */
|
||||
Index: util/configlexer.lex
|
||||
===================================================================
|
||||
--- util/configlexer.lex (revision 4191)
|
||||
+++ util/configlexer.lex (working copy)
|
||||
@@ -410,6 +410,8 @@
|
||||
response-ip-tag{COLON} { YDVAR(2, VAR_RESPONSE_IP_TAG) }
|
||||
response-ip{COLON} { YDVAR(2, VAR_RESPONSE_IP) }
|
||||
response-ip-data{COLON} { YDVAR(2, VAR_RESPONSE_IP_DATA) }
|
||||
+redirect-bogus-ipv4{COLON} { YDVAR(1, VAR_REDIRECT_BOGUS_IPV4) }
|
||||
+redirect-bogus-ipv6{COLON} { YDVAR(1, VAR_REDIRECT_BOGUS_IPV6) }
|
||||
dnscrypt{COLON} { YDVAR(0, VAR_DNSCRYPT) }
|
||||
dnscrypt-enable{COLON} { YDVAR(1, VAR_DNSCRYPT_ENABLE) }
|
||||
dnscrypt-port{COLON} { YDVAR(1, VAR_DNSCRYPT_PORT) }
|
||||
Index: util/configparser.y
|
||||
===================================================================
|
||||
--- util/configparser.y (revision 4191)
|
||||
+++ util/configparser.y (working copy)
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
+#include "sldns/str2wire.h"
|
||||
#include "util/configyyrename.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
@@ -141,6 +142,7 @@
|
||||
%token VAR_ACCESS_CONTROL_TAG_DATA VAR_VIEW VAR_ACCESS_CONTROL_VIEW
|
||||
%token VAR_VIEW_FIRST VAR_SERVE_EXPIRED VAR_FAKE_DSA VAR_FAKE_SHA1
|
||||
%token VAR_LOG_IDENTITY VAR_HIDE_TRUSTANCHOR VAR_TRUST_ANCHOR_SIGNALING
|
||||
+%token VAR_REDIRECT_BOGUS_IPV4 VAR_REDIRECT_BOGUS_IPV6
|
||||
%token VAR_USE_SYSTEMD VAR_SHM_ENABLE VAR_SHM_KEY
|
||||
%token VAR_DNSCRYPT VAR_DNSCRYPT_ENABLE VAR_DNSCRYPT_PORT VAR_DNSCRYPT_PROVIDER
|
||||
%token VAR_DNSCRYPT_SECRET_KEY VAR_DNSCRYPT_PROVIDER_CERT
|
||||
@@ -228,6 +230,7 @@
|
||||
server_access_control_tag_data | server_access_control_view |
|
||||
server_qname_minimisation_strict | server_serve_expired |
|
||||
server_fake_dsa | server_log_identity | server_use_systemd |
|
||||
+ server_redirect_bogus_ipv4 | server_redirect_bogus_ipv6 |
|
||||
server_response_ip_tag | server_response_ip | server_response_ip_data |
|
||||
server_shm_enable | server_shm_key | server_fake_sha1 |
|
||||
server_hide_trustanchor | server_trust_anchor_signaling |
|
||||
@@ -1873,6 +1876,34 @@
|
||||
#endif
|
||||
}
|
||||
;
|
||||
+server_redirect_bogus_ipv4: VAR_REDIRECT_BOGUS_IPV4 STRING_ARG
|
||||
+ {
|
||||
+ uint8_t data[4];
|
||||
+ size_t data_len = 4;
|
||||
+ OUTYY(("P(name:%s)\n", $2));
|
||||
+ if(cfg_parser->cfg->redirect_bogus_ipv4) {
|
||||
+ yyerror("redirect-bogus-ipv4, can only use one address");
|
||||
+ }
|
||||
+ if(sldns_str2wire_a_buf($2, data, &data_len) != LDNS_WIREPARSE_ERR_OK) {
|
||||
+ yyerror("redirect-bogus-ipv4, not a valid IPv4 address");
|
||||
+ }
|
||||
+ free(cfg_parser->cfg->redirect_bogus_ipv4);
|
||||
+ cfg_parser->cfg->redirect_bogus_ipv4 = $2;
|
||||
+ }
|
||||
+server_redirect_bogus_ipv6: VAR_REDIRECT_BOGUS_IPV6 STRING_ARG
|
||||
+ {
|
||||
+ uint8_t data[16];
|
||||
+ size_t data_len = 16;
|
||||
+ OUTYY(("P(name:%s)\n", $2));
|
||||
+ if(cfg_parser->cfg->redirect_bogus_ipv6) {
|
||||
+ yyerror("redirect-bogus-ipv6, can only use one address");
|
||||
+ }
|
||||
+ if(sldns_str2wire_aaaa_buf($2, data, &data_len) != LDNS_WIREPARSE_ERR_OK) {
|
||||
+ yyerror("redirect-bogus-ipv6, not a valid IPv6 address");
|
||||
+ }
|
||||
+ free(cfg_parser->cfg->redirect_bogus_ipv6);
|
||||
+ cfg_parser->cfg->redirect_bogus_ipv6 = $2;
|
||||
+ }
|
||||
stub_name: VAR_NAME STRING_ARG
|
||||
{
|
||||
OUTYY(("P(name:%s)\n", $2));
|
||||
Index: util/data/msgencode.c
|
||||
===================================================================
|
||||
--- util/data/msgencode.c (revision 4191)
|
||||
+++ util/data/msgencode.c (working copy)
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "util/regional.h"
|
||||
#include "util/net_help.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
+#include "sldns/str2wire.h"
|
||||
#include "services/localzone.h"
|
||||
|
||||
/** return code that means the function ran out of memory. negative so it does
|
||||
@@ -914,3 +915,63 @@
|
||||
attach_edns_record(buf, &es);
|
||||
}
|
||||
}
|
||||
+
|
||||
+void
|
||||
+fixed_address_encode(sldns_buffer* buf, int r, struct query_info* qinfo,
|
||||
+ uint16_t qid, uint16_t qflags, struct edns_data* edns, char* data)
|
||||
+{
|
||||
+ uint16_t flags;
|
||||
+ uint8_t addr_data[16];
|
||||
+ size_t addr_len = 16;
|
||||
+ if (qinfo->qtype == LDNS_RR_TYPE_A) {
|
||||
+ sldns_str2wire_a_buf(data, addr_data, &addr_len);
|
||||
+ } else if (qinfo->qtype == LDNS_RR_TYPE_AAAA) {
|
||||
+ sldns_str2wire_aaaa_buf(data, addr_data, &addr_len);
|
||||
+ } else {
|
||||
+ return error_encode(buf, LDNS_RCODE_NOERROR, qinfo, qid, qflags, edns);
|
||||
+ }
|
||||
+ sldns_buffer_clear(buf);
|
||||
+ sldns_buffer_write(buf, &qid, sizeof(uint16_t));
|
||||
+ flags = (uint16_t)(BIT_QR | BIT_RA | r); /* QR and retcode*/
|
||||
+ flags |= (qflags & (BIT_RD|BIT_CD)); /* copy RD and CD bit */
|
||||
+ sldns_buffer_write_u16(buf, flags);
|
||||
+ if(qinfo) flags = 1;
|
||||
+ else flags = 0;
|
||||
+ sldns_buffer_write_u16(buf, flags);
|
||||
+ sldns_buffer_write_u16(buf, 1);
|
||||
+ flags = 0;
|
||||
+ sldns_buffer_write(buf, &flags, sizeof(uint16_t));
|
||||
+ sldns_buffer_write(buf, &flags, sizeof(uint16_t));
|
||||
+ if(qinfo) {
|
||||
+ // query
|
||||
+ if(sldns_buffer_current(buf) == qinfo->qname)
|
||||
+ sldns_buffer_skip(buf, (ssize_t)qinfo->qname_len);
|
||||
+ else sldns_buffer_write(buf, qinfo->qname, qinfo->qname_len);
|
||||
+ sldns_buffer_write_u16(buf, qinfo->qtype);
|
||||
+ sldns_buffer_write_u16(buf, qinfo->qclass);
|
||||
+ // faked answer
|
||||
+ if(sldns_buffer_current(buf) == qinfo->qname)
|
||||
+ sldns_buffer_skip(buf, (ssize_t)qinfo->qname_len);
|
||||
+ else sldns_buffer_write(buf, qinfo->qname, qinfo->qname_len);
|
||||
+ sldns_buffer_write_u16(buf, qinfo->qtype);
|
||||
+ sldns_buffer_write_u16(buf, qinfo->qclass);
|
||||
+ sldns_buffer_write_u16(buf, 0);
|
||||
+ // TTL. Should we make this configurable too?
|
||||
+ sldns_buffer_write_u16(buf, 5);
|
||||
+ sldns_buffer_write_u16(buf, addr_len);
|
||||
+ sldns_buffer_write(buf, addr_data, addr_len);
|
||||
+ fflush(stderr);
|
||||
+ }
|
||||
+ sldns_buffer_flip(buf);
|
||||
+ if(edns) {
|
||||
+ struct edns_data es = *edns;
|
||||
+ es.edns_version = EDNS_ADVERTISED_VERSION;
|
||||
+ es.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
+ es.ext_rcode = 0;
|
||||
+ es.bits &= EDNS_DO;
|
||||
+ if(sldns_buffer_limit(buf) + calc_edns_field_size(&es) >
|
||||
+ edns->udp_size)
|
||||
+ return;
|
||||
+ attach_edns_record(buf, &es);
|
||||
+ }
|
||||
+}
|
||||
Index: util/data/msgencode.h
|
||||
===================================================================
|
||||
--- util/data/msgencode.h (revision 4191)
|
||||
+++ util/data/msgencode.h (working copy)
|
||||
@@ -128,4 +128,20 @@
|
||||
void error_encode(struct sldns_buffer* pkt, int r, struct query_info* qinfo,
|
||||
uint16_t qid, uint16_t qflags, struct edns_data* edns);
|
||||
|
||||
+/**
|
||||
+ * Encode a fixed address response.
|
||||
+ * This is a fake answer to either an A or AAA query
|
||||
+ *
|
||||
+ * It will answer with that address
|
||||
+ *
|
||||
+ * @param pkt: where to store the packet.
|
||||
+ * @param r: RCODE value to encode.
|
||||
+ * @param qinfo: if not NULL, the query is included.
|
||||
+ * @param qid: query ID to set in packet. network order.
|
||||
+ * @param qflags: original query flags (to copy RD and CD bits). host order.
|
||||
+ * @param edns: if not NULL, this is the query edns info,
|
||||
+ * and an edns reply is attached. Only attached if EDNS record fits reply.
|
||||
+ */
|
||||
+void fixed_address_encode(struct sldns_buffer* pkt, int r, struct query_info* qinfo,
|
||||
+ uint16_t qid, uint16_t qflags, struct edns_data* edns, char* address);
|
||||
#endif /* UTIL_DATA_MSGENCODE_H */
|
||||
Binary file not shown.
@@ -0,0 +1,148 @@
|
||||
>From cc9b927f8f29d989ddb8415fe6508a538546abca Mon Sep 17 00:00:00 2001
|
||||
From: Jacob Hoffman-Andrews <github@hoffman-andrews.com>
|
||||
Date: Wed, 2 Jan 2019 22:52:51 -0800
|
||||
Subject: [PATCH] Add unbound-fuzzme.
|
||||
|
||||
This is a small program that simply parses a packet provided on stdout,
|
||||
for the purposes of fuzzing.
|
||||
---
|
||||
.gitignore | 1 +
|
||||
Makefile.in | 22 ++++++++++++++++++++--
|
||||
smallapp/unbound-fuzzme.c | 38 ++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 59 insertions(+), 2 deletions(-)
|
||||
create mode 100644 smallapp/unbound-fuzzme.c
|
||||
|
||||
diff --git a/.gitignore b/.gitignore
|
||||
index f4527fd8..6163f905 100644
|
||||
--- a/.gitignore
|
||||
+++ b/.gitignore
|
||||
@@ -24,6 +24,7 @@
|
||||
/unbound-checkconf
|
||||
/unbound-control
|
||||
/unbound-control-setup
|
||||
+/unbound-fuzzme
|
||||
/unbound-host
|
||||
/unbound.h
|
||||
/asynclook
|
||||
diff --git a/Makefile.in b/Makefile.in
|
||||
index af5b10f6..dacf1ab5 100644
|
||||
--- a/Makefile.in
|
||||
+++ b/Makefile.in
|
||||
@@ -177,6 +177,10 @@ shm_main.lo remote.lo stats.lo unbound.lo \
|
||||
worker.lo @WIN_DAEMON_OBJ@
|
||||
DAEMON_OBJ_LINK=$(DAEMON_OBJ) $(COMMON_OBJ_ALL_SYMBOLS) $(SLDNS_OBJ) \
|
||||
$(COMPAT_OBJ) @WIN_DAEMON_OBJ_LINK@
|
||||
+FUZZME_SRC=smallapp/unbound-fuzzme.c
|
||||
+FUZZME_OBJ=unbound-fuzzme.lo
|
||||
+FUZZME_OBJ_LINK=$(FUZZME_OBJ) worker_cb.lo $(COMMON_OBJ_ALL_SYMBOLS) $(SLDNS_OBJ) \
|
||||
+$(COMPAT_OBJ)
|
||||
CHECKCONF_SRC=smallapp/unbound-checkconf.c smallapp/worker_cb.c
|
||||
CHECKCONF_OBJ=unbound-checkconf.lo worker_cb.lo
|
||||
CHECKCONF_OBJ_LINK=$(CHECKCONF_OBJ) $(COMMON_OBJ_ALL_SYMBOLS) $(SLDNS_OBJ) \
|
||||
@@ -252,6 +256,7 @@ RSRC_OBJ=rsrc_svcinst.o rsrc_svcuninst.o rsrc_anchorupd.o rsrc_unbound.o \
|
||||
rsrc_unbound_checkconf.o
|
||||
|
||||
ALL_SRC=$(COMMON_SRC) $(UNITTEST_SRC) $(DAEMON_SRC) \
|
||||
+ $(FUZZME_SRC) \
|
||||
$(TESTBOUND_SRC) $(LOCKVERIFY_SRC) $(PKTVIEW_SRC) \
|
||||
$(MEMSTATS_SRC) $(CHECKCONF_SRC) $(LIBUNBOUND_SRC) $(HOST_SRC) \
|
||||
$(ASYNCLOOK_SRC) $(STREAMTCP_SRC) $(PERF_SRC) $(DELAYER_SRC) \
|
||||
@@ -259,6 +264,7 @@ ALL_SRC=$(COMMON_SRC) $(UNITTEST_SRC) $(DAEMON_SRC) \
|
||||
$(PYTHONMOD_SRC) $(PYUNBOUND_SRC) $(WIN_DAEMON_THE_SRC)\
|
||||
$(SVCINST_SRC) $(SVCUNINST_SRC) $(ANCHORUPD_SRC) $(SLDNS_SRC)
|
||||
ALL_OBJ=$(COMMON_OBJ) $(UNITTEST_OBJ) $(DAEMON_OBJ) \
|
||||
+ $(FUZZME_OBJ) \
|
||||
$(TESTBOUND_OBJ) $(LOCKVERIFY_OBJ) $(PKTVIEW_OBJ) \
|
||||
$(MEMSTATS_OBJ) $(CHECKCONF_OBJ) $(LIBUNBOUND_OBJ) $(HOST_OBJ) \
|
||||
$(ASYNCLOOK_OBJ) $(STREAMTCP_OBJ) $(PERF_OBJ) $(DELAYER_OBJ) \
|
||||
@@ -274,7 +280,7 @@ LINK_LIB=$(LIBTOOL) --tag=CC --mode=link $(CC) $(RUNTIME_PATH) $(CPPFLAGS) $(CFL
|
||||
|
||||
all: $(COMMON_OBJ) $(ALLTARGET)
|
||||
|
||||
-alltargets: unbound$(EXEEXT) unbound-checkconf$(EXEEXT) lib unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup $(WINAPPS) $(PYUNBOUND_TARGET)
|
||||
+alltargets: unbound$(EXEEXT) unbound-checkconf$(EXEEXT) lib unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup unbound-fuzzme$(EXEEXT) $(WINAPPS) $(PYUNBOUND_TARGET)
|
||||
|
||||
# compat with BSD make, register suffix, and an implicit rule to actualise it.
|
||||
.SUFFIXES: .lo
|
||||
@@ -325,6 +331,9 @@ libunbound.la: $(LIBUNBOUND_OBJ_LINK)
|
||||
unbound$(EXEEXT): $(DAEMON_OBJ_LINK) libunbound.la
|
||||
$(LINK) -o $@ $(DAEMON_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS)
|
||||
|
||||
+unbound-fuzzme$(EXEEXT): $(FUZZME_OBJ_LINK) libunbound.la
|
||||
+ $(LINK) -o $@ $(FUZZME_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS)
|
||||
+
|
||||
unbound-checkconf$(EXEEXT): $(CHECKCONF_OBJ_LINK) libunbound.la
|
||||
$(LINK) -o $@ $(CHECKCONF_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS)
|
||||
|
||||
@@ -447,7 +456,7 @@ util/configparser.c util/configparser.h: $(srcdir)/util/configparser.y
|
||||
|
||||
clean:
|
||||
rm -f *.o *.d *.lo *~ tags
|
||||
- rm -f unbound$(EXEEXT) unbound-checkconf$(EXEEXT) unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup libunbound.la unbound.h
|
||||
+ rm -f unbound$(EXEEXT) unbound-checkconf$(EXEEXT) unbound-fuzzme$(EXEEXT) unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup libunbound.la unbound.h
|
||||
rm -f $(ALL_SRC:.c=.lint)
|
||||
rm -f _unbound.la libunbound/python/libunbound_wrap.c libunbound/python/unbound.py pythonmod/interface.h pythonmod/unboundmodule.py
|
||||
rm -rf autom4te.cache .libs build doc/html doc/xml
|
||||
@@ -1183,6 +1192,15 @@ stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(s
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
|
||||
$(srcdir)/util/rtt.h $(srcdir)/services/authzone.h $(srcdir)/validator/val_kcache.h \
|
||||
$(srcdir)/validator/val_neg.h
|
||||
+unbound-fuzzme.lo unbound-fuzzme.o: $(srcdir)/smallapp/unbound-fuzzme.c \
|
||||
+ $(srcdir)/util/locks.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
|
||||
+ $(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h \
|
||||
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h $(srcdir)/services/listen_dnsport.h \
|
||||
+ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/services/cache/rrset.h \
|
||||
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
|
||||
+ $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/fptr_wlist.h \
|
||||
+ $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
|
||||
+ $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/net_help.h $(srcdir)/util/ub_event.h
|
||||
unbound.lo unbound.o: $(srcdir)/daemon/unbound.c config.h $(srcdir)/util/log.h $(srcdir)/daemon/daemon.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/daemon/remote.h \
|
||||
diff --git a/smallapp/unbound-fuzzme.c b/smallapp/unbound-fuzzme.c
|
||||
new file mode 100644
|
||||
index 00000000..74ae5204
|
||||
--- /dev/null
|
||||
+++ b/smallapp/unbound-fuzzme.c
|
||||
@@ -0,0 +1,38 @@
|
||||
+/*
|
||||
+ * unbound-fuzzme.c - parse a packet provided on stdin (for fuzzing).
|
||||
+ *
|
||||
+ */
|
||||
+#include "config.h"
|
||||
+#include "util/regional.h"
|
||||
+#include "util/fptr_wlist.h"
|
||||
+#include "sldns/sbuffer.h"
|
||||
+
|
||||
+#define SZ 10000
|
||||
+
|
||||
+int main() {
|
||||
+ char buffer[SZ];
|
||||
+ size_t n_read = fread(buffer, 1, SZ, stdin);
|
||||
+ if (n_read == SZ) {
|
||||
+ printf("input too big\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ sldns_buffer *pkt = sldns_buffer_new(n_read);
|
||||
+ sldns_buffer_init_frm_data(pkt, buffer, n_read);
|
||||
+
|
||||
+ struct regional *region = regional_create();
|
||||
+
|
||||
+ struct msg_parse* prs;
|
||||
+ struct edns_data edns;
|
||||
+ prs = (struct msg_parse*)malloc(sizeof(struct msg_parse));
|
||||
+ if(!prs) {
|
||||
+ printf("out of memory on incoming message\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ memset(prs, 0, sizeof(*prs));
|
||||
+ memset(&edns, 0, sizeof(edns));
|
||||
+ sldns_buffer_set_position(pkt, 0);
|
||||
+ if(parse_packet(pkt, prs, region) != LDNS_RCODE_NOERROR) {
|
||||
+ printf("parse error\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import hashlib
|
||||
import sys
|
||||
import struct
|
||||
import socket
|
||||
import time
|
||||
from optparse import OptionParser
|
||||
|
||||
import dns.message
|
||||
import dns.name
|
||||
import dns.rdataclass
|
||||
import dns.rdatatype
|
||||
|
||||
def _calc_hashkey(qname, secret, qtype):
|
||||
qclass = 'IN' # CLASS is fixed for simplicity
|
||||
hobj = hashlib.sha256()
|
||||
hobj.update(dns.name.from_text(qname).to_wire())
|
||||
hobj.update(struct.pack('HH',
|
||||
socket.htons(dns.rdatatype.from_text(qtype)),
|
||||
socket.htons(dns.rdataclass.from_text(qclass))))
|
||||
hobj.update(secret)
|
||||
return hobj.hexdigest().upper()
|
||||
|
||||
def _redis_get(options, key):
|
||||
import redis
|
||||
return redis.Redis(options.address, int(options.port)).get(key)
|
||||
|
||||
def _dump_value(options, qname, key, value):
|
||||
print(';; query=%s/IN/%s' % (qname, options.qtype))
|
||||
print(';; key=%s' % key)
|
||||
if value is None:
|
||||
print(';; no value')
|
||||
return
|
||||
if len(value) < 16:
|
||||
print(';; broken value, short length: %d' % len(value))
|
||||
return
|
||||
now = int(time.time())
|
||||
timestamp = struct.unpack('!Q', value[-16:-8])[0]
|
||||
expire = struct.unpack('!Q', value[-8:])[0]
|
||||
print(';; Now=%d, TimeStamp=%d, Expire=%d, TTL=%d' %
|
||||
(now, timestamp, expire, max(expire - now, 0)))
|
||||
print(dns.message.from_wire(value[:-16]))
|
||||
|
||||
def main():
|
||||
parser = OptionParser(usage='usage: %prog [options] query_name')
|
||||
parser.add_option("-a", "--address", dest="address", action="store",
|
||||
default='127.0.0.1', help="backend-server address",
|
||||
metavar='ADDRESS')
|
||||
parser.add_option("-b", "--backend", dest="backend", action="store",
|
||||
default='redis', help="backend name",
|
||||
metavar='BACKEND')
|
||||
parser.add_option("-p", "--port", dest="port", action="store",
|
||||
default='6379', help="backend-server port",
|
||||
metavar='PORT')
|
||||
parser.add_option("-s", "--secret", dest="secret", action="store",
|
||||
default='default', help="secret seed", metavar='SECRET')
|
||||
parser.add_option("-t", "--qtype", dest="qtype", action="store",
|
||||
default='A', help="query RR type", metavar='QTYPE')
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
if len(args) < 1:
|
||||
parser.error('qname is missing')
|
||||
if options.backend == 'redis':
|
||||
get_func = _redis_get
|
||||
else:
|
||||
raise Exception('unknown backend name: %s\n' % options.backend)
|
||||
key = _calc_hashkey(args[0], options.secret, options.qtype)
|
||||
value = get_func(options, key)
|
||||
_dump_value(options, args[0], key, value)
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main()
|
||||
except Exception as e:
|
||||
sys.stderr.write('%s\n' % e)
|
||||
exit(1)
|
||||
@@ -39,13 +39,13 @@ start() {
|
||||
# setup root jail
|
||||
if [ -s /etc/localtime ]; then
|
||||
[ -d ${rootdir}/etc ] || mkdir -p ${rootdir}/etc ;
|
||||
if [ ! -e ${rootdir}/etc/localtime ] || /usr/bin/cmp -s /etc/localtime ${rootdir}/etc/localtime; then
|
||||
if [ ! -e ${rootdir}/etc/localtime ] || ! /usr/bin/cmp -s /etc/localtime ${rootdir}/etc/localtime; then
|
||||
cp -fp /etc/localtime ${rootdir}/etc/localtime
|
||||
fi;
|
||||
fi;
|
||||
if [ -s /etc/resolv.conf ]; then
|
||||
[ -d ${rootdir}/etc ] || mkdir -p ${rootdir}/etc ;
|
||||
if [ ! -e ${rootdir}/etc/resolv.conf ] || /usr/bin/cmp -s /etc/resolv.conf ${rootdir}/etc/resolv.conf; then
|
||||
if [ ! -e ${rootdir}/etc/resolv.conf ] || ! /usr/bin/cmp -s /etc/resolv.conf ${rootdir}/etc/resolv.conf; then
|
||||
cp -fp /etc/resolv.conf ${rootdir}/etc/resolv.conf
|
||||
fi;
|
||||
fi;
|
||||
@@ -54,10 +54,10 @@ start() {
|
||||
[ -e ${rootdir}/dev/log ] || touch ${rootdir}/dev/log
|
||||
mount --bind -n /dev/log ${rootdir}/dev/log >/dev/null 2>&1;
|
||||
fi;
|
||||
if ! egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/random' /proc/mounts; then
|
||||
if ! egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/urandom' /proc/mounts; then
|
||||
[ -d ${rootdir}/dev ] || mkdir -p ${rootdir}/dev ;
|
||||
[ -e ${rootdir}/dev/random ] || touch ${rootdir}/dev/random
|
||||
mount --bind -n /dev/random ${rootdir}/dev/random >/dev/null 2>&1;
|
||||
[ -e ${rootdir}/dev/urandom ] || touch ${rootdir}/dev/urandom
|
||||
mount --bind -n /dev/urandom ${rootdir}/dev/urandom >/dev/null 2>&1;
|
||||
fi;
|
||||
|
||||
# if not running, start it up here
|
||||
@@ -78,8 +78,8 @@ stop() {
|
||||
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
|
||||
umount ${rootdir}/dev/log >/dev/null 2>&1
|
||||
fi;
|
||||
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/random' /proc/mounts; then
|
||||
umount ${rootdir}/dev/random >/dev/null 2>&1
|
||||
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/urandom' /proc/mounts; then
|
||||
umount ${rootdir}/dev/urandom >/dev/null 2>&1
|
||||
fi;
|
||||
return $retval
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ start() {
|
||||
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 /dev/urandom ${rootdir}/dev/urandom >/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
|
||||
@@ -58,7 +58,7 @@ stop() {
|
||||
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
|
||||
for mountfile in /dev/log /dev/urandom /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
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
[Unit]
|
||||
Description=Validating, recursive, and caching DNS resolver
|
||||
Documentation=man:unbound(8)
|
||||
After=network.target
|
||||
Before=network-online.target nss-lookup.target
|
||||
Wants=nss-lookup.target
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
[Service]
|
||||
ExecReload=+/bin/kill -HUP $MAINPID
|
||||
ExecStart=@UNBOUND_SBIN_DIR@/unbound -d
|
||||
NotifyAccess=main
|
||||
Type=notify
|
||||
CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_RAW
|
||||
MemoryDenyWriteExecute=true
|
||||
NoNewPrivileges=true
|
||||
PrivateDevices=true
|
||||
PrivateTmp=true
|
||||
ProtectHome=true
|
||||
ProtectControlGroups=true
|
||||
ProtectKernelModules=true
|
||||
ProtectSystem=strict
|
||||
ReadWritePaths=/run @UNBOUND_RUN_DIR@ @UNBOUND_CHROOT_DIR@
|
||||
TemporaryFileSystem=@UNBOUND_CHROOT_DIR@/dev:ro
|
||||
TemporaryFileSystem=@UNBOUND_CHROOT_DIR@/run:ro
|
||||
BindReadOnlyPaths=-/run/systemd/notify:@UNBOUND_CHROOT_DIR@/run/systemd/notify
|
||||
BindPaths=-@UNBOUND_PIDFILE@:@UNBOUND_CHROOT_DIR@@UNBOUND_PIDFILE@
|
||||
BindReadOnlyPaths=-/dev/urandom:@UNBOUND_CHROOT_DIR@/dev/urandom
|
||||
BindPaths=-/dev/log:@UNBOUND_CHROOT_DIR@/dev/log
|
||||
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
|
||||
RestrictRealtime=true
|
||||
SystemCallArchitectures=native
|
||||
SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module mount @obsolete @resources
|
||||
RestrictNamespaces=yes
|
||||
LockPersonality=yes
|
||||
RestrictSUIDSGID=yes
|
||||
@@ -0,0 +1,6 @@
|
||||
[Socket]
|
||||
ListenDatagram=127.0.0.1:1153
|
||||
ListenStream=127.0.0.1:1153
|
||||
# ListenStream=@UNBOUND_RUN_DIR@/control
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
@@ -111,6 +111,8 @@ acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
|
||||
control = acl_refuse_non_local;
|
||||
else if(strcmp(s2, "allow_snoop") == 0)
|
||||
control = acl_allow_snoop;
|
||||
else if(strcmp(s2, "allow_setrd") == 0)
|
||||
control = acl_allow_setrd;
|
||||
else {
|
||||
log_err("access control type %s unknown", str);
|
||||
return 0;
|
||||
|
||||
+4
-2
@@ -63,7 +63,9 @@ enum acl_access {
|
||||
/** allow full access for recursion (+RD) queries */
|
||||
acl_allow,
|
||||
/** allow full access for all queries, recursion and cache snooping */
|
||||
acl_allow_snoop
|
||||
acl_allow_snoop,
|
||||
/** allow full access for recursion queries and set RD flag regardless of request */
|
||||
acl_allow_setrd
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -76,7 +78,7 @@ struct acl_list {
|
||||
* Tree of the addresses that are allowed/blocked.
|
||||
* contents of type acl_addr.
|
||||
*/
|
||||
rbtree_t tree;
|
||||
rbtree_type tree;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+23
-21
@@ -62,7 +62,7 @@
|
||||
|
||||
/** dump one rrset zonefile line */
|
||||
static int
|
||||
dump_rrset_line(SSL* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i)
|
||||
dump_rrset_line(RES* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i)
|
||||
{
|
||||
char s[65535];
|
||||
if(!packed_rr_to_string(k, i, now, s, sizeof(s))) {
|
||||
@@ -73,12 +73,13 @@ dump_rrset_line(SSL* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i)
|
||||
|
||||
/** dump rrset key and data info */
|
||||
static int
|
||||
dump_rrset(SSL* ssl, struct ub_packed_rrset_key* k,
|
||||
dump_rrset(RES* ssl, struct ub_packed_rrset_key* k,
|
||||
struct packed_rrset_data* d, time_t now)
|
||||
{
|
||||
size_t i;
|
||||
/* rd lock held by caller */
|
||||
if(!k || !d) return 1;
|
||||
if(k->id == 0) return 1; /* deleted */
|
||||
if(d->ttl < now) return 1; /* expired */
|
||||
|
||||
/* meta line */
|
||||
@@ -98,7 +99,7 @@ dump_rrset(SSL* ssl, struct ub_packed_rrset_key* k,
|
||||
|
||||
/** dump lruhash rrset cache */
|
||||
static int
|
||||
dump_rrset_lruhash(SSL* ssl, struct lruhash* h, time_t now)
|
||||
dump_rrset_lruhash(RES* ssl, struct lruhash* h, time_t now)
|
||||
{
|
||||
struct lruhash_entry* e;
|
||||
/* lruhash already locked by caller */
|
||||
@@ -117,7 +118,7 @@ dump_rrset_lruhash(SSL* ssl, struct lruhash* h, time_t now)
|
||||
|
||||
/** dump rrset cache */
|
||||
static int
|
||||
dump_rrset_cache(SSL* ssl, struct worker* worker)
|
||||
dump_rrset_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
struct rrset_cache* r = worker->env.rrset_cache;
|
||||
size_t slab;
|
||||
@@ -136,7 +137,7 @@ dump_rrset_cache(SSL* ssl, struct worker* worker)
|
||||
|
||||
/** dump message to rrset reference */
|
||||
static int
|
||||
dump_msg_ref(SSL* ssl, struct ub_packed_rrset_key* k)
|
||||
dump_msg_ref(RES* ssl, struct ub_packed_rrset_key* k)
|
||||
{
|
||||
char* nm, *tp, *cl;
|
||||
nm = sldns_wire2str_dname(k->rk.dname, k->rk.dname_len);
|
||||
@@ -163,7 +164,7 @@ dump_msg_ref(SSL* ssl, struct ub_packed_rrset_key* k)
|
||||
|
||||
/** dump message entry */
|
||||
static int
|
||||
dump_msg(SSL* ssl, struct query_info* k, struct reply_info* d,
|
||||
dump_msg(RES* ssl, struct query_info* k, struct reply_info* d,
|
||||
time_t now)
|
||||
{
|
||||
size_t i;
|
||||
@@ -245,7 +246,7 @@ copy_msg(struct regional* region, struct lruhash_entry* e,
|
||||
|
||||
/** dump lruhash msg cache */
|
||||
static int
|
||||
dump_msg_lruhash(SSL* ssl, struct worker* worker, struct lruhash* h)
|
||||
dump_msg_lruhash(RES* ssl, struct worker* worker, struct lruhash* h)
|
||||
{
|
||||
struct lruhash_entry* e;
|
||||
struct query_info* k;
|
||||
@@ -273,7 +274,7 @@ dump_msg_lruhash(SSL* ssl, struct worker* worker, struct lruhash* h)
|
||||
|
||||
/** dump msg cache */
|
||||
static int
|
||||
dump_msg_cache(SSL* ssl, struct worker* worker)
|
||||
dump_msg_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
struct slabhash* sh = worker->env.msg_cache;
|
||||
size_t slab;
|
||||
@@ -290,7 +291,7 @@ dump_msg_cache(SSL* ssl, struct worker* worker)
|
||||
}
|
||||
|
||||
int
|
||||
dump_cache(SSL* ssl, struct worker* worker)
|
||||
dump_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
if(!dump_rrset_cache(ssl, worker))
|
||||
return 0;
|
||||
@@ -301,7 +302,7 @@ dump_cache(SSL* ssl, struct worker* worker)
|
||||
|
||||
/** read a line from ssl into buffer */
|
||||
static int
|
||||
ssl_read_buf(SSL* ssl, sldns_buffer* buf)
|
||||
ssl_read_buf(RES* ssl, sldns_buffer* buf)
|
||||
{
|
||||
return ssl_read_line(ssl, (char*)sldns_buffer_begin(buf),
|
||||
sldns_buffer_capacity(buf));
|
||||
@@ -309,7 +310,7 @@ ssl_read_buf(SSL* ssl, sldns_buffer* buf)
|
||||
|
||||
/** check fixed text on line */
|
||||
static int
|
||||
read_fixed(SSL* ssl, sldns_buffer* buf, const char* str)
|
||||
read_fixed(RES* ssl, sldns_buffer* buf, const char* str)
|
||||
{
|
||||
if(!ssl_read_buf(ssl, buf)) return 0;
|
||||
return (strcmp((char*)sldns_buffer_begin(buf), str) == 0);
|
||||
@@ -317,7 +318,7 @@ read_fixed(SSL* ssl, sldns_buffer* buf, const char* str)
|
||||
|
||||
/** load an RR into rrset */
|
||||
static int
|
||||
load_rr(SSL* ssl, sldns_buffer* buf, struct regional* region,
|
||||
load_rr(RES* ssl, sldns_buffer* buf, struct regional* region,
|
||||
struct ub_packed_rrset_key* rk, struct packed_rrset_data* d,
|
||||
unsigned int i, int is_rrsig, int* go_on, time_t now)
|
||||
{
|
||||
@@ -434,7 +435,7 @@ move_into_cache(struct ub_packed_rrset_key* k,
|
||||
|
||||
/** load an rrset entry */
|
||||
static int
|
||||
load_rrset(SSL* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
load_rrset(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
{
|
||||
char* s = (char*)sldns_buffer_begin(buf);
|
||||
struct regional* region = worker->scratchpad;
|
||||
@@ -518,7 +519,7 @@ load_rrset(SSL* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
|
||||
/** load rrset cache */
|
||||
static int
|
||||
load_rrset_cache(SSL* ssl, struct worker* worker)
|
||||
load_rrset_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
sldns_buffer* buf = worker->env.scratch_buffer;
|
||||
if(!read_fixed(ssl, buf, "START_RRSET_CACHE")) return 0;
|
||||
@@ -574,7 +575,7 @@ load_qinfo(char* str, struct query_info* qinfo, struct regional* region)
|
||||
|
||||
/** load a msg rrset reference */
|
||||
static int
|
||||
load_ref(SSL* ssl, sldns_buffer* buf, struct worker* worker,
|
||||
load_ref(RES* ssl, sldns_buffer* buf, struct worker* worker,
|
||||
struct regional *region, struct ub_packed_rrset_key** rrset,
|
||||
int* go_on)
|
||||
{
|
||||
@@ -619,7 +620,7 @@ load_ref(SSL* ssl, sldns_buffer* buf, struct worker* worker,
|
||||
|
||||
/** load a msg entry */
|
||||
static int
|
||||
load_msg(SSL* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
{
|
||||
struct regional* region = worker->scratchpad;
|
||||
struct query_info qinf;
|
||||
@@ -652,6 +653,7 @@ load_msg(SSL* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
rep.qdcount = (uint16_t)qdcount;
|
||||
rep.ttl = (time_t)ttl;
|
||||
rep.prefetch_ttl = PREFETCH_TTL_CALC(rep.ttl);
|
||||
rep.serve_expired_ttl = rep.ttl + SERVE_EXPIRED_TTL;
|
||||
rep.security = (enum sec_status)security;
|
||||
if(an > RR_COUNT_MAX || ns > RR_COUNT_MAX || ar > RR_COUNT_MAX) {
|
||||
log_warn("error too many rrsets");
|
||||
@@ -684,7 +686,7 @@ load_msg(SSL* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
|
||||
/** load msg cache */
|
||||
static int
|
||||
load_msg_cache(SSL* ssl, struct worker* worker)
|
||||
load_msg_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
sldns_buffer* buf = worker->env.scratch_buffer;
|
||||
if(!read_fixed(ssl, buf, "START_MSG_CACHE")) return 0;
|
||||
@@ -697,7 +699,7 @@ load_msg_cache(SSL* ssl, struct worker* worker)
|
||||
}
|
||||
|
||||
int
|
||||
load_cache(SSL* ssl, struct worker* worker)
|
||||
load_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
if(!load_rrset_cache(ssl, worker))
|
||||
return 0;
|
||||
@@ -708,7 +710,7 @@ load_cache(SSL* ssl, struct worker* worker)
|
||||
|
||||
/** print details on a delegation point */
|
||||
static void
|
||||
print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp)
|
||||
print_dp_details(RES* ssl, struct worker* worker, struct delegpt* dp)
|
||||
{
|
||||
char buf[257];
|
||||
struct delegpt_addr* a;
|
||||
@@ -784,7 +786,7 @@ print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp)
|
||||
|
||||
/** print main dp info */
|
||||
static void
|
||||
print_dp_main(SSL* ssl, struct delegpt* dp, struct dns_msg* msg)
|
||||
print_dp_main(RES* ssl, struct delegpt* dp, struct dns_msg* msg)
|
||||
{
|
||||
size_t i, n_ns, n_miss, n_addr, n_res, n_avail;
|
||||
|
||||
@@ -812,7 +814,7 @@ print_dp_main(SSL* ssl, struct delegpt* dp, struct dns_msg* msg)
|
||||
return;
|
||||
}
|
||||
|
||||
int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
|
||||
int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
||||
size_t nmlen, int ATTR_UNUSED(nmlabs))
|
||||
{
|
||||
/* deep links into the iterator module */
|
||||
|
||||
+4
-3
@@ -72,6 +72,7 @@
|
||||
#ifndef DAEMON_DUMPCACHE_H
|
||||
#define DAEMON_DUMPCACHE_H
|
||||
struct worker;
|
||||
#include "daemon/remote.h"
|
||||
|
||||
/**
|
||||
* Dump cache(s) to text
|
||||
@@ -80,7 +81,7 @@ struct worker;
|
||||
* ptrs to the caches.
|
||||
* @return false on ssl print error.
|
||||
*/
|
||||
int dump_cache(SSL* ssl, struct worker* worker);
|
||||
int dump_cache(RES* ssl, struct worker* worker);
|
||||
|
||||
/**
|
||||
* Load cache(s) from text
|
||||
@@ -89,7 +90,7 @@ int dump_cache(SSL* ssl, struct worker* worker);
|
||||
* ptrs to the caches.
|
||||
* @return false on ssl error.
|
||||
*/
|
||||
int load_cache(SSL* ssl, struct worker* worker);
|
||||
int load_cache(RES* ssl, struct worker* worker);
|
||||
|
||||
/**
|
||||
* Print the delegation used to lookup for this name.
|
||||
@@ -101,7 +102,7 @@ int load_cache(SSL* ssl, struct worker* worker);
|
||||
* @param nmlabs: labels in name.
|
||||
* @return false on ssl error.
|
||||
*/
|
||||
int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
|
||||
int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
||||
size_t nmlen, int nmlabs);
|
||||
|
||||
#endif /* DAEMON_DUMPCACHE_H */
|
||||
|
||||
+110
-16
@@ -73,21 +73,29 @@
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/shm_side/shm_main.h"
|
||||
#include "util/storage/lookup3.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/tcp_conn_limit.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/localzone.h"
|
||||
#include "services/view.h"
|
||||
#include "services/modstack.h"
|
||||
#include "services/authzone.h"
|
||||
#include "util/module.h"
|
||||
#include "util/random.h"
|
||||
#include "util/tube.h"
|
||||
#include "util/net_help.h"
|
||||
#include "sldns/keyraw.h"
|
||||
#include "respip/respip.h"
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef HAVE_SYSTEMD
|
||||
#include <systemd/sd-daemon.h>
|
||||
#endif
|
||||
|
||||
/** How many quit requests happened. */
|
||||
static int sig_record_quit = 0;
|
||||
/** How many reload requests happened. */
|
||||
@@ -97,10 +105,8 @@ static int sig_record_reload = 0;
|
||||
/** cleaner ssl memory freeup */
|
||||
static void* comp_meth = NULL;
|
||||
#endif
|
||||
#ifdef LEX_HAS_YYLEX_DESTROY
|
||||
/** remove buffers for parsing and init */
|
||||
int ub_c_lex_destroy(void);
|
||||
#endif
|
||||
|
||||
/** used when no other sighandling happens, so we don't die
|
||||
* when multiple signals in quick succession are sent to us.
|
||||
@@ -208,12 +214,16 @@ daemon_init(void)
|
||||
# ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
|
||||
ERR_load_crypto_strings();
|
||||
# endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
ERR_load_SSL_strings();
|
||||
#endif
|
||||
# ifdef USE_GOST
|
||||
(void)sldns_key_EVP_load_gost_id();
|
||||
# endif
|
||||
# if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
|
||||
# ifndef S_SPLINT_S
|
||||
OpenSSL_add_all_algorithms();
|
||||
# endif
|
||||
# else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
@@ -226,7 +236,7 @@ daemon_init(void)
|
||||
# if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
# else
|
||||
(void)OPENSSL_init_ssl(0, NULL);
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||
# endif
|
||||
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
|
||||
if(!ub_openssl_lock_init())
|
||||
@@ -240,8 +250,6 @@ daemon_init(void)
|
||||
/* 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,
|
||||
@@ -263,9 +271,25 @@ daemon_init(void)
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
daemon->tcl = tcl_list_create();
|
||||
if(!daemon->tcl) {
|
||||
acl_list_delete(daemon->acl);
|
||||
edns_known_options_delete(daemon->env);
|
||||
free(daemon->env);
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
if(gettimeofday(&daemon->time_boot, NULL) < 0)
|
||||
log_err("gettimeofday: %s", strerror(errno));
|
||||
daemon->time_last_stat = daemon->time_boot;
|
||||
if((daemon->env->auth_zones = auth_zones_create()) == 0) {
|
||||
acl_list_delete(daemon->acl);
|
||||
tcl_list_delete(daemon->tcl);
|
||||
edns_known_options_delete(daemon->env);
|
||||
free(daemon->env);
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
return daemon;
|
||||
}
|
||||
|
||||
@@ -403,13 +427,11 @@ daemon_create_workers(struct daemon* daemon)
|
||||
int* shufport;
|
||||
log_assert(daemon && daemon->cfg);
|
||||
if(!daemon->rand) {
|
||||
unsigned int seed = (unsigned int)time(NULL) ^
|
||||
(unsigned int)getpid() ^ 0x438;
|
||||
daemon->rand = ub_initstate(seed, NULL);
|
||||
daemon->rand = ub_initstate(NULL);
|
||||
if(!daemon->rand)
|
||||
fatal_exit("could not init random generator");
|
||||
hash_set_raninit((uint32_t)ub_random(daemon->rand));
|
||||
}
|
||||
hash_set_raninit((uint32_t)ub_random(daemon->rand));
|
||||
shufport = (int*)calloc(65536, sizeof(int));
|
||||
if(!shufport)
|
||||
fatal_exit("out of memory during daemon init");
|
||||
@@ -550,6 +572,11 @@ daemon_stop_others(struct daemon* daemon)
|
||||
void
|
||||
daemon_fork(struct daemon* daemon)
|
||||
{
|
||||
int have_view_respip_cfg = 0;
|
||||
#ifdef HAVE_SYSTEMD
|
||||
int ret;
|
||||
#endif
|
||||
|
||||
log_assert(daemon);
|
||||
if(!(daemon->views = views_create()))
|
||||
fatal_exit("Could not create views: out of memory");
|
||||
@@ -559,15 +586,50 @@ daemon_fork(struct daemon* daemon)
|
||||
|
||||
if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->views))
|
||||
fatal_exit("Could not setup access control list");
|
||||
if(!tcl_list_apply_cfg(daemon->tcl, daemon->cfg))
|
||||
fatal_exit("Could not setup TCP connection limits");
|
||||
if(daemon->cfg->dnscrypt) {
|
||||
#ifdef USE_DNSCRYPT
|
||||
daemon->dnscenv = dnsc_create();
|
||||
if (!daemon->dnscenv)
|
||||
fatal_exit("dnsc_create failed");
|
||||
dnsc_apply_cfg(daemon->dnscenv, daemon->cfg);
|
||||
#else
|
||||
fatal_exit("dnscrypt enabled in config but unbound was not built with "
|
||||
"dnscrypt support");
|
||||
#endif
|
||||
}
|
||||
/* create global local_zones */
|
||||
if(!(daemon->local_zones = local_zones_create()))
|
||||
fatal_exit("Could not create local zones: out of memory");
|
||||
if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg))
|
||||
fatal_exit("Could not set up local zones");
|
||||
|
||||
/* process raw response-ip configuration data */
|
||||
if(!(daemon->respip_set = respip_set_create()))
|
||||
fatal_exit("Could not create response IP set");
|
||||
if(!respip_global_apply_cfg(daemon->respip_set, daemon->cfg))
|
||||
fatal_exit("Could not set up response IP set");
|
||||
if(!respip_views_apply_cfg(daemon->views, daemon->cfg,
|
||||
&have_view_respip_cfg))
|
||||
fatal_exit("Could not set up per-view response IP sets");
|
||||
daemon->use_response_ip = !respip_set_is_empty(daemon->respip_set) ||
|
||||
have_view_respip_cfg;
|
||||
|
||||
/* read auth zonefiles */
|
||||
if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1))
|
||||
fatal_exit("auth_zones could not be setup");
|
||||
|
||||
/* setup modules */
|
||||
daemon_setup_modules(daemon);
|
||||
|
||||
/* response-ip-xxx options don't work as expected without the respip
|
||||
* module. To avoid run-time operational surprise we reject such
|
||||
* configuration. */
|
||||
if(daemon->use_response_ip &&
|
||||
modstack_find(&daemon->mods, "respip") < 0)
|
||||
fatal_exit("response-ip options require respip module");
|
||||
|
||||
/* first create all the worker structures, so we can pass
|
||||
* them to the newly created threads.
|
||||
*/
|
||||
@@ -594,14 +656,34 @@ daemon_fork(struct daemon* daemon)
|
||||
#endif
|
||||
signal_handling_playback(daemon->workers[0]);
|
||||
|
||||
if (!shm_main_init(daemon))
|
||||
log_warn("SHM has failed");
|
||||
|
||||
/* Start resolver service on main thread. */
|
||||
#ifdef HAVE_SYSTEMD
|
||||
ret = sd_notify(0, "READY=1");
|
||||
if(ret <= 0 && getenv("NOTIFY_SOCKET"))
|
||||
fatal_exit("sd_notify failed %s: %s. Make sure that unbound has "
|
||||
"access/permission to use the socket presented by systemd.",
|
||||
getenv("NOTIFY_SOCKET"),
|
||||
(ret==0?"no $NOTIFY_SOCKET": strerror(-ret)));
|
||||
#endif
|
||||
log_info("start of service (%s).", PACKAGE_STRING);
|
||||
worker_work(daemon->workers[0]);
|
||||
#ifdef HAVE_SYSTEMD
|
||||
if (daemon->workers[0]->need_to_exit)
|
||||
sd_notify(0, "STOPPING=1");
|
||||
else
|
||||
sd_notify(0, "RELOADING=1");
|
||||
#endif
|
||||
log_info("service stopped (%s).", PACKAGE_STRING);
|
||||
|
||||
/* we exited! a signal happened! Stop other threads */
|
||||
daemon_stop_others(daemon);
|
||||
|
||||
/* Shutdown SHM */
|
||||
shm_main_shutdown(daemon);
|
||||
|
||||
daemon->need_to_exit = daemon->workers[0]->need_to_exit;
|
||||
}
|
||||
|
||||
@@ -621,8 +703,12 @@ daemon_cleanup(struct daemon* daemon)
|
||||
slabhash_clear(daemon->env->msg_cache);
|
||||
local_zones_delete(daemon->local_zones);
|
||||
daemon->local_zones = NULL;
|
||||
respip_set_delete(daemon->respip_set);
|
||||
daemon->respip_set = NULL;
|
||||
views_delete(daemon->views);
|
||||
daemon->views = NULL;
|
||||
if(daemon->env->auth_zones)
|
||||
auth_zones_cleanup(daemon->env->auth_zones);
|
||||
/* key cache is cleared by module desetup during next daemon_fork() */
|
||||
daemon_remote_clear(daemon->rc);
|
||||
for(i=0; i<daemon->num; i++)
|
||||
@@ -630,8 +716,14 @@ daemon_cleanup(struct daemon* daemon)
|
||||
free(daemon->workers);
|
||||
daemon->workers = NULL;
|
||||
daemon->num = 0;
|
||||
alloc_clear_special(&daemon->superalloc);
|
||||
#ifdef USE_DNSTAP
|
||||
dt_delete(daemon->dtenv);
|
||||
daemon->dtenv = NULL;
|
||||
#endif
|
||||
#ifdef USE_DNSCRYPT
|
||||
dnsc_delete(daemon->dnscenv);
|
||||
daemon->dnscenv = NULL;
|
||||
#endif
|
||||
daemon->cfg = NULL;
|
||||
}
|
||||
@@ -653,23 +745,23 @@ daemon_delete(struct daemon* daemon)
|
||||
rrset_cache_delete(daemon->env->rrset_cache);
|
||||
infra_delete(daemon->env->infra_cache);
|
||||
edns_known_options_delete(daemon->env);
|
||||
inplace_cb_lists_delete(daemon->env);
|
||||
auth_zones_delete(daemon->env->auth_zones);
|
||||
}
|
||||
ub_randfree(daemon->rand);
|
||||
alloc_clear(&daemon->superalloc);
|
||||
acl_list_delete(daemon->acl);
|
||||
tcl_list_delete(daemon->tcl);
|
||||
free(daemon->chroot);
|
||||
free(daemon->pidfile);
|
||||
free(daemon->env);
|
||||
#ifdef HAVE_SSL
|
||||
listen_sslctx_delete_ticket_keys();
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_sslctx);
|
||||
SSL_CTX_free((SSL_CTX*)daemon->connect_sslctx);
|
||||
#endif
|
||||
free(daemon);
|
||||
#ifdef LEX_HAS_YYLEX_DESTROY
|
||||
/* lex cleanup */
|
||||
ub_c_lex_destroy();
|
||||
#endif
|
||||
/* libcrypto cleanup */
|
||||
#ifdef HAVE_SSL
|
||||
# if defined(USE_GOST) && defined(HAVE_LDNS_KEY_EVP_UNLOAD_GOST)
|
||||
@@ -684,7 +776,7 @@ daemon_delete(struct daemon* daemon)
|
||||
# endif
|
||||
# ifdef HAVE_OPENSSL_CONFIG
|
||||
EVP_cleanup();
|
||||
# if OPENSSL_VERSION_NUMBER < 0x10100000
|
||||
# if (OPENSSL_VERSION_NUMBER < 0x10100000) && !defined(OPENSSL_NO_ENGINE)
|
||||
ENGINE_cleanup();
|
||||
# endif
|
||||
CONF_modules_free();
|
||||
@@ -701,6 +793,9 @@ daemon_delete(struct daemon* daemon)
|
||||
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
|
||||
ub_openssl_lock_delete();
|
||||
# endif
|
||||
#ifndef HAVE_ARC4RANDOM
|
||||
_ARC4_LOCK_DESTROY();
|
||||
#endif
|
||||
#elif defined(HAVE_NSS)
|
||||
NSS_Shutdown();
|
||||
#endif /* HAVE_SSL or HAVE_NSS */
|
||||
@@ -717,9 +812,8 @@ void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg)
|
||||
{
|
||||
daemon->cfg = cfg;
|
||||
config_apply(cfg);
|
||||
if(!daemon->env->msg_cache ||
|
||||
cfg->msg_cache_size != slabhash_get_size(daemon->env->msg_cache) ||
|
||||
cfg->msg_cache_slabs != daemon->env->msg_cache->size) {
|
||||
if(!slabhash_is_size(daemon->env->msg_cache, cfg->msg_cache_size,
|
||||
cfg->msg_cache_slabs)) {
|
||||
slabhash_delete(daemon->env->msg_cache);
|
||||
daemon->env->msg_cache = slabhash_create(cfg->msg_cache_slabs,
|
||||
HASH_DEFAULT_STARTARRAY, cfg->msg_cache_size,
|
||||
|
||||
@@ -56,12 +56,19 @@ struct local_zones;
|
||||
struct views;
|
||||
struct ub_randstate;
|
||||
struct daemon_remote;
|
||||
struct respip_set;
|
||||
struct shm_main_info;
|
||||
|
||||
#include "dnstap/dnstap_config.h"
|
||||
#ifdef USE_DNSTAP
|
||||
struct dt_env;
|
||||
#endif
|
||||
|
||||
#include "dnscrypt/dnscrypt_config.h"
|
||||
#ifdef USE_DNSCRYPT
|
||||
struct dnsc_env;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Structure holding worker list.
|
||||
* Holds globally visible information.
|
||||
@@ -106,6 +113,8 @@ struct daemon {
|
||||
struct module_stack mods;
|
||||
/** access control, which client IPs are allowed to connect */
|
||||
struct acl_list* acl;
|
||||
/** TCP connection limit, limit connections from client IPs */
|
||||
struct tcl_list* tcl;
|
||||
/** local authority zones */
|
||||
struct local_zones* local_zones;
|
||||
/** last time of statistics printout */
|
||||
@@ -117,6 +126,15 @@ struct daemon {
|
||||
#ifdef USE_DNSTAP
|
||||
/** the dnstap environment master value, copied and changed by threads*/
|
||||
struct dt_env* dtenv;
|
||||
#endif
|
||||
struct shm_main_info* shm_info;
|
||||
/** response-ip set with associated actions and tags. */
|
||||
struct respip_set* respip_set;
|
||||
/** some response-ip tags or actions are configured if true */
|
||||
int use_response_ip;
|
||||
#ifdef USE_DNSCRYPT
|
||||
/** the dnscrypt environment */
|
||||
struct dnsc_env* dnscenv;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
+605
-337
File diff suppressed because it is too large
Load Diff
+21
-6
@@ -73,6 +73,8 @@ struct rc_state {
|
||||
/** the ssl state */
|
||||
SSL* ssl;
|
||||
#endif
|
||||
/** file descriptor */
|
||||
int fd;
|
||||
/** the rc this is part of */
|
||||
struct daemon_remote* rc;
|
||||
};
|
||||
@@ -103,6 +105,19 @@ struct daemon_remote {
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Connection to print to, either SSL or plain over fd
|
||||
*/
|
||||
struct remote_stream {
|
||||
#ifdef HAVE_SSL
|
||||
/** SSL structure, nonNULL if using SSL */
|
||||
SSL* ssl;
|
||||
#endif
|
||||
/** file descriptor for plain transfer */
|
||||
int fd;
|
||||
};
|
||||
typedef struct remote_stream RES;
|
||||
|
||||
/**
|
||||
* Create new remote control state for the daemon.
|
||||
* @param cfg: config file with key file settings.
|
||||
@@ -166,26 +181,26 @@ void daemon_remote_exec(struct worker* worker);
|
||||
* @param text: the text.
|
||||
* @return false on connection failure.
|
||||
*/
|
||||
int ssl_print_text(SSL* ssl, const char* text);
|
||||
int ssl_print_text(RES* ssl, const char* text);
|
||||
|
||||
/**
|
||||
* printf style printing to the ssl connection
|
||||
* @param ssl: the SSL connection to print to. Blocking.
|
||||
* @param ssl: the RES connection to print to. Blocking.
|
||||
* @param format: printf style format string.
|
||||
* @return success or false on a network failure.
|
||||
*/
|
||||
int ssl_printf(SSL* ssl, const char* format, ...)
|
||||
int ssl_printf(RES* ssl, const char* format, ...)
|
||||
ATTR_FORMAT(printf, 2, 3);
|
||||
|
||||
/**
|
||||
* Read until \n is encountered
|
||||
* If SSL signals EOF, the string up to then is returned (without \n).
|
||||
* @param ssl: the SSL connection to read from. blocking.
|
||||
* If stream signals EOF, the string up to then is returned (without \n).
|
||||
* @param ssl: the RES connection to read from. blocking.
|
||||
* @param buf: buffer to read to.
|
||||
* @param max: size of buffer.
|
||||
* @return false on connection failure.
|
||||
*/
|
||||
int ssl_read_line(SSL* ssl, char* buf, size_t max);
|
||||
int ssl_read_line(RES* ssl, char* buf, size_t max);
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
#endif /* DAEMON_REMOTE_H */
|
||||
|
||||
+238
-52
@@ -56,72 +56,134 @@
|
||||
#include "util/timehist.h"
|
||||
#include "util/net_help.h"
|
||||
#include "validator/validator.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/authzone.h"
|
||||
#include "validator/val_kcache.h"
|
||||
#include "validator/val_neg.h"
|
||||
#ifdef CLIENT_SUBNET
|
||||
#include "edns-subnet/subnetmod.h"
|
||||
#endif
|
||||
#ifdef HAVE_SSL
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
|
||||
/** add timers and the values do not overflow or become negative */
|
||||
static void
|
||||
timeval_add(struct timeval* d, const struct timeval* add)
|
||||
stats_timeval_add(long long* d_sec, long long* d_usec, long long add_sec, long long add_usec)
|
||||
{
|
||||
#ifndef S_SPLINT_S
|
||||
d->tv_sec += add->tv_sec;
|
||||
d->tv_usec += add->tv_usec;
|
||||
if(d->tv_usec > 1000000) {
|
||||
d->tv_usec -= 1000000;
|
||||
d->tv_sec++;
|
||||
(*d_sec) += add_sec;
|
||||
(*d_usec) += add_usec;
|
||||
if((*d_usec) >= 1000000) {
|
||||
(*d_usec) -= 1000000;
|
||||
(*d_sec)++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void server_stats_init(struct server_stats* stats, struct config_file* cfg)
|
||||
void server_stats_init(struct ub_server_stats* stats, struct config_file* cfg)
|
||||
{
|
||||
memset(stats, 0, sizeof(*stats));
|
||||
stats->extended = cfg->stat_extended;
|
||||
}
|
||||
|
||||
void server_stats_querymiss(struct server_stats* stats, struct worker* worker)
|
||||
void server_stats_querymiss(struct ub_server_stats* stats, struct worker* worker)
|
||||
{
|
||||
stats->num_queries_missed_cache++;
|
||||
stats->sum_query_list_size += worker->env.mesh->all.count;
|
||||
if(worker->env.mesh->all.count > stats->max_query_list_size)
|
||||
stats->max_query_list_size = worker->env.mesh->all.count;
|
||||
if((long long)worker->env.mesh->all.count > stats->max_query_list_size)
|
||||
stats->max_query_list_size = (long long)worker->env.mesh->all.count;
|
||||
}
|
||||
|
||||
void server_stats_prefetch(struct server_stats* stats, struct worker* worker)
|
||||
void server_stats_prefetch(struct ub_server_stats* stats, struct worker* worker)
|
||||
{
|
||||
stats->num_queries_prefetch++;
|
||||
/* changes the query list size so account that, like a querymiss */
|
||||
stats->sum_query_list_size += worker->env.mesh->all.count;
|
||||
if(worker->env.mesh->all.count > stats->max_query_list_size)
|
||||
stats->max_query_list_size = worker->env.mesh->all.count;
|
||||
if((long long)worker->env.mesh->all.count > stats->max_query_list_size)
|
||||
stats->max_query_list_size = (long long)worker->env.mesh->all.count;
|
||||
}
|
||||
|
||||
void server_stats_log(struct server_stats* stats, struct worker* worker,
|
||||
void server_stats_log(struct ub_server_stats* stats, struct worker* worker,
|
||||
int threadnum)
|
||||
{
|
||||
log_info("server stats for thread %d: %u queries, "
|
||||
"%u answers from cache, %u recursions, %u prefetch",
|
||||
"%u answers from cache, %u recursions, %u prefetch, %u rejected by "
|
||||
"ip ratelimiting",
|
||||
threadnum, (unsigned)stats->num_queries,
|
||||
(unsigned)(stats->num_queries -
|
||||
stats->num_queries_missed_cache),
|
||||
(unsigned)stats->num_queries_missed_cache,
|
||||
(unsigned)stats->num_queries_prefetch);
|
||||
(unsigned)stats->num_queries_prefetch,
|
||||
(unsigned)stats->num_queries_ip_ratelimited);
|
||||
log_info("server stats for thread %d: requestlist max %u avg %g "
|
||||
"exceeded %u jostled %u", threadnum,
|
||||
(unsigned)stats->max_query_list_size,
|
||||
(stats->num_queries_missed_cache+stats->num_queries_prefetch)?
|
||||
(double)stats->sum_query_list_size/
|
||||
(stats->num_queries_missed_cache+
|
||||
(double)(stats->num_queries_missed_cache+
|
||||
stats->num_queries_prefetch) : 0.0,
|
||||
(unsigned)worker->env.mesh->stats_dropped,
|
||||
(unsigned)worker->env.mesh->stats_jostled);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CLIENT_SUBNET
|
||||
/** Set the EDNS Subnet stats. */
|
||||
static void
|
||||
set_subnet_stats(struct worker* worker, struct ub_server_stats* svr,
|
||||
int reset)
|
||||
{
|
||||
int m = modstack_find(&worker->env.mesh->mods, "subnet");
|
||||
struct subnet_env* sne;
|
||||
if(m == -1)
|
||||
return;
|
||||
sne = (struct subnet_env*)worker->env.modinfo[m];
|
||||
if(reset && !worker->env.cfg->stat_cumulative) {
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
} else {
|
||||
lock_rw_rdlock(&sne->biglock);
|
||||
}
|
||||
svr->num_query_subnet = (long long)(sne->num_msg_nocache + sne->num_msg_cache);
|
||||
svr->num_query_subnet_cache = (long long)sne->num_msg_cache;
|
||||
if(reset && !worker->env.cfg->stat_cumulative) {
|
||||
sne->num_msg_cache = 0;
|
||||
sne->num_msg_nocache = 0;
|
||||
}
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
}
|
||||
#endif /* CLIENT_SUBNET */
|
||||
|
||||
/** Set the neg cache stats. */
|
||||
static void
|
||||
set_neg_cache_stats(struct worker* worker, struct ub_server_stats* svr,
|
||||
int reset)
|
||||
{
|
||||
int m = modstack_find(&worker->env.mesh->mods, "validator");
|
||||
struct val_env* ve;
|
||||
struct val_neg_cache* neg;
|
||||
if(m == -1)
|
||||
return;
|
||||
ve = (struct val_env*)worker->env.modinfo[m];
|
||||
if(!ve->neg_cache)
|
||||
return;
|
||||
neg = ve->neg_cache;
|
||||
lock_basic_lock(&neg->lock);
|
||||
svr->num_neg_cache_noerror = (long long)neg->num_neg_cache_noerror;
|
||||
svr->num_neg_cache_nxdomain = (long long)neg->num_neg_cache_nxdomain;
|
||||
if(reset && !worker->env.cfg->stat_cumulative) {
|
||||
neg->num_neg_cache_noerror = 0;
|
||||
neg->num_neg_cache_nxdomain = 0;
|
||||
}
|
||||
lock_basic_unlock(&neg->lock);
|
||||
}
|
||||
|
||||
/** get rrsets bogus number from validator */
|
||||
static size_t
|
||||
get_rrset_bogus(struct worker* worker)
|
||||
get_rrset_bogus(struct worker* worker, int reset)
|
||||
{
|
||||
int m = modstack_find(&worker->env.mesh->mods, "validator");
|
||||
struct val_env* ve;
|
||||
@@ -131,56 +193,162 @@ get_rrset_bogus(struct worker* worker)
|
||||
ve = (struct val_env*)worker->env.modinfo[m];
|
||||
lock_basic_lock(&ve->bogus_lock);
|
||||
r = ve->num_rrset_bogus;
|
||||
if(!worker->env.cfg->stat_cumulative)
|
||||
if(reset && !worker->env.cfg->stat_cumulative)
|
||||
ve->num_rrset_bogus = 0;
|
||||
lock_basic_unlock(&ve->bogus_lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
/** get number of ratelimited queries from iterator */
|
||||
static size_t
|
||||
get_queries_ratelimit(struct worker* worker, int reset)
|
||||
{
|
||||
int m = modstack_find(&worker->env.mesh->mods, "iterator");
|
||||
struct iter_env* ie;
|
||||
size_t r;
|
||||
if(m == -1)
|
||||
return 0;
|
||||
ie = (struct iter_env*)worker->env.modinfo[m];
|
||||
lock_basic_lock(&ie->queries_ratelimit_lock);
|
||||
r = ie->num_queries_ratelimited;
|
||||
if(reset && !worker->env.cfg->stat_cumulative)
|
||||
ie->num_queries_ratelimited = 0;
|
||||
lock_basic_unlock(&ie->queries_ratelimit_lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef USE_DNSCRYPT
|
||||
/** get the number of shared secret cache miss */
|
||||
static size_t
|
||||
get_dnscrypt_cache_miss(struct worker* worker, int reset)
|
||||
{
|
||||
size_t r;
|
||||
struct dnsc_env* de = worker->daemon->dnscenv;
|
||||
if(!de) return 0;
|
||||
|
||||
lock_basic_lock(&de->shared_secrets_cache_lock);
|
||||
r = de->num_query_dnscrypt_secret_missed_cache;
|
||||
if(reset && !worker->env.cfg->stat_cumulative)
|
||||
de->num_query_dnscrypt_secret_missed_cache = 0;
|
||||
lock_basic_unlock(&de->shared_secrets_cache_lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
/** get the number of replayed queries */
|
||||
static size_t
|
||||
get_dnscrypt_replay(struct worker* worker, int reset)
|
||||
{
|
||||
size_t r;
|
||||
struct dnsc_env* de = worker->daemon->dnscenv;
|
||||
|
||||
lock_basic_lock(&de->nonces_cache_lock);
|
||||
r = de->num_query_dnscrypt_replay;
|
||||
if(reset && !worker->env.cfg->stat_cumulative)
|
||||
de->num_query_dnscrypt_replay = 0;
|
||||
lock_basic_unlock(&de->nonces_cache_lock);
|
||||
return r;
|
||||
}
|
||||
#endif /* USE_DNSCRYPT */
|
||||
|
||||
void
|
||||
server_stats_compile(struct worker* worker, struct stats_info* s, int reset)
|
||||
server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
{
|
||||
int i;
|
||||
struct listen_list* lp;
|
||||
|
||||
s->svr = worker->stats;
|
||||
s->mesh_num_states = worker->env.mesh->all.count;
|
||||
s->mesh_num_reply_states = worker->env.mesh->num_reply_states;
|
||||
s->mesh_jostled = worker->env.mesh->stats_jostled;
|
||||
s->mesh_dropped = worker->env.mesh->stats_dropped;
|
||||
s->mesh_replies_sent = worker->env.mesh->replies_sent;
|
||||
s->mesh_replies_sum_wait = worker->env.mesh->replies_sum_wait;
|
||||
s->mesh_num_states = (long long)worker->env.mesh->all.count;
|
||||
s->mesh_num_reply_states = (long long)worker->env.mesh->num_reply_states;
|
||||
s->mesh_jostled = (long long)worker->env.mesh->stats_jostled;
|
||||
s->mesh_dropped = (long long)worker->env.mesh->stats_dropped;
|
||||
s->mesh_replies_sent = (long long)worker->env.mesh->replies_sent;
|
||||
s->mesh_replies_sum_wait_sec = (long long)worker->env.mesh->replies_sum_wait.tv_sec;
|
||||
s->mesh_replies_sum_wait_usec = (long long)worker->env.mesh->replies_sum_wait.tv_usec;
|
||||
s->mesh_time_median = timehist_quartile(worker->env.mesh->histogram,
|
||||
0.50);
|
||||
|
||||
/* add in the values from the mesh */
|
||||
s->svr.ans_secure += worker->env.mesh->ans_secure;
|
||||
s->svr.ans_bogus += worker->env.mesh->ans_bogus;
|
||||
s->svr.ans_rcode_nodata += worker->env.mesh->ans_nodata;
|
||||
s->svr.ans_secure += (long long)worker->env.mesh->ans_secure;
|
||||
s->svr.ans_bogus += (long long)worker->env.mesh->ans_bogus;
|
||||
s->svr.ans_rcode_nodata += (long long)worker->env.mesh->ans_nodata;
|
||||
for(i=0; i<16; i++)
|
||||
s->svr.ans_rcode[i] += worker->env.mesh->ans_rcode[i];
|
||||
s->svr.ans_rcode[i] += (long long)worker->env.mesh->ans_rcode[i];
|
||||
timehist_export(worker->env.mesh->histogram, s->svr.hist,
|
||||
NUM_BUCKETS_HIST);
|
||||
/* values from outside network */
|
||||
s->svr.unwanted_replies = worker->back->unwanted_replies;
|
||||
s->svr.qtcp_outgoing = worker->back->num_tcp_outgoing;
|
||||
s->svr.unwanted_replies = (long long)worker->back->unwanted_replies;
|
||||
s->svr.qtcp_outgoing = (long long)worker->back->num_tcp_outgoing;
|
||||
|
||||
/* get and reset validator rrset bogus number */
|
||||
s->svr.rrset_bogus = get_rrset_bogus(worker);
|
||||
s->svr.rrset_bogus = (long long)get_rrset_bogus(worker, reset);
|
||||
|
||||
/* get and reset iterator query ratelimit number */
|
||||
s->svr.queries_ratelimited = (long long)get_queries_ratelimit(worker, reset);
|
||||
|
||||
/* get cache sizes */
|
||||
s->svr.msg_cache_count = count_slabhash_entries(worker->env.msg_cache);
|
||||
s->svr.rrset_cache_count = count_slabhash_entries(&worker->env.rrset_cache->table);
|
||||
s->svr.infra_cache_count = count_slabhash_entries(worker->env.infra_cache->hosts);
|
||||
s->svr.msg_cache_count = (long long)count_slabhash_entries(worker->env.msg_cache);
|
||||
s->svr.rrset_cache_count = (long long)count_slabhash_entries(&worker->env.rrset_cache->table);
|
||||
s->svr.infra_cache_count = (long long)count_slabhash_entries(worker->env.infra_cache->hosts);
|
||||
if(worker->env.key_cache)
|
||||
s->svr.key_cache_count = count_slabhash_entries(worker->env.key_cache->slab);
|
||||
s->svr.key_cache_count = (long long)count_slabhash_entries(worker->env.key_cache->slab);
|
||||
else s->svr.key_cache_count = 0;
|
||||
|
||||
#ifdef USE_DNSCRYPT
|
||||
if(worker->daemon->dnscenv) {
|
||||
s->svr.num_query_dnscrypt_secret_missed_cache =
|
||||
(long long)get_dnscrypt_cache_miss(worker, reset);
|
||||
s->svr.shared_secret_cache_count = (long long)count_slabhash_entries(
|
||||
worker->daemon->dnscenv->shared_secrets_cache);
|
||||
s->svr.nonce_cache_count = (long long)count_slabhash_entries(
|
||||
worker->daemon->dnscenv->nonces_cache);
|
||||
s->svr.num_query_dnscrypt_replay =
|
||||
(long long)get_dnscrypt_replay(worker, reset);
|
||||
} else {
|
||||
s->svr.num_query_dnscrypt_secret_missed_cache = 0;
|
||||
s->svr.shared_secret_cache_count = 0;
|
||||
s->svr.nonce_cache_count = 0;
|
||||
s->svr.num_query_dnscrypt_replay = 0;
|
||||
}
|
||||
#else
|
||||
s->svr.num_query_dnscrypt_secret_missed_cache = 0;
|
||||
s->svr.shared_secret_cache_count = 0;
|
||||
s->svr.nonce_cache_count = 0;
|
||||
s->svr.num_query_dnscrypt_replay = 0;
|
||||
#endif /* USE_DNSCRYPT */
|
||||
if(worker->env.auth_zones) {
|
||||
if(reset && !worker->env.cfg->stat_cumulative) {
|
||||
lock_rw_wrlock(&worker->env.auth_zones->lock);
|
||||
} else {
|
||||
lock_rw_rdlock(&worker->env.auth_zones->lock);
|
||||
}
|
||||
s->svr.num_query_authzone_up = (long long)worker->env.
|
||||
auth_zones->num_query_up;
|
||||
s->svr.num_query_authzone_down = (long long)worker->env.
|
||||
auth_zones->num_query_down;
|
||||
if(reset && !worker->env.cfg->stat_cumulative) {
|
||||
worker->env.auth_zones->num_query_up = 0;
|
||||
worker->env.auth_zones->num_query_down = 0;
|
||||
}
|
||||
lock_rw_unlock(&worker->env.auth_zones->lock);
|
||||
}
|
||||
s->svr.mem_stream_wait =
|
||||
(long long)tcp_req_info_get_stream_buffer_size();
|
||||
|
||||
/* Set neg cache usage numbers */
|
||||
set_neg_cache_stats(worker, &s->svr, reset);
|
||||
#ifdef CLIENT_SUBNET
|
||||
/* EDNS Subnet usage numbers */
|
||||
set_subnet_stats(worker, &s->svr, reset);
|
||||
#else
|
||||
s->svr.num_query_subnet = 0;
|
||||
s->svr.num_query_subnet_cache = 0;
|
||||
#endif
|
||||
|
||||
/* get tcp accept usage */
|
||||
s->svr.tcp_accept_usage = 0;
|
||||
for(lp = worker->front->cps; lp; lp = lp->next) {
|
||||
if(lp->com->type == comm_tcp_accept)
|
||||
s->svr.tcp_accept_usage += lp->com->cur_tcp_count;
|
||||
s->svr.tcp_accept_usage += (long long)lp->com->cur_tcp_count;
|
||||
}
|
||||
|
||||
if(reset && !worker->env.cfg->stat_cumulative) {
|
||||
@@ -189,7 +357,7 @@ server_stats_compile(struct worker* worker, struct stats_info* s, int reset)
|
||||
}
|
||||
|
||||
void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
struct stats_info* s, int reset)
|
||||
struct ub_stats_info* s, int reset)
|
||||
{
|
||||
uint8_t *reply = NULL;
|
||||
uint32_t len = 0;
|
||||
@@ -215,7 +383,7 @@ void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
|
||||
void server_stats_reply(struct worker* worker, int reset)
|
||||
{
|
||||
struct stats_info s;
|
||||
struct ub_stats_info s;
|
||||
server_stats_compile(worker, &s, reset);
|
||||
verbose(VERB_ALGO, "write stats replymsg");
|
||||
if(!tube_write_msg(worker->daemon->workers[0]->cmd,
|
||||
@@ -223,12 +391,21 @@ void server_stats_reply(struct worker* worker, int reset)
|
||||
fatal_exit("could not write stat values over cmd channel");
|
||||
}
|
||||
|
||||
void server_stats_add(struct stats_info* total, struct stats_info* a)
|
||||
void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
||||
{
|
||||
total->svr.num_queries += a->svr.num_queries;
|
||||
total->svr.num_queries_ip_ratelimited += a->svr.num_queries_ip_ratelimited;
|
||||
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;
|
||||
#ifdef USE_DNSCRYPT
|
||||
total->svr.num_query_dnscrypt_crypted += a->svr.num_query_dnscrypt_crypted;
|
||||
total->svr.num_query_dnscrypt_cert += a->svr.num_query_dnscrypt_cert;
|
||||
total->svr.num_query_dnscrypt_cleartext += \
|
||||
a->svr.num_query_dnscrypt_cleartext;
|
||||
total->svr.num_query_dnscrypt_crypted_malformed += \
|
||||
a->svr.num_query_dnscrypt_crypted_malformed;
|
||||
#endif /* USE_DNSCRYPT */
|
||||
/* the max size reached is upped to higher of both */
|
||||
if(a->svr.max_query_list_size > total->svr.max_query_list_size)
|
||||
total->svr.max_query_list_size = a->svr.max_query_list_size;
|
||||
@@ -239,6 +416,8 @@ void server_stats_add(struct stats_info* total, struct stats_info* a)
|
||||
total->svr.qclass_big += a->svr.qclass_big;
|
||||
total->svr.qtcp += a->svr.qtcp;
|
||||
total->svr.qtcp_outgoing += a->svr.qtcp_outgoing;
|
||||
total->svr.qtls += a->svr.qtls;
|
||||
total->svr.qtls_resume += a->svr.qtls_resume;
|
||||
total->svr.qipv6 += a->svr.qipv6;
|
||||
total->svr.qbit_QR += a->svr.qbit_QR;
|
||||
total->svr.qbit_AA += a->svr.qbit_AA;
|
||||
@@ -254,17 +433,16 @@ void server_stats_add(struct stats_info* total, struct stats_info* a)
|
||||
total->svr.zero_ttl_responses += a->svr.zero_ttl_responses;
|
||||
total->svr.ans_secure += a->svr.ans_secure;
|
||||
total->svr.ans_bogus += a->svr.ans_bogus;
|
||||
total->svr.rrset_bogus += a->svr.rrset_bogus;
|
||||
total->svr.unwanted_replies += a->svr.unwanted_replies;
|
||||
total->svr.unwanted_queries += a->svr.unwanted_queries;
|
||||
total->svr.tcp_accept_usage += a->svr.tcp_accept_usage;
|
||||
for(i=0; i<STATS_QTYPE_NUM; i++)
|
||||
for(i=0; i<UB_STATS_QTYPE_NUM; i++)
|
||||
total->svr.qtype[i] += a->svr.qtype[i];
|
||||
for(i=0; i<STATS_QCLASS_NUM; i++)
|
||||
for(i=0; i<UB_STATS_QCLASS_NUM; i++)
|
||||
total->svr.qclass[i] += a->svr.qclass[i];
|
||||
for(i=0; i<STATS_OPCODE_NUM; i++)
|
||||
for(i=0; i<UB_STATS_OPCODE_NUM; i++)
|
||||
total->svr.qopcode[i] += a->svr.qopcode[i];
|
||||
for(i=0; i<STATS_RCODE_NUM; i++)
|
||||
for(i=0; i<UB_STATS_RCODE_NUM; i++)
|
||||
total->svr.ans_rcode[i] += a->svr.ans_rcode[i];
|
||||
for(i=0; i<NUM_BUCKETS_HIST; i++)
|
||||
total->svr.hist[i] += a->svr.hist[i];
|
||||
@@ -275,27 +453,35 @@ void server_stats_add(struct stats_info* total, struct stats_info* a)
|
||||
total->mesh_jostled += a->mesh_jostled;
|
||||
total->mesh_dropped += a->mesh_dropped;
|
||||
total->mesh_replies_sent += a->mesh_replies_sent;
|
||||
timeval_add(&total->mesh_replies_sum_wait, &a->mesh_replies_sum_wait);
|
||||
stats_timeval_add(&total->mesh_replies_sum_wait_sec, &total->mesh_replies_sum_wait_usec, a->mesh_replies_sum_wait_sec, a->mesh_replies_sum_wait_usec);
|
||||
/* the medians are averaged together, this is not as accurate as
|
||||
* taking the median over all of the data, but is good and fast
|
||||
* added up here, division later*/
|
||||
total->mesh_time_median += a->mesh_time_median;
|
||||
}
|
||||
|
||||
void server_stats_insquery(struct server_stats* stats, struct comm_point* c,
|
||||
void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
|
||||
uint16_t qtype, uint16_t qclass, struct edns_data* edns,
|
||||
struct comm_reply* repinfo)
|
||||
{
|
||||
uint16_t flags = sldns_buffer_read_u16_at(c->buffer, 2);
|
||||
if(qtype < STATS_QTYPE_NUM)
|
||||
if(qtype < UB_STATS_QTYPE_NUM)
|
||||
stats->qtype[qtype]++;
|
||||
else stats->qtype_big++;
|
||||
if(qclass < STATS_QCLASS_NUM)
|
||||
if(qclass < UB_STATS_QCLASS_NUM)
|
||||
stats->qclass[qclass]++;
|
||||
else stats->qclass_big++;
|
||||
stats->qopcode[ LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) ]++;
|
||||
if(c->type != comm_udp)
|
||||
if(c->type != comm_udp) {
|
||||
stats->qtcp++;
|
||||
if(c->ssl != NULL) {
|
||||
stats->qtls++;
|
||||
#ifdef HAVE_SSL
|
||||
if(SSL_session_reused(c->ssl))
|
||||
stats->qtls_resume++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if(repinfo && addr_is_ip6(&repinfo->addr, repinfo->addrlen))
|
||||
stats->qipv6++;
|
||||
if( (flags&BIT_QR) )
|
||||
@@ -321,7 +507,7 @@ void server_stats_insquery(struct server_stats* stats, struct comm_point* c,
|
||||
}
|
||||
}
|
||||
|
||||
void server_stats_insrcode(struct server_stats* stats, sldns_buffer* buf)
|
||||
void server_stats_insrcode(struct ub_server_stats* stats, sldns_buffer* buf)
|
||||
{
|
||||
if(stats->extended && sldns_buffer_limit(buf) != 0) {
|
||||
int r = (int)LDNS_RCODE_WIRE( sldns_buffer_begin(buf) );
|
||||
|
||||
+11
-131
@@ -50,144 +50,24 @@ struct comm_reply;
|
||||
struct edns_data;
|
||||
struct sldns_buffer;
|
||||
|
||||
/** number of qtype that is stored for in array */
|
||||
#define STATS_QTYPE_NUM 256
|
||||
/** number of qclass that is stored for in array */
|
||||
#define STATS_QCLASS_NUM 256
|
||||
/** number of rcodes in stats */
|
||||
#define STATS_RCODE_NUM 16
|
||||
/** number of opcodes in stats */
|
||||
#define STATS_OPCODE_NUM 16
|
||||
|
||||
/** per worker statistics */
|
||||
struct server_stats {
|
||||
/** number of queries from clients received. */
|
||||
size_t num_queries;
|
||||
/** number of queries that had a cache-miss. */
|
||||
size_t num_queries_missed_cache;
|
||||
/** number of prefetch queries - cachehits with prefetch */
|
||||
size_t num_queries_prefetch;
|
||||
|
||||
/**
|
||||
* Sum of the querylistsize of the worker for
|
||||
* every query that missed cache. To calculate average.
|
||||
*/
|
||||
size_t sum_query_list_size;
|
||||
/** max value of query list size reached. */
|
||||
size_t max_query_list_size;
|
||||
|
||||
/** Extended stats below (bool) */
|
||||
int extended;
|
||||
|
||||
/** qtype stats */
|
||||
size_t qtype[STATS_QTYPE_NUM];
|
||||
/** bigger qtype values not in array */
|
||||
size_t qtype_big;
|
||||
/** qclass stats */
|
||||
size_t qclass[STATS_QCLASS_NUM];
|
||||
/** bigger qclass values not in array */
|
||||
size_t qclass_big;
|
||||
/** query opcodes */
|
||||
size_t qopcode[STATS_OPCODE_NUM];
|
||||
/** number of queries over TCP */
|
||||
size_t qtcp;
|
||||
/** number of outgoing queries over TCP */
|
||||
size_t qtcp_outgoing;
|
||||
/** number of queries over IPv6 */
|
||||
size_t qipv6;
|
||||
/** number of queries with QR bit */
|
||||
size_t qbit_QR;
|
||||
/** number of queries with AA bit */
|
||||
size_t qbit_AA;
|
||||
/** number of queries with TC bit */
|
||||
size_t qbit_TC;
|
||||
/** number of queries with RD bit */
|
||||
size_t qbit_RD;
|
||||
/** number of queries with RA bit */
|
||||
size_t qbit_RA;
|
||||
/** number of queries with Z bit */
|
||||
size_t qbit_Z;
|
||||
/** number of queries with AD bit */
|
||||
size_t qbit_AD;
|
||||
/** number of queries with CD bit */
|
||||
size_t qbit_CD;
|
||||
/** number of queries with EDNS OPT record */
|
||||
size_t qEDNS;
|
||||
/** number of queries with EDNS with DO flag */
|
||||
size_t qEDNS_DO;
|
||||
/** answer rcodes */
|
||||
size_t ans_rcode[STATS_RCODE_NUM];
|
||||
/** answers with pseudo rcode 'nodata' */
|
||||
size_t ans_rcode_nodata;
|
||||
/** answers that were secure (AD) */
|
||||
size_t ans_secure;
|
||||
/** answers that were bogus (withheld as SERVFAIL) */
|
||||
size_t ans_bogus;
|
||||
/** rrsets marked bogus by validator */
|
||||
size_t rrset_bogus;
|
||||
/** unwanted traffic received on server-facing ports */
|
||||
size_t unwanted_replies;
|
||||
/** unwanted traffic received on client-facing ports */
|
||||
size_t unwanted_queries;
|
||||
/** usage of tcp accept list */
|
||||
size_t tcp_accept_usage;
|
||||
/** answers served from expired cache */
|
||||
size_t zero_ttl_responses;
|
||||
/** histogram data exported to array
|
||||
* if the array is the same size, no data is lost, and
|
||||
* if all histograms are same size (is so by default) then
|
||||
* adding up works well. */
|
||||
size_t hist[NUM_BUCKETS_HIST];
|
||||
|
||||
/** number of message cache entries */
|
||||
size_t msg_cache_count;
|
||||
/** number of rrset cache entries */
|
||||
size_t rrset_cache_count;
|
||||
/** number of infra cache entries */
|
||||
size_t infra_cache_count;
|
||||
/** number of key cache entries */
|
||||
size_t key_cache_count;
|
||||
};
|
||||
|
||||
/**
|
||||
* Statistics to send over the control pipe when asked
|
||||
* This struct is made to be memcpied, sent in binary.
|
||||
*/
|
||||
struct stats_info {
|
||||
/** the thread stats */
|
||||
struct server_stats svr;
|
||||
|
||||
/** mesh stats: current number of states */
|
||||
size_t mesh_num_states;
|
||||
/** mesh stats: current number of reply (user) states */
|
||||
size_t mesh_num_reply_states;
|
||||
/** mesh stats: number of reply states overwritten with a new one */
|
||||
size_t mesh_jostled;
|
||||
/** mesh stats: number of incoming queries dropped */
|
||||
size_t mesh_dropped;
|
||||
/** mesh stats: replies sent */
|
||||
size_t mesh_replies_sent;
|
||||
/** mesh stats: sum of waiting times for the replies */
|
||||
struct timeval mesh_replies_sum_wait;
|
||||
/** mesh stats: median of waiting times for replies (in sec) */
|
||||
double mesh_time_median;
|
||||
};
|
||||
/* stats struct */
|
||||
#include "libunbound/unbound.h"
|
||||
|
||||
/**
|
||||
* Initialize server stats to 0.
|
||||
* @param stats: what to init (this is alloced by the caller).
|
||||
* @param cfg: with extended statistics option.
|
||||
*/
|
||||
void server_stats_init(struct server_stats* stats, struct config_file* cfg);
|
||||
void server_stats_init(struct ub_server_stats* stats, struct config_file* cfg);
|
||||
|
||||
/** add query if it missed the cache */
|
||||
void server_stats_querymiss(struct server_stats* stats, struct worker* worker);
|
||||
void server_stats_querymiss(struct ub_server_stats* stats, struct worker* worker);
|
||||
|
||||
/** add query if was cached and also resulted in a prefetch */
|
||||
void server_stats_prefetch(struct server_stats* stats, struct worker* worker);
|
||||
void server_stats_prefetch(struct ub_server_stats* stats, struct worker* worker);
|
||||
|
||||
/** display the stats to the log */
|
||||
void server_stats_log(struct server_stats* stats, struct worker* worker,
|
||||
void server_stats_log(struct ub_server_stats* stats, struct worker* worker,
|
||||
int threadnum);
|
||||
|
||||
/**
|
||||
@@ -198,7 +78,7 @@ void server_stats_log(struct server_stats* stats, struct worker* worker,
|
||||
* @param reset: if stats can be reset.
|
||||
*/
|
||||
void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
struct stats_info* s, int reset);
|
||||
struct ub_stats_info* s, int reset);
|
||||
|
||||
/**
|
||||
* Compile stats into structure for this thread worker.
|
||||
@@ -208,7 +88,7 @@ void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
* @param reset: if true, depending on config stats are reset.
|
||||
* if false, statistics are not reset.
|
||||
*/
|
||||
void server_stats_compile(struct worker* worker, struct stats_info* s,
|
||||
void server_stats_compile(struct worker* worker, struct ub_stats_info* s,
|
||||
int reset);
|
||||
|
||||
/**
|
||||
@@ -224,7 +104,7 @@ void server_stats_reply(struct worker* worker, int reset);
|
||||
* @param total: sum of the two entries.
|
||||
* @param a: to add to it.
|
||||
*/
|
||||
void server_stats_add(struct stats_info* total, struct stats_info* a);
|
||||
void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a);
|
||||
|
||||
/**
|
||||
* Add stats for this query
|
||||
@@ -235,7 +115,7 @@ void server_stats_add(struct stats_info* total, struct stats_info* a);
|
||||
* @param edns: edns record
|
||||
* @param repinfo: reply info with remote address
|
||||
*/
|
||||
void server_stats_insquery(struct server_stats* stats, struct comm_point* c,
|
||||
void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
|
||||
uint16_t qtype, uint16_t qclass, struct edns_data* edns,
|
||||
struct comm_reply* repinfo);
|
||||
|
||||
@@ -244,6 +124,6 @@ void server_stats_insquery(struct server_stats* stats, struct comm_point* c,
|
||||
* @param stats: the stats
|
||||
* @param buf: buffer with rcode. If buffer is length0: not counted.
|
||||
*/
|
||||
void server_stats_insrcode(struct server_stats* stats, struct sldns_buffer* buf);
|
||||
void server_stats_insrcode(struct ub_server_stats* stats, struct sldns_buffer* buf);
|
||||
|
||||
#endif /* DAEMON_STATS_H */
|
||||
|
||||
+105
-44
@@ -67,6 +67,7 @@
|
||||
#ifdef HAVE_GRP_H
|
||||
#include <grp.h>
|
||||
#endif
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#ifndef S_SPLINT_S
|
||||
/* splint chokes on this system header file */
|
||||
@@ -87,30 +88,20 @@
|
||||
# include "nss.h"
|
||||
#endif
|
||||
|
||||
/** print usage. */
|
||||
static void usage(void)
|
||||
/** print build options. */
|
||||
static void
|
||||
print_build_options(void)
|
||||
{
|
||||
const char** m;
|
||||
const char *evnm="event", *evsys="", *evmethod="";
|
||||
time_t t;
|
||||
struct timeval now;
|
||||
struct ub_event_base* base;
|
||||
printf("usage: unbound [options]\n");
|
||||
printf(" start unbound daemon DNS resolver.\n");
|
||||
printf("-h this help\n");
|
||||
printf("-c file config file to read instead of %s\n", CONFIGFILE);
|
||||
printf(" file format is described in unbound.conf(5).\n");
|
||||
printf("-d do not fork into the background.\n");
|
||||
printf("-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("Version %s\n\n", PACKAGE_VERSION);
|
||||
printf("Configure line: %s\n", CONFCMDLINE);
|
||||
base = ub_default_event_base(0,&t,&now);
|
||||
ub_get_event_sys(base, &evnm, &evsys, &evmethod);
|
||||
printf("linked libs: %s %s (it uses %s), %s\n",
|
||||
printf("Linked libs: %s %s (it uses %s), %s\n",
|
||||
evnm, evsys, evmethod,
|
||||
#ifdef HAVE_SSL
|
||||
# ifdef SSLEAY_VERSION
|
||||
@@ -124,13 +115,42 @@ static void usage(void)
|
||||
"nettle"
|
||||
#endif
|
||||
);
|
||||
printf("linked modules:");
|
||||
printf("Linked modules:");
|
||||
for(m = module_list_avail(); *m; m++)
|
||||
printf(" %s", *m);
|
||||
printf("\n");
|
||||
#ifdef USE_DNSCRYPT
|
||||
printf("DNSCrypt feature available\n");
|
||||
#endif
|
||||
#ifdef USE_TCP_FASTOPEN
|
||||
printf("TCP Fastopen feature available\n");
|
||||
#endif
|
||||
ub_event_base_free(base);
|
||||
printf("\nBSD licensed, see LICENSE in source package for details.\n");
|
||||
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
|
||||
}
|
||||
|
||||
/** print usage. */
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("usage: unbound [options]\n");
|
||||
printf(" start unbound daemon DNS resolver.\n");
|
||||
printf("-h this help.\n");
|
||||
printf("-c file config file to read instead of %s\n", CONFIGFILE);
|
||||
printf(" file format is described in unbound.conf(5).\n");
|
||||
printf("-d do not fork into the background.\n");
|
||||
printf("-p do not create a pidfile.\n");
|
||||
printf("-v verbose (more times to increase verbosity).\n");
|
||||
printf("-V show version number and build options.\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("\nVersion %s\n", PACKAGE_VERSION);
|
||||
printf("BSD licensed, see LICENSE in source package for details.\n");
|
||||
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
|
||||
ub_event_base_free(base);
|
||||
}
|
||||
|
||||
#ifndef unbound_testbound
|
||||
@@ -264,6 +284,11 @@ apply_settings(struct daemon* daemon, struct config_file* cfg,
|
||||
}
|
||||
daemon_apply_cfg(daemon, cfg);
|
||||
checkrlimits(cfg);
|
||||
|
||||
if (cfg->use_systemd && cfg->do_daemonize) {
|
||||
log_warn("use-systemd and do-daemonize should not be enabled at the same time");
|
||||
}
|
||||
|
||||
log_ident_set_fromdefault(cfg, log_default_identity);
|
||||
}
|
||||
|
||||
@@ -392,10 +417,10 @@ detach(void)
|
||||
#endif /* HAVE_DAEMON */
|
||||
}
|
||||
|
||||
/** daemonize, drop user priviliges and chroot if needed */
|
||||
/** daemonize, drop user privileges and chroot if needed */
|
||||
static void
|
||||
perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
const char** cfgfile)
|
||||
const char** cfgfile, int need_pidfile)
|
||||
{
|
||||
#ifdef HAVE_KILL
|
||||
int pidinchroot;
|
||||
@@ -413,6 +438,38 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
w_config_adjust_directory(cfg);
|
||||
#endif
|
||||
|
||||
/* read ssl keys while superuser and outside chroot */
|
||||
#ifdef HAVE_SSL
|
||||
if(!(daemon->rc = daemon_remote_create(cfg)))
|
||||
fatal_exit("could not set up remote-control");
|
||||
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
|
||||
if(!(daemon->listen_sslctx = listen_sslctx_create(
|
||||
cfg->ssl_service_key, cfg->ssl_service_pem, NULL)))
|
||||
fatal_exit("could not set up listen SSL_CTX");
|
||||
if(cfg->tls_ciphers && cfg->tls_ciphers[0]) {
|
||||
if (!SSL_CTX_set_cipher_list(daemon->listen_sslctx, cfg->tls_ciphers)) {
|
||||
fatal_exit("failed to set tls-cipher %s", cfg->tls_ciphers);
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
|
||||
if(cfg->tls_ciphersuites && cfg->tls_ciphersuites[0]) {
|
||||
if (!SSL_CTX_set_ciphersuites(daemon->listen_sslctx, cfg->tls_ciphersuites)) {
|
||||
fatal_exit("failed to set tls-ciphersuites %s", cfg->tls_ciphersuites);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(cfg->tls_session_ticket_keys.first &&
|
||||
cfg->tls_session_ticket_keys.first->str[0] != 0) {
|
||||
if(!listen_sslctx_setup_ticket_keys(daemon->listen_sslctx, cfg->tls_session_ticket_keys.first)) {
|
||||
fatal_exit("could not set session ticket SSL_CTX");
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL,
|
||||
cfg->tls_cert_bundle, cfg->tls_win_cert)))
|
||||
fatal_exit("could not set up connect SSL_CTX");
|
||||
#endif
|
||||
|
||||
/* init syslog (as root) if needed, before daemonize, otherwise
|
||||
* a fork error could not be printed since daemonize closed stderr.*/
|
||||
if(cfg->use_syslog) {
|
||||
@@ -424,28 +481,15 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
* So, using a logfile, the user does not see errors unless -d is
|
||||
* given to unbound on the commandline. */
|
||||
|
||||
/* read ssl keys while superuser and outside chroot */
|
||||
#ifdef HAVE_SSL
|
||||
if(!(daemon->rc = daemon_remote_create(cfg)))
|
||||
fatal_exit("could not set up remote-control");
|
||||
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
|
||||
if(!(daemon->listen_sslctx = listen_sslctx_create(
|
||||
cfg->ssl_service_key, cfg->ssl_service_pem, NULL)))
|
||||
fatal_exit("could not set up listen SSL_CTX");
|
||||
}
|
||||
if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL, NULL)))
|
||||
fatal_exit("could not set up connect SSL_CTX");
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_KILL
|
||||
/* true if pidfile is inside chrootdir, or nochroot */
|
||||
pidinchroot = !(cfg->chrootdir && cfg->chrootdir[0]) ||
|
||||
pidinchroot = need_pidfile && (!(cfg->chrootdir && cfg->chrootdir[0]) ||
|
||||
(cfg->chrootdir && cfg->chrootdir[0] &&
|
||||
strncmp(cfg->pidfile, cfg->chrootdir,
|
||||
strlen(cfg->chrootdir))==0);
|
||||
strlen(cfg->chrootdir))==0));
|
||||
|
||||
/* check old pid file before forking */
|
||||
if(cfg->pidfile && cfg->pidfile[0]) {
|
||||
if(cfg->pidfile && cfg->pidfile[0] && need_pidfile) {
|
||||
/* calculate position of pidfile */
|
||||
if(cfg->pidfile[0] == '/')
|
||||
daemon->pidfile = strdup(cfg->pidfile);
|
||||
@@ -464,7 +508,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
|
||||
/* write new pidfile (while still root, so can be outside chroot) */
|
||||
#ifdef HAVE_KILL
|
||||
if(cfg->pidfile && cfg->pidfile[0]) {
|
||||
if(cfg->pidfile && cfg->pidfile[0] && need_pidfile) {
|
||||
writepid(daemon->pidfile, getpid());
|
||||
if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1 &&
|
||||
pidinchroot) {
|
||||
@@ -479,6 +523,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
}
|
||||
#else
|
||||
(void)daemon;
|
||||
(void)need_pidfile;
|
||||
#endif /* HAVE_KILL */
|
||||
|
||||
/* Set user context */
|
||||
@@ -595,9 +640,10 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
* These increase verbosity as specified in the config file.
|
||||
* @param debug_mode: if set, do not daemonize.
|
||||
* @param log_default_identity: Default identity to report in logs
|
||||
* @param need_pidfile: if false, no pidfile is checked or created.
|
||||
*/
|
||||
static void
|
||||
run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char* log_default_identity)
|
||||
run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char* log_default_identity, int need_pidfile)
|
||||
{
|
||||
struct config_file* cfg = NULL;
|
||||
struct daemon* daemon = NULL;
|
||||
@@ -615,8 +661,10 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char*
|
||||
fatal_exit("Could not alloc config defaults");
|
||||
if(!config_read(cfg, cfgfile, daemon->chroot)) {
|
||||
if(errno != ENOENT)
|
||||
fatal_exit("Could not read config file: %s",
|
||||
cfgfile);
|
||||
fatal_exit("Could not read config file: %s."
|
||||
" Maybe try unbound -dd, it stays on "
|
||||
"the commandline to see more errors, "
|
||||
"or unbound-checkconf", cfgfile);
|
||||
log_warn("Continuing with default config settings");
|
||||
}
|
||||
apply_settings(daemon, cfg, cmdline_verbose, debug_mode, log_default_identity);
|
||||
@@ -627,7 +675,7 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char*
|
||||
if(!daemon_open_shared_ports(daemon))
|
||||
fatal_exit("could not open ports");
|
||||
if(!done_setup) {
|
||||
perform_setup(daemon, cfg, debug_mode, &cfgfile);
|
||||
perform_setup(daemon, cfg, debug_mode, &cfgfile, need_pidfile);
|
||||
done_setup = 1;
|
||||
} else {
|
||||
/* reopen log after HUP to facilitate log rotation */
|
||||
@@ -677,6 +725,8 @@ main(int argc, char* argv[])
|
||||
const char* log_ident_default;
|
||||
int cmdline_verbose = 0;
|
||||
int debug_mode = 0;
|
||||
int need_pidfile = 1;
|
||||
|
||||
#ifdef UB_ON_WINDOWS
|
||||
int cmdline_cfg = 0;
|
||||
#endif
|
||||
@@ -685,7 +735,7 @@ main(int argc, char* argv[])
|
||||
log_ident_default = strrchr(argv[0],'/')?strrchr(argv[0],'/')+1:argv[0];
|
||||
log_ident_set(log_ident_default);
|
||||
/* parse the options */
|
||||
while( (c=getopt(argc, argv, "c:dhvw:")) != -1) {
|
||||
while( (c=getopt(argc, argv, "c:dhpvw:V")) != -1) {
|
||||
switch(c) {
|
||||
case 'c':
|
||||
cfgfile = optarg;
|
||||
@@ -697,12 +747,18 @@ main(int argc, char* argv[])
|
||||
cmdline_verbose++;
|
||||
verbosity++;
|
||||
break;
|
||||
case 'p':
|
||||
need_pidfile = 0;
|
||||
break;
|
||||
case 'd':
|
||||
debug_mode++;
|
||||
break;
|
||||
case 'w':
|
||||
winopt = optarg;
|
||||
break;
|
||||
case 'V':
|
||||
print_build_options();
|
||||
return 0;
|
||||
case '?':
|
||||
case 'h':
|
||||
default:
|
||||
@@ -711,7 +767,7 @@ main(int argc, char* argv[])
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
/* argv += optind; not using further arguments */
|
||||
|
||||
if(winopt) {
|
||||
#ifdef UB_ON_WINDOWS
|
||||
@@ -727,7 +783,12 @@ main(int argc, char* argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
run_daemon(cfgfile, cmdline_verbose, debug_mode, log_ident_default);
|
||||
run_daemon(cfgfile, cmdline_verbose, debug_mode, log_ident_default, need_pidfile);
|
||||
log_init(NULL, 0, NULL); /* close logfile */
|
||||
#ifndef unbound_testbound
|
||||
if(log_get_lock()) {
|
||||
lock_basic_destroy((lock_basic_type*)log_get_lock());
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
+659
-117
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -85,7 +85,7 @@ struct worker {
|
||||
/** global shared daemon structure */
|
||||
struct daemon* daemon;
|
||||
/** thread id */
|
||||
ub_thread_t thr_id;
|
||||
ub_thread_type thr_id;
|
||||
/** pipe, for commands for this worker */
|
||||
struct tube* cmd;
|
||||
/** the event base this worker works with */
|
||||
@@ -116,7 +116,7 @@ struct worker {
|
||||
/** allocation cache for this thread */
|
||||
struct alloc_cache alloc;
|
||||
/** per thread statistics */
|
||||
struct server_stats stats;
|
||||
struct ub_server_stats stats;
|
||||
/** thread scratch regional */
|
||||
struct regional* scratchpad;
|
||||
|
||||
|
||||
+220
-66
@@ -48,6 +48,9 @@
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/storage/dnstree.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "sldns/str2wire.h"
|
||||
|
||||
/******************************************************************************
|
||||
* *
|
||||
@@ -67,12 +70,9 @@ static const char DEFAULT_DNS64_PREFIX[] = "64:ff9b::/96";
|
||||
#define MAX_PTR_QNAME_IPV4 30
|
||||
|
||||
/**
|
||||
* Per-query module-specific state. This is usually a dynamically-allocated
|
||||
* structure, but in our case we only need to store one variable describing the
|
||||
* state the query is in. So we repurpose the minfo pointer by storing an
|
||||
* integer in there.
|
||||
* State of DNS64 processing for a query.
|
||||
*/
|
||||
enum dns64_qstate {
|
||||
enum dns64_state {
|
||||
DNS64_INTERNAL_QUERY, /**< Internally-generated query, no DNS64
|
||||
processing. */
|
||||
DNS64_NEW_QUERY, /**< Query for which we're the first module in
|
||||
@@ -81,6 +81,19 @@ enum dns64_qstate {
|
||||
for which this sub-query is finished. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Per-query module-specific state. For the DNS64 module.
|
||||
*/
|
||||
struct dns64_qstate {
|
||||
/** State of the DNS64 module. */
|
||||
enum dns64_state state;
|
||||
/** If the dns64 module started with no_cache bool set in the qstate,
|
||||
* a message to tell it to not modify the cache contents, then this
|
||||
* is true. The dns64 module is then free to modify that flag for
|
||||
* its own purposes.
|
||||
* Otherwise, it is false, the dns64 module was not told to no_cache */
|
||||
int started_no_cache_store;
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* *
|
||||
@@ -111,6 +124,11 @@ struct dns64_env {
|
||||
* This is the CIDR length of the prefix. It needs to be between 0 and 96.
|
||||
*/
|
||||
int prefix_net;
|
||||
|
||||
/**
|
||||
* Tree of names for which AAAA is ignored. always synthesize from A.
|
||||
*/
|
||||
rbtree_type ignore_aaaa;
|
||||
};
|
||||
|
||||
|
||||
@@ -173,16 +191,19 @@ uitoa(unsigned n, char* s)
|
||||
*
|
||||
* \param ipv6 IPv6 address represented as a 128-bit array in big-endian
|
||||
* order.
|
||||
* \param ipv6_len length of the ipv6 byte array.
|
||||
* \param offset Index of the MSB of the IPv4 address embedded in the IPv6
|
||||
* address.
|
||||
*/
|
||||
static uint32_t
|
||||
extract_ipv4(const uint8_t ipv6[16], const int offset)
|
||||
extract_ipv4(const uint8_t ipv6[], size_t ipv6_len, const int offset)
|
||||
{
|
||||
uint32_t ipv4 = (uint32_t)ipv6[offset/8+0] << (24 + (offset%8))
|
||||
| (uint32_t)ipv6[offset/8+1] << (16 + (offset%8))
|
||||
| (uint32_t)ipv6[offset/8+2] << ( 8 + (offset%8))
|
||||
| (uint32_t)ipv6[offset/8+3] << ( 0 + (offset%8));
|
||||
uint32_t ipv4;
|
||||
log_assert(ipv6_len == 16); (void)ipv6_len;
|
||||
ipv4 = (uint32_t)ipv6[offset/8+0] << (24 + (offset%8))
|
||||
| (uint32_t)ipv6[offset/8+1] << (16 + (offset%8))
|
||||
| (uint32_t)ipv6[offset/8+2] << ( 8 + (offset%8))
|
||||
| (uint32_t)ipv6[offset/8+3] << ( 0 + (offset%8));
|
||||
if (offset/8+4 < 16)
|
||||
ipv4 |= (uint32_t)ipv6[offset/8+4] >> (8 - offset%8);
|
||||
return ipv4;
|
||||
@@ -196,22 +217,26 @@ extract_ipv4(const uint8_t ipv6[16], const int offset)
|
||||
* \param ipv4 IPv4 address represented as an unsigned 32-bit number.
|
||||
* \param ptr The result will be written here. Must be large enough, be
|
||||
* careful!
|
||||
* \param nm_len length of the ptr buffer.
|
||||
*
|
||||
* \return The number of characters written.
|
||||
*/
|
||||
static size_t
|
||||
ipv4_to_ptr(uint32_t ipv4, char ptr[MAX_PTR_QNAME_IPV4])
|
||||
ipv4_to_ptr(uint32_t ipv4, char ptr[], size_t nm_len)
|
||||
{
|
||||
static const char IPV4_PTR_SUFFIX[] = "\07in-addr\04arpa";
|
||||
int i;
|
||||
char* c = ptr;
|
||||
log_assert(nm_len == MAX_PTR_QNAME_IPV4);
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
*c = uitoa((unsigned int)(ipv4 % 256), c + 1);
|
||||
c += *c + 1;
|
||||
log_assert(c < ptr+nm_len);
|
||||
ipv4 /= 256;
|
||||
}
|
||||
|
||||
log_assert(c + sizeof(IPV4_PTR_SUFFIX) <= ptr+nm_len);
|
||||
memmove(c, IPV4_PTR_SUFFIX, sizeof(IPV4_PTR_SUFFIX));
|
||||
|
||||
return c + sizeof(IPV4_PTR_SUFFIX) - ptr;
|
||||
@@ -223,13 +248,15 @@ ipv4_to_ptr(uint32_t ipv4, char ptr[MAX_PTR_QNAME_IPV4])
|
||||
*
|
||||
* \param ptr The domain name. (e.g. "\011[...]\010\012\016\012\03ip6\04arpa")
|
||||
* \param ipv6 The result will be written here, in network byte order.
|
||||
* \param ipv6_len length of the ipv6 byte array.
|
||||
*
|
||||
* \return 1 on success, 0 on failure.
|
||||
*/
|
||||
static int
|
||||
ptr_to_ipv6(const char* ptr, uint8_t ipv6[16])
|
||||
ptr_to_ipv6(const char* ptr, uint8_t ipv6[], size_t ipv6_len)
|
||||
{
|
||||
int i;
|
||||
log_assert(ipv6_len == 16); (void)ipv6_len;
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
int x;
|
||||
@@ -257,14 +284,20 @@ ptr_to_ipv6(const char* ptr, uint8_t ipv6[16])
|
||||
* Synthesize an IPv6 address based on an IPv4 address and the DNS64 prefix.
|
||||
*
|
||||
* \param prefix_addr DNS64 prefix address.
|
||||
* \param prefix_addr_len length of the prefix_addr buffer.
|
||||
* \param prefix_net CIDR length of the DNS64 prefix. Must be between 0 and 96.
|
||||
* \param a IPv4 address.
|
||||
* \param a_len length of the a buffer.
|
||||
* \param aaaa IPv6 address. The result will be written here.
|
||||
* \param aaaa_len length of the aaaa buffer.
|
||||
*/
|
||||
static void
|
||||
synthesize_aaaa(const uint8_t prefix_addr[16], int prefix_net,
|
||||
const uint8_t a[4], uint8_t aaaa[16])
|
||||
synthesize_aaaa(const uint8_t prefix_addr[], size_t prefix_addr_len,
|
||||
int prefix_net, const uint8_t a[], size_t a_len, uint8_t aaaa[],
|
||||
size_t aaaa_len)
|
||||
{
|
||||
log_assert(prefix_addr_len == 16 && a_len == 4 && aaaa_len == 16);
|
||||
(void)prefix_addr_len; (void)a_len; (void)aaaa_len;
|
||||
memcpy(aaaa, prefix_addr, 16);
|
||||
aaaa[prefix_net/8+0] |= a[0] >> (0+prefix_net%8);
|
||||
aaaa[prefix_net/8+1] |= a[0] << (8-prefix_net%8);
|
||||
@@ -284,6 +317,40 @@ synthesize_aaaa(const uint8_t prefix_addr[16], int prefix_net,
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* insert ignore_aaaa element into the tree
|
||||
* @param dns64_env: module env.
|
||||
* @param str: string with domain name.
|
||||
* @return false on failure.
|
||||
*/
|
||||
static int
|
||||
dns64_insert_ignore_aaaa(struct dns64_env* dns64_env, char* str)
|
||||
{
|
||||
/* parse and insert element */
|
||||
struct name_tree_node* node;
|
||||
node = (struct name_tree_node*)calloc(1, sizeof(*node));
|
||||
if(!node) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
node->name = sldns_str2wire_dname(str, &node->len);
|
||||
if(!node->name) {
|
||||
free(node);
|
||||
log_err("cannot parse dns64-ignore-aaaa: %s", str);
|
||||
return 0;
|
||||
}
|
||||
node->labs = dname_count_labels(node->name);
|
||||
node->dclass = LDNS_RR_CLASS_IN;
|
||||
if(!name_tree_insert(&dns64_env->ignore_aaaa, node,
|
||||
node->name, node->len, node->labs, node->dclass)) {
|
||||
/* ignore duplicate element */
|
||||
free(node->name);
|
||||
free(node);
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function applies the configuration found in the parsed configuration
|
||||
* file \a cfg to this instance of the dns64 module. Currently only the DNS64
|
||||
@@ -295,6 +362,7 @@ synthesize_aaaa(const uint8_t prefix_addr[16], int prefix_net,
|
||||
static int
|
||||
dns64_apply_cfg(struct dns64_env* dns64_env, struct config_file* cfg)
|
||||
{
|
||||
struct config_strlist* s;
|
||||
verbose(VERB_ALGO, "dns64-prefix: %s", cfg->dns64_prefix);
|
||||
if (!netblockstrtoaddr(cfg->dns64_prefix ? cfg->dns64_prefix :
|
||||
DEFAULT_DNS64_PREFIX, 0, &dns64_env->prefix_addr,
|
||||
@@ -311,6 +379,11 @@ dns64_apply_cfg(struct dns64_env* dns64_env, struct config_file* cfg)
|
||||
cfg->dns64_prefix);
|
||||
return 0;
|
||||
}
|
||||
for(s = cfg->dns64_ignore_aaaa; s; s = s->next) {
|
||||
if(!dns64_insert_ignore_aaaa(dns64_env, s->str))
|
||||
return 0;
|
||||
}
|
||||
name_tree_init_parents(&dns64_env->ignore_aaaa);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -329,7 +402,8 @@ dns64_init(struct module_env* env, int id)
|
||||
log_err("malloc failure");
|
||||
return 0;
|
||||
}
|
||||
env->modinfo[id] = (void*)dns64_env;
|
||||
env->modinfo[id] = (void*)dns64_env;
|
||||
name_tree_init(&dns64_env->ignore_aaaa);
|
||||
if (!dns64_apply_cfg(dns64_env, env->cfg)) {
|
||||
log_err("dns64: could not apply configuration settings.");
|
||||
return 0;
|
||||
@@ -337,6 +411,16 @@ dns64_init(struct module_env* env, int id)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** free ignore AAAA elements */
|
||||
static void
|
||||
free_ignore_aaaa_node(rbnode_type* node, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct name_tree_node* n = (struct name_tree_node*)node;
|
||||
if(!n) return;
|
||||
free(n->name);
|
||||
free(n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deinitializes this instance of the dns64 module.
|
||||
*
|
||||
@@ -346,8 +430,14 @@ dns64_init(struct module_env* env, int id)
|
||||
void
|
||||
dns64_deinit(struct module_env* env, int id)
|
||||
{
|
||||
struct dns64_env* dns64_env;
|
||||
if (!env)
|
||||
return;
|
||||
dns64_env = (struct dns64_env*)env->modinfo[id];
|
||||
if(dns64_env) {
|
||||
traverse_postorder(&dns64_env->ignore_aaaa, free_ignore_aaaa_node,
|
||||
NULL);
|
||||
}
|
||||
free(env->modinfo[id]);
|
||||
env->modinfo[id] = NULL;
|
||||
}
|
||||
@@ -372,7 +462,8 @@ handle_ipv6_ptr(struct module_qstate* qstate, int id)
|
||||
/* Convert the PTR query string to an IPv6 address. */
|
||||
memset(&sin6, 0, sizeof(sin6));
|
||||
sin6.sin6_family = AF_INET6;
|
||||
if (!ptr_to_ipv6((char*)qstate->qinfo.qname, sin6.sin6_addr.s6_addr))
|
||||
if (!ptr_to_ipv6((char*)qstate->qinfo.qname, sin6.sin6_addr.s6_addr,
|
||||
sizeof(sin6.sin6_addr.s6_addr)))
|
||||
return module_wait_module; /* Let other module handle this. */
|
||||
|
||||
/*
|
||||
@@ -395,7 +486,8 @@ handle_ipv6_ptr(struct module_qstate* qstate, int id)
|
||||
if (!(qinfo.qname = regional_alloc(qstate->region, MAX_PTR_QNAME_IPV4)))
|
||||
return module_error;
|
||||
qinfo.qname_len = ipv4_to_ptr(extract_ipv4(sin6.sin6_addr.s6_addr,
|
||||
dns64_env->prefix_net), (char*)qinfo.qname);
|
||||
sizeof(sin6.sin6_addr.s6_addr), dns64_env->prefix_net),
|
||||
(char*)qinfo.qname, MAX_PTR_QNAME_IPV4);
|
||||
|
||||
/* Create the new sub-query. */
|
||||
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
|
||||
@@ -405,37 +497,12 @@ handle_ipv6_ptr(struct module_qstate* qstate, int id)
|
||||
if (subq) {
|
||||
subq->curmod = id;
|
||||
subq->ext_state[id] = module_state_initial;
|
||||
subq->minfo[id] = NULL;
|
||||
subq->minfo[id] = NULL;
|
||||
}
|
||||
|
||||
return module_wait_subquery;
|
||||
}
|
||||
|
||||
/** allocate (special) rrset keys, return 0 on error */
|
||||
static int
|
||||
repinfo_alloc_rrset_keys(struct reply_info* rep,
|
||||
struct regional* region)
|
||||
{
|
||||
size_t i;
|
||||
for(i=0; i<rep->rrset_count; i++) {
|
||||
if(region) {
|
||||
rep->rrsets[i] = (struct ub_packed_rrset_key*)
|
||||
regional_alloc(region,
|
||||
sizeof(struct ub_packed_rrset_key));
|
||||
if(rep->rrsets[i]) {
|
||||
memset(rep->rrsets[i], 0,
|
||||
sizeof(struct ub_packed_rrset_key));
|
||||
rep->rrsets[i]->entry.key = rep->rrsets[i];
|
||||
}
|
||||
}
|
||||
else return 0;/* rep->rrsets[i] = alloc_special_obtain(alloc);*/
|
||||
if(!rep->rrsets[i])
|
||||
return 0;
|
||||
rep->rrsets[i]->entry.data = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static enum module_ext_state
|
||||
generate_type_A_query(struct module_qstate* qstate, int id)
|
||||
{
|
||||
@@ -465,6 +532,25 @@ generate_type_A_query(struct module_qstate* qstate, int id)
|
||||
return module_wait_subquery;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if query name is in the always synth config.
|
||||
* The ignore-aaaa list has names for which the AAAA for the domain is
|
||||
* ignored and the A is always used to create the answer.
|
||||
* @param qstate: query state.
|
||||
* @param id: module id.
|
||||
* @return true if the name is covered by ignore-aaaa.
|
||||
*/
|
||||
static int
|
||||
dns64_always_synth_for_qname(struct module_qstate* qstate, int id)
|
||||
{
|
||||
struct dns64_env* dns64_env = (struct dns64_env*)qstate->env->modinfo[id];
|
||||
int labs = dname_count_labels(qstate->qinfo.qname);
|
||||
struct name_tree_node* node = name_tree_lookup(&dns64_env->ignore_aaaa,
|
||||
qstate->qinfo.qname, qstate->qinfo.qname_len, labs,
|
||||
qstate->qinfo.qclass);
|
||||
return (node != NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the "pass" event for a query. This event is received when a new query
|
||||
* is received by this module. The query may have been generated internally by
|
||||
@@ -481,7 +567,8 @@ generate_type_A_query(struct module_qstate* qstate, int id)
|
||||
static enum module_ext_state
|
||||
handle_event_pass(struct module_qstate* qstate, int id)
|
||||
{
|
||||
if ((uintptr_t)qstate->minfo[id] == DNS64_NEW_QUERY
|
||||
struct dns64_qstate* iq = (struct dns64_qstate*)qstate->minfo[id];
|
||||
if (iq && iq->state == DNS64_NEW_QUERY
|
||||
&& qstate->qinfo.qtype == LDNS_RR_TYPE_PTR
|
||||
&& qstate->qinfo.qname_len == 74
|
||||
&& !strcmp((char*)&qstate->qinfo.qname[64], "\03ip6\04arpa"))
|
||||
@@ -489,12 +576,20 @@ handle_event_pass(struct module_qstate* qstate, int id)
|
||||
return handle_ipv6_ptr(qstate, id);
|
||||
|
||||
if (qstate->env->cfg->dns64_synthall &&
|
||||
(uintptr_t)qstate->minfo[id] == DNS64_NEW_QUERY
|
||||
iq && iq->state == DNS64_NEW_QUERY
|
||||
&& qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA)
|
||||
return generate_type_A_query(qstate, id);
|
||||
|
||||
if(dns64_always_synth_for_qname(qstate, id) &&
|
||||
iq && iq->state == DNS64_NEW_QUERY
|
||||
&& !(qstate->query_flags & BIT_CD)
|
||||
&& qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) {
|
||||
verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway");
|
||||
return generate_type_A_query(qstate, id);
|
||||
}
|
||||
|
||||
/* We are finished when our sub-query is finished. */
|
||||
if ((uintptr_t)qstate->minfo[id] == DNS64_SUBQUERY_FINISHED)
|
||||
if (iq && iq->state == DNS64_SUBQUERY_FINISHED)
|
||||
return module_finished;
|
||||
|
||||
/* Otherwise, pass request to next module. */
|
||||
@@ -515,6 +610,7 @@ handle_event_pass(struct module_qstate* qstate, int id)
|
||||
static enum module_ext_state
|
||||
handle_event_moddone(struct module_qstate* qstate, int id)
|
||||
{
|
||||
struct dns64_qstate* iq = (struct dns64_qstate*)qstate->minfo[id];
|
||||
/*
|
||||
* In many cases we have nothing special to do. From most to least common:
|
||||
*
|
||||
@@ -526,17 +622,36 @@ handle_event_moddone(struct module_qstate* qstate, int id)
|
||||
* synthesize in (sec 5.1.2 of RFC6147).
|
||||
* - A successful AAAA query with an answer.
|
||||
*/
|
||||
if ( (enum dns64_qstate)qstate->minfo[id] == DNS64_INTERNAL_QUERY
|
||||
|| qstate->qinfo.qtype != LDNS_RR_TYPE_AAAA
|
||||
|| (qstate->query_flags & BIT_CD)
|
||||
|| (qstate->return_msg &&
|
||||
if((!iq || iq->state != DNS64_INTERNAL_QUERY)
|
||||
&& qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA
|
||||
&& !(qstate->query_flags & BIT_CD)
|
||||
&& !(qstate->return_msg &&
|
||||
qstate->return_msg->rep &&
|
||||
reply_find_answer_rrset(&qstate->qinfo,
|
||||
qstate->return_msg->rep)))
|
||||
return module_finished;
|
||||
/* not internal, type AAAA, not CD, and no answer RRset,
|
||||
* So, this is a AAAA noerror/nodata answer */
|
||||
return generate_type_A_query(qstate, id);
|
||||
|
||||
/* So, this is a AAAA noerror/nodata answer */
|
||||
return generate_type_A_query(qstate, id);
|
||||
if((!iq || iq->state != DNS64_INTERNAL_QUERY)
|
||||
&& qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA
|
||||
&& !(qstate->query_flags & BIT_CD)
|
||||
&& dns64_always_synth_for_qname(qstate, id)) {
|
||||
/* if it is not internal, AAAA, not CD and listed domain,
|
||||
* generate from A record and ignore AAAA */
|
||||
verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway");
|
||||
return generate_type_A_query(qstate, id);
|
||||
}
|
||||
|
||||
/* Store the response in cache. */
|
||||
if ( (!iq || !iq->started_no_cache_store) &&
|
||||
qstate->return_msg && qstate->return_msg->rep &&
|
||||
!dns_cache_store(qstate->env, &qstate->qinfo, qstate->return_msg->rep,
|
||||
0, 0, 0, NULL, qstate->query_flags))
|
||||
log_err("out of memory");
|
||||
|
||||
/* do nothing */
|
||||
return module_finished;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -555,6 +670,7 @@ void
|
||||
dns64_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
struct outbound_entry* outbound)
|
||||
{
|
||||
struct dns64_qstate* iq;
|
||||
(void)outbound;
|
||||
verbose(VERB_QUERY, "dns64[module %d] operate: extstate:%s event:%s",
|
||||
id, strextstate(qstate->ext_state[id]),
|
||||
@@ -564,7 +680,13 @@ dns64_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
switch(event) {
|
||||
case module_event_new:
|
||||
/* Tag this query as being new and fall through. */
|
||||
qstate->minfo[id] = (void*)DNS64_NEW_QUERY;
|
||||
iq = (struct dns64_qstate*)regional_alloc(
|
||||
qstate->region, sizeof(*iq));
|
||||
qstate->minfo[id] = iq;
|
||||
iq->state = DNS64_NEW_QUERY;
|
||||
iq->started_no_cache_store = qstate->no_cache_store;
|
||||
qstate->no_cache_store = 1;
|
||||
/* fallthrough */
|
||||
case module_event_pass:
|
||||
qstate->ext_state[id] = handle_event_pass(qstate, id);
|
||||
break;
|
||||
@@ -575,6 +697,11 @@ dns64_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
qstate->ext_state[id] = module_finished;
|
||||
break;
|
||||
}
|
||||
if(qstate->ext_state[id] == module_finished) {
|
||||
iq = (struct dns64_qstate*)qstate->minfo[id];
|
||||
if(iq && iq->state != DNS64_INTERNAL_QUERY)
|
||||
qstate->no_cache_store = iq->started_no_cache_store;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -630,8 +757,10 @@ dns64_synth_aaaa_data(const struct ub_packed_rrset_key* fk,
|
||||
dd->rr_data[i][1] = 16;
|
||||
synthesize_aaaa(
|
||||
((struct sockaddr_in6*)&dns64_env->prefix_addr)->sin6_addr.s6_addr,
|
||||
sizeof(((struct sockaddr_in6*)&dns64_env->prefix_addr)->sin6_addr.s6_addr),
|
||||
dns64_env->prefix_net, &fd->rr_data[i][2],
|
||||
&dd->rr_data[i][2] );
|
||||
fd->rr_len[i]-2, &dd->rr_data[i][2],
|
||||
dd->rr_len[i]-2);
|
||||
dd->rr_ttl[i] = fd->rr_ttl[i];
|
||||
}
|
||||
|
||||
@@ -701,13 +830,14 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
||||
* Build the actual reply.
|
||||
*/
|
||||
cp = construct_reply_info_base(super->region, rep->flags, rep->qdcount,
|
||||
rep->ttl, rep->prefetch_ttl, rep->an_numrrsets, rep->ns_numrrsets,
|
||||
rep->ar_numrrsets, rep->rrset_count, rep->security);
|
||||
rep->ttl, rep->prefetch_ttl, rep->serve_expired_ttl,
|
||||
rep->an_numrrsets, rep->ns_numrrsets, rep->ar_numrrsets,
|
||||
rep->rrset_count, rep->security);
|
||||
if(!cp)
|
||||
return;
|
||||
|
||||
/* allocate ub_key structures special or not */
|
||||
if(!repinfo_alloc_rrset_keys(cp, super->region)) {
|
||||
if(!reply_info_alloc_rrset_keys(cp, NULL, super->region)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -729,6 +859,12 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
||||
rrset_cache_remove(super->env->rrset_cache, dk->rk.dname,
|
||||
dk->rk.dname_len, LDNS_RR_TYPE_AAAA,
|
||||
LDNS_RR_CLASS_IN, 0);
|
||||
/* Delete negative AAAA in msg cache for CNAMEs,
|
||||
* stored by the iterator module */
|
||||
if(i != 0) /* if not the first RR */
|
||||
msg_cache_remove(super->env, dk->rk.dname,
|
||||
dk->rk.dname_len, LDNS_RR_TYPE_AAAA,
|
||||
LDNS_RR_CLASS_IN, 0);
|
||||
} else {
|
||||
dk->entry.hash = fk->entry.hash;
|
||||
dk->rk.dname = (uint8_t*)regional_alloc_init(super->region,
|
||||
@@ -780,9 +916,10 @@ dns64_adjust_ptr(struct module_qstate* qstate, struct module_qstate* super)
|
||||
* initial query's domain name.
|
||||
*/
|
||||
answer = reply_find_answer_rrset(&qstate->qinfo, super->return_msg->rep);
|
||||
log_assert(answer);
|
||||
answer->rk.dname = super->qinfo.qname;
|
||||
answer->rk.dname_len = super->qinfo.qname_len;
|
||||
if(answer) {
|
||||
answer->rk.dname = super->qinfo.qname;
|
||||
answer->rk.dname_len = super->qinfo.qname_len;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -798,6 +935,7 @@ void
|
||||
dns64_inform_super(struct module_qstate* qstate, int id,
|
||||
struct module_qstate* super)
|
||||
{
|
||||
struct dns64_qstate* super_dq = (struct dns64_qstate*)super->minfo[id];
|
||||
log_query_info(VERB_ALGO, "dns64: inform_super, sub is",
|
||||
&qstate->qinfo);
|
||||
log_query_info(VERB_ALGO, "super is", &super->qinfo);
|
||||
@@ -806,15 +944,31 @@ dns64_inform_super(struct module_qstate* qstate, int id,
|
||||
* Signal that the sub-query is finished, no matter whether we are
|
||||
* successful or not. This lets the state machine terminate.
|
||||
*/
|
||||
super->minfo[id] = (void*)DNS64_SUBQUERY_FINISHED;
|
||||
if(!super_dq) {
|
||||
super_dq = (struct dns64_qstate*)regional_alloc(super->region,
|
||||
sizeof(*super_dq));
|
||||
if(!super_dq) {
|
||||
log_err("out of memory");
|
||||
super->return_rcode = LDNS_RCODE_SERVFAIL;
|
||||
super->return_msg = NULL;
|
||||
return;
|
||||
}
|
||||
super->minfo[id] = super_dq;
|
||||
memset(super_dq, 0, sizeof(*super_dq));
|
||||
super_dq->started_no_cache_store = super->no_cache_store;
|
||||
}
|
||||
super_dq->state = DNS64_SUBQUERY_FINISHED;
|
||||
|
||||
/* If there is no successful answer, we're done. */
|
||||
if (qstate->return_rcode != LDNS_RCODE_NOERROR
|
||||
|| !qstate->return_msg
|
||||
|| !qstate->return_msg->rep
|
||||
|| !reply_find_answer_rrset(&qstate->qinfo,
|
||||
qstate->return_msg->rep))
|
||||
|| !qstate->return_msg->rep) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Use return code from A query in response to client. */
|
||||
if (super->return_rcode != LDNS_RCODE_NOERROR)
|
||||
super->return_rcode = qstate->return_rcode;
|
||||
|
||||
/* Generate a response suitable for the original query. */
|
||||
if (qstate->qinfo.qtype == LDNS_RR_TYPE_A) {
|
||||
@@ -825,7 +979,7 @@ dns64_inform_super(struct module_qstate* qstate, int id,
|
||||
}
|
||||
|
||||
/* Store the generated response in cache. */
|
||||
if (!super->no_cache_store &&
|
||||
if ( (!super_dq || !super_dq->started_no_cache_store) &&
|
||||
!dns_cache_store(super->env, &super->qinfo, super->return_msg->rep,
|
||||
0, 0, 0, NULL, super->query_flags))
|
||||
log_err("out of memory");
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef UNBOUND_DNSCRYPT_CERT_H
|
||||
#define UNBOUND_DNSCRYPT_CERT_H
|
||||
|
||||
/**
|
||||
* \file
|
||||
* certificate type for dnscrypt for use in other header files
|
||||
*/
|
||||
|
||||
#include <sodium.h>
|
||||
#define CERT_MAGIC_CERT "DNSC"
|
||||
#define CERT_MAJOR_VERSION 1
|
||||
#define CERT_MINOR_VERSION 0
|
||||
#define CERT_OLD_MAGIC_HEADER "7PYqwfzt"
|
||||
|
||||
#define CERT_FILE_EXPIRE_DAYS 365
|
||||
|
||||
struct SignedCert {
|
||||
uint8_t magic_cert[4];
|
||||
uint8_t version_major[2];
|
||||
uint8_t version_minor[2];
|
||||
|
||||
// Signed Content
|
||||
uint8_t signed_content[64];
|
||||
uint8_t server_publickey[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t magic_query[8];
|
||||
uint8_t serial[4];
|
||||
uint8_t ts_begin[4];
|
||||
uint8_t ts_end[4];
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
+1108
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,175 @@
|
||||
#ifndef UNBOUND_DNSCRYPT_H
|
||||
#define UNBOUND_DNSCRYPT_H
|
||||
|
||||
/**
|
||||
* \file
|
||||
* dnscrypt functions for encrypting DNS packets.
|
||||
*/
|
||||
|
||||
#include "dnscrypt/dnscrypt_config.h"
|
||||
#ifdef USE_DNSCRYPT
|
||||
|
||||
#define DNSCRYPT_MAGIC_HEADER_LEN 8U
|
||||
#define DNSCRYPT_MAGIC_RESPONSE "r6fnvWj8"
|
||||
|
||||
#ifndef DNSCRYPT_MAX_PADDING
|
||||
# define DNSCRYPT_MAX_PADDING 256U
|
||||
#endif
|
||||
#ifndef DNSCRYPT_BLOCK_SIZE
|
||||
# define DNSCRYPT_BLOCK_SIZE 64U
|
||||
#endif
|
||||
#ifndef DNSCRYPT_MIN_PAD_LEN
|
||||
# define DNSCRYPT_MIN_PAD_LEN 8U
|
||||
#endif
|
||||
|
||||
#define crypto_box_HALF_NONCEBYTES (crypto_box_NONCEBYTES / 2U)
|
||||
|
||||
#include "config.h"
|
||||
#include "dnscrypt/cert.h"
|
||||
#include "util/locks.h"
|
||||
|
||||
#define DNSCRYPT_QUERY_HEADER_SIZE \
|
||||
(DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_PUBLICKEYBYTES + crypto_box_HALF_NONCEBYTES + crypto_box_MACBYTES)
|
||||
#define DNSCRYPT_RESPONSE_HEADER_SIZE \
|
||||
(DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_NONCEBYTES + crypto_box_MACBYTES)
|
||||
|
||||
#define DNSCRYPT_REPLY_HEADER_SIZE \
|
||||
(DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_HALF_NONCEBYTES * 2 + crypto_box_MACBYTES)
|
||||
|
||||
struct sldns_buffer;
|
||||
struct config_file;
|
||||
struct comm_reply;
|
||||
struct slabhash;
|
||||
|
||||
typedef struct KeyPair_ {
|
||||
uint8_t crypt_publickey[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t crypt_secretkey[crypto_box_SECRETKEYBYTES];
|
||||
} KeyPair;
|
||||
|
||||
typedef struct cert_ {
|
||||
uint8_t magic_query[DNSCRYPT_MAGIC_HEADER_LEN];
|
||||
uint8_t es_version[2];
|
||||
KeyPair *keypair;
|
||||
} dnsccert;
|
||||
|
||||
struct dnsc_env {
|
||||
struct SignedCert *signed_certs;
|
||||
struct SignedCert **rotated_certs;
|
||||
dnsccert *certs;
|
||||
size_t signed_certs_count;
|
||||
size_t rotated_certs_count;
|
||||
uint8_t provider_publickey[crypto_sign_ed25519_PUBLICKEYBYTES];
|
||||
uint8_t provider_secretkey[crypto_sign_ed25519_SECRETKEYBYTES];
|
||||
KeyPair *keypairs;
|
||||
size_t keypairs_count;
|
||||
uint64_t nonce_ts_last;
|
||||
unsigned char hash_key[crypto_shorthash_KEYBYTES];
|
||||
char * provider_name;
|
||||
|
||||
/** Caches */
|
||||
struct slabhash *shared_secrets_cache;
|
||||
/** lock on shared secret cache counters */
|
||||
lock_basic_type shared_secrets_cache_lock;
|
||||
/** number of misses from shared_secrets_cache */
|
||||
size_t num_query_dnscrypt_secret_missed_cache;
|
||||
|
||||
/** slabhash keeping track of nonce/cient pk/server sk pairs. */
|
||||
struct slabhash *nonces_cache;
|
||||
/** lock on nonces_cache, used to avoid race condition in updating the hash */
|
||||
lock_basic_type nonces_cache_lock;
|
||||
/** number of replayed queries */
|
||||
size_t num_query_dnscrypt_replay;
|
||||
};
|
||||
|
||||
struct dnscrypt_query_header {
|
||||
uint8_t magic_query[DNSCRYPT_MAGIC_HEADER_LEN];
|
||||
uint8_t publickey[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t nonce[crypto_box_HALF_NONCEBYTES];
|
||||
uint8_t mac[crypto_box_MACBYTES];
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize DNSCrypt environment.
|
||||
* Initialize sodium library and allocate the dnsc_env structure.
|
||||
* \return an uninitialized struct dnsc_env.
|
||||
*/
|
||||
struct dnsc_env * dnsc_create(void);
|
||||
|
||||
/**
|
||||
* Apply configuration.
|
||||
* Read certificates and secret keys from configuration. Initialize hashkey and
|
||||
* provider name as well as loading cert TXT records.
|
||||
* In case of issue applying configuration, this function fatals.
|
||||
* \param[in] env the struct dnsc_env to populate.
|
||||
* \param[in] cfg the config_file struct with dnscrypt options.
|
||||
* \return 0 on success.
|
||||
*/
|
||||
int dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg);
|
||||
|
||||
/**
|
||||
* Delete DNSCrypt environment
|
||||
*
|
||||
*/
|
||||
void dnsc_delete(struct dnsc_env *env);
|
||||
|
||||
/**
|
||||
* handle a crypted dnscrypt request.
|
||||
* Determine wether or not a query is coming over the dnscrypt listener and
|
||||
* attempt to uncurve it or detect if it is a certificate query.
|
||||
* return 0 in case of failure.
|
||||
*/
|
||||
int dnsc_handle_curved_request(struct dnsc_env* dnscenv,
|
||||
struct comm_reply* repinfo);
|
||||
/**
|
||||
* handle an unencrypted dnscrypt request.
|
||||
* Determine wether or not a query is going over the dnscrypt channel and
|
||||
* attempt to curve it unless it was not crypted like when it is a
|
||||
* certificate query.
|
||||
* \return 0 in case of failure.
|
||||
*/
|
||||
|
||||
int dnsc_handle_uncurved_request(struct comm_reply *repinfo);
|
||||
|
||||
/**
|
||||
* Computes the size of the shared secret cache entry.
|
||||
*/
|
||||
size_t dnsc_shared_secrets_sizefunc(void *k, void *d);
|
||||
|
||||
/**
|
||||
* Compares two shared secret cache keys.
|
||||
*/
|
||||
int dnsc_shared_secrets_compfunc(void *m1, void *m2);
|
||||
|
||||
/**
|
||||
* Function to delete a shared secret cache key.
|
||||
*/
|
||||
void dnsc_shared_secrets_delkeyfunc(void *k, void* arg);
|
||||
|
||||
/**
|
||||
* Function to delete a share secret cache value.
|
||||
*/
|
||||
void dnsc_shared_secrets_deldatafunc(void* d, void* arg);
|
||||
|
||||
/**
|
||||
* Computes the size of the nonce cache entry.
|
||||
*/
|
||||
size_t dnsc_nonces_sizefunc(void *k, void *d);
|
||||
|
||||
/**
|
||||
* Compares two nonce cache keys.
|
||||
*/
|
||||
int dnsc_nonces_compfunc(void *m1, void *m2);
|
||||
|
||||
/**
|
||||
* Function to delete a nonce cache key.
|
||||
*/
|
||||
void dnsc_nonces_delkeyfunc(void *k, void* arg);
|
||||
|
||||
/**
|
||||
* Function to delete a nonce cache value.
|
||||
*/
|
||||
void dnsc_nonces_deldatafunc(void* d, void* arg);
|
||||
|
||||
|
||||
#endif /* USE_DNSCRYPT */
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
# dnscrypt.m4
|
||||
|
||||
# dnsc_DNSCRYPT([action-if-true], [action-if-false])
|
||||
# --------------------------------------------------------------------------
|
||||
# Check for required dnscrypt libraries and add dnscrypt configure args.
|
||||
AC_DEFUN([dnsc_DNSCRYPT],
|
||||
[
|
||||
AC_ARG_ENABLE([dnscrypt],
|
||||
AS_HELP_STRING([--enable-dnscrypt],
|
||||
[Enable dnscrypt support (requires libsodium)]),
|
||||
[opt_dnscrypt=$enableval], [opt_dnscrypt=no])
|
||||
|
||||
if test "x$opt_dnscrypt" != "xno"; then
|
||||
AC_ARG_WITH([libsodium], AC_HELP_STRING([--with-libsodium=path],
|
||||
[Path where libsodium is installed, for dnscrypt]), [
|
||||
CFLAGS="$CFLAGS -I$withval/include"
|
||||
LDFLAGS="$LDFLAGS -L$withval/lib"
|
||||
])
|
||||
AC_SEARCH_LIBS([sodium_init], [sodium], [],
|
||||
AC_MSG_ERROR([The sodium library was not found. Please install sodium!]))
|
||||
AC_SEARCH_LIBS([crypto_box_curve25519xchacha20poly1305_beforenm], [sodium],
|
||||
[
|
||||
AC_SUBST([ENABLE_DNSCRYPT_XCHACHA20], [1])
|
||||
AC_DEFINE(
|
||||
[USE_DNSCRYPT_XCHACHA20], [1],
|
||||
[Define to 1 to enable dnscrypt with xchacha20 support])
|
||||
],
|
||||
[
|
||||
AC_SUBST([ENABLE_DNSCRYPT_XCHACHA20], [0])
|
||||
])
|
||||
AC_SEARCH_LIBS([sodium_set_misuse_handler], [sodium],
|
||||
[
|
||||
AC_DEFINE(
|
||||
[SODIUM_MISUSE_HANDLER], [1],
|
||||
[Define to 1 if libsodium supports sodium_set_misuse_handler])
|
||||
],
|
||||
[
|
||||
])
|
||||
$1
|
||||
else
|
||||
AC_SUBST([ENABLE_DNSCRYPT_XCHACHA20], [0])
|
||||
$2
|
||||
fi
|
||||
])
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef UNBOUND_DNSCRYPT_CONFIG_H
|
||||
#define UNBOUND_DNSCRYPT_CONFIG_H
|
||||
|
||||
/*
|
||||
* Process this file (dnscrypt_config.h.in) with AC_CONFIG_FILES to generate
|
||||
* dnscrypt_config.h.
|
||||
*
|
||||
* This file exists so that USE_DNSCRYPT can be used without including config.h.
|
||||
*/
|
||||
|
||||
#if @ENABLE_DNSCRYPT@ /* ENABLE_DNSCRYPT */
|
||||
# ifndef USE_DNSCRYPT
|
||||
# define USE_DNSCRYPT 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* UNBOUND_DNSCRYPT_CONFIG_H */
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
CERT_EXPIRE_DAYS="$(( 365 * 15 ))"
|
||||
DIR="$(dirname "$0")"
|
||||
|
||||
|
||||
if [[ "$PWD" != *tdir ]]
|
||||
then
|
||||
echo "You should run this script with a .tdir directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for i in 1 2
|
||||
do
|
||||
# Ephemeral key
|
||||
rm -f "${i}.key"
|
||||
dnscrypt-wrapper --gen-crypt-keypair \
|
||||
--crypt-secretkey-file="${i}.key" \
|
||||
--provider-publickey-file="${DIR}/keys${i}/public.key" \
|
||||
--provider-secretkey-file="${DIR}/keys${i}/secret.key"
|
||||
# Cert file
|
||||
for cipher in salsa chacha
|
||||
do
|
||||
rm -f "${i}_${cipher}.cert"
|
||||
extraarg=""
|
||||
if [ "${cipher}" == "chacha" ]
|
||||
then
|
||||
extraarg="-x"
|
||||
fi
|
||||
|
||||
dnscrypt-wrapper ${extraarg} --gen-cert-file \
|
||||
--provider-cert-file="${i}_${cipher}.cert" \
|
||||
--crypt-secretkey-file="${i}.key" \
|
||||
--provider-publickey-file="${DIR}/keys${i}/public.key" \
|
||||
--provider-secretkey-file="${DIR}/keys${i}/secret.key" \
|
||||
--cert-file-expire-days="${CERT_EXPIRE_DAYS}"
|
||||
done
|
||||
done
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
¸_A¡O#÷ÛÈfó—ÌoD¶_�eŶ)|'T¦éÜòO�
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
-&ç6\Uùõñh`^"…ºz/C9‚
óˆ¸_A¡O#÷ÛÈfó—ÌoD¶_�eŶ)|'T¦éÜòO�
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
ΓR ς�ύeµτ{φl�ΑKΛ€Ξ:5r\±}KΣηƒ
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
ηi%‚ 5fΝ™–νΙϋ�νBnκΝ―.Ί“ΓR ς�ύeµτ{φl�ΑKΛ€Ξ:5r\±}KΣηƒ
|
||||
+25
-1
@@ -39,6 +39,10 @@
|
||||
#include "config.h"
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
@@ -118,10 +122,24 @@ dt_msg_init(const struct dt_env *env,
|
||||
}
|
||||
}
|
||||
|
||||
/* check that the socket file can be opened and exists, print error if not */
|
||||
static void
|
||||
check_socket_file(const char* socket_path)
|
||||
{
|
||||
struct stat statbuf;
|
||||
memset(&statbuf, 0, sizeof(statbuf));
|
||||
if(stat(socket_path, &statbuf) < 0) {
|
||||
log_warn("could not open dnstap-socket-path: %s, %s",
|
||||
socket_path, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
struct dt_env *
|
||||
dt_create(const char *socket_path, unsigned num_workers)
|
||||
{
|
||||
#ifdef UNBOUND_DEBUG
|
||||
fstrm_res res;
|
||||
#endif
|
||||
struct dt_env *env;
|
||||
struct fstrm_iothr_options *fopt;
|
||||
struct fstrm_unix_writer_options *fuwopt;
|
||||
@@ -132,13 +150,19 @@ dt_create(const char *socket_path, unsigned num_workers)
|
||||
socket_path);
|
||||
log_assert(socket_path != NULL);
|
||||
log_assert(num_workers > 0);
|
||||
check_socket_file(socket_path);
|
||||
|
||||
env = (struct dt_env *) calloc(1, sizeof(struct dt_env));
|
||||
if (!env)
|
||||
return NULL;
|
||||
|
||||
fwopt = fstrm_writer_options_init();
|
||||
res = fstrm_writer_options_add_content_type(fwopt,
|
||||
#ifdef UNBOUND_DEBUG
|
||||
res =
|
||||
#else
|
||||
(void)
|
||||
#endif
|
||||
fstrm_writer_options_add_content_type(fwopt,
|
||||
DNSTAP_CONTENT_TYPE, sizeof(DNSTAP_CONTENT_TYPE) - 1);
|
||||
log_assert(res == fstrm_res_success);
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
// with this file. If not, see:
|
||||
//
|
||||
// <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
syntax = "proto2";
|
||||
|
||||
package dnstap;
|
||||
|
||||
|
||||
Binary file not shown.
+2350
-1
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+3
-1
@@ -76,6 +76,8 @@ The DNSTAP code has BSD license in dnstap/dnstap.c.
|
||||
Disable support for RSASHA256 and RSASHA512 crypto.
|
||||
* --disable-gost
|
||||
Disable support for GOST crypto, RFC 5933.
|
||||
* --enable-subnet
|
||||
Enable EDNS client subnet processing.
|
||||
|
||||
* 'make test' runs a series of self checks.
|
||||
|
||||
@@ -97,7 +99,7 @@ o If you are not receiving the correct source IP address on replies (e.g.
|
||||
the config file is an alternative. The interface-automatic option uses
|
||||
non portable socket options, Linux and FreeBSD should work fine.
|
||||
o The warning 'openssl has no entropy, seeding with time', with chroot
|
||||
enabled, may be solved with a symbolic link to /dev/random from <chrootdir>.
|
||||
enabled, may be solved with a symbolic link to /dev/urandom from <chrootdir>.
|
||||
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...].
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
## Created a module to support the ipset that could add the domain's ip to a list easily.
|
||||
|
||||
### Purposes:
|
||||
* In my case, I can't access the facebook, twitter, youtube and thousands web site for some reason. VPN is a solution. But the internet too slow whether all traffics pass through the vpn.
|
||||
So, I set up a transparent proxy to proxy the traffic which has been blocked only.
|
||||
At the final step, I need to install a dns service which would work with ipset well to launch the system.
|
||||
I did some research for this. Unfortunately, Unbound, My favorite dns service doesn't support ipset yet. So, I decided to implement it by my self and contribute the patch. It's good for me and the community.
|
||||
```
|
||||
# unbound.conf
|
||||
server:
|
||||
...
|
||||
local-zone: "facebook.com" ipset
|
||||
local-zone: "twitter.com" ipset
|
||||
local-zone: "instagram.com" ipset
|
||||
more social website
|
||||
|
||||
ipset:
|
||||
name-v4: "gfwlist"
|
||||
```
|
||||
```
|
||||
# iptables
|
||||
iptables -A PREROUTING -p tcp -m set --match-set gfwlist dst -j REDIRECT --to-ports 10800
|
||||
iptables -A OUTPUT -p tcp -m set --match-set gfwlist dst -j REDIRECT --to-ports 10800
|
||||
```
|
||||
|
||||
* This patch could work with iptables rules to batch block the IPs.
|
||||
```
|
||||
# unbound.conf
|
||||
server:
|
||||
...
|
||||
local-zone: "facebook.com" ipset
|
||||
local-zone: "twitter.com" ipset
|
||||
local-zone: "instagram.com" ipset
|
||||
more social website
|
||||
|
||||
ipset:
|
||||
name-v4: "blacklist"
|
||||
name-v6: "blacklist6"
|
||||
```
|
||||
```
|
||||
# iptables
|
||||
iptables -A INPUT -m set --set blacklist src -j DROP
|
||||
ip6tables -A INPUT -m set --set blacklist6 src -j DROP
|
||||
```
|
||||
|
||||
### Notes:
|
||||
* To enable this module the root privileges is required.
|
||||
* Please create a set with ipset command first. eg. **ipset -N blacklist iphash**
|
||||
|
||||
### How to use:
|
||||
```
|
||||
./configure --enable-ipset
|
||||
make && make install
|
||||
```
|
||||
|
||||
### Configuration:
|
||||
```
|
||||
# unbound.conf
|
||||
server:
|
||||
...
|
||||
local-zone: "example.com" ipset
|
||||
|
||||
ipset:
|
||||
name-v4: "blacklist"
|
||||
```
|
||||
@@ -29,7 +29,7 @@ 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.
|
||||
perhaps also print reminder to link /dev/urandom and sysloghack.
|
||||
o overhaul outside-network servicedquery to merge with udpwait and tcpwait,
|
||||
to make timers in servicedquery independent of udpwait queues.
|
||||
o check into rebinding ports for efficiency, configure time test.
|
||||
|
||||
+276
-23
@@ -19,6 +19,14 @@ server:
|
||||
# Set to "" or 0 to disable. Default is disabled.
|
||||
# statistics-interval: 0
|
||||
|
||||
# enable shm for stats, default no. if you enable also enable
|
||||
# statistics-interval, every time it also writes stats to the
|
||||
# shared memory segment keyed with shm-key.
|
||||
# shm-enable: no
|
||||
|
||||
# shm for stats uses this key, and key+1 for the shared mem segment.
|
||||
# shm-key: 11777
|
||||
|
||||
# enable cumulative statistics, without clearing them after printing.
|
||||
# statistics-cumulative: no
|
||||
|
||||
@@ -95,7 +103,8 @@ server:
|
||||
# so-sndbuf: 0
|
||||
|
||||
# use SO_REUSEPORT to distribute queries over threads.
|
||||
# so-reuseport: no
|
||||
# at extreme load it could be better to turn it off to distribute even.
|
||||
# so-reuseport: yes
|
||||
|
||||
# use IP_TRANSPARENT so the interface: addresses can be non-local
|
||||
# and you can config non-existing IPs that are going to work later on
|
||||
@@ -108,13 +117,16 @@ server:
|
||||
# ip-freebind: no
|
||||
|
||||
# EDNS reassembly buffer to advertise to UDP peers (the actual buffer
|
||||
# is set with msg-buffer-size). 1480 can solve fragmentation (timeouts).
|
||||
# is set with msg-buffer-size). 1472 can solve fragmentation (timeouts)
|
||||
# edns-buffer-size: 4096
|
||||
|
||||
# Maximum UDP response size (not applied to TCP response).
|
||||
# Suggested values are 512 to 4096. Default is 4096. 65536 disables it.
|
||||
# max-udp-size: 4096
|
||||
|
||||
# max memory to use for stream(tcp and tls) waiting result buffers.
|
||||
# stream-wait-size: 4m
|
||||
|
||||
# buffer size for handling DNS data. No messages larger than this
|
||||
# size can be sent or received, by UDP or TCP. In bytes.
|
||||
# msg-buffer-size: 65552
|
||||
@@ -137,6 +149,10 @@ server:
|
||||
# msec to wait before close of port on timeout UDP. 0 disables.
|
||||
# delay-close: 0
|
||||
|
||||
# msec for waiting for an unknown server to reply. Increase if you
|
||||
# are behind a slow satellite link, to eg. 1128.
|
||||
# unknown-server-time-limit: 376
|
||||
|
||||
# the amount of memory to use for the RRset cache.
|
||||
# plain value in bytes or you can append k, m or G. default is "4Mb".
|
||||
# rrset-cache-size: 4m
|
||||
@@ -192,6 +208,10 @@ server:
|
||||
# useful for tunneling scenarios, default no.
|
||||
# tcp-upstream: no
|
||||
|
||||
# upstream connections also use UDP (even if do-udp is no).
|
||||
# useful if if you want UDP upstream, but don't provide UDP downstream.
|
||||
# udp-upstream-without-downstream: no
|
||||
|
||||
# Maximum segment size (MSS) of TCP socket on which the server
|
||||
# responds to queries. Default is 0, system default MSS.
|
||||
# tcp-mss: 0
|
||||
@@ -200,14 +220,28 @@ server:
|
||||
# Default is 0, system default MSS.
|
||||
# outgoing-tcp-mss: 0
|
||||
|
||||
# Idle TCP timeout, connection closed in milliseconds
|
||||
# tcp-idle-timeout: 30000
|
||||
|
||||
# Enable EDNS TCP keepalive option.
|
||||
# edns-tcp-keepalive: no
|
||||
|
||||
# Timeout for EDNS TCP keepalive, in msec.
|
||||
# edns-tcp-keepalive-timeout: 120000
|
||||
|
||||
# Use systemd socket activation for UDP, TCP, and control sockets.
|
||||
# use-systemd: no
|
||||
|
||||
# Detach from the terminal, run in background, "yes" or "no".
|
||||
# Set the value to "no" when unbound runs as systemd service.
|
||||
# do-daemonize: yes
|
||||
|
||||
# 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 (recursive ok), allow_snoop (recursive and nonrecursive ok)
|
||||
# allow (recursive ok), allow_setrd (recursive ok, rd bit is forced on),
|
||||
# allow_snoop (recursive and nonrecursive ok)
|
||||
# deny_non_local (drop queries unless can be answered from local-data)
|
||||
# refuse_non_local (like deny_non_local but polite error reply).
|
||||
# access-control: 0.0.0.0/0 refuse
|
||||
@@ -252,7 +286,7 @@ server:
|
||||
# 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).
|
||||
# Additionally, unbound may need to access /dev/urandom (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 /.
|
||||
@@ -288,6 +322,21 @@ server:
|
||||
# print one line with time, IP, name, type, class for every query.
|
||||
# log-queries: no
|
||||
|
||||
# print one line per reply, with time, IP, name, type, class, rcode,
|
||||
# timetoresolve, fromcache and responsesize.
|
||||
# log-replies: no
|
||||
|
||||
# log with tag 'query' and 'reply' instead of 'info' for
|
||||
# filtering log-queries and log-replies from the log.
|
||||
# log-tag-queryreply: no
|
||||
|
||||
# log the local-zone actions, like local-zone type inform is enabled
|
||||
# also for the other local zone types.
|
||||
# log-local-actions: no
|
||||
|
||||
# print log lines that say why queries return SERVFAIL to clients.
|
||||
# log-servfail: no
|
||||
|
||||
# the pid file. Can be an absolute path outside of chroot/work dir.
|
||||
# pidfile: "@UNBOUND_PIDFILE@"
|
||||
|
||||
@@ -301,6 +350,9 @@ server:
|
||||
# enable to not answer version.server and version.bind queries.
|
||||
# hide-version: no
|
||||
|
||||
# enable to not answer trustanchor.unbound queries.
|
||||
# hide-trustanchor: no
|
||||
|
||||
# the identity to report. Leave "" or default to return hostname.
|
||||
# identity: ""
|
||||
|
||||
@@ -333,7 +385,7 @@ server:
|
||||
# harden-dnssec-stripped: yes
|
||||
|
||||
# Harden against queries that fall under dnssec-signed nxdomain names.
|
||||
# harden-below-nxdomain: no
|
||||
# harden-below-nxdomain: yes
|
||||
|
||||
# Harden the referral path by performing additional queries for
|
||||
# infrastructure data. Validates the replies (if possible).
|
||||
@@ -348,8 +400,8 @@ server:
|
||||
|
||||
# Sent minimum amount of information to upstream servers to enhance
|
||||
# privacy. Only sent minimum required labels of the QNAME and set QTYPE
|
||||
# to NS when possible.
|
||||
# qname-minimisation: no
|
||||
# to A when possible.
|
||||
# qname-minimisation: yes
|
||||
|
||||
# QNAME minimisation in strict mode. Do not fall-back to sending full
|
||||
# QNAME to potentially broken nameservers. A lot of domains will not be
|
||||
@@ -357,6 +409,10 @@ server:
|
||||
# This option only has effect when qname-minimisation is enabled.
|
||||
# qname-minimisation-strict: no
|
||||
|
||||
# Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN
|
||||
# and other denials, using information from previous NXDOMAINs answers.
|
||||
# aggressive-nsec: no
|
||||
|
||||
# Use 0x20-encoded random bits in the query to foil spoof attempts.
|
||||
# This feature is an experimental implementation of draft dns-0x20.
|
||||
# use-caps-for-id: no
|
||||
@@ -405,18 +461,24 @@ server:
|
||||
# if yes, perform key lookups adjacent to normal lookups.
|
||||
# prefetch-key: no
|
||||
|
||||
# deny queries of type ANY with an empty response.
|
||||
# deny-any: no
|
||||
|
||||
# if yes, Unbound rotates RRSet order in response.
|
||||
# rrset-roundrobin: no
|
||||
|
||||
# if yes, Unbound doesn't insert authority/additional sections
|
||||
# into response messages when those sections are not required.
|
||||
# minimal-responses: no
|
||||
# minimal-responses: yes
|
||||
|
||||
# true to disable DNSSEC lameness check in iterator.
|
||||
# disable-dnssec-lame-check: no
|
||||
|
||||
# module configuration of the server. A string with identifiers
|
||||
# separated by spaces. Syntax: "[dns64] [validator] iterator"
|
||||
# most modules have to be listed at the beginning of the line,
|
||||
# except cachedb(just before iterator), and python (at the beginning,
|
||||
# or, just before the iterator).
|
||||
# module-config: "validator iterator"
|
||||
|
||||
# File with trusted keys, kept uptodate using RFC5011 probes,
|
||||
@@ -429,6 +491,12 @@ server:
|
||||
# and under the terms of our LICENSE (see that file in the source).
|
||||
# auto-trust-anchor-file: "@UNBOUND_ROOTKEY_FILE@"
|
||||
|
||||
# trust anchor signaling sends a RFC8145 key tag query after priming.
|
||||
# trust-anchor-signaling: yes
|
||||
|
||||
# Root key trust anchor sentinel (draft-ietf-dnsop-kskroll-sentinel)
|
||||
# root-key-sentinel: yes
|
||||
|
||||
# File with DLV trusted keys. Same format as trust-anchor-file.
|
||||
# There can be only one DLV configured, it is trusted from root down.
|
||||
# DLV is going to be decommissioned. Please do not use it any more.
|
||||
@@ -490,9 +558,19 @@ server:
|
||||
# that set CD but cannot validate themselves.
|
||||
# ignore-cd-flag: no
|
||||
|
||||
# Serve expired reponses from cache, with TTL 0 in the response,
|
||||
# Serve expired responses from cache, with TTL 0 in the response,
|
||||
# and then attempt to fetch the data afresh.
|
||||
# serve-expired: no
|
||||
#
|
||||
# Limit serving of expired responses to configured seconds after
|
||||
# expiration. 0 disables the limit.
|
||||
# serve-expired-ttl: 0
|
||||
#
|
||||
# Set the TTL of expired records to the serve-expired-ttl value after a
|
||||
# failed attempt to retrieve the record from upstream. This makes sure
|
||||
# that the expired records will be served as long as there are queries
|
||||
# for it.
|
||||
# serve-expired-ttl-reset: no
|
||||
|
||||
# Have the validator log failed validations for your diagnosis.
|
||||
# 0: off. 1: A line per failed user query. 2: With reason and bad IP.
|
||||
@@ -541,6 +619,8 @@ server:
|
||||
# local-zone: "127.in-addr.arpa." nodefault
|
||||
# local-zone: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." nodefault
|
||||
# local-zone: "onion." nodefault
|
||||
# local-zone: "test." nodefault
|
||||
# local-zone: "invalid." nodefault
|
||||
# local-zone: "10.in-addr.arpa." nodefault
|
||||
# local-zone: "16.172.in-addr.arpa." nodefault
|
||||
# local-zone: "17.172.in-addr.arpa." nodefault
|
||||
@@ -574,6 +654,9 @@ server:
|
||||
# local-zone: "8.b.d.0.1.0.0.2.ip6.arpa." nodefault
|
||||
# And for 64.100.in-addr.arpa. to 127.100.in-addr.arpa.
|
||||
|
||||
# Add example.com into ipset
|
||||
# local-zone: "example.com" ipset
|
||||
|
||||
# If unbound is running service for the local host then it is useful
|
||||
# to perform lan-wide lookups to the upstream, and unblock the
|
||||
# long list of local-zones above. If this unbound is a dns server
|
||||
@@ -597,8 +680,10 @@ server:
|
||||
# o typetransparent resolves normally for other types and other names
|
||||
# o inform acts like transparent, but logs client IP address
|
||||
# o inform_deny drops queries and logs client IP address
|
||||
# o inform_redirect redirects queries and logs client IP address
|
||||
# o always_transparent, always_refuse, always_nxdomain, resolve in
|
||||
# that way but ignore local data for that name.
|
||||
# that way but ignore local data for that name
|
||||
# o noview breaks out of that view towards global local-zones.
|
||||
#
|
||||
# defaults are localhost address, reverse for 127.0.0.1 and ::1
|
||||
# and nxdomain for AS112 zones. If you configure one of these zones
|
||||
@@ -631,21 +716,46 @@ server:
|
||||
# add a netblock specific override to a localzone, with zone type
|
||||
# local-zone-override: "example.com" 192.0.2.0/24 refuse
|
||||
|
||||
# service clients over SSL (on the TCP sockets), with plain DNS inside
|
||||
# the SSL stream. Give the certificate to use and private key.
|
||||
# service clients over TLS (on the TCP sockets), with plain DNS inside
|
||||
# the TLS stream. Give the certificate to use and private key.
|
||||
# default is "" (disabled). requires restart to take effect.
|
||||
# ssl-service-key: "path/to/privatekeyfile.key"
|
||||
# ssl-service-pem: "path/to/publiccertfile.pem"
|
||||
# ssl-port: 853
|
||||
# tls-service-key: "path/to/privatekeyfile.key"
|
||||
# tls-service-pem: "path/to/publiccertfile.pem"
|
||||
# tls-port: 853
|
||||
|
||||
# request upstream over SSL (with plain DNS inside the SSL stream).
|
||||
# cipher setting for TLSv1.2
|
||||
# tls-ciphers: "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256"
|
||||
# cipher setting for TLSv1.3
|
||||
# tls-ciphersuites: "TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256"
|
||||
|
||||
# Add the secret file for TLS Session Ticket.
|
||||
# Secret file must be 80 bytes of random data.
|
||||
# First key use to encrypt and decrypt TLS session tickets.
|
||||
# Other keys use to decrypt only.
|
||||
# requires restart to take effect.
|
||||
# tls-session-ticket-keys: "path/to/secret_file1"
|
||||
# tls-session-ticket-keys: "path/to/secret_file2"
|
||||
|
||||
# request upstream over TLS (with plain DNS inside the TLS stream).
|
||||
# Default is no. Can be turned on and off with unbound-control.
|
||||
# ssl-upstream: no
|
||||
# tls-upstream: no
|
||||
|
||||
# Certificates used to authenticate connections made upstream.
|
||||
# tls-cert-bundle: ""
|
||||
|
||||
# Add system certs to the cert bundle, from the Windows Cert Store
|
||||
# tls-win-cert: no
|
||||
|
||||
# Also serve tls on these port numbers (eg. 443, ...), by listing
|
||||
# tls-additional-port: portno for each of the port numbers.
|
||||
|
||||
# DNS64 prefix. Must be specified when DNS64 is use.
|
||||
# Enable dns64 in module-config. Used to synthesize IPv6 from IPv4.
|
||||
# dns64-prefix: 64:ff9b::0/96
|
||||
|
||||
# DNS64 ignore AAAA records for these domains and use A instead.
|
||||
# dns64-ignore-aaaa: "example.com"
|
||||
|
||||
# ratelimit for uncached, new queries, this limits recursion effort.
|
||||
# ratelimiting is experimental, and may help against randomqueryflood.
|
||||
# if 0(default) it is disabled, otherwise state qps allowed per zone.
|
||||
@@ -666,9 +776,62 @@ server:
|
||||
# can give this multiple times, the name closest to the zone is used.
|
||||
# ratelimit-below-domain: com 1000
|
||||
|
||||
# global query ratelimit for all ip addresses.
|
||||
# feature is experimental.
|
||||
# if 0(default) it is disabled, otherwise states qps allowed per ip address
|
||||
# ip-ratelimit: 0
|
||||
|
||||
# ip ratelimits are tracked in a cache, size in bytes of cache (or k,m).
|
||||
# ip-ratelimit-size: 4m
|
||||
# ip ratelimit cache slabs, reduces lock contention if equal to cpucount.
|
||||
# ip-ratelimit-slabs: 4
|
||||
|
||||
# 0 blocks when ip is ratelimited, otherwise let 1/xth traffic through
|
||||
# ip-ratelimit-factor: 10
|
||||
|
||||
# Limit the number of connections simultaneous from a netblock
|
||||
# tcp-connection-limit: 192.0.2.0/24 12
|
||||
|
||||
# select from the fastest servers this many times out of 1000. 0 means
|
||||
# the fast server select is disabled. prefetches are not sped up.
|
||||
# fast-server-permil: 0
|
||||
# the number of servers that will be used in the fast server selection.
|
||||
# fast-server-num: 3
|
||||
|
||||
# Specific options for ipsecmod. unbound needs to be configured with
|
||||
# --enable-ipsecmod for these to take effect.
|
||||
#
|
||||
# Enable or disable ipsecmod (it still needs to be defined in
|
||||
# module-config above). Can be used when ipsecmod needs to be
|
||||
# enabled/disabled via remote-control(below).
|
||||
# ipsecmod-enabled: yes
|
||||
#
|
||||
# Path to executable external hook. It must be defined when ipsecmod is
|
||||
# listed in module-config (above).
|
||||
# ipsecmod-hook: "./my_executable"
|
||||
#
|
||||
# When enabled unbound will reply with SERVFAIL if the return value of
|
||||
# the ipsecmod-hook is not 0.
|
||||
# ipsecmod-strict: no
|
||||
#
|
||||
# Maximum time to live (TTL) for cached A/AAAA records with IPSECKEY.
|
||||
# ipsecmod-max-ttl: 3600
|
||||
#
|
||||
# Reply with A/AAAA even if the relevant IPSECKEY is bogus. Mainly used for
|
||||
# testing.
|
||||
# ipsecmod-ignore-bogus: no
|
||||
#
|
||||
# Domains for which ipsecmod will be triggered. If not defined (default)
|
||||
# all domains are treated as being whitelisted.
|
||||
# ipsecmod-whitelist: "example.com"
|
||||
# ipsecmod-whitelist: "nlnetlabs.nl"
|
||||
|
||||
|
||||
# Python config section. To enable:
|
||||
# o use --with-pythonmodule to configure before compiling.
|
||||
# o list python in the module-config string (above) to enable.
|
||||
# It can be at the start, it gets validated results, or just before
|
||||
# the iterator and process before DNSSEC validation.
|
||||
# o and give a python-script to run.
|
||||
python:
|
||||
# Script file to load
|
||||
@@ -680,18 +843,20 @@ remote-control:
|
||||
# set up the keys and certificates with unbound-control-setup.
|
||||
# control-enable: no
|
||||
|
||||
# Set to no and use an absolute path as control-interface to use
|
||||
# a unix local named pipe for unbound-control.
|
||||
# control-use-cert: yes
|
||||
|
||||
# what interfaces are listened to for remote control.
|
||||
# give 0.0.0.0 and ::0 to listen to all interfaces.
|
||||
# set to an absolute path to use a unix local name pipe, certificates
|
||||
# are not used for that, so key and cert files need not be present.
|
||||
# control-interface: 127.0.0.1
|
||||
# control-interface: ::1
|
||||
|
||||
# port number for remote control operations.
|
||||
# control-port: 8953
|
||||
|
||||
# for localhost, you can disable use of TLS by setting this to "no"
|
||||
# For local sockets this option is ignored, and TLS is not used.
|
||||
# control-use-cert: "yes"
|
||||
|
||||
# unbound server key file.
|
||||
# server-key-file: "@UNBOUND_RUN_DIR@/unbound_server.key"
|
||||
|
||||
@@ -717,7 +882,8 @@ remote-control:
|
||||
# stub-addr: 192.0.2.68
|
||||
# stub-prime: no
|
||||
# stub-first: no
|
||||
# stub-ssl-upstream: no
|
||||
# stub-tls-upstream: no
|
||||
# stub-no-cache: no
|
||||
# stub-zone:
|
||||
# name: "example.org"
|
||||
# stub-host: ns.example.com.
|
||||
@@ -733,11 +899,48 @@ remote-control:
|
||||
# forward-addr: 192.0.2.68
|
||||
# forward-addr: 192.0.2.73@5355 # forward to port 5355.
|
||||
# forward-first: no
|
||||
# forward-ssl-upstream: no
|
||||
# forward-tls-upstream: no
|
||||
# forward-no-cache: no
|
||||
# forward-zone:
|
||||
# name: "example.org"
|
||||
# forward-host: fwd.example.com
|
||||
|
||||
# Authority zones
|
||||
# The data for these zones is kept locally, from a file or downloaded.
|
||||
# The data can be served to downstream clients, or used instead of the
|
||||
# upstream (which saves a lookup to the upstream). The first example
|
||||
# has a copy of the root for local usage. The second serves example.org
|
||||
# authoritatively. zonefile: reads from file (and writes to it if you also
|
||||
# download it), master: fetches with AXFR and IXFR, or url to zonefile.
|
||||
# With allow-notify: you can give additional (apart from masters) sources of
|
||||
# notifies.
|
||||
# auth-zone:
|
||||
# name: "."
|
||||
# master: 199.9.14.201 # b.root-servers.net
|
||||
# master: 192.33.4.12 # c.root-servers.net
|
||||
# master: 199.7.91.13 # d.root-servers.net
|
||||
# master: 192.5.5.241 # f.root-servers.net
|
||||
# master: 192.112.36.4 # g.root-servers.net
|
||||
# master: 193.0.14.129 # k.root-servers.net
|
||||
# master: 192.0.47.132 # xfr.cjr.dns.icann.org
|
||||
# master: 192.0.32.132 # xfr.lax.dns.icann.org
|
||||
# master: 2001:500:200::b # b.root-servers.net
|
||||
# master: 2001:500:2::c # c.root-servers.net
|
||||
# master: 2001:500:2d::d # d.root-servers.net
|
||||
# master: 2001:500:2f::f # f.root-servers.net
|
||||
# master: 2001:500:12::d0d # g.root-servers.net
|
||||
# master: 2001:7fd::1 # k.root-servers.net
|
||||
# master: 2620:0:2830:202::132 # xfr.cjr.dns.icann.org
|
||||
# master: 2620:0:2d0:202::132 # xfr.lax.dns.icann.org
|
||||
# fallback-enabled: yes
|
||||
# for-downstream: no
|
||||
# for-upstream: yes
|
||||
# auth-zone:
|
||||
# name: "example.org"
|
||||
# for-downstream: yes
|
||||
# for-upstream: yes
|
||||
# zonefile: "example.org.zone"
|
||||
|
||||
# Views
|
||||
# Create named views. Name must be unique. Map views to requests using
|
||||
# the access-control-view option. Views can contain zero or more local-zone
|
||||
@@ -749,7 +952,57 @@ remote-control:
|
||||
# name: "viewname"
|
||||
# local-zone: "example.com" redirect
|
||||
# local-data: "example.com A 192.0.2.3"
|
||||
# local-data-ptr: "192.0.2.3 www.example.com"
|
||||
# view-first: no
|
||||
# view:
|
||||
# name: "anotherview"
|
||||
# local-zone: "example.com" refuse
|
||||
|
||||
# DNSCrypt
|
||||
# Caveats:
|
||||
# 1. the keys/certs cannot be produced by unbound. You can use dnscrypt-wrapper
|
||||
# for this: https://github.com/cofyc/dnscrypt-wrapper/blob/master/README.md#usage
|
||||
# 2. dnscrypt channel attaches to an interface. you MUST set interfaces to
|
||||
# listen on `dnscrypt-port` with the follo0wing snippet:
|
||||
# server:
|
||||
# interface: 0.0.0.0@443
|
||||
# interface: ::0@443
|
||||
#
|
||||
# Finally, `dnscrypt` config has its own section.
|
||||
# dnscrypt:
|
||||
# dnscrypt-enable: yes
|
||||
# dnscrypt-port: 443
|
||||
# dnscrypt-provider: 2.dnscrypt-cert.example.com.
|
||||
# dnscrypt-secret-key: /path/unbound-conf/keys1/1.key
|
||||
# dnscrypt-secret-key: /path/unbound-conf/keys2/1.key
|
||||
# dnscrypt-provider-cert: /path/unbound-conf/keys1/1.cert
|
||||
# dnscrypt-provider-cert: /path/unbound-conf/keys2/1.cert
|
||||
|
||||
# CacheDB
|
||||
# Enable external backend DB as auxiliary cache. Specify the backend name
|
||||
# (default is "testframe", which has no use other than for debugging and
|
||||
# testing) and backend-specific options. The 'cachedb' module must be
|
||||
# included in module-config, just before the iterator module.
|
||||
# cachedb:
|
||||
# backend: "testframe"
|
||||
# # secret seed string to calculate hashed keys
|
||||
# secret-seed: "default"
|
||||
#
|
||||
# # For "redis" backend:
|
||||
# # redis server's IP address or host name
|
||||
# redis-server-host: 127.0.0.1
|
||||
# # redis server's TCP port
|
||||
# redis-server-port: 6379
|
||||
# # timeout (in ms) for communication with the redis server
|
||||
# redis-timeout: 100
|
||||
|
||||
# IPSet
|
||||
# Add specify domain into set via ipset.
|
||||
# Note: To enable ipset needs run unbound as root user.
|
||||
# ipset:
|
||||
# # set name for ip v4 addresses
|
||||
# name-v4: "list-v4"
|
||||
# # set name for ip v6 addresses
|
||||
# name-v6: "list-v6"
|
||||
#
|
||||
|
||||
|
||||
+23
-5
@@ -12,7 +12,7 @@
|
||||
.B unbound.h,
|
||||
.B ub_ctx,
|
||||
.B ub_result,
|
||||
.B ub_callback_t,
|
||||
.B ub_callback_type,
|
||||
.B ub_ctx_create,
|
||||
.B ub_ctx_delete,
|
||||
.B ub_ctx_set_option,
|
||||
@@ -20,6 +20,7 @@
|
||||
.B ub_ctx_config,
|
||||
.B ub_ctx_set_fwd,
|
||||
.B ub_ctx_set_stub,
|
||||
.B ub_ctx_set_tls,
|
||||
.B ub_ctx_resolvconf,
|
||||
.B ub_ctx_hosts,
|
||||
.B ub_ctx_add_ta,
|
||||
@@ -72,6 +73,9 @@
|
||||
\fIint\fR isprime);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_set_tls\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR tls);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_resolvconf\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
|
||||
.LP
|
||||
\fIint\fR
|
||||
@@ -120,7 +124,7 @@
|
||||
.br
|
||||
\fIint\fR rrtype, \fIint\fR rrclass, \fIvoid*\fR mydata,
|
||||
.br
|
||||
\fIub_callback_t\fR callback, \fIint*\fR async_id);
|
||||
\fIub_callback_type\fR callback, \fIint*\fR async_id);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_cancel\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR async_id);
|
||||
@@ -150,7 +154,8 @@
|
||||
is an implementation of a DNS resolver, that does caching and
|
||||
DNSSEC validation. This is the library API, for using the \-lunbound library.
|
||||
The server daemon is described in \fIunbound\fR(8).
|
||||
The library can be used to convert hostnames to ip addresses, and back,
|
||||
The library works independent from a running unbound server, and
|
||||
can be used to convert hostnames to ip addresses, and back,
|
||||
and obtain other information from the DNS. The library performs public\-key
|
||||
validation of results with DNSSEC.
|
||||
.P
|
||||
@@ -162,7 +167,7 @@ and deleting it with
|
||||
It can be created and deleted at any time. Creating it anew removes any
|
||||
previous configuration (such as trusted keys) and clears any cached results.
|
||||
.P
|
||||
The functions are thread\-safe, and a context an be used in a threaded (as
|
||||
The functions are thread\-safe, and a context can be used in a threaded (as
|
||||
well as in a non\-threaded) environment. Also resolution (and validation)
|
||||
can be performed blocking and non\-blocking (also called asynchronous).
|
||||
The async method returns from the call immediately, so that processing
|
||||
@@ -203,7 +208,10 @@ without trailing ':'. The returned value must be free(2)d by the caller.
|
||||
A power\-user interface that lets you specify an unbound config file, see
|
||||
\fIunbound.conf\fR(5), which is read for configuration. Not all options are
|
||||
relevant. For some specific options, such as adding trust anchors, special
|
||||
routines exist.
|
||||
routines exist. This function is thread\-safe only if a single instance of
|
||||
ub_ctx* exists in the application. If several instances exist the
|
||||
application has to ensure that ub_ctx_config is not called in parallel by
|
||||
the different instances.
|
||||
.TP
|
||||
.B ub_ctx_set_fwd
|
||||
Set machine to forward DNS queries to, the caching resolver to use.
|
||||
@@ -223,6 +231,12 @@ for different zones, or to add multiple addresses for a particular zone.
|
||||
At this time it is only possible to set configuration before the
|
||||
first resolve is done.
|
||||
.TP
|
||||
.B ub_ctx_set_tls
|
||||
Enable DNS over TLS (DoT) for machines set with
|
||||
.B ub_ctx_set_fwd.
|
||||
At this time it is only possible to set configuration before the
|
||||
first resolve is done.
|
||||
.TP
|
||||
.B ub_ctx_resolvconf
|
||||
By default the root servers are queried and full resolver mode is used, but
|
||||
you can use this call to read the list of nameservers to use from the
|
||||
@@ -407,6 +421,10 @@ returns NULL on an error (a malloc failure).
|
||||
returns true if some information may be available, false otherwise.
|
||||
.B ub_fd
|
||||
returns a file descriptor or \-1 on error.
|
||||
.B ub_ctx_config
|
||||
and
|
||||
.B ub_ctx_resolvconf
|
||||
attempt to leave errno informative on a function return with file read failure.
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound\fR(8).
|
||||
|
||||
@@ -81,7 +81,7 @@ o Too many Features.
|
||||
|
||||
5. Choices
|
||||
----------
|
||||
o rfc2181 decourages duplicates RRs in RRsets. unbound does not create
|
||||
o rfc2181 discourages duplicates RRs in RRsets. unbound does not create
|
||||
duplicates, but when presented with duplicates on the wire from the
|
||||
authoritative servers, does not perform duplicate removal.
|
||||
It does do some rrsig duplicate removal, in the msgparser, for dnssec qtype
|
||||
|
||||
@@ -69,6 +69,10 @@ 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 address or IPv6 address (no brackets) if you want.
|
||||
.TP
|
||||
.B \-b \fIaddress
|
||||
The source address to bind to for domain resolution and contacting the server
|
||||
on https. May be either an IPv4 address or IPv6 address (no brackets).
|
||||
.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.
|
||||
@@ -109,6 +113,11 @@ It does so, because the tool when used for bootstrapping the recursive
|
||||
resolver, cannot use that recursive resolver itself because it is bootstrapping
|
||||
that server.
|
||||
.TP
|
||||
.B \-R
|
||||
Allow fallback from \-f resolv.conf file to direct root servers query.
|
||||
It allows you to prefer local resolvers, but fallback automatically
|
||||
to direct root query if they do not respond or do not support DNSSEC.
|
||||
.TP
|
||||
.B \-v
|
||||
More verbose. Once prints informational messages, multiple times may enable
|
||||
large debug amounts (such as full certificates or byte\-dumps of downloaded
|
||||
|
||||
+131
-1
@@ -144,6 +144,9 @@ Remove the name, type information from the cache.
|
||||
Remove all information at or below the name from the cache.
|
||||
The rrsets and key entries are removed so that new lookups will be performed.
|
||||
This needs to walk and inspect the entire cache, and is a slow operation.
|
||||
The entries are set to expired in the implementation of this command (so,
|
||||
with serve\-expired enabled, it'll serve that information but schedule a
|
||||
prefetch for new information).
|
||||
.TP
|
||||
.B flush_bogus
|
||||
Remove all bogus data from the cache.
|
||||
@@ -194,7 +197,7 @@ harden\-referral\-path, prefetch, prefetch\-key, log\-queries,
|
||||
hide\-identity, hide\-version, identity, version, val\-log\-level,
|
||||
val\-log\-squelch, ignore\-cd\-flag, add\-holddown, del\-holddown,
|
||||
keep\-missing, tcp\-upstream, ssl\-upstream, max\-udp\-size, ratelimit,
|
||||
cache\-max\-ttl, cache\-min\-ttl, cache\-max\-negative\-ttl.
|
||||
ip\-ratelimit, cache\-max\-ttl, cache\-min\-ttl, cache\-max\-negative\-ttl.
|
||||
.TP
|
||||
.B get_option \fIopt
|
||||
Get the value of the option. Give the option name without a trailing ':'.
|
||||
@@ -280,6 +283,28 @@ just the ratelimited domains, with their estimated qps. The ratelimited
|
||||
domains return an error for uncached (new) queries, but cached queries work
|
||||
as normal.
|
||||
.TP
|
||||
.B ip_ratelimit_list \fR[\fI+a\fR]
|
||||
List the ip addresses that are ratelimited. Printed one per line with current
|
||||
estimated qps and qps limit from config. With +a it prints all ips, not
|
||||
just the ratelimited ips, with their estimated qps. The ratelimited
|
||||
ips are dropped before checking the cache.
|
||||
.TP
|
||||
.B list_auth_zones
|
||||
List the auth zones that are configured. Printed one per line with a
|
||||
status, indicating if the zone is expired and current serial number.
|
||||
.TP
|
||||
.B auth_zone_reload \fIzone\fR
|
||||
Reload the auth zone from zonefile. The zonefile is read in overwriting
|
||||
the current contents of the zone in memory. This changes the auth zone
|
||||
contents itself, not the cache contents. Such cache contents exists if
|
||||
you set unbound to validate with for-upstream yes and that can be cleared
|
||||
with \fBflush_zone\fR \fIzone\fR.
|
||||
.TP
|
||||
.B auth_zone_transfer \fIzone\fR
|
||||
Transfer the auth zone from master. The auth zone probe sequence is started,
|
||||
where the masters are probed to see if they have an updated zone (with the SOA
|
||||
serial check). And then the zone is transferred for a newer zone version.
|
||||
.TP
|
||||
.B view_list_local_zones \fIview\fR
|
||||
\fIlist_local_zones\fR for given view.
|
||||
.TP
|
||||
@@ -289,11 +314,17 @@ as normal.
|
||||
.B view_local_zone_remove \fIview\fR \fIname
|
||||
\fIlocal_zone_remove\fR for given view.
|
||||
.TP
|
||||
.B view_list_local_data \fIview\fR
|
||||
\fIlist_local_data\fR for given view.
|
||||
.TP
|
||||
.B view_local_data \fIview\fR \fIRR data...
|
||||
\fIlocal_data\fR for given view.
|
||||
.TP
|
||||
.B view_local_data_remove \fIview\fR \fIname
|
||||
\fIlocal_data_remove\fR for given view.
|
||||
.TP
|
||||
.B view_local_datas \fIview\fR
|
||||
Add a list of \fIlocal_data\fR for given view from stdin. Like local_datas.
|
||||
.SH "EXIT CODE"
|
||||
The unbound\-control program exits with status code 1 on error, 0 on success.
|
||||
.SH "SET UP"
|
||||
@@ -319,12 +350,28 @@ The \fIstats\fR command shows a number of statistic counters.
|
||||
.I threadX.num.queries
|
||||
number of queries received by thread
|
||||
.TP
|
||||
.I threadX.num.queries_ip_ratelimited
|
||||
number of queries rate limited 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.dnscrypt.crypted
|
||||
number of queries that were encrypted and successfully decapsulated by dnscrypt.
|
||||
.TP
|
||||
.I threadX.num.dnscrypt.cert
|
||||
number of queries that were requesting dnscrypt certificates.
|
||||
.TP
|
||||
.I threadX.num.dnscrypt.cleartext
|
||||
number of queries received on dnscrypt port that were cleartext and not a
|
||||
request for certificates.
|
||||
.TP
|
||||
.I threadX.num.dnscrypt.malformed
|
||||
number of request that were neither cleartext, not valid dnscrypt messages.
|
||||
.TP
|
||||
.I threadX.num.prefetch
|
||||
number of cache prefetches performed. This number is included in
|
||||
cachehits, as the original query had the unprefetched answer from cache,
|
||||
@@ -381,6 +428,18 @@ summed over threads.
|
||||
.I total.num.cachemiss
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.dnscrypt.crypted
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.dnscrypt.cert
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.dnscrypt.cleartext
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.dnscrypt.malformed
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.prefetch
|
||||
summed over threads.
|
||||
.TP
|
||||
@@ -427,6 +486,12 @@ Memory in bytes in use by the RRset cache.
|
||||
.I mem.cache.message
|
||||
Memory in bytes in use by the message cache.
|
||||
.TP
|
||||
.I mem.cache.dnscrypt_shared_secret
|
||||
Memory in bytes in use by the dnscrypt shared secrets cache.
|
||||
.TP
|
||||
.I mem.cache.dnscrypt_nonce
|
||||
Memory in bytes in use by the dnscrypt nonce cache.
|
||||
.TP
|
||||
.I mem.mod.iterator
|
||||
Memory in bytes in use by the iterator module.
|
||||
.TP
|
||||
@@ -434,6 +499,10 @@ Memory in bytes in use by the iterator module.
|
||||
Memory in bytes in use by the validator module. Includes the key cache and
|
||||
negative cache.
|
||||
.TP
|
||||
.I mem.streamwait
|
||||
Memory in bytes in used by the TCP and TLS stream wait buffers. These are
|
||||
answers waiting to be written back to the clients.
|
||||
.TP
|
||||
.I histogram.<sec>.<usec>.to.<sec>.<usec>
|
||||
Shows a histogram, summed over all threads. Every element counts the
|
||||
recursive queries whose reply time fit between the lower and upper bound.
|
||||
@@ -465,6 +534,14 @@ Number of queries that were made using TCP towards the unbound server.
|
||||
Number of queries that the unbound server made using TCP outgoing towards
|
||||
other servers.
|
||||
.TP
|
||||
.I num.query.tls
|
||||
Number of queries that were made using TLS towards the unbound server.
|
||||
These are also counted in num.query.tcp, because TLS uses TCP.
|
||||
.TP
|
||||
.I num.query.tls.resume
|
||||
Number of TLS session resumptions, these are queries over TLS towards
|
||||
the unbound server where the client negotiated a TLS session resumption key.
|
||||
.TP
|
||||
.I num.query.ipv6
|
||||
Number of queries that were made using IPv6 towards the unbound server.
|
||||
.TP
|
||||
@@ -481,6 +558,18 @@ number of queries that had an EDNS OPT record present.
|
||||
number of queries that had an EDNS OPT record with the DO (DNSSEC OK) bit set.
|
||||
These queries are also included in the num.query.edns.present number.
|
||||
.TP
|
||||
.I num.query.ratelimited
|
||||
The number of queries that are turned away from being send to nameserver due to
|
||||
ratelimiting.
|
||||
.TP
|
||||
.I num.query.dnscrypt.shared_secret.cachemiss
|
||||
The number of dnscrypt queries that did not find a shared secret in the cache.
|
||||
The can be use to compute the shared secret hitrate.
|
||||
.TP
|
||||
.I num.query.dnscrypt.replay
|
||||
The number of dnscrypt queries that found a nonce hit in the nonce cache and
|
||||
hence are considered a query replay.
|
||||
.TP
|
||||
.I num.answer.rcode.NXDOMAIN
|
||||
The number of answers to queries, from cache or from recursion, that had the
|
||||
return code NXDOMAIN. Also printed for the other return codes.
|
||||
@@ -530,6 +619,47 @@ timing and protocol support information.
|
||||
.I key.cache.count
|
||||
The number of items in the key cache. These are DNSSEC keys, one item
|
||||
per delegation point, and their validation status.
|
||||
.TP
|
||||
.I dnscrypt_shared_secret.cache.count
|
||||
The number of items in the shared secret cache. These are precomputed shared
|
||||
secrets for a given client public key/server secret key pair. Shared secrets
|
||||
are CPU intensive and this cache allows unbound to avoid recomputing the
|
||||
shared secret when multiple dnscrypt queries are sent from the same client.
|
||||
.TP
|
||||
.I dnscrypt_nonce.cache.count
|
||||
The number of items in the client nonce cache. This cache is used to prevent
|
||||
dnscrypt queries replay. The client nonce must be unique for each client public
|
||||
key/server secret key pair. This cache should be able to host QPS * `replay
|
||||
window` interval keys to prevent replay of a query during `replay window`
|
||||
seconds.
|
||||
.TP
|
||||
.I num.query.authzone.up
|
||||
The number of queries answered from auth\-zone data, upstream queries.
|
||||
These queries would otherwise have been sent (with fallback enabled) to
|
||||
the internet, but are now answered from the auth zone.
|
||||
.TP
|
||||
.I num.query.authzone.down
|
||||
The number of queries for downstream answered from auth\-zone data.
|
||||
These queries are from downstream clients, and have had an answer from
|
||||
the data in the auth zone.
|
||||
.TP
|
||||
.I num.query.aggressive.NOERROR
|
||||
The number of queries answered using cached NSEC records with NODATA RCODE.
|
||||
These queries would otherwise have been sent to the internet, but are now
|
||||
answered using cached data.
|
||||
.TP
|
||||
.I num.query.aggressive.NXDOMAIN
|
||||
The number of queries answered using cached NSEC records with NXDOMAIN RCODE.
|
||||
These queries would otherwise have been sent to the internet, but are now
|
||||
answered using cached data.
|
||||
.TP
|
||||
.I num.query.subnet
|
||||
Number of queries that got an answer that contained EDNS client subnet data.
|
||||
.TP
|
||||
.I num.query.subnet_cache
|
||||
Number of queries answered from the edns client subnet cache. These are
|
||||
counted as cachemiss by the main counters, but hit the client subnet
|
||||
specific cache, after getting processed by the edns client subnet module.
|
||||
.SH "FILES"
|
||||
.TP
|
||||
.I @ub_conf_file@
|
||||
|
||||
@@ -12,20 +12,20 @@
|
||||
\- unbound DNS lookup utility
|
||||
.SH "SYNOPSIS"
|
||||
.B unbound\-host
|
||||
.RB [ \-C
|
||||
.IR configfile ]
|
||||
.RB [ \-vdhr46D ]
|
||||
.RB [ \-c
|
||||
.IR class ]
|
||||
.RB [ \-t
|
||||
.IR type ]
|
||||
.I hostname
|
||||
.RB [ \-y
|
||||
.IR key ]
|
||||
.RB [ \-f
|
||||
.IR keyfile ]
|
||||
.RB [ \-F
|
||||
.IR namedkeyfile ]
|
||||
.RB [ \-C
|
||||
.IR configfile ]
|
||||
.I hostname
|
||||
.SH "DESCRIPTION"
|
||||
.B Unbound\-host
|
||||
uses the unbound validating resolver to query for the hostname and display
|
||||
@@ -86,6 +86,8 @@ are read.
|
||||
.B \-C \fIconfigfile
|
||||
Uses the specified unbound.conf to prime
|
||||
.IR libunbound (3).
|
||||
Pass it as first argument if you want to override some options from the
|
||||
config file with further arguments on the commandline.
|
||||
.TP
|
||||
.B \-r
|
||||
Read /etc/resolv.conf, and use the forward DNS servers from there (those could
|
||||
|
||||
+10
-1
@@ -14,6 +14,7 @@
|
||||
.B unbound
|
||||
.RB [ \-h ]
|
||||
.RB [ \-d ]
|
||||
.RB [ \-p ]
|
||||
.RB [ \-v ]
|
||||
.RB [ \-c
|
||||
.IR cfgfile ]
|
||||
@@ -53,7 +54,7 @@ resolvers are using the same port number (53).
|
||||
The available options are:
|
||||
.TP
|
||||
.B \-h
|
||||
Show the version and commandline option help.
|
||||
Show the version number and commandline option help, and exit.
|
||||
.TP
|
||||
.B \-c\fI cfgfile
|
||||
Set the config file with settings for unbound to read instead of reading the
|
||||
@@ -67,9 +68,17 @@ the thread\-spawn time, so that most config and setup errors appear on
|
||||
stderr. If given twice or more, logging does not switch to the log file
|
||||
or to syslog, but the log messages are printed to stderr all the time.
|
||||
.TP
|
||||
.B \-p
|
||||
Don't use a pidfile. This argument should only be used by supervision
|
||||
systems which can ensure that only one instance of unbound will run
|
||||
concurrently.
|
||||
.TP
|
||||
.B \-v
|
||||
Increase verbosity. If given multiple times, more information is logged.
|
||||
This is in addition to the verbosity (if any) from the config file.
|
||||
.TP
|
||||
.B \-V
|
||||
Show the version number and build options, and exit.
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound\-checkconf\fR(8),
|
||||
|
||||
+921
-233
File diff suppressed because it is too large
Load Diff
+9
-3
@@ -612,18 +612,24 @@ RECURSIVE = YES
|
||||
|
||||
EXCLUDE = ./build \
|
||||
./compat \
|
||||
./contrib \
|
||||
util/configparser.c \
|
||||
util/configparser.h \
|
||||
util/configlexer.c \
|
||||
util/locks.h \
|
||||
pythonmod/doc \
|
||||
pythonmod/examples \
|
||||
pythonmod/unboundmodule.py \
|
||||
pythonmod/interface.h \
|
||||
pythonmod/examples/resgen.py \
|
||||
pythonmod/examples/resmod.py \
|
||||
pythonmod/examples/resip.py \
|
||||
pythonmod/ubmodule-msg.py \
|
||||
pythonmod/ubmodule-tst.py \
|
||||
unboundmodule.py \
|
||||
libunbound/python/unbound.py \
|
||||
libunbound/python/libunbound_wrap.c \
|
||||
libunbound/python/doc \
|
||||
libunbound/python/examples \
|
||||
./ldns-src \
|
||||
README.md \
|
||||
doc/control_proto_spec.txt \
|
||||
doc/requirements.txt
|
||||
|
||||
|
||||
@@ -0,0 +1,532 @@
|
||||
/*
|
||||
* edns-subnet/addrtree.c -- radix tree for edns subnet cache.
|
||||
*
|
||||
* Copyright (c) 2013, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/** \file
|
||||
* addrtree -- radix tree for edns subnet cache.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "util/log.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/module.h"
|
||||
#include "addrtree.h"
|
||||
|
||||
/**
|
||||
* Create a new edge
|
||||
* @param node: Child node this edge will connect to.
|
||||
* @param addr: full key to this edge.
|
||||
* @param addrlen: length of relevant part of key for this node
|
||||
* @param parent_node: Parent node for node
|
||||
* @param parent_index: Index of child node at parent node
|
||||
* @return new addredge or NULL on failure
|
||||
*/
|
||||
static struct addredge *
|
||||
edge_create(struct addrnode *node, const addrkey_t *addr,
|
||||
addrlen_t addrlen, struct addrnode *parent_node, int parent_index)
|
||||
{
|
||||
size_t n;
|
||||
struct addredge *edge = (struct addredge *)malloc( sizeof (*edge) );
|
||||
if (!edge)
|
||||
return NULL;
|
||||
edge->node = node;
|
||||
edge->len = addrlen;
|
||||
edge->parent_index = parent_index;
|
||||
edge->parent_node = parent_node;
|
||||
/* ceil() */
|
||||
n = (size_t)((addrlen / KEYWIDTH) + ((addrlen % KEYWIDTH != 0)?1:0));
|
||||
edge->str = (addrkey_t *)calloc(n, sizeof (addrkey_t));
|
||||
if (!edge->str) {
|
||||
free(edge);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(edge->str, addr, n * sizeof (addrkey_t));
|
||||
/* Only manipulate other objects after successful alloc */
|
||||
node->parent_edge = edge;
|
||||
log_assert(parent_node->edge[parent_index] == NULL);
|
||||
parent_node->edge[parent_index] = edge;
|
||||
return edge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new node
|
||||
* @param tree: Tree the node lives in.
|
||||
* @param elem: Element to store at this node
|
||||
* @param scope: Scopemask from server reply
|
||||
* @param ttl: Element is valid up to this time. Absolute, seconds
|
||||
* @return new addrnode or NULL on failure
|
||||
*/
|
||||
static struct addrnode *
|
||||
node_create(struct addrtree *tree, void *elem, addrlen_t scope,
|
||||
time_t ttl)
|
||||
{
|
||||
struct addrnode* node = (struct addrnode *)malloc( sizeof (*node) );
|
||||
if (!node)
|
||||
return NULL;
|
||||
node->elem = elem;
|
||||
tree->node_count++;
|
||||
node->scope = scope;
|
||||
node->ttl = ttl;
|
||||
node->edge[0] = NULL;
|
||||
node->edge[1] = NULL;
|
||||
node->parent_edge = NULL;
|
||||
node->next = NULL;
|
||||
node->prev = NULL;
|
||||
return node;
|
||||
}
|
||||
|
||||
/** Size in bytes of node and parent edge
|
||||
* @param tree: tree the node lives in
|
||||
* @param n: node which size must be calculated
|
||||
* @return size in bytes.
|
||||
**/
|
||||
static inline size_t
|
||||
node_size(const struct addrtree *tree, const struct addrnode *n)
|
||||
{
|
||||
return sizeof *n + sizeof *n->parent_edge + n->parent_edge->len +
|
||||
(n->elem?tree->sizefunc(n->elem):0);
|
||||
}
|
||||
|
||||
struct addrtree *
|
||||
addrtree_create(addrlen_t max_depth, void (*delfunc)(void *, void *),
|
||||
size_t (*sizefunc)(void *), void *env, uint32_t max_node_count)
|
||||
{
|
||||
struct addrtree *tree;
|
||||
log_assert(delfunc != NULL);
|
||||
log_assert(sizefunc != NULL);
|
||||
tree = (struct addrtree *)calloc(1, sizeof(*tree));
|
||||
if (!tree)
|
||||
return NULL;
|
||||
tree->root = node_create(tree, NULL, 0, 0);
|
||||
if (!tree->root) {
|
||||
free(tree);
|
||||
return NULL;
|
||||
}
|
||||
tree->size_bytes = sizeof *tree + sizeof *tree->root;
|
||||
tree->first = NULL;
|
||||
tree->last = NULL;
|
||||
tree->max_depth = max_depth;
|
||||
tree->delfunc = delfunc;
|
||||
tree->sizefunc = sizefunc;
|
||||
tree->env = env;
|
||||
tree->node_count = 0;
|
||||
tree->max_node_count = max_node_count;
|
||||
return tree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrub a node clean of elem
|
||||
* @param tree: tree the node lives in.
|
||||
* @param node: node to be cleaned.
|
||||
*/
|
||||
static void
|
||||
clean_node(struct addrtree *tree, struct addrnode *node)
|
||||
{
|
||||
if (!node->elem) return;
|
||||
tree->size_bytes -= tree->sizefunc(node->elem);
|
||||
tree->delfunc(tree->env, node->elem);
|
||||
node->elem = NULL;
|
||||
}
|
||||
|
||||
/** Remove specified node from LRU list */
|
||||
static void
|
||||
lru_pop(struct addrtree *tree, struct addrnode *node)
|
||||
{
|
||||
if (node == tree->first) {
|
||||
if (!node->next) { /* it is the last as well */
|
||||
tree->first = NULL;
|
||||
tree->last = NULL;
|
||||
} else {
|
||||
tree->first = node->next;
|
||||
tree->first->prev = NULL;
|
||||
}
|
||||
} else if (node == tree->last) { /* but not the first */
|
||||
tree->last = node->prev;
|
||||
tree->last->next = NULL;
|
||||
} else {
|
||||
node->prev->next = node->next;
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
}
|
||||
|
||||
/** Add node to LRU list as most recently used. */
|
||||
static void
|
||||
lru_push(struct addrtree *tree, struct addrnode *node)
|
||||
{
|
||||
if (!tree->first) {
|
||||
tree->first = node;
|
||||
node->prev = NULL;
|
||||
} else {
|
||||
tree->last->next = node;
|
||||
node->prev = tree->last;
|
||||
}
|
||||
tree->last = node;
|
||||
node->next = NULL;
|
||||
}
|
||||
|
||||
/** Move node to the end of LRU list */
|
||||
static void
|
||||
lru_update(struct addrtree *tree, struct addrnode *node)
|
||||
{
|
||||
if (tree->root == node) return;
|
||||
lru_pop(tree, node);
|
||||
lru_push(tree, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Purge a node from the tree. Node and parentedge are cleaned and
|
||||
* free'd.
|
||||
* @param tree: Tree the node lives in.
|
||||
* @param node: Node to be freed
|
||||
*/
|
||||
static void
|
||||
purge_node(struct addrtree *tree, struct addrnode *node)
|
||||
{
|
||||
struct addredge *parent_edge, *child_edge = NULL;
|
||||
int index;
|
||||
int keep = node->edge[0] && node->edge[1];
|
||||
|
||||
clean_node(tree, node);
|
||||
parent_edge = node->parent_edge;
|
||||
if (keep || !parent_edge) return;
|
||||
tree->node_count--;
|
||||
index = parent_edge->parent_index;
|
||||
child_edge = node->edge[!node->edge[0]];
|
||||
if (child_edge) {
|
||||
child_edge->parent_node = parent_edge->parent_node;
|
||||
child_edge->parent_index = index;
|
||||
}
|
||||
parent_edge->parent_node->edge[index] = child_edge;
|
||||
tree->size_bytes -= node_size(tree, node);
|
||||
free(parent_edge->str);
|
||||
free(parent_edge);
|
||||
lru_pop(tree, node);
|
||||
free(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* If a limit is set remove old nodes while above that limit.
|
||||
* @param tree: Tree to be cleaned up.
|
||||
*/
|
||||
static void
|
||||
lru_cleanup(struct addrtree *tree)
|
||||
{
|
||||
struct addrnode *n, *p;
|
||||
int children;
|
||||
if (tree->max_node_count == 0) return;
|
||||
while (tree->node_count > tree->max_node_count) {
|
||||
n = tree->first;
|
||||
if (!n) break;
|
||||
children = (n->edge[0] != NULL) + (n->edge[1] != NULL);
|
||||
/** Don't remove this node, it is either the root or we can't
|
||||
* do without it because it has 2 children */
|
||||
if (children == 2 || !n->parent_edge) {
|
||||
lru_update(tree, n);
|
||||
continue;
|
||||
}
|
||||
p = n->parent_edge->parent_node;
|
||||
purge_node(tree, n);
|
||||
/** Since we removed n, n's parent p is eligible for deletion
|
||||
* if it is not the root node, caries no data and has only 1
|
||||
* child */
|
||||
children = (p->edge[0] != NULL) + (p->edge[1] != NULL);
|
||||
if (!p->elem && children == 1 && p->parent_edge) {
|
||||
purge_node(tree, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline size_t
|
||||
addrtree_size(const struct addrtree *tree)
|
||||
{
|
||||
return tree?tree->size_bytes:0;
|
||||
}
|
||||
|
||||
void addrtree_delete(struct addrtree *tree)
|
||||
{
|
||||
struct addrnode *n;
|
||||
if (!tree) return;
|
||||
clean_node(tree, tree->root);
|
||||
free(tree->root);
|
||||
tree->size_bytes -= sizeof(struct addrnode);
|
||||
while ((n = tree->first)) {
|
||||
tree->first = n->next;
|
||||
clean_node(tree, n);
|
||||
tree->size_bytes -= node_size(tree, n);
|
||||
free(n->parent_edge->str);
|
||||
free(n->parent_edge);
|
||||
free(n);
|
||||
}
|
||||
log_assert(sizeof *tree == addrtree_size(tree));
|
||||
free(tree);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get N'th bit from address
|
||||
* @param addr: address to inspect
|
||||
* @param addrlen: length of addr in bits
|
||||
* @param n: index of bit to test. Must be in range [0, addrlen)
|
||||
* @return 0 or 1
|
||||
*/
|
||||
static int
|
||||
getbit(const addrkey_t *addr, addrlen_t addrlen, addrlen_t n)
|
||||
{
|
||||
log_assert(addrlen > n);
|
||||
(void)addrlen;
|
||||
return (int)(addr[n/KEYWIDTH]>>((KEYWIDTH-1)-(n%KEYWIDTH))) & 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for equality on N'th bit.
|
||||
* @return 0 for equal, 1 otherwise
|
||||
*/
|
||||
static inline int
|
||||
cmpbit(const addrkey_t *key1, const addrkey_t *key2, addrlen_t n)
|
||||
{
|
||||
addrkey_t c = key1[n/KEYWIDTH] ^ key2[n/KEYWIDTH];
|
||||
return (int)(c >> ((KEYWIDTH-1)-(n%KEYWIDTH))) & 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Common number of bits in prefix.
|
||||
* @param s1: first prefix.
|
||||
* @param l1: length of s1 in bits.
|
||||
* @param s2: second prefix.
|
||||
* @param l2: length of s2 in bits.
|
||||
* @param skip: nr of bits already checked.
|
||||
* @return common number of bits.
|
||||
*/
|
||||
static addrlen_t
|
||||
bits_common(const addrkey_t *s1, addrlen_t l1,
|
||||
const addrkey_t *s2, addrlen_t l2, addrlen_t skip)
|
||||
{
|
||||
addrlen_t len, i;
|
||||
len = (l1 > l2) ? l2 : l1;
|
||||
log_assert(skip < len);
|
||||
for (i = skip; i < len; i++) {
|
||||
if (cmpbit(s1, s2, i)) return i;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if s1 is a substring of s2
|
||||
* @param s1: first prefix.
|
||||
* @param l1: length of s1 in bits.
|
||||
* @param s2: second prefix.
|
||||
* @param l2: length of s2 in bits.
|
||||
* @param skip: nr of bits already checked.
|
||||
* @return 1 for substring, 0 otherwise
|
||||
*/
|
||||
static int
|
||||
issub(const addrkey_t *s1, addrlen_t l1,
|
||||
const addrkey_t *s2, addrlen_t l2, addrlen_t skip)
|
||||
{
|
||||
return bits_common(s1, l1, s2, l2, skip) == l1;
|
||||
}
|
||||
|
||||
void
|
||||
addrtree_insert(struct addrtree *tree, const addrkey_t *addr,
|
||||
addrlen_t sourcemask, addrlen_t scope, void *elem, time_t ttl,
|
||||
time_t now)
|
||||
{
|
||||
struct addrnode *newnode, *node;
|
||||
struct addredge *edge;
|
||||
int index;
|
||||
addrlen_t common, depth;
|
||||
|
||||
node = tree->root;
|
||||
log_assert(node != NULL);
|
||||
|
||||
/* Protect our cache against too much fine-grained data */
|
||||
if (tree->max_depth < scope) scope = tree->max_depth;
|
||||
/* Server answer was less specific than question */
|
||||
if (scope < sourcemask) sourcemask = scope;
|
||||
|
||||
depth = 0;
|
||||
while (1) {
|
||||
log_assert(depth <= sourcemask);
|
||||
/* Case 1: update existing node */
|
||||
if (depth == sourcemask) {
|
||||
/* update this node's scope and data */
|
||||
clean_node(tree, node);
|
||||
node->ttl = ttl;
|
||||
node->elem = elem;
|
||||
node->scope = scope;
|
||||
tree->size_bytes += tree->sizefunc(elem);
|
||||
return;
|
||||
}
|
||||
index = getbit(addr, sourcemask, depth);
|
||||
/* Get an edge to an unexpired node */
|
||||
edge = node->edge[index];
|
||||
while (edge) {
|
||||
/* Purge all expired nodes on path */
|
||||
if (!edge->node->elem || edge->node->ttl >= now)
|
||||
break;
|
||||
purge_node(tree, edge->node);
|
||||
edge = node->edge[index];
|
||||
}
|
||||
/* Case 2: New leafnode */
|
||||
if (!edge) {
|
||||
newnode = node_create(tree, elem, scope, ttl);
|
||||
if (!newnode) return;
|
||||
if (!edge_create(newnode, addr, sourcemask, node,
|
||||
index)) {
|
||||
clean_node(tree, newnode);
|
||||
tree->node_count--;
|
||||
free(newnode);
|
||||
return;
|
||||
}
|
||||
tree->size_bytes += node_size(tree, newnode);
|
||||
lru_push(tree, newnode);
|
||||
lru_cleanup(tree);
|
||||
return;
|
||||
}
|
||||
/* Case 3: Traverse edge */
|
||||
common = bits_common(edge->str, edge->len, addr, sourcemask,
|
||||
depth);
|
||||
if (common == edge->len) {
|
||||
/* We update the scope of intermediate nodes. Apparently
|
||||
* the * authority changed its mind. If we would not do
|
||||
* this we might not be able to reach our new node. */
|
||||
node->scope = scope;
|
||||
depth = edge->len;
|
||||
node = edge->node;
|
||||
continue;
|
||||
}
|
||||
/* Case 4: split. */
|
||||
if (!(newnode = node_create(tree, NULL, 0, 0)))
|
||||
return;
|
||||
node->edge[index] = NULL;
|
||||
if (!edge_create(newnode, addr, common, node, index)) {
|
||||
node->edge[index] = edge;
|
||||
clean_node(tree, newnode);
|
||||
tree->node_count--;
|
||||
free(newnode);
|
||||
return;
|
||||
}
|
||||
lru_push(tree, newnode);
|
||||
/* connect existing child to our new node */
|
||||
index = getbit(edge->str, edge->len, common);
|
||||
newnode->edge[index] = edge;
|
||||
edge->parent_node = newnode;
|
||||
edge->parent_index = (int)index;
|
||||
|
||||
if (common == sourcemask) {
|
||||
/* Data is stored in the node */
|
||||
newnode->elem = elem;
|
||||
newnode->scope = scope;
|
||||
newnode->ttl = ttl;
|
||||
}
|
||||
|
||||
tree->size_bytes += node_size(tree, newnode);
|
||||
|
||||
if (common != sourcemask) {
|
||||
/* Data is stored in other leafnode */
|
||||
node = newnode;
|
||||
newnode = node_create(tree, elem, scope, ttl);
|
||||
if (!edge_create(newnode, addr, sourcemask, node,
|
||||
index^1)) {
|
||||
clean_node(tree, newnode);
|
||||
tree->node_count--;
|
||||
free(newnode);
|
||||
return;
|
||||
}
|
||||
tree->size_bytes += node_size(tree, newnode);
|
||||
lru_push(tree, newnode);
|
||||
}
|
||||
lru_cleanup(tree);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
struct addrnode *
|
||||
addrtree_find(struct addrtree *tree, const addrkey_t *addr,
|
||||
addrlen_t sourcemask, time_t now)
|
||||
{
|
||||
struct addrnode *node = tree->root;
|
||||
struct addredge *edge = NULL;
|
||||
addrlen_t depth = 0;
|
||||
|
||||
log_assert(node != NULL);
|
||||
while (1) {
|
||||
/* Current node more specific then question. */
|
||||
log_assert(depth <= sourcemask);
|
||||
/* does this node have data? if yes, see if we have a match */
|
||||
if (node->elem && node->ttl >= now) {
|
||||
/* saved at wrong depth */;
|
||||
log_assert(node->scope >= depth);
|
||||
if (depth == node->scope ||
|
||||
(node->scope > sourcemask &&
|
||||
depth == sourcemask)) {
|
||||
/* Authority indicates it does not have a more
|
||||
* precise answer or we cannot ask a more
|
||||
* specific question. */
|
||||
lru_update(tree, node);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
/* This is our final depth, but we haven't found an answer. */
|
||||
if (depth == sourcemask)
|
||||
return NULL;
|
||||
/* Find an edge to traverse */
|
||||
edge = node->edge[getbit(addr, sourcemask, depth)];
|
||||
if (!edge || !edge->node)
|
||||
return NULL;
|
||||
if (edge->len > sourcemask )
|
||||
return NULL;
|
||||
if (!issub(edge->str, edge->len, addr, sourcemask, depth))
|
||||
return NULL;
|
||||
log_assert(depth < edge->len);
|
||||
depth = edge->len;
|
||||
node = edge->node;
|
||||
}
|
||||
}
|
||||
|
||||
/** Wrappers for static functions to unit test */
|
||||
int unittest_wrapper_addrtree_cmpbit(const addrkey_t *key1,
|
||||
const addrkey_t *key2, addrlen_t n) {
|
||||
return cmpbit(key1, key2, n);
|
||||
}
|
||||
addrlen_t unittest_wrapper_addrtree_bits_common(const addrkey_t *s1,
|
||||
addrlen_t l1, const addrkey_t *s2, addrlen_t l2, addrlen_t skip) {
|
||||
return bits_common(s1, l1, s2, l2, skip);
|
||||
}
|
||||
int unittest_wrapper_addrtree_getbit(const addrkey_t *addr,
|
||||
addrlen_t addrlen, addrlen_t n) {
|
||||
return getbit(addr, addrlen, n);
|
||||
}
|
||||
int unittest_wrapper_addrtree_issub(const addrkey_t *s1, addrlen_t l1,
|
||||
const addrkey_t *s2, addrlen_t l2, addrlen_t skip) {
|
||||
return issub(s1, l1, s2, l2, skip);
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* edns-subnet/addrtree.h -- radix tree for edns subnet cache.
|
||||
*
|
||||
* Copyright (c) 2013, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* The addrtree is a radix tree designed for edns subnet. Most notable
|
||||
* is the addition of 'scope' to a node. Scope is only relevant for
|
||||
* nodes with elem set, it indicates the number of bits the authority
|
||||
* desires.
|
||||
*
|
||||
* For retrieving data one needs an address and address length
|
||||
* (sourcemask). While traversing the tree the first matching node is
|
||||
* returned. A node matches when
|
||||
* node.scope<=sourcemask && node.elem!=NULL
|
||||
* (This is the most specific answer the authority has.)
|
||||
* or
|
||||
* node.sourcemask==sourcemask && node.elem!=NULL
|
||||
* (This is the most specific question the client can ask.)
|
||||
*
|
||||
* Insertion needs an address, sourcemask and scope. The length of the
|
||||
* address is capped by min(sourcemask, scope). While traversing the
|
||||
* tree the scope of all visited nodes is updated. This ensures we are
|
||||
* always able to find the most specific answer available.
|
||||
*/
|
||||
|
||||
#ifndef ADDRTREE_H
|
||||
#define ADDRTREE_H
|
||||
|
||||
typedef uint8_t addrlen_t;
|
||||
typedef uint8_t addrkey_t;
|
||||
#define KEYWIDTH 8
|
||||
|
||||
struct addrtree {
|
||||
struct addrnode *root;
|
||||
/** Number of elements in the tree (not always equal to number of
|
||||
* nodes) */
|
||||
uint32_t node_count;
|
||||
/** Maximum number of allowed nodes, will be enforced by LRU list.
|
||||
* Excluding the root node, 0 for unlimited */
|
||||
uint32_t max_node_count;
|
||||
/** Size of tree in bytes */
|
||||
size_t size_bytes;
|
||||
/** Maximum prefix length we are willing to cache. */
|
||||
addrlen_t max_depth;
|
||||
/** External function to delete elem. Called as
|
||||
* delfunc(addrnode->elem, addrtree->env) */
|
||||
void (*delfunc)(void *, void *);
|
||||
/** Environment for delfunc */
|
||||
void *env;
|
||||
/** External function returning size of elem. Called as
|
||||
* sizefunc(addrnode->elem) */
|
||||
size_t (*sizefunc)(void *);
|
||||
/** first node in LRU list, first candidate to go */
|
||||
struct addrnode* first;
|
||||
/** last node in LRU list, last candidate to go */
|
||||
struct addrnode *last;
|
||||
};
|
||||
|
||||
struct addrnode {
|
||||
/** Payload of node, may be NULL */
|
||||
void *elem;
|
||||
/** Abs time in seconds in which elem is meaningful */
|
||||
time_t ttl;
|
||||
/** Number of significant bits in address. */
|
||||
addrlen_t scope;
|
||||
/** A node can have 0-2 edges, set to NULL for unused */
|
||||
struct addredge *edge[2];
|
||||
/** edge between this node and parent */
|
||||
struct addredge *parent_edge;
|
||||
/** previous node in LRU list */
|
||||
struct addrnode *prev;
|
||||
/** next node in LRU list */
|
||||
struct addrnode *next;
|
||||
};
|
||||
|
||||
struct addredge {
|
||||
/** address of connected node */
|
||||
addrkey_t *str;
|
||||
/** length in bits of str */
|
||||
addrlen_t len;
|
||||
/** child node this edge is connected to */
|
||||
struct addrnode *node;
|
||||
/** Parent node this ege is connected to */
|
||||
struct addrnode *parent_node;
|
||||
/** Index of this edge in parent_node */
|
||||
int parent_index;
|
||||
};
|
||||
|
||||
/**
|
||||
* Size of tree in bytes.
|
||||
* @param tree: Tree.
|
||||
* @return size of tree in bytes.
|
||||
*/
|
||||
size_t addrtree_size(const struct addrtree *tree);
|
||||
|
||||
/**
|
||||
* Create a new tree.
|
||||
* @param max_depth: Tree will cap keys to this length.
|
||||
* @param delfunc: f(element, env) delete element.
|
||||
* @param sizefunc: f(element) returning the size of element.
|
||||
* @param env: Module environment for alloc information.
|
||||
* @param max_node_count: Maximum size of this data structure in nodes.
|
||||
* 0 for unlimited.
|
||||
* @return new addrtree or NULL on failure.
|
||||
*/
|
||||
struct addrtree *
|
||||
addrtree_create(addrlen_t max_depth, void (*delfunc)(void *, void *),
|
||||
size_t (*sizefunc)(void *), void *env, uint32_t max_node_count);
|
||||
|
||||
/**
|
||||
* Free tree and all nodes below.
|
||||
* @param tree: Tree to be freed.
|
||||
*/
|
||||
void addrtree_delete(struct addrtree *tree);
|
||||
|
||||
/**
|
||||
* Insert an element in the tree. Failures are silent. Sourcemask and
|
||||
* scope might be changed according to local policy. Caller should no
|
||||
* longer access elem, it could be free'd now or later during future
|
||||
* inserts.
|
||||
*
|
||||
* @param tree: Tree insert elem in.
|
||||
* @param addr: key for element lookup.
|
||||
* @param sourcemask: Length of addr in bits.
|
||||
* @param scope: Number of significant bits in addr.
|
||||
* @param elem: data to store in the tree.
|
||||
* @param ttl: elem is valid up to this time, seconds.
|
||||
* @param now: Current time in seconds.
|
||||
*/
|
||||
void addrtree_insert(struct addrtree *tree, const addrkey_t *addr,
|
||||
addrlen_t sourcemask, addrlen_t scope, void *elem, time_t ttl,
|
||||
time_t now);
|
||||
|
||||
/**
|
||||
* Find a node containing an element in the tree.
|
||||
*
|
||||
* @param tree: Tree to search.
|
||||
* @param addr: key for element lookup.
|
||||
* @param sourcemask: Length of addr in bits.
|
||||
* @param now: Current time in seconds.
|
||||
* @return addrnode or NULL on miss.
|
||||
*/
|
||||
struct addrnode * addrtree_find(struct addrtree *tree,
|
||||
const addrkey_t *addr, addrlen_t sourcemask, time_t now);
|
||||
|
||||
/** Wrappers for static functions to unit test */
|
||||
int unittest_wrapper_addrtree_cmpbit(const addrkey_t *key1,
|
||||
const addrkey_t *key2, addrlen_t n);
|
||||
addrlen_t unittest_wrapper_addrtree_bits_common(const addrkey_t *s1,
|
||||
addrlen_t l1, const addrkey_t *s2, addrlen_t l2, addrlen_t skip);
|
||||
int unittest_wrapper_addrtree_getbit(const addrkey_t *addr,
|
||||
addrlen_t addrlen, addrlen_t n);
|
||||
int unittest_wrapper_addrtree_issub(const addrkey_t *s1, addrlen_t l1,
|
||||
const addrkey_t *s2, addrlen_t l2, addrlen_t skip);
|
||||
#endif /* ADDRTREE_H */
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* edns-subnet/edns-subnet.c - Subnet option related constants
|
||||
*
|
||||
* Copyright (c) 2013, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Subnet option related constants.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef CLIENT_SUBNET /* keeps splint happy */
|
||||
#include "edns-subnet/edns-subnet.h"
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
copy_clear(uint8_t* dst, size_t dstlen, uint8_t* src, size_t srclen, size_t n)
|
||||
{
|
||||
size_t intpart = n / 8; /* bytes */
|
||||
size_t fracpart = n % 8; /* bits */
|
||||
size_t written = intpart;
|
||||
if (intpart > dstlen || intpart > srclen)
|
||||
return 1;
|
||||
if (fracpart && (intpart+1 > dstlen || intpart+1 > srclen))
|
||||
return 1;
|
||||
memcpy(dst, src, intpart);
|
||||
if (fracpart) {
|
||||
dst[intpart] = src[intpart] & ~(0xFF >> fracpart);
|
||||
written++;
|
||||
}
|
||||
memset(dst + written, 0, dstlen - written);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CLIENT_SUBNET */
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* edns-subnet/edns-subnet.h - Subnet option related constants
|
||||
*
|
||||
* Copyright (c) 2013, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Subnet option related constants.
|
||||
*/
|
||||
|
||||
#include "util/net_help.h"
|
||||
|
||||
#ifndef EDNSSUBNET_EDNSSUBNET_H
|
||||
#define EDNSSUBNET_EDNSSUBNET_H
|
||||
|
||||
/** In use by the edns subnet option code, as assigned by IANA */
|
||||
#define EDNSSUBNET_ADDRFAM_IP4 1
|
||||
#define EDNSSUBNET_ADDRFAM_IP6 2
|
||||
|
||||
/**
|
||||
* ECS option
|
||||
*/
|
||||
struct ecs_data {
|
||||
uint16_t subnet_addr_fam;
|
||||
uint8_t subnet_source_mask;
|
||||
uint8_t subnet_scope_mask;
|
||||
uint8_t subnet_addr[INET6_SIZE];
|
||||
int subnet_validdata;
|
||||
};
|
||||
|
||||
/**
|
||||
* copy the first n BITS from src to dst iff both src and dst
|
||||
* are large enough, return 0 on succes
|
||||
*/
|
||||
int
|
||||
copy_clear(uint8_t* dst, size_t dstlen, uint8_t* src, size_t srclen, size_t n);
|
||||
|
||||
#endif /* EDNSSUBNET_EDNSSUBNET_H */
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* edns-subnet/subnet-whitelist.c - Hosts we actively try to send subnet option
|
||||
* to.
|
||||
*
|
||||
* Copyright (c) 2013, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Keep track of the white listed servers for subnet option. Based
|
||||
* on acl_list.c|h
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef CLIENT_SUBNET /* keeps splint happy */
|
||||
#include "edns-subnet/edns-subnet.h"
|
||||
#include "edns-subnet/subnet-whitelist.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/storage/dnstree.h"
|
||||
#include "sldns/str2wire.h"
|
||||
#include "util/data/dname.h"
|
||||
|
||||
struct ecs_whitelist*
|
||||
ecs_whitelist_create(void)
|
||||
{
|
||||
struct ecs_whitelist* whitelist =
|
||||
(struct ecs_whitelist*)calloc(1,
|
||||
sizeof(struct ecs_whitelist));
|
||||
if(!whitelist)
|
||||
return NULL;
|
||||
whitelist->region = regional_create();
|
||||
if(!whitelist->region) {
|
||||
ecs_whitelist_delete(whitelist);
|
||||
return NULL;
|
||||
}
|
||||
return whitelist;
|
||||
}
|
||||
|
||||
void
|
||||
ecs_whitelist_delete(struct ecs_whitelist* whitelist)
|
||||
{
|
||||
if(!whitelist)
|
||||
return;
|
||||
regional_destroy(whitelist->region);
|
||||
free(whitelist);
|
||||
}
|
||||
|
||||
/** insert new address into whitelist structure */
|
||||
static int
|
||||
upstream_insert(struct ecs_whitelist* whitelist,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int net)
|
||||
{
|
||||
struct addr_tree_node* node = (struct addr_tree_node*)regional_alloc(
|
||||
whitelist->region, sizeof(*node));
|
||||
if(!node)
|
||||
return 0;
|
||||
if(!addr_tree_insert(&whitelist->upstream, node, addr, addrlen, net)) {
|
||||
verbose(VERB_QUERY,
|
||||
"duplicate send-client-subnet address ignored.");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** apply edns-subnet string */
|
||||
static int
|
||||
upstream_str_cfg(struct ecs_whitelist* whitelist, const char* str)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
int net;
|
||||
socklen_t addrlen;
|
||||
verbose(VERB_ALGO, "send-client-subnet: %s", str);
|
||||
if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
|
||||
log_err("cannot parse send-client-subnet netblock: %s", str);
|
||||
return 0;
|
||||
}
|
||||
if(!upstream_insert(whitelist, &addr, addrlen, net)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read client_subnet config */
|
||||
static int
|
||||
read_upstream(struct ecs_whitelist* whitelist, struct config_file* cfg)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
for(p = cfg->client_subnet; p; p = p->next) {
|
||||
log_assert(p->str);
|
||||
if(!upstream_str_cfg(whitelist, p->str))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read client_subnet_zone config */
|
||||
static int
|
||||
read_names(struct ecs_whitelist* whitelist, struct config_file* cfg)
|
||||
{
|
||||
/* parse names, report errors, insert into tree */
|
||||
struct config_strlist* p;
|
||||
struct name_tree_node* n;
|
||||
uint8_t* nm, *nmr;
|
||||
size_t nm_len;
|
||||
int nm_labs;
|
||||
|
||||
for(p = cfg->client_subnet_zone; p; p = p->next) {
|
||||
log_assert(p->str);
|
||||
nm = sldns_str2wire_dname(p->str, &nm_len);
|
||||
if(!nm) {
|
||||
log_err("cannot parse client-subnet-zone: %s", p->str);
|
||||
return 0;
|
||||
}
|
||||
nm_labs = dname_count_size_labels(nm, &nm_len);
|
||||
nmr = (uint8_t*)regional_alloc_init(whitelist->region, nm,
|
||||
nm_len);
|
||||
free(nm);
|
||||
if(!nmr) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
n = (struct name_tree_node*)regional_alloc(whitelist->region,
|
||||
sizeof(*n));
|
||||
if(!n) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
if(!name_tree_insert(&whitelist->dname, n, nmr, nm_len, nm_labs,
|
||||
LDNS_RR_CLASS_IN)) {
|
||||
verbose(VERB_QUERY, "ignoring duplicate "
|
||||
"client-subnet-zone: %s", p->str);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ecs_whitelist_apply_cfg(struct ecs_whitelist* whitelist,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
regional_free_all(whitelist->region);
|
||||
addr_tree_init(&whitelist->upstream);
|
||||
name_tree_init(&whitelist->dname);
|
||||
if(!read_upstream(whitelist, cfg))
|
||||
return 0;
|
||||
if(!read_names(whitelist, cfg))
|
||||
return 0;
|
||||
addr_tree_init_parents(&whitelist->upstream);
|
||||
name_tree_init_parents(&whitelist->dname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ecs_is_whitelisted(struct ecs_whitelist* whitelist,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* qname,
|
||||
size_t qname_len, uint16_t qclass)
|
||||
{
|
||||
int labs;
|
||||
if(addr_tree_lookup(&whitelist->upstream, addr, addrlen))
|
||||
return 1;
|
||||
/* Not in upstream whitelist, check dname whitelist. */
|
||||
labs = dname_count_labels(qname);
|
||||
return name_tree_lookup(&whitelist->dname, qname, qname_len, labs,
|
||||
qclass) != NULL;
|
||||
}
|
||||
|
||||
size_t
|
||||
ecs_whitelist_get_mem(struct ecs_whitelist* whitelist)
|
||||
{
|
||||
if(!whitelist) return 0;
|
||||
return sizeof(*whitelist) + regional_get_mem(whitelist->region);
|
||||
}
|
||||
|
||||
#endif /* CLIENT_SUBNET */
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* edns-subnet/subnet-whitelist.h - Hosts we actively try to send subnet option
|
||||
* to.
|
||||
*
|
||||
* Copyright (c) 2013, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Keep track of the white listed servers and domain names for subnet option.
|
||||
* Based on acl_list.c|h
|
||||
*/
|
||||
|
||||
#ifndef EDNSSUBNET_WHITELIST_H
|
||||
#define EDNSSUBNET_WHITELIST_H
|
||||
#include "util/storage/dnstree.h"
|
||||
|
||||
struct config_file;
|
||||
struct regional;
|
||||
|
||||
/**
|
||||
* ecs_whitelist structure
|
||||
*/
|
||||
struct ecs_whitelist {
|
||||
/** regional for allocation */
|
||||
struct regional* region;
|
||||
/**
|
||||
* Tree of the address spans that are whitelisted.
|
||||
* contents of type addr_tree_node. Each node is an address span
|
||||
* Unbound will append subnet option for.
|
||||
*/
|
||||
rbtree_type upstream;
|
||||
/**
|
||||
* Tree of domain names for which Unbound will append an ECS option.
|
||||
* rbtree of struct name_tree_node.
|
||||
*/
|
||||
rbtree_type dname;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create ecs_whitelist structure
|
||||
* @return new structure or NULL on error.
|
||||
*/
|
||||
struct ecs_whitelist* ecs_whitelist_create(void);
|
||||
|
||||
/**
|
||||
* Delete ecs_whitelist structure.
|
||||
* @param whitelist: to delete.
|
||||
*/
|
||||
void ecs_whitelist_delete(struct ecs_whitelist* whitelist);
|
||||
|
||||
/**
|
||||
* Process ecs_whitelist config.
|
||||
* @param whitelist: where to store.
|
||||
* @param cfg: config options.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
int ecs_whitelist_apply_cfg(struct ecs_whitelist* whitelist,
|
||||
struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* See if an address or domain is whitelisted.
|
||||
* @param whitelist: structure for address storage.
|
||||
* @param addr: address to check
|
||||
* @param addrlen: length of addr.
|
||||
* @param qname: dname in query
|
||||
* @param qname_len: length of dname
|
||||
* @param qclass: class in query
|
||||
* @return: true if the address is whitelisted for subnet option.
|
||||
*/
|
||||
int ecs_is_whitelisted(struct ecs_whitelist* whitelist,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* qname,
|
||||
size_t qname_len, uint16_t qclass);
|
||||
|
||||
/**
|
||||
* Get memory used by ecs_whitelist structure.
|
||||
* @param whitelist: structure for address storage.
|
||||
* @return bytes in use.
|
||||
*/
|
||||
size_t ecs_whitelist_get_mem(struct ecs_whitelist* whitelist);
|
||||
|
||||
#endif /* EDNSSUBNET_WHITELIST_H */
|
||||
@@ -0,0 +1,866 @@
|
||||
/*
|
||||
* edns-subnet/subnetmod.c - edns subnet module. Must be called before validator
|
||||
* and iterator.
|
||||
*
|
||||
* Copyright (c) 2013, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* subnet module for unbound.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef CLIENT_SUBNET /* keeps splint happy */
|
||||
|
||||
#include "edns-subnet/subnetmod.h"
|
||||
#include "edns-subnet/edns-subnet.h"
|
||||
#include "edns-subnet/addrtree.h"
|
||||
#include "edns-subnet/subnet-whitelist.h"
|
||||
|
||||
#include "services/mesh.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "util/module.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "iterator/iter_utils.h"
|
||||
|
||||
/** externally called */
|
||||
void
|
||||
subnet_data_delete(void *d, void *ATTR_UNUSED(arg))
|
||||
{
|
||||
struct subnet_msg_cache_data *r;
|
||||
r = (struct subnet_msg_cache_data*)d;
|
||||
addrtree_delete(r->tree4);
|
||||
addrtree_delete(r->tree6);
|
||||
free(r);
|
||||
}
|
||||
|
||||
/** externally called */
|
||||
size_t
|
||||
msg_cache_sizefunc(void *k, void *d)
|
||||
{
|
||||
struct msgreply_entry *q = (struct msgreply_entry*)k;
|
||||
struct subnet_msg_cache_data *r = (struct subnet_msg_cache_data*)d;
|
||||
size_t s = sizeof(struct msgreply_entry)
|
||||
+ sizeof(struct subnet_msg_cache_data)
|
||||
+ q->key.qname_len + lock_get_mem(&q->entry.lock);
|
||||
s += addrtree_size(r->tree4);
|
||||
s += addrtree_size(r->tree6);
|
||||
return s;
|
||||
}
|
||||
|
||||
/** new query for ecs module */
|
||||
static int
|
||||
subnet_new_qstate(struct module_qstate *qstate, int id)
|
||||
{
|
||||
struct subnet_qstate *sq = (struct subnet_qstate*)regional_alloc(
|
||||
qstate->region, sizeof(struct subnet_qstate));
|
||||
if(!sq)
|
||||
return 0;
|
||||
qstate->minfo[id] = sq;
|
||||
memset(sq, 0, sizeof(*sq));
|
||||
sq->started_no_cache_store = qstate->no_cache_store;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Add ecs struct to edns list, after parsing it to wire format. */
|
||||
static void
|
||||
ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
|
||||
struct module_qstate *qstate)
|
||||
{
|
||||
size_t sn_octs, sn_octs_remainder;
|
||||
sldns_buffer* buf = qstate->env->scratch_buffer;
|
||||
|
||||
if(ecs->subnet_validdata) {
|
||||
log_assert(ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 ||
|
||||
ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6);
|
||||
log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP4 ||
|
||||
ecs->subnet_source_mask <= INET_SIZE*8);
|
||||
log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP6 ||
|
||||
ecs->subnet_source_mask <= INET6_SIZE*8);
|
||||
|
||||
sn_octs = ecs->subnet_source_mask / 8;
|
||||
sn_octs_remainder =
|
||||
(size_t)((ecs->subnet_source_mask % 8)>0?1:0);
|
||||
|
||||
log_assert(sn_octs + sn_octs_remainder <= INET6_SIZE);
|
||||
|
||||
sldns_buffer_clear(buf);
|
||||
sldns_buffer_write_u16(buf, ecs->subnet_addr_fam);
|
||||
sldns_buffer_write_u8(buf, ecs->subnet_source_mask);
|
||||
sldns_buffer_write_u8(buf, ecs->subnet_scope_mask);
|
||||
sldns_buffer_write(buf, ecs->subnet_addr, sn_octs);
|
||||
if(sn_octs_remainder)
|
||||
sldns_buffer_write_u8(buf, ecs->subnet_addr[sn_octs] &
|
||||
~(0xFF >> (ecs->subnet_source_mask % 8)));
|
||||
sldns_buffer_flip(buf);
|
||||
|
||||
edns_opt_list_append(list,
|
||||
qstate->env->cfg->client_subnet_opcode,
|
||||
sn_octs + sn_octs_remainder + 4,
|
||||
sldns_buffer_begin(buf), qstate->region);
|
||||
}
|
||||
}
|
||||
|
||||
int ecs_whitelist_check(struct query_info* qinfo,
|
||||
uint16_t ATTR_UNUSED(flags), struct module_qstate* qstate,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
|
||||
struct regional* ATTR_UNUSED(region), int id, void* ATTR_UNUSED(cbargs))
|
||||
{
|
||||
struct subnet_qstate *sq;
|
||||
struct subnet_env *sn_env;
|
||||
|
||||
if(!(sq=(struct subnet_qstate*)qstate->minfo[id]))
|
||||
return 1;
|
||||
sn_env = (struct subnet_env*)qstate->env->modinfo[id];
|
||||
|
||||
/* Cache by default, might be disabled after parsing EDNS option
|
||||
* received from nameserver. */
|
||||
if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo)) {
|
||||
qstate->no_cache_store = 0;
|
||||
}
|
||||
|
||||
if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream &&
|
||||
qstate->env->cfg->client_subnet_always_forward) ||
|
||||
ecs_is_whitelisted(sn_env->whitelist,
|
||||
addr, addrlen, qinfo->qname, qinfo->qname_len,
|
||||
qinfo->qclass))) {
|
||||
/* Address on whitelist or client query contains ECS option, we
|
||||
* want to sent out ECS. Only add option if it is not already
|
||||
* set. */
|
||||
if(!(sq->subnet_sent)) {
|
||||
ecs_opt_list_append(&sq->ecs_server_out,
|
||||
&qstate->edns_opts_back_out, qstate);
|
||||
sq->subnet_sent = 1;
|
||||
}
|
||||
}
|
||||
else if(sq->subnet_sent) {
|
||||
/* Outgoing ECS option is set, but we don't want to sent it to
|
||||
* this address, remove option. */
|
||||
edns_opt_list_remove(&qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode);
|
||||
sq->subnet_sent = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
subnet_markdel(void* key)
|
||||
{
|
||||
struct msgreply_entry *e = (struct msgreply_entry*)key;
|
||||
e->key.qtype = 0;
|
||||
e->key.qclass = 0;
|
||||
}
|
||||
|
||||
int
|
||||
subnetmod_init(struct module_env *env, int id)
|
||||
{
|
||||
struct subnet_env *sn_env = (struct subnet_env*)calloc(1,
|
||||
sizeof(struct subnet_env));
|
||||
if(!sn_env) {
|
||||
log_err("malloc failure");
|
||||
return 0;
|
||||
}
|
||||
alloc_init(&sn_env->alloc, NULL, 0);
|
||||
env->modinfo[id] = (void*)sn_env;
|
||||
/* Copy msg_cache settings */
|
||||
sn_env->subnet_msg_cache = slabhash_create(env->cfg->msg_cache_slabs,
|
||||
HASH_DEFAULT_STARTARRAY, env->cfg->msg_cache_size,
|
||||
msg_cache_sizefunc, query_info_compare, query_entry_delete,
|
||||
subnet_data_delete, NULL);
|
||||
slabhash_setmarkdel(sn_env->subnet_msg_cache, &subnet_markdel);
|
||||
if(!sn_env->subnet_msg_cache) {
|
||||
log_err("subnet: could not create cache");
|
||||
free(sn_env);
|
||||
env->modinfo[id] = NULL;
|
||||
return 0;
|
||||
}
|
||||
/* whitelist for edns subnet capable servers */
|
||||
sn_env->whitelist = ecs_whitelist_create();
|
||||
if(!sn_env->whitelist ||
|
||||
!ecs_whitelist_apply_cfg(sn_env->whitelist, env->cfg)) {
|
||||
log_err("subnet: could not create ECS whitelist");
|
||||
slabhash_delete(sn_env->subnet_msg_cache);
|
||||
free(sn_env);
|
||||
env->modinfo[id] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
verbose(VERB_QUERY, "subnet: option registered (%d)",
|
||||
env->cfg->client_subnet_opcode);
|
||||
/* Create new mesh state for all queries. */
|
||||
env->unique_mesh = 1;
|
||||
if(!edns_register_option(env->cfg->client_subnet_opcode,
|
||||
env->cfg->client_subnet_always_forward /* bypass cache */,
|
||||
0 /* no aggregation */, env)) {
|
||||
log_err("subnet: could not register opcode");
|
||||
ecs_whitelist_delete(sn_env->whitelist);
|
||||
slabhash_delete(sn_env->subnet_msg_cache);
|
||||
free(sn_env);
|
||||
env->modinfo[id] = NULL;
|
||||
return 0;
|
||||
}
|
||||
inplace_cb_register((void*)ecs_whitelist_check, inplace_cb_query, NULL,
|
||||
env, id);
|
||||
inplace_cb_register((void*)ecs_edns_back_parsed,
|
||||
inplace_cb_edns_back_parsed, NULL, env, id);
|
||||
inplace_cb_register((void*)ecs_query_response,
|
||||
inplace_cb_query_response, NULL, env, id);
|
||||
lock_rw_init(&sn_env->biglock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
subnetmod_deinit(struct module_env *env, int id)
|
||||
{
|
||||
struct subnet_env *sn_env;
|
||||
if(!env || !env->modinfo[id])
|
||||
return;
|
||||
sn_env = (struct subnet_env*)env->modinfo[id];
|
||||
lock_rw_destroy(&sn_env->biglock);
|
||||
inplace_cb_delete(env, inplace_cb_edns_back_parsed, id);
|
||||
inplace_cb_delete(env, inplace_cb_query, id);
|
||||
inplace_cb_delete(env, inplace_cb_query_response, id);
|
||||
ecs_whitelist_delete(sn_env->whitelist);
|
||||
slabhash_delete(sn_env->subnet_msg_cache);
|
||||
alloc_clear(&sn_env->alloc);
|
||||
free(sn_env);
|
||||
env->modinfo[id] = NULL;
|
||||
}
|
||||
|
||||
/** Tells client that upstream has no/improper support */
|
||||
static void
|
||||
cp_edns_bad_response(struct ecs_data *target, struct ecs_data *source)
|
||||
{
|
||||
target->subnet_scope_mask = 0;
|
||||
target->subnet_source_mask = source->subnet_source_mask;
|
||||
target->subnet_addr_fam = source->subnet_addr_fam;
|
||||
memcpy(target->subnet_addr, source->subnet_addr, INET6_SIZE);
|
||||
target->subnet_validdata = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
delfunc(void *envptr, void *elemptr) {
|
||||
struct reply_info *elem = (struct reply_info *)elemptr;
|
||||
struct subnet_env *env = (struct subnet_env *)envptr;
|
||||
reply_info_parsedelete(elem, &env->alloc);
|
||||
}
|
||||
|
||||
static size_t
|
||||
sizefunc(void *elemptr) {
|
||||
struct reply_info *elem = (struct reply_info *)elemptr;
|
||||
return sizeof (struct reply_info) - sizeof (struct rrset_ref)
|
||||
+ elem->rrset_count * sizeof (struct rrset_ref)
|
||||
+ elem->rrset_count * sizeof (struct ub_packed_rrset_key *);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select tree from cache entry based on edns data.
|
||||
* If for address family not present it will create a new one.
|
||||
* NULL on failure to create. */
|
||||
static struct addrtree*
|
||||
get_tree(struct subnet_msg_cache_data *data, struct ecs_data *edns,
|
||||
struct subnet_env *env, struct config_file* cfg)
|
||||
{
|
||||
struct addrtree *tree;
|
||||
if (edns->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
|
||||
if (!data->tree4)
|
||||
data->tree4 = addrtree_create(
|
||||
cfg->max_client_subnet_ipv4, &delfunc,
|
||||
&sizefunc, env, cfg->max_ecs_tree_size_ipv4);
|
||||
tree = data->tree4;
|
||||
} else {
|
||||
if (!data->tree6)
|
||||
data->tree6 = addrtree_create(
|
||||
cfg->max_client_subnet_ipv6, &delfunc,
|
||||
&sizefunc, env, cfg->max_ecs_tree_size_ipv6);
|
||||
tree = data->tree6;
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
static void
|
||||
update_cache(struct module_qstate *qstate, int id)
|
||||
{
|
||||
struct msgreply_entry *mrep_entry;
|
||||
struct addrtree *tree;
|
||||
struct reply_info *rep;
|
||||
struct query_info qinf;
|
||||
struct subnet_env *sne = qstate->env->modinfo[id];
|
||||
struct subnet_qstate *sq = (struct subnet_qstate*)qstate->minfo[id];
|
||||
struct slabhash *subnet_msg_cache = sne->subnet_msg_cache;
|
||||
struct ecs_data *edns = &sq->ecs_client_in;
|
||||
size_t i;
|
||||
|
||||
/* We already calculated hash upon lookup */
|
||||
hashvalue_type h = qstate->minfo[id] ?
|
||||
((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash :
|
||||
query_info_hash(&qstate->qinfo, qstate->query_flags);
|
||||
/* Step 1, general qinfo lookup */
|
||||
struct lruhash_entry *lru_entry = slabhash_lookup(subnet_msg_cache, h,
|
||||
&qstate->qinfo, 1);
|
||||
int need_to_insert = (lru_entry == NULL);
|
||||
if (!lru_entry) {
|
||||
void* data = calloc(1,
|
||||
sizeof(struct subnet_msg_cache_data));
|
||||
if(!data) {
|
||||
log_err("malloc failed");
|
||||
return;
|
||||
}
|
||||
qinf = qstate->qinfo;
|
||||
qinf.qname = memdup(qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len);
|
||||
if(!qinf.qname) {
|
||||
free(data);
|
||||
log_err("memdup failed");
|
||||
return;
|
||||
}
|
||||
mrep_entry = query_info_entrysetup(&qinf, data, h);
|
||||
free(qinf.qname); /* if qname 'consumed', it is set to NULL */
|
||||
if (!mrep_entry) {
|
||||
free(data);
|
||||
log_err("query_info_entrysetup failed");
|
||||
return;
|
||||
}
|
||||
lru_entry = &mrep_entry->entry;
|
||||
lock_rw_wrlock(&lru_entry->lock);
|
||||
}
|
||||
/* lru_entry->lock is locked regardless of how we got here,
|
||||
* either from the slabhash_lookup, or above in the new allocated */
|
||||
/* Step 2, find the correct tree */
|
||||
if (!(tree = get_tree(lru_entry->data, edns, sne, qstate->env->cfg))) {
|
||||
lock_rw_unlock(&lru_entry->lock);
|
||||
log_err("Subnet cache insertion failed");
|
||||
return;
|
||||
}
|
||||
lock_quick_lock(&sne->alloc.lock);
|
||||
rep = reply_info_copy(qstate->return_msg->rep, &sne->alloc, NULL);
|
||||
lock_quick_unlock(&sne->alloc.lock);
|
||||
if (!rep) {
|
||||
lock_rw_unlock(&lru_entry->lock);
|
||||
log_err("Subnet cache insertion failed");
|
||||
return;
|
||||
}
|
||||
|
||||
/* store RRsets */
|
||||
for(i=0; i<rep->rrset_count; i++) {
|
||||
rep->ref[i].key = rep->rrsets[i];
|
||||
rep->ref[i].id = rep->rrsets[i]->id;
|
||||
}
|
||||
reply_info_set_ttls(rep, *qstate->env->now);
|
||||
rep->flags |= (BIT_RA | BIT_QR); /* fix flags to be sensible for */
|
||||
rep->flags &= ~(BIT_AA | BIT_CD);/* a reply based on the cache */
|
||||
addrtree_insert(tree, (addrkey_t*)edns->subnet_addr,
|
||||
edns->subnet_source_mask,
|
||||
sq->ecs_server_in.subnet_scope_mask, rep,
|
||||
rep->ttl, *qstate->env->now);
|
||||
|
||||
lock_rw_unlock(&lru_entry->lock);
|
||||
if (need_to_insert) {
|
||||
slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/** Lookup in cache and reply true iff reply is sent. */
|
||||
static int
|
||||
lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
{
|
||||
struct lruhash_entry *e;
|
||||
struct module_env *env = qstate->env;
|
||||
struct subnet_env *sne = (struct subnet_env*)env->modinfo[id];
|
||||
hashvalue_type h = query_info_hash(&qstate->qinfo, qstate->query_flags);
|
||||
struct subnet_msg_cache_data *data;
|
||||
struct ecs_data *ecs = &sq->ecs_client_in;
|
||||
struct addrtree *tree;
|
||||
struct addrnode *node;
|
||||
uint8_t scope;
|
||||
|
||||
memset(&sq->ecs_client_out, 0, sizeof(sq->ecs_client_out));
|
||||
|
||||
if (sq) sq->qinfo_hash = h; /* Might be useful on cache miss */
|
||||
e = slabhash_lookup(sne->subnet_msg_cache, h, &qstate->qinfo, 1);
|
||||
if (!e) return 0; /* qinfo not in cache */
|
||||
data = e->data;
|
||||
tree = (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4)?
|
||||
data->tree4 : data->tree6;
|
||||
if (!tree) { /* qinfo in cache but not for this family */
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 0;
|
||||
}
|
||||
node = addrtree_find(tree, (addrkey_t*)ecs->subnet_addr,
|
||||
ecs->subnet_source_mask, *env->now);
|
||||
if (!node) { /* plain old cache miss */
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
qstate->return_msg = tomsg(NULL, &qstate->qinfo,
|
||||
(struct reply_info *)node->elem, qstate->region, *env->now,
|
||||
env->scratch);
|
||||
scope = (uint8_t)node->scope;
|
||||
lock_rw_unlock(&e->lock);
|
||||
|
||||
if (!qstate->return_msg) { /* Failed allocation or expired TTL */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sq->subnet_downstream) { /* relay to interested client */
|
||||
sq->ecs_client_out.subnet_scope_mask = scope;
|
||||
sq->ecs_client_out.subnet_addr_fam = ecs->subnet_addr_fam;
|
||||
sq->ecs_client_out.subnet_source_mask = ecs->subnet_source_mask;
|
||||
memcpy(&sq->ecs_client_out.subnet_addr, &ecs->subnet_addr,
|
||||
INET6_SIZE);
|
||||
sq->ecs_client_out.subnet_validdata = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test first bits of addresses for equality. Caller is responsible
|
||||
* for making sure that both a and b are at least net/8 octets long.
|
||||
* @param a: first address.
|
||||
* @param a: seconds address.
|
||||
* @param net: Number of bits to test.
|
||||
* @return: 1 if equal, 0 otherwise.
|
||||
*/
|
||||
static int
|
||||
common_prefix(uint8_t *a, uint8_t *b, uint8_t net)
|
||||
{
|
||||
size_t n = (size_t)net / 8;
|
||||
return !memcmp(a, b, n) && ((net % 8) == 0 || a[n] == b[n]);
|
||||
}
|
||||
|
||||
static enum module_ext_state
|
||||
eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
{
|
||||
struct subnet_env *sne = qstate->env->modinfo[id];
|
||||
|
||||
struct ecs_data *c_in = &sq->ecs_client_in; /* rcvd from client */
|
||||
struct ecs_data *c_out = &sq->ecs_client_out;/* will send to client */
|
||||
struct ecs_data *s_in = &sq->ecs_server_in; /* rcvd from auth */
|
||||
struct ecs_data *s_out = &sq->ecs_server_out;/* sent to auth */
|
||||
|
||||
memset(c_out, 0, sizeof(*c_out));
|
||||
|
||||
if (!qstate->return_msg) {
|
||||
/* already an answer and its not a message, but retain
|
||||
* the actual rcode, instead of module_error, so send
|
||||
* module_finished */
|
||||
return module_finished;
|
||||
}
|
||||
|
||||
/* We have not asked for subnet data */
|
||||
if (!sq->subnet_sent) {
|
||||
if (s_in->subnet_validdata)
|
||||
verbose(VERB_QUERY, "subnet: received spurious data");
|
||||
if (sq->subnet_downstream) /* Copy back to client */
|
||||
cp_edns_bad_response(c_out, c_in);
|
||||
return module_finished;
|
||||
}
|
||||
|
||||
/* subnet sent but nothing came back */
|
||||
if (!s_in->subnet_validdata) {
|
||||
/* The authority indicated no support for edns subnet. As a
|
||||
* consequence the answer ended up in the regular cache. It
|
||||
* is still usefull to put it in the edns subnet cache for
|
||||
* when a client explicitly asks for subnet specific answer. */
|
||||
verbose(VERB_QUERY, "subnet: Authority indicates no support");
|
||||
if(!sq->started_no_cache_store) {
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
update_cache(qstate, id);
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
}
|
||||
if (sq->subnet_downstream)
|
||||
cp_edns_bad_response(c_out, c_in);
|
||||
return module_finished;
|
||||
}
|
||||
|
||||
/* Being here means we have asked for and got a subnet specific
|
||||
* answer. Also, the answer from the authority is not yet cached
|
||||
* anywhere. */
|
||||
|
||||
/* can we accept response? */
|
||||
if(s_out->subnet_addr_fam != s_in->subnet_addr_fam ||
|
||||
s_out->subnet_source_mask != s_in->subnet_source_mask ||
|
||||
!common_prefix(s_out->subnet_addr, s_in->subnet_addr,
|
||||
s_out->subnet_source_mask))
|
||||
{
|
||||
/* we can not accept, restart query without option */
|
||||
verbose(VERB_QUERY, "subnet: forged data");
|
||||
s_out->subnet_validdata = 0;
|
||||
(void)edns_opt_list_remove(&qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode);
|
||||
sq->subnet_sent = 0;
|
||||
return module_restart_next;
|
||||
}
|
||||
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
if(!sq->started_no_cache_store) {
|
||||
update_cache(qstate, id);
|
||||
}
|
||||
sne->num_msg_nocache++;
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
|
||||
if (sq->subnet_downstream) {
|
||||
/* Client wants to see the answer, echo option back
|
||||
* and adjust the scope. */
|
||||
c_out->subnet_addr_fam = c_in->subnet_addr_fam;
|
||||
c_out->subnet_source_mask = c_in->subnet_source_mask;
|
||||
memcpy(&c_out->subnet_addr, &c_in->subnet_addr, INET6_SIZE);
|
||||
c_out->subnet_scope_mask = s_in->subnet_scope_mask;
|
||||
/* Limit scope returned to client to scope used for caching. */
|
||||
if(c_out->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
|
||||
if(c_out->subnet_scope_mask >
|
||||
qstate->env->cfg->max_client_subnet_ipv4) {
|
||||
c_out->subnet_scope_mask =
|
||||
qstate->env->cfg->max_client_subnet_ipv4;
|
||||
}
|
||||
}
|
||||
else if(c_out->subnet_scope_mask >
|
||||
qstate->env->cfg->max_client_subnet_ipv6) {
|
||||
c_out->subnet_scope_mask =
|
||||
qstate->env->cfg->max_client_subnet_ipv6;
|
||||
}
|
||||
c_out->subnet_validdata = 1;
|
||||
}
|
||||
return module_finished;
|
||||
}
|
||||
|
||||
/** Parse EDNS opt data containing ECS */
|
||||
static int
|
||||
parse_subnet_option(struct edns_option* ecs_option, struct ecs_data* ecs)
|
||||
{
|
||||
memset(ecs, 0, sizeof(*ecs));
|
||||
if (ecs_option->opt_len < 4)
|
||||
return 0;
|
||||
|
||||
ecs->subnet_addr_fam = sldns_read_uint16(ecs_option->opt_data);
|
||||
ecs->subnet_source_mask = ecs_option->opt_data[2];
|
||||
ecs->subnet_scope_mask = ecs_option->opt_data[3];
|
||||
/* remaining bytes indicate address */
|
||||
|
||||
/* validate input*/
|
||||
/* option length matches calculated length? */
|
||||
if (ecs_option->opt_len != (size_t)((ecs->subnet_source_mask+7)/8 + 4))
|
||||
return 0;
|
||||
if (ecs_option->opt_len - 4 > INET6_SIZE || ecs_option->opt_len == 0)
|
||||
return 0;
|
||||
if (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
|
||||
if (ecs->subnet_source_mask > 32 || ecs->subnet_scope_mask > 32)
|
||||
return 0;
|
||||
} else if (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6) {
|
||||
if (ecs->subnet_source_mask > 128 ||
|
||||
ecs->subnet_scope_mask > 128)
|
||||
return 0;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
/* valid ECS data, write to ecs_data */
|
||||
if (copy_clear(ecs->subnet_addr, INET6_SIZE, ecs_option->opt_data + 4,
|
||||
ecs_option->opt_len - 4, ecs->subnet_source_mask))
|
||||
return 0;
|
||||
ecs->subnet_validdata = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
void* sinaddr;
|
||||
|
||||
/* Construct subnet option from original query */
|
||||
if(((struct sockaddr_in*)ss)->sin_family == AF_INET) {
|
||||
ecs->subnet_source_mask = cfg->max_client_subnet_ipv4;
|
||||
ecs->subnet_addr_fam = EDNSSUBNET_ADDRFAM_IP4;
|
||||
sinaddr = &((struct sockaddr_in*)ss)->sin_addr;
|
||||
if (!copy_clear( ecs->subnet_addr, INET6_SIZE,
|
||||
(uint8_t *)sinaddr, INET_SIZE,
|
||||
ecs->subnet_source_mask)) {
|
||||
ecs->subnet_validdata = 1;
|
||||
}
|
||||
}
|
||||
#ifdef INET6
|
||||
else {
|
||||
ecs->subnet_source_mask = cfg->max_client_subnet_ipv6;
|
||||
ecs->subnet_addr_fam = EDNSSUBNET_ADDRFAM_IP6;
|
||||
sinaddr = &((struct sockaddr_in6*)ss)->sin6_addr;
|
||||
if (!copy_clear( ecs->subnet_addr, INET6_SIZE,
|
||||
(uint8_t *)sinaddr, INET6_SIZE,
|
||||
ecs->subnet_source_mask)) {
|
||||
ecs->subnet_validdata = 1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* We don't know how to handle ip6, just pass */
|
||||
#endif /* INET6 */
|
||||
}
|
||||
|
||||
int
|
||||
ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
|
||||
int id, void* ATTR_UNUSED(cbargs))
|
||||
{
|
||||
struct subnet_qstate *sq;
|
||||
|
||||
if(!response || !(sq=(struct subnet_qstate*)qstate->minfo[id]))
|
||||
return 1;
|
||||
|
||||
if(sq->subnet_sent &&
|
||||
FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_REFUSED) {
|
||||
/* REFUSED response to ECS query, remove ECS option. */
|
||||
edns_opt_list_remove(&qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode);
|
||||
sq->subnet_sent = 0;
|
||||
memset(&sq->ecs_server_out, 0, sizeof(sq->ecs_server_out));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ecs_edns_back_parsed(struct module_qstate* qstate, int id,
|
||||
void* ATTR_UNUSED(cbargs))
|
||||
{
|
||||
struct subnet_qstate *sq;
|
||||
struct edns_option* ecs_opt;
|
||||
|
||||
if(!(sq=(struct subnet_qstate*)qstate->minfo[id]))
|
||||
return 1;
|
||||
if((ecs_opt = edns_opt_list_find(
|
||||
qstate->edns_opts_back_in,
|
||||
qstate->env->cfg->client_subnet_opcode))) {
|
||||
if(parse_subnet_option(ecs_opt, &sq->ecs_server_in) &&
|
||||
sq->subnet_sent &&
|
||||
sq->ecs_server_in.subnet_validdata)
|
||||
/* Only skip global cache store if we sent an ECS option
|
||||
* and received one back. Answers from non-whitelisted
|
||||
* servers will end up in global cache. Answers for
|
||||
* queries with 0 source will not (unless nameserver
|
||||
* does not support ECS). */
|
||||
qstate->no_cache_store = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
int id, struct outbound_entry* outbound)
|
||||
{
|
||||
struct subnet_env *sne = qstate->env->modinfo[id];
|
||||
struct subnet_qstate *sq = (struct subnet_qstate*)qstate->minfo[id];
|
||||
|
||||
verbose(VERB_QUERY, "subnet[module %d] operate: extstate:%s "
|
||||
"event:%s", id, strextstate(qstate->ext_state[id]),
|
||||
strmodulevent(event));
|
||||
log_query_info(VERB_QUERY, "subnet operate: query", &qstate->qinfo);
|
||||
|
||||
if((event == module_event_new || event == module_event_pass) &&
|
||||
sq == NULL) {
|
||||
struct edns_option* ecs_opt;
|
||||
if(!subnet_new_qstate(qstate, id)) {
|
||||
qstate->return_msg = NULL;
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
|
||||
sq = (struct subnet_qstate*)qstate->minfo[id];
|
||||
|
||||
if((ecs_opt = edns_opt_list_find(
|
||||
qstate->edns_opts_front_in,
|
||||
qstate->env->cfg->client_subnet_opcode))) {
|
||||
if(!parse_subnet_option(ecs_opt, &sq->ecs_client_in)) {
|
||||
/* Wrongly formatted ECS option. RFC mandates to
|
||||
* return FORMERROR. */
|
||||
qstate->return_rcode = LDNS_RCODE_FORMERR;
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
sq->subnet_downstream = 1;
|
||||
}
|
||||
else if(qstate->mesh_info->reply_list) {
|
||||
subnet_option_from_ss(
|
||||
&qstate->mesh_info->reply_list->query_reply.addr,
|
||||
&sq->ecs_client_in, qstate->env->cfg);
|
||||
}
|
||||
|
||||
if(sq->ecs_client_in.subnet_validdata == 0) {
|
||||
/* No clients are interested in result or we could not
|
||||
* parse it, we don't do client subnet */
|
||||
sq->ecs_server_out.subnet_validdata = 0;
|
||||
verbose(VERB_ALGO, "subnet: pass to next module");
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Limit to minimum allowed source mask */
|
||||
if(sq->ecs_client_in.subnet_source_mask != 0 && (
|
||||
(sq->ecs_client_in.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 &&
|
||||
sq->ecs_client_in.subnet_source_mask < qstate->env->cfg->min_client_subnet_ipv4) ||
|
||||
(sq->ecs_client_in.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6 &&
|
||||
sq->ecs_client_in.subnet_source_mask < qstate->env->cfg->min_client_subnet_ipv6))) {
|
||||
qstate->return_rcode = LDNS_RCODE_REFUSED;
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
if (lookup_and_reply(qstate, id, sq)) {
|
||||
sne->num_msg_cache++;
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
verbose(VERB_QUERY, "subnet: answered from cache");
|
||||
qstate->ext_state[id] = module_finished;
|
||||
|
||||
ecs_opt_list_append(&sq->ecs_client_out,
|
||||
&qstate->edns_opts_front_out, qstate);
|
||||
return;
|
||||
}
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
|
||||
sq->ecs_server_out.subnet_addr_fam =
|
||||
sq->ecs_client_in.subnet_addr_fam;
|
||||
sq->ecs_server_out.subnet_source_mask =
|
||||
sq->ecs_client_in.subnet_source_mask;
|
||||
/* Limit source prefix to configured maximum */
|
||||
if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4
|
||||
&& sq->ecs_server_out.subnet_source_mask >
|
||||
qstate->env->cfg->max_client_subnet_ipv4)
|
||||
sq->ecs_server_out.subnet_source_mask =
|
||||
qstate->env->cfg->max_client_subnet_ipv4;
|
||||
else if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6
|
||||
&& sq->ecs_server_out.subnet_source_mask >
|
||||
qstate->env->cfg->max_client_subnet_ipv6)
|
||||
sq->ecs_server_out.subnet_source_mask =
|
||||
qstate->env->cfg->max_client_subnet_ipv6;
|
||||
/* Safe to copy completely, even if the source is limited by the
|
||||
* configuration. ecs_opt_list_append() will limit the address.
|
||||
* */
|
||||
memcpy(&sq->ecs_server_out.subnet_addr,
|
||||
sq->ecs_client_in.subnet_addr, INET6_SIZE);
|
||||
sq->ecs_server_out.subnet_scope_mask = 0;
|
||||
sq->ecs_server_out.subnet_validdata = 1;
|
||||
if(sq->ecs_server_out.subnet_source_mask != 0 &&
|
||||
qstate->env->cfg->client_subnet_always_forward &&
|
||||
sq->subnet_downstream)
|
||||
/* ECS specific data required, do not look at the global
|
||||
* cache in other modules. */
|
||||
qstate->no_cache_lookup = 1;
|
||||
|
||||
/* pass request to next module */
|
||||
verbose(VERB_ALGO,
|
||||
"subnet: not found in cache. pass to next module");
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
/* Query handed back by next module, we have a 'final' answer */
|
||||
if(sq && event == module_event_moddone) {
|
||||
qstate->ext_state[id] = eval_response(qstate, id, sq);
|
||||
if(qstate->ext_state[id] == module_finished &&
|
||||
qstate->return_msg) {
|
||||
ecs_opt_list_append(&sq->ecs_client_out,
|
||||
&qstate->edns_opts_front_out, qstate);
|
||||
}
|
||||
qstate->no_cache_store = sq->started_no_cache_store;
|
||||
return;
|
||||
}
|
||||
if(sq && outbound) {
|
||||
return;
|
||||
}
|
||||
/* We are being revisited */
|
||||
if(event == module_event_pass || event == module_event_new) {
|
||||
/* Just pass it on, we already did the work */
|
||||
verbose(VERB_ALGO, "subnet: pass to next module");
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
if(!sq && (event == module_event_moddone)) {
|
||||
/* during priming, module done but we never started */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
log_err("subnet: bad event %s", strmodulevent(event));
|
||||
qstate->ext_state[id] = module_error;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
subnetmod_clear(struct module_qstate *ATTR_UNUSED(qstate),
|
||||
int ATTR_UNUSED(id))
|
||||
{
|
||||
/* qstate has no data outside region */
|
||||
}
|
||||
|
||||
void
|
||||
subnetmod_inform_super(struct module_qstate *ATTR_UNUSED(qstate),
|
||||
int ATTR_UNUSED(id), struct module_qstate *ATTR_UNUSED(super))
|
||||
{
|
||||
/* Not used */
|
||||
}
|
||||
|
||||
size_t
|
||||
subnetmod_get_mem(struct module_env *env, int id)
|
||||
{
|
||||
struct subnet_env *sn_env = env->modinfo[id];
|
||||
if (!sn_env) return 0;
|
||||
return sizeof(*sn_env) +
|
||||
slabhash_get_mem(sn_env->subnet_msg_cache) +
|
||||
ecs_whitelist_get_mem(sn_env->whitelist);
|
||||
}
|
||||
|
||||
/**
|
||||
* The module function block
|
||||
*/
|
||||
static struct module_func_block subnetmod_block = {
|
||||
"subnet", &subnetmod_init, &subnetmod_deinit, &subnetmod_operate,
|
||||
&subnetmod_inform_super, &subnetmod_clear, &subnetmod_get_mem
|
||||
};
|
||||
|
||||
struct module_func_block*
|
||||
subnetmod_get_funcblock(void)
|
||||
{
|
||||
return &subnetmod_block;
|
||||
}
|
||||
|
||||
/** Wrappers for static functions to unit test */
|
||||
size_t
|
||||
unittest_wrapper_subnetmod_sizefunc(void *elemptr)
|
||||
{
|
||||
return sizefunc(elemptr);
|
||||
}
|
||||
|
||||
#endif /* CLIENT_SUBNET */
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* edns-subnet/subnetmod.h - edns subnet module. Must be called before validator
|
||||
* and iterator.
|
||||
*
|
||||
* Copyright (c) 2013, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* subnet module for unbound.
|
||||
*/
|
||||
|
||||
#ifndef SUBNETMOD_H
|
||||
#define SUBNETMOD_H
|
||||
#include "util/module.h"
|
||||
#include "services/outbound_list.h"
|
||||
#include "util/alloc.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "edns-subnet/addrtree.h"
|
||||
#include "edns-subnet/edns-subnet.h"
|
||||
|
||||
/**
|
||||
* Global state for the subnet module.
|
||||
*/
|
||||
struct subnet_env {
|
||||
/** shared message cache
|
||||
* key: struct query_info*
|
||||
* data: struct subnet_msg_cache_data* */
|
||||
struct slabhash* subnet_msg_cache;
|
||||
/** access control, which upstream servers we send client address */
|
||||
struct ecs_whitelist* whitelist;
|
||||
/** allocation service */
|
||||
struct alloc_cache alloc;
|
||||
lock_rw_type biglock;
|
||||
/** number of messages from cache */
|
||||
size_t num_msg_cache;
|
||||
/** number of messages not from cache */
|
||||
size_t num_msg_nocache;
|
||||
};
|
||||
|
||||
struct subnet_msg_cache_data {
|
||||
struct addrtree* tree4;
|
||||
struct addrtree* tree6;
|
||||
};
|
||||
|
||||
struct subnet_qstate {
|
||||
/** We need the hash for both cache lookup and insert */
|
||||
hashvalue_type qinfo_hash;
|
||||
/** ecs_data for client communication */
|
||||
struct ecs_data ecs_client_in;
|
||||
struct ecs_data ecs_client_out;
|
||||
/** ecss data for server communication */
|
||||
struct ecs_data ecs_server_in;
|
||||
struct ecs_data ecs_server_out;
|
||||
int subnet_downstream;
|
||||
int subnet_sent;
|
||||
/** has the subnet module been started with no_cache_store? */
|
||||
int started_no_cache_store;
|
||||
};
|
||||
|
||||
void subnet_data_delete(void* d, void* ATTR_UNUSED(arg));
|
||||
size_t msg_cache_sizefunc(void* k, void* d);
|
||||
|
||||
/**
|
||||
* Get the module function block.
|
||||
* @return: function block with function pointers to module methods.
|
||||
*/
|
||||
struct module_func_block* subnetmod_get_funcblock(void);
|
||||
|
||||
/** subnet module init */
|
||||
int subnetmod_init(struct module_env* env, int id);
|
||||
|
||||
/** subnet module deinit */
|
||||
void subnetmod_deinit(struct module_env* env, int id);
|
||||
|
||||
/** subnet module operate on a query */
|
||||
void subnetmod_operate(struct module_qstate* qstate, enum module_ev event,
|
||||
int id, struct outbound_entry* outbound);
|
||||
|
||||
/** subnet module */
|
||||
void subnetmod_inform_super(struct module_qstate* qstate, int id,
|
||||
struct module_qstate* super);
|
||||
|
||||
/** subnet module cleanup query state */
|
||||
void subnetmod_clear(struct module_qstate* qstate, int id);
|
||||
|
||||
/** subnet module alloc size routine */
|
||||
size_t subnetmod_get_mem(struct module_env* env, int id);
|
||||
|
||||
/** Wrappers for static functions to unit test */
|
||||
size_t unittest_wrapper_subnetmod_sizefunc(void *elemptr);
|
||||
|
||||
/** Whitelist check, called just before query is sent upstream. */
|
||||
int ecs_whitelist_check(struct query_info* qinfo, uint16_t flags,
|
||||
struct module_qstate* qstate, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* zone, size_t zonelen,
|
||||
struct regional* region, int id, void* cbargs);
|
||||
|
||||
/** Check whether response from server contains ECS record, if so, skip cache
|
||||
* store. Called just after parsing EDNS data from server. */
|
||||
int ecs_edns_back_parsed(struct module_qstate* qstate, int id, void* cbargs);
|
||||
|
||||
/** Remove ECS record from back_out when query resulted in REFUSED response. */
|
||||
int ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
|
||||
int id, void* cbargs);
|
||||
|
||||
/** mark subnet msg to be deleted */
|
||||
void subnet_markdel(void* key);
|
||||
|
||||
#endif /* SUBNETMOD_H */
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
#!/usr/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2013-12-25.23; # UTC
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* ipsecmod/ipsecmod-whitelist.h - White listed domains for the ipsecmod to
|
||||
* operate on.
|
||||
*
|
||||
* Copyright (c) 2017, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Keep track of the white listed domains for ipsecmod.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef USE_IPSECMOD
|
||||
#include "ipsecmod/ipsecmod.h"
|
||||
#include "ipsecmod/ipsecmod-whitelist.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/rbtree.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/storage/dnstree.h"
|
||||
#include "sldns/str2wire.h"
|
||||
|
||||
/** Apply ipsecmod-whitelist string. */
|
||||
static int
|
||||
whitelist_str_cfg(rbtree_type* whitelist, const char* name)
|
||||
{
|
||||
struct name_tree_node* n;
|
||||
size_t len;
|
||||
uint8_t* nm = sldns_str2wire_dname(name, &len);
|
||||
if(!nm) {
|
||||
log_err("ipsecmod: could not parse %s for whitelist.", name);
|
||||
return 0;
|
||||
}
|
||||
n = (struct name_tree_node*)calloc(1, sizeof(*n));
|
||||
if(!n) {
|
||||
log_err("ipsecmod: out of memory while creating whitelist.");
|
||||
free(nm);
|
||||
return 0;
|
||||
}
|
||||
n->node.key = n;
|
||||
n->name = nm;
|
||||
n->len = len;
|
||||
n->labs = dname_count_labels(nm);
|
||||
n->dclass = LDNS_RR_CLASS_IN;
|
||||
if(!name_tree_insert(whitelist, n, nm, len, n->labs, n->dclass)) {
|
||||
/* duplicate element ignored, idempotent */
|
||||
free(n->name);
|
||||
free(n);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Read ipsecmod-whitelist config. */
|
||||
static int
|
||||
read_whitelist(rbtree_type* whitelist, struct config_file* cfg)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
for(p = cfg->ipsecmod_whitelist; p; p = p->next) {
|
||||
log_assert(p->str);
|
||||
if(!whitelist_str_cfg(whitelist, p->str))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ipsecmod_whitelist_apply_cfg(struct ipsecmod_env* ie,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
ie->whitelist = rbtree_create(name_tree_compare);
|
||||
if(!read_whitelist(ie->whitelist, cfg))
|
||||
return 0;
|
||||
name_tree_init_parents(ie->whitelist);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Delete ipsecmod_env->whitelist element. */
|
||||
static void
|
||||
whitelist_free(struct rbnode_type* n, void* ATTR_UNUSED(d))
|
||||
{
|
||||
if(n) {
|
||||
free(((struct name_tree_node*)n)->name);
|
||||
free(n);
|
||||
}
|
||||
}
|
||||
|
||||
/** Get memory usage of ipsecmod_env->whitelist element. */
|
||||
static void
|
||||
whitelist_get_mem(struct rbnode_type* n, void* arg)
|
||||
{
|
||||
struct name_tree_node* node = (struct name_tree_node*)n;
|
||||
size_t* size = (size_t*) arg;
|
||||
if(node) {
|
||||
*size += sizeof(node) + node->len;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ipsecmod_whitelist_delete(rbtree_type* whitelist)
|
||||
{
|
||||
if(whitelist) {
|
||||
traverse_postorder(whitelist, whitelist_free, NULL);
|
||||
free(whitelist);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ipsecmod_domain_is_whitelisted(struct ipsecmod_env* ie, uint8_t* dname,
|
||||
size_t dname_len, uint16_t qclass)
|
||||
{
|
||||
if(!ie->whitelist) return 1; /* No whitelist, treat as whitelisted. */
|
||||
return name_tree_lookup(ie->whitelist, dname, dname_len,
|
||||
dname_count_labels(dname), qclass) != NULL;
|
||||
}
|
||||
|
||||
size_t
|
||||
ipsecmod_whitelist_get_mem(rbtree_type* whitelist)
|
||||
{
|
||||
size_t size = 0;
|
||||
if(whitelist) {
|
||||
traverse_postorder(whitelist, whitelist_get_mem, &size);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
#endif /* USE_IPSECMOD */
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* ipsecmod/ipsecmod-whitelist.h - White listed domains for the ipsecmod to
|
||||
* operate on.
|
||||
*
|
||||
* Copyright (c) 2017, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Keep track of the white listed domains for ipsecmod.
|
||||
*/
|
||||
|
||||
#ifndef IPSECMOD_WHITELIST_H
|
||||
#define IPSECMOD_WHITELIST_H
|
||||
#include "util/storage/dnstree.h"
|
||||
|
||||
struct config_file;
|
||||
struct regional;
|
||||
|
||||
/**
|
||||
* Process ipsecmod_whitelist config.
|
||||
* @param ie: ipsecmod environment.
|
||||
* @param cfg: config options.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
int ipsecmod_whitelist_apply_cfg(struct ipsecmod_env* ie,
|
||||
struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Delete the ipsecmod whitelist.
|
||||
* @param whitelist: ipsecmod whitelist.
|
||||
*/
|
||||
void ipsecmod_whitelist_delete(rbtree_type* whitelist);
|
||||
|
||||
/**
|
||||
* See if a domain is whitelisted.
|
||||
* @param ie: ipsecmod environment.
|
||||
* @param dname: domain name to check.
|
||||
* @param dname_len: length of domain name.
|
||||
* @param qclass: query CLASS.
|
||||
* @return: true if the domain is whitelisted for the ipsecmod.
|
||||
*/
|
||||
int ipsecmod_domain_is_whitelisted(struct ipsecmod_env* ie, uint8_t* dname,
|
||||
size_t dname_len, uint16_t qclass);
|
||||
|
||||
/**
|
||||
* Get memory used by ipsecmod whitelist.
|
||||
* @param whitelist: structure for domain storage.
|
||||
* @return bytes in use.
|
||||
*/
|
||||
size_t ipsecmod_whitelist_get_mem(rbtree_type* whitelist);
|
||||
|
||||
#endif /* IPSECMOD_WHITELIST_H */
|
||||
@@ -0,0 +1,610 @@
|
||||
/*
|
||||
* ipsecmod/ipsecmod.c - facilitate opportunistic IPsec module
|
||||
*
|
||||
* Copyright (c) 2017, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains a module that facilitates opportunistic IPsec. It does so
|
||||
* by also quering for the IPSECKEY for A/AAAA queries and calling a
|
||||
* configurable hook (eg. signaling an IKE daemon) before replying.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#ifdef USE_IPSECMOD
|
||||
#include "ipsecmod/ipsecmod.h"
|
||||
#include "ipsecmod/ipsecmod-whitelist.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/config_file.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "sldns/wire2str.h"
|
||||
|
||||
/** Apply configuration to ipsecmod module 'global' state. */
|
||||
static int
|
||||
ipsecmod_apply_cfg(struct ipsecmod_env* ipsecmod_env, struct config_file* cfg)
|
||||
{
|
||||
if(!cfg->ipsecmod_hook || (cfg->ipsecmod_hook && !cfg->ipsecmod_hook[0])) {
|
||||
log_err("ipsecmod: missing ipsecmod-hook.");
|
||||
return 0;
|
||||
}
|
||||
if(cfg->ipsecmod_whitelist &&
|
||||
!ipsecmod_whitelist_apply_cfg(ipsecmod_env, cfg))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ipsecmod_init(struct module_env* env, int id)
|
||||
{
|
||||
struct ipsecmod_env* ipsecmod_env = (struct ipsecmod_env*)calloc(1,
|
||||
sizeof(struct ipsecmod_env));
|
||||
if(!ipsecmod_env) {
|
||||
log_err("malloc failure");
|
||||
return 0;
|
||||
}
|
||||
env->modinfo[id] = (void*)ipsecmod_env;
|
||||
ipsecmod_env->whitelist = NULL;
|
||||
if(!ipsecmod_apply_cfg(ipsecmod_env, env->cfg)) {
|
||||
log_err("ipsecmod: could not apply configuration settings.");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
ipsecmod_deinit(struct module_env* env, int id)
|
||||
{
|
||||
struct ipsecmod_env* ipsecmod_env;
|
||||
if(!env || !env->modinfo[id])
|
||||
return;
|
||||
ipsecmod_env = (struct ipsecmod_env*)env->modinfo[id];
|
||||
/* Free contents. */
|
||||
ipsecmod_whitelist_delete(ipsecmod_env->whitelist);
|
||||
free(ipsecmod_env);
|
||||
env->modinfo[id] = NULL;
|
||||
}
|
||||
|
||||
/** New query for ipsecmod. */
|
||||
static int
|
||||
ipsecmod_new(struct module_qstate* qstate, int id)
|
||||
{
|
||||
struct ipsecmod_qstate* iq = (struct ipsecmod_qstate*)regional_alloc(
|
||||
qstate->region, sizeof(struct ipsecmod_qstate));
|
||||
qstate->minfo[id] = iq;
|
||||
if(!iq)
|
||||
return 0;
|
||||
/* Initialise it. */
|
||||
memset(iq, 0, sizeof(*iq));
|
||||
iq->enabled = qstate->env->cfg->ipsecmod_enabled;
|
||||
iq->is_whitelisted = ipsecmod_domain_is_whitelisted(
|
||||
(struct ipsecmod_env*)qstate->env->modinfo[id], qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len, qstate->qinfo.qclass);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit module with an error status.
|
||||
* @param qstate: query state
|
||||
* @param id: module id.
|
||||
*/
|
||||
static void
|
||||
ipsecmod_error(struct module_qstate* qstate, int id)
|
||||
{
|
||||
qstate->ext_state[id] = module_error;
|
||||
qstate->return_rcode = LDNS_RCODE_SERVFAIL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a request for the IPSECKEY.
|
||||
*
|
||||
* @param qstate: query state that is the parent.
|
||||
* @param id: module id.
|
||||
* @param name: what name to query for.
|
||||
* @param namelen: length of name.
|
||||
* @param qtype: query type.
|
||||
* @param qclass: query class.
|
||||
* @param flags: additional flags, such as the CD bit (BIT_CD), or 0.
|
||||
* @return false on alloc failure.
|
||||
*/
|
||||
static int
|
||||
generate_request(struct module_qstate* qstate, int id, uint8_t* name,
|
||||
size_t namelen, uint16_t qtype, uint16_t qclass, uint16_t flags)
|
||||
{
|
||||
struct module_qstate* newq;
|
||||
struct query_info ask;
|
||||
ask.qname = name;
|
||||
ask.qname_len = namelen;
|
||||
ask.qtype = qtype;
|
||||
ask.qclass = qclass;
|
||||
ask.local_alias = NULL;
|
||||
log_query_info(VERB_ALGO, "ipsecmod: generate request", &ask);
|
||||
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
|
||||
if(!(*qstate->env->attach_sub)(qstate, &ask,
|
||||
(uint16_t)(BIT_RD|flags), 0, 0, &newq)){
|
||||
log_err("Could not generate request: out of memory");
|
||||
return 0;
|
||||
}
|
||||
qstate->ext_state[id] = module_wait_subquery;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the string passed is a valid domain name with safe characters to
|
||||
* pass to a shell.
|
||||
* This will only allow:
|
||||
* - digits
|
||||
* - alphas
|
||||
* - hyphen (not at the start)
|
||||
* - dot (not at the start, or the only character)
|
||||
* - underscore
|
||||
* @param s: pointer to the string.
|
||||
* @param slen: string's length.
|
||||
* @return true if s only contains safe characters; false otherwise.
|
||||
*/
|
||||
static int
|
||||
domainname_has_safe_characters(char* s, size_t slen) {
|
||||
size_t i;
|
||||
for(i = 0; i < slen; i++) {
|
||||
if(s[i] == '\0') return 1;
|
||||
if((s[i] == '-' && i != 0)
|
||||
|| (s[i] == '.' && (i != 0 || s[1] == '\0'))
|
||||
|| (s[i] == '_') || (s[i] >= '0' && s[i] <= '9')
|
||||
|| (s[i] >= 'A' && s[i] <= 'Z')
|
||||
|| (s[i] >= 'a' && s[i] <= 'z')) {
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the stringified IPSECKEY RDATA contains safe characters to pass to
|
||||
* a shell.
|
||||
* This is only relevant for checking the gateway when the gateway type is 3
|
||||
* (domainname).
|
||||
* @param s: pointer to the string.
|
||||
* @param slen: string's length.
|
||||
* @return true if s contains only safe characters; false otherwise.
|
||||
*/
|
||||
static int
|
||||
ipseckey_has_safe_characters(char* s, size_t slen) {
|
||||
int precedence, gateway_type, algorithm;
|
||||
char* gateway;
|
||||
gateway = (char*)calloc(slen, sizeof(char));
|
||||
if(!gateway) {
|
||||
log_err("ipsecmod: out of memory when calling the hook");
|
||||
return 0;
|
||||
}
|
||||
if(sscanf(s, "%d %d %d %s ",
|
||||
&precedence, &gateway_type, &algorithm, gateway) != 4) {
|
||||
free(gateway);
|
||||
return 0;
|
||||
}
|
||||
if(gateway_type != 3) {
|
||||
free(gateway);
|
||||
return 1;
|
||||
}
|
||||
if(domainname_has_safe_characters(gateway, slen)) {
|
||||
free(gateway);
|
||||
return 1;
|
||||
}
|
||||
free(gateway);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data and call the hook.
|
||||
*
|
||||
* @param qstate: query state.
|
||||
* @param iq: ipsecmod qstate.
|
||||
* @param ie: ipsecmod environment.
|
||||
* @return true on success, false otherwise.
|
||||
*/
|
||||
static int
|
||||
call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
|
||||
struct ipsecmod_env* ATTR_UNUSED(ie))
|
||||
{
|
||||
size_t slen, tempdata_len, tempstring_len, i;
|
||||
char str[65535], *s, *tempstring;
|
||||
int w = 0, w_temp, qtype;
|
||||
struct ub_packed_rrset_key* rrset_key;
|
||||
struct packed_rrset_data* rrset_data;
|
||||
uint8_t *tempdata;
|
||||
|
||||
/* Check if a shell is available */
|
||||
if(system(NULL) == 0) {
|
||||
log_err("ipsecmod: no shell available for ipsecmod-hook");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Zero the buffer. */
|
||||
s = str;
|
||||
slen = sizeof(str);
|
||||
memset(s, 0, slen);
|
||||
|
||||
/* Copy the hook into the buffer. */
|
||||
w += sldns_str_print(&s, &slen, "%s", qstate->env->cfg->ipsecmod_hook);
|
||||
/* Put space into the buffer. */
|
||||
w += sldns_str_print(&s, &slen, " ");
|
||||
/* Copy the qname into the buffer. */
|
||||
tempstring = sldns_wire2str_dname(qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len);
|
||||
if(!tempstring) {
|
||||
log_err("ipsecmod: out of memory when calling the hook");
|
||||
return 0;
|
||||
}
|
||||
if(!domainname_has_safe_characters(tempstring, strlen(tempstring))) {
|
||||
log_err("ipsecmod: qname has unsafe characters");
|
||||
free(tempstring);
|
||||
return 0;
|
||||
}
|
||||
w += sldns_str_print(&s, &slen, "\"%s\"", tempstring);
|
||||
free(tempstring);
|
||||
/* Put space into the buffer. */
|
||||
w += sldns_str_print(&s, &slen, " ");
|
||||
/* Copy the IPSECKEY TTL into the buffer. */
|
||||
rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data;
|
||||
w += sldns_str_print(&s, &slen, "\"%ld\"", (long)rrset_data->ttl);
|
||||
/* Put space into the buffer. */
|
||||
w += sldns_str_print(&s, &slen, " ");
|
||||
rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
/* Double check that the records are indeed A/AAAA.
|
||||
* This should never happen as this function is only executed for A/AAAA
|
||||
* queries but make sure we don't pass anything other than A/AAAA to the
|
||||
* shell. */
|
||||
qtype = ntohs(rrset_key->rk.type);
|
||||
if(qtype != LDNS_RR_TYPE_AAAA && qtype != LDNS_RR_TYPE_A) {
|
||||
log_err("ipsecmod: Answer is not of A or AAAA type");
|
||||
return 0;
|
||||
}
|
||||
rrset_data = (struct packed_rrset_data*)rrset_key->entry.data;
|
||||
/* Copy the A/AAAA record(s) into the buffer. Start and end this section
|
||||
* with a double quote. */
|
||||
w += sldns_str_print(&s, &slen, "\"");
|
||||
for(i=0; i<rrset_data->count; i++) {
|
||||
if(i > 0) {
|
||||
/* Put space into the buffer. */
|
||||
w += sldns_str_print(&s, &slen, " ");
|
||||
}
|
||||
/* Ignore the first two bytes, they are the rr_data len. */
|
||||
w_temp = sldns_wire2str_rdata_buf(rrset_data->rr_data[i] + 2,
|
||||
rrset_data->rr_len[i] - 2, s, slen, qstate->qinfo.qtype);
|
||||
if(w_temp < 0) {
|
||||
/* Error in printout. */
|
||||
log_err("ipsecmod: Error in printing IP address");
|
||||
return 0;
|
||||
} else if((size_t)w_temp >= slen) {
|
||||
s = NULL; /* We do not want str to point outside of buffer. */
|
||||
slen = 0;
|
||||
log_err("ipsecmod: shell command too long");
|
||||
return 0;
|
||||
} else {
|
||||
s += w_temp;
|
||||
slen -= w_temp;
|
||||
w += w_temp;
|
||||
}
|
||||
}
|
||||
w += sldns_str_print(&s, &slen, "\"");
|
||||
/* Put space into the buffer. */
|
||||
w += sldns_str_print(&s, &slen, " ");
|
||||
/* Copy the IPSECKEY record(s) into the buffer. Start and end this section
|
||||
* with a double quote. */
|
||||
w += sldns_str_print(&s, &slen, "\"");
|
||||
rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data;
|
||||
for(i=0; i<rrset_data->count; i++) {
|
||||
if(i > 0) {
|
||||
/* Put space into the buffer. */
|
||||
w += sldns_str_print(&s, &slen, " ");
|
||||
}
|
||||
/* Ignore the first two bytes, they are the rr_data len. */
|
||||
tempdata = rrset_data->rr_data[i] + 2;
|
||||
tempdata_len = rrset_data->rr_len[i] - 2;
|
||||
/* Save the buffer pointers. */
|
||||
tempstring = s; tempstring_len = slen;
|
||||
w_temp = sldns_wire2str_ipseckey_scan(&tempdata, &tempdata_len, &s,
|
||||
&slen, NULL, 0, NULL);
|
||||
/* There was an error when parsing the IPSECKEY; reset the buffer
|
||||
* pointers to their previous values. */
|
||||
if(w_temp == -1) {
|
||||
s = tempstring; slen = tempstring_len;
|
||||
} else if(w_temp > 0) {
|
||||
if(!ipseckey_has_safe_characters(
|
||||
tempstring, tempstring_len - slen)) {
|
||||
log_err("ipsecmod: ipseckey has unsafe characters");
|
||||
return 0;
|
||||
}
|
||||
w += w_temp;
|
||||
}
|
||||
}
|
||||
w += sldns_str_print(&s, &slen, "\"");
|
||||
if(w >= (int)sizeof(str)) {
|
||||
log_err("ipsecmod: shell command too long");
|
||||
return 0;
|
||||
}
|
||||
verbose(VERB_ALGO, "ipsecmod: shell command: '%s'", str);
|
||||
/* ipsecmod-hook should return 0 on success. */
|
||||
if(system(str) != 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an ipsecmod module event with a query
|
||||
* @param qstate: query state (from the mesh), passed between modules.
|
||||
* contains qstate->env module environment with global caches and so on.
|
||||
* @param iq: query state specific for this module. per-query.
|
||||
* @param ie: environment specific for this module. global.
|
||||
* @param id: module id.
|
||||
*/
|
||||
static void
|
||||
ipsecmod_handle_query(struct module_qstate* qstate,
|
||||
struct ipsecmod_qstate* iq, struct ipsecmod_env* ie, int id)
|
||||
{
|
||||
struct ub_packed_rrset_key* rrset_key;
|
||||
struct packed_rrset_data* rrset_data;
|
||||
size_t i;
|
||||
/* Pass to next module if we are not enabled and whitelisted. */
|
||||
if(!(iq->enabled && iq->is_whitelisted)) {
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
/* New query, check if the query is for an A/AAAA record and disable
|
||||
* caching for other modules. */
|
||||
if(!iq->ipseckey_done) {
|
||||
if(qstate->qinfo.qtype == LDNS_RR_TYPE_A ||
|
||||
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) {
|
||||
char type[16];
|
||||
sldns_wire2str_type_buf(qstate->qinfo.qtype, type,
|
||||
sizeof(type));
|
||||
verbose(VERB_ALGO, "ipsecmod: query for %s; engaging",
|
||||
type);
|
||||
qstate->no_cache_store = 1;
|
||||
}
|
||||
/* Pass request to next module. */
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
/* IPSECKEY subquery is finished. */
|
||||
/* We have an IPSECKEY answer. */
|
||||
if(iq->ipseckey_rrset) {
|
||||
rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data;
|
||||
if(rrset_data) {
|
||||
/* If bogus return SERVFAIL. */
|
||||
if(!qstate->env->cfg->ipsecmod_ignore_bogus &&
|
||||
rrset_data->security == sec_status_bogus) {
|
||||
log_err("ipsecmod: bogus IPSECKEY");
|
||||
ipsecmod_error(qstate, id);
|
||||
return;
|
||||
}
|
||||
/* We have a valid IPSECKEY reply, call hook. */
|
||||
if(!call_hook(qstate, iq, ie) &&
|
||||
qstate->env->cfg->ipsecmod_strict) {
|
||||
log_err("ipsecmod: ipsecmod-hook failed");
|
||||
ipsecmod_error(qstate, id);
|
||||
return;
|
||||
}
|
||||
/* Make sure the A/AAAA's TTL is equal/less than the
|
||||
* ipsecmod_max_ttl. */
|
||||
rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
rrset_data = (struct packed_rrset_data*)rrset_key->entry.data;
|
||||
if(rrset_data->ttl > (time_t)qstate->env->cfg->ipsecmod_max_ttl) {
|
||||
/* Update TTL for rrset to fixed value. */
|
||||
rrset_data->ttl = qstate->env->cfg->ipsecmod_max_ttl;
|
||||
for(i=0; i<rrset_data->count+rrset_data->rrsig_count; i++)
|
||||
rrset_data->rr_ttl[i] = qstate->env->cfg->ipsecmod_max_ttl;
|
||||
/* Also update reply_info's TTL */
|
||||
if(qstate->return_msg->rep->ttl > (time_t)qstate->env->cfg->ipsecmod_max_ttl) {
|
||||
qstate->return_msg->rep->ttl =
|
||||
qstate->env->cfg->ipsecmod_max_ttl;
|
||||
qstate->return_msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(
|
||||
qstate->return_msg->rep->ttl);
|
||||
qstate->return_msg->rep->serve_expired_ttl = qstate->return_msg->rep->ttl +
|
||||
qstate->env->cfg->serve_expired_ttl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Store A/AAAA in cache. */
|
||||
if(!dns_cache_store(qstate->env, &qstate->qinfo,
|
||||
qstate->return_msg->rep, 0, qstate->prefetch_leeway,
|
||||
0, qstate->region, qstate->query_flags)) {
|
||||
log_err("ipsecmod: out of memory caching record");
|
||||
}
|
||||
qstate->ext_state[id] = module_finished;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an ipsecmod module event with a response from the iterator.
|
||||
* @param qstate: query state (from the mesh), passed between modules.
|
||||
* contains qstate->env module environment with global caches and so on.
|
||||
* @param iq: query state specific for this module. per-query.
|
||||
* @param ie: environment specific for this module. global.
|
||||
* @param id: module id.
|
||||
*/
|
||||
static void
|
||||
ipsecmod_handle_response(struct module_qstate* qstate,
|
||||
struct ipsecmod_qstate* ATTR_UNUSED(iq),
|
||||
struct ipsecmod_env* ATTR_UNUSED(ie), int id)
|
||||
{
|
||||
/* Pass to previous module if we are not enabled and whitelisted. */
|
||||
if(!(iq->enabled && iq->is_whitelisted)) {
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
/* check if the response is for an A/AAAA query. */
|
||||
if((qstate->qinfo.qtype == LDNS_RR_TYPE_A ||
|
||||
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) &&
|
||||
/* check that we had an answer for the A/AAAA query. */
|
||||
qstate->return_msg &&
|
||||
reply_find_answer_rrset(&qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep) &&
|
||||
/* check that another module didn't SERVFAIL. */
|
||||
qstate->return_rcode == LDNS_RCODE_NOERROR) {
|
||||
char type[16];
|
||||
sldns_wire2str_type_buf(qstate->qinfo.qtype, type,
|
||||
sizeof(type));
|
||||
verbose(VERB_ALGO, "ipsecmod: response for %s; generating IPSECKEY "
|
||||
"subquery", type);
|
||||
/* generate an IPSECKEY query. */
|
||||
if(!generate_request(qstate, id, qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len, LDNS_RR_TYPE_IPSECKEY,
|
||||
qstate->qinfo.qclass, 0)) {
|
||||
log_err("ipsecmod: could not generate subquery.");
|
||||
ipsecmod_error(qstate, id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* we are done with the query. */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
}
|
||||
|
||||
void
|
||||
ipsecmod_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
struct outbound_entry* outbound)
|
||||
{
|
||||
struct ipsecmod_env* ie = (struct ipsecmod_env*)qstate->env->modinfo[id];
|
||||
struct ipsecmod_qstate* iq = (struct ipsecmod_qstate*)qstate->minfo[id];
|
||||
verbose(VERB_QUERY, "ipsecmod[module %d] operate: extstate:%s event:%s",
|
||||
id, strextstate(qstate->ext_state[id]), strmodulevent(event));
|
||||
if(iq) log_query_info(VERB_QUERY, "ipsecmod operate: query",
|
||||
&qstate->qinfo);
|
||||
|
||||
/* create ipsecmod_qstate. */
|
||||
if((event == module_event_new || event == module_event_pass) &&
|
||||
iq == NULL) {
|
||||
if(!ipsecmod_new(qstate, id)) {
|
||||
ipsecmod_error(qstate, id);
|
||||
return;
|
||||
}
|
||||
iq = (struct ipsecmod_qstate*)qstate->minfo[id];
|
||||
}
|
||||
if(iq && (event == module_event_pass || event == module_event_new)) {
|
||||
ipsecmod_handle_query(qstate, iq, ie, id);
|
||||
return;
|
||||
}
|
||||
if(iq && (event == module_event_moddone)) {
|
||||
ipsecmod_handle_response(qstate, iq, ie, id);
|
||||
return;
|
||||
}
|
||||
if(iq && outbound) {
|
||||
/* cachedb does not need to process responses at this time
|
||||
* ignore it.
|
||||
cachedb_process_response(qstate, iq, ie, id, outbound, event);
|
||||
*/
|
||||
return;
|
||||
}
|
||||
if(event == module_event_error) {
|
||||
verbose(VERB_ALGO, "got called with event error, giving up");
|
||||
ipsecmod_error(qstate, id);
|
||||
return;
|
||||
}
|
||||
if(!iq && (event == module_event_moddone)) {
|
||||
/* during priming, module done but we never started. */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
|
||||
log_err("ipsecmod: bad event %s", strmodulevent(event));
|
||||
ipsecmod_error(qstate, id);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
ipsecmod_inform_super(struct module_qstate* qstate, int id,
|
||||
struct module_qstate* super)
|
||||
{
|
||||
struct ipsecmod_qstate* siq;
|
||||
log_query_info(VERB_ALGO, "ipsecmod: inform_super, sub is",
|
||||
&qstate->qinfo);
|
||||
log_query_info(VERB_ALGO, "super is", &super->qinfo);
|
||||
siq = (struct ipsecmod_qstate*)super->minfo[id];
|
||||
if(!siq) {
|
||||
verbose(VERB_ALGO, "super has no ipsecmod state");
|
||||
return;
|
||||
}
|
||||
|
||||
if(qstate->return_msg) {
|
||||
struct ub_packed_rrset_key* rrset_key = reply_find_answer_rrset(
|
||||
&qstate->return_msg->qinfo, qstate->return_msg->rep);
|
||||
if(rrset_key) {
|
||||
/* We have an answer. */
|
||||
/* Copy to super's region. */
|
||||
rrset_key = packed_rrset_copy_region(rrset_key, super->region, 0);
|
||||
siq->ipseckey_rrset = rrset_key;
|
||||
if(!rrset_key) {
|
||||
log_err("ipsecmod: out of memory.");
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Notify super to proceed. */
|
||||
siq->ipseckey_done = 1;
|
||||
}
|
||||
|
||||
void
|
||||
ipsecmod_clear(struct module_qstate* qstate, int id)
|
||||
{
|
||||
if(!qstate)
|
||||
return;
|
||||
qstate->minfo[id] = NULL;
|
||||
}
|
||||
|
||||
size_t
|
||||
ipsecmod_get_mem(struct module_env* env, int id)
|
||||
{
|
||||
struct ipsecmod_env* ie = (struct ipsecmod_env*)env->modinfo[id];
|
||||
if(!ie)
|
||||
return 0;
|
||||
return sizeof(*ie) + ipsecmod_whitelist_get_mem(ie->whitelist);
|
||||
}
|
||||
|
||||
/**
|
||||
* The ipsecmod function block
|
||||
*/
|
||||
static struct module_func_block ipsecmod_block = {
|
||||
"ipsecmod",
|
||||
&ipsecmod_init, &ipsecmod_deinit, &ipsecmod_operate,
|
||||
&ipsecmod_inform_super, &ipsecmod_clear, &ipsecmod_get_mem
|
||||
};
|
||||
|
||||
struct module_func_block*
|
||||
ipsecmod_get_funcblock(void)
|
||||
{
|
||||
return &ipsecmod_block;
|
||||
}
|
||||
#endif /* USE_IPSECMOD */
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* ipsecmod/ipsecmod.h - facilitate opportunistic IPsec module
|
||||
*
|
||||
* Copyright (c) 2017, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains a module that facilitates opportunistic IPsec. It does so
|
||||
* by also quering for the IPSECKEY for A/AAAA queries and calling a
|
||||
* configurable hook (eg. signaling an IKE daemon) before replying.
|
||||
*/
|
||||
|
||||
#ifndef IPSECMOD_H
|
||||
#define IPSECMOD_H
|
||||
#include "util/module.h"
|
||||
#include "util/rbtree.h"
|
||||
|
||||
/**
|
||||
* The global variable environment contents for the ipsecmod
|
||||
* Shared between threads, this represents long term information.
|
||||
*/
|
||||
struct ipsecmod_env {
|
||||
/** White listed domains for ipsecmod. */
|
||||
rbtree_type* whitelist;
|
||||
};
|
||||
|
||||
/**
|
||||
* Per query state for the ipsecmod module.
|
||||
*/
|
||||
struct ipsecmod_qstate {
|
||||
/** State of the IPsec module. */
|
||||
/** NOTE: This value is copied here from the configuration so that a change
|
||||
* with unbound-control would not complicate an already running mesh. */
|
||||
int enabled;
|
||||
/** If the qname is whitelisted or not. */
|
||||
/** NOTE: No whitelist means all qnames are whitelisted. */
|
||||
int is_whitelisted;
|
||||
/** Pointer to IPSECKEY rrset allocated in the qstate region. NULL if there
|
||||
* was no IPSECKEY reply from the subquery. */
|
||||
struct ub_packed_rrset_key* ipseckey_rrset;
|
||||
/** If the IPSECKEY subquery has finished. */
|
||||
int ipseckey_done;
|
||||
};
|
||||
|
||||
/** Init the ipsecmod module */
|
||||
int ipsecmod_init(struct module_env* env, int id);
|
||||
/** Deinit the ipsecmod module */
|
||||
void ipsecmod_deinit(struct module_env* env, int id);
|
||||
/** Operate on an event on a query (in qstate). */
|
||||
void ipsecmod_operate(struct module_qstate* qstate, enum module_ev event,
|
||||
int id, struct outbound_entry* outbound);
|
||||
/** Subordinate query done, inform this super request of its conclusion */
|
||||
void ipsecmod_inform_super(struct module_qstate* qstate, int id,
|
||||
struct module_qstate* super);
|
||||
/** clear the ipsecmod query-specific contents out of qstate */
|
||||
void ipsecmod_clear(struct module_qstate* qstate, int id);
|
||||
/** return memory estimate for the ipsecmod module */
|
||||
size_t ipsecmod_get_mem(struct module_env* env, int id);
|
||||
|
||||
/**
|
||||
* Get the function block with pointers to the ipsecmod functions
|
||||
* @return the function block for "ipsecmod".
|
||||
*/
|
||||
struct module_func_block* ipsecmod_get_funcblock(void);
|
||||
|
||||
#endif /* IPSECMOD_H */
|
||||
Executable
+383
@@ -0,0 +1,383 @@
|
||||
/**
|
||||
* \file
|
||||
* This file implements the ipset module. It can handle packets by putting
|
||||
* the A and AAAA addresses that are configured in unbound.conf as type
|
||||
* ipset (local-zone statements) into a firewall rule IPSet. For firewall
|
||||
* blacklist and whitelist usage.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ipset/ipset.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/config_file.h"
|
||||
|
||||
#include "services/cache/dns.h"
|
||||
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#include "sldns/parseutil.h"
|
||||
|
||||
#include <libmnl/libmnl.h>
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/netfilter/ipset/ip_set.h>
|
||||
|
||||
#define BUFF_LEN 256
|
||||
|
||||
/**
|
||||
* Return an error
|
||||
* @param qstate: our query state
|
||||
* @param id: module id
|
||||
* @param rcode: error code (DNS errcode).
|
||||
* @return: 0 for use by caller, to make notation easy, like:
|
||||
* return error_response(..).
|
||||
*/
|
||||
static int error_response(struct module_qstate* qstate, int id, int rcode) {
|
||||
verbose(VERB_QUERY, "return error response %s",
|
||||
sldns_lookup_by_id(sldns_rcodes, rcode)?
|
||||
sldns_lookup_by_id(sldns_rcodes, rcode)->name:"??");
|
||||
qstate->return_rcode = rcode;
|
||||
qstate->return_msg = NULL;
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mnl_socket * open_mnl_socket() {
|
||||
struct mnl_socket *mnl;
|
||||
|
||||
mnl = mnl_socket_open(NETLINK_NETFILTER);
|
||||
if (!mnl) {
|
||||
log_err("ipset: could not open netfilter.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(mnl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||
mnl_socket_close(mnl);
|
||||
log_err("ipset: could not bind netfilter.");
|
||||
return NULL;
|
||||
}
|
||||
return mnl;
|
||||
}
|
||||
|
||||
static int add_to_ipset(struct mnl_socket *mnl, const char *setname, const void *ipaddr, int af) {
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfg;
|
||||
struct nlattr *nested[2];
|
||||
static char buffer[BUFF_LEN];
|
||||
|
||||
if (strlen(setname) >= IPSET_MAXNAMELEN) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
if (af != AF_INET && af != AF_INET6) {
|
||||
errno = EAFNOSUPPORT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
nlh = mnl_nlmsg_put_header(buffer);
|
||||
nlh->nlmsg_type = IPSET_CMD_ADD | (NFNL_SUBSYS_IPSET << 8);
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL;
|
||||
|
||||
nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
|
||||
nfg->nfgen_family = af;
|
||||
nfg->version = NFNETLINK_V0;
|
||||
nfg->res_id = htons(0);
|
||||
|
||||
mnl_attr_put_u8(nlh, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
|
||||
mnl_attr_put(nlh, IPSET_ATTR_SETNAME, strlen(setname) + 1, setname);
|
||||
nested[0] = mnl_attr_nest_start(nlh, IPSET_ATTR_DATA);
|
||||
nested[1] = mnl_attr_nest_start(nlh, IPSET_ATTR_IP);
|
||||
mnl_attr_put(nlh, (af == AF_INET ? IPSET_ATTR_IPADDR_IPV4 : IPSET_ATTR_IPADDR_IPV6)
|
||||
| NLA_F_NET_BYTEORDER, (af == AF_INET ? sizeof(struct in_addr) : sizeof(struct in6_addr)), ipaddr);
|
||||
mnl_attr_nest_end(nlh, nested[1]);
|
||||
mnl_attr_nest_end(nlh, nested[0]);
|
||||
|
||||
if (mnl_socket_sendto(mnl, nlh, nlh->nlmsg_len) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl,
|
||||
struct packed_rrset_data *d, const char* setname, int af,
|
||||
const char* dname)
|
||||
{
|
||||
int ret;
|
||||
size_t j, rr_len, rd_len;
|
||||
uint8_t *rr_data;
|
||||
|
||||
/* to d->count, not d->rrsig_count, because we do not want to add the RRSIGs, only the addresses */
|
||||
for (j = 0; j < d->count; j++) {
|
||||
rr_len = d->rr_len[j];
|
||||
rr_data = d->rr_data[j];
|
||||
|
||||
rd_len = sldns_read_uint16(rr_data);
|
||||
if(af == AF_INET && rd_len != INET_SIZE)
|
||||
continue;
|
||||
if(af == AF_INET6 && rd_len != INET6_SIZE)
|
||||
continue;
|
||||
if (rr_len - 2 >= rd_len) {
|
||||
if(verbosity >= VERB_QUERY) {
|
||||
char ip[128];
|
||||
if(inet_ntop(af, rr_data+2, ip, (socklen_t)sizeof(ip)) == 0)
|
||||
snprintf(ip, sizeof(ip), "(inet_ntop_error)");
|
||||
verbose(VERB_QUERY, "ipset: add %s to %s for %s", ip, setname, dname);
|
||||
}
|
||||
ret = add_to_ipset(mnl, setname, rr_data + 2, af);
|
||||
if (ret < 0) {
|
||||
log_err("ipset: could not add %s into %s", dname, setname);
|
||||
|
||||
mnl_socket_close(mnl);
|
||||
ie->mnl = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
|
||||
struct mnl_socket *mnl, struct ub_packed_rrset_key *rrset,
|
||||
const char *setname, int af)
|
||||
{
|
||||
static char dname[BUFF_LEN];
|
||||
const char *s;
|
||||
int dlen, plen;
|
||||
|
||||
struct config_strlist *p;
|
||||
struct packed_rrset_data *d;
|
||||
|
||||
dlen = sldns_wire2str_dname_buf(rrset->rk.dname, rrset->rk.dname_len, dname, BUFF_LEN);
|
||||
if (dlen == 0) {
|
||||
log_err("bad domain name");
|
||||
return -1;
|
||||
}
|
||||
if (dname[dlen - 1] == '.') {
|
||||
dlen--;
|
||||
}
|
||||
|
||||
for (p = env->cfg->local_zones_ipset; p; p = p->next) {
|
||||
plen = strlen(p->str);
|
||||
|
||||
if (dlen >= plen) {
|
||||
s = dname + (dlen - plen);
|
||||
|
||||
if (strncasecmp(p->str, s, plen) == 0) {
|
||||
d = (struct packed_rrset_data*)rrset->entry.data;
|
||||
ipset_add_rrset_data(ie, mnl, d, setname,
|
||||
af, dname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipset_update(struct module_env *env, struct dns_msg *return_msg, struct ipset_env *ie) {
|
||||
struct mnl_socket *mnl;
|
||||
|
||||
size_t i;
|
||||
|
||||
const char *setname;
|
||||
|
||||
struct ub_packed_rrset_key *rrset;
|
||||
|
||||
int af;
|
||||
|
||||
|
||||
mnl = (struct mnl_socket *)ie->mnl;
|
||||
if (!mnl) {
|
||||
// retry to create mnl socket
|
||||
mnl = open_mnl_socket();
|
||||
if (!mnl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ie->mnl = mnl;
|
||||
}
|
||||
|
||||
for (i = 0; i < return_msg->rep->rrset_count; ++i) {
|
||||
setname = NULL;
|
||||
|
||||
rrset = return_msg->rep->rrsets[i];
|
||||
|
||||
if (rrset->rk.type == htons(LDNS_RR_TYPE_A)) {
|
||||
af = AF_INET;
|
||||
if ((ie->v4_enabled == 1)) {
|
||||
setname = ie->name_v4;
|
||||
}
|
||||
} else {
|
||||
af = AF_INET6;
|
||||
if ((ie->v6_enabled == 1)) {
|
||||
setname = ie->name_v6;
|
||||
}
|
||||
}
|
||||
|
||||
if (setname) {
|
||||
if(ipset_check_zones_for_rrset(env, ie, mnl, rrset,
|
||||
setname, af) == -1)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipset_init(struct module_env* env, int id) {
|
||||
struct ipset_env *ipset_env;
|
||||
|
||||
ipset_env = (struct ipset_env *)calloc(1, sizeof(struct ipset_env));
|
||||
if (!ipset_env) {
|
||||
log_err("malloc failure");
|
||||
return 0;
|
||||
}
|
||||
|
||||
env->modinfo[id] = (void *)ipset_env;
|
||||
|
||||
ipset_env->mnl = NULL;
|
||||
|
||||
ipset_env->name_v4 = env->cfg->ipset_name_v4;
|
||||
ipset_env->name_v6 = env->cfg->ipset_name_v6;
|
||||
|
||||
ipset_env->v4_enabled = !ipset_env->name_v4 || (strlen(ipset_env->name_v4) == 0) ? 0 : 1;
|
||||
ipset_env->v6_enabled = !ipset_env->name_v6 || (strlen(ipset_env->name_v6) == 0) ? 0 : 1;
|
||||
|
||||
if ((ipset_env->v4_enabled < 1) && (ipset_env->v6_enabled < 1)) {
|
||||
log_err("ipset: set name no configuration?");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ipset_deinit(struct module_env *env, int id) {
|
||||
struct mnl_socket *mnl;
|
||||
struct ipset_env *ipset_env;
|
||||
|
||||
if (!env || !env->modinfo[id]) {
|
||||
return;
|
||||
}
|
||||
|
||||
ipset_env = (struct ipset_env *)env->modinfo[id];
|
||||
|
||||
mnl = (struct mnl_socket *)ipset_env->mnl;
|
||||
if (mnl) {
|
||||
mnl_socket_close(mnl);
|
||||
ipset_env->mnl = NULL;
|
||||
}
|
||||
|
||||
free(ipset_env);
|
||||
env->modinfo[id] = NULL;
|
||||
}
|
||||
|
||||
static int ipset_new(struct module_qstate* qstate, int id) {
|
||||
struct ipset_qstate *iq = (struct ipset_qstate *)regional_alloc(
|
||||
qstate->region, sizeof(struct ipset_qstate));
|
||||
qstate->minfo[id] = iq;
|
||||
if (!iq) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(iq, 0, sizeof(*iq));
|
||||
/* initialise it */
|
||||
/* TODO */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ipset_operate(struct module_qstate *qstate, enum module_ev event, int id,
|
||||
struct outbound_entry *outbound) {
|
||||
struct ipset_env *ie = (struct ipset_env *)qstate->env->modinfo[id];
|
||||
struct ipset_qstate *iq = (struct ipset_qstate *)qstate->minfo[id];
|
||||
verbose(VERB_QUERY, "ipset[module %d] operate: extstate:%s event:%s",
|
||||
id, strextstate(qstate->ext_state[id]), strmodulevent(event));
|
||||
if (iq) {
|
||||
log_query_info(VERB_QUERY, "ipset operate: query", &qstate->qinfo);
|
||||
}
|
||||
|
||||
/* perform ipset state machine */
|
||||
if ((event == module_event_new || event == module_event_pass) && !iq) {
|
||||
if (!ipset_new(qstate, id)) {
|
||||
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
return;
|
||||
}
|
||||
iq = (struct ipset_qstate*)qstate->minfo[id];
|
||||
}
|
||||
|
||||
if (iq && (event == module_event_pass || event == module_event_new)) {
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
|
||||
if (iq && (event == module_event_moddone)) {
|
||||
if (qstate->return_msg && qstate->return_msg->rep) {
|
||||
ipset_update(qstate->env, qstate->return_msg, ie);
|
||||
}
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
|
||||
if (iq && outbound) {
|
||||
/* ipset does not need to process responses at this time
|
||||
* ignore it.
|
||||
ipset_process_response(qstate, iq, ie, id, outbound, event);
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
if (event == module_event_error) {
|
||||
verbose(VERB_ALGO, "got called with event error, giving up");
|
||||
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!iq && (event == module_event_moddone)) {
|
||||
/* during priming, module done but we never started */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
|
||||
log_err("bad event for ipset");
|
||||
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
void ipset_inform_super(struct module_qstate *ATTR_UNUSED(qstate),
|
||||
int ATTR_UNUSED(id), struct module_qstate *ATTR_UNUSED(super)) {
|
||||
/* ipset does not use subordinate requests at this time */
|
||||
verbose(VERB_ALGO, "ipset inform_super was called");
|
||||
}
|
||||
|
||||
void ipset_clear(struct module_qstate *qstate, int id) {
|
||||
struct cachedb_qstate *iq;
|
||||
if (!qstate) {
|
||||
return;
|
||||
}
|
||||
iq = (struct cachedb_qstate *)qstate->minfo[id];
|
||||
if (iq) {
|
||||
/* free contents of iq */
|
||||
/* TODO */
|
||||
}
|
||||
qstate->minfo[id] = NULL;
|
||||
}
|
||||
|
||||
size_t ipset_get_mem(struct module_env *env, int id) {
|
||||
struct ipset_env *ie = (struct ipset_env *)env->modinfo[id];
|
||||
if (!ie) {
|
||||
return 0;
|
||||
}
|
||||
return sizeof(*ie);
|
||||
}
|
||||
|
||||
/**
|
||||
* The ipset function block
|
||||
*/
|
||||
static struct module_func_block ipset_block = {
|
||||
"ipset",
|
||||
&ipset_init, &ipset_deinit, &ipset_operate,
|
||||
&ipset_inform_super, &ipset_clear, &ipset_get_mem
|
||||
};
|
||||
|
||||
struct module_func_block * ipset_get_funcblock(void) {
|
||||
return &ipset_block;
|
||||
}
|
||||
|
||||
Executable
+79
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* ipset.h
|
||||
*
|
||||
* Author: Kevin Chou
|
||||
* Email: k9982874@gmail.com
|
||||
*/
|
||||
#ifndef IPSET_H
|
||||
#define IPSET_H
|
||||
/** \file
|
||||
*
|
||||
* This file implements the ipset module. It can handle packets by putting
|
||||
* the A and AAAA addresses that are configured in unbound.conf as type
|
||||
* ipset (local-zone statements) into a firewall rule IPSet. For firewall
|
||||
* blacklist and whitelist usage.
|
||||
*
|
||||
* To use the IPset module, install the libmnl-dev (or libmnl-devel) package
|
||||
* and configure with --enable-ipset. And compile. Then enable the ipset
|
||||
* module in unbound.conf with module-config: "ipset validator iterator"
|
||||
* then create it with ipset -N blacklist iphash and then add
|
||||
* local-zone: "example.com." ipset
|
||||
* statements for the zones where you want the addresses of the names
|
||||
* looked up added to the set.
|
||||
*
|
||||
* Set the name of the set with
|
||||
* ipset:
|
||||
* name-v4: "blacklist"
|
||||
* name-v6: "blacklist6"
|
||||
* in unbound.conf. The set can be used in this way:
|
||||
* iptables -A INPUT -m set --set blacklist src -j DROP
|
||||
* ip6tables -A INPUT -m set --set blacklist6 src -j DROP
|
||||
*/
|
||||
|
||||
#include "util/module.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ipset_env {
|
||||
void* mnl;
|
||||
|
||||
int v4_enabled;
|
||||
int v6_enabled;
|
||||
|
||||
const char *name_v4;
|
||||
const char *name_v6;
|
||||
};
|
||||
|
||||
struct ipset_qstate {
|
||||
int dummy;
|
||||
};
|
||||
|
||||
/** Init the ipset module */
|
||||
int ipset_init(struct module_env* env, int id);
|
||||
/** Deinit the ipset module */
|
||||
void ipset_deinit(struct module_env* env, int id);
|
||||
/** Operate on an event on a query (in qstate). */
|
||||
void ipset_operate(struct module_qstate* qstate, enum module_ev event,
|
||||
int id, struct outbound_entry* outbound);
|
||||
/** Subordinate query done, inform this super request of its conclusion */
|
||||
void ipset_inform_super(struct module_qstate* qstate, int id,
|
||||
struct module_qstate* super);
|
||||
/** clear the ipset query-specific contents out of qstate */
|
||||
void ipset_clear(struct module_qstate* qstate, int id);
|
||||
/** return memory estimate for ipset module */
|
||||
size_t ipset_get_mem(struct module_env* env, int id);
|
||||
|
||||
/**
|
||||
* Get the function block with pointers to the ipset functions
|
||||
* @return the function block for "ipset".
|
||||
*/
|
||||
struct module_func_block* ipset_get_funcblock(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* IPSET_H */
|
||||
|
||||
+28
-6
@@ -84,7 +84,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
|
||||
}
|
||||
for(a = dp->target_list; a; a = a->next_target) {
|
||||
if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen,
|
||||
a->bogus, a->lame))
|
||||
a->bogus, a->lame, a->tls_auth_name))
|
||||
return NULL;
|
||||
}
|
||||
return copy;
|
||||
@@ -176,13 +176,13 @@ delegpt_add_target(struct delegpt* dp, struct regional* region,
|
||||
if(ns->got4 && ns->got6)
|
||||
ns->resolved = 1;
|
||||
}
|
||||
return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame);
|
||||
return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
delegpt_add_addr(struct delegpt* dp, struct regional* region,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus,
|
||||
uint8_t lame)
|
||||
uint8_t lame, char* tls_auth_name)
|
||||
{
|
||||
struct delegpt_addr* a;
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
@@ -210,6 +210,13 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region,
|
||||
a->bogus = bogus;
|
||||
a->lame = lame;
|
||||
a->dnsseclame = 0;
|
||||
if(tls_auth_name) {
|
||||
a->tls_auth_name = regional_strdup(region, tls_auth_name);
|
||||
if(!a->tls_auth_name)
|
||||
return 0;
|
||||
} else {
|
||||
a->tls_auth_name = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -276,11 +283,16 @@ void delegpt_log(enum verbosity_value v, struct delegpt* dp)
|
||||
(ns->done_pside6?" PSIDE_AAAA":""));
|
||||
}
|
||||
for(a = dp->target_list; a; a = a->next_target) {
|
||||
char s[128];
|
||||
const char* str = " ";
|
||||
if(a->bogus && a->lame) str = " BOGUS ADDR_LAME ";
|
||||
else if(a->bogus) str = " BOGUS ";
|
||||
else if(a->lame) str = " ADDR_LAME ";
|
||||
log_addr(VERB_ALGO, str, &a->addr, a->addrlen);
|
||||
if(a->tls_auth_name)
|
||||
snprintf(s, sizeof(s), "%s[%s]", str,
|
||||
a->tls_auth_name);
|
||||
else snprintf(s, sizeof(s), "%s", str);
|
||||
log_addr(VERB_ALGO, s, &a->addr, a->addrlen);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -539,6 +551,7 @@ void delegpt_free_mlc(struct delegpt* dp)
|
||||
a = dp->target_list;
|
||||
while(a) {
|
||||
na = a->next_target;
|
||||
free(a->tls_auth_name);
|
||||
free(a);
|
||||
a = na;
|
||||
}
|
||||
@@ -585,7 +598,7 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame)
|
||||
}
|
||||
|
||||
int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t bogus, uint8_t lame)
|
||||
socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name)
|
||||
{
|
||||
struct delegpt_addr* a;
|
||||
log_assert(dp->dp_type_mlc);
|
||||
@@ -612,6 +625,15 @@ int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
|
||||
a->bogus = bogus;
|
||||
a->lame = lame;
|
||||
a->dnsseclame = 0;
|
||||
if(tls_auth_name) {
|
||||
a->tls_auth_name = strdup(tls_auth_name);
|
||||
if(!a->tls_auth_name) {
|
||||
free(a);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
a->tls_auth_name = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -632,7 +654,7 @@ int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen,
|
||||
if(ns->got4 && ns->got6)
|
||||
ns->resolved = 1;
|
||||
}
|
||||
return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame);
|
||||
return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame, NULL);
|
||||
}
|
||||
|
||||
size_t delegpt_get_mem(struct delegpt* dp)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user