mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
Compare commits
1934
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a45da353d3 | ||
|
|
c21e3ee929 | ||
|
|
8a38bed262 | ||
|
|
7cc7a43ff6 | ||
|
|
9bd8df0149 | ||
|
|
8f7411057f | ||
|
|
ca1fe4f82a | ||
|
|
e183c2c506 | ||
|
|
52b18fc6f5 | ||
|
|
e6d00725c2 | ||
|
|
e597711824 | ||
|
|
e1e646c6fc | ||
|
|
fc3b5b4f63 | ||
|
|
1e904a3ce5 | ||
|
|
79e100a7fb | ||
|
|
a65d3d7283 | ||
|
|
3b8766aa43 | ||
|
|
c8b3c89a39 | ||
|
|
a05d460e66 | ||
|
|
5eb362a6c0 | ||
|
|
0735cb28d1 | ||
|
|
737c28e836 | ||
|
|
1bab2dfafa | ||
|
|
22e2c5b6d1 | ||
|
|
914dbfea4e | ||
|
|
cf5e6e89a5 | ||
|
|
4941edf275 | ||
|
|
b08723ef97 | ||
|
|
c163fbc505 | ||
|
|
eed3f1ab38 | ||
|
|
63501f51bb | ||
|
|
1ae2570bda | ||
|
|
9ad825b267 | ||
|
|
3d5e6c0692 | ||
|
|
23e19ca6fc | ||
|
|
9f757aa9f3 | ||
|
|
1df6c170ff | ||
|
|
7a95bedc26 | ||
|
|
ae685bc33d | ||
|
|
91ac449bcd | ||
|
|
c33ad1b1a2 | ||
|
|
84d9682dd0 | ||
|
|
4b1635e194 | ||
|
|
aac261cbb3 | ||
|
|
ae1b3810cc | ||
|
|
96f8755520 | ||
|
|
2ce2ca3691 | ||
|
|
c29ff70f6a | ||
|
|
8a15ffee62 | ||
|
|
8c702de175 | ||
|
|
804cff4c15 | ||
|
|
e180b06298 | ||
|
|
3530c81e29 | ||
|
|
02b16de1ae | ||
|
|
1ad8d4c395 | ||
|
|
364ac737f7 | ||
|
|
f7637a4f18 | ||
|
|
1e1940383a | ||
|
|
f52a9e864b | ||
|
|
13ec8d0f26 | ||
|
|
27f22b8808 | ||
|
|
f54e0791ba | ||
|
|
01dfd2f466 | ||
|
|
f157c691bb | ||
|
|
fea0ff550b | ||
|
|
87d59bfced | ||
|
|
25b2543e5e | ||
|
|
7133e0d32a | ||
|
|
fac7584830 | ||
|
|
87f9258fb4 | ||
|
|
a2fe5356b5 | ||
|
|
ad9b12a863 | ||
|
|
61ca4111a1 | ||
|
|
71a971d70c | ||
|
|
ba4f8478e6 | ||
|
|
374a18cc5b | ||
|
|
f35561287a | ||
|
|
672b9659cf | ||
|
|
1978add0cd | ||
|
|
6cbcea3ac7 | ||
|
|
65e23d4b6f | ||
|
|
fbe41cdef9 | ||
|
|
01a95108b3 | ||
|
|
f75d11821f | ||
|
|
6aa5cfc903 | ||
|
|
f6931c794e | ||
|
|
4c5082ad05 | ||
|
|
5fb892a097 | ||
|
|
55e9532d16 | ||
|
|
fff6657cea | ||
|
|
45d1e75caf | ||
|
|
b806f16c8b | ||
|
|
8d3348c71b | ||
|
|
e2cc14681e | ||
|
|
5ae979bb6e | ||
|
|
8f2fbd66fc | ||
|
|
b5909d8d22 | ||
|
|
fa8e94f155 | ||
|
|
cb5683aeae | ||
|
|
c9715724ec | ||
|
|
78d9cfffd8 | ||
|
|
b47b1d048d | ||
|
|
740952fb82 | ||
|
|
5c550f4548 | ||
|
|
3d78cb8d9a | ||
|
|
1ab75c0043 | ||
|
|
bebc8d516b | ||
|
|
a7debe7ff6 | ||
|
|
215e3920ef | ||
|
|
aabf28aef5 | ||
|
|
aa09835c90 | ||
|
|
9b9e13b665 | ||
|
|
f72e11ef5b | ||
|
|
a45e54555d | ||
|
|
4693c00c9f | ||
|
|
8fe23e0297 | ||
|
|
8557788699 | ||
|
|
81a19ebeb3 | ||
|
|
299df5ec77 | ||
|
|
6f9b6db7be | ||
|
|
96f15b9160 | ||
|
|
159384c2a9 | ||
|
|
621fc91453 | ||
|
|
543c49f76c | ||
|
|
d0a760a587 | ||
|
|
f68cca4097 | ||
|
|
3129357874 | ||
|
|
fc09352df6 | ||
|
|
06da5d45a3 | ||
|
|
69524cadad | ||
|
|
98e95d80e6 | ||
|
|
2f8aa8a43a | ||
|
|
56e60e37ae | ||
|
|
8f5348ab47 | ||
|
|
c5d693b21c | ||
|
|
27e3ac55b9 | ||
|
|
7879218773 | ||
|
|
1354624ba4 | ||
|
|
153f8d5353 | ||
|
|
a1cecf7462 | ||
|
|
e2dac8a00a | ||
|
|
ecd41bef27 | ||
|
|
fd2131687a | ||
|
|
316b9ab4fc | ||
|
|
d45daaf313 | ||
|
|
db1c6d6557 | ||
|
|
e7a713a525 | ||
|
|
39e67508c9 | ||
|
|
3eab974ca2 | ||
|
|
b1d1dcb3b6 | ||
|
|
10cb62aca2 | ||
|
|
6da73aba38 | ||
|
|
1b1b9626ee | ||
|
|
8bc074043a | ||
|
|
04a6322aa4 | ||
|
|
5748f518d1 | ||
|
|
d05eff4d54 | ||
|
|
4544eaa4cc | ||
|
|
5d0770d0ad | ||
|
|
7f4beb846e | ||
|
|
8e8c04e1b9 | ||
|
|
bf0da2ed21 | ||
|
|
670ece06df | ||
|
|
9e41903be8 | ||
|
|
57f92cc97e | ||
|
|
c0741ccc68 | ||
|
|
fb2745024a | ||
|
|
0c15ddd133 | ||
|
|
b53504049c | ||
|
|
a5324e58eb | ||
|
|
963cd68535 | ||
|
|
047df73887 | ||
|
|
d2e1ea7d19 | ||
|
|
fbbe95ba5b | ||
|
|
758c649611 | ||
|
|
a23f95f620 | ||
|
|
5363570df0 | ||
|
|
368857a45b | ||
|
|
40b16d0565 | ||
|
|
08e901a1ac | ||
|
|
bc703c9129 | ||
|
|
9ce52de6c1 | ||
|
|
b3aa262477 | ||
|
|
25e112c674 | ||
|
|
0d2282d551 | ||
|
|
b5f21f4165 | ||
|
|
d357935f66 | ||
|
|
9d2e0f1c02 | ||
|
|
b46ff5c18e | ||
|
|
f597105800 | ||
|
|
3692517a41 | ||
|
|
75b6dba593 | ||
|
|
138fb48eac | ||
|
|
dae7a37974 | ||
|
|
8ae4b4545d | ||
|
|
c343fff3a4 | ||
|
|
a794c87578 | ||
|
|
ef5ca84360 | ||
|
|
8d8fa42266 | ||
|
|
a587535c5d | ||
|
|
94d5babaee | ||
|
|
fe946ba4e9 | ||
|
|
6a31e470f8 | ||
|
|
e577695aeb | ||
|
|
a58bd6cb1e | ||
|
|
4bad944ae4 | ||
|
|
594182f109 | ||
|
|
53c261cb33 | ||
|
|
8703d9a5be | ||
|
|
aa9f1e68ff | ||
|
|
84a4f556b1 | ||
|
|
5b166dbf0a | ||
|
|
9e2233b821 | ||
|
|
13716dc8be | ||
|
|
8ada1bd88d | ||
|
|
9c80bb9fb0 | ||
|
|
33e2863862 | ||
|
|
027e23a11d | ||
|
|
62e8db1c6a | ||
|
|
581b2f31bc | ||
|
|
25fe602024 | ||
|
|
df0e86de49 | ||
|
|
e49b550cf3 | ||
|
|
07c96792f2 | ||
|
|
84ab430e11 | ||
|
|
53499e4a88 | ||
|
|
8a25a97687 | ||
|
|
c112bcf2fd | ||
|
|
9de549c498 | ||
|
|
84c645e7b3 | ||
|
|
197a425c7d | ||
|
|
311054728d | ||
|
|
6d74856212 | ||
|
|
d489e6027e | ||
|
|
e1d146d6b0 | ||
|
|
eb2fe8df8d | ||
|
|
86a8be75f0 | ||
|
|
52fc5ee374 | ||
|
|
82359c8fb1 | ||
|
|
c996671a1f | ||
|
|
e233a1ef65 | ||
|
|
06ff9f20d0 | ||
|
|
af209a12ea | ||
|
|
84ac7e1b58 | ||
|
|
24d502763c | ||
|
|
99c61c19ac | ||
|
|
cb05e9d525 | ||
|
|
abddd4e270 | ||
|
|
656b412492 | ||
|
|
f15a46fcd4 | ||
|
|
8d434bf744 | ||
|
|
13b269d398 | ||
|
|
7aff88881a | ||
|
|
b97bd3a1fc | ||
|
|
6aa5ad85f4 | ||
|
|
42b19c20c1 | ||
|
|
db1fe8b475 | ||
|
|
f4f964f4fb | ||
|
|
a2272860de | ||
|
|
95083d4377 | ||
|
|
5ce0bf5281 | ||
|
|
6a0d5e2cb1 | ||
|
|
330d5211c9 | ||
|
|
2dc28a249a | ||
|
|
c5f14dc880 | ||
|
|
a2ace114de | ||
|
|
2e9b880718 | ||
|
|
a0ec6cd946 | ||
|
|
ea36979c40 | ||
|
|
315077b9e6 | ||
|
|
535d899bef | ||
|
|
8656cfd4c8 | ||
|
|
8f44ddb7de | ||
|
|
4484dc3954 | ||
|
|
eb3bba0724 | ||
|
|
2eff1d8ab5 | ||
|
|
4672fa5b53 | ||
|
|
18029fc44f | ||
|
|
5c6f56f8f1 | ||
|
|
9af29c3ed1 | ||
|
|
76ef8c5803 | ||
|
|
94ef1a8fee | ||
|
|
683241a2f5 | ||
|
|
92ab54641e | ||
|
|
da3812953a | ||
|
|
1bd7c8dfee | ||
|
|
8f96ae7acf | ||
|
|
c4f8e60c85 | ||
|
|
a296b248b0 | ||
|
|
1ef131299a | ||
|
|
5b58a872ef | ||
|
|
94b04d6d46 | ||
|
|
f1a65eb4e8 | ||
|
|
38e1e3eec3 | ||
|
|
bff3d762ff | ||
|
|
fb322f3e87 | ||
|
|
2feee13735 | ||
|
|
1d36696462 | ||
|
|
aa4e2a9e69 | ||
|
|
8e04d04949 | ||
|
|
c5627dbd52 | ||
|
|
014ed9c5ff | ||
|
|
16e1e6d375 | ||
|
|
1a9a4e4ca1 | ||
|
|
f7f638e18f | ||
|
|
c956aea93d | ||
|
|
4556a4f490 | ||
|
|
1cdddf0fe9 | ||
|
|
18fec256b7 | ||
|
|
567c70dada | ||
|
|
8b4b2a88f7 | ||
|
|
faf40c97fc | ||
|
|
daa016e3e4 | ||
|
|
039f69e735 | ||
|
|
b39009e487 | ||
|
|
933769ee73 | ||
|
|
57bff79627 | ||
|
|
1b5559d534 | ||
|
|
9d271c5343 | ||
|
|
74cc49e6c4 | ||
|
|
d414ebf0c7 | ||
|
|
9b123d1b78 | ||
|
|
37b71261a2 | ||
|
|
4426db4d3d | ||
|
|
fe10bc7682 | ||
|
|
67d2eae28c | ||
|
|
9010a7075e | ||
|
|
cc6dbc9f38 | ||
|
|
4198343dbe | ||
|
|
08600d68e8 | ||
|
|
18e098285e | ||
|
|
f1b35bab4b | ||
|
|
84ed77238d | ||
|
|
adb0374a4d | ||
|
|
b0b634558b | ||
|
|
8546247292 | ||
|
|
44659cb3bf | ||
|
|
a1ac2d0252 | ||
|
|
5c7a26b615 | ||
|
|
09d352b917 | ||
|
|
c0522043f0 | ||
|
|
b858801feb | ||
|
|
588db09928 | ||
|
|
5c66c48a1b | ||
|
|
83336477c6 | ||
|
|
e3e5eb66cf | ||
|
|
00d3b97dbb | ||
|
|
f6269baa60 | ||
|
|
19154c6e58 | ||
|
|
0f43b0ea6c | ||
|
|
e6d92f458f | ||
|
|
a31b9d50e2 | ||
|
|
fceb4e8585 | ||
|
|
98f4257890 | ||
|
|
0a15118aff | ||
|
|
e887a79a92 | ||
|
|
f9b9050ab8 | ||
|
|
94735384fd | ||
|
|
5dab0609e5 | ||
|
|
024c921dbf | ||
|
|
1a808e2978 | ||
|
|
56ded934de | ||
|
|
98952f11d1 | ||
|
|
cb4b3de62f | ||
|
|
c8dcfc0853 | ||
|
|
2bb28fdf12 | ||
|
|
6ad26909dd | ||
|
|
9602973c86 | ||
|
|
713b1783d4 | ||
|
|
e06b7eb3f1 | ||
|
|
a33f0638e1 | ||
|
|
bbeee42e25 | ||
|
|
1cb9595a42 | ||
|
|
aa21e38b3a | ||
|
|
964848b94a | ||
|
|
a4dd321fd8 | ||
|
|
d23a28a693 | ||
|
|
5423c0a8e9 | ||
|
|
6a5385f291 | ||
|
|
16f3478048 | ||
|
|
c8860a5fb6 | ||
|
|
735c96aac7 | ||
|
|
a75ea01a15 | ||
|
|
21f02a0865 | ||
|
|
e017d66fc1 | ||
|
|
adaf5dab49 | ||
|
|
feeebc95f8 | ||
|
|
187aa52859 | ||
|
|
f1fea8dc46 | ||
|
|
0c01257d1d | ||
|
|
50a11ebcc8 | ||
|
|
1e2dc657a1 | ||
|
|
843124852f | ||
|
|
5e2fdff8e5 | ||
|
|
499a3a7a61 | ||
|
|
2024c1d050 | ||
|
|
6cd595a816 | ||
|
|
74cf81e9a7 | ||
|
|
35f6fd47fb | ||
|
|
270e099aab | ||
|
|
64645e1401 | ||
|
|
421d317a64 | ||
|
|
0b8ed987de | ||
|
|
9511797487 | ||
|
|
0b7bb75152 | ||
|
|
88c688ec10 | ||
|
|
81fd1dc71c | ||
|
|
69217cf675 | ||
|
|
7c28f1b99c | ||
|
|
fa6340cfa5 | ||
|
|
e471e15774 | ||
|
|
ec3db03121 | ||
|
|
e2bf773089 | ||
|
|
3017a0aa52 | ||
|
|
8419e9780e | ||
|
|
c429c4ab96 | ||
|
|
bc61034f60 | ||
|
|
2dd821c257 | ||
|
|
713b5db537 | ||
|
|
c3a8d5251f | ||
|
|
73e408f1d0 | ||
|
|
d521135f66 | ||
|
|
d71ead5598 | ||
|
|
cdbfadfb7b | ||
|
|
4267de87b5 | ||
|
|
dd6200065f | ||
|
|
a72177e73c | ||
|
|
1d3d78dff5 | ||
|
|
5588f66bdb | ||
|
|
85e916e7e0 | ||
|
|
af96824642 | ||
|
|
8faa95354d | ||
|
|
c57c39833e | ||
|
|
44da5eee66 | ||
|
|
74bc8c9e77 | ||
|
|
0c558cb805 | ||
|
|
533291dce9 | ||
|
|
e613e27f35 | ||
|
|
f2f36a2733 | ||
|
|
78d9bcacb6 | ||
|
|
c170ed1b30 | ||
|
|
ebfa09e04f | ||
|
|
65be1d0ec3 | ||
|
|
ca36e21f71 | ||
|
|
458c793012 | ||
|
|
1341905de8 | ||
|
|
1d877400ea | ||
|
|
8fd4b91afc | ||
|
|
523710f371 | ||
|
|
13bb78a740 | ||
|
|
1e37f86ef5 | ||
|
|
81345fe1e3 | ||
|
|
40877f46e5 | ||
|
|
991108af8d | ||
|
|
4f790bd65e | ||
|
|
d122ae6490 | ||
|
|
651a71fa76 | ||
|
|
2f7890eb6e | ||
|
|
fad747308f | ||
|
|
d55f20fdcc | ||
|
|
19b289feec | ||
|
|
752a3f7f52 | ||
|
|
3ec5d78ac9 | ||
|
|
08d59c9a78 | ||
|
|
cdcc0337d1 | ||
|
|
305adf12bf | ||
|
|
3d7e847a5e | ||
|
|
da6b735ed9 | ||
|
|
5758427d86 | ||
|
|
4f12148af4 | ||
|
|
f8f4779f1f | ||
|
|
da9ab59e10 | ||
|
|
424f86466a | ||
|
|
910288c0d1 | ||
|
|
b6e52c0a52 | ||
|
|
b58af78b63 | ||
|
|
a1150078f2 | ||
|
|
f49e6ccecd | ||
|
|
ad0e0fc290 | ||
|
|
5bf82f2464 | ||
|
|
20f862de51 | ||
|
|
46823f7bc3 | ||
|
|
dd3ac53ff1 | ||
|
|
1a6052fcac | ||
|
|
6689f0b4da | ||
|
|
44ac818f87 | ||
|
|
b4e12030e7 | ||
|
|
9fe92d1119 | ||
|
|
6ba2d6840b | ||
|
|
1de9d6ec66 | ||
|
|
cb919d5126 | ||
|
|
444c839474 | ||
|
|
0276bcbceb | ||
|
|
41c55ffac1 | ||
|
|
4200d23882 | ||
|
|
e2814fe165 | ||
|
|
ca153f4657 | ||
|
|
ee607c0f72 | ||
|
|
2d90d5d729 | ||
|
|
ce72770f61 | ||
|
|
de93a636da | ||
|
|
d3f88d008f | ||
|
|
a1d68cdc96 | ||
|
|
9201c75013 | ||
|
|
f066d6d453 | ||
|
|
a04bd5da29 | ||
|
|
e4cf7aeccf | ||
|
|
a8aa1dbbe1 | ||
|
|
9f29292839 | ||
|
|
1cc1e0b89e | ||
|
|
565bce670c | ||
|
|
c0563f43b0 | ||
|
|
81f3de4da2 | ||
|
|
ff7dfd52a2 | ||
|
|
342a0f48e3 | ||
|
|
71ac59e6f4 | ||
|
|
6662f71732 | ||
|
|
32644937b0 | ||
|
|
1634beb4a0 | ||
|
|
1ef7b4a246 | ||
|
|
03772d10fb | ||
|
|
9152c914af | ||
|
|
a35ac5d82e | ||
|
|
21e3278400 | ||
|
|
8e1deede08 | ||
|
|
4e23523d1a | ||
|
|
8190526250 | ||
|
|
5dd14e2644 | ||
|
|
b50faccb1d | ||
|
|
fcc21885e4 | ||
|
|
a904a3a2c2 | ||
|
|
c253c8367a | ||
|
|
0f95fae445 | ||
|
|
e5bbc36ae0 | ||
|
|
c88fa02c18 | ||
|
|
e794234ac8 | ||
|
|
db53ebb798 | ||
|
|
fe835f9d52 | ||
|
|
30c13d0351 | ||
|
|
d6e8ac1289 | ||
|
|
9c99b404a1 | ||
|
|
75e8fd7539 | ||
|
|
16ee7cf944 | ||
|
|
38026a21ee | ||
|
|
4f06e658d1 | ||
|
|
fca3ae0535 | ||
|
|
66b3abc803 | ||
|
|
922c5c3ab3 | ||
|
|
f9d740dfdc | ||
|
|
5eb1382fc0 | ||
|
|
e94e140f49 | ||
|
|
db6505eb8b | ||
|
|
a616437338 | ||
|
|
eb390dd038 | ||
|
|
4074a5b2ba | ||
|
|
a7e618b9c2 | ||
|
|
349721a39d | ||
|
|
ed71f72baa | ||
|
|
0e5d26807d | ||
|
|
90243a694a | ||
|
|
7fb6f9d613 | ||
|
|
7fb05c01c2 | ||
|
|
cb5a019d9f | ||
|
|
53ecdb25ef | ||
|
|
9939d5cdb0 | ||
|
|
5f91d5f74c | ||
|
|
c2ca679f5c | ||
|
|
ba18abcd35 | ||
|
|
a7704ad49f | ||
|
|
8b38fe5ab6 | ||
|
|
fcdb0bbf91 | ||
|
|
b738b354bd | ||
|
|
1c58ce0791 | ||
|
|
a7106fc58d | ||
|
|
17f95ffac1 | ||
|
|
0ca76b05e0 | ||
|
|
218f5cfc92 | ||
|
|
914cef75f9 | ||
|
|
f76365754e | ||
|
|
aa77d02336 | ||
|
|
23273d76a5 | ||
|
|
94a84d3387 | ||
|
|
d91c857e22 | ||
|
|
d03e4b1884 | ||
|
|
376f2ade2a | ||
|
|
0eabc8d0f1 | ||
|
|
a42fb99508 | ||
|
|
eccf52e39d | ||
|
|
30b9cb5f81 | ||
|
|
b0d20e2d28 | ||
|
|
13afde2cad | ||
|
|
71bb60e586 | ||
|
|
5c84bb573f | ||
|
|
d9f1dae540 | ||
|
|
a3d750b7d8 | ||
|
|
c371be3f9f | ||
|
|
c5c5486261 | ||
|
|
1894c0a150 | ||
|
|
edb20a2ad2 | ||
|
|
bcf162abd7 | ||
|
|
5e1f35b59b | ||
|
|
72828ff81c | ||
|
|
01cea4d5be | ||
|
|
35dbbcb2f5 | ||
|
|
911509fd59 | ||
|
|
b48958c983 | ||
|
|
cc55beefc8 | ||
|
|
a2bf32bb4e | ||
|
|
d9b863ed76 | ||
|
|
073c7301eb | ||
|
|
f822042cd0 | ||
|
|
5f58ced71e | ||
|
|
207ae97ff9 | ||
|
|
9a0de14aa1 | ||
|
|
048c193243 | ||
|
|
d62fff2c7c | ||
|
|
3f839cebc3 | ||
|
|
e4483bbbd1 | ||
|
|
8672b34fca | ||
|
|
1d428f2d54 | ||
|
|
9882a395ab | ||
|
|
394588818f | ||
|
|
f52b2a6ea2 | ||
|
|
b2fec3be11 | ||
|
|
f4881bd81a | ||
|
|
c3b5bff311 | ||
|
|
62a0e03801 | ||
|
|
716f3df385 | ||
|
|
7e4f7ec5be | ||
|
|
7559d26c93 | ||
|
|
eb36c880de | ||
|
|
fff9f62a1e | ||
|
|
e57e537c85 | ||
|
|
71d821fde9 | ||
|
|
df5ab5624d | ||
|
|
eb08dc617a | ||
|
|
ded4c82ced | ||
|
|
e82a691efe | ||
|
|
61d7250b96 | ||
|
|
b4a9c8bb05 | ||
|
|
be92752368 | ||
|
|
1512945c79 | ||
|
|
9de159b96b | ||
|
|
bd2e66de1e | ||
|
|
9770e855d2 | ||
|
|
c124f67f33 | ||
|
|
c55490c1e6 | ||
|
|
f46acec35f | ||
|
|
1cd2fb3b9d | ||
|
|
06fb30d0a0 | ||
|
|
9e3c50ec9e | ||
|
|
eefdbb341f | ||
|
|
e75da7d954 | ||
|
|
9a3a1bc221 | ||
|
|
c1e9d7be7f | ||
|
|
2c72a4970b | ||
|
|
4cf7fae50c | ||
|
|
a2ac980737 | ||
|
|
c88eed83d9 | ||
|
|
50fcf71f04 | ||
|
|
733d5f7161 | ||
|
|
fe288a9b06 | ||
|
|
fd1a1d5fa0 | ||
|
|
3c4b87636a | ||
|
|
36d8c6e778 | ||
|
|
60fd77b8f9 | ||
|
|
d5e91d181b | ||
|
|
7985d17b57 | ||
|
|
46cfbf313d | ||
|
|
533c3b0514 | ||
|
|
5f3f214da5 | ||
|
|
11b8157a98 | ||
|
|
1c24cd79cc | ||
|
|
d34fb3ed77 | ||
|
|
c37833c943 | ||
|
|
8a6a4bd7f3 | ||
|
|
d23523e528 | ||
|
|
75967e7f5e | ||
|
|
f5580f0a63 | ||
|
|
0e2b2743d8 | ||
|
|
018be1d089 | ||
|
|
9a63db344e | ||
|
|
0076736fc4 | ||
|
|
f8e45ed696 | ||
|
|
2a28c7389c | ||
|
|
114edf2c38 | ||
|
|
e0c93e300b | ||
|
|
bd1813b126 | ||
|
|
1b7e14dc39 | ||
|
|
8b7782e8fc | ||
|
|
e0201435a4 | ||
|
|
66fb3ff670 | ||
|
|
36461ea73d | ||
|
|
5679c8b1df | ||
|
|
a4d8c0c43b | ||
|
|
3d89c26d32 | ||
|
|
dcf7afd722 | ||
|
|
e67171612b | ||
|
|
a1b25f0296 | ||
|
|
490585bf29 | ||
|
|
b7c61d7cc2 | ||
|
|
01883fb017 | ||
|
|
5bb3b9cc83 | ||
|
|
3a1b79f6a1 | ||
|
|
84eeb9b97c | ||
|
|
d88eeb4c32 | ||
|
|
2e398d51ba | ||
|
|
24ebca7df6 | ||
|
|
7f4a61e6fc | ||
|
|
db719d404f | ||
|
|
a35a0c49da | ||
|
|
5e9b6296b7 | ||
|
|
606e262fdd | ||
|
|
819764663b | ||
|
|
6bf2b2ac56 | ||
|
|
5767b0933f | ||
|
|
24e0f0ab7e | ||
|
|
d3fdbba877 | ||
|
|
c36ce2a390 | ||
|
|
7ecff4113c | ||
|
|
99824bc0e6 | ||
|
|
9f09c36401 | ||
|
|
a887284703 | ||
|
|
fb198b96f1 | ||
|
|
30bf996f39 | ||
|
|
52154e658a | ||
|
|
c06d3646a9 | ||
|
|
42d421a305 | ||
|
|
b5951ce1fa | ||
|
|
6b37309705 | ||
|
|
dc274fef9b | ||
|
|
db1167c8b3 | ||
|
|
1e0cf1e86b | ||
|
|
348df52e05 | ||
|
|
6b3266aaf8 | ||
|
|
4f52461e81 | ||
|
|
06d5031d22 | ||
|
|
12119e2d3e | ||
|
|
19d53d5663 | ||
|
|
04e6f9e03b | ||
|
|
3d350fa73d | ||
|
|
015b2b0daf | ||
|
|
5fa84d50bf | ||
|
|
79e4c57851 | ||
|
|
5abdd09095 | ||
|
|
158c1defe3 | ||
|
|
b4519012dc | ||
|
|
ed883238fd | ||
|
|
0f2f6025e7 | ||
|
|
3cbf554e3b | ||
|
|
ad21dbd1c2 | ||
|
|
50cf55bdac | ||
|
|
6106528a50 | ||
|
|
befa7d8cd8 | ||
|
|
92be76fb89 | ||
|
|
9a6b6765cc | ||
|
|
03b511b1a2 | ||
|
|
6af28bed08 | ||
|
|
f094f4ea3c | ||
|
|
c717debace | ||
|
|
7d4d21764a | ||
|
|
83e6977f06 | ||
|
|
671e11552c | ||
|
|
c4541e634b | ||
|
|
30da725e67 | ||
|
|
8de5ae3552 | ||
|
|
5bea29b01c | ||
|
|
89c9eafa44 | ||
|
|
3512eaec48 | ||
|
|
f9bd35dcfa | ||
|
|
3af4e44646 | ||
|
|
c3dd6a2dbd | ||
|
|
8fca3e7c5b | ||
|
|
8947c2c764 | ||
|
|
b1e3319a11 | ||
|
|
d52f501d90 | ||
|
|
7083d58c6b | ||
|
|
3adb9c8f92 | ||
|
|
51425b2388 | ||
|
|
d43760a8cd | ||
|
|
ea3e327006 | ||
|
|
be09350eca | ||
|
|
169acfc546 | ||
|
|
bed7cc2a90 | ||
|
|
02f4446833 | ||
|
|
c8a2289542 | ||
|
|
b53d90053e | ||
|
|
978b0696d3 | ||
|
|
ec5f86b4eb | ||
|
|
ec2f45c6fd | ||
|
|
6b319c97ee | ||
|
|
6eb3992c9e | ||
|
|
94a94fd8c8 | ||
|
|
36f9d1a2a9 | ||
|
|
d3a2264272 | ||
|
|
92b6c2a7b9 | ||
|
|
a335e601e4 | ||
|
|
a19009df1d | ||
|
|
96f8a94c19 | ||
|
|
2fe4e2ec3e | ||
|
|
e54928a628 | ||
|
|
538434186e | ||
|
|
65e7253d19 | ||
|
|
03ac902296 | ||
|
|
97ad1df343 | ||
|
|
2279cde8f7 | ||
|
|
ff653a7ef8 | ||
|
|
fd11cd9182 | ||
|
|
3953f827fb | ||
|
|
7fbc061846 | ||
|
|
70f73a33b3 | ||
|
|
b67fbb69e7 | ||
|
|
902c79608c | ||
|
|
08050dc939 | ||
|
|
9603924bb4 | ||
|
|
4c2da2b979 | ||
|
|
1974732d19 | ||
|
|
3cad5818a1 | ||
|
|
ad12109191 | ||
|
|
f611220eb8 | ||
|
|
86fe9cbce5 | ||
|
|
ac609fcbfc | ||
|
|
486985fbdf | ||
|
|
caab100207 | ||
|
|
4b30e88eec | ||
|
|
b6c7ea563f | ||
|
|
910d7cf446 | ||
|
|
cd485f2036 | ||
|
|
8ff1baf585 | ||
|
|
5fc4673901 | ||
|
|
faf3d358dc | ||
|
|
f5a2160ba3 | ||
|
|
0c0c36f015 | ||
|
|
47956de897 | ||
|
|
b30c869a59 | ||
|
|
6f030e9672 | ||
|
|
7107d3c9e7 | ||
|
|
fbdc06ebc4 | ||
|
|
d149e755fd | ||
|
|
86ee8ccd12 | ||
|
|
8d6a1ba811 | ||
|
|
9ccb8d5f20 | ||
|
|
8e43e2574c | ||
|
|
2e70506763 | ||
|
|
7f184c8ca8 | ||
|
|
da2b307aa3 | ||
|
|
739a88ceed | ||
|
|
3ff5c7a74d | ||
|
|
1048c4a28c | ||
|
|
7de009f99a | ||
|
|
95669855fb | ||
|
|
56e7cade28 | ||
|
|
c085a53268 | ||
|
|
49569b81aa | ||
|
|
4497e8a154 | ||
|
|
b9525c5fd4 | ||
|
|
c3206f4568 | ||
|
|
9abed3fc83 | ||
|
|
63a6b7b255 | ||
|
|
15dc8e8a3f | ||
|
|
cd4a017e96 | ||
|
|
82c0207fa6 | ||
|
|
7c5e765b3b | ||
|
|
f456d97a34 | ||
|
|
8b490b1540 | ||
|
|
b3951e5885 | ||
|
|
ced9762b14 | ||
|
|
9b9bba9f02 | ||
|
|
07859a9ef3 | ||
|
|
cb74467acb | ||
|
|
62dad42152 | ||
|
|
3ec74d1e3a | ||
|
|
52aff65e35 | ||
|
|
5994fb3db5 | ||
|
|
0dbcb45d28 | ||
|
|
d71f257215 | ||
|
|
b11d234f77 | ||
|
|
0d4c5aa421 | ||
|
|
9e60f93b84 | ||
|
|
9d63e8f093 | ||
|
|
4c40253df7 | ||
|
|
491b56d051 | ||
|
|
4d530920e0 | ||
|
|
08fb9a9209 | ||
|
|
04ff2672b5 | ||
|
|
d47849a26e | ||
|
|
63ee97d0fd | ||
|
|
bd74a32b79 | ||
|
|
b990be88ef | ||
|
|
cccf5e73c0 | ||
|
|
f3f85e5a11 | ||
|
|
d55511f1dd | ||
|
|
d98c7b9ae3 | ||
|
|
a30221c5bb | ||
|
|
411e843fc4 | ||
|
|
8575d5b35c | ||
|
|
ba16e41160 | ||
|
|
708d5229ae | ||
|
|
fb4a7d65d7 | ||
|
|
d7353e6e99 | ||
|
|
48113cfaba | ||
|
|
c0b5754ef7 | ||
|
|
f2fb498c69 | ||
|
|
91e8e0e511 | ||
|
|
dfff8d23cf | ||
|
|
103d9a68fa | ||
|
|
a814fe8c5f | ||
|
|
193401e754 | ||
|
|
e1aeabde44 | ||
|
|
6d1e61173b | ||
|
|
6f82b5be4a | ||
|
|
192f1b0e2b | ||
|
|
238a796e38 | ||
|
|
fe393ac355 | ||
|
|
3ea078baf6 | ||
|
|
eb3e1ae24f | ||
|
|
c2b20c585e | ||
|
|
07561964fc | ||
|
|
ce8c1ce5b0 | ||
|
|
ef60dcac31 | ||
|
|
73bd5a19aa | ||
|
|
fef974ca5c | ||
|
|
8dbf46913b | ||
|
|
e46b188fe8 | ||
|
|
e6b1f9a4c3 | ||
|
|
39cfc8c1c0 | ||
|
|
79e25e192c | ||
|
|
792089f523 | ||
|
|
34636caa2d | ||
|
|
2993437eaa | ||
|
|
0bcc8c0211 | ||
|
|
4b54d8e15e | ||
|
|
afe52595a9 | ||
|
|
4f417262e3 | ||
|
|
1db3b38104 | ||
|
|
bc47f50926 | ||
|
|
e36b5a099c | ||
|
|
025881d0e9 | ||
|
|
320d0a5f1b | ||
|
|
d382210fce | ||
|
|
7b62767e16 | ||
|
|
6568841bb0 | ||
|
|
e361f6b284 | ||
|
|
53766917ef | ||
|
|
2a255076f5 | ||
|
|
fb080e7853 | ||
|
|
0818841038 | ||
|
|
939baebfe7 | ||
|
|
326ba26522 | ||
|
|
ec0b510f1c | ||
|
|
be626f7c53 | ||
|
|
3096e4930e | ||
|
|
33bdf44a04 | ||
|
|
ccbe31c21f | ||
|
|
c6746499c1 | ||
|
|
e1229e375f | ||
|
|
be27499d39 | ||
|
|
56a2b564ef | ||
|
|
9a00877af9 | ||
|
|
92f2a1ca69 | ||
|
|
882903f2fa | ||
|
|
54d86dd73b | ||
|
|
b496714caa | ||
|
|
3f5175584b | ||
|
|
11fff226f3 | ||
|
|
93490a0fc1 | ||
|
|
0585c3e5fd | ||
|
|
0b74f2a007 | ||
|
|
59d98b9ef6 | ||
|
|
3522451600 | ||
|
|
fe03bacd6c | ||
|
|
1f46d5945b | ||
|
|
585d73bf7c | ||
|
|
9e84cebfdb | ||
|
|
d1a2bd67da | ||
|
|
7708429d35 | ||
|
|
6045911d95 | ||
|
|
1b212aa073 | ||
|
|
4d48166835 | ||
|
|
437bac370a | ||
|
|
546062d3a3 | ||
|
|
576b93c99f | ||
|
|
180275c4e0 | ||
|
|
379e4b68f5 | ||
|
|
74b4d81992 | ||
|
|
fea8f0d5fd | ||
|
|
0e5dab5eaf | ||
|
|
c550bc154f | ||
|
|
40fcb91206 | ||
|
|
c8554ff48c | ||
|
|
3d95cef08c | ||
|
|
9cd724cf5e | ||
|
|
eb7eb5ce68 | ||
|
|
418eeb642c | ||
|
|
8ac56d004d | ||
|
|
52a76583c5 | ||
|
|
b1d02cc94f | ||
|
|
b9b488b6d3 | ||
|
|
9a2d0238a8 | ||
|
|
5cc21690eb | ||
|
|
f80f65d58c | ||
|
|
df284fbe65 | ||
|
|
b632ebf129 | ||
|
|
4b9cd8e81d | ||
|
|
6c82f4ae9b | ||
|
|
87644fa46b | ||
|
|
22dc376392 | ||
|
|
4ef1fb5a24 | ||
|
|
be6fd80a1c | ||
|
|
c48a467b8e | ||
|
|
557edbb84a | ||
|
|
0cfc6e6d95 | ||
|
|
2978106991 | ||
|
|
8517f49745 | ||
|
|
6c76b4e2f8 | ||
|
|
c91bd60051 | ||
|
|
a8739bad76 | ||
|
|
2b97442f2e | ||
|
|
5997355e22 | ||
|
|
d8bd9845cc | ||
|
|
3d1bc143af | ||
|
|
72a25f825c | ||
|
|
c4e0354876 | ||
|
|
389e820878 | ||
|
|
a2f0186427 | ||
|
|
58d670a258 | ||
|
|
ca88669435 | ||
|
|
15a9b0f2be | ||
|
|
197bf15402 | ||
|
|
0bae242cbf | ||
|
|
3352b1090e | ||
|
|
c4d17dd231 | ||
|
|
5f78f67e39 | ||
|
|
b1d99bb6b6 | ||
|
|
8914e9fd03 | ||
|
|
8d1d728d88 | ||
|
|
59c14c747a | ||
|
|
ccdf29a5f8 | ||
|
|
a7e079ea16 | ||
|
|
a97bed9d22 | ||
|
|
0ce68e97a7 | ||
|
|
3f66230874 | ||
|
|
35d0a8a843 | ||
|
|
44c3d4d2dc | ||
|
|
167772fbca | ||
|
|
2f0b11673a | ||
|
|
c5aa6a2286 | ||
|
|
d5522c3480 | ||
|
|
c1e5e6781e | ||
|
|
dd086e5bfd | ||
|
|
213bb7c6ed | ||
|
|
0c88f98a3b | ||
|
|
23ae0a9838 | ||
|
|
0f78bea4a3 | ||
|
|
4b627bd29e | ||
|
|
e4510c76e5 | ||
|
|
122dd6c11e | ||
|
|
63a5280f8f | ||
|
|
07149f576a | ||
|
|
dbd2a43ab1 | ||
|
|
4a211a9117 | ||
|
|
18ebe165ba | ||
|
|
908e1cb11a | ||
|
|
5c6c57ed89 | ||
|
|
47094fd83f | ||
|
|
67153f897e | ||
|
|
f2528dc3ac | ||
|
|
935bc162e1 | ||
|
|
d5954aff08 | ||
|
|
e98b89651e | ||
|
|
516f90abdb | ||
|
|
c09320c651 | ||
|
|
6d0812b567 | ||
|
|
b05154218c | ||
|
|
c8ae3de610 | ||
|
|
ae96aa0a6d | ||
|
|
1e85749e6e | ||
|
|
b624ed5050 | ||
|
|
b865aca03a | ||
|
|
2e7714e80c | ||
|
|
39df4f0923 | ||
|
|
eff3e01ec3 | ||
|
|
13d4504dfc | ||
|
|
9342bf685e | ||
|
|
f804c087e4 | ||
|
|
0102360e92 | ||
|
|
ca481322d4 | ||
|
|
654a7eab62 | ||
|
|
4e5b0b7eec | ||
|
|
9aaafddf04 | ||
|
|
9cd282e001 | ||
|
|
bd5dc855af | ||
|
|
31218166fc | ||
|
|
6bdecdbc5a | ||
|
|
45e6e71652 | ||
|
|
3abb32c3ba | ||
|
|
6e65343895 | ||
|
|
d1977c679b | ||
|
|
0ee44ef384 | ||
|
|
1c8f0e0fc5 | ||
|
|
17a557dfd5 | ||
|
|
8c751d48a2 | ||
|
|
5b8a7340bb | ||
|
|
33784e612a | ||
|
|
fdd5f8ff83 | ||
|
|
63616a5fce | ||
|
|
dfc00271d1 | ||
|
|
1143050ea6 | ||
|
|
5ab4a9330a | ||
|
|
2cd7c719ef | ||
|
|
ed00129866 | ||
|
|
10843805ac | ||
|
|
f0e15272b2 | ||
|
|
d4c4537b33 | ||
|
|
ba1183bb6e | ||
|
|
85ee5284f5 | ||
|
|
3795e37410 | ||
|
|
d396d8dae3 | ||
|
|
8da117b086 | ||
|
|
6e43145382 | ||
|
|
be53e37b15 | ||
|
|
3160d6ac08 | ||
|
|
d1f388ec93 | ||
|
|
5bd07f8e88 | ||
|
|
3ea6f730ac | ||
|
|
083770cb39 | ||
|
|
8756ad63dd | ||
|
|
c4566aa5d3 | ||
|
|
2791ccbe02 | ||
|
|
5f423906de | ||
|
|
4844fa3481 | ||
|
|
0f5fecd516 | ||
|
|
a1c82ac5fd | ||
|
|
1c85901cc4 | ||
|
|
b1c707e551 | ||
|
|
2b1028bdad | ||
|
|
bab5ad623c | ||
|
|
49e4258102 | ||
|
|
81e219827e | ||
|
|
02ac374640 | ||
|
|
025d810b45 | ||
|
|
4ccb613396 | ||
|
|
9025be814a | ||
|
|
fbc0256825 | ||
|
|
8580a74b37 | ||
|
|
b6e2f4dbf8 | ||
|
|
702f485587 | ||
|
|
6e47c1e05b | ||
|
|
d4145772b5 | ||
|
|
00a08beee9 | ||
|
|
5b55a46550 | ||
|
|
2cc9563cf8 | ||
|
|
8aec671860 | ||
|
|
990b12bc8e | ||
|
|
11f12bc981 | ||
|
|
08e11284fb | ||
|
|
f531011e85 | ||
|
|
d18813be30 | ||
|
|
5f76e201f0 | ||
|
|
dcd0191d7e | ||
|
|
8936f3496e | ||
|
|
f97927a47e | ||
|
|
6819c1e444 | ||
|
|
6487d6febe | ||
|
|
373904f865 | ||
|
|
0912015fb9 | ||
|
|
c15cfb4bd9 | ||
|
|
66c95e8081 | ||
|
|
843fc69927 | ||
|
|
50ea4a1072 | ||
|
|
1e47eea6e3 | ||
|
|
6289238cd6 | ||
|
|
97fdd0e2eb | ||
|
|
201da1f50a | ||
|
|
51c189394d | ||
|
|
2e257fff2a | ||
|
|
4776f749be | ||
|
|
04053d39a0 | ||
|
|
ef9f7f113f | ||
|
|
2d33bba3c0 | ||
|
|
36b38cea74 | ||
|
|
40f446a499 | ||
|
|
e839771ddf | ||
|
|
ae2c2be1a5 | ||
|
|
bf37487dca | ||
|
|
8d45c1592b | ||
|
|
862fa0d514 | ||
|
|
27c028cf27 | ||
|
|
5b7faca7db | ||
|
|
d29bc712b1 | ||
|
|
0b131d5a31 | ||
|
|
90b434c260 | ||
|
|
846b158304 | ||
|
|
95604a90e8 | ||
|
|
f5a2a58ce3 | ||
|
|
78c284e05d | ||
|
|
299f55b0d1 | ||
|
|
52f0387cac | ||
|
|
606e5a0a5f | ||
|
|
15b8d8b96a | ||
|
|
67e52ea9c5 | ||
|
|
7240ecbeb0 | ||
|
|
a952ac17be | ||
|
|
40e47bf767 | ||
|
|
0afe58a06e | ||
|
|
2069271384 | ||
|
|
014db3fb03 | ||
|
|
5aa47fb1fa | ||
|
|
1962991937 | ||
|
|
5be7f1ef8a | ||
|
|
48a6ff14a4 | ||
|
|
ade710a9fd | ||
|
|
31d38d2cfe | ||
|
|
380e3de140 | ||
|
|
fc8bf269e9 | ||
|
|
7696074fa9 | ||
|
|
bea61fc37c | ||
|
|
41dac805f5 | ||
|
|
2207a55107 | ||
|
|
196f8a68f6 | ||
|
|
0d13b4ec4c | ||
|
|
f1537e2041 | ||
|
|
47cf44cc70 | ||
|
|
1cd75cccfc | ||
|
|
d10a889a68 | ||
|
|
64476280ed | ||
|
|
b1bcde3137 | ||
|
|
b02f9befcd | ||
|
|
0f1ea7e490 | ||
|
|
f9317d65b3 | ||
|
|
2cf0359ffe | ||
|
|
35885e5a70 | ||
|
|
0585b1d75a | ||
|
|
a25fc52818 | ||
|
|
52581f8644 | ||
|
|
9412b9c2ca | ||
|
|
65230bd117 | ||
|
|
db5cf5851d | ||
|
|
3c3fd7a795 | ||
|
|
4f52be4db9 | ||
|
|
512236d705 | ||
|
|
d57986724e | ||
|
|
4e39d3dfe1 | ||
|
|
a21bc23139 | ||
|
|
62d54d8091 | ||
|
|
17559c737b | ||
|
|
59fd48c226 | ||
|
|
da78c42f88 | ||
|
|
a07ccbae9a | ||
|
|
2a2598dbf2 | ||
|
|
1fb78afc29 | ||
|
|
b2cba7b707 | ||
|
|
8dd09e31d2 | ||
|
|
806c3d7330 | ||
|
|
cac1d13fda | ||
|
|
80153decd1 | ||
|
|
2695eb9d1a | ||
|
|
20184483df | ||
|
|
adb4aeb609 | ||
|
|
70c2b587fc | ||
|
|
a50ddd7ab9 | ||
|
|
4a04ba813a | ||
|
|
1aa2c318e7 | ||
|
|
e1ec3cf893 | ||
|
|
8058dc9127 | ||
|
|
144f29638c | ||
|
|
7081b0340f | ||
|
|
263096d1f6 | ||
|
|
e577ab105e | ||
|
|
04540f82e5 | ||
|
|
2e6ddd6032 | ||
|
|
a197aac2f6 | ||
|
|
15a2add0f8 | ||
|
|
648ad4db6f | ||
|
|
4bcc0a0a7a | ||
|
|
542f717bf9 | ||
|
|
b5cc8b6c59 | ||
|
|
cba1350886 | ||
|
|
fe46bc47d7 | ||
|
|
e11d206a82 | ||
|
|
8de8c8f6f7 | ||
|
|
4954df5859 | ||
|
|
a3ef9dd53b | ||
|
|
d6c33e1757 | ||
|
|
7033234a48 | ||
|
|
c7618a9b80 | ||
|
|
312035f58a | ||
|
|
7e6a7f310d | ||
|
|
1ac9b7548b | ||
|
|
eb7eff4fc7 | ||
|
|
072be3300f | ||
|
|
9d7b1d3127 | ||
|
|
e850ca67f1 | ||
|
|
2a100ee9ee | ||
|
|
8f83c0a2cb | ||
|
|
d7e7761141 | ||
|
|
a97d7175a6 | ||
|
|
4f25d75d4b | ||
|
|
184248eb0e | ||
|
|
319119943f | ||
|
|
60304f972e | ||
|
|
d97c174f50 | ||
|
|
ed07c5424d | ||
|
|
fb187d1a60 | ||
|
|
71e0ddc94a | ||
|
|
b89d0d1cce | ||
|
|
d1f5ded1d9 | ||
|
|
fb06364014 | ||
|
|
02a77f0567 | ||
|
|
eb81761b13 | ||
|
|
96c70d91ca | ||
|
|
488811157e | ||
|
|
e225e4bcab | ||
|
|
1c1c5d72d3 | ||
|
|
87a8c80fcb | ||
|
|
a8977df4d9 | ||
|
|
4953daa016 | ||
|
|
5ab5b3b43a | ||
|
|
0bf55e6063 | ||
|
|
24e6d1e18e | ||
|
|
45142868ec | ||
|
|
8b9382998d | ||
|
|
c482999898 | ||
|
|
6bf677e7de | ||
|
|
d666e9bd13 | ||
|
|
77f15428c9 | ||
|
|
111e66ae64 | ||
|
|
6a4a9435d1 | ||
|
|
55a28d6946 | ||
|
|
ddecffd918 | ||
|
|
6afdc336ba | ||
|
|
c9233f8429 | ||
|
|
8df1e58209 | ||
|
|
d69f875261 | ||
|
|
b12ab31ae3 | ||
|
|
cfd3bcb21e | ||
|
|
90d42148de | ||
|
|
469133e8df | ||
|
|
785c938106 | ||
|
|
52a4ccee18 | ||
|
|
aa621f1c04 | ||
|
|
0fed35a4b7 | ||
|
|
4517dcd439 | ||
|
|
c5c4f6d40b | ||
|
|
0419b06ca4 | ||
|
|
90831af981 | ||
|
|
ba6325f24f | ||
|
|
2025946247 | ||
|
|
e92bd614c0 | ||
|
|
f93fdb5e09 | ||
|
|
d5b9a790fe | ||
|
|
70260273a4 | ||
|
|
1224cd9d25 | ||
|
|
0682d4371e | ||
|
|
7716d26d46 | ||
|
|
857d6ce3a1 | ||
|
|
af2ef61c49 | ||
|
|
df411b3f28 | ||
|
|
71db243b0d | ||
|
|
67cf625608 | ||
|
|
c61b2121b5 | ||
|
|
859d0f2dfe | ||
|
|
1a2e6aabac | ||
|
|
726aa5b0f5 | ||
|
|
5204c14e6d | ||
|
|
2daaebf3aa | ||
|
|
dd3984eae9 | ||
|
|
6b8642b662 | ||
|
|
5c041c0ba9 | ||
|
|
d7a9def160 | ||
|
|
ef8111ece7 | ||
|
|
90f6cb1158 | ||
|
|
effbf99281 | ||
|
|
81861aee05 | ||
|
|
6f7da59b77 | ||
|
|
a96c64d966 | ||
|
|
79d39e7f4d | ||
|
|
b86a97019f | ||
|
|
896f7a8306 | ||
|
|
a7ac109e4e | ||
|
|
79108f4c3d | ||
|
|
6dcba49ff1 | ||
|
|
8b4a8493d0 | ||
|
|
b65ff768bc | ||
|
|
f72116883b | ||
|
|
4e305e644b | ||
|
|
89d9b25090 | ||
|
|
dda1d9544c | ||
|
|
52a9e6268e | ||
|
|
8367b24bc5 | ||
|
|
8df26b132b | ||
|
|
64fb06f892 | ||
|
|
5bf4c505db | ||
|
|
5158876bfd | ||
|
|
f531faf163 | ||
|
|
c0c9acccfd | ||
|
|
17e5dd6131 | ||
|
|
e9107907e5 | ||
|
|
ba8642aeb7 | ||
|
|
5ffa4d7232 | ||
|
|
2571d00535 | ||
|
|
f9a563d495 | ||
|
|
08dcae0dab | ||
|
|
5ac1bc13cb | ||
|
|
f5e1ef650d | ||
|
|
d25e0cd9b0 | ||
|
|
4f27799456 | ||
|
|
97d1cff315 | ||
|
|
a4631a3ecf | ||
|
|
2569b12b9c | ||
|
|
bf1cce6f9b | ||
|
|
b043bc5eb4 | ||
|
|
d122617dd4 | ||
|
|
6b8181acb7 | ||
|
|
f609a45354 | ||
|
|
60db1111c0 | ||
|
|
40b2b3a6f3 | ||
|
|
f1d263a318 | ||
|
|
f0614a57f8 | ||
|
|
bf7a2884fb | ||
|
|
c0eaadfc42 | ||
|
|
22e43aa631 | ||
|
|
c4e51a4cfe | ||
|
|
7d96a7e3fe | ||
|
|
9842fbf760 | ||
|
|
a102fb1df8 | ||
|
|
bd2c202674 | ||
|
|
75f3fbdd65 | ||
|
|
71f23ef354 | ||
|
|
5b98816751 | ||
|
|
0b176750bd | ||
|
|
f0989fc754 | ||
|
|
c9f90def0a | ||
|
|
57c4f28f20 | ||
|
|
d731fa2e21 | ||
|
|
e93c75a5d4 | ||
|
|
8e18f11965 | ||
|
|
e3871ca907 | ||
|
|
dcfcde2ec8 | ||
|
|
137719522a | ||
|
|
bd3c5702a7 | ||
|
|
f68e252345 | ||
|
|
1e5158045f | ||
|
|
99e12ae4b5 | ||
|
|
5f3b460586 | ||
|
|
9b1647ebae | ||
|
|
307805b64f | ||
|
|
f02d6bddd1 | ||
|
|
eb02170338 | ||
|
|
d301bfe4a2 | ||
|
|
fc123303ac | ||
|
|
aec33b3d63 | ||
|
|
7e9fd2114b | ||
|
|
c30bdff939 | ||
|
|
cfc656294e | ||
|
|
007db2c327 | ||
|
|
5bbaf78c3f | ||
|
|
57230d7f22 | ||
|
|
5f309d0018 | ||
|
|
d66e1cccf8 | ||
|
|
2450b4653a | ||
|
|
eb3378396f | ||
|
|
1f5cc25974 | ||
|
|
ec5812a748 | ||
|
|
10a5a5880a | ||
|
|
2fa1c17cd9 | ||
|
|
b642c5fe1f | ||
|
|
f3fa363443 | ||
|
|
e6f878ee71 | ||
|
|
8d939691a3 | ||
|
|
b465e0cfc0 | ||
|
|
73b3b32062 | ||
|
|
6e31d1f5be | ||
|
|
14fe4669e7 | ||
|
|
dc6c04b243 | ||
|
|
ef57f8bd51 | ||
|
|
fbe8e3b0b2 | ||
|
|
1c164ab442 | ||
|
|
e738ec31ca | ||
|
|
07b073ddb3 | ||
|
|
0f08cc6d55 | ||
|
|
7d3c6f1c43 | ||
|
|
cd22fdc28d | ||
|
|
5ae48f85c0 | ||
|
|
cbed768b8f | ||
|
|
f6753a0f10 | ||
|
|
efdd70c7b5 | ||
|
|
fccb2eb2e8 | ||
|
|
1464b166a4 | ||
|
|
f993ffbb07 | ||
|
|
ef9bb0213b | ||
|
|
309e23515e | ||
|
|
249efd4285 | ||
|
|
12cd495d55 | ||
|
|
33bd49af81 | ||
|
|
6e50c46102 | ||
|
|
88bf803297 | ||
|
|
9e4a17baaf | ||
|
|
2abd6f7d58 | ||
|
|
7696398231 | ||
|
|
886ffcc155 | ||
|
|
a45ced7739 | ||
|
|
125983558b | ||
|
|
903538c76e | ||
|
|
d447d60fc6 | ||
|
|
e5f66b4902 | ||
|
|
0f4c4c1163 | ||
|
|
eda0c0c194 | ||
|
|
309b1d368b | ||
|
|
c513119bba | ||
|
|
a30286502c | ||
|
|
317bab9f1d | ||
|
|
2fba248ebe | ||
|
|
e102aea751 | ||
|
|
24cb764d61 | ||
|
|
cb28bdcdb0 | ||
|
|
bcf7a8aed2 | ||
|
|
391dd86c3b | ||
|
|
b0ce31b4e4 | ||
|
|
2dbaba7d73 | ||
|
|
923eb7d474 | ||
|
|
58b21e4fca | ||
|
|
ef718f02e4 | ||
|
|
c8add463c4 | ||
|
|
203f606c38 | ||
|
|
e7badb9428 | ||
|
|
b816318106 | ||
|
|
1ceb031b58 | ||
|
|
352e1b28a1 | ||
|
|
80dbc7dd2c | ||
|
|
c8e7539313 | ||
|
|
12796d0af8 | ||
|
|
b057d2127a | ||
|
|
9177867d07 | ||
|
|
9e6b838d0b | ||
|
|
12552fddf0 | ||
|
|
3bade62c8a | ||
|
|
c806b5a2df | ||
|
|
7f67f7118c | ||
|
|
7c9177095f | ||
|
|
233cb5c218 | ||
|
|
e6a0afae73 | ||
|
|
90767fce98 | ||
|
|
187bc72633 | ||
|
|
78b4b12713 | ||
|
|
b8e111e379 | ||
|
|
0e1c266f86 | ||
|
|
c6ef39a22d | ||
|
|
459b73018f | ||
|
|
97b7224885 | ||
|
|
a3ab0921b0 | ||
|
|
16dd802c2e | ||
|
|
6dad2d2fc6 | ||
|
|
edc1d07718 | ||
|
|
2d61706171 | ||
|
|
11d077c826 | ||
|
|
d19d7b81ec | ||
|
|
714200ad0e | ||
|
|
c76420664a | ||
|
|
7e506bb477 | ||
|
|
91c298c901 | ||
|
|
f73e548934 | ||
|
|
e62b309959 | ||
|
|
2132e67b36 | ||
|
|
0abfddd279 | ||
|
|
ba4564b4ef | ||
|
|
daf316ea1b | ||
|
|
f0d91950ad | ||
|
|
917c30a46a | ||
|
|
77149fc2aa | ||
|
|
47ce372f13 | ||
|
|
0ce36e8289 | ||
|
|
8afbc0944f | ||
|
|
b61b0af5d6 | ||
|
|
6a4ea692d4 | ||
|
|
d19e12ab5d | ||
|
|
74c6cf5ac6 | ||
|
|
33c8baaaba | ||
|
|
6cfcf21451 | ||
|
|
1289c53c1a | ||
|
|
d02e83ae2b | ||
|
|
8f2847ba69 | ||
|
|
730a03e9bd | ||
|
|
e4ca71e85b | ||
|
|
8f8a8a341a | ||
|
|
722391baf1 | ||
|
|
ee63ac8f9b | ||
|
|
1e23c4a376 | ||
|
|
c60bed8eef | ||
|
|
9484ddee2e | ||
|
|
402135b41a | ||
|
|
b0dbfa37f9 | ||
|
|
79f8fc1472 | ||
|
|
516f4f9cf4 | ||
|
|
62c5039ab9 | ||
|
|
b202b0874c | ||
|
|
debe5c665f | ||
|
|
f81420d77f | ||
|
|
b8e7dfa01e | ||
|
|
f7ca447368 | ||
|
|
a6880644aa | ||
|
|
0b8e6dafe5 | ||
|
|
99a3f5ee85 | ||
|
|
7749d98a14 | ||
|
|
8e8ccfe3c3 | ||
|
|
ad158ed5cc | ||
|
|
6e79237dc8 | ||
|
|
82adcfb971 | ||
|
|
6e64356175 | ||
|
|
e11cf2d964 | ||
|
|
c084c27b39 | ||
|
|
2c3225e6c7 | ||
|
|
4b772ed571 | ||
|
|
4f3df7ee86 | ||
|
|
c7be51a11b | ||
|
|
c4d8104db3 | ||
|
|
fbbb42c9d4 | ||
|
|
a746d9693a | ||
|
|
78aee89201 | ||
|
|
6de5310728 | ||
|
|
2b90181d3a | ||
|
|
91a5cc9a08 | ||
|
|
a0feea393a | ||
|
|
4c6b59fa47 | ||
|
|
ed4ce7b398 | ||
|
|
58ac43c754 | ||
|
|
5f724da8c5 | ||
|
|
c44fe07a07 | ||
|
|
c29b0e0a96 | ||
|
|
50a312b8da | ||
|
|
893fb4d54b | ||
|
|
6bad577781 | ||
|
|
2642319ea6 | ||
|
|
d123e1c919 | ||
|
|
c53171d942 | ||
|
|
e656be63f9 | ||
|
|
ee3c478239 | ||
|
|
b1feb9fb1e | ||
|
|
819008cf7e | ||
|
|
11f2e7e6ae | ||
|
|
414a37ed2b | ||
|
|
32c3bbd249 | ||
|
|
c6b413069d | ||
|
|
358e3a5963 | ||
|
|
25eae982de | ||
|
|
506d24c7a6 | ||
|
|
d81e1c999b | ||
|
|
a5e9221933 | ||
|
|
1199482372 | ||
|
|
b93aa79a05 | ||
|
|
7ddd456f02 | ||
|
|
814a234876 | ||
|
|
10d9804149 | ||
|
|
a60bbd12ed | ||
|
|
84df46289d | ||
|
|
52283194eb | ||
|
|
c8a6234aac | ||
|
|
3086335724 | ||
|
|
f857af873e | ||
|
|
888eb224a6 | ||
|
|
c49e87e1b7 | ||
|
|
d10562c823 | ||
|
|
54ea2948da | ||
|
|
ea47c08e70 | ||
|
|
79e755e1dd | ||
|
|
ddc3c754b0 | ||
|
|
5c85615515 | ||
|
|
f0c6d26155 | ||
|
|
4573629fc4 | ||
|
|
70f13e54bf | ||
|
|
12a1053dfa | ||
|
|
c3c0186658 | ||
|
|
8e76eb95a0 | ||
|
|
c7ae3ef156 | ||
|
|
2996040c6c | ||
|
|
3c8a79eed8 | ||
|
|
f00d96a21b | ||
|
|
773d1f2911 | ||
|
|
de1e91fc7f | ||
|
|
ff35659d5a | ||
|
|
a97604737b | ||
|
|
d52d94c6db | ||
|
|
370a855f08 | ||
|
|
c7f44b99e3 | ||
|
|
9bbbca5de9 | ||
|
|
33ef79d433 | ||
|
|
eccfe3e1f5 | ||
|
|
adcbb6ced7 | ||
|
|
c678c696a1 | ||
|
|
313bceb983 | ||
|
|
6b2e96430e | ||
|
|
ceef84e022 | ||
|
|
95644c9309 | ||
|
|
cbdc138df7 | ||
|
|
392c1f0f54 | ||
|
|
4e492725e1 | ||
|
|
65113ac775 | ||
|
|
983c716feb | ||
|
|
83c712ca60 | ||
|
|
2c1a5203a5 | ||
|
|
778b50f113 | ||
|
|
d29ab10a34 | ||
|
|
c6c54f9de4 | ||
|
|
c7afaef10c | ||
|
|
9d1eb66f19 | ||
|
|
ef076c0e15 | ||
|
|
56cf526c68 | ||
|
|
4efbee08b5 | ||
|
|
919c8c9527 | ||
|
|
5d63ad6474 | ||
|
|
31bac7d5ca | ||
|
|
3dbda3aac3 | ||
|
|
7c0cb7198b | ||
|
|
7adeba3690 | ||
|
|
2add585015 | ||
|
|
43615e98b5 | ||
|
|
05c198ebd6 | ||
|
|
806a75808d | ||
|
|
173a8bb2b6 | ||
|
|
ba9356af99 | ||
|
|
dc162f7fee | ||
|
|
fcedb24b8d | ||
|
|
a22a79572e | ||
|
|
178be45fb3 | ||
|
|
94ea0e5e8f | ||
|
|
88da8ce174 | ||
|
|
2cee189e53 | ||
|
|
8648db9583 | ||
|
|
b5dbb0282e | ||
|
|
766c3164a3 | ||
|
|
b48d6760fc | ||
|
|
dcad9d5863 | ||
|
|
2921ce9e61 | ||
|
|
22881e28cc | ||
|
|
9645228f03 | ||
|
|
5bde54b530 | ||
|
|
c47e98a659 | ||
|
|
ff030fa332 | ||
|
|
e899b4cefe | ||
|
|
b47dc528aa | ||
|
|
c5a1e87f75 | ||
|
|
c21d6af617 | ||
|
|
5b2eda28e3 | ||
|
|
a0df340b1e | ||
|
|
f5b586dbdc | ||
|
|
8205c87a96 | ||
|
|
fa73142b79 | ||
|
|
3fc987955e | ||
|
|
7df1a347a5 | ||
|
|
738c7db9ab | ||
|
|
0006c08f15 | ||
|
|
24eded6ef9 | ||
|
|
431b749d7a | ||
|
|
e7fbd27060 | ||
|
|
8eb5010104 | ||
|
|
1a94a68fc2 | ||
|
|
53a1677828 | ||
|
|
cb48d9e4a1 | ||
|
|
5f8447830a | ||
|
|
89d7476539 | ||
|
|
3925297d07 | ||
|
|
3ebfa9fc97 | ||
|
|
3e6eeb504d | ||
|
|
8756f1e4c7 | ||
|
|
ecb0b44ba8 | ||
|
|
09afdb7669 | ||
|
|
ce39d5ad17 | ||
|
|
89510f4a0c | ||
|
|
962cb07055 | ||
|
|
9f26f397a9 | ||
|
|
24d0dc1725 | ||
|
|
38f500f1c9 | ||
|
|
808a3cb16d | ||
|
|
63a406a432 | ||
|
|
a64cbe958d | ||
|
|
7d70e3c861 | ||
|
|
f976fdee28 | ||
|
|
829f3c932e | ||
|
|
750f46d1aa | ||
|
|
b2cf56e0ec | ||
|
|
204edd229e | ||
|
|
48995dba21 | ||
|
|
4c90250043 | ||
|
|
ebb4987146 | ||
|
|
520fa84265 | ||
|
|
4b2799fdd6 | ||
|
|
087a7ff95e | ||
|
|
1ea624d0c7 | ||
|
|
9fa1ae1340 | ||
|
|
c93a7fb38a | ||
|
|
889a2d09c3 | ||
|
|
924ff7b373 | ||
|
|
74f1f0addd | ||
|
|
0b362e3a4d | ||
|
|
2315fc9d9b | ||
|
|
1ae42b94b3 | ||
|
|
ba7598f559 | ||
|
|
5730e7bb59 | ||
|
|
54b7554b5a | ||
|
|
a4d1224d92 | ||
|
|
4ea9651624 | ||
|
|
a9de6879b8 | ||
|
|
51f5b3ab44 | ||
|
|
d88f554503 | ||
|
|
cc6d428cb7 | ||
|
|
d0cc58be3d | ||
|
|
2a72845576 | ||
|
|
45542053fe | ||
|
|
25b7eb3c7c | ||
|
|
4034c009bb | ||
|
|
c8c2dfff22 | ||
|
|
ad45e9b89e | ||
|
|
de31bcdf2e | ||
|
|
a158f365b9 | ||
|
|
3b8b2e0dc7 | ||
|
|
3829faf679 | ||
|
|
fdae4cdbbb | ||
|
|
b13bcab089 | ||
|
|
2f828ec720 | ||
|
|
6bee3e77fc | ||
|
|
0ace659fe2 | ||
|
|
07f70d0745 | ||
|
|
79df099f4c | ||
|
|
20febc2179 | ||
|
|
6780a0844d | ||
|
|
f8ddcc15b8 | ||
|
|
c5ceee22a9 | ||
|
|
e20b2c1aaf | ||
|
|
98087a051e | ||
|
|
0d8dd6ec33 | ||
|
|
edbf9c21ee | ||
|
|
f232562430 | ||
|
|
ae45f46b9e | ||
|
|
59552a7a76 | ||
|
|
1900ea3bb3 | ||
|
|
a922c6d525 | ||
|
|
3e310a17be | ||
|
|
cf0aad9fb6 | ||
|
|
56a112001a | ||
|
|
76532f7447 | ||
|
|
e5cb48c432 | ||
|
|
0a6b22dc55 | ||
|
|
ddec5aa559 | ||
|
|
44f5d27683 | ||
|
|
568aab1b67 | ||
|
|
355526da7d | ||
|
|
2094763beb | ||
|
|
50dcadd495 | ||
|
|
ad08971b7a | ||
|
|
e7f476d5c3 | ||
|
|
193e37d6e8 | ||
|
|
a9df16cf9b | ||
|
|
9f40e93fe6 | ||
|
|
f9f3e9d4d0 | ||
|
|
32d82fac9b | ||
|
|
69349c7c24 | ||
|
|
a23efc70ee | ||
|
|
ab94ca9684 | ||
|
|
b366441157 | ||
|
|
0491176315 | ||
|
|
473f0cc44b | ||
|
|
f2d7620308 | ||
|
|
766244bd81 | ||
|
|
07c0d04a14 | ||
|
|
0e3068559c | ||
|
|
41fa45c99e | ||
|
|
f64358b351 | ||
|
|
a2ea701f31 | ||
|
|
14582d2445 | ||
|
|
1c75e62804 | ||
|
|
1f2296a8a2 | ||
|
|
49d9e91492 | ||
|
|
a8e0de95b8 | ||
|
|
3dd804755b | ||
|
|
8e7ced72e5 | ||
|
|
81cd0d76c8 | ||
|
|
5a23c84951 | ||
|
|
7f39003c04 | ||
|
|
1a528238e2 | ||
|
|
e7afe0b153 | ||
|
|
2d4523d946 | ||
|
|
5ea042c863 | ||
|
|
62674aaff8 | ||
|
|
263f974120 | ||
|
|
da0bbcec48 | ||
|
|
4f892a37bd | ||
|
|
c7bb118a88 | ||
|
|
7a5d82dd48 | ||
|
|
6f507eb036 | ||
|
|
eb82c368e0 | ||
|
|
1d23e0c920 | ||
|
|
5c760a13a4 | ||
|
|
5e00d516fe | ||
|
|
15b46257e1 | ||
|
|
db7413acb6 | ||
|
|
cdb60adcdc | ||
|
|
28b45e1d87 | ||
|
|
78bcfdee64 | ||
|
|
842c9bfc41 | ||
|
|
8fce4ff27a | ||
|
|
eba7e1a7c7 | ||
|
|
714d546d1d | ||
|
|
caaa38f7c5 | ||
|
|
f78aa90ff1 | ||
|
|
d6a69d77e2 | ||
|
|
7acf1a5088 | ||
|
|
afc73e28d8 | ||
|
|
b178cf34b6 | ||
|
|
126e114d6f | ||
|
|
354c19f6ac | ||
|
|
f7fb338c95 | ||
|
|
07d937f508 | ||
|
|
e27b160acd | ||
|
|
9149a6d1e4 | ||
|
|
667863770f | ||
|
|
9b4bbb49b4 | ||
|
|
731afdc924 | ||
|
|
80205ba133 | ||
|
|
bd0c910830 | ||
|
|
fc4de71fe0 | ||
|
|
1ab84a1d27 | ||
|
|
fb8c5a764d | ||
|
|
dd70c2ef9a | ||
|
|
ad51795314 | ||
|
|
7d76e84953 | ||
|
|
c96e4ca121 | ||
|
|
f72885e5d7 | ||
|
|
8d9b94d3ef | ||
|
|
7c18b36521 | ||
|
|
eb5683d6e6 | ||
|
|
79cc049096 | ||
|
|
78fa3fcb07 | ||
|
|
2a4c7c81e7 | ||
|
|
1f9e3e9ba6 |
@@ -12,6 +12,7 @@ jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: GCC on Linux
|
||||
@@ -32,12 +33,12 @@ jobs:
|
||||
- name: OS X
|
||||
os: macos-latest
|
||||
install_expat: "yes"
|
||||
config: "--enable-debug --disable-flto --with-ssl=/usr/local/opt/openssl --with-libexpat=/usr/local/opt/expat"
|
||||
config: "--enable-debug --disable-flto --with-ssl=/opt/homebrew/opt/openssl --with-libexpat=/opt/homebrew/opt/expat"
|
||||
make_test: "yes"
|
||||
- name: Clang on OS X
|
||||
os: macos-latest
|
||||
install_expat: "yes"
|
||||
config: "CC=clang --enable-debug --disable-flto --with-ssl=/usr/local/opt/openssl --with-libexpat=/usr/local/opt/expat --disable-static"
|
||||
config: "CC=clang --enable-debug --disable-flto --with-ssl=/opt/homebrew/opt/openssl --with-libexpat=/opt/homebrew/opt/expat --disable-static"
|
||||
make_test: "yes"
|
||||
clang_analysis: "yes"
|
||||
- name: ubsan (gcc undefined behaviour sanitizer)
|
||||
@@ -48,15 +49,6 @@ jobs:
|
||||
os: ubuntu-latest
|
||||
config: 'CFLAGS="-DNDEBUG -g2 -O3 -fsanitize=address" --disable-flto --disable-static'
|
||||
make_test: "yes"
|
||||
- name: Apple iPhone on iOS, armv7
|
||||
os: macos-latest
|
||||
AUTOTOOLS_HOST: armv7-apple-ios
|
||||
OPENSSL_HOST: ios-cross
|
||||
IOS_SDK: iPhoneOS
|
||||
IOS_CPU: armv7s
|
||||
test_ios: "yes"
|
||||
config: "no"
|
||||
make: "no"
|
||||
- name: Apple iPhone on iOS, arm64
|
||||
os: macos-latest
|
||||
AUTOTOOLS_HOST: aarch64-apple-ios
|
||||
@@ -84,15 +76,6 @@ jobs:
|
||||
test_ios: "yes"
|
||||
config: "no"
|
||||
make: "no"
|
||||
- name: iPhoneSimulator on OS X, i386
|
||||
os: macos-latest
|
||||
AUTOTOOLS_HOST: i386-apple-ios
|
||||
OPENSSL_HOST: iphoneos-cross
|
||||
IOS_SDK: iPhoneSimulator
|
||||
IOS_CPU: i386
|
||||
test_ios: "yes"
|
||||
config: "no"
|
||||
make: "no"
|
||||
- name: iPhoneSimulator on OS X, x86_64
|
||||
os: macos-latest
|
||||
AUTOTOOLS_HOST: x86_64-apple-ios
|
||||
@@ -161,13 +144,44 @@ jobs:
|
||||
test_windows: "yes"
|
||||
config: "no"
|
||||
make: "no"
|
||||
- name: FreeBSD
|
||||
os: ubuntu-latest
|
||||
config: "no"
|
||||
make: "no"
|
||||
with_cross_platform_action: "yes"
|
||||
cross_platform_os: "freebsd"
|
||||
cross_platform_arch: "x86-64"
|
||||
cross_platform_version: "14.1"
|
||||
cross_platform_config: "--enable-debug --disable-flto --with-libevent --disable-static"
|
||||
- name: OpenBSD
|
||||
os: ubuntu-latest
|
||||
config: "no"
|
||||
make: "no"
|
||||
with_cross_platform_action: "yes"
|
||||
cross_platform_os: "openbsd"
|
||||
cross_platform_arch: "x86-64"
|
||||
cross_platform_version: "7.5"
|
||||
cross_platform_config: "--enable-debug --disable-flto --with-libevent --disable-static"
|
||||
- name: NetBSD
|
||||
os: ubuntu-latest
|
||||
config: "no"
|
||||
make: "no"
|
||||
with_cross_platform_action: "yes"
|
||||
cross_platform_os: "netbsd"
|
||||
cross_platform_arch: "x86-64"
|
||||
cross_platform_version: "10.0"
|
||||
cross_platform_config: "--enable-debug --disable-flto --with-libevent --disable-static"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: false
|
||||
persist-credentials: false
|
||||
- name: test_windows
|
||||
if: ${{ matrix.test_windows == 'yes' }}
|
||||
env:
|
||||
LIBEXPAT_FNAME: expat-2.7.0
|
||||
LIBEXPAT_VERSION_DIR: R_2_7_0
|
||||
shell: bash
|
||||
run: |
|
||||
export unboundpath=`pwd`
|
||||
@@ -175,25 +189,32 @@ jobs:
|
||||
cd ..
|
||||
export prepath=`pwd`
|
||||
echo prepath=${prepath}
|
||||
#echo "curl cpanm"
|
||||
#curl -L -k -s -S -o cpanm https://cpanmin.us/
|
||||
#echo "perl cpanm Pod::Usage"
|
||||
#perl cpanm Pod::Usage
|
||||
# parralel build option
|
||||
export MINJ="-j4"
|
||||
echo "choco install winflexbison3"
|
||||
choco install winflexbison3
|
||||
echo 'LEX="win_flex"'
|
||||
export LEX="win_flex"
|
||||
echo 'YACC="win_bison -y"'
|
||||
export YACC="win_bison -y"
|
||||
mkdir openssl
|
||||
echo "curl openssl"
|
||||
curl -L -k -s -S -o openssl-1.1.1j.tar.gz https://www.openssl.org/source/openssl-1.1.1j.tar.gz
|
||||
tar xzf openssl-1.1.1j.tar.gz
|
||||
cd openssl-1.1.1j
|
||||
curl -L -k -s -S -o openssl-3.2.0.tar.gz https://www.openssl.org/source/openssl-3.2.0.tar.gz
|
||||
tar xzf openssl-3.2.0.tar.gz
|
||||
cd openssl-3.2.0
|
||||
# remove pod::Usage because we do not need -help or -man output
|
||||
# from the Configure script
|
||||
echo "Fixup ./Configure by removing use Pod::Usage require"
|
||||
sed -e 's/use Pod::Usage//' < Configure > Configure.fix
|
||||
echo "./Configure.fix no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix=\""$prepath/openssl\"""
|
||||
./Configure.fix no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix="$prepath/openssl"
|
||||
# from the Configure script, this fixes it for openssl 1.1.1
|
||||
#echo "Fixup ./Configure by removing use Pod::Usage require"
|
||||
#sed -e 's/use Pod::Usage//' < Configure > Configure.fix
|
||||
# ./Configure.fix no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix="$prepath/openssl"
|
||||
# pacman is used to install for msys2, with
|
||||
# C:/msys64/usr/bin/pacman -S perl
|
||||
echo "C:/msys64/usr/bin/perl ./Configure no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix=\""$prepath/openssl"\" PERL=\"C:/msys64/usr/bin/perl\""
|
||||
C:/msys64/usr/bin/perl ./Configure no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix="$prepath/openssl" PERL="C:/msys64/usr/bin/perl"
|
||||
# make the libs only, build faster
|
||||
echo "make build_libs"
|
||||
#make
|
||||
make build_libs
|
||||
#make $MINJ
|
||||
make $MINJ build_libs
|
||||
mv Makefile Makefile.orig
|
||||
# fixup \\ in the installtop to /.
|
||||
echo "fixup INSTALLTOP"
|
||||
@@ -205,9 +226,9 @@ jobs:
|
||||
cd ..
|
||||
mkdir expat
|
||||
echo "curl expat"
|
||||
curl -L -k -s -S -o expat-2.2.10.tar.gz https://github.com/libexpat/libexpat/releases/download/R_2_2_10/expat-2.2.10.tar.gz
|
||||
tar xzf expat-2.2.10.tar.gz
|
||||
cd expat-2.2.10
|
||||
curl -L -k -s -S -o $LIBEXPAT_FNAME.tar.gz https://github.com/libexpat/libexpat/releases/download/$LIBEXPAT_VERSION_DIR/$LIBEXPAT_FNAME.tar.gz
|
||||
tar xzf $LIBEXPAT_FNAME.tar.gz
|
||||
cd $LIBEXPAT_FNAME
|
||||
echo "./configure SHELL=/usr/bin/bash CONFIG_SHELL=/usr/bin/bash --prefix=\"$prepath/expat\" --exec-prefix=\"$prepath/expat\" --bindir=\"$prepath/expat/bin\" --includedir=\"$prepath/expat/include\" --mandir=\"$prepath/expat/man\" --libdir=\"$prepath/expat/lib\""
|
||||
./configure SHELL=/usr/bin/bash CONFIG_SHELL=/usr/bin/bash --prefix="$prepath/expat" --exec-prefix="$prepath/expat" --bindir="$prepath/expat/bin" --includedir="$prepath/expat/include" --mandir="$prepath/expat/man" --libdir="$prepath/expat/lib"
|
||||
# fixup SHELL is treated specially, but SHELZZ is not by make.
|
||||
@@ -225,7 +246,7 @@ jobs:
|
||||
mv xmlwf/Makefile xmlwf/Makefile.orig
|
||||
sed -e 's/SHELL/SHELLZZ/g' < xmlwf/Makefile.orig > xmlwf/Makefile
|
||||
echo "make"
|
||||
make
|
||||
make $MINJ
|
||||
echo "make install"
|
||||
make install
|
||||
cd ..
|
||||
@@ -233,7 +254,7 @@ jobs:
|
||||
cd unbound
|
||||
echo "./configure --enable-debug --enable-static-exe --disable-flto \"--with-ssl=$prepath/openssl\" --with-libexpat=\"$prepath/expat\" --disable-shared"
|
||||
./configure --enable-debug --enable-static-exe --disable-flto "--with-ssl=$prepath/openssl" --with-libexpat="$prepath/expat" --disable-shared
|
||||
make
|
||||
make $MINJ
|
||||
# specific test output
|
||||
#make testbound.exe; ./testbound.exe -s
|
||||
#make testbound; ./testbound.exe -p testdata/acl.rpl -o -vvvv
|
||||
@@ -326,6 +347,33 @@ jobs:
|
||||
echo "::group::make install"
|
||||
make install
|
||||
echo "::endgroup::"
|
||||
- name: cross-platform-action on ${{ matrix.cross_platform_os }} ${{ matrix.cross_platform_version }}
|
||||
if: ${{ matrix.with_cross_platform_action == 'yes' }}
|
||||
uses: cross-platform-actions/action@v1.0.0
|
||||
env:
|
||||
CROSS_PLATFORM_OS: ${{ matrix.cross_platform_os }}
|
||||
with:
|
||||
environment_variables: CROSS_PLATFORM_OS
|
||||
operating_system: ${{ matrix.cross_platform_os }}
|
||||
architecture: ${{ matrix.cross_platform_arch }}
|
||||
version: ${{ matrix.cross_platform_version }}
|
||||
shell: bash
|
||||
memory: 4G
|
||||
cpu_count: 2
|
||||
run: |
|
||||
set -e -x
|
||||
if test "$CROSS_PLATFORM_OS" = "freebsd"; then sudo pkg install -y openssl libevent expat; fi
|
||||
if test "$CROSS_PLATFORM_OS" = "openbsd"; then sudo pkg_add libevent; fi
|
||||
if test "$CROSS_PLATFORM_OS" = "netbsd"; then sudo pkgin -y install libevent; fi
|
||||
echo "::group::configure"
|
||||
./configure ${{ matrix.cross_platform_config }}
|
||||
echo "::endgroup::"
|
||||
echo "::group::make"
|
||||
make
|
||||
echo "::endgroup::"
|
||||
echo "::group::make test"
|
||||
make test
|
||||
echo "::endgroup::"
|
||||
- name: install libevent
|
||||
if: ${{ matrix.install_libevent == 'yes' }}
|
||||
run: sudo apt-get install libevent-dev
|
||||
|
||||
@@ -12,7 +12,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: configure
|
||||
run: ./configure --enable-debug
|
||||
- name: make
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
/config.status
|
||||
/dnstap/dnstap_config.h
|
||||
/dnscrypt/dnscrypt_config.h
|
||||
/util/configlexer.c
|
||||
/util/configparser.c
|
||||
/util/configparser.h
|
||||
/clubsyms.def
|
||||
/doc/example.conf
|
||||
/doc/libunbound.3
|
||||
/doc/unbound-anchor.8
|
||||
@@ -32,11 +36,13 @@
|
||||
/asynclook
|
||||
/delayer
|
||||
/dohclient
|
||||
/doqclient
|
||||
/lock-verify
|
||||
/memstats
|
||||
/perf
|
||||
/petal
|
||||
/pktview
|
||||
/readzone
|
||||
/streamtcp
|
||||
/unbound-dnstap-socket
|
||||
/testbound
|
||||
@@ -53,6 +59,7 @@
|
||||
/pythonmod/unboundmodule.py
|
||||
/testdata/result.*
|
||||
/testdata/.done-*
|
||||
/testdata/.skip-*
|
||||
/testdata/.perfstats.txt
|
||||
/doc/html
|
||||
/doc/xml
|
||||
|
||||
+865
-573
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -241,7 +241,7 @@ If you are working from a developer machine you probably already have the necess
|
||||
|
||||
The fourth step builds OpenSSL and Expat. OpenSSL and Expat are built for iOS using the scripts `contrib/ios/install_openssl.sh` and `contrib/ios/install_expat.sh`. The scripts download, configure and install the latest release version of the libraries. The libraries are configured with `--prefix="$IOS_PREFIX"` so the headers are placed in `$IOS_PREFIX/include` directory, and the libraries are placed in the `$IOS_PREFIX/lib` directory.
|
||||
|
||||
`IOS_PREFIX` is the value `$HOME/$IOS_SDK-$IOS_CPU`. The scheme handles both iOS SDKs and cpu architectures so the pair recieves a unique installation directory. The libraries will be installed in `$HOME/iPhoneOS-armv7s`, `$HOME/iPhoneOS-arm64`, `$HOME/iPhoneSimulator-i386`, etc. For Autotools projects, the appropriate `PKG_CONFIG_PATH` is exported.
|
||||
`IOS_PREFIX` is the value `$HOME/$IOS_SDK-$IOS_CPU`. The scheme handles both iOS SDKs and cpu architectures so the pair receives a unique installation directory. The libraries will be installed in `$HOME/iPhoneOS-armv7s`, `$HOME/iPhoneOS-arm64`, `$HOME/iPhoneSimulator-i386`, etc. For Autotools projects, the appropriate `PKG_CONFIG_PATH` is exported.
|
||||
|
||||
`PKG_CONFIG_PATH` is an important variable. It is the userland equivalent to sysroot, and allows Autotools to find non-system headers and libraries for an architecture. Typical `PKG_CONFIG_PATH` are `$HOME/iPhoneOS-armv7s/lib/pkgconfig` and `$HOME/iPhoneOS-arm64/lib/pkgconfig`.
|
||||
|
||||
|
||||
@@ -1,39 +1,45 @@
|
||||
# Unbound
|
||||
|
||||
[](https://travis-ci.org/NLnetLabs/unbound)
|
||||
[](https://github.com/NLnetLabs/unbound/actions)
|
||||
[](https://repology.org/project/unbound/versions)
|
||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:unbound)
|
||||
[](https://unbound.readthedocs.io/en/latest/?badge=latest)
|
||||
[](https://social.nlnetlabs.nl/@nlnetlabs)
|
||||
|
||||
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://lists.nlnetlabs.nl/mailman/listinfo/unbound-users).
|
||||
or post a message on our [community forum](https://community.nlnetlabs.nl/).
|
||||
You can learn more about Unbound by reading our
|
||||
[documentation](https://nlnetlabs.nl/documentation/unbound/).
|
||||
[documentation](https://unbound.docs.nlnetlabs.nl/).
|
||||
|
||||
## Compiling
|
||||
|
||||
Make sure you have the C toolchain, OpenSSL and its include files, and libexpat
|
||||
installed. Unbound can be compiled and installed using:
|
||||
installed.
|
||||
If building from the repository source you also need flex and bison 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
|
||||
You can use libevent if you want. libevent is useful when using many (e.g.,
|
||||
10000) outgoing ports.
|
||||
Use the `--with-libevent` configure option to compile Unbound with libevent
|
||||
support.
|
||||
|
||||
If not, the default builtin alternative opens max 256 ports at the same time
|
||||
and is equally capable and a little faster.
|
||||
|
||||
|
||||
## 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/).
|
||||
All of Unbound's configuration options are described in the `unbound.conf(5)`
|
||||
man page, which will be installed and is also available on the Unbound
|
||||
[documentation page](https://unbound.docs.nlnetlabs.nl/en/latest/manpages/unbound.conf.html)
|
||||
for the latest version.
|
||||
|
||||
An example configuration file is located in
|
||||
An example configuration file, with minimal documentation, is located in
|
||||
[doc/example.conf](https://github.com/NLnetLabs/unbound/blob/master/doc/example.conf.in).
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
NLnet Labs adheres to the straightforward, semantic versioning scheme that is
|
||||
commonly used in the software industry.
|
||||
|
||||
Support is provided in respect of the latest release, i.e. releases with the
|
||||
highest minor and patch version level. We do not backport security fixes to
|
||||
older (minor) versions. In the event a new major version is released (e.g. from
|
||||
3.2.18 to 4.0.0), support will also be provided on the latest minor version of
|
||||
the previous major version (3.2.18) for a period of one year from the release of
|
||||
the new major version (4.0.0).
|
||||
|
||||
In the event that, during this period, a new patch or minor version of the
|
||||
previous major version is released, then support on these versions will only be
|
||||
provided for the remainder of the one-year-period.
|
||||
|
||||
You can find detailed information on our software support policy here:
|
||||
|
||||
https://www.nlnetlabs.nl/support/software-support-policy/
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
We take security very seriously. If you have discovered a security vulnerability
|
||||
in one of our projects and you would like to report it to us, you can send an
|
||||
encrypted message to our Security Entry Point.
|
||||
|
||||
Details are described here:
|
||||
|
||||
https://www.nlnetlabs.nl/security-report/
|
||||
+218
-80
@@ -2,7 +2,21 @@
|
||||
# Copyright 2009, Wouter Wijngaards, NLnet Labs.
|
||||
# BSD licensed.
|
||||
#
|
||||
# Version 41
|
||||
# Version 51
|
||||
# 2025-11-06 Fix ACX_CHECK_NONSTRING_ATTRIBUTE to reject clang, that prints
|
||||
# a warning for 'unknown attribute' when nonstring is used.
|
||||
# 2025-09-29 add ac_cv_func_malloc_0_nonnull as a cache value for the malloc(0)
|
||||
# check by ACX_FUNC_MALLOC.
|
||||
# 2025-09-29 add ACX_CHECK_NONSTRING_ATTRIBUTE, AHX_CONFIG_NONSTRING_ATTRIBUTE.
|
||||
# 2024-01-16 fix to add -l:libssp.a to -lcrypto link check.
|
||||
# and check for getaddrinfo with only header.
|
||||
# 2024-01-15 fix to add crypt32 to -lcrypto link check when checking for gdi32.
|
||||
# 2023-05-04 fix to remove unused whitespace.
|
||||
# 2023-01-26 fix -Wstrict-prototypes.
|
||||
# 2022-09-01 fix checking if nonblocking sockets work on OpenBSD.
|
||||
# 2021-08-17 fix sed script in ssldir split handling.
|
||||
# 2021-08-17 fix for openssl to detect split version, with ssldir_include
|
||||
# and ssldir_lib output directories.
|
||||
# 2021-07-30 fix for openssl use of lib64 directory.
|
||||
# 2021-06-14 fix nonblocking test to use host instead of target for mingw test.
|
||||
# 2021-05-17 fix nonblocking socket test from grep on mingw32 to mingw for
|
||||
@@ -62,6 +76,7 @@
|
||||
# ACX_DEPFLAG - find cc dependency flags.
|
||||
# ACX_DETERMINE_EXT_FLAGS_UNBOUND - find out which flags enable BSD and POSIX.
|
||||
# ACX_CHECK_FORMAT_ATTRIBUTE - find cc printf format syntax.
|
||||
# ACX_CHECK_NONSTRING_ATTRIBUTE - find cc nonstring attribute syntax.
|
||||
# ACX_CHECK_UNUSED_ATTRIBUTE - find cc variable unused syntax.
|
||||
# ACX_CHECK_FLTO - see if cc supports -flto and use it if so.
|
||||
# ACX_LIBTOOL_C_ONLY - create libtool for C only, improved.
|
||||
@@ -83,6 +98,7 @@
|
||||
# ACX_FUNC_IOCTLSOCKET - find ioctlsocket, portably.
|
||||
# ACX_FUNC_MALLOC - check malloc, define replacement .
|
||||
# AHX_CONFIG_FORMAT_ATTRIBUTE - config.h text for format.
|
||||
# AHX_CONFIG_NONSTRING_ATTRIBUTE - config.h text for nonstring.
|
||||
# AHX_CONFIG_UNUSED_ATTRIBUTE - config.h text for unused.
|
||||
# AHX_CONFIG_FSEEKO - define fseeko, ftello fallback.
|
||||
# AHX_CONFIG_RAND_MAX - define RAND_MAX if needed.
|
||||
@@ -183,7 +199,7 @@ dnl cache=`echo $1 | sed 'y%.=/+- %___p__%'`
|
||||
AC_CACHE_VAL(cv_prog_cc_flag_needed_$cache,
|
||||
[
|
||||
echo '$2' > conftest.c
|
||||
echo 'void f(){}' >>conftest.c
|
||||
echo 'void f(void){}' >>conftest.c
|
||||
if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then
|
||||
eval "cv_prog_cc_flag_needed_$cache=no"
|
||||
else
|
||||
@@ -229,7 +245,7 @@ dnl DEPFLAG: set to flag that generates dependencies.
|
||||
AC_DEFUN([ACX_DEPFLAG],
|
||||
[
|
||||
AC_MSG_CHECKING([$CC dependency flag])
|
||||
echo 'void f(){}' >conftest.c
|
||||
echo 'void f(void){}' >conftest.c
|
||||
if test "`$CC -MM conftest.c 2>&1`" = "conftest.o: conftest.c"; then
|
||||
DEPFLAG="-MM"
|
||||
else
|
||||
@@ -268,7 +284,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_DEFAUL
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a;
|
||||
char **opts = NULL;
|
||||
struct timeval tv;
|
||||
@@ -305,7 +321,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_DEFAUL
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a;
|
||||
char **opts = NULL;
|
||||
struct timeval tv;
|
||||
@@ -331,7 +347,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG,
|
||||
[
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a = 0;
|
||||
return a;
|
||||
}
|
||||
@@ -341,7 +357,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED(-D_BSD_SOURCE -D_DEFAULT_SOURCE,
|
||||
[
|
||||
#include <ctype.h>
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a;
|
||||
a = isascii(32);
|
||||
return a;
|
||||
@@ -352,7 +368,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED(-D_GNU_SOURCE,
|
||||
[
|
||||
#include <netinet/in.h>
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
struct in6_pktinfo inf;
|
||||
int a = (int)sizeof(inf);
|
||||
return a;
|
||||
@@ -366,7 +382,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED(-D_GNU_SOURCE -D_FRSRESGID,
|
||||
[
|
||||
#include <unistd.h>
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a = setresgid(0,0,0);
|
||||
a = setresuid(0,0,0);
|
||||
return a;
|
||||
@@ -381,7 +397,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED(-D_POSIX_C_SOURCE=200112,
|
||||
#endif
|
||||
#include <netdb.h>
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a = 0;
|
||||
char *t;
|
||||
time_t time = 0;
|
||||
@@ -409,7 +425,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED(-D__EXTENSIONS__,
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a;
|
||||
char **opts = NULL;
|
||||
struct timeval tv;
|
||||
@@ -471,7 +487,7 @@ fi
|
||||
dnl Setup ATTR_FORMAT config.h parts.
|
||||
dnl make sure you call ACX_CHECK_FORMAT_ATTRIBUTE also.
|
||||
AC_DEFUN([AHX_CONFIG_FORMAT_ATTRIBUTE],
|
||||
[
|
||||
[
|
||||
#ifdef HAVE_ATTR_FORMAT
|
||||
# define ATTR_FORMAT(archetype, string_index, first_to_check) \
|
||||
__attribute__ ((format (archetype, string_index, first_to_check)))
|
||||
@@ -481,7 +497,7 @@ AC_DEFUN([AHX_CONFIG_FORMAT_ATTRIBUTE],
|
||||
])
|
||||
|
||||
dnl Check how to mark function arguments as unused.
|
||||
dnl result in HAVE_ATTR_UNUSED.
|
||||
dnl result in HAVE_ATTR_UNUSED.
|
||||
dnl Make sure you include AHX_CONFIG_UNUSED_ATTRIBUTE also.
|
||||
AC_DEFUN([ACX_CHECK_UNUSED_ATTRIBUTE],
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
@@ -516,6 +532,49 @@ if test $ac_cv_c_unused_attribute = yes; then
|
||||
fi
|
||||
])dnl
|
||||
|
||||
dnl Check how to mark function arguments as nonstring.
|
||||
dnl result in HAVE_ATTR_NONSTRING.
|
||||
dnl Make sure you include AHX_CONFIG_NONSTRING_ATTRIBUTE also.
|
||||
AC_DEFUN([ACX_CHECK_NONSTRING_ATTRIBUTE],
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
AC_REQUIRE([ACX_CHECK_ERROR_FLAGS])
|
||||
BAKCFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $ERRFLAG"
|
||||
AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "nonstring" attribute)
|
||||
AC_CACHE_VAL(ac_cv_c_nonstring_attribute,
|
||||
[ac_cv_c_nonstring_attribute=no
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>
|
||||
struct test {
|
||||
char __attribute__((nonstring)) s[1];
|
||||
};
|
||||
]], [[
|
||||
struct test t = { "1" };
|
||||
(void) t;
|
||||
]])],[ac_cv_c_nonstring_attribute="yes"],[ac_cv_c_nonstring_attribute="no"])
|
||||
CFLAGS="$BAKCFLAGS"
|
||||
])
|
||||
|
||||
dnl Setup ATTR_NONSTRING config.h parts.
|
||||
dnl make sure you call ACX_CHECK_NONSTRING_ATTRIBUTE also.
|
||||
AC_DEFUN([AHX_CONFIG_NONSTRING_ATTRIBUTE],
|
||||
[
|
||||
#if defined(DOXYGEN)
|
||||
# define ATTR_NONSTRING(x) x
|
||||
#elif defined(__cplusplus)
|
||||
# define ATTR_NONSTRING(x) __attribute__((nonstring)) x
|
||||
#elif defined(HAVE_ATTR_NONSTRING)
|
||||
# define ATTR_NONSTRING(x) __attribute__((nonstring)) x
|
||||
#else /* !HAVE_ATTR_NONSTRING */
|
||||
# define ATTR_NONSTRING(x) x
|
||||
#endif /* !HAVE_ATTR_NONSTRING */
|
||||
])
|
||||
|
||||
AC_MSG_RESULT($ac_cv_c_nonstring_attribute)
|
||||
if test $ac_cv_c_nonstring_attribute = yes; then
|
||||
AC_DEFINE(HAVE_ATTR_NONSTRING, 1, [Whether the C compiler accepts the "nonstring" attribute])
|
||||
fi
|
||||
])dnl
|
||||
|
||||
dnl Pre-fun for ACX_LIBTOOL_C_ONLY
|
||||
AC_DEFUN([ACX_LIBTOOL_C_PRE], [
|
||||
# skip these tests, we do not need them.
|
||||
@@ -647,6 +706,30 @@ AC_DEFUN([ACX_SSL_CHECKS], [
|
||||
withval=$1
|
||||
if test x_$withval != x_no; then
|
||||
AC_MSG_CHECKING(for SSL)
|
||||
if test -n "$withval"; then
|
||||
dnl look for openssl install with different version, eg.
|
||||
dnl in /usr/include/openssl11/openssl/ssl.h
|
||||
dnl and /usr/lib64/openssl11/libssl.so
|
||||
dnl with the --with-ssl=/usr/include/openssl11
|
||||
if test ! -f "$withval/include/openssl/ssl.h" -a -f "$withval/openssl/ssl.h"; then
|
||||
ssldir="$withval"
|
||||
found_ssl="yes"
|
||||
withval=""
|
||||
ssldir_include="$ssldir"
|
||||
dnl find the libdir
|
||||
ssldir_lib=`echo $ssldir | sed -e 's/include/lib/'`
|
||||
if test -f "$ssldir_lib/libssl.a" -o -f "$ssldir_lib/libssl.so"; then
|
||||
: # found here
|
||||
else
|
||||
ssldir_lib=`echo $ssldir | sed -e 's/include/lib64/'`
|
||||
if test -f "$ssldir_lib/libssl.a" -o -f "$ssldir_lib/libssl.so"; then
|
||||
: # found here
|
||||
else
|
||||
AC_MSG_ERROR([Could not find openssl lib file, $ssldir_lib/libssl.[so,a], pass like "/usr/local" or "/usr/include/openssl11"])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test x_$withval = x_ -o x_$withval = x_yes; then
|
||||
withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr"
|
||||
fi
|
||||
@@ -654,12 +737,12 @@ AC_DEFUN([ACX_SSL_CHECKS], [
|
||||
ssldir="$dir"
|
||||
if test -f "$dir/include/openssl/ssl.h"; then
|
||||
found_ssl="yes"
|
||||
AC_DEFINE_UNQUOTED([HAVE_SSL], [], [Define if you have the SSL libraries installed.])
|
||||
dnl assume /usr/include is already in the include-path.
|
||||
if test "$ssldir" != "/usr"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$ssldir/include"
|
||||
LIBSSL_CPPFLAGS="$LIBSSL_CPPFLAGS -I$ssldir/include"
|
||||
fi
|
||||
ssldir_include="$ssldir/include"
|
||||
if test ! -d "$ssldir/lib" -a -d "$ssldir/lib64"; then
|
||||
ssldir_lib="$ssldir/lib64"
|
||||
else
|
||||
ssldir_lib="$ssldir/lib"
|
||||
fi
|
||||
break;
|
||||
fi
|
||||
done
|
||||
@@ -667,20 +750,17 @@ AC_DEFUN([ACX_SSL_CHECKS], [
|
||||
AC_MSG_ERROR(Cannot find the SSL libraries in $withval)
|
||||
else
|
||||
AC_MSG_RESULT(found in $ssldir)
|
||||
AC_DEFINE_UNQUOTED([HAVE_SSL], [], [Define if you have the SSL libraries installed.])
|
||||
HAVE_SSL=yes
|
||||
dnl assume /usr is already in the lib and dynlib paths.
|
||||
if test "$ssldir" != "/usr" -a "$ssldir" != ""; then
|
||||
if test ! -d "$ssldir/lib" -a -d "$ssldir/lib64"; then
|
||||
LDFLAGS="$LDFLAGS -L$ssldir/lib64"
|
||||
LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir/lib64"
|
||||
ACX_RUNTIME_PATH_ADD([$ssldir/lib64])
|
||||
else
|
||||
LDFLAGS="$LDFLAGS -L$ssldir/lib"
|
||||
LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir/lib"
|
||||
ACX_RUNTIME_PATH_ADD([$ssldir/lib])
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl assume /usr is already in the include, lib and dynlib paths.
|
||||
if test "$ssldir" != "/usr"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$ssldir_include"
|
||||
LIBSSL_CPPFLAGS="$LIBSSL_CPPFLAGS -I$ssldir_include"
|
||||
LDFLAGS="$LDFLAGS -L$ssldir_lib"
|
||||
LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir_lib"
|
||||
ACX_RUNTIME_PATH_ADD([$ssldir_lib])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for EVP_sha256 in -lcrypto])
|
||||
LIBS="$LIBS -lcrypto"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto"
|
||||
@@ -705,40 +785,73 @@ AC_DEFUN([ACX_SSL_CHECKS], [
|
||||
]])],[
|
||||
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
||||
[If you have EVP_sha256])
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
LIBS="$BAKLIBS"
|
||||
LIBSSL_LIBS="$BAKSSLLIBS"
|
||||
LIBS="$LIBS -ldl"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -ldl])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
|
||||
int EVP_sha256(void);
|
||||
(void)EVP_sha256();
|
||||
]])],[
|
||||
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
||||
[If you have EVP_sha256])
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
LIBS="$BAKLIBS"
|
||||
LIBSSL_LIBS="$BAKSSLLIBS"
|
||||
LIBS="$LIBS -ldl -pthread"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -ldl -pthread])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
|
||||
int EVP_sha256(void);
|
||||
(void)EVP_sha256();
|
||||
]])],[
|
||||
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
||||
[If you have EVP_sha256])
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
|
||||
|
||||
LIBS="$LIBS -lgdi32 -lws2_32 -lcrypt32"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32 -lws2_32 -lcrypt32"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -lgdi32 -lws2_32 -lcrypt32])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
|
||||
int EVP_sha256(void);
|
||||
(void)EVP_sha256();
|
||||
]])],[
|
||||
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
||||
[If you have EVP_sha256])
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
LIBS="$BAKLIBS"
|
||||
LIBSSL_LIBS="$BAKSSLLIBS"
|
||||
|
||||
LIBS="$LIBS -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
|
||||
int EVP_sha256(void);
|
||||
(void)EVP_sha256();
|
||||
]])],[
|
||||
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
||||
[If you have EVP_sha256])
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
LIBS="$BAKLIBS"
|
||||
LIBSSL_LIBS="$BAKSSLLIBS"
|
||||
|
||||
LIBS="$LIBS -ldl"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -ldl])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
|
||||
int EVP_sha256(void);
|
||||
(void)EVP_sha256();
|
||||
]])],[
|
||||
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
||||
[If you have EVP_sha256])
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
LIBS="$BAKLIBS"
|
||||
LIBSSL_LIBS="$BAKSSLLIBS"
|
||||
LIBS="$LIBS -ldl -pthread"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -ldl -pthread])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
|
||||
int EVP_sha256(void);
|
||||
(void)EVP_sha256();
|
||||
]])],[
|
||||
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
||||
[If you have EVP_sha256])
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
|
||||
])
|
||||
])
|
||||
])
|
||||
])
|
||||
])
|
||||
])
|
||||
])
|
||||
fi
|
||||
@@ -752,13 +865,13 @@ AC_CHECK_HEADERS([openssl/rand.h],,, [AC_INCLUDES_DEFAULT])
|
||||
|
||||
dnl Check for SSL, where SSL is mandatory
|
||||
dnl Adds --with-ssl option, searches for openssl and defines HAVE_SSL if found
|
||||
dnl Setup of CPPFLAGS, CFLAGS. Adds -lcrypto to LIBS.
|
||||
dnl Setup of CPPFLAGS, CFLAGS. Adds -lcrypto to LIBS.
|
||||
dnl Checks main header files of SSL.
|
||||
dnl
|
||||
AC_DEFUN([ACX_WITH_SSL],
|
||||
[
|
||||
AC_ARG_WITH(ssl, AS_HELP_STRING([--with-ssl=pathname],[enable SSL (will check /usr/local/ssl
|
||||
/usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr)]),[
|
||||
/usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr or specify like /usr/include/openssl11)]),[
|
||||
],[
|
||||
withval="yes"
|
||||
])
|
||||
@@ -776,7 +889,7 @@ dnl
|
||||
AC_DEFUN([ACX_WITH_SSL_OPTIONAL],
|
||||
[
|
||||
AC_ARG_WITH(ssl, AS_HELP_STRING([--with-ssl=pathname],[enable SSL (will check /usr/local/ssl
|
||||
/usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr)]),[
|
||||
/usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr or specify like /usr/include/openssl11)]),[
|
||||
],[
|
||||
withval="yes"
|
||||
])
|
||||
@@ -809,7 +922,7 @@ dnl try to see if an additional _LARGEFILE_SOURCE 1 is needed to get fseeko
|
||||
ACX_CHECK_COMPILER_FLAG_NEEDED(-D_LARGEFILE_SOURCE=1,
|
||||
[
|
||||
#include <stdio.h>
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a = fseeko(stdin, 0, 0);
|
||||
return a;
|
||||
}
|
||||
@@ -834,7 +947,7 @@ char* (*f) () = getaddrinfo;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
int main() {
|
||||
int main(void) {
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
@@ -845,7 +958,7 @@ 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"
|
||||
if echo $LIBS | grep 'lws2_32' >/dev/null; then
|
||||
if echo "$LIBS" | grep 'lws2_32' >/dev/null; then
|
||||
:
|
||||
else
|
||||
LIBS="$LIBS -lws2_32"
|
||||
@@ -853,6 +966,24 @@ if test "$ac_cv_header_windows_h" = "yes"; then
|
||||
fi
|
||||
],
|
||||
dnl no quick getaddrinfo, try mingw32 and winsock2 library.
|
||||
dnl perhaps getaddrinfo needs only the include
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
],
|
||||
[
|
||||
(void)getaddrinfo(NULL, NULL, NULL, NULL);
|
||||
]
|
||||
)],
|
||||
[
|
||||
ac_cv_func_getaddrinfo="yes"
|
||||
AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
|
||||
USE_WINSOCK="1"
|
||||
],
|
||||
|
||||
ORIGLIBS="$LIBS"
|
||||
LIBS="$LIBS -lws2_32"
|
||||
AC_LINK_IFELSE(
|
||||
@@ -877,6 +1008,7 @@ ac_cv_func_getaddrinfo="no"
|
||||
LIBS="$ORIGLIBS"
|
||||
])
|
||||
)
|
||||
)
|
||||
|
||||
AC_MSG_RESULT($ac_cv_func_getaddrinfo)
|
||||
if test $ac_cv_func_getaddrinfo = yes; then
|
||||
@@ -898,7 +1030,7 @@ cache=`echo $1 | sed 'y%.=/+-%___p_%'`
|
||||
AC_CACHE_VAL(cv_cc_deprecated_$cache,
|
||||
[
|
||||
echo '$3' >conftest.c
|
||||
echo 'void f(){ $2 }' >>conftest.c
|
||||
echo 'void f(void){ $2 }' >>conftest.c
|
||||
if test -z "`$CC $CPPFLAGS $CFLAGS -c conftest.c 2>&1 | grep -e deprecated -e unavailable`"; then
|
||||
eval "cv_cc_deprecated_$cache=no"
|
||||
else
|
||||
@@ -939,6 +1071,9 @@ AC_LANG_SOURCE([[
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
@@ -1105,8 +1240,9 @@ dnl detect malloc and provide malloc compat prototype.
|
||||
dnl $1: unique name for compat code
|
||||
AC_DEFUN([ACX_FUNC_MALLOC],
|
||||
[
|
||||
AC_MSG_CHECKING([for GNU libc compatible malloc])
|
||||
AC_RUN_IFELSE([AC_LANG_PROGRAM(
|
||||
AC_CACHE_CHECK([for GNU libc compatible malloc],[ac_cv_func_malloc_0_nonnull],
|
||||
[
|
||||
AC_RUN_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#if defined STDC_HEADERS || defined HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
@@ -1114,14 +1250,16 @@ char *malloc ();
|
||||
#endif
|
||||
]], [ if(malloc(0) != 0) return 1;])
|
||||
],
|
||||
[AC_MSG_RESULT([no])
|
||||
AC_LIBOBJ(malloc)
|
||||
AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])] ,
|
||||
[AC_MSG_RESULT([yes])
|
||||
AC_DEFINE([HAVE_MALLOC], 1, [If have GNU libc compatible malloc])],
|
||||
[AC_MSG_RESULT([no (crosscompile)])
|
||||
AC_LIBOBJ(malloc)
|
||||
AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])] )
|
||||
[ac_cv_func_malloc_0_nonnull=no],
|
||||
[ac_cv_func_malloc_0_nonnull=yes],
|
||||
[ac_cv_func_malloc_0_nonnull="no (crosscompile)"])
|
||||
])
|
||||
AS_IF([test "$ac_cv_func_malloc_0_nonnull" = yes],
|
||||
[AC_DEFINE([HAVE_MALLOC], 1, [If have GNU libc compatible malloc])],
|
||||
[
|
||||
AC_LIBOBJ(malloc)
|
||||
AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])
|
||||
])
|
||||
])
|
||||
|
||||
dnl Define fallback for fseeko and ftello if needed.
|
||||
@@ -1289,7 +1427,7 @@ AC_DEFUN([AHX_CONFIG_W32_FD_SET_T],
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
#define FD_SET_T (u_int)
|
||||
#else
|
||||
#define FD_SET_T
|
||||
#define FD_SET_T
|
||||
#endif
|
||||
])
|
||||
|
||||
@@ -1327,7 +1465,7 @@ dnl $3: define value, 1
|
||||
AC_DEFUN([AHX_CONFIG_FLAG_OMITTED],
|
||||
[#if defined($1) && !defined($2)
|
||||
#define $2 $3
|
||||
[#]endif ])
|
||||
[#]endif])
|
||||
|
||||
dnl Wrapper for AHX_CONFIG_FLAG_OMITTED for -D style flags
|
||||
dnl $1: the -DNAME or -DNAME=value string.
|
||||
|
||||
+70
-18
@@ -9,7 +9,7 @@ AC_DEFUN([AC_PYTHON_DEVEL],[
|
||||
|
||||
AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]])
|
||||
if test -z "$PYTHON"; then
|
||||
AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path])
|
||||
AC_MSG_ERROR([Cannot find 'python$PYTHON_VERSION' in your system path. You can use the environment variable 'PYTHON_VERSION=version_number' for an explicit version.])
|
||||
PYTHON_VERSION=""
|
||||
fi
|
||||
|
||||
@@ -17,28 +17,75 @@ AC_DEFUN([AC_PYTHON_DEVEL],[
|
||||
PYTHON_VERSION=`$PYTHON -c "import sys; \
|
||||
print(sys.version.split()[[0]])"`
|
||||
fi
|
||||
# calculate the version number components.
|
||||
[
|
||||
v="$PYTHON_VERSION"
|
||||
PYTHON_VERSION_MAJOR=`echo $v | sed 's/[^0-9].*//'`
|
||||
if test -z "$PYTHON_VERSION_MAJOR"; then PYTHON_VERSION_MAJOR="0"; fi
|
||||
v=`echo $v | sed -e 's/^[0-9]*$//' -e 's/[0-9]*[^0-9]//'`
|
||||
PYTHON_VERSION_MINOR=`echo $v | sed 's/[^0-9].*//'`
|
||||
if test -z "$PYTHON_VERSION_MINOR"; then PYTHON_VERSION_MINOR="0"; fi
|
||||
v=`echo $v | sed -e 's/^[0-9]*$//' -e 's/[0-9]*[^0-9]//'`
|
||||
PYTHON_VERSION_PATCH=`echo $v | sed 's/[^0-9].*//'`
|
||||
if test -z "$PYTHON_VERSION_PATCH"; then PYTHON_VERSION_PATCH="0"; fi
|
||||
]
|
||||
|
||||
#
|
||||
# Check if you have distutils, else fail
|
||||
#
|
||||
AC_MSG_CHECKING([for the distutils Python package])
|
||||
if ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`; then
|
||||
# For some systems, sysconfig exists, but has the wrong paths,
|
||||
# on Debian 10, for python 2.7 and 3.7. So, we check the version,
|
||||
# and for older versions try distutils.sysconfig first. For newer
|
||||
# versions>=3.10, where distutils.sysconfig is deprecated, use
|
||||
# sysconfig first and then attempt the other one.
|
||||
py_distutils_first="no"
|
||||
if test $PYTHON_VERSION_MAJOR -lt 3; then
|
||||
py_distutils_first="yes"
|
||||
fi
|
||||
if test $PYTHON_VERSION_MAJOR -eq 3 -a $PYTHON_VERSION_MINOR -lt 10; then
|
||||
py_distutils_first="yes"
|
||||
fi
|
||||
|
||||
# Check if you have the first module
|
||||
if test "$py_distutils_first" = "yes"; then m="distutils"; else m="sysconfig"; fi
|
||||
sysconfig_module=""
|
||||
AC_MSG_CHECKING([for the $m Python module])
|
||||
if ac_modulecheck_result1=`$PYTHON -c "import $m" 2>&1`; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
sysconfig_module="$m"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([cannot import Python module "distutils".
|
||||
Please check your Python installation. The error was:
|
||||
$ac_distutils_result])
|
||||
PYTHON_VERSION=""
|
||||
fi
|
||||
fi
|
||||
|
||||
# if not found, try the other one.
|
||||
if test -z "$sysconfig_module"; then
|
||||
if test "$py_distutils_first" = "yes"; then m2="sysconfig"; else m2="distutils"; fi
|
||||
AC_MSG_CHECKING([for the $m2 Python module])
|
||||
if ac_modulecheck_result2=`$PYTHON -c "import $m2" 2>&1`; then
|
||||
AC_MSG_RESULT([yes])
|
||||
sysconfig_module="$m2"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([cannot import Python module "$m", or "$m2".
|
||||
Please check your Python installation. The errors are:
|
||||
$m
|
||||
$ac_modulecheck_result1
|
||||
$m2
|
||||
$ac_modulecheck_result2])
|
||||
PYTHON_VERSION=""
|
||||
fi
|
||||
fi
|
||||
if test "$sysconfig_module" = "distutils"; then sysconfig_module="distutils.sysconfig"; fi
|
||||
|
||||
#
|
||||
# Check for Python include path
|
||||
#
|
||||
AC_MSG_CHECKING([for Python include path])
|
||||
if test -z "$PYTHON_CPPFLAGS"; then
|
||||
python_path=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print(distutils.sysconfig.get_python_inc());"`
|
||||
if test "$sysconfig_module" = "sysconfig"; then
|
||||
python_path=`$PYTHON -c 'import sysconfig; \
|
||||
print(sysconfig.get_path("include"));'`
|
||||
else
|
||||
python_path=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print(distutils.sysconfig.get_python_inc());"`
|
||||
fi
|
||||
if test -n "${python_path}"; then
|
||||
python_path="-I$python_path"
|
||||
fi
|
||||
@@ -52,14 +99,14 @@ $ac_distutils_result])
|
||||
#
|
||||
AC_MSG_CHECKING([for Python library path])
|
||||
if test -z "$PYTHON_LDFLAGS"; then
|
||||
PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \
|
||||
PYTHON_LDFLAGS=`$PYTHON -c "from $sysconfig_module import *; \
|
||||
print('-L'+get_config_var('LIBDIR')+' -L'+get_config_var('LIBDEST')+' '+get_config_var('BLDLIBRARY'));"`
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_LDFLAGS])
|
||||
AC_SUBST([PYTHON_LDFLAGS])
|
||||
|
||||
if test -z "$PYTHON_LIBDIR"; then
|
||||
PYTHON_LIBDIR=`$PYTHON -c "from distutils.sysconfig import *; \
|
||||
PYTHON_LIBDIR=`$PYTHON -c "from $sysconfig_module import *; \
|
||||
print(get_config_var('LIBDIR'));"`
|
||||
fi
|
||||
|
||||
@@ -68,8 +115,13 @@ $ac_distutils_result])
|
||||
#
|
||||
AC_MSG_CHECKING([for Python site-packages path])
|
||||
if test -z "$PYTHON_SITE_PKG"; then
|
||||
PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print(distutils.sysconfig.get_python_lib(1,0));"`
|
||||
if test "$sysconfig_module" = "sysconfig"; then
|
||||
PYTHON_SITE_PKG=`$PYTHON -c 'import sysconfig; \
|
||||
print(sysconfig.get_path("platlib"));'`
|
||||
else
|
||||
PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print(distutils.sysconfig.get_python_lib(1,0));"`
|
||||
fi
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_SITE_PKG])
|
||||
AC_SUBST([PYTHON_SITE_PKG])
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_build_date_epoch.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_BUILD_DATE_EPOCH(VARIABLE[, FORMAT[, ACTION-IF-FAIL]])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Sets VARIABLE to a string representing the current time. It is
|
||||
# formatted according to FORMAT if specified, otherwise it is formatted as
|
||||
# the number of seconds (excluding leap seconds) since the UNIX epoch (01
|
||||
# Jan 1970 00:00:00 UTC).
|
||||
#
|
||||
# If the SOURCE_DATE_EPOCH environment variable is set, it uses the value
|
||||
# of that variable instead of the current time. See
|
||||
# https://reproducible-builds.org/specs/source-date-epoch). If
|
||||
# SOURCE_DATE_EPOCH is set but cannot be properly interpreted as a UNIX
|
||||
# timestamp, then execute ACTION-IF-FAIL if specified, otherwise error.
|
||||
#
|
||||
# VARIABLE is AC_SUBST-ed.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2016 Eric Bavier <bavier@member.fsf.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation, either version 3 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 2
|
||||
|
||||
AC_DEFUN([AX_BUILD_DATE_EPOCH],
|
||||
[dnl
|
||||
AC_MSG_CHECKING([for build time])
|
||||
ax_date_fmt="m4_default($2,%s)"
|
||||
AS_IF([test x"$SOURCE_DATE_EPOCH" = x],
|
||||
[$1=`date "+$ax_date_fmt"`],
|
||||
[ax_build_date=`date -u -d "@$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null \
|
||||
|| date -u -r "$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null`
|
||||
AS_IF([test x"$ax_build_date" = x],
|
||||
[m4_ifval([$3],
|
||||
[$3],
|
||||
[AC_MSG_ERROR([malformed SOURCE_DATE_EPOCH])])],
|
||||
[$1=$ax_build_date])])
|
||||
AC_MSG_RESULT([$$1])
|
||||
])dnl AX_BUILD_DATE_EPOCH
|
||||
@@ -1,39 +1,43 @@
|
||||
# ===========================================================================
|
||||
# http://autoconf-archive.cryp.to/ac_pkg_swig.html
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AC_PROG_SWIG([major.minor.micro])
|
||||
# AX_PKG_SWIG([major.minor.micro], [action-if-found], [action-if-not-found])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This macro searches for a SWIG installation on your system. If found you
|
||||
# should call SWIG via $(SWIG). You can use the optional first argument to
|
||||
# check if the version of the available SWIG is greater than or equal to
|
||||
# the value of the argument. It should have the format: N[.N[.N]] (N is a
|
||||
# number between 0 and 999. Only the first N is mandatory.)
|
||||
# This macro searches for a SWIG installation on your system. If found,
|
||||
# then SWIG is AC_SUBST'd; if not found, then $SWIG is empty. If SWIG is
|
||||
# found, then SWIG_LIB is set to the SWIG library path, and AC_SUBST'd.
|
||||
#
|
||||
# If the version argument is given (e.g. 1.3.17), AC_PROG_SWIG checks that
|
||||
# the swig package is this version number or higher.
|
||||
# You can use the optional first argument to check if the version of the
|
||||
# available SWIG is greater than or equal to the value of the argument. It
|
||||
# should have the format: N[.N[.N]] (N is a number between 0 and 999. Only
|
||||
# the first N is mandatory.) If the version argument is given (e.g.
|
||||
# 1.3.17), AX_PKG_SWIG checks that the swig package is this version number
|
||||
# or higher.
|
||||
#
|
||||
# As usual, action-if-found is executed if SWIG is found, otherwise
|
||||
# action-if-not-found is executed.
|
||||
#
|
||||
# In configure.in, use as:
|
||||
#
|
||||
# AC_PROG_SWIG(1.3.17)
|
||||
# SWIG_ENABLE_CXX
|
||||
# SWIG_MULTI_MODULE_SUPPORT
|
||||
# SWIG_PYTHON
|
||||
# AX_PKG_SWIG(1.3.17, [], [ AC_MSG_ERROR([SWIG is required to build..]) ])
|
||||
# AX_SWIG_ENABLE_CXX
|
||||
# AX_SWIG_MULTI_MODULE_SUPPORT
|
||||
# AX_SWIG_PYTHON
|
||||
#
|
||||
# LAST MODIFICATION
|
||||
#
|
||||
# 2008-04-12
|
||||
#
|
||||
# COPYLEFT
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Sebastian Huber <sebastian-huber@web.de>
|
||||
# Copyright (c) 2008 Alan W. Irwin <irwin@beluga.phys.uvic.ca>
|
||||
# Copyright (c) 2008 Alan W. Irwin
|
||||
# Copyright (c) 2008 Rafael Laboissiere <rafael@laboissiere.net>
|
||||
# Copyright (c) 2008 Andrew Collier <colliera@ukzn.ac.za>
|
||||
# Copyright (c) 2008 Andrew Collier
|
||||
# Copyright (c) 2011 Murray Cumming <murrayc@openismus.com>
|
||||
# Copyright (c) 2018 Reini Urban <rurban@cpan.org>
|
||||
# Copyright (c) 2021 Vincent Danjean <Vincent.Danjean@ens-lyon.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
@@ -46,7 +50,7 @@
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
@@ -57,17 +61,21 @@
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Macro Archive. When you make and
|
||||
# distribute a modified version of the Autoconf Macro, you may extend this
|
||||
# special exception to the GPL to apply to your modified version as well.
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
AC_DEFUN([AC_PROG_SWIG],[
|
||||
AC_PATH_PROG([SWIG],[swig])
|
||||
#serial 15
|
||||
|
||||
AC_DEFUN([AX_PKG_SWIG],[
|
||||
# Find path to the "swig" executable.
|
||||
AC_PATH_PROGS([SWIG],[swig swig3.0 swig2.0])
|
||||
if test -z "$SWIG" ; then
|
||||
AC_MSG_WARN([cannot find 'swig' program. You should look at http://www.swig.org])
|
||||
SWIG='echo "Error: SWIG is not installed. You should look at http://www.swig.org" ; false'
|
||||
elif test -n "$1" ; then
|
||||
AC_MSG_CHECKING([for SWIG version])
|
||||
m4_ifval([$3],[$3],[:])
|
||||
elif test -z "$1" ; then
|
||||
m4_ifval([$2],[$2],[:])
|
||||
else
|
||||
AC_MSG_CHECKING([SWIG version])
|
||||
[swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`]
|
||||
AC_MSG_RESULT([$swig_version])
|
||||
if test -n "$swig_version" ; then
|
||||
@@ -77,12 +85,12 @@ AC_DEFUN([AC_PROG_SWIG],[
|
||||
if test -z "$required_major" ; then
|
||||
[required_major=0]
|
||||
fi
|
||||
[required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
|
||||
[required=`echo $required. | sed 's/[0-9]*[^0-9]//'`]
|
||||
[required_minor=`echo $required | sed 's/[^0-9].*//'`]
|
||||
if test -z "$required_minor" ; then
|
||||
[required_minor=0]
|
||||
fi
|
||||
[required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
|
||||
[required=`echo $required. | sed 's/[0-9]*[^0-9]//'`]
|
||||
[required_patch=`echo $required | sed 's/[^0-9].*//'`]
|
||||
if test -z "$required_patch" ; then
|
||||
[required_patch=0]
|
||||
@@ -103,30 +111,28 @@ AC_DEFUN([AC_PROG_SWIG],[
|
||||
if test -z "$available_patch" ; then
|
||||
[available_patch=0]
|
||||
fi
|
||||
[badversion=0]
|
||||
if test $available_major -lt $required_major ; then
|
||||
[badversion=1]
|
||||
fi
|
||||
if test $available_major -eq $required_major \
|
||||
-a $available_minor -lt $required_minor ; then
|
||||
[badversion=1]
|
||||
fi
|
||||
if test $available_major -eq $required_major \
|
||||
-a $available_minor -eq $required_minor \
|
||||
-a $available_patch -lt $required_patch ; then
|
||||
[badversion=1]
|
||||
fi
|
||||
if test $badversion -eq 1 ; then
|
||||
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'
|
||||
# Convert the version tuple into a single number for easier comparison.
|
||||
# Using base 100 should be safe since SWIG internally uses BCD values
|
||||
# to encode its version number.
|
||||
required_swig_vernum=`expr $required_major \* 10000 \
|
||||
\+ $required_minor \* 100 \+ $required_patch`
|
||||
available_swig_vernum=`expr $available_major \* 10000 \
|
||||
\+ $available_minor \* 100 \+ $available_patch`
|
||||
|
||||
if test $available_swig_vernum -lt $required_swig_vernum; then
|
||||
AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version.])
|
||||
SWIG=''
|
||||
m4_ifval([$3],[$3],[])
|
||||
else
|
||||
AC_MSG_NOTICE([SWIG executable is '$SWIG'])
|
||||
SWIG_LIB=`$SWIG -swiglib`
|
||||
AC_MSG_NOTICE([SWIG library directory is '$SWIG_LIB'])
|
||||
AC_MSG_CHECKING([for SWIG library])
|
||||
SWIG_LIB=`$SWIG -swiglib | tr '\r\n' ' '`
|
||||
AC_MSG_RESULT([$SWIG_LIB])
|
||||
m4_ifval([$2],[$2],[])
|
||||
fi
|
||||
else
|
||||
AC_MSG_WARN([cannot determine SWIG version])
|
||||
SWIG='echo "Error: Cannot determine SWIG version. You should look at http://www.swig.org" ; false'
|
||||
SWIG=''
|
||||
m4_ifval([$3],[$3],[])
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([SWIG_LIB])
|
||||
+332
-127
@@ -1,5 +1,5 @@
|
||||
# ===========================================================================
|
||||
# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_pthread.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
@@ -14,24 +14,28 @@
|
||||
# flags that are needed. (The user can also force certain compiler
|
||||
# flags/libs to be tested by setting these environment variables.)
|
||||
#
|
||||
# Also sets PTHREAD_CC to any special C compiler that is needed for
|
||||
# multi-threaded programs (defaults to the value of CC otherwise). (This
|
||||
# is necessary on AIX to use the special cc_r compiler alias.)
|
||||
# Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is
|
||||
# needed for multi-threaded programs (defaults to the value of CC
|
||||
# respectively CXX otherwise). (This is necessary on e.g. AIX to use the
|
||||
# special cc_r/CC_r compiler alias.)
|
||||
#
|
||||
# NOTE: You are assumed to not only compile your program with these flags,
|
||||
# but also link it with them as well. e.g. you should link with
|
||||
# but also to link with them as well. For example, you might link with
|
||||
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
|
||||
# $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
|
||||
#
|
||||
# If you are only building threads programs, you may wish to use these
|
||||
# If you are only building threaded programs, you may wish to use these
|
||||
# variables in your default LIBS, CFLAGS, and CC:
|
||||
#
|
||||
# LIBS="$PTHREAD_LIBS $LIBS"
|
||||
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
|
||||
# CC="$PTHREAD_CC"
|
||||
# CXX="$PTHREAD_CXX"
|
||||
#
|
||||
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
|
||||
# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
|
||||
# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
||||
# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
|
||||
# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
||||
#
|
||||
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
|
||||
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
|
||||
@@ -55,6 +59,7 @@
|
||||
#
|
||||
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
|
||||
# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
|
||||
# Copyright (c) 2019 Marc Stevens <marc.stevens@cwi.nl>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
@@ -67,7 +72,7 @@
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
@@ -82,35 +87,41 @@
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 21
|
||||
#serial 32
|
||||
|
||||
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
|
||||
AC_DEFUN([AX_PTHREAD], [
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
AC_REQUIRE([AC_PROG_CC])
|
||||
AC_REQUIRE([AC_PROG_SED])
|
||||
AC_LANG_PUSH([C])
|
||||
ax_pthread_ok=no
|
||||
|
||||
# We used to check for pthread.h first, but this fails if pthread.h
|
||||
# requires special compiler flags (e.g. on True64 or Sequent).
|
||||
# requires special compiler flags (e.g. on Tru64 or Sequent).
|
||||
# It gets checked for in the link test anyway.
|
||||
|
||||
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
||||
# etcetera environment variables, and if threads linking works using
|
||||
# them:
|
||||
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
|
||||
save_CFLAGS="$CFLAGS"
|
||||
if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
|
||||
ax_pthread_save_CC="$CC"
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_LIBS="$LIBS"
|
||||
AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
|
||||
AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"])
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
|
||||
AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes])
|
||||
AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
|
||||
AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
|
||||
AC_MSG_RESULT([$ax_pthread_ok])
|
||||
if test x"$ax_pthread_ok" = xno; then
|
||||
if test "x$ax_pthread_ok" = "xno"; then
|
||||
PTHREAD_LIBS=""
|
||||
PTHREAD_CFLAGS=""
|
||||
fi
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
CC="$ax_pthread_save_CC"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
LIBS="$ax_pthread_save_LIBS"
|
||||
fi
|
||||
|
||||
# We must check for the threads library under a number of different
|
||||
@@ -118,12 +129,14 @@ fi
|
||||
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
|
||||
# libraries is broken (non-POSIX).
|
||||
|
||||
# Create a list of thread flags to try. Items starting with a "-" are
|
||||
# C compiler flags, and other items are library names, except for "none"
|
||||
# which indicates that we try without any flags at all, and "pthread-config"
|
||||
# which is a program returning the flags for the Pth emulation library.
|
||||
# Create a list of thread flags to try. Items with a "," contain both
|
||||
# C compiler flags (before ",") and linker flags (after ","). Other items
|
||||
# starting with a "-" are C compiler flags, and remaining items are
|
||||
# library names, except for "none" which indicates that we try without
|
||||
# any flags at all, and "pthread-config" which is a program returning
|
||||
# the flags for the Pth emulation library.
|
||||
|
||||
ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
||||
ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
||||
|
||||
# The ordering *is* (sometimes) important. Some notes on the
|
||||
# individual items follow:
|
||||
@@ -132,82 +145,178 @@ ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mt
|
||||
# none: in case threads are in libc; should be tried before -Kthread and
|
||||
# other compiler flags to prevent continual compiler warnings
|
||||
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
||||
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
||||
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
|
||||
# -pthreads: Solaris/gcc
|
||||
# -mthreads: Mingw32/gcc, Lynx/gcc
|
||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
|
||||
# (Note: HP C rejects this with "bad form for `-t' option")
|
||||
# -pthreads: Solaris/gcc (Note: HP C also rejects)
|
||||
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
||||
# doesn't hurt to check since this sometimes defines pthreads too;
|
||||
# also defines -D_REENTRANT)
|
||||
# ... -mt is also the pthreads flag for HP/aCC
|
||||
# doesn't hurt to check since this sometimes defines pthreads and
|
||||
# -D_REENTRANT too), HP C (must be checked before -lpthread, which
|
||||
# is present but should not be used directly; and before -mthreads,
|
||||
# because the compiler interprets this as "-mt" + "-hreads")
|
||||
# -mthreads: Mingw32/gcc, Lynx/gcc
|
||||
# pthread: Linux, etcetera
|
||||
# --thread-safe: KAI C++
|
||||
# pthread-config: use pthread-config program (for GNU Pth library)
|
||||
|
||||
case ${host_os} in
|
||||
case $host_os in
|
||||
|
||||
freebsd*)
|
||||
|
||||
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
||||
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
||||
|
||||
ax_pthread_flags="-kthread lthread $ax_pthread_flags"
|
||||
;;
|
||||
|
||||
hpux*)
|
||||
|
||||
# From the cc(1) man page: "[-mt] Sets various -D flags to enable
|
||||
# multi-threading and also sets -lpthread."
|
||||
|
||||
ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
|
||||
;;
|
||||
|
||||
openedition*)
|
||||
|
||||
# IBM z/OS requires a feature-test macro to be defined in order to
|
||||
# enable POSIX threads at all, so give the user a hint if this is
|
||||
# not set. (We don't define these ourselves, as they can affect
|
||||
# other portions of the system API in unpredictable ways.)
|
||||
|
||||
AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
|
||||
[
|
||||
# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
|
||||
AX_PTHREAD_ZOS_MISSING
|
||||
# endif
|
||||
],
|
||||
[AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
|
||||
;;
|
||||
|
||||
solaris*)
|
||||
|
||||
# On Solaris (at least, for some versions), libc contains stubbed
|
||||
# (non-functional) versions of the pthreads routines, so link-based
|
||||
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
|
||||
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
|
||||
# a function called by this macro, so we could check for that, but
|
||||
# who knows whether they'll stub that too in a future libc.) So,
|
||||
# we'll just look for -pthreads and -lpthread first:
|
||||
# tests will erroneously succeed. (N.B.: The stubs are missing
|
||||
# pthread_cleanup_push, or rather a function called by this macro,
|
||||
# so we could check for that, but who knows whether they'll stub
|
||||
# that too in a future libc.) So we'll check first for the
|
||||
# standard Solaris way of linking pthreads (-mt -lpthread).
|
||||
|
||||
ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
|
||||
;;
|
||||
|
||||
darwin*)
|
||||
ax_pthread_flags="-pthread $ax_pthread_flags"
|
||||
ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Clang doesn't consider unrecognized options an error unless we specify
|
||||
# -Werror. We throw in some extra Clang-specific options to ensure that
|
||||
# this doesn't happen for GCC, which also accepts -Werror.
|
||||
# Are we compiling with Clang?
|
||||
|
||||
AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags])
|
||||
save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_extra_flags="-Werror"
|
||||
CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[ax_pthread_extra_flags=
|
||||
AC_MSG_RESULT([no])])
|
||||
CFLAGS="$save_CFLAGS"
|
||||
AC_CACHE_CHECK([whether $CC is Clang],
|
||||
[ax_cv_PTHREAD_CLANG],
|
||||
[ax_cv_PTHREAD_CLANG=no
|
||||
# Note that Autoconf sets GCC=yes for Clang as well as GCC
|
||||
if test "x$GCC" = "xyes"; then
|
||||
AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
|
||||
[/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
|
||||
# if defined(__clang__) && defined(__llvm__)
|
||||
AX_PTHREAD_CC_IS_CLANG
|
||||
# endif
|
||||
],
|
||||
[ax_cv_PTHREAD_CLANG=yes])
|
||||
fi
|
||||
])
|
||||
ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
|
||||
|
||||
if test x"$ax_pthread_ok" = xno; then
|
||||
for flag in $ax_pthread_flags; do
|
||||
|
||||
case $flag in
|
||||
# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
|
||||
|
||||
# Note that for GCC and Clang -pthread generally implies -lpthread,
|
||||
# except when -nostdlib is passed.
|
||||
# This is problematic using libtool to build C++ shared libraries with pthread:
|
||||
# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460
|
||||
# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333
|
||||
# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555
|
||||
# To solve this, first try -pthread together with -lpthread for GCC
|
||||
|
||||
AS_IF([test "x$GCC" = "xyes"],
|
||||
[ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"])
|
||||
|
||||
# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first
|
||||
|
||||
AS_IF([test "x$ax_pthread_clang" = "xyes"],
|
||||
[ax_pthread_flags="-pthread,-lpthread -pthread"])
|
||||
|
||||
|
||||
# The presence of a feature test macro requesting re-entrant function
|
||||
# definitions is, on some systems, a strong hint that pthreads support is
|
||||
# correctly enabled
|
||||
|
||||
case $host_os in
|
||||
solaris*)
|
||||
# Solaris 11.4 introduced XPG7 support and did away with the need for
|
||||
# _REENTRANT.
|
||||
|
||||
AC_EGREP_CPP([AX_PTHREAD_SOLARIS__REENTRANT],
|
||||
[
|
||||
# undef _XOPEN_SOURCE
|
||||
# include <sys/feature_tests.h>
|
||||
# if _XOPEN_VERSION < 700
|
||||
AX_PTHREAD_SOLARIS__REENTRANT
|
||||
# endif
|
||||
],
|
||||
[ax_pthread_check_macro="_REENTRANT"],
|
||||
[ax_pthread_check_macro="--"])
|
||||
;;
|
||||
darwin* | hpux* | linux* | osf*)
|
||||
ax_pthread_check_macro="_REENTRANT"
|
||||
;;
|
||||
|
||||
aix*)
|
||||
ax_pthread_check_macro="_THREAD_SAFE"
|
||||
;;
|
||||
|
||||
*)
|
||||
ax_pthread_check_macro="--"
|
||||
;;
|
||||
esac
|
||||
AS_IF([test "x$ax_pthread_check_macro" = "x--"],
|
||||
[ax_pthread_check_cond=0],
|
||||
[ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
|
||||
|
||||
|
||||
if test "x$ax_pthread_ok" = "xno"; then
|
||||
for ax_pthread_try_flag in $ax_pthread_flags; do
|
||||
|
||||
case $ax_pthread_try_flag in
|
||||
none)
|
||||
AC_MSG_CHECKING([whether pthreads work without any flags])
|
||||
;;
|
||||
|
||||
*,*)
|
||||
PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"`
|
||||
PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"`
|
||||
AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"])
|
||||
;;
|
||||
|
||||
-*)
|
||||
AC_MSG_CHECKING([whether pthreads work with $flag])
|
||||
PTHREAD_CFLAGS="$flag"
|
||||
AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
|
||||
PTHREAD_CFLAGS="$ax_pthread_try_flag"
|
||||
;;
|
||||
|
||||
pthread-config)
|
||||
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
|
||||
if test x"$ax_pthread_config" = xno; then continue; fi
|
||||
AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
|
||||
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
||||
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
||||
;;
|
||||
|
||||
*)
|
||||
AC_MSG_CHECKING([for the pthreads library -l$flag])
|
||||
PTHREAD_LIBS="-l$flag"
|
||||
AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
|
||||
PTHREAD_LIBS="-l$ax_pthread_try_flag"
|
||||
;;
|
||||
esac
|
||||
|
||||
save_LIBS="$LIBS"
|
||||
save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags"
|
||||
|
||||
# Check for various functions. We must include pthread.h,
|
||||
# since some functions may be macros. (On the Sequent, we
|
||||
@@ -218,8 +327,18 @@ for flag in $ax_pthread_flags; do
|
||||
# pthread_cleanup_push because it is one of the few pthread
|
||||
# functions on Solaris that doesn't have a non-functional libc stub.
|
||||
# We try pthread_create on general principles.
|
||||
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
|
||||
static void routine(void *a) { *((int*)a) = 0; }
|
||||
# if $ax_pthread_check_cond
|
||||
# error "$ax_pthread_check_macro must be defined"
|
||||
# endif
|
||||
static void *some_global = NULL;
|
||||
static void routine(void *a)
|
||||
{
|
||||
/* To avoid any unused-parameter or
|
||||
unused-but-set-parameter warning. */
|
||||
some_global = a;
|
||||
}
|
||||
static void *start_routine(void *a) { return a; }],
|
||||
[pthread_t th; pthread_attr_t attr;
|
||||
pthread_create(&th, 0, start_routine, 0);
|
||||
@@ -227,101 +346,187 @@ for flag in $ax_pthread_flags; do
|
||||
pthread_attr_init(&attr);
|
||||
pthread_cleanup_push(routine, 0);
|
||||
pthread_cleanup_pop(0) /* ; */])],
|
||||
[ax_pthread_ok=yes],
|
||||
[])
|
||||
[ax_pthread_ok=yes],
|
||||
[])
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
LIBS="$ax_pthread_save_LIBS"
|
||||
|
||||
AC_MSG_RESULT([$ax_pthread_ok])
|
||||
if test "x$ax_pthread_ok" = xyes; then
|
||||
break;
|
||||
fi
|
||||
AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
|
||||
|
||||
PTHREAD_LIBS=""
|
||||
PTHREAD_CFLAGS=""
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Clang needs special handling, because older versions handle the -pthread
|
||||
# option in a rather... idiosyncratic way
|
||||
|
||||
if test "x$ax_pthread_clang" = "xyes"; then
|
||||
|
||||
# Clang takes -pthread; it has never supported any other flag
|
||||
|
||||
# (Note 1: This will need to be revisited if a system that Clang
|
||||
# supports has POSIX threads in a separate library. This tends not
|
||||
# to be the way of modern systems, but it's conceivable.)
|
||||
|
||||
# (Note 2: On some systems, notably Darwin, -pthread is not needed
|
||||
# to get POSIX threads support; the API is always present and
|
||||
# active. We could reasonably leave PTHREAD_CFLAGS empty. But
|
||||
# -pthread does define _REENTRANT, and while the Darwin headers
|
||||
# ignore this macro, third-party headers might not.)
|
||||
|
||||
# However, older versions of Clang make a point of warning the user
|
||||
# that, in an invocation where only linking and no compilation is
|
||||
# taking place, the -pthread option has no effect ("argument unused
|
||||
# during compilation"). They expect -pthread to be passed in only
|
||||
# when source code is being compiled.
|
||||
#
|
||||
# Problem is, this is at odds with the way Automake and most other
|
||||
# C build frameworks function, which is that the same flags used in
|
||||
# compilation (CFLAGS) are also used in linking. Many systems
|
||||
# supported by AX_PTHREAD require exactly this for POSIX threads
|
||||
# support, and in fact it is often not straightforward to specify a
|
||||
# flag that is used only in the compilation phase and not in
|
||||
# linking. Such a scenario is extremely rare in practice.
|
||||
#
|
||||
# Even though use of the -pthread flag in linking would only print
|
||||
# a warning, this can be a nuisance for well-run software projects
|
||||
# that build with -Werror. So if the active version of Clang has
|
||||
# this misfeature, we search for an option to squash it.
|
||||
|
||||
AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
|
||||
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
|
||||
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
|
||||
# Create an alternate version of $ac_link that compiles and
|
||||
# links in two steps (.c -> .o, .o -> exe) instead of one
|
||||
# (.c -> exe), because the warning occurs only in the second
|
||||
# step
|
||||
ax_pthread_save_ac_link="$ac_link"
|
||||
ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
|
||||
ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"`
|
||||
ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
|
||||
AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
|
||||
CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
|
||||
ac_link="$ax_pthread_save_ac_link"
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
|
||||
[ac_link="$ax_pthread_2step_ac_link"
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
|
||||
[break])
|
||||
])
|
||||
done
|
||||
ac_link="$ax_pthread_save_ac_link"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
|
||||
ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
|
||||
])
|
||||
|
||||
case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
|
||||
no | unknown) ;;
|
||||
*) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
|
||||
esac
|
||||
|
||||
fi # $ax_pthread_clang = yes
|
||||
|
||||
|
||||
|
||||
# Various other checks:
|
||||
if test "x$ax_pthread_ok" = xyes; then
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
save_CFLAGS="$CFLAGS"
|
||||
if test "x$ax_pthread_ok" = "xyes"; then
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
|
||||
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
||||
AC_MSG_CHECKING([for joinable pthread attribute])
|
||||
attr_name=unknown
|
||||
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
|
||||
[int attr = $attr; return attr /* ; */])],
|
||||
[attr_name=$attr; break],
|
||||
[])
|
||||
done
|
||||
AC_MSG_RESULT([$attr_name])
|
||||
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
|
||||
AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name],
|
||||
[Define to necessary symbol if this constant
|
||||
uses a non-standard name on your system.])
|
||||
fi
|
||||
AC_CACHE_CHECK([for joinable pthread attribute],
|
||||
[ax_cv_PTHREAD_JOINABLE_ATTR],
|
||||
[ax_cv_PTHREAD_JOINABLE_ATTR=unknown
|
||||
for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
|
||||
[int attr = $ax_pthread_attr; return attr /* ; */])],
|
||||
[ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
|
||||
[])
|
||||
done
|
||||
])
|
||||
AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
|
||||
test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
|
||||
test "x$ax_pthread_joinable_attr_defined" != "xyes"],
|
||||
[AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
|
||||
[$ax_cv_PTHREAD_JOINABLE_ATTR],
|
||||
[Define to necessary symbol if this constant
|
||||
uses a non-standard name on your system.])
|
||||
ax_pthread_joinable_attr_defined=yes
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([if more special flags are required for pthreads])
|
||||
flag=no
|
||||
case ${host_os} in
|
||||
aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
|
||||
osf* | hpux*) flag="-D_REENTRANT";;
|
||||
solaris*)
|
||||
if test "$GCC" = "yes"; then
|
||||
flag="-D_REENTRANT"
|
||||
else
|
||||
# TODO: What about Clang on Solaris?
|
||||
flag="-mt -D_REENTRANT"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
AC_MSG_RESULT([$flag])
|
||||
if test "x$flag" != xno; then
|
||||
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
|
||||
fi
|
||||
AC_CACHE_CHECK([whether more special flags are required for pthreads],
|
||||
[ax_cv_PTHREAD_SPECIAL_FLAGS],
|
||||
[ax_cv_PTHREAD_SPECIAL_FLAGS=no
|
||||
case $host_os in
|
||||
solaris*)
|
||||
ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
|
||||
;;
|
||||
esac
|
||||
])
|
||||
AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
|
||||
test "x$ax_pthread_special_flags_added" != "xyes"],
|
||||
[PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
|
||||
ax_pthread_special_flags_added=yes])
|
||||
|
||||
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT], [
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
|
||||
[[int i = PTHREAD_PRIO_INHERIT;]])],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT=no])
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT],
|
||||
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
|
||||
[[int i = PTHREAD_PRIO_INHERIT;
|
||||
return i;]])],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT=no])
|
||||
])
|
||||
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
|
||||
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])])
|
||||
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
|
||||
test "x$ax_pthread_prio_inherit_defined" != "xyes"],
|
||||
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
|
||||
ax_pthread_prio_inherit_defined=yes
|
||||
])
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
LIBS="$ax_pthread_save_LIBS"
|
||||
|
||||
# More AIX lossage: compile with *_r variant
|
||||
if test "x$GCC" != xyes; then
|
||||
if test "x$GCC" != "xyes"; then
|
||||
case $host_os in
|
||||
aix*)
|
||||
AS_CASE(["x/$CC"],
|
||||
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
|
||||
[#handle absolute path differently from PATH based program lookup
|
||||
AS_CASE(["x$CC"],
|
||||
[x/*],
|
||||
[AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
|
||||
[AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
|
||||
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
|
||||
[#handle absolute path differently from PATH based program lookup
|
||||
AS_CASE(["x$CC"],
|
||||
[x/*],
|
||||
[
|
||||
AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])
|
||||
AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])])
|
||||
],
|
||||
[
|
||||
AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])
|
||||
AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])])
|
||||
]
|
||||
)
|
||||
])
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
|
||||
test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
|
||||
|
||||
AC_SUBST([PTHREAD_LIBS])
|
||||
AC_SUBST([PTHREAD_CFLAGS])
|
||||
AC_SUBST([PTHREAD_CC])
|
||||
AC_SUBST([PTHREAD_CXX])
|
||||
|
||||
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
||||
if test x"$ax_pthread_ok" = xyes; then
|
||||
if test "x$ax_pthread_ok" = "xyes"; then
|
||||
ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
|
||||
:
|
||||
else
|
||||
|
||||
+270
-72
@@ -47,9 +47,12 @@
|
||||
#include "util/regional.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/data/msgencode.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/mesh.h"
|
||||
#include "services/modstack.h"
|
||||
#include "validator/val_neg.h"
|
||||
#include "validator/val_secalgo.h"
|
||||
#include "iterator/iter_utils.h"
|
||||
@@ -102,7 +105,6 @@ static int
|
||||
testframe_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
{
|
||||
struct testframe_moddata* d;
|
||||
(void)env;
|
||||
verbose(VERB_ALGO, "testframe_init");
|
||||
d = (struct testframe_moddata*)calloc(1,
|
||||
sizeof(struct testframe_moddata));
|
||||
@@ -111,6 +113,15 @@ testframe_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
/* Register an EDNS option (65534) to bypass the worker cache lookup
|
||||
* for testing */
|
||||
if(!edns_register_option(LDNS_EDNS_UNBOUND_CACHEDB_TESTFRAME_TEST,
|
||||
1 /* bypass cache */,
|
||||
0 /* no aggregation */, env)) {
|
||||
log_err("testframe_init, could not register test opcode");
|
||||
free(d);
|
||||
return 0;
|
||||
}
|
||||
lock_basic_init(&d->lock);
|
||||
lock_protect(&d->lock, d, sizeof(*d));
|
||||
return 1;
|
||||
@@ -218,6 +229,8 @@ static int
|
||||
cachedb_apply_cfg(struct cachedb_env* cachedb_env, struct config_file* cfg)
|
||||
{
|
||||
const char* backend_str = cfg->cachedb_backend;
|
||||
if(!backend_str || *backend_str==0)
|
||||
return 1;
|
||||
cachedb_env->backend = cachedb_find_backend(backend_str);
|
||||
if(!cachedb_env->backend) {
|
||||
log_err("cachedb: cannot find backend name '%s'", backend_str);
|
||||
@@ -228,7 +241,7 @@ cachedb_apply_cfg(struct cachedb_env* cachedb_env, struct config_file* cfg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
cachedb_init(struct module_env* env, int id)
|
||||
{
|
||||
struct cachedb_env* cachedb_env = (struct cachedb_env*)calloc(1,
|
||||
@@ -255,31 +268,19 @@ cachedb_init(struct module_env* env, int id)
|
||||
return 0;
|
||||
}
|
||||
cachedb_env->enabled = 1;
|
||||
if(env->cfg->serve_expired_reply_ttl)
|
||||
log_warn(
|
||||
"cachedb: serve-expired-reply-ttl is set but not working for data "
|
||||
"originating from the external cache; 0 TLL is used for those.");
|
||||
if(env->cfg->serve_expired_client_timeout)
|
||||
log_warn(
|
||||
"cachedb: serve-expired-client-timeout is set but not working for "
|
||||
"data originating from the external cache; expired data are used "
|
||||
"in the reply without first trying to refresh the data.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
cachedb_deinit(struct module_env* env, int id)
|
||||
{
|
||||
struct cachedb_env* cachedb_env;
|
||||
if(!env || !env->modinfo[id])
|
||||
return;
|
||||
cachedb_env = (struct cachedb_env*)env->modinfo[id];
|
||||
/* free contents */
|
||||
/* TODO */
|
||||
if(cachedb_env->enabled) {
|
||||
(*cachedb_env->backend->deinit)(env, cachedb_env);
|
||||
}
|
||||
|
||||
free(cachedb_env);
|
||||
env->modinfo[id] = NULL;
|
||||
}
|
||||
@@ -322,30 +323,31 @@ error_response(struct module_qstate* qstate, int id, int rcode)
|
||||
|
||||
/**
|
||||
* Hash the query name, type, class and dbacess-secret into lookup buffer.
|
||||
* @param qstate: query state with query info
|
||||
* and env->cfg with secret.
|
||||
* @param qinfo: query info
|
||||
* @param env: with env->cfg with secret.
|
||||
* @param buf: returned buffer with hash to lookup
|
||||
* @param len: length of the buffer.
|
||||
*/
|
||||
static void
|
||||
calc_hash(struct module_qstate* qstate, char* buf, size_t len)
|
||||
calc_hash(struct query_info* qinfo, struct module_env* env, char* buf,
|
||||
size_t len)
|
||||
{
|
||||
uint8_t clear[1024];
|
||||
size_t clen = 0;
|
||||
uint8_t hash[CACHEDB_HASHSIZE/8];
|
||||
const char* hex = "0123456789ABCDEF";
|
||||
const char* secret = qstate->env->cfg->cachedb_secret;
|
||||
const char* secret = env->cfg->cachedb_secret;
|
||||
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,
|
||||
qstate->qinfo.qname_len);
|
||||
clen += qstate->qinfo.qname_len;
|
||||
if(clen + qinfo->qname_len < sizeof(clear)) {
|
||||
memmove(clear+clen, qinfo->qname, qinfo->qname_len);
|
||||
query_dname_tolower(clear+clen);
|
||||
clen += qinfo->qname_len;
|
||||
}
|
||||
if(clen + 4 < sizeof(clear)) {
|
||||
uint16_t t = htons(qstate->qinfo.qtype);
|
||||
uint16_t c = htons(qstate->qinfo.qclass);
|
||||
uint16_t t = htons(qinfo->qtype);
|
||||
uint16_t c = htons(qinfo->qclass);
|
||||
memmove(clear+clen, &t, 2);
|
||||
memmove(clear+clen+2, &c, 2);
|
||||
clen += 4;
|
||||
@@ -390,13 +392,33 @@ 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)
|
||||
/* do not store failures like SERVFAIL in the cachedb, this avoids
|
||||
* overwriting expired, valid, content with broken content. */
|
||||
if(FLAGS_GET_RCODE(qstate->return_msg->rep->flags) !=
|
||||
LDNS_RCODE_NOERROR &&
|
||||
FLAGS_GET_RCODE(qstate->return_msg->rep->flags) !=
|
||||
LDNS_RCODE_NXDOMAIN &&
|
||||
FLAGS_GET_RCODE(qstate->return_msg->rep->flags) !=
|
||||
LDNS_RCODE_YXDOMAIN)
|
||||
return 0;
|
||||
/* Do not persist data the validator has not yet seen, or has rejected.
|
||||
* Otherwise an expired blob could maybe reach clients via
|
||||
* serve-expired. */
|
||||
if(qstate->env->need_to_validate &&
|
||||
qstate->return_msg->rep->security == sec_status_bogus)
|
||||
return 0;
|
||||
/* We don't store the reply if its TTL is 0. This is probably coming
|
||||
* from upstream and it is not meant to be stored. */
|
||||
if(qstate->return_msg->rep->ttl == 0)
|
||||
return 0;
|
||||
|
||||
/* The EDE is added to the out-list so it is encoded in the cached message */
|
||||
if (qstate->env->cfg->ede && qstate->return_msg->rep->reason_bogus != LDNS_EDE_NONE) {
|
||||
edns_opt_list_append_ede(&edns.opt_list_out, qstate->env->scratch,
|
||||
qstate->return_msg->rep->reason_bogus,
|
||||
qstate->return_msg->rep->reason_bogus_str);
|
||||
}
|
||||
|
||||
if(verbosity >= VERB_ALGO)
|
||||
log_dns_msg("cachedb encoding", &qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
@@ -441,7 +463,7 @@ good_expiry_and_qinfo(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
* - serve_expired needs to be set
|
||||
* - if SERVE_EXPIRED_TTL is set make sure that the record is not older
|
||||
* than that. */
|
||||
if((time_t)expiry < *qstate->env->now &&
|
||||
if(TTL_IS_EXPIRED((time_t)expiry, *qstate->env->now) &&
|
||||
(!qstate->env->cfg->serve_expired ||
|
||||
(SERVE_EXPIRED_TTL &&
|
||||
*qstate->env->now - (time_t)expiry > SERVE_EXPIRED_TTL)))
|
||||
@@ -453,7 +475,8 @@ good_expiry_and_qinfo(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
/* 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)
|
||||
packed_rrset_ttl_subtract(struct packed_rrset_data* data, time_t subtract,
|
||||
time_t timestamp)
|
||||
{
|
||||
size_t i;
|
||||
size_t total = data->count + data->rrsig_count;
|
||||
@@ -465,13 +488,13 @@ packed_rrset_ttl_subtract(struct packed_rrset_data* data, time_t subtract)
|
||||
data->rr_ttl[i] -= subtract;
|
||||
else data->rr_ttl[i] = 0;
|
||||
}
|
||||
data->ttl_add = (subtract < data->ttl_add) ? (data->ttl_add - subtract) : 0;
|
||||
data->ttl_add = timestamp;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
adjust_msg_ttl(struct dns_msg* msg, time_t adjust, time_t timestamp)
|
||||
{
|
||||
size_t i;
|
||||
if(adjust >= 0 && msg->rep->ttl > adjust)
|
||||
@@ -483,16 +506,46 @@ adjust_msg_ttl(struct dns_msg* msg, time_t adjust)
|
||||
|
||||
for(i=0; i<msg->rep->rrset_count; i++) {
|
||||
packed_rrset_ttl_subtract((struct packed_rrset_data*)msg->
|
||||
rep->rrsets[i]->entry.data, adjust);
|
||||
rep->rrsets[i]->entry.data, adjust, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the TTL of the given RRset to fixed value. */
|
||||
static void
|
||||
packed_rrset_ttl_set(struct packed_rrset_data* data, time_t ttl, time_t timestamp)
|
||||
{
|
||||
size_t i;
|
||||
size_t total = data->count + data->rrsig_count;
|
||||
data->ttl = ttl;
|
||||
for(i=0; i<total; i++) {
|
||||
data->rr_ttl[i] = ttl;
|
||||
}
|
||||
data->ttl_add = timestamp;
|
||||
}
|
||||
|
||||
/* Set the TTL of a DNS message and its RRs by to a fixed value. */
|
||||
static void
|
||||
set_msg_ttl(struct dns_msg* msg, time_t ttl, time_t timestamp)
|
||||
{
|
||||
size_t i;
|
||||
msg->rep->ttl = ttl;
|
||||
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_set((struct packed_rrset_data*)msg->
|
||||
rep->rrsets[i]->entry.data, ttl, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
/** convert dns message in buffer to return_msg */
|
||||
static int
|
||||
parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
parse_data(struct module_qstate* qstate, struct sldns_buffer* buf,
|
||||
int* msg_expired, time_t* msg_timestamp, time_t* msg_expiry)
|
||||
{
|
||||
struct msg_parse* prs;
|
||||
struct edns_data edns;
|
||||
struct edns_option* ede;
|
||||
uint64_t timestamp, expiry;
|
||||
time_t adjust;
|
||||
size_t lim = sldns_buffer_limit(buf);
|
||||
@@ -505,6 +558,9 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
×tamp, sizeof(timestamp));
|
||||
expiry = be64toh(expiry);
|
||||
timestamp = be64toh(timestamp);
|
||||
log_assert(timestamp <= expiry);
|
||||
*msg_expiry = (time_t)expiry;
|
||||
*msg_timestamp = (time_t)timestamp;
|
||||
|
||||
/* parse DNS packet */
|
||||
regional_free_all(qstate->env->scratch);
|
||||
@@ -519,7 +575,7 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
sldns_buffer_set_limit(buf, lim);
|
||||
return 0;
|
||||
}
|
||||
if(parse_extract_edns(prs, &edns, qstate->env->scratch) !=
|
||||
if(parse_extract_edns_from_response_msg(prs, &edns, qstate->env->scratch) !=
|
||||
LDNS_RCODE_NOERROR) {
|
||||
sldns_buffer_set_limit(buf, lim);
|
||||
return 0;
|
||||
@@ -530,6 +586,24 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
if(!qstate->return_msg)
|
||||
return 0;
|
||||
|
||||
/* We find the EDE in the in-list after parsing */
|
||||
if(qstate->env->cfg->ede &&
|
||||
(ede = edns_opt_list_find(edns.opt_list_in, LDNS_EDNS_EDE))) {
|
||||
if(ede->opt_len >= 2) {
|
||||
qstate->return_msg->rep->reason_bogus =
|
||||
sldns_read_uint16(ede->opt_data);
|
||||
}
|
||||
/* allocate space and store the error string and it's size */
|
||||
if(ede->opt_len > 2) {
|
||||
size_t ede_len = ede->opt_len - 2;
|
||||
qstate->return_msg->rep->reason_bogus_str = regional_alloc(
|
||||
qstate->region, sizeof(char) * (ede_len+1));
|
||||
memcpy(qstate->return_msg->rep->reason_bogus_str,
|
||||
ede->opt_data+2, ede_len);
|
||||
qstate->return_msg->rep->reason_bogus_str[ede_len] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
|
||||
/* see how much of the TTL expired, and remove it */
|
||||
@@ -538,25 +612,32 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
return 1; /* message from the future (clock skew?) */
|
||||
}
|
||||
adjust = *qstate->env->now - (time_t)timestamp;
|
||||
if(qstate->return_msg->rep->ttl < adjust) {
|
||||
if(TTL_IS_EXPIRED((time_t)expiry, *qstate->env->now)) {
|
||||
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
|
||||
*msg_expired = 1;
|
||||
if(!qstate->env->cfg->serve_expired ||
|
||||
(FLAGS_GET_RCODE(qstate->return_msg->rep->flags)
|
||||
!= LDNS_RCODE_NOERROR &&
|
||||
FLAGS_GET_RCODE(qstate->return_msg->rep->flags)
|
||||
!= LDNS_RCODE_NXDOMAIN &&
|
||||
FLAGS_GET_RCODE(qstate->return_msg->rep->flags)
|
||||
!= LDNS_RCODE_YXDOMAIN))
|
||||
return 0; /* message expired */
|
||||
/* If serve-expired is enabled, we still use an expired message.
|
||||
* Set the TTL to 0 now and it will be handled specially later
|
||||
* when we need to store it internally. */
|
||||
adjust = -1;
|
||||
}
|
||||
adjust_msg_ttl(qstate->return_msg, adjust, timestamp);
|
||||
verbose(VERB_ALGO, "cachedb msg adjusted down by %d", (int)adjust);
|
||||
adjust_msg_ttl(qstate->return_msg, adjust);
|
||||
if(qstate->env->cfg->aggressive_nsec) {
|
||||
limit_nsec_ttl(qstate->return_msg);
|
||||
}
|
||||
|
||||
/* 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)) {
|
||||
* refetch will be scheduled. */
|
||||
if(*msg_expired && !qstate->env->cfg->serve_expired_client_timeout) {
|
||||
qstate->need_refetch = 1;
|
||||
}
|
||||
|
||||
@@ -568,10 +649,11 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
* return true if lookup was successful.
|
||||
*/
|
||||
static int
|
||||
cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie)
|
||||
cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie,
|
||||
int* msg_expired, time_t* msg_timestamp, time_t* msg_expiry)
|
||||
{
|
||||
char key[(CACHEDB_HASHSIZE/8)*2+1];
|
||||
calc_hash(qstate, key, sizeof(key));
|
||||
calc_hash(&qstate->qinfo, qstate->env, key, sizeof(key));
|
||||
|
||||
/* call backend to fetch data for key into scratch buffer */
|
||||
if( !(*ie->backend->lookup)(qstate->env, ie, key,
|
||||
@@ -585,7 +667,8 @@ cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie)
|
||||
}
|
||||
|
||||
/* parse dns message into return_msg */
|
||||
if( !parse_data(qstate, qstate->env->scratch_buffer) ) {
|
||||
if( !parse_data(qstate, qstate->env->scratch_buffer, msg_expired,
|
||||
msg_timestamp, msg_expiry) ) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -598,7 +681,7 @@ static void
|
||||
cachedb_extcache_store(struct module_qstate* qstate, struct cachedb_env* ie)
|
||||
{
|
||||
char key[(CACHEDB_HASHSIZE/8)*2+1];
|
||||
calc_hash(qstate, key, sizeof(key));
|
||||
calc_hash(&qstate->qinfo, qstate->env, key, sizeof(key));
|
||||
|
||||
/* prepare data in scratch buffer */
|
||||
if(!prep_data(qstate, qstate->env->scratch_buffer))
|
||||
@@ -615,13 +698,18 @@ cachedb_extcache_store(struct module_qstate* qstate, struct cachedb_env* ie)
|
||||
* See if unbound's internal cache can answer the query
|
||||
*/
|
||||
static int
|
||||
cachedb_intcache_lookup(struct module_qstate* qstate)
|
||||
cachedb_intcache_lookup(struct module_qstate* qstate, struct cachedb_env* cde)
|
||||
{
|
||||
uint8_t dpname_storage[LDNS_MAX_DOMAINLEN+1];
|
||||
uint8_t* dpname=NULL;
|
||||
size_t dpnamelen=0;
|
||||
struct dns_msg* msg;
|
||||
/* for testframe bypass this lookup */
|
||||
if(cde->backend == &testframe_backend) {
|
||||
return 0;
|
||||
}
|
||||
if(iter_stub_fwd_no_cache(qstate, &qstate->qinfo,
|
||||
&dpname, &dpnamelen))
|
||||
&dpname, &dpnamelen, dpname_storage, sizeof(dpname_storage)))
|
||||
return 0; /* no cache for these queries */
|
||||
msg = dns_cache_lookup(qstate->env, qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len, qstate->qinfo.qtype,
|
||||
@@ -652,17 +740,52 @@ cachedb_intcache_lookup(struct module_qstate* qstate)
|
||||
* Store query into the internal cache of unbound.
|
||||
*/
|
||||
static void
|
||||
cachedb_intcache_store(struct module_qstate* qstate)
|
||||
cachedb_intcache_store(struct module_qstate* qstate, int msg_expired,
|
||||
time_t msg_timestamp, time_t msg_expiry)
|
||||
{
|
||||
uint32_t store_flags = qstate->query_flags;
|
||||
|
||||
if(qstate->env->cfg->serve_expired)
|
||||
store_flags |= DNSCACHE_STORE_ZEROTTL;
|
||||
int serve_expired = qstate->env->cfg->serve_expired;
|
||||
if(!qstate->return_msg)
|
||||
return;
|
||||
if(serve_expired && msg_expired) {
|
||||
time_t original_ttl = msg_expiry - msg_timestamp;
|
||||
store_flags |= DNSCACHE_STORE_EXPIRED_MSG_CACHEDB;
|
||||
/* Pass the original TTL of the expired message and signal with
|
||||
* the DNSCACHE_STORE_EXPIRED_MSG_CACHEDB flag that
|
||||
* dns_cache_store_msg() needs to set absolute expired TTLs
|
||||
* based on the original message TTL.
|
||||
* Results as expired message in the cache */
|
||||
set_msg_ttl(qstate->return_msg, original_ttl, 0);
|
||||
verbose(VERB_ALGO, "cachedb expired msg set to be expired now "
|
||||
"(original ttl: %d)", (int)original_ttl);
|
||||
/* The expired entry does not get checked by the validator
|
||||
* and we need a validation value for it. */
|
||||
/* By setting this to unchecked, bogus data is not returned
|
||||
* as non-bogus. */
|
||||
if(qstate->env->cfg->cachedb_check_when_serve_expired)
|
||||
qstate->return_msg->rep->security = sec_status_unchecked;
|
||||
}
|
||||
(void)dns_cache_store(qstate->env, &qstate->qinfo,
|
||||
qstate->return_msg->rep, 0, qstate->prefetch_leeway, 0,
|
||||
qstate->region, store_flags);
|
||||
qstate->region, store_flags, qstate->qstarttime,
|
||||
qstate->is_valrec);
|
||||
if(serve_expired && msg_expired) {
|
||||
if(qstate->env->cfg->serve_expired_client_timeout) {
|
||||
/* No expired response from the query state, the
|
||||
* query resolution needs to continue and it can
|
||||
* pick up the expired result after the timer out
|
||||
* of cache. */
|
||||
return;
|
||||
}
|
||||
/* Send serve expired responses based on the cachedb
|
||||
* returned message, that was just stored in the cache.
|
||||
* It can then continue to work on this query. */
|
||||
mesh_respond_serve_expired(qstate->mesh_info);
|
||||
/* set TTLs as expired for this return_msg in case it is used
|
||||
* later on */
|
||||
set_msg_ttl(qstate->return_msg,
|
||||
EXPIRED_REPLY_TTL_CALC(msg_expiry, msg_timestamp), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -678,6 +801,9 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
struct cachedb_qstate* ATTR_UNUSED(iq),
|
||||
struct cachedb_env* ie, int id)
|
||||
{
|
||||
int msg_expired = 0;
|
||||
time_t msg_timestamp, msg_expiry;
|
||||
qstate->is_cachedb_answer = 0;
|
||||
/* check if we are enabled, and skip if so */
|
||||
if(!ie->enabled) {
|
||||
/* pass request to next module */
|
||||
@@ -685,8 +811,11 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
return;
|
||||
}
|
||||
|
||||
if(qstate->blacklist || qstate->no_cache_lookup) {
|
||||
/* cache is blacklisted or we are instructed from edns to not look */
|
||||
if(qstate->blacklist || qstate->no_cache_lookup
|
||||
|| iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL,
|
||||
NULL, 0)) {
|
||||
/* cache is blacklisted or we are instructed from edns to not
|
||||
* look or a forwarder/stub forbids it */
|
||||
/* pass request to next module */
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
@@ -694,7 +823,7 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
|
||||
/* lookup inside unbound's internal cache.
|
||||
* This does not look for expired entries. */
|
||||
if(cachedb_intcache_lookup(qstate)) {
|
||||
if(cachedb_intcache_lookup(qstate, ie)) {
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
if(qstate->return_msg->rep)
|
||||
log_dns_msg("cachedb internal cache lookup",
|
||||
@@ -711,31 +840,55 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
}
|
||||
|
||||
/* ask backend cache to see if we have data */
|
||||
if(cachedb_extcache_lookup(qstate, ie)) {
|
||||
if(cachedb_extcache_lookup(qstate, ie, &msg_expired, &msg_timestamp,
|
||||
&msg_expiry)) {
|
||||
if(verbosity >= VERB_ALGO)
|
||||
log_dns_msg(ie->backend->name,
|
||||
&qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
/* store this result in internal cache */
|
||||
cachedb_intcache_store(qstate);
|
||||
cachedb_intcache_store(qstate,
|
||||
msg_expired, msg_timestamp, msg_expiry);
|
||||
/* In case we have expired data but there is a client timer for expired
|
||||
* answers, pass execution to next module in order to try updating the
|
||||
* data first.
|
||||
* TODO: this needs revisit. The expired data stored from cachedb has
|
||||
* 0 TTL which is picked up by iterator later when looking in the cache.
|
||||
* Document that ext cachedb does not work properly with
|
||||
* serve_stale_reply_ttl yet. */
|
||||
*/
|
||||
if(qstate->env->cfg->serve_expired && msg_expired) {
|
||||
qstate->return_msg = NULL;
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
/* The expired reply is sent with
|
||||
* mesh_respond_serve_expired, and so
|
||||
* the need_refetch is not used. */
|
||||
qstate->need_refetch = 0;
|
||||
return;
|
||||
}
|
||||
if(qstate->need_refetch && qstate->serve_expired_data &&
|
||||
qstate->serve_expired_data->timer) {
|
||||
qstate->return_msg = NULL;
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
/* No 0TTL answers escaping from external cache. */
|
||||
if(qstate->return_msg->rep->ttl == 0) {
|
||||
qstate->return_msg = NULL;
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
log_assert(qstate->return_msg->rep->ttl > 0);
|
||||
qstate->is_cachedb_answer = 1;
|
||||
/* we are done with the query */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
|
||||
if(qstate->serve_expired_data &&
|
||||
qstate->env->cfg->cachedb_check_when_serve_expired &&
|
||||
!qstate->env->cfg->serve_expired_client_timeout) {
|
||||
/* Reply with expired data if any to client, because cachedb
|
||||
* also has no useful, current data */
|
||||
mesh_respond_serve_expired(qstate->mesh_info);
|
||||
}
|
||||
|
||||
/* no cache fetches */
|
||||
/* pass request to next module */
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
@@ -753,12 +906,20 @@ static void
|
||||
cachedb_handle_response(struct module_qstate* qstate,
|
||||
struct cachedb_qstate* ATTR_UNUSED(iq), struct cachedb_env* ie, int id)
|
||||
{
|
||||
qstate->is_cachedb_answer = 0;
|
||||
/* check if we are not enabled or instructed to not cache, and skip */
|
||||
if(!ie->enabled || qstate->no_cache_store) {
|
||||
if(!ie->enabled || qstate->no_cache_store
|
||||
|| iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL,
|
||||
NULL, 0)) {
|
||||
/* we are done with the query */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
if(qstate->env->cfg->cachedb_no_store) {
|
||||
/* do not store the item in the external cache */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
|
||||
/* store the item into the backend cache */
|
||||
cachedb_extcache_store(qstate, ie);
|
||||
@@ -853,7 +1014,7 @@ cachedb_get_mem(struct module_env* env, int id)
|
||||
*/
|
||||
static struct module_func_block cachedb_block = {
|
||||
"cachedb",
|
||||
&cachedb_init, &cachedb_deinit, &cachedb_operate,
|
||||
NULL, NULL, &cachedb_init, &cachedb_deinit, &cachedb_operate,
|
||||
&cachedb_inform_super, &cachedb_clear, &cachedb_get_mem
|
||||
};
|
||||
|
||||
@@ -862,4 +1023,41 @@ cachedb_get_funcblock(void)
|
||||
{
|
||||
return &cachedb_block;
|
||||
}
|
||||
|
||||
int
|
||||
cachedb_is_enabled(struct module_stack* mods, struct module_env* env)
|
||||
{
|
||||
struct cachedb_env* ie;
|
||||
int id = modstack_find(mods, "cachedb");
|
||||
if(id == -1)
|
||||
return 0;
|
||||
ie = (struct cachedb_env*)env->modinfo[id];
|
||||
if(ie && ie->enabled)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cachedb_msg_remove(struct module_qstate* qstate)
|
||||
{
|
||||
cachedb_msg_remove_qinfo(qstate->env, &qstate->qinfo);
|
||||
}
|
||||
|
||||
void cachedb_msg_remove_qinfo(struct module_env* env, struct query_info* qinfo)
|
||||
{
|
||||
char key[(CACHEDB_HASHSIZE/8)*2+1];
|
||||
int id = modstack_find(env->modstack, "cachedb");
|
||||
struct cachedb_env* ie = (struct cachedb_env*)env->modinfo[id];
|
||||
|
||||
log_query_info(VERB_ALGO, "cachedb msg remove", qinfo);
|
||||
calc_hash(qinfo, env, key, sizeof(key));
|
||||
sldns_buffer_clear(env->scratch_buffer);
|
||||
sldns_buffer_write_u32(env->scratch_buffer, 0);
|
||||
sldns_buffer_flip(env->scratch_buffer);
|
||||
|
||||
/* call backend */
|
||||
(*ie->backend->store)(env, ie, key,
|
||||
sldns_buffer_begin(env->scratch_buffer),
|
||||
sldns_buffer_limit(env->scratch_buffer),
|
||||
0);
|
||||
}
|
||||
#endif /* USE_CACHEDB */
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
*/
|
||||
#include "util/module.h"
|
||||
struct cachedb_backend;
|
||||
struct module_stack;
|
||||
|
||||
/**
|
||||
* The global variable environment contents for the cachedb
|
||||
@@ -110,3 +111,26 @@ size_t cachedb_get_mem(struct module_env* env, int id);
|
||||
*/
|
||||
struct module_func_block* cachedb_get_funcblock(void);
|
||||
|
||||
/**
|
||||
* See if the cachedb is enabled.
|
||||
* @param mods: module stack. It finds the cachedb module environment.
|
||||
* @param env: module environment.
|
||||
* @return true if exists and enabled.
|
||||
*/
|
||||
int cachedb_is_enabled(struct module_stack* mods, struct module_env* env);
|
||||
|
||||
/**
|
||||
* Remove a message from the global cache. Because edns subnet has a more
|
||||
* specific entry, and if not removed when everything expires, the global
|
||||
* entry is used, instead of a fresh lookup of the edns subnet entry.
|
||||
* @param qstate: query state.
|
||||
*/
|
||||
void cachedb_msg_remove(struct module_qstate* qstate);
|
||||
|
||||
/**
|
||||
* Remove message from the cachedb cache, by query info.
|
||||
* @param env: module environment to look up cachedb state.
|
||||
* @param qinfo: the message to remove.
|
||||
*/
|
||||
void cachedb_msg_remove_qinfo(struct module_env* env,
|
||||
struct query_info* qinfo);
|
||||
|
||||
+376
-69
@@ -46,89 +46,341 @@
|
||||
#include "cachedb/cachedb.h"
|
||||
#include "util/alloc.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/locks.h"
|
||||
#include "util/timeval_func.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 */
|
||||
/* thread-specific redis contexts */
|
||||
redisContext** ctxs;
|
||||
redisContext** replica_ctxs;
|
||||
/* number of ctx entries */
|
||||
int numctxs;
|
||||
/* server's IP address or host name */
|
||||
const char* server_host;
|
||||
const char* replica_server_host;
|
||||
/* server's TCP port */
|
||||
int server_port;
|
||||
int replica_server_port;
|
||||
/* server's unix path, or "", NULL if unused */
|
||||
const char* server_path;
|
||||
const char* replica_server_path;
|
||||
/* server's AUTH password, or "", NULL if unused */
|
||||
const char* server_password;
|
||||
const char* replica_server_password;
|
||||
/* timeout for commands */
|
||||
struct timeval command_timeout;
|
||||
struct timeval replica_command_timeout;
|
||||
/* timeout for connection setup */
|
||||
struct timeval connect_timeout;
|
||||
struct timeval replica_connect_timeout;
|
||||
/* the reconnect interval time. */
|
||||
struct timeval reconnect_interval;
|
||||
struct timeval replica_reconnect_interval;
|
||||
/* reconnect attempts, 0 if connected, counts up failed reconnects. */
|
||||
int reconnect_attempts;
|
||||
int replica_reconnect_attempts;
|
||||
/* Lock on reconnect_wait time. */
|
||||
lock_basic_type wait_lock;
|
||||
lock_basic_type replica_wait_lock;
|
||||
/* reconnect wait time, wait until it has passed before reconnect. */
|
||||
struct timeval reconnect_wait;
|
||||
struct timeval replica_reconnect_wait;
|
||||
/* the redis logical database to use */
|
||||
int logical_db;
|
||||
int replica_logical_db;
|
||||
/* if the SET with EX command is supported */
|
||||
int set_with_ex_available;
|
||||
};
|
||||
|
||||
/** The limit on the number of redis connect attempts. After failure if
|
||||
* the number is exceeded, the reconnects are throttled by the wait time. */
|
||||
#define REDIS_RECONNECT_ATTEMPT_LIMIT 3
|
||||
|
||||
static redisReply* redis_command(struct module_env*, struct cachedb_env*,
|
||||
const char*, const uint8_t*, size_t);
|
||||
const char*, const uint8_t*, size_t, int);
|
||||
|
||||
static void
|
||||
moddata_clean(struct redis_moddata** moddata) {
|
||||
if(!moddata || !*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);
|
||||
}
|
||||
if((*moddata)->replica_ctxs) {
|
||||
int i;
|
||||
for(i = 0; i < (*moddata)->numctxs; i++) {
|
||||
if((*moddata)->replica_ctxs[i])
|
||||
redisFree((*moddata)->replica_ctxs[i]);
|
||||
}
|
||||
free((*moddata)->replica_ctxs);
|
||||
}
|
||||
lock_basic_destroy(&(*moddata)->wait_lock);
|
||||
lock_basic_destroy(&(*moddata)->replica_wait_lock);
|
||||
free(*moddata);
|
||||
*moddata = NULL;
|
||||
}
|
||||
|
||||
static redisContext*
|
||||
redis_connect(const struct redis_moddata* moddata)
|
||||
redis_connect(const char* host, int port, const char* path,
|
||||
const char* password, int logical_db,
|
||||
const struct timeval connect_timeout,
|
||||
const struct timeval command_timeout,
|
||||
const struct timeval* reconnect_interval,
|
||||
int* reconnect_attempts,
|
||||
struct timeval* reconnect_wait,
|
||||
lock_basic_type* wait_lock,
|
||||
struct timeval* now_tv,
|
||||
const char* infostr)
|
||||
{
|
||||
struct timeval now_val;
|
||||
redisContext* ctx;
|
||||
#ifdef THREADS_DISABLED
|
||||
/* Fix attribute unused warning.
|
||||
* wait_lock is only used with lock_basic_* functions that are nop'ed
|
||||
* when compiled without thread support. */
|
||||
(void)wait_lock;
|
||||
#endif /* THREADS_DISABLED */
|
||||
|
||||
ctx = redisConnectWithTimeout(moddata->server_host,
|
||||
moddata->server_port, moddata->timeout);
|
||||
/* See if the redis server is down, and reconnect has to wait. */
|
||||
if(*reconnect_attempts > REDIS_RECONNECT_ATTEMPT_LIMIT) {
|
||||
/* Acquire lock to look at timeval, the integer has atomic
|
||||
* integrity. */
|
||||
struct timeval wait_tv;
|
||||
if(now_tv) {
|
||||
now_val = *now_tv;
|
||||
} else {
|
||||
if(gettimeofday(&now_val, NULL) < 0)
|
||||
log_err("redis: gettimeofday: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
lock_basic_lock(wait_lock);
|
||||
wait_tv = *reconnect_wait;
|
||||
lock_basic_unlock(wait_lock);
|
||||
if(timeval_smaller(&now_val, &wait_tv)) {
|
||||
verbose(VERB_ALGO, "redis %sdown, reconnect wait",
|
||||
infostr);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if(path && path[0]!=0) {
|
||||
ctx = redisConnectUnixWithTimeout(path, connect_timeout);
|
||||
} else {
|
||||
ctx = redisConnectWithTimeout(host, port, connect_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);
|
||||
log_err("failed to connect to redis %sserver: %s", infostr, errstr);
|
||||
goto fail;
|
||||
}
|
||||
if(redisSetTimeout(ctx, moddata->timeout) != REDIS_OK) {
|
||||
log_err("failed to set redis timeout");
|
||||
if(redisSetTimeout(ctx, command_timeout) != REDIS_OK) {
|
||||
log_err("failed to set redis %stimeout, %s", infostr, ctx->errstr);
|
||||
goto fail;
|
||||
}
|
||||
if(password && password[0]!=0) {
|
||||
redisReply* rep;
|
||||
rep = redisCommand(ctx, "AUTH %s", password);
|
||||
if(!rep || rep->type == REDIS_REPLY_ERROR) {
|
||||
log_err("failed to authenticate %swith password", infostr);
|
||||
freeReplyObject(rep);
|
||||
goto fail;
|
||||
}
|
||||
freeReplyObject(rep);
|
||||
}
|
||||
if(logical_db > 0) {
|
||||
redisReply* rep;
|
||||
rep = redisCommand(ctx, "SELECT %d", logical_db);
|
||||
if(!rep || rep->type == REDIS_REPLY_ERROR) {
|
||||
log_err("failed %sto set logical database (%d)",
|
||||
infostr, logical_db);
|
||||
freeReplyObject(rep);
|
||||
goto fail;
|
||||
}
|
||||
freeReplyObject(rep);
|
||||
}
|
||||
*reconnect_attempts = 0;
|
||||
if(verbosity >= VERB_OPS) {
|
||||
char port_str[6+1];
|
||||
port_str[0] = ' ';
|
||||
(void)snprintf(port_str+1, sizeof(port_str)-1, "%d", port);
|
||||
verbose(VERB_OPS, "Connection to Redis %sestablished (%s%s)",
|
||||
infostr,
|
||||
path&&path[0]!=0?path:host,
|
||||
path&&path[0]!=0?"":port_str);
|
||||
}
|
||||
return ctx;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
if(ctx)
|
||||
redisFree(ctx);
|
||||
(*reconnect_attempts)++;
|
||||
if(*reconnect_attempts > REDIS_RECONNECT_ATTEMPT_LIMIT) {
|
||||
/* Wait for the reconnect interval before trying again. */
|
||||
struct timeval tv;
|
||||
if(now_tv) {
|
||||
now_val = *now_tv;
|
||||
} else {
|
||||
if(gettimeofday(&now_val, NULL) < 0)
|
||||
log_err("redis: gettimeofday: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
tv = now_val;
|
||||
timeval_add(&tv, reconnect_interval);
|
||||
lock_basic_lock(wait_lock);
|
||||
*reconnect_wait = tv;
|
||||
lock_basic_unlock(wait_lock);
|
||||
verbose(VERB_ALGO, "redis %sreconnect wait until %d.%6.6d",
|
||||
infostr, (int)tv.tv_sec, (int)tv.tv_usec);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
set_timeout(struct timeval* timeout, int value, int explicit_value)
|
||||
{
|
||||
int v = explicit_value != 0 ? explicit_value : value;
|
||||
timeout->tv_sec = v / 1000;
|
||||
timeout->tv_usec = (v % 1000) * 1000;
|
||||
}
|
||||
|
||||
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");
|
||||
verbose(VERB_OPS, "Redis initialization");
|
||||
|
||||
moddata = calloc(1, sizeof(struct redis_moddata));
|
||||
if(!moddata) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
goto fail;
|
||||
}
|
||||
lock_basic_init(&moddata->wait_lock);
|
||||
lock_protect(&moddata->wait_lock, &moddata->reconnect_wait,
|
||||
sizeof(moddata->reconnect_wait));
|
||||
lock_basic_init(&moddata->replica_wait_lock);
|
||||
lock_protect(&moddata->replica_wait_lock,
|
||||
&moddata->replica_reconnect_wait,
|
||||
sizeof(moddata->replica_reconnect_wait));
|
||||
moddata->numctxs = env->cfg->num_threads;
|
||||
/* note: server_host and similar string configuration options are
|
||||
* shallow references to configured strings; we don't have to free them
|
||||
* in this module. */
|
||||
moddata->server_host = env->cfg->redis_server_host;
|
||||
moddata->replica_server_host = env->cfg->redis_replica_server_host;
|
||||
|
||||
moddata->server_port = env->cfg->redis_server_port;
|
||||
moddata->replica_server_port = env->cfg->redis_replica_server_port;
|
||||
|
||||
moddata->server_path = env->cfg->redis_server_path;
|
||||
moddata->replica_server_path = env->cfg->redis_replica_server_path;
|
||||
|
||||
moddata->server_password = env->cfg->redis_server_password;
|
||||
moddata->replica_server_password = env->cfg->redis_replica_server_password;
|
||||
|
||||
set_timeout(&moddata->command_timeout,
|
||||
env->cfg->redis_timeout,
|
||||
env->cfg->redis_command_timeout);
|
||||
set_timeout(&moddata->replica_command_timeout,
|
||||
env->cfg->redis_replica_timeout,
|
||||
env->cfg->redis_replica_command_timeout);
|
||||
set_timeout(&moddata->connect_timeout,
|
||||
env->cfg->redis_timeout,
|
||||
env->cfg->redis_connect_timeout);
|
||||
set_timeout(&moddata->replica_connect_timeout,
|
||||
env->cfg->redis_replica_timeout,
|
||||
env->cfg->redis_replica_connect_timeout);
|
||||
set_timeout(&moddata->reconnect_interval, 1000, 0);
|
||||
set_timeout(&moddata->replica_reconnect_interval, 1000, 0);
|
||||
|
||||
moddata->logical_db = env->cfg->redis_logical_db;
|
||||
moddata->replica_logical_db = env->cfg->redis_replica_logical_db;
|
||||
|
||||
moddata->ctxs = calloc(env->cfg->num_threads, sizeof(redisContext*));
|
||||
if(!moddata->ctxs) {
|
||||
log_err("out of memory");
|
||||
free(moddata);
|
||||
return 0;
|
||||
goto fail;
|
||||
}
|
||||
if((moddata->replica_server_host && moddata->replica_server_host[0]!=0)
|
||||
|| (moddata->replica_server_path && moddata->replica_server_path[0]!=0)) {
|
||||
/* There is a replica configured, allocate ctxs */
|
||||
moddata->replica_ctxs = calloc(env->cfg->num_threads, sizeof(redisContext*));
|
||||
if(!moddata->replica_ctxs) {
|
||||
log_err("out of memory");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
for(i = 0; i < moddata->numctxs; i++) {
|
||||
redisContext* ctx = redis_connect(
|
||||
moddata->server_host,
|
||||
moddata->server_port,
|
||||
moddata->server_path,
|
||||
moddata->server_password,
|
||||
moddata->logical_db,
|
||||
moddata->connect_timeout,
|
||||
moddata->command_timeout,
|
||||
&moddata->reconnect_interval,
|
||||
&moddata->reconnect_attempts,
|
||||
&moddata->reconnect_wait,
|
||||
&moddata->wait_lock,
|
||||
env->now_tv,
|
||||
"");
|
||||
if(!ctx) {
|
||||
log_err("redis_init: failed to init redis "
|
||||
"(for thread %d)", i);
|
||||
/* And continue, the context can be established
|
||||
* later, just like after a disconnect. */
|
||||
}
|
||||
moddata->ctxs[i] = ctx;
|
||||
}
|
||||
if(moddata->replica_ctxs) {
|
||||
for(i = 0; i < moddata->numctxs; i++) {
|
||||
redisContext* ctx = redis_connect(
|
||||
moddata->replica_server_host,
|
||||
moddata->replica_server_port,
|
||||
moddata->replica_server_path,
|
||||
moddata->replica_server_password,
|
||||
moddata->replica_logical_db,
|
||||
moddata->replica_connect_timeout,
|
||||
moddata->replica_command_timeout,
|
||||
&moddata->replica_reconnect_interval,
|
||||
&moddata->replica_reconnect_attempts,
|
||||
&moddata->replica_reconnect_wait,
|
||||
&moddata->replica_wait_lock,
|
||||
env->now_tv,
|
||||
"replica ");
|
||||
if(!ctx) {
|
||||
log_err("redis_init: failed to init redis "
|
||||
"replica (for thread %d)", i);
|
||||
/* And continue, the context can be established
|
||||
* later, just like after a disconnect. */
|
||||
}
|
||||
moddata->replica_ctxs[i] = ctx;
|
||||
}
|
||||
}
|
||||
/* 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;
|
||||
if(env->cfg->redis_expire_records) {
|
||||
if(env->cfg->redis_expire_records &&
|
||||
moddata->ctxs[env->alloc->thread_num] != NULL) {
|
||||
redisReply* rep = NULL;
|
||||
int redis_reply_type = 0;
|
||||
/** check if setex command is supported */
|
||||
/** check if set with ex command is supported */
|
||||
rep = redis_command(env, cachedb_env,
|
||||
"SETEX __UNBOUND_REDIS_CHECK__ 1 none", NULL, 0);
|
||||
"SET __UNBOUND_REDIS_CHECK__ none EX 1", NULL, 0, 1);
|
||||
if(!rep) {
|
||||
/** init failed, no response from redis server*/
|
||||
log_err("redis_init: failed to init redis, the "
|
||||
"redis-expire-records option requires the SETEX command "
|
||||
"(redis >= 2.0.0)");
|
||||
return 0;
|
||||
goto set_with_ex_fail;
|
||||
}
|
||||
redis_reply_type = rep->type;
|
||||
freeReplyObject(rep);
|
||||
@@ -136,15 +388,21 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
case REDIS_REPLY_STATUS:
|
||||
break;
|
||||
default:
|
||||
/** init failed, setex command not supported */
|
||||
log_err("redis_init: failed to init redis, the "
|
||||
"redis-expire-records option requires the SETEX command "
|
||||
"(redis >= 2.0.0)");
|
||||
return 0;
|
||||
/** init failed, set_with_ex command not supported */
|
||||
goto set_with_ex_fail;
|
||||
}
|
||||
moddata->set_with_ex_available = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
set_with_ex_fail:
|
||||
log_err("redis_init: failure during redis_init, the "
|
||||
"redis-expire-records option requires the SET with EX command "
|
||||
"(redis >= 2.6.12)");
|
||||
return 1;
|
||||
fail:
|
||||
moddata_clean(&moddata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -154,19 +412,8 @@ redis_deinit(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
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);
|
||||
verbose(VERB_OPS, "Redis deinitialization");
|
||||
moddata_clean(&moddata);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -183,9 +430,9 @@ redis_deinit(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
*/
|
||||
static redisReply*
|
||||
redis_command(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
const char* command, const uint8_t* data, size_t data_len)
|
||||
const char* command, const uint8_t* data, size_t data_len, int write)
|
||||
{
|
||||
redisContext* ctx;
|
||||
redisContext* ctx, **ctx_selector;
|
||||
redisReply* rep;
|
||||
struct redis_moddata* d = (struct redis_moddata*)
|
||||
cachedb_env->backend_data;
|
||||
@@ -196,17 +443,50 @@ redis_command(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
* 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];
|
||||
|
||||
ctx_selector = !write && d->replica_ctxs
|
||||
?d->replica_ctxs
|
||||
:d->ctxs;
|
||||
ctx = ctx_selector[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(!write && d->replica_ctxs) {
|
||||
ctx = redis_connect(
|
||||
d->replica_server_host,
|
||||
d->replica_server_port,
|
||||
d->replica_server_path,
|
||||
d->replica_server_password,
|
||||
d->replica_logical_db,
|
||||
d->replica_connect_timeout,
|
||||
d->replica_command_timeout,
|
||||
&d->replica_reconnect_interval,
|
||||
&d->replica_reconnect_attempts,
|
||||
&d->replica_reconnect_wait,
|
||||
&d->replica_wait_lock,
|
||||
env->now_tv,
|
||||
"replica ");
|
||||
} else {
|
||||
ctx = redis_connect(
|
||||
d->server_host,
|
||||
d->server_port,
|
||||
d->server_path,
|
||||
d->server_password,
|
||||
d->logical_db,
|
||||
d->connect_timeout,
|
||||
d->command_timeout,
|
||||
&d->reconnect_interval,
|
||||
&d->reconnect_attempts,
|
||||
&d->reconnect_wait,
|
||||
&d->wait_lock,
|
||||
env->now_tv,
|
||||
"");
|
||||
}
|
||||
ctx_selector[env->alloc->thread_num] = ctx;
|
||||
}
|
||||
if(!ctx)
|
||||
return NULL;
|
||||
if(!ctx) return NULL;
|
||||
|
||||
/* Send the command and get a reply, synchronously. */
|
||||
rep = (redisReply*)redisCommand(ctx, command, data, data_len);
|
||||
@@ -216,7 +496,7 @@ redis_command(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
log_err("redis_command: failed to receive a reply, "
|
||||
"closing connection: %s", ctx->errstr);
|
||||
redisFree(ctx);
|
||||
d->ctxs[env->alloc->thread_num] = NULL;
|
||||
ctx_selector[env->alloc->thread_num] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -234,7 +514,14 @@ 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 */
|
||||
/* Supported commands:
|
||||
* - "GET " + key
|
||||
*/
|
||||
#define REDIS_LOOKUP_MAX_BUF_LEN \
|
||||
4 /* "GET " */ \
|
||||
+(CACHEDB_HASHSIZE/8)*2 /* key hash */ \
|
||||
+ 1 /* \0 */
|
||||
char cmdbuf[REDIS_LOOKUP_MAX_BUF_LEN];
|
||||
int n;
|
||||
int ret = 0;
|
||||
|
||||
@@ -246,7 +533,7 @@ redis_lookup(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
return 0;
|
||||
}
|
||||
|
||||
rep = redis_command(env, cachedb_env, cmdbuf, NULL, 0);
|
||||
rep = redis_command(env, cachedb_env, cmdbuf, NULL, 0, 0);
|
||||
if(!rep)
|
||||
return 0;
|
||||
switch(rep->type) {
|
||||
@@ -283,26 +570,45 @@ redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
{
|
||||
redisReply* rep;
|
||||
int n;
|
||||
int set_ttl = (env->cfg->redis_expire_records &&
|
||||
struct redis_moddata* moddata = (struct redis_moddata*)
|
||||
cachedb_env->backend_data;
|
||||
int set_ttl = (moddata->set_with_ex_available &&
|
||||
env->cfg->redis_expire_records &&
|
||||
(!env->cfg->serve_expired || env->cfg->serve_expired_ttl > 0));
|
||||
/* Supported commands:
|
||||
* - "SET " + key + " %b"
|
||||
* - "SETEX " + key + " " + ttl + " %b"
|
||||
* - "SET " + key + " %b EX " + ttl
|
||||
* older redis 2.0.0 was "SETEX " + key + " " + ttl + " %b"
|
||||
* - "EXPIRE " + key + " 0"
|
||||
*/
|
||||
char cmdbuf[6+(CACHEDB_HASHSIZE/8)*2+11+3+1];
|
||||
#define REDIS_STORE_MAX_BUF_LEN \
|
||||
7 /* "EXPIRE " */ \
|
||||
+(CACHEDB_HASHSIZE/8)*2 /* key hash */ \
|
||||
+ 7 /* " %b EX " */ \
|
||||
+ 20 /* ttl (uint64_t) */ \
|
||||
+ 1 /* \0 */
|
||||
char cmdbuf[REDIS_STORE_MAX_BUF_LEN];
|
||||
|
||||
if (!set_ttl) {
|
||||
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);
|
||||
} else if(ttl == 0) {
|
||||
/* use the EXPIRE command, SET with EX 0 is an invalid time. */
|
||||
/* Replies with REDIS_REPLY_INTEGER of 1. */
|
||||
verbose(VERB_ALGO, "redis_store expire %s (%d bytes)",
|
||||
key, (int)data_len);
|
||||
n = snprintf(cmdbuf, sizeof(cmdbuf), "EXPIRE %s 0", key);
|
||||
data = NULL;
|
||||
data_len = 0;
|
||||
} else {
|
||||
/* add expired ttl time to redis ttl to avoid premature eviction of key */
|
||||
ttl += env->cfg->serve_expired_ttl;
|
||||
verbose(VERB_ALGO, "redis_store %s (%d bytes) with ttl %u",
|
||||
key, (int)data_len, (uint32_t)ttl);
|
||||
key, (int)data_len, (unsigned)(uint32_t)ttl);
|
||||
/* build command to set to a binary safe string */
|
||||
n = snprintf(cmdbuf, sizeof(cmdbuf), "SETEX %s %u %%b", key,
|
||||
(uint32_t)ttl);
|
||||
n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b EX %u", key,
|
||||
(unsigned)(uint32_t)ttl);
|
||||
}
|
||||
|
||||
|
||||
@@ -311,11 +617,12 @@ redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
return;
|
||||
}
|
||||
|
||||
rep = redis_command(env, cachedb_env, cmdbuf, data, data_len);
|
||||
rep = redis_command(env, cachedb_env, cmdbuf, data, data_len, 1);
|
||||
if(rep) {
|
||||
verbose(VERB_ALGO, "redis_store set completed");
|
||||
if(rep->type != REDIS_REPLY_STATUS &&
|
||||
rep->type != REDIS_REPLY_ERROR) {
|
||||
rep->type != REDIS_REPLY_ERROR &&
|
||||
rep->type != REDIS_REPLY_INTEGER) {
|
||||
log_err("redis_store: unexpected type of reply (%d)",
|
||||
rep->type);
|
||||
}
|
||||
|
||||
+14
-1
@@ -38,6 +38,9 @@
|
||||
#ifndef UB_ON_WINDOWS
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
#ifdef __QNX__
|
||||
#include "util/log.h"
|
||||
#endif /* __QNX__ */
|
||||
|
||||
#define KEYSTREAM_ONLY
|
||||
#include "chacha_private.h"
|
||||
@@ -57,6 +60,8 @@
|
||||
#define BLOCKSZ 64
|
||||
#define RSBUFSZ (16*BLOCKSZ)
|
||||
|
||||
#define REKEY_BASE (1024*1024) /* NB. should be a power of 2 */
|
||||
|
||||
/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */
|
||||
static struct {
|
||||
size_t rs_have; /* valid bytes at end of rs_buf */
|
||||
@@ -179,12 +184,17 @@ static void
|
||||
_rs_stir(void)
|
||||
{
|
||||
u_char rnd[KEYSZ + IVSZ];
|
||||
uint32_t rekey_fuzz = 0;
|
||||
|
||||
if (getentropy(rnd, sizeof rnd) == -1) {
|
||||
if(errno != ENOSYS ||
|
||||
fallback_getentropy_urandom(rnd, sizeof rnd) == -1) {
|
||||
#ifdef SIGKILL
|
||||
#ifndef __QNX__
|
||||
raise(SIGKILL);
|
||||
#else /* !__QNX__ */
|
||||
fatal_exit("failed to getentropy");
|
||||
#endif /* __QNX__ */
|
||||
#else
|
||||
exit(9); /* windows */
|
||||
#endif
|
||||
@@ -201,7 +211,10 @@ _rs_stir(void)
|
||||
rs->rs_have = 0;
|
||||
memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
|
||||
|
||||
rs->rs_count = 1600000;
|
||||
/* rekey interval should not be predictable */
|
||||
chacha_encrypt_bytes(&rsx->rs_chacha, (uint8_t *)&rekey_fuzz,
|
||||
(uint8_t *)&rekey_fuzz, sizeof(rekey_fuzz));
|
||||
rs->rs_count = REKEY_BASE + (rekey_fuzz % REKEY_BASE);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
||||
@@ -48,8 +48,8 @@ typedef struct
|
||||
a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
|
||||
c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
|
||||
|
||||
static const char sigma[16] = "expand 32-byte k";
|
||||
static const char tau[16] = "expand 16-byte k";
|
||||
static const char ATTR_NONSTRING(sigma[16]) = "expand 32-byte k";
|
||||
static const char ATTR_NONSTRING(tau[16]) = "expand 16-byte k";
|
||||
|
||||
static void
|
||||
chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ATTR_UNUSED(ivbits))
|
||||
|
||||
@@ -57,7 +57,7 @@ int getnameinfo(const struct sockaddr *sa, size_t ATTR_UNUSED(salen), char *host
|
||||
}
|
||||
|
||||
if (host != NULL) {
|
||||
if (flags & NI_NUMERICHOST) {
|
||||
if ((flags & NI_NUMERICHOST)) {
|
||||
if (strlcpy(host, inet_ntoa(sin->sin_addr),
|
||||
hostlen) >= hostlen)
|
||||
return (EAI_MEMORY);
|
||||
@@ -168,7 +168,7 @@ getaddrinfo(const char *hostname, const char *servname,
|
||||
port = 0;
|
||||
}
|
||||
|
||||
if (hints && hints->ai_flags & AI_PASSIVE) {
|
||||
if (hints && (hints->ai_flags & AI_PASSIVE)) {
|
||||
addr = htonl(0x00000000);
|
||||
if (hostname && inet_aton(hostname, &in) != 0)
|
||||
addr = in.s_addr;
|
||||
@@ -193,7 +193,7 @@ getaddrinfo(const char *hostname, const char *servname,
|
||||
}
|
||||
|
||||
/* Don't try DNS if AI_NUMERICHOST is set */
|
||||
if (hints && hints->ai_flags & AI_NUMERICHOST)
|
||||
if (hints && (hints->ai_flags & AI_NUMERICHOST))
|
||||
return (EAI_NONAME);
|
||||
|
||||
hp = gethostbyname(hostname);
|
||||
|
||||
@@ -29,7 +29,9 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/resource.h>
|
||||
#ifndef __QNX__
|
||||
#include <sys/syscall.h>
|
||||
#endif /* !__QNX__ */
|
||||
#ifdef SYS__sysctl
|
||||
#include <linux/sysctl.h>
|
||||
#endif
|
||||
@@ -42,7 +44,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#ifndef __QNX__
|
||||
#include <link.h>
|
||||
#endif /* __QNX__ */
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
@@ -60,12 +64,14 @@
|
||||
#define SHA512_Final(r, c) sha512_digest(c, SHA512_DIGEST_SIZE, r)
|
||||
#endif
|
||||
|
||||
#ifndef __QNX__
|
||||
#include <linux/types.h>
|
||||
#include <linux/random.h>
|
||||
#ifdef HAVE_GETAUXVAL
|
||||
#include <sys/auxv.h>
|
||||
#endif
|
||||
#include <sys/vfs.h>
|
||||
#endif /* !__QNX__ */
|
||||
#ifndef MAP_ANON
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
#endif
|
||||
@@ -94,8 +100,10 @@ static int getentropy_urandom(void *buf, size_t len);
|
||||
#ifdef SYS__sysctl
|
||||
static int getentropy_sysctl(void *buf, size_t len);
|
||||
#endif
|
||||
#ifndef __QNX__
|
||||
static int getentropy_fallback(void *buf, size_t len);
|
||||
static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
|
||||
#endif /* !__QNX__ */
|
||||
|
||||
int
|
||||
getentropy(void *buf, size_t len)
|
||||
@@ -178,6 +186,7 @@ getentropy(void *buf, size_t len)
|
||||
* sysctl ABI, or consider providing a new failsafe API which
|
||||
* works in a chroot or when file descriptors are exhausted.
|
||||
*/
|
||||
#ifndef __QNX__
|
||||
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
|
||||
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
|
||||
raise(SIGKILL);
|
||||
@@ -185,6 +194,9 @@ getentropy(void *buf, size_t len)
|
||||
ret = getentropy_fallback(buf, len);
|
||||
if (ret != -1)
|
||||
return (ret);
|
||||
#else /* !__QNX__ */
|
||||
fatal_exit("failed to read from /dev/urandom");
|
||||
#endif /* __QNX__ */
|
||||
|
||||
errno = EIO;
|
||||
return (ret);
|
||||
@@ -214,7 +226,11 @@ getentropy_urandom(void *buf, size_t len)
|
||||
{
|
||||
struct stat st;
|
||||
size_t i;
|
||||
#ifndef __QNX__
|
||||
int fd, cnt, flags;
|
||||
#else /* !__QNX__ */
|
||||
int fd, flags;
|
||||
#endif /* __QNX__ */
|
||||
int save_errno = errno;
|
||||
|
||||
start:
|
||||
@@ -241,10 +257,12 @@ start:
|
||||
close(fd);
|
||||
goto nodevrandom;
|
||||
}
|
||||
#ifndef __QNX__
|
||||
if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
|
||||
close(fd);
|
||||
goto nodevrandom;
|
||||
}
|
||||
#endif /* !__QNX__ */
|
||||
for (i = 0; i < len; ) {
|
||||
size_t wanted = len - i;
|
||||
ssize_t ret = read(fd, (char *)buf + i, wanted);
|
||||
@@ -265,6 +283,7 @@ nodevrandom:
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#ifndef __QNX__
|
||||
#ifdef SYS__sysctl
|
||||
static int
|
||||
getentropy_sysctl(void *buf, size_t len)
|
||||
@@ -537,3 +556,4 @@ getentropy_fallback(void *buf, size_t len)
|
||||
errno = save_errno;
|
||||
return (0); /* satisfied */
|
||||
}
|
||||
#endif /* !__QNX__ */
|
||||
|
||||
+9
-382
@@ -20,398 +20,25 @@
|
||||
* http://man.openbsd.org/getentropy.2
|
||||
*/
|
||||
|
||||
#include <TargetConditionals.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
/* Modified to use SecRandomCopyBytes. It is from macOS 10.7 (2011) and
|
||||
* iOS 2.0 (2008), and is the primary API for cryptographic random numbers. */
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#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)))
|
||||
#define SHA512_Final(xxx, yyy) (CC_SHA512_Final((xxx), (yyy)))
|
||||
#define SHA512_CTX CC_SHA512_CTX
|
||||
#define SHA512_DIGEST_LENGTH CC_SHA512_DIGEST_LENGTH
|
||||
|
||||
#define REPEAT 5
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
#define HX(a, b) \
|
||||
do { \
|
||||
if ((a)) \
|
||||
HD(errno); \
|
||||
else \
|
||||
HD(b); \
|
||||
} while (0)
|
||||
|
||||
#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*)))
|
||||
#include <Security/SecRandom.h>
|
||||
|
||||
int getentropy(void *buf, size_t len);
|
||||
|
||||
static int getentropy_urandom(void *buf, size_t len);
|
||||
static int getentropy_fallback(void *buf, size_t len);
|
||||
|
||||
int
|
||||
getentropy(void *buf, size_t len)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
if (len > 256) {
|
||||
errno = EIO;
|
||||
return (-1);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to get entropy with /dev/urandom
|
||||
*
|
||||
* This can fail if the process is inside a chroot or if file
|
||||
* descriptors are exhausted.
|
||||
*/
|
||||
ret = getentropy_urandom(buf, len);
|
||||
if (ret != -1)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
* Entropy collection via /dev/urandom and sysctl have failed.
|
||||
*
|
||||
* No other API exists for collecting entropy, and we have
|
||||
* no failsafe way to get it on OSX that is not sensitive
|
||||
* to resource exhaustion.
|
||||
*
|
||||
* We have very few options:
|
||||
* - Even syslog_r is unsafe to call at this low level, so
|
||||
* there is no way to alert the user or program.
|
||||
* - Cannot call abort() because some systems have unsafe
|
||||
* corefiles.
|
||||
* - Could raise(SIGKILL) resulting in silent program termination.
|
||||
* - Return EIO, to hint that arc4random's stir function
|
||||
* should raise(SIGKILL)
|
||||
* - Do the best under the circumstances....
|
||||
*
|
||||
* This code path exists to bring light to the issue that OSX
|
||||
* does not provide a failsafe API for entropy collection.
|
||||
*
|
||||
* We hope this demonstrates that OSX should consider
|
||||
* providing a new failsafe API which works in a chroot or
|
||||
* when file descriptors are exhausted.
|
||||
*/
|
||||
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
|
||||
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
|
||||
raise(SIGKILL);
|
||||
#endif
|
||||
ret = getentropy_fallback(buf, len);
|
||||
if (ret != -1)
|
||||
return (ret);
|
||||
if (SecRandomCopyBytes(kSecRandomDefault, len, buf) == errSecSuccess) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
error:
|
||||
errno = EIO;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
getentropy_urandom(void *buf, size_t len)
|
||||
{
|
||||
struct stat st;
|
||||
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
|
||||
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
/* Lightly verify that the device node looks sane */
|
||||
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
|
||||
close(fd);
|
||||
goto nodevrandom;
|
||||
}
|
||||
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);
|
||||
errno = save_errno;
|
||||
return (0); /* satisfied */
|
||||
nodevrandom:
|
||||
errno = EIO;
|
||||
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 };
|
||||
|
||||
static int
|
||||
getentropy_fallback(void *buf, size_t len)
|
||||
{
|
||||
uint8_t results[SHA512_DIGEST_LENGTH];
|
||||
int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
|
||||
static int cnt;
|
||||
struct timespec ts;
|
||||
struct timeval tv;
|
||||
struct rusage ru;
|
||||
sigset_t sigset;
|
||||
struct stat st;
|
||||
SHA512_CTX ctx;
|
||||
static pid_t lastpid;
|
||||
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;
|
||||
|
||||
pid = getpid();
|
||||
if (lastpid == pid) {
|
||||
faster = 1;
|
||||
repeat = 2;
|
||||
} else {
|
||||
faster = 0;
|
||||
lastpid = pid;
|
||||
repeat = REPEAT;
|
||||
}
|
||||
for (i = 0; i < len; ) {
|
||||
int j;
|
||||
SHA512_Init(&ctx);
|
||||
for (j = 0; j < repeat; j++) {
|
||||
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
|
||||
if (e != -1) {
|
||||
cnt += (int)tv.tv_sec;
|
||||
cnt += (int)tv.tv_usec;
|
||||
}
|
||||
|
||||
mach_time = mach_absolute_time();
|
||||
HD(mach_time);
|
||||
|
||||
ii = sizeof(addr);
|
||||
HX(sysctl(kmib, sizeof(kmib) / sizeof(kmib[0]),
|
||||
&addr, &ii, NULL, 0) == -1, addr);
|
||||
|
||||
ii = sizeof(idata);
|
||||
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);
|
||||
|
||||
ii = sizeof(udpstat);
|
||||
HX(sysctl(udpmib, sizeof(udpmib) / sizeof(udpmib[0]),
|
||||
&udpstat, &ii, NULL, 0) == -1, udpstat);
|
||||
|
||||
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);
|
||||
HX((pid = getppid()) == -1, pid);
|
||||
HX((pid = getpgid(0)) == -1, pid);
|
||||
HX((e = getpriority(0, 0)) == -1, e);
|
||||
|
||||
if (!faster) {
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 1;
|
||||
(void) nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
HX(sigpending(&sigset) == -1, sigset);
|
||||
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
|
||||
sigset);
|
||||
|
||||
HF(getentropy); /* an addr in this library */
|
||||
HF(printf); /* an addr in libc */
|
||||
p = (char *)&p;
|
||||
HD(p); /* an addr on stack */
|
||||
p = (char *)&errno;
|
||||
HD(p); /* the addr of errno */
|
||||
|
||||
if (i == 0) {
|
||||
struct sockaddr_storage ss;
|
||||
struct statvfs stvfs;
|
||||
struct termios tios;
|
||||
struct statfs stfs;
|
||||
socklen_t ssl;
|
||||
off_t off;
|
||||
|
||||
/*
|
||||
* Prime-sized mappings encourage fragmentation;
|
||||
* thus exposing some address entropy.
|
||||
*/
|
||||
struct mm {
|
||||
size_t npg;
|
||||
void *p;
|
||||
} mm[] = {
|
||||
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
|
||||
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
|
||||
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
|
||||
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
|
||||
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
|
||||
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
|
||||
};
|
||||
|
||||
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
|
||||
HX(mm[m].p = mmap(NULL,
|
||||
mm[m].npg * pgs,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_PRIVATE|MAP_ANON, -1,
|
||||
(off_t)0), mm[m].p);
|
||||
if (mm[m].p != MAP_FAILED) {
|
||||
size_t mo;
|
||||
|
||||
/* Touch some memory... */
|
||||
p = mm[m].p;
|
||||
mo = cnt %
|
||||
(mm[m].npg * pgs - 1);
|
||||
p[mo] = 1;
|
||||
cnt += (int)((long)(mm[m].p)
|
||||
/ pgs);
|
||||
}
|
||||
|
||||
/* Check cnts and times... */
|
||||
mach_time = mach_absolute_time();
|
||||
HD(mach_time);
|
||||
cnt += (int)mach_time;
|
||||
|
||||
HX((e = getrusage(RUSAGE_SELF,
|
||||
&ru)) == -1, ru);
|
||||
if (e != -1) {
|
||||
cnt += (int)ru.ru_utime.tv_sec;
|
||||
cnt += (int)ru.ru_utime.tv_usec;
|
||||
}
|
||||
}
|
||||
|
||||
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
|
||||
if (mm[m].p != MAP_FAILED)
|
||||
munmap(mm[m].p, mm[m].npg * pgs);
|
||||
mm[m].p = MAP_FAILED;
|
||||
}
|
||||
|
||||
HX(stat(".", &st) == -1, st);
|
||||
HX(statvfs(".", &stvfs) == -1, stvfs);
|
||||
HX(statfs(".", &stfs) == -1, stfs);
|
||||
|
||||
HX(stat("/", &st) == -1, st);
|
||||
HX(statvfs("/", &stvfs) == -1, stvfs);
|
||||
HX(statfs("/", &stfs) == -1, stfs);
|
||||
|
||||
HX((e = fstat(0, &st)) == -1, st);
|
||||
if (e == -1) {
|
||||
if (S_ISREG(st.st_mode) ||
|
||||
S_ISFIFO(st.st_mode) ||
|
||||
S_ISSOCK(st.st_mode)) {
|
||||
HX(fstatvfs(0, &stvfs) == -1,
|
||||
stvfs);
|
||||
HX(fstatfs(0, &stfs) == -1,
|
||||
stfs);
|
||||
HX((off = lseek(0, (off_t)0,
|
||||
SEEK_CUR)) < 0, off);
|
||||
}
|
||||
if (S_ISCHR(st.st_mode)) {
|
||||
HX(tcgetattr(0, &tios) == -1,
|
||||
tios);
|
||||
} else if (S_ISSOCK(st.st_mode)) {
|
||||
memset(&ss, 0, sizeof ss);
|
||||
ssl = sizeof(ss);
|
||||
HX(getpeername(0,
|
||||
(void *)&ss, &ssl) == -1,
|
||||
ss);
|
||||
}
|
||||
}
|
||||
|
||||
HX((e = getrusage(RUSAGE_CHILDREN,
|
||||
&ru)) == -1, ru);
|
||||
if (e != -1) {
|
||||
cnt += (int)ru.ru_utime.tv_sec;
|
||||
cnt += (int)ru.ru_utime.tv_usec;
|
||||
}
|
||||
} else {
|
||||
/* Subsequent hashes absorb previous result */
|
||||
HD(results);
|
||||
}
|
||||
|
||||
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
|
||||
if (e != -1) {
|
||||
cnt += (int)tv.tv_sec;
|
||||
cnt += (int)tv.tv_usec;
|
||||
}
|
||||
|
||||
HD(cnt);
|
||||
}
|
||||
|
||||
SHA512_Final(results, &ctx);
|
||||
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
|
||||
i += min(sizeof(results), len - i);
|
||||
}
|
||||
explicit_bzero(&ctx, sizeof ctx);
|
||||
explicit_bzero(results, sizeof results);
|
||||
errno = save_errno;
|
||||
return (0); /* satisfied */
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
#define SHA512_Update SHA512Update
|
||||
#define SHA512_Final SHA512Final
|
||||
#else
|
||||
#include "openssl/sha.h"
|
||||
#include <openssl/sha.h>
|
||||
#endif
|
||||
|
||||
#include <sys/vfs.h>
|
||||
|
||||
+1
-4
@@ -42,10 +42,7 @@ static const int year_lengths[2] = {
|
||||
};
|
||||
|
||||
static void
|
||||
timesub(timep, offset, tmp)
|
||||
const time_t * const timep;
|
||||
const long offset;
|
||||
struct tm * const tmp;
|
||||
timesub(const time_t * const timep, const long offset, struct tm * const tmp)
|
||||
{
|
||||
long days;
|
||||
long rem;
|
||||
|
||||
+3
-10
@@ -59,10 +59,7 @@ static int inet_pton6 (const char *src, uint8_t *dst);
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
int
|
||||
inet_pton(af, src, dst)
|
||||
int af;
|
||||
const char *src;
|
||||
void *dst;
|
||||
inet_pton(int af, const char *src, void *dst)
|
||||
{
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
@@ -91,9 +88,7 @@ inet_pton(af, src, dst)
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static int
|
||||
inet_pton4(src, dst)
|
||||
const char *src;
|
||||
uint8_t *dst;
|
||||
inet_pton4(const char *src, uint8_t *dst)
|
||||
{
|
||||
static const char digits[] = "0123456789";
|
||||
int saw_digit, octets, ch;
|
||||
@@ -145,9 +140,7 @@ inet_pton4(src, dst)
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static int
|
||||
inet_pton6(src, dst)
|
||||
const char *src;
|
||||
uint8_t *dst;
|
||||
inet_pton6(const char *src, uint8_t *dst)
|
||||
{
|
||||
static const char xdigits_l[] = "0123456789abcdef",
|
||||
xdigits_u[] = "0123456789ABCDEF";
|
||||
|
||||
@@ -5,12 +5,8 @@
|
||||
#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. */
|
||||
|
||||
Vendored
+704
-559
File diff suppressed because it is too large
Load Diff
+320
-34
@@ -1,5 +1,8 @@
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* apply the fallthrough attribute. */
|
||||
#undef ATTR_FALLTHROUGH
|
||||
|
||||
/* apply the noreturn attribute to a function that exits the program */
|
||||
#undef ATTR_NORETURN
|
||||
|
||||
@@ -28,6 +31,9 @@
|
||||
/* Whether daemon is deprecated */
|
||||
#undef DEPRECATED_DAEMON
|
||||
|
||||
/* Whether X509_NAME_get_text_by_NID is deprecated */
|
||||
#undef DEPRECATED_X509_NAME_GET_TEXT_BY_NID
|
||||
|
||||
/* Deprecate RSA 1024 bit length, makes that an unsupported key */
|
||||
#undef DEPRECATE_RSA_1024
|
||||
|
||||
@@ -57,9 +63,18 @@
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#undef HAVE_ARPA_INET_H
|
||||
|
||||
/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
|
||||
#undef HAVE_ASN1_STRING_GET0_DATA
|
||||
|
||||
/* Whether the C compiler accepts the "fallthrough" attribute */
|
||||
#undef HAVE_ATTR_FALLTHROUGH
|
||||
|
||||
/* Whether the C compiler accepts the "format" attribute */
|
||||
#undef HAVE_ATTR_FORMAT
|
||||
|
||||
/* Whether the C compiler accepts the "nonstring" attribute */
|
||||
#undef HAVE_ATTR_NONSTRING
|
||||
|
||||
/* Whether the C compiler accepts the "noreturn" attribute */
|
||||
#undef HAVE_ATTR_NORETURN
|
||||
|
||||
@@ -72,6 +87,9 @@
|
||||
/* If we have be64toh */
|
||||
#undef HAVE_BE64TOH
|
||||
|
||||
/* Define to 1 if you have the `BIO_set_callback_ex' function. */
|
||||
#undef HAVE_BIO_SET_CALLBACK_EX
|
||||
|
||||
/* Define to 1 if you have the <bsd/stdlib.h> header file. */
|
||||
#undef HAVE_BSD_STDLIB_H
|
||||
|
||||
@@ -120,6 +138,18 @@
|
||||
and to 0 if you don't. */
|
||||
#undef HAVE_DECL_NGHTTP2_SESSION_SERVER_NEW
|
||||
|
||||
/* Define to 1 if you have the declaration of `ngtcp2_conn_server_new', and to
|
||||
0 if you don't. */
|
||||
#undef HAVE_DECL_NGTCP2_CONN_SERVER_NEW
|
||||
|
||||
/* Define to 1 if you have the declaration of `ngtcp2_crypto_encrypt_cb', and
|
||||
to 0 if you don't. */
|
||||
#undef HAVE_DECL_NGTCP2_CRYPTO_ENCRYPT_CB
|
||||
|
||||
/* Define to 1 if you have the declaration of `ngtcp2_crypto_ossl_ctx_new',
|
||||
and to 0 if you don't. */
|
||||
#undef HAVE_DECL_NGTCP2_CRYPTO_OSSL_CTX_NEW
|
||||
|
||||
/* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_NID_ED25519
|
||||
@@ -156,6 +186,10 @@
|
||||
0 if you don't. */
|
||||
#undef HAVE_DECL_SSL_CTX_SET_ECDH_AUTO
|
||||
|
||||
/* Define to 1 if you have the declaration of `SSL_CTX_set_tmp_ecdh', and to 0
|
||||
if you don't. */
|
||||
#undef HAVE_DECL_SSL_CTX_SET_TMP_ECDH
|
||||
|
||||
/* Define to 1 if you have the declaration of `strlcat', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_STRLCAT
|
||||
@@ -219,6 +253,10 @@
|
||||
/* Define to 1 if you have the `EVP_cleanup' function. */
|
||||
#undef HAVE_EVP_CLEANUP
|
||||
|
||||
/* Define to 1 if you have the `EVP_default_properties_is_fips_enabled'
|
||||
function. */
|
||||
#undef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED
|
||||
|
||||
/* Define to 1 if you have the `EVP_DigestVerify' function. */
|
||||
#undef HAVE_EVP_DIGESTVERIFY
|
||||
|
||||
@@ -261,6 +299,12 @@
|
||||
/* Define to 1 if you have the `FIPS_mode' function. */
|
||||
#undef HAVE_FIPS_MODE
|
||||
|
||||
/* Define to 1 if you have the `fnmatch' function. */
|
||||
#undef HAVE_FNMATCH
|
||||
|
||||
/* Define to 1 if you have the <fnmatch.h> header file. */
|
||||
#undef HAVE_FNMATCH_H
|
||||
|
||||
/* Define to 1 if you have the `fork' function. */
|
||||
#undef HAVE_FORK
|
||||
|
||||
@@ -291,6 +335,9 @@
|
||||
/* Define to 1 if you have the `getrlimit' function. */
|
||||
#undef HAVE_GETRLIMIT
|
||||
|
||||
/* Define to 1 if you have the `gettid' function. */
|
||||
#undef HAVE_GETTID
|
||||
|
||||
/* Define to 1 if you have the `glob' function. */
|
||||
#undef HAVE_GLOB
|
||||
|
||||
@@ -315,6 +362,9 @@
|
||||
/* Define to 1 if you have the <ifaddrs.h> header file. */
|
||||
#undef HAVE_IFADDRS_H
|
||||
|
||||
/* Define to 1 if you have the `if_nametoindex' function. */
|
||||
#undef HAVE_IF_NAMETOINDEX
|
||||
|
||||
/* Define to 1 if you have the `inet_aton' function. */
|
||||
#undef HAVE_INET_ATON
|
||||
|
||||
@@ -351,6 +401,12 @@
|
||||
/* Define if we have LibreSSL */
|
||||
#undef HAVE_LIBRESSL
|
||||
|
||||
/* If we have atomic_store */
|
||||
#undef HAVE_LINK_ATOMIC_STORE
|
||||
|
||||
/* Define to 1 if you have the <linux/net_tstamp.h> header file. */
|
||||
#undef HAVE_LINUX_NET_TSTAMP_H
|
||||
|
||||
/* Define to 1 if you have the `localtime_r' function. */
|
||||
#undef HAVE_LOCALTIME_R
|
||||
|
||||
@@ -363,8 +419,8 @@
|
||||
/* Define to 1 if you have the `memmove' function. */
|
||||
#undef HAVE_MEMMOVE
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
/* Define to 1 if you have the <minix/config.h> header file. */
|
||||
#undef HAVE_MINIX_CONFIG_H
|
||||
|
||||
/* Define to 1 if you have the <netdb.h> header file. */
|
||||
#undef HAVE_NETDB_H
|
||||
@@ -375,6 +431,9 @@
|
||||
/* Define to 1 if you have the <netinet/tcp.h> header file. */
|
||||
#undef HAVE_NETINET_TCP_H
|
||||
|
||||
/* Define to 1 if you have the <netioapi.h> header file. */
|
||||
#undef HAVE_NETIOAPI_H
|
||||
|
||||
/* Use libnettle for crypto */
|
||||
#undef HAVE_NETTLE
|
||||
|
||||
@@ -387,12 +446,80 @@
|
||||
/* Define to 1 if you have the <net/if.h> header file. */
|
||||
#undef HAVE_NET_IF_H
|
||||
|
||||
/* Define to 1 if you have the <net/pfvar.h> header file. */
|
||||
#undef HAVE_NET_PFVAR_H
|
||||
|
||||
/* Define this to use nghttp2 client. */
|
||||
#undef HAVE_NGHTTP2
|
||||
|
||||
/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
|
||||
#undef HAVE_NGHTTP2_NGHTTP2_H
|
||||
|
||||
/* Define this to use ngtcp2. */
|
||||
#undef HAVE_NGTCP2
|
||||
|
||||
/* Define to 1 if you have the `ngtcp2_ccerr_default' function. */
|
||||
#undef HAVE_NGTCP2_CCERR_DEFAULT
|
||||
|
||||
/* Define to 1 if you have the `ngtcp2_conn_encode_0rtt_transport_params'
|
||||
function. */
|
||||
#undef HAVE_NGTCP2_CONN_ENCODE_0RTT_TRANSPORT_PARAMS
|
||||
|
||||
/* Define to 1 if you have the `ngtcp2_conn_get_max_local_streams_uni'
|
||||
function. */
|
||||
#undef HAVE_NGTCP2_CONN_GET_MAX_LOCAL_STREAMS_UNI
|
||||
|
||||
/* Define to 1 if you have the `ngtcp2_conn_get_num_scid' function. */
|
||||
#undef HAVE_NGTCP2_CONN_GET_NUM_SCID
|
||||
|
||||
/* Define to 1 if you have the `ngtcp2_conn_in_closing_period' function. */
|
||||
#undef HAVE_NGTCP2_CONN_IN_CLOSING_PERIOD
|
||||
|
||||
/* Define to 1 if you have the `ngtcp2_conn_in_draining_period' function. */
|
||||
#undef HAVE_NGTCP2_CONN_IN_DRAINING_PERIOD
|
||||
|
||||
/* Define if ngtcp2_conn_shutdown_stream has 4 arguments. */
|
||||
#undef HAVE_NGTCP2_CONN_SHUTDOWN_STREAM4
|
||||
|
||||
/* Define to 1 if you have the `ngtcp2_conn_tls_early_data_rejected' function.
|
||||
*/
|
||||
#undef HAVE_NGTCP2_CONN_TLS_EARLY_DATA_REJECTED
|
||||
|
||||
/* Define to 1 if you have the `ngtcp2_crypto_encrypt_cb' function. */
|
||||
#undef HAVE_NGTCP2_CRYPTO_ENCRYPT_CB
|
||||
|
||||
/* Define to 1 if you have the
|
||||
`ngtcp2_crypto_quictls_configure_client_context' function. */
|
||||
#undef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_CLIENT_CONTEXT
|
||||
|
||||
/* Define to 1 if you have the
|
||||
`ngtcp2_crypto_quictls_configure_server_context' function. */
|
||||
#undef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_SERVER_CONTEXT
|
||||
|
||||
/* Define to 1 if you have the
|
||||
`ngtcp2_crypto_quictls_from_ossl_encryption_level' function. */
|
||||
#undef HAVE_NGTCP2_CRYPTO_QUICTLS_FROM_OSSL_ENCRYPTION_LEVEL
|
||||
|
||||
/* Define to 1 if you have the `ngtcp2_crypto_quictls_init' function. */
|
||||
#undef HAVE_NGTCP2_CRYPTO_QUICTLS_INIT
|
||||
|
||||
/* Define to 1 if the system has the type `ngtcp2_encryption_level'. */
|
||||
#undef HAVE_NGTCP2_ENCRYPTION_LEVEL
|
||||
|
||||
/* Define to 1 if you have the <ngtcp2/ngtcp2_crypto_openssl.h> header file.
|
||||
*/
|
||||
#undef HAVE_NGTCP2_NGTCP2_CRYPTO_OPENSSL_H
|
||||
|
||||
/* Define to 1 if you have the <ngtcp2/ngtcp2_crypto_ossl.h> header file. */
|
||||
#undef HAVE_NGTCP2_NGTCP2_CRYPTO_OSSL_H
|
||||
|
||||
/* Define to 1 if you have the <ngtcp2/ngtcp2_crypto_quictls.h> header file.
|
||||
*/
|
||||
#undef HAVE_NGTCP2_NGTCP2_CRYPTO_QUICTLS_H
|
||||
|
||||
/* Define to 1 if you have the <ngtcp2/ngtcp2.h> header file. */
|
||||
#undef HAVE_NGTCP2_NGTCP2_H
|
||||
|
||||
/* Use libnss for crypto */
|
||||
#undef HAVE_NSS
|
||||
|
||||
@@ -402,6 +529,9 @@
|
||||
/* Define to 1 if you have the <openssl/bn.h> header file. */
|
||||
#undef HAVE_OPENSSL_BN_H
|
||||
|
||||
/* Define to 1 if you have the `OPENSSL_cleanup' function. */
|
||||
#undef HAVE_OPENSSL_CLEANUP
|
||||
|
||||
/* Define to 1 if you have the `OPENSSL_config' function. */
|
||||
#undef HAVE_OPENSSL_CONFIG
|
||||
|
||||
@@ -444,15 +574,36 @@
|
||||
/* Define to 1 if you have the `OSSL_PARAM_BLD_new' function. */
|
||||
#undef HAVE_OSSL_PARAM_BLD_NEW
|
||||
|
||||
/* Define to 1 if you have the `poll' function. */
|
||||
#undef HAVE_POLL
|
||||
|
||||
/* Define to 1 if you have the <poll.h> header file. */
|
||||
#undef HAVE_POLL_H
|
||||
|
||||
/* Define if you have POSIX threads libraries and header files. */
|
||||
#undef HAVE_PTHREAD
|
||||
|
||||
/* Define to 1 if you have the <pthread_np.h> header file. */
|
||||
#undef HAVE_PTHREAD_NP_H
|
||||
|
||||
/* Have PTHREAD_PRIO_INHERIT. */
|
||||
#undef HAVE_PTHREAD_PRIO_INHERIT
|
||||
|
||||
/* Define to 1 if the system has the type `pthread_rwlock_t'. */
|
||||
#undef HAVE_PTHREAD_RWLOCK_T
|
||||
|
||||
/* Define if pthread_setname_np has the common 2 arguments. */
|
||||
#undef HAVE_PTHREAD_SETNAME_NP
|
||||
|
||||
/* Define if pthread_setname_np has only 1 argument. */
|
||||
#undef HAVE_PTHREAD_SETNAME_NP1
|
||||
|
||||
/* Define if pthread_setname_np has 3 arguments. */
|
||||
#undef HAVE_PTHREAD_SETNAME_NP3
|
||||
|
||||
/* Define if pthread_setname_np exists as pthread_set_name_np instead. */
|
||||
#undef HAVE_PTHREAD_SET_NAME_NP
|
||||
|
||||
/* Define to 1 if the system has the type `pthread_spinlock_t'. */
|
||||
#undef HAVE_PTHREAD_SPINLOCK_T
|
||||
|
||||
@@ -550,18 +701,34 @@
|
||||
/* Define to 1 if you have the `SSL_get1_peer_certificate' function. */
|
||||
#undef HAVE_SSL_GET1_PEER_CERTIFICATE
|
||||
|
||||
/* Define to 1 if you have the `SSL_is_quic' function. */
|
||||
#undef HAVE_SSL_IS_QUIC
|
||||
|
||||
/* Define to 1 if you have the `SSL_set1_dnsname' function. */
|
||||
#undef HAVE_SSL_SET1_DNSNAME
|
||||
|
||||
/* Define to 1 if you have the `SSL_set1_host' function. */
|
||||
#undef HAVE_SSL_SET1_HOST
|
||||
|
||||
/* Define to 1 if you have the `SSL_set_quic_tls_early_data_enabled' function.
|
||||
*/
|
||||
#undef HAVE_SSL_SET_QUIC_TLS_EARLY_DATA_ENABLED
|
||||
|
||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||
#undef HAVE_STDARG_H
|
||||
|
||||
/* Define to 1 if you have the <stdatomic.h> header file. */
|
||||
#undef HAVE_STDATOMIC_H
|
||||
|
||||
/* Define to 1 if you have the <stdbool.h> header file. */
|
||||
#undef HAVE_STDBOOL_H
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#undef HAVE_STDIO_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
@@ -589,9 +756,32 @@
|
||||
/* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */
|
||||
#undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST
|
||||
|
||||
/* Define to 1 if `tokenlen' is a member of `struct ngtcp2_pkt_hd'. */
|
||||
#undef HAVE_STRUCT_NGTCP2_PKT_HD_TOKENLEN
|
||||
|
||||
/* Define to 1 if `max_tx_udp_payload_size' is a member of `struct
|
||||
ngtcp2_settings'. */
|
||||
#undef HAVE_STRUCT_NGTCP2_SETTINGS_MAX_TX_UDP_PAYLOAD_SIZE
|
||||
|
||||
/* Define to 1 if `tokenlen' is a member of `struct ngtcp2_settings'. */
|
||||
#undef HAVE_STRUCT_NGTCP2_SETTINGS_TOKENLEN
|
||||
|
||||
/* Define to 1 if `original_dcid_present' is a member of `struct
|
||||
ngtcp2_transport_params'. */
|
||||
#undef HAVE_STRUCT_NGTCP2_TRANSPORT_PARAMS_ORIGINAL_DCID_PRESENT
|
||||
|
||||
/* Define to 1 if the system has the type `struct ngtcp2_version_cid'. */
|
||||
#undef HAVE_STRUCT_NGTCP2_VERSION_CID
|
||||
|
||||
/* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */
|
||||
#undef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
|
||||
|
||||
/* Define to 1 if `st_mtimensec' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_MTIMENSEC
|
||||
|
||||
/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
|
||||
|
||||
/* Define if you have Swig libraries and header files. */
|
||||
#undef HAVE_SWIG
|
||||
|
||||
@@ -664,6 +854,9 @@
|
||||
/* Define to 1 if you have the <vfork.h> header file. */
|
||||
#undef HAVE_VFORK_H
|
||||
|
||||
/* Define to 1 if you have the <wchar.h> header file. */
|
||||
#undef HAVE_WCHAR_H
|
||||
|
||||
/* Define to 1 if you have the <windows.h> header file. */
|
||||
#undef HAVE_WINDOWS_H
|
||||
|
||||
@@ -685,6 +878,12 @@
|
||||
/* Define to 1 if you have the <ws2tcpip.h> header file. */
|
||||
#undef HAVE_WS2TCPIP_H
|
||||
|
||||
/* Define to 1 if you have the `X509_get_key_usage' function. */
|
||||
#undef HAVE_X509_GET_KEY_USAGE
|
||||
|
||||
/* Define to 1 if you have the `X509_NAME_get_text_by_NID' function. */
|
||||
#undef HAVE_X509_NAME_GET_TEXT_BY_NID
|
||||
|
||||
/* Define to 1 if you have the `X509_VERIFY_PARAM_set1_host' function. */
|
||||
#undef HAVE_X509_VERIFY_PARAM_SET1_HOST
|
||||
|
||||
@@ -787,19 +986,27 @@
|
||||
/* Shared data */
|
||||
#undef SHARE_DIR
|
||||
|
||||
/* The size of `pthread_t', as computed by sizeof. */
|
||||
#undef SIZEOF_PTHREAD_T
|
||||
|
||||
/* 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
|
||||
|
||||
/* The size of `unsigned long', as computed by sizeof. */
|
||||
#undef SIZEOF_UNSIGNED_LONG
|
||||
|
||||
/* 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. */
|
||||
/* Define to 1 if all of the C90 standard headers exist (not just the ones
|
||||
required in a freestanding environment). This macro is provided for
|
||||
backward compatibility; new code need not use it. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* use default strptime. */
|
||||
@@ -879,6 +1086,9 @@
|
||||
/* Define this to enable client TCP Fast Open. */
|
||||
#undef USE_MSG_FASTOPEN
|
||||
|
||||
/* Define this to use ngtcp2_crypto_ossl. */
|
||||
#undef USE_NGTCP2_CRYPTO_OSSL
|
||||
|
||||
/* Define this to enable client TCP Fast Open. */
|
||||
#undef USE_OSX_MSG_FASTOPEN
|
||||
|
||||
@@ -895,21 +1105,87 @@
|
||||
#ifndef _ALL_SOURCE
|
||||
# undef _ALL_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on macOS. */
|
||||
#ifndef _DARWIN_C_SOURCE
|
||||
# undef _DARWIN_C_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
#endif
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# undef _GNU_SOURCE
|
||||
#endif
|
||||
/* Enable threading extensions on Solaris. */
|
||||
/* Enable X/Open compliant socket functions that do not require linking
|
||||
with -lxnet on HP-UX 11.11. */
|
||||
#ifndef _HPUX_ALT_XOPEN_SOCKET_API
|
||||
# undef _HPUX_ALT_XOPEN_SOCKET_API
|
||||
#endif
|
||||
/* Identify the host operating system as Minix.
|
||||
This macro does not affect the system headers' behavior.
|
||||
A future release of Autoconf may stop defining this macro. */
|
||||
#ifndef _MINIX
|
||||
# undef _MINIX
|
||||
#endif
|
||||
/* Enable general extensions on NetBSD.
|
||||
Enable NetBSD compatibility extensions on Minix. */
|
||||
#ifndef _NETBSD_SOURCE
|
||||
# undef _NETBSD_SOURCE
|
||||
#endif
|
||||
/* Enable OpenBSD compatibility extensions on NetBSD.
|
||||
Oddly enough, this does nothing on OpenBSD. */
|
||||
#ifndef _OPENBSD_SOURCE
|
||||
# undef _OPENBSD_SOURCE
|
||||
#endif
|
||||
/* Define to 1 if needed for POSIX-compatible behavior. */
|
||||
#ifndef _POSIX_SOURCE
|
||||
# undef _POSIX_SOURCE
|
||||
#endif
|
||||
/* Define to 2 if needed for POSIX-compatible behavior. */
|
||||
#ifndef _POSIX_1_SOURCE
|
||||
# undef _POSIX_1_SOURCE
|
||||
#endif
|
||||
/* Enable POSIX-compatible threading on Solaris. */
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# undef _POSIX_PTHREAD_SEMANTICS
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */
|
||||
#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */
|
||||
#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_BFP_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_DFP_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_FUNCS_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */
|
||||
#ifndef __STDC_WANT_LIB_EXT2__
|
||||
# undef __STDC_WANT_LIB_EXT2__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC 24747:2009. */
|
||||
#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
|
||||
# undef __STDC_WANT_MATH_SPEC_FUNCS__
|
||||
#endif
|
||||
/* Enable extensions on HP NonStop. */
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# undef _TANDEM_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
/* Enable X/Open extensions. Define to 500 only if necessary
|
||||
to make mbstate_t available. */
|
||||
#ifndef _XOPEN_SOURCE
|
||||
# undef _XOPEN_SOURCE
|
||||
#endif
|
||||
|
||||
|
||||
@@ -935,11 +1211,6 @@
|
||||
`char[]'. */
|
||||
#undef YYTEXT_POINTER
|
||||
|
||||
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||
# define _DARWIN_USE_64_BIT_INODE 1
|
||||
#endif
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#undef _FILE_OFFSET_BITS
|
||||
|
||||
@@ -949,18 +1220,12 @@
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#undef _LARGE_FILES
|
||||
|
||||
/* Define to 1 if on MINIX. */
|
||||
#undef _MINIX
|
||||
|
||||
/* Enable for compile on Minix */
|
||||
#undef _NETBSD_SOURCE
|
||||
|
||||
/* Define to 2 if the system does not provide POSIX.1 features except with
|
||||
this defined. */
|
||||
#undef _POSIX_1_SOURCE
|
||||
|
||||
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||
#undef _POSIX_SOURCE
|
||||
/* defined to use gcc ansi snprintf and sscanf that understands %lld when
|
||||
compiled for windows. */
|
||||
#undef __USE_MINGW_ANSI_STDIO
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#undef const
|
||||
@@ -998,7 +1263,7 @@
|
||||
/* Define to `long int' if <sys/types.h> does not define. */
|
||||
#undef off_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
/* Define as a signed integer type capable of holding a process identifier. */
|
||||
#undef pid_t
|
||||
|
||||
/* Define to 'int' if not defined */
|
||||
@@ -1036,39 +1301,39 @@
|
||||
|
||||
#if defined(OMITTED__D_GNU_SOURCE) && !defined(_GNU_SOURCE)
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_BSD_SOURCE) && !defined(_BSD_SOURCE)
|
||||
#define _BSD_SOURCE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_DEFAULT_SOURCE) && !defined(_DEFAULT_SOURCE)
|
||||
#define _DEFAULT_SOURCE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D__EXTENSIONS__) && !defined(__EXTENSIONS__)
|
||||
#define __EXTENSIONS__ 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_POSIX_C_SOURCE_200112) && !defined(_POSIX_C_SOURCE)
|
||||
#define _POSIX_C_SOURCE 200112
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_XOPEN_SOURCE_600) && !defined(_XOPEN_SOURCE)
|
||||
#define _XOPEN_SOURCE 600
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_XOPEN_SOURCE_EXTENDED_1) && !defined(_XOPEN_SOURCE_EXTENDED)
|
||||
#define _XOPEN_SOURCE_EXTENDED 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_ALL_SOURCE) && !defined(_ALL_SOURCE)
|
||||
#define _ALL_SOURCE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_LARGEFILE_SOURCE_1) && !defined(_LARGEFILE_SOURCE)
|
||||
#define _LARGEFILE_SOURCE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1141,7 +1406,7 @@
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#ifndef USE_WINSOCK
|
||||
#if !defined(USE_WINSOCK) || !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN) || defined(__USE_MINGW_ANSI_STDIO)
|
||||
#define ARG_LL "%ll"
|
||||
#else
|
||||
#define ARG_LL "%I64"
|
||||
@@ -1152,7 +1417,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_ATTR_FORMAT
|
||||
# define ATTR_FORMAT(archetype, string_index, first_to_check) \
|
||||
__attribute__ ((format (archetype, string_index, first_to_check)))
|
||||
@@ -1172,6 +1437,17 @@
|
||||
#endif /* !HAVE_ATTR_UNUSED */
|
||||
|
||||
|
||||
#if defined(DOXYGEN)
|
||||
# define ATTR_NONSTRING(x) x
|
||||
#elif defined(__cplusplus)
|
||||
# define ATTR_NONSTRING(x) __attribute__((nonstring)) x
|
||||
#elif defined(HAVE_ATTR_NONSTRING)
|
||||
# define ATTR_NONSTRING(x) __attribute__((nonstring)) x
|
||||
#else /* !HAVE_ATTR_NONSTRING */
|
||||
# define ATTR_NONSTRING(x) x
|
||||
#endif /* !HAVE_ATTR_NONSTRING */
|
||||
|
||||
|
||||
#ifndef HAVE_FSEEKO
|
||||
#define fseeko fseek
|
||||
#define ftello ftell
|
||||
@@ -1262,7 +1538,7 @@ void* reallocarray(void *ptr, size_t nmemb, size_t size);
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
#define FD_SET_T (u_int)
|
||||
#else
|
||||
#define FD_SET_T
|
||||
#define FD_SET_T
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1390,6 +1666,10 @@ struct sockaddr_storage;
|
||||
# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__)
|
||||
# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__)
|
||||
# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__)
|
||||
# define strdup(s) unbound_stat_strdup_log(s, __FILE__, __LINE__, __func__)
|
||||
#ifdef HAVE_REALLOCARRAY
|
||||
# define reallocarray(p,n,s) unbound_stat_reallocarray_log(p, n, s, __FILE__, __LINE__, __func__)
|
||||
#endif
|
||||
void *unbound_stat_malloc(size_t size);
|
||||
void *unbound_stat_calloc(size_t nmemb, size_t size);
|
||||
void unbound_stat_free(void *ptr);
|
||||
@@ -1402,6 +1682,10 @@ void unbound_stat_free_log(void *ptr, const char* file, int line,
|
||||
const char* func);
|
||||
void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
||||
int line, const char* func);
|
||||
void *unbound_stat_reallocarray_log(void *ptr, size_t nmemb, size_t size,
|
||||
const char* file, int line, const char* func);
|
||||
char *unbound_stat_strdup_log(const char *s, const char* file, int line,
|
||||
const char* func);
|
||||
#elif defined(UNBOUND_ALLOC_LITE)
|
||||
# include "util/alloc.h"
|
||||
#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */
|
||||
@@ -1412,6 +1696,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
||||
#define UNBOUND_DNS_OVER_TLS_PORT 853
|
||||
/** default port for DNS over HTTPS traffic. */
|
||||
#define UNBOUND_DNS_OVER_HTTPS_PORT 443
|
||||
/** default port for DNS over QUIC traffic. */
|
||||
#define UNBOUND_DNS_OVER_QUIC_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
+503
-325
File diff suppressed because it is too large
Load Diff
+486
-95
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
||||
FROM gcc:latest
|
||||
WORKDIR /usr/src/unbound
|
||||
# install semantic parser & lexical analyzer
|
||||
# install packages used in tests
|
||||
RUN apt-get update && apt-get install -y bison flex ldnsutils dnsutils xxd splint doxygen netcat-openbsd
|
||||
# accept short rsa keys, which are used in tests
|
||||
RUN sed -i 's/SECLEVEL=2/SECLEVEL=1/g' /usr/lib/ssl/openssl.cnf
|
||||
|
||||
CMD ["/bin/bash"]
|
||||
@@ -55,3 +55,8 @@ distribution but may be helpful.
|
||||
contributed by Andreas Schulze.
|
||||
* metrics.awk: awk script that can convert unbound-control stats to
|
||||
Prometheus metrics format output.
|
||||
* unbound.init_yocto: An init script to start and stop the server. Put it
|
||||
in /etc/init.d/unbound to use it. It is for the Yocto Project, in
|
||||
embedded systems, contributed by beni-sandu.
|
||||
* gost12.patch: adds ECC-GOST12 support for the informational RFC9558.
|
||||
Contributed by Igor V. Ruzanov.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in
|
||||
index f426ac5f..147fbfa9 100644
|
||||
index 172eb26c..2921c87f 100644
|
||||
--- a/doc/unbound.conf.5.in
|
||||
+++ b/doc/unbound.conf.5.in
|
||||
@@ -872,6 +872,13 @@ potentially broken nameservers. A lot of domains will not be resolvable when
|
||||
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 no.
|
||||
@@ -2146,6 +2146,13 @@ Default: no
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
+.B aaaa\-filter: \fI<yes or no>
|
||||
+Activate behavior similar to BIND's AAAA-filter.
|
||||
@@ -13,14 +13,14 @@ index f426ac5f..147fbfa9 100644
|
||||
+This also causes an additional A query to be sent for each AAAA query.
|
||||
+This breaks DNSSEC!
|
||||
+.TP
|
||||
.B aggressive\-nsec: \fI<yes or no>
|
||||
Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN
|
||||
and other denials, using information from previous NXDOMAINs answers.
|
||||
.B aggressive\-nsec: \fI<yes or no>\fP
|
||||
Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN and other
|
||||
denials, using information from previous NXDOMAINs answers.
|
||||
diff --git a/iterator/iter_scrub.c b/iterator/iter_scrub.c
|
||||
index aae934dd..55c55de0 100644
|
||||
index 49a5f5da..fbe434fa 100644
|
||||
--- a/iterator/iter_scrub.c
|
||||
+++ b/iterator/iter_scrub.c
|
||||
@@ -667,6 +667,32 @@ static int sanitize_nsec_is_overreach(struct rrset_parse* rrset,
|
||||
@@ -849,6 +849,32 @@ scrub_sanitize_rr_length(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -53,15 +53,15 @@ index aae934dd..55c55de0 100644
|
||||
/**
|
||||
* Given a response event, remove suspect RRsets from the response.
|
||||
* "Suspect" rrsets are potentially poison. Note that this routine expects
|
||||
@@ -686,6 +712,7 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
@@ -869,6 +895,7 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
struct query_info* qinfo, uint8_t* zonename, struct module_env* env,
|
||||
struct iter_env* ie)
|
||||
struct iter_env* ie, struct module_qstate* qstate)
|
||||
{
|
||||
+ int found_a_record = 0; /* ASN: do we have a A record? */
|
||||
int del_addi = 0; /* if additional-holding rrsets are deleted, we
|
||||
do not trust the normalized additional-A-AAAA any more */
|
||||
struct rrset_parse* rrset, *prev;
|
||||
@@ -721,6 +748,13 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
uint8_t* ns_rrset_dname = NULL;
|
||||
@@ -906,6 +933,13 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
rrset = rrset->rrset_all_next;
|
||||
}
|
||||
|
||||
@@ -75,9 +75,9 @@ index aae934dd..55c55de0 100644
|
||||
/* 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
|
||||
@@ -732,6 +766,24 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
rrset = msg->rrset_first;
|
||||
while(rrset) {
|
||||
@@ -925,6 +959,24 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
continue;
|
||||
}
|
||||
|
||||
+ /* ASN: For AAAA records only... */
|
||||
+ if((ie->aaaa_filter) && (rrset->type == LDNS_RR_TYPE_AAAA)) {
|
||||
@@ -101,24 +101,24 @@ index aae934dd..55c55de0 100644
|
||||
if( (rrset->type == LDNS_RR_TYPE_A ||
|
||||
rrset->type == LDNS_RR_TYPE_AAAA)) {
|
||||
diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c
|
||||
index 7bc67da6..e10f547a 100644
|
||||
index 1da21896..6583dd0e 100644
|
||||
--- a/iterator/iter_utils.c
|
||||
+++ b/iterator/iter_utils.c
|
||||
@@ -175,6 +175,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
}
|
||||
iter_env->supports_ipv6 = cfg->do_ip6;
|
||||
iter_env->supports_ipv4 = cfg->do_ip4;
|
||||
@@ -250,6 +250,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
iter_env->outbound_msg_retry = cfg->outbound_msg_retry;
|
||||
iter_env->max_sent_count = cfg->max_sent_count;
|
||||
iter_env->max_query_restarts = cfg->max_query_restarts;
|
||||
+ iter_env->aaaa_filter = cfg->aaaa_filter;
|
||||
return 1;
|
||||
}
|
||||
|
||||
diff --git a/iterator/iterator.c b/iterator/iterator.c
|
||||
index 23b07ea9..ca29b48c 100644
|
||||
index 71e64655..735f4ca0 100644
|
||||
--- a/iterator/iterator.c
|
||||
+++ b/iterator/iterator.c
|
||||
@@ -2127,6 +2127,53 @@ processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id)
|
||||
|
||||
return 0;
|
||||
@@ -2412,6 +2412,53 @@ check_waiting_queries(struct iter_qstate* iq, struct module_qstate* qstate,
|
||||
qstate->ext_state[id] = module_wait_reply;
|
||||
}
|
||||
}
|
||||
+
|
||||
+/**
|
||||
@@ -170,8 +170,8 @@ index 23b07ea9..ca29b48c 100644
|
||||
|
||||
/**
|
||||
* This is the request event state where the request will be sent to one of
|
||||
@@ -2186,6 +2233,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
@@ -2554,6 +2601,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
}
|
||||
|
||||
+ /* ASN: If we have a AAAA query, then also query for A records */
|
||||
@@ -184,7 +184,7 @@ index 23b07ea9..ca29b48c 100644
|
||||
/* Make sure we have a delegation point, otherwise priming failed
|
||||
* or another failure occurred */
|
||||
if(!iq->dp) {
|
||||
@@ -3574,6 +3628,61 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
@@ -4178,6 +4232,61 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -236,7 +236,7 @@ index 23b07ea9..ca29b48c 100644
|
||||
+ /* see if the failure did get (parent-lame) info */
|
||||
+ if(!cache_fill_missing(super->env,
|
||||
+ super_iq->qchase.qclass, super->region,
|
||||
+ super_iq->dp))
|
||||
+ super_iq->dp, 0))
|
||||
+ log_err("ASN-AAAA-filter: out of memory adding missing");
|
||||
+ dpns->resolved = 1; /* mark as failed */
|
||||
+ }
|
||||
@@ -246,7 +246,7 @@ index 23b07ea9..ca29b48c 100644
|
||||
/*
|
||||
* Return priming query results to interested super querystates.
|
||||
*
|
||||
@@ -3593,6 +3702,9 @@ iter_inform_super(struct module_qstate* qstate, int id,
|
||||
@@ -4197,6 +4306,9 @@ iter_inform_super(struct module_qstate* qstate, int id,
|
||||
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 23b07ea9..ca29b48c 100644
|
||||
else if(qstate->return_rcode != LDNS_RCODE_NOERROR)
|
||||
error_supers(qstate, id, super);
|
||||
else if(qstate->is_priming)
|
||||
@@ -3630,6 +3742,9 @@ iter_handle(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
@@ -4234,6 +4346,9 @@ iter_handle(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
case INIT_REQUEST_3_STATE:
|
||||
cont = processInitRequest3(qstate, iq, id);
|
||||
break;
|
||||
@@ -266,7 +266,7 @@ index 23b07ea9..ca29b48c 100644
|
||||
case QUERYTARGETS_STATE:
|
||||
cont = processQueryTargets(qstate, iq, ie, id);
|
||||
break;
|
||||
@@ -3961,6 +4076,8 @@ iter_state_to_string(enum iter_state state)
|
||||
@@ -4578,6 +4693,8 @@ iter_state_to_string(enum iter_state state)
|
||||
return "INIT REQUEST STATE (stage 2)";
|
||||
case INIT_REQUEST_3_STATE:
|
||||
return "INIT REQUEST STATE (stage 3)";
|
||||
@@ -275,7 +275,7 @@ index 23b07ea9..ca29b48c 100644
|
||||
case QUERYTARGETS_STATE :
|
||||
return "QUERY TARGETS STATE";
|
||||
case PRIME_RESP_STATE :
|
||||
@@ -3985,6 +4102,7 @@ iter_state_is_responsestate(enum iter_state s)
|
||||
@@ -4602,6 +4719,7 @@ iter_state_is_responsestate(enum iter_state s)
|
||||
case INIT_REQUEST_STATE :
|
||||
case INIT_REQUEST_2_STATE :
|
||||
case INIT_REQUEST_3_STATE :
|
||||
@@ -284,10 +284,10 @@ index 23b07ea9..ca29b48c 100644
|
||||
case COLLECT_CLASS_STATE :
|
||||
return 0;
|
||||
diff --git a/iterator/iterator.h b/iterator/iterator.h
|
||||
index 342ac207..731948d1 100644
|
||||
index ae4b4e45..a44f9d27 100644
|
||||
--- a/iterator/iterator.h
|
||||
+++ b/iterator/iterator.h
|
||||
@@ -135,6 +135,9 @@ struct iter_env {
|
||||
@@ -157,6 +157,9 @@ struct iter_env {
|
||||
*/
|
||||
int* target_fetch_policy;
|
||||
|
||||
@@ -297,7 +297,7 @@ index 342ac207..731948d1 100644
|
||||
/** lock on ratelimit counter */
|
||||
lock_basic_type queries_ratelimit_lock;
|
||||
/** number of queries that have been ratelimited */
|
||||
@@ -186,6 +189,14 @@ enum iter_state {
|
||||
@@ -217,6 +220,14 @@ enum iter_state {
|
||||
*/
|
||||
INIT_REQUEST_3_STATE,
|
||||
|
||||
@@ -312,9 +312,9 @@ index 342ac207..731948d1 100644
|
||||
/**
|
||||
* Each time a delegation point changes for a given query or a
|
||||
* query times out and/or wakes up, this state is (re)visited.
|
||||
@@ -375,6 +386,13 @@ struct iter_qstate {
|
||||
*/
|
||||
int refetch_glue;
|
||||
@@ -434,6 +445,13 @@ struct iter_qstate {
|
||||
* already so that it is accepted later. */
|
||||
int empty_nodata_found;
|
||||
|
||||
+ /**
|
||||
+ * ASN: This is a flag that, if true, means that this query is
|
||||
@@ -327,10 +327,10 @@ index 342ac207..731948d1 100644
|
||||
struct outbound_list outlist;
|
||||
|
||||
diff --git a/pythonmod/interface.i b/pythonmod/interface.i
|
||||
index f08b575d..47f1bb2e 100644
|
||||
index 2040fb9e..f073c3dc 100644
|
||||
--- a/pythonmod/interface.i
|
||||
+++ b/pythonmod/interface.i
|
||||
@@ -975,6 +975,7 @@ struct config_file {
|
||||
@@ -1013,6 +1013,7 @@ struct config_file {
|
||||
int harden_dnssec_stripped;
|
||||
int harden_referral_path;
|
||||
int use_caps_bits_for_id;
|
||||
@@ -339,23 +339,23 @@ index f08b575d..47f1bb2e 100644
|
||||
struct config_strlist* private_domain;
|
||||
size_t unwanted_threshold;
|
||||
diff --git a/util/config_file.c b/util/config_file.c
|
||||
index 0ab8614a..729fb147 100644
|
||||
index b1e767b3..5eb3c099 100644
|
||||
--- a/util/config_file.c
|
||||
+++ b/util/config_file.c
|
||||
@@ -218,6 +218,7 @@ config_create(void)
|
||||
cfg->harden_referral_path = 0;
|
||||
@@ -247,6 +247,7 @@ config_create(void)
|
||||
cfg->harden_algo_downgrade = 0;
|
||||
cfg->harden_unknown_additional = 0;
|
||||
cfg->use_caps_bits_for_id = 0;
|
||||
+ cfg->aaaa_filter = 0; /* ASN: default is disabled */
|
||||
cfg->caps_whitelist = NULL;
|
||||
cfg->private_address = NULL;
|
||||
cfg->private_domain = NULL;
|
||||
diff --git a/util/config_file.h b/util/config_file.h
|
||||
index e61257a3..dabaa7bb 100644
|
||||
index 44ac036b..1e59ab07 100644
|
||||
--- a/util/config_file.h
|
||||
+++ b/util/config_file.h
|
||||
@@ -260,6 +260,8 @@ struct config_file {
|
||||
int harden_algo_downgrade;
|
||||
@@ -311,6 +311,8 @@ struct config_file {
|
||||
int harden_unknown_additional;
|
||||
/** use 0x20 bits in query as random ID bits */
|
||||
int use_caps_bits_for_id;
|
||||
+ /** ASN: enable AAAA filter? */
|
||||
@@ -364,38 +364,38 @@ index e61257a3..dabaa7bb 100644
|
||||
struct config_strlist* caps_whitelist;
|
||||
/** strip away these private addrs from answers, no DNS Rebinding */
|
||||
diff --git a/util/configlexer.lex b/util/configlexer.lex
|
||||
index 79a0edca..4eaec678 100644
|
||||
index bc258673..76aab170 100644
|
||||
--- a/util/configlexer.lex
|
||||
+++ b/util/configlexer.lex
|
||||
@@ -304,6 +304,7 @@ harden-algo-downgrade{COLON} { YDVAR(1, VAR_HARDEN_ALGO_DOWNGRADE) }
|
||||
use-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) }
|
||||
@@ -327,6 +327,7 @@ use-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) }
|
||||
caps-whitelist{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
|
||||
caps-exempt{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
|
||||
unwanted-reply-threshold{COLON} { YDVAR(1, VAR_UNWANTED_REPLY_THRESHOLD) }
|
||||
+aaaa-filter{COLON} { YDVAR(1, VAR_AAAA_FILTER) }
|
||||
private-address{COLON} { YDVAR(1, VAR_PRIVATE_ADDRESS) }
|
||||
private-domain{COLON} { YDVAR(1, VAR_PRIVATE_DOMAIN) }
|
||||
prefetch-key{COLON} { YDVAR(1, VAR_PREFETCH_KEY) }
|
||||
diff --git a/util/configparser.y b/util/configparser.y
|
||||
index 1d0e8658..f284dd43 100644
|
||||
index 82e1d878..dc19bed5 100644
|
||||
--- a/util/configparser.y
|
||||
+++ b/util/configparser.y
|
||||
@@ -97,6 +97,7 @@ extern struct config_parser_state* cfg_parser;
|
||||
%token VAR_STATISTICS_CUMULATIVE VAR_OUTGOING_PORT_PERMIT
|
||||
@@ -100,6 +100,7 @@ extern struct config_parser_state* cfg_parser;
|
||||
%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
|
||||
+%token VAR_AAAA_FILTER
|
||||
%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
|
||||
@@ -233,6 +234,7 @@ content_server: server_num_threads | server_verbosity | server_port |
|
||||
@@ -276,6 +277,7 @@ content_server: server_num_threads | server_verbosity | server_port |
|
||||
server_dlv_anchor_file | server_dlv_anchor | server_neg_cache_size |
|
||||
server_harden_referral_path | server_private_address |
|
||||
server_private_domain | server_extended_statistics |
|
||||
server_private_domain | server_extended_statistics |
|
||||
+ server_aaaa_filter |
|
||||
server_local_data_ptr | server_jostle_timeout |
|
||||
server_unwanted_reply_threshold | server_log_time_ascii |
|
||||
server_domain_insecure | server_val_sig_skew_min |
|
||||
@@ -1563,6 +1565,15 @@ server_caps_whitelist: VAR_CAPS_WHITELIST STRING_ARG
|
||||
server_local_data_ptr | server_jostle_timeout |
|
||||
server_unwanted_reply_threshold | server_log_time_ascii |
|
||||
server_domain_insecure | server_val_sig_skew_min |
|
||||
@@ -1932,6 +1934,15 @@ server_caps_whitelist: VAR_CAPS_WHITELIST STRING_ARG
|
||||
yyerror("out of memory");
|
||||
}
|
||||
;
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
LIBEXPAT_FNAME=expat-2.7.0
|
||||
LIBEXPAT_VERSION_DIR=R_2_7_0
|
||||
|
||||
echo "Downloading Expat"
|
||||
if ! curl -L -k -s -o expat-2.2.9.tar.gz https://github.com/libexpat/libexpat/releases/download/R_2_2_9/expat-2.2.9.tar.gz;
|
||||
if ! curl -L -k -s -o $LIBEXPAT_FNAME.tar.gz https://github.com/libexpat/libexpat/releases/download/$LIBEXPAT_VERSION_DIR/$LIBEXPAT_FNAME.tar.gz;
|
||||
then
|
||||
echo "Failed to download Expat"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Unpacking Expat"
|
||||
rm -rf ./expat-2.2.9
|
||||
if ! tar -xf expat-2.2.9.tar.gz;
|
||||
rm -rf ./$LIBEXPAT_FNAME
|
||||
if ! tar -xf $LIBEXPAT_FNAME.tar.gz;
|
||||
then
|
||||
echo "Failed to unpack Expat"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd expat-2.2.9 || exit 1
|
||||
cd $LIBEXPAT_FNAME || exit 1
|
||||
|
||||
echo "Configuring Expat"
|
||||
if ! ./configure --build="$AUTOTOOLS_BUILD" --host="$AUTOTOOLS_HOST" --prefix="$ANDROID_PREFIX"; then
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
#
|
||||
# unbound.conf:
|
||||
# rpz:
|
||||
# name: "spamhaus-drop.rpz.local."
|
||||
# name: "drop.spamhaus.org.rpz.local."
|
||||
# zonefile: "/path/tp/spamhaus-drop.rpz.local"
|
||||
# rpz-log: yes
|
||||
# rpz-log-name: "spamhaus-drop"
|
||||
|
||||
@@ -0,0 +1,325 @@
|
||||
diff --git a/sldns/keyraw.c b/sldns/keyraw.c
|
||||
index 42a9262a3..cc6406a56 100644
|
||||
--- a/sldns/keyraw.c
|
||||
+++ b/sldns/keyraw.c
|
||||
@@ -85,7 +85,7 @@ sldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
|
||||
}
|
||||
break;
|
||||
#ifdef USE_GOST
|
||||
- case LDNS_ECC_GOST:
|
||||
+ case LDNS_ECC_GOST12:
|
||||
return 512;
|
||||
#endif
|
||||
#ifdef USE_ECDSA
|
||||
@@ -146,7 +146,7 @@ sldns_key_EVP_load_gost_id(void)
|
||||
if(gost_id) return gost_id;
|
||||
|
||||
/* see if configuration loaded gost implementation from other engine*/
|
||||
- meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
|
||||
+ meth = EVP_PKEY_asn1_find_str(NULL, "gost2012_256", -1);
|
||||
if(meth) {
|
||||
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
|
||||
return gost_id;
|
||||
@@ -170,7 +170,7 @@ sldns_key_EVP_load_gost_id(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
- meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
|
||||
+ meth = EVP_PKEY_asn1_find_str(&e, "gost2012_256", -1);
|
||||
if(!meth) {
|
||||
/* algo not found */
|
||||
ENGINE_finish(e);
|
||||
@@ -536,12 +536,17 @@ EVP_PKEY* sldns_key_rsa2pkey_raw(unsigned char* key, size_t len)
|
||||
EVP_PKEY*
|
||||
sldns_gost2pkey_raw(unsigned char* key, size_t keylen)
|
||||
{
|
||||
- /* prefix header for X509 encoding */
|
||||
- uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
|
||||
- 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
|
||||
- 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
|
||||
- 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
|
||||
- unsigned char encoded[37+64];
|
||||
+ /* prefix header for X509 encoding
|
||||
+ *
|
||||
+ * note: based on draft-makarenko-gost2012-dnssec-01 (pre-RFC9558 and it DOES work!)
|
||||
+ * ASN1 header described in RFC9558 is not suitable due to d2i_PUBKEY() works with
|
||||
+ * non-compressed public keys (two additional bytes 0x04, 0x40 at the end of header)
|
||||
+ */
|
||||
+ uint8_t asn[32] = { 0x30, 0x5e, 0x30, 0x17, 0x06, 0x08, 0x2a, 0x85,
|
||||
+ 0x03, 0x07, 0x01, 0x01, 0x01, 0x01, 0x30, 0x0b,
|
||||
+ 0x06, 0x09, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x02,
|
||||
+ 0x01, 0x01, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40 };
|
||||
+ unsigned char encoded[32+64];
|
||||
const unsigned char* pp;
|
||||
if(keylen != 64) {
|
||||
/* key wrong size */
|
||||
@@ -549,8 +554,8 @@ sldns_gost2pkey_raw(unsigned char* key, size_t keylen)
|
||||
}
|
||||
|
||||
/* create evp_key */
|
||||
- memmove(encoded, asn, 37);
|
||||
- memmove(encoded+37, key, 64);
|
||||
+ memmove(encoded, asn, 32);
|
||||
+ memmove(encoded+32, key, 64);
|
||||
pp = (unsigned char*)&encoded[0];
|
||||
|
||||
return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
|
||||
diff --git a/sldns/rrdef.h b/sldns/rrdef.h
|
||||
index bbc3d5b86..7d5f3c057 100644
|
||||
--- a/sldns/rrdef.h
|
||||
+++ b/sldns/rrdef.h
|
||||
@@ -384,11 +384,12 @@ enum sldns_enum_algorithm
|
||||
LDNS_RSASHA1_NSEC3 = 7,
|
||||
LDNS_RSASHA256 = 8, /* RFC 5702 */
|
||||
LDNS_RSASHA512 = 10, /* RFC 5702 */
|
||||
- LDNS_ECC_GOST = 12, /* RFC 5933 */
|
||||
+ LDNS_ECC_GOST = 12, /* RFC 5933, deprecated */
|
||||
LDNS_ECDSAP256SHA256 = 13, /* RFC 6605 */
|
||||
LDNS_ECDSAP384SHA384 = 14, /* RFC 6605 */
|
||||
LDNS_ED25519 = 15, /* RFC 8080 */
|
||||
LDNS_ED448 = 16, /* RFC 8080 */
|
||||
+ LDNS_ECC_GOST12 = 23, /* RFC 9558 */
|
||||
LDNS_INDIRECT = 252,
|
||||
LDNS_PRIVATEDNS = 253,
|
||||
LDNS_PRIVATEOID = 254
|
||||
@@ -402,8 +403,9 @@ enum sldns_enum_hash
|
||||
{
|
||||
LDNS_SHA1 = 1, /* RFC 4034 */
|
||||
LDNS_SHA256 = 2, /* RFC 4509 */
|
||||
- LDNS_HASH_GOST = 3, /* RFC 5933 */
|
||||
- LDNS_SHA384 = 4 /* RFC 6605 */
|
||||
+ LDNS_HASH_GOST = 3, /* RFC 5933, deprecated */
|
||||
+ LDNS_SHA384 = 4, /* RFC 6605 */
|
||||
+ LDNS_HASH_GOST12 = 5 /* RFC 9558 */
|
||||
};
|
||||
typedef enum sldns_enum_hash sldns_hash;
|
||||
|
||||
diff --git a/sldns/wire2str.c b/sldns/wire2str.c
|
||||
index 75b8f37b0..b4c4755e6 100644
|
||||
--- a/sldns/wire2str.c
|
||||
+++ b/sldns/wire2str.c
|
||||
@@ -45,11 +45,12 @@ static sldns_lookup_table sldns_algorithms_data[] = {
|
||||
{ LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" },
|
||||
{ LDNS_RSASHA256, "RSASHA256"},
|
||||
{ LDNS_RSASHA512, "RSASHA512"},
|
||||
- { LDNS_ECC_GOST, "ECC-GOST"},
|
||||
+ { LDNS_ECC_GOST, "ECC-GOST"}, /* deprecated */
|
||||
{ LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"},
|
||||
{ LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"},
|
||||
{ LDNS_ED25519, "ED25519"},
|
||||
{ LDNS_ED448, "ED448"},
|
||||
+ { LDNS_ECC_GOST12, "ECC-GOST12"},
|
||||
{ LDNS_INDIRECT, "INDIRECT" },
|
||||
{ LDNS_PRIVATEDNS, "PRIVATEDNS" },
|
||||
{ LDNS_PRIVATEOID, "PRIVATEOID" },
|
||||
@@ -61,8 +62,9 @@ sldns_lookup_table* sldns_algorithms = sldns_algorithms_data;
|
||||
static sldns_lookup_table sldns_hashes_data[] = {
|
||||
{ LDNS_SHA1, "SHA1" },
|
||||
{ LDNS_SHA256, "SHA256" },
|
||||
- { LDNS_HASH_GOST, "HASH-GOST" },
|
||||
+ { LDNS_HASH_GOST, "HASH-GOST" }, /* deprecated */
|
||||
{ LDNS_SHA384, "SHA384" },
|
||||
+ { LDNS_HASH_GOST12, "HASH-GOST12" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
sldns_lookup_table* sldns_hashes = sldns_hashes_data;
|
||||
diff --git a/testcode/unitverify.c b/testcode/unitverify.c
|
||||
index fcf2e2ffe..4a33e9f6a 100644
|
||||
--- a/testcode/unitverify.c
|
||||
+++ b/testcode/unitverify.c
|
||||
@@ -696,7 +696,7 @@ verify_test(void)
|
||||
#endif
|
||||
#ifdef USE_GOST
|
||||
if(sldns_key_EVP_load_gost_id())
|
||||
- verifytest_file(SRCDIRSTR "/testdata/test_sigs.gost", "20090807060504");
|
||||
+ verifytest_file(SRCDIRSTR "/testdata/test_sigs.gost12", "20251226060504");
|
||||
else printf("Warning: skipped GOST, openssl does not provide gost.\n");
|
||||
#endif
|
||||
#ifdef USE_ECDSA
|
||||
diff --git a/testdata/test_sigs.gost12 b/testdata/test_sigs.gost12
|
||||
new file mode 100644
|
||||
index 000000000..72a250cff
|
||||
--- /dev/null
|
||||
+++ b/testdata/test_sigs.gost12
|
||||
@@ -0,0 +1,39 @@
|
||||
+; Signature test file
|
||||
+
|
||||
+; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification.
|
||||
+; later entries are verified with it.
|
||||
+
|
||||
+; Test GOST signatures using algo number 23.
|
||||
+
|
||||
+ENTRY_BEGIN
|
||||
+SECTION QUESTION
|
||||
+nlnetlabs.nl. IN DNSKEY
|
||||
+SECTION ANSWER
|
||||
+nlnetlabs.nl. 3600 IN DNSKEY 256 3 23 cdOtkEcb6NhcdOpIbPYtWyWxdlUiKgtKQbYg3lIjtG7i3fYjUID9zyOgoQEiV9wuGCfrw5cNsnvNw+8HiVFK4g== ;{id = 12301 (zsk), size = 512b}
|
||||
+ENTRY_END
|
||||
+
|
||||
+; entry to test
|
||||
+ENTRY_BEGIN
|
||||
+SECTION QUESTION
|
||||
+open.nlnetlabs.nl. IN A
|
||||
+SECTION ANSWER
|
||||
+open.nlnetlabs.nl. 600 IN A 213.154.224.1
|
||||
+open.nlnetlabs.nl. 600 IN RRSIG A 23 3 600 20260122084903 20251225084903 12301 nlnetlabs.nl. I12wYNs96DxMy26CWx296/sWMJAFg4nNXBo0sw7PnuMbJW5NFAmZYtFWhUdOWn4umaiodYOAmKG8Zg/OKvEtAQ==
|
||||
+ENTRY_END
|
||||
+
|
||||
+ENTRY_BEGIN
|
||||
+SECTION QUESTION
|
||||
+open.nlnetlabs.nl. IN AAAA
|
||||
+SECTION ANSWER
|
||||
+open.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::1
|
||||
+open.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::53
|
||||
+open.nlnetlabs.nl. 600 IN RRSIG AAAA 23 3 600 20260122084903 20251225084903 12301 nlnetlabs.nl. J0jHa+CP8HM6UDa2+uYgaze2mfpJTh2hkZ2KwMTYb5sfL6iBmxxql0c/403Itk4fMfYBMGn7zfzDQ+CxnCgSWw==
|
||||
+ENTRY_END
|
||||
+
|
||||
+ENTRY_BEGIN
|
||||
+SECTION QUESTION
|
||||
+open.nlnetlabs.nl. IN NSEC
|
||||
+SECTION ANSWER
|
||||
+open.nlnetlabs.nl. 86400 IN NSEC nlnetlabs.nl. A AAAA RRSIG NSEC
|
||||
+open.nlnetlabs.nl. 86400 IN RRSIG NSEC 23 3 86400 20260122084903 20251225084903 12301 nlnetlabs.nl. INCLYe9vAaNYaYx5Ay3Q6QdX+wPW9sMRvVlGt/jUEGgCi+88QlV80CT1oHrhRI66I14Wk6NRAGZRNx1tUPSHSg==
|
||||
+ENTRY_END
|
||||
diff --git a/validator/val_secalgo.c b/validator/val_secalgo.c
|
||||
index be8347b1b..4f621a309 100644
|
||||
--- a/validator/val_secalgo.c
|
||||
+++ b/validator/val_secalgo.c
|
||||
@@ -246,10 +246,10 @@ ds_digest_size_supported(int algo)
|
||||
return SHA256_DIGEST_LENGTH;
|
||||
#endif
|
||||
#ifdef USE_GOST
|
||||
- case LDNS_HASH_GOST:
|
||||
+ case LDNS_HASH_GOST12:
|
||||
/* we support GOST if it can be loaded */
|
||||
(void)sldns_key_EVP_load_gost_id();
|
||||
- if(EVP_get_digestbyname("md_gost94"))
|
||||
+ if(EVP_get_digestbyname("md_gost12_256"))
|
||||
return 32;
|
||||
else return 0;
|
||||
#endif
|
||||
@@ -265,9 +265,9 @@ ds_digest_size_supported(int algo)
|
||||
#ifdef USE_GOST
|
||||
/** Perform GOST hash */
|
||||
static int
|
||||
-do_gost94(unsigned char* data, size_t len, unsigned char* dest)
|
||||
+do_gost12(unsigned char* data, size_t len, unsigned char* dest)
|
||||
{
|
||||
- const EVP_MD* md = EVP_get_digestbyname("md_gost94");
|
||||
+ const EVP_MD* md = EVP_get_digestbyname("md_gost12_256");
|
||||
if(!md)
|
||||
return 0;
|
||||
return sldns_digest_evp(data, (unsigned int)len, dest, md);
|
||||
@@ -302,8 +302,8 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef USE_GOST
|
||||
- case LDNS_HASH_GOST:
|
||||
- if(do_gost94(buf, len, res))
|
||||
+ case LDNS_HASH_GOST12:
|
||||
+ if(do_gost12(buf, len, res))
|
||||
return 1;
|
||||
break;
|
||||
#endif
|
||||
@@ -384,7 +384,7 @@ dnskey_algo_id_is_supported(int id)
|
||||
#endif
|
||||
|
||||
#ifdef USE_GOST
|
||||
- case LDNS_ECC_GOST:
|
||||
+ case LDNS_ECC_GOST12:
|
||||
/* we support GOST if it can be loaded */
|
||||
return sldns_key_EVP_load_gost_id();
|
||||
#endif
|
||||
@@ -612,17 +612,17 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
|
||||
|
||||
break;
|
||||
#ifdef USE_GOST
|
||||
- case LDNS_ECC_GOST:
|
||||
+ case LDNS_ECC_GOST12:
|
||||
*evp_key = sldns_gost2pkey_raw(key, keylen);
|
||||
if(!*evp_key) {
|
||||
verbose(VERB_QUERY, "verify: "
|
||||
"sldns_gost2pkey_raw failed");
|
||||
return 0;
|
||||
}
|
||||
- *digest_type = EVP_get_digestbyname("md_gost94");
|
||||
+ *digest_type = EVP_get_digestbyname("md_gost12_256");
|
||||
if(!*digest_type) {
|
||||
verbose(VERB_QUERY, "verify: "
|
||||
- "EVP_getdigest md_gost94 failed");
|
||||
+ "EVP_getdigest md_gost12_256 failed");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
@@ -964,7 +964,7 @@ ds_digest_size_supported(int algo)
|
||||
return SHA384_LENGTH;
|
||||
#endif
|
||||
/* GOST not supported in NSS */
|
||||
- case LDNS_HASH_GOST:
|
||||
+ case LDNS_HASH_GOST12:
|
||||
default: break;
|
||||
}
|
||||
return 0;
|
||||
@@ -991,7 +991,7 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
|
||||
return HASH_HashBuf(HASH_AlgSHA384, res, buf, len)
|
||||
== SECSuccess;
|
||||
#endif
|
||||
- case LDNS_HASH_GOST:
|
||||
+ case LDNS_HASH_GOST12:
|
||||
default:
|
||||
verbose(VERB_QUERY, "unknown DS digest algorithm %d",
|
||||
algo);
|
||||
@@ -1031,7 +1031,7 @@ dnskey_algo_id_is_supported(int id)
|
||||
case LDNS_ECDSAP384SHA384:
|
||||
return PK11_TokenExists(CKM_ECDSA);
|
||||
#endif
|
||||
- case LDNS_ECC_GOST:
|
||||
+ case LDNS_ECC_GOST12:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -1352,7 +1352,7 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
|
||||
/* no prefix for DSA verification */
|
||||
break;
|
||||
#endif /* USE_ECDSA */
|
||||
- case LDNS_ECC_GOST:
|
||||
+ case LDNS_ECC_GOST12:
|
||||
default:
|
||||
verbose(VERB_QUERY, "verify: unknown algorithm %d",
|
||||
algo);
|
||||
@@ -1675,7 +1675,7 @@ ds_digest_size_supported(int algo)
|
||||
return SHA384_DIGEST_SIZE;
|
||||
#endif
|
||||
/* GOST not supported */
|
||||
- case LDNS_HASH_GOST:
|
||||
+ case LDNS_ECC_GOST12:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1700,7 +1700,7 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
|
||||
return _digest_nettle(SHA384_DIGEST_SIZE, buf, len, res);
|
||||
|
||||
#endif
|
||||
- case LDNS_HASH_GOST:
|
||||
+ case LDNS_ECC_GOST12:
|
||||
default:
|
||||
verbose(VERB_QUERY, "unknown DS digest algorithm %d",
|
||||
algo);
|
||||
@@ -1744,7 +1744,7 @@ dnskey_algo_id_is_supported(int id)
|
||||
return 1;
|
||||
#endif
|
||||
case LDNS_RSAMD5: /* RFC 6725 deprecates RSAMD5 */
|
||||
- case LDNS_ECC_GOST:
|
||||
+ case LDNS_ECC_GOST12:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -2103,7 +2103,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
|
||||
return sec_status_secure;
|
||||
#endif
|
||||
case LDNS_RSAMD5:
|
||||
- case LDNS_ECC_GOST:
|
||||
+ case LDNS_ECC_GOST12:
|
||||
default:
|
||||
*reason = "unable to verify signature, unknown algorithm";
|
||||
return sec_status_bogus;
|
||||
@@ -1,28 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
LIBEXPAT_FNAME=expat-2.7.0
|
||||
LIBEXPAT_VERSION_DIR=R_2_7_0
|
||||
|
||||
echo "Downloading Expat"
|
||||
if ! curl -L -k -s -o expat-2.2.9.tar.gz https://github.com/libexpat/libexpat/releases/download/R_2_2_9/expat-2.2.9.tar.gz;
|
||||
if ! curl -L -k -s -o $LIBEXPAT_FNAME.tar.gz https://github.com/libexpat/libexpat/releases/download/$LIBEXPAT_VERSION_DIR/$LIBEXPAT_FNAME.tar.gz;
|
||||
then
|
||||
echo "Failed to download Expat"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Unpacking Expat"
|
||||
rm -rf ./expat-2.2.9
|
||||
if ! tar -xf expat-2.2.9.tar.gz;
|
||||
rm -rf ./$LIBEXPAT_FNAME
|
||||
if ! tar -xf $LIBEXPAT_FNAME.tar.gz;
|
||||
then
|
||||
echo "Failed to unpack Expat"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd expat-2.2.9 || exit 1
|
||||
cd $LIBEXPAT_FNAME || exit 1
|
||||
|
||||
export PKG_CONFIG_PATH="$IOS_PREFIX/lib/pkgconfig"
|
||||
|
||||
echo "Configuring Expat"
|
||||
if ! ./configure \
|
||||
--build="$AUTOTOOLS_BUILD" --host="$AUTOTOOLS_HOST" \
|
||||
--prefix="$IOS_PREFIX" ; then
|
||||
if ! ./configure --without-tests \
|
||||
--build="$AUTOTOOLS_BUILD" --host="$AUTOTOOLS_HOST" \
|
||||
--prefix="$IOS_PREFIX" ;
|
||||
then
|
||||
echo "Error: Failed to configure Expat"
|
||||
cat config.log
|
||||
exit 1
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
OPENSSL_VERSION=1.1.1d
|
||||
|
||||
echo "Downloading OpenSSL"
|
||||
if ! curl -L -k -s -o openssl-1.1.1d.tar.gz https://www.openssl.org/source/openssl-1.1.1d.tar.gz;
|
||||
if ! curl -L -k -s -o openssl-$OPENSSL_VERSION.tar.gz https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz;
|
||||
then
|
||||
echo "Failed to download OpenSSL"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Unpacking OpenSSL"
|
||||
rm -rf ./openssl-1.1.1d
|
||||
if ! tar -xf openssl-1.1.1d.tar.gz;
|
||||
rm -rf ./openssl-$OPENSSL_VERSION
|
||||
if ! tar -xf openssl-$OPENSSL_VERSION.tar.gz;
|
||||
then
|
||||
echo "Failed to unpack OpenSSL"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd openssl-1.1.1d || exit 1
|
||||
cd openssl-$OPENSSL_VERSION || exit 1
|
||||
|
||||
if ! cp ../contrib/ios/15-ios.conf Configurations/; then
|
||||
echo "Failed to copy OpenSSL ios config"
|
||||
@@ -27,7 +28,8 @@ fi
|
||||
# Also see https://github.com/openssl/openssl/issues/7607.
|
||||
if ! patch -u -p0 < ../contrib/ios/openssl.patch; then
|
||||
echo "Failed to patch OpenSSL"
|
||||
exit 1
|
||||
# the partial patch may be useful.
|
||||
#exit 1
|
||||
fi
|
||||
|
||||
echo "Configuring OpenSSL"
|
||||
|
||||
@@ -175,6 +175,7 @@ fi
|
||||
# For example, remove 4.3, 6.2, and 6.1 if they are not installed. We go back to
|
||||
# the 1.0 SDKs because Apple WatchOS uses low numbers, like 2.0 and 2.1.
|
||||
XCODE_SDK=
|
||||
if test -z "$SDK_VERSION"; then
|
||||
for i in $(seq -f "%.1f" 30.0 -0.1 1.0)
|
||||
do
|
||||
if [ -d "$XCODE_DEVELOPER_SDK/Developer/SDKs/$IOS_SDK$i.sdk" ]; then
|
||||
@@ -182,6 +183,10 @@ do
|
||||
break
|
||||
fi
|
||||
done
|
||||
else
|
||||
i="$SDK_VERSION"
|
||||
XCODE_SDK="$IOS_SDK$i.sdk"
|
||||
fi
|
||||
|
||||
# Error checking
|
||||
if [ -z "$XCODE_SDK" ]; then
|
||||
|
||||
@@ -28,6 +28,7 @@ END {
|
||||
print "unbound_hits_queries{type=\"total.num.prefetch\"} " val["total.num.prefetch"];
|
||||
print "unbound_hits_queries{type=\"num.query.tcp\"} " val["num.query.tcp"];
|
||||
print "unbound_hits_queries{type=\"num.query.tcpout\"} " val["num.query.tcpout"];
|
||||
print "unbound_hits_queries{type=\"num.query.udpout\"} " val["num.query.udpout"];
|
||||
print "unbound_hits_queries{type=\"num.query.tls\"} " val["num.query.tls"];
|
||||
print "unbound_hits_queries{type=\"num.query.tls.resume\"} " val["num.query.tls.resume"];
|
||||
print "unbound_hits_queries{type=\"num.query.ipv6\"} " val["num.query.ipv6"];
|
||||
|
||||
@@ -22,4 +22,13 @@ pidfile=${unbound_pidfile:-"/usr/local/etc/unbound/unbound.pid"}
|
||||
command_args=${unbound_flags:-"-c /usr/local/etc/unbound/unbound.conf"}
|
||||
extra_commands="reload"
|
||||
|
||||
if test "$1" = "stop" ; then
|
||||
run_rc_command "$1"
|
||||
ret=$?
|
||||
if test $ret -eq 0; then
|
||||
rm -f "$pidfile"
|
||||
fi
|
||||
exit $ret
|
||||
fi
|
||||
|
||||
run_rc_command "$1"
|
||||
|
||||
@@ -75,6 +75,7 @@ stop() {
|
||||
retval=$?
|
||||
echo
|
||||
[ $retval -eq 0 ] && rm -f $lockfile
|
||||
[ $retval -eq 0 ] && rm -f $pidfile
|
||||
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
|
||||
umount ${rootdir}/dev/log >/dev/null 2>&1
|
||||
fi;
|
||||
|
||||
@@ -58,6 +58,7 @@ stop() {
|
||||
killproc -p $pidfile unbound
|
||||
retval=$?
|
||||
[ $retval -eq 0 ] && rm -f $lockfile
|
||||
[ $retval -eq 0 ] && rm -f $pidfile
|
||||
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
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# unbound This shell script takes care of starting and stopping
|
||||
# unbound (DNS server).
|
||||
#
|
||||
# chkconfig: - 14 86
|
||||
# description: unbound is a Domain Name Server (DNS) \
|
||||
# that is used to resolve host names to IP addresses.
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: $named unbound
|
||||
# Required-Start: $network $local_fs
|
||||
# Required-Stop: $network $local_fs
|
||||
# Should-Start: $syslog
|
||||
# Should-Stop: $syslog
|
||||
# Short-Description: unbound recursive Domain Name Server.
|
||||
# Description: unbound is a Domain Name Server (DNS)
|
||||
# that is used to resolve host names to IP addresses.
|
||||
### END INIT INFO
|
||||
|
||||
# Source function library.
|
||||
. /etc/init.d/functions
|
||||
|
||||
exec="/usr/sbin/unbound"
|
||||
prog="unbound"
|
||||
config="/etc/unbound/unbound.conf"
|
||||
pidfile="/var/unbound/unbound.pid"
|
||||
rootdir="/var/unbound"
|
||||
|
||||
[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
|
||||
|
||||
lockfile=/var/lock/subsys/$prog
|
||||
|
||||
start() {
|
||||
[ -x $exec ] || exit 5
|
||||
[ -f $config ] || exit 6
|
||||
echo -n $"Starting $prog: "
|
||||
|
||||
# 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
|
||||
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
|
||||
cp -fp /etc/resolv.conf ${rootdir}/etc/resolv.conf
|
||||
fi;
|
||||
fi;
|
||||
if ! egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
|
||||
[ -d ${rootdir}/dev ] || mkdir -p ${rootdir}/dev ;
|
||||
[ -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
|
||||
[ -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;
|
||||
fi;
|
||||
|
||||
# if not running, start it up here
|
||||
daemonize $exec
|
||||
retval=$?
|
||||
echo
|
||||
[ $retval -eq 0 ] && touch $lockfile
|
||||
return $retval
|
||||
}
|
||||
|
||||
stop() {
|
||||
echo -n $"Stopping $prog: "
|
||||
# stop it here, often "killproc $prog"
|
||||
killproc $prog
|
||||
retval=$?
|
||||
echo
|
||||
[ $retval -eq 0 ] && rm -f $lockfile
|
||||
[ $retval -eq 0 ] && rm -f $pidfile
|
||||
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
|
||||
fi;
|
||||
return $retval
|
||||
}
|
||||
|
||||
restart() {
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
reload() {
|
||||
kill -HUP `cat $pidfile`
|
||||
}
|
||||
|
||||
force_reload() {
|
||||
restart
|
||||
}
|
||||
|
||||
rh_status() {
|
||||
# run checks to determine if the service is running or use generic status
|
||||
status $prog
|
||||
}
|
||||
|
||||
rh_status_q() {
|
||||
rh_status -p $pidfile >/dev/null 2>&1
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
rh_status_q && exit 0
|
||||
$1
|
||||
;;
|
||||
stop)
|
||||
rh_status_q || exit 0
|
||||
$1
|
||||
;;
|
||||
restart)
|
||||
$1
|
||||
;;
|
||||
reload)
|
||||
rh_status_q || exit 7
|
||||
$1
|
||||
;;
|
||||
force-reload)
|
||||
force_reload
|
||||
;;
|
||||
status)
|
||||
rh_status
|
||||
;;
|
||||
condrestart|try-restart)
|
||||
rh_status_q || exit 0
|
||||
restart
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
|
||||
exit 2
|
||||
esac
|
||||
exit $?
|
||||
@@ -38,13 +38,18 @@
|
||||
; - `LockPersonality=yes` locks down the personality system call so that the
|
||||
; kernel execution domain may not be changed from the default.
|
||||
;
|
||||
; - With /etc/systemd/network/*.network a setting to make sure the network
|
||||
; is not considered online too early, can reduce network unreachable
|
||||
; errors on server start:
|
||||
; [Link]
|
||||
; RequiredForOnline=routable
|
||||
;
|
||||
[Unit]
|
||||
Description=Validating, recursive, and caching DNS resolver
|
||||
Documentation=man:unbound(8)
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
Before=nss-lookup.target
|
||||
Wants=network-online.target nss-lookup.target
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -54,7 +59,7 @@ ExecReload=+/bin/kill -HUP $MAINPID
|
||||
ExecStart=@UNBOUND_SBIN_DIR@/unbound -d -p
|
||||
NotifyAccess=main
|
||||
Type=notify
|
||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_RAW
|
||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_ADMIN
|
||||
MemoryDenyWriteExecute=true
|
||||
NoNewPrivileges=true
|
||||
PrivateDevices=true
|
||||
@@ -64,7 +69,8 @@ ProtectClock=true
|
||||
ProtectControlGroups=true
|
||||
ProtectKernelLogs=true
|
||||
ProtectKernelModules=true
|
||||
ProtectKernelTunables=true
|
||||
# This breaks using socket options like 'so-rcvbuf'. Explicitly disable for visibility.
|
||||
ProtectKernelTunables=false
|
||||
ProtectProc=invisible
|
||||
ProtectSystem=strict
|
||||
RuntimeDirectory=unbound
|
||||
|
||||
@@ -253,6 +253,7 @@ if test "$1" = "config" ; then
|
||||
p_config "total.num.prefetch" "cache prefetch" "ABSOLUTE"
|
||||
p_config "num.query.tcp" "TCP queries" "ABSOLUTE"
|
||||
p_config "num.query.tcpout" "TCP out queries" "ABSOLUTE"
|
||||
p_config "num.query.udpout" "UDP out queries" "ABSOLUTE"
|
||||
p_config "num.query.tls" "TLS queries" "ABSOLUTE"
|
||||
p_config "num.query.tls.resume" "TLS resumes" "ABSOLUTE"
|
||||
p_config "num.query.ipv6" "IPv6 queries" "ABSOLUTE"
|
||||
@@ -452,7 +453,7 @@ hits)
|
||||
for x in `grep "^thread[0-9][0-9]*\.num\.queries=" $state |
|
||||
sed -e 's/=.*//'` total.num.queries \
|
||||
total.num.cachehits total.num.prefetch num.query.tcp \
|
||||
num.query.tcpout num.query.tls num.query.tls.resume \
|
||||
num.query.tcpout num.query.udpout num.query.tls num.query.tls.resume \
|
||||
num.query.ipv6 unwanted.queries \
|
||||
unwanted.replies; do
|
||||
if grep "^"$x"=" $state >/dev/null 2>&1; then
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
[Unit]
|
||||
Description=Validating, recursive, and caching DNS resolver
|
||||
Documentation=man:unbound(8)
|
||||
After=network.target
|
||||
Before=network-online.target nss-lookup.target
|
||||
After=network-online.target
|
||||
Before=nss-lookup.target
|
||||
Wants=nss-lookup.target
|
||||
|
||||
[Install]
|
||||
@@ -26,7 +26,7 @@ ExecReload=+/bin/kill -HUP $MAINPID
|
||||
ExecStart=@UNBOUND_SBIN_DIR@/unbound -d -p
|
||||
NotifyAccess=main
|
||||
Type=notify
|
||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_RAW
|
||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_ADMIN
|
||||
MemoryDenyWriteExecute=true
|
||||
NoNewPrivileges=true
|
||||
PrivateDevices=true
|
||||
|
||||
+428
-88
@@ -46,9 +46,10 @@
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
#include "services/localzone.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "sldns/str2wire.h"
|
||||
|
||||
struct acl_list*
|
||||
struct acl_list*
|
||||
acl_list_create(void)
|
||||
{
|
||||
struct acl_list* acl = (struct acl_list*)calloc(1,
|
||||
@@ -63,10 +64,10 @@ acl_list_create(void)
|
||||
return acl;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
acl_list_delete(struct acl_list* acl)
|
||||
{
|
||||
if(!acl)
|
||||
if(!acl)
|
||||
return;
|
||||
regional_destroy(acl->region);
|
||||
free(acl);
|
||||
@@ -74,8 +75,8 @@ acl_list_delete(struct acl_list* acl)
|
||||
|
||||
/** insert new address into acl_list structure */
|
||||
static struct acl_addr*
|
||||
acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int net, enum acl_access control,
|
||||
acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int net, enum acl_access control,
|
||||
int complain_duplicates)
|
||||
{
|
||||
struct acl_addr* node = regional_alloc_zero(acl->region,
|
||||
@@ -90,6 +91,33 @@ acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr,
|
||||
return node;
|
||||
}
|
||||
|
||||
/** parse str to acl_access enum */
|
||||
static int
|
||||
parse_acl_access(const char* str, enum acl_access* control)
|
||||
{
|
||||
if(strcmp(str, "allow") == 0)
|
||||
*control = acl_allow;
|
||||
else if(strcmp(str, "deny") == 0)
|
||||
*control = acl_deny;
|
||||
else if(strcmp(str, "refuse") == 0)
|
||||
*control = acl_refuse;
|
||||
else if(strcmp(str, "deny_non_local") == 0)
|
||||
*control = acl_deny_non_local;
|
||||
else if(strcmp(str, "refuse_non_local") == 0)
|
||||
*control = acl_refuse_non_local;
|
||||
else if(strcmp(str, "allow_snoop") == 0)
|
||||
*control = acl_allow_snoop;
|
||||
else if(strcmp(str, "allow_setrd") == 0)
|
||||
*control = acl_allow_setrd;
|
||||
else if (strcmp(str, "allow_cookie") == 0)
|
||||
*control = acl_allow_cookie;
|
||||
else {
|
||||
log_err("access control type %s unknown", str);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** apply acl_list string */
|
||||
static int
|
||||
acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
|
||||
@@ -99,29 +127,14 @@ acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
|
||||
int net;
|
||||
socklen_t addrlen;
|
||||
enum acl_access control;
|
||||
if(strcmp(s2, "allow") == 0)
|
||||
control = acl_allow;
|
||||
else if(strcmp(s2, "deny") == 0)
|
||||
control = acl_deny;
|
||||
else if(strcmp(s2, "refuse") == 0)
|
||||
control = acl_refuse;
|
||||
else if(strcmp(s2, "deny_non_local") == 0)
|
||||
control = acl_deny_non_local;
|
||||
else if(strcmp(s2, "refuse_non_local") == 0)
|
||||
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);
|
||||
if(!parse_acl_access(s2, &control)) {
|
||||
return 0;
|
||||
}
|
||||
if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
|
||||
log_err("cannot parse access control: %s %s", str, s2);
|
||||
return 0;
|
||||
}
|
||||
if(!acl_list_insert(acl, &addr, addrlen, net, control,
|
||||
if(!acl_list_insert(acl, &addr, addrlen, net, control,
|
||||
complain_duplicates)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
@@ -131,19 +144,27 @@ acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
|
||||
|
||||
/** find or create node (NULL on parse or error) */
|
||||
static struct acl_addr*
|
||||
acl_find_or_create(struct acl_list* acl, const char* str)
|
||||
acl_find_or_create_str2addr(struct acl_list* acl, const char* str,
|
||||
int is_interface, int port)
|
||||
{
|
||||
struct acl_addr* node;
|
||||
struct sockaddr_storage addr;
|
||||
int net;
|
||||
socklen_t addrlen;
|
||||
if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
|
||||
log_err("cannot parse netblock: %s", str);
|
||||
return NULL;
|
||||
int net = (str_is_ip6(str)?128:32);
|
||||
if(is_interface) {
|
||||
if(!extstrtoaddr(str, &addr, &addrlen, port)) {
|
||||
log_err("cannot parse interface: %s", str);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
|
||||
log_err("cannot parse netblock: %s", str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* find or create node */
|
||||
if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, &addr,
|
||||
addrlen, net))) {
|
||||
addrlen, net)) && !is_interface) {
|
||||
/* create node, type 'allow' since otherwise tags are
|
||||
* pointless, can override with specific access-control: cfg */
|
||||
if(!(node=(struct acl_addr*)acl_list_insert(acl, &addr,
|
||||
@@ -155,14 +176,67 @@ acl_find_or_create(struct acl_list* acl, const char* str)
|
||||
return node;
|
||||
}
|
||||
|
||||
/** find or create node (NULL on error) */
|
||||
static struct acl_addr*
|
||||
acl_find_or_create(struct acl_list* acl, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, enum acl_access control)
|
||||
{
|
||||
struct acl_addr* node;
|
||||
int net = (addr_is_ip6(addr, addrlen)?128:32);
|
||||
/* find or create node */
|
||||
if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, addr,
|
||||
addrlen, net))) {
|
||||
/* create node;
|
||||
* can override with specific access-control: cfg */
|
||||
if(!(node=(struct acl_addr*)acl_list_insert(acl, addr,
|
||||
addrlen, net, control, 1))) {
|
||||
log_err("out of memory");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/** apply acl_interface string */
|
||||
static int
|
||||
acl_interface_str_cfg(struct acl_list* acl_interface, const char* iface,
|
||||
const char* s2, int port)
|
||||
{
|
||||
struct acl_addr* node;
|
||||
enum acl_access control;
|
||||
if(!parse_acl_access(s2, &control)) {
|
||||
return 0;
|
||||
}
|
||||
if(!(node=acl_find_or_create_str2addr(acl_interface, iface, 1, port))) {
|
||||
log_err("cannot update ACL on non-configured interface: %s %d",
|
||||
iface, port);
|
||||
return 0;
|
||||
}
|
||||
node->control = control;
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct acl_addr*
|
||||
acl_interface_insert(struct acl_list* acl_interface,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
enum acl_access control)
|
||||
{
|
||||
struct acl_addr* node = acl_find_or_create(acl_interface, addr, addrlen, control);
|
||||
node->is_interface = 1;
|
||||
return node;
|
||||
}
|
||||
|
||||
/** apply acl_tag string */
|
||||
static int
|
||||
acl_list_tags_cfg(struct acl_list* acl, const char* str, uint8_t* bitmap,
|
||||
size_t bitmaplen)
|
||||
size_t bitmaplen, int is_interface, int port)
|
||||
{
|
||||
struct acl_addr* node;
|
||||
if(!(node=acl_find_or_create(acl, str)))
|
||||
if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
|
||||
if(is_interface)
|
||||
log_err("non-configured interface: %s", str);
|
||||
return 0;
|
||||
}
|
||||
node->taglen = bitmaplen;
|
||||
node->taglist = regional_alloc_init(acl->region, bitmap, bitmaplen);
|
||||
if(!node->taglist) {
|
||||
@@ -175,11 +249,14 @@ acl_list_tags_cfg(struct acl_list* acl, const char* str, uint8_t* bitmap,
|
||||
/** apply acl_view string */
|
||||
static int
|
||||
acl_list_view_cfg(struct acl_list* acl, const char* str, const char* str2,
|
||||
struct views* vs)
|
||||
struct views* vs, int is_interface, int port)
|
||||
{
|
||||
struct acl_addr* node;
|
||||
if(!(node=acl_find_or_create(acl, str)))
|
||||
if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
|
||||
if(is_interface)
|
||||
log_err("non-configured interface: %s", str);
|
||||
return 0;
|
||||
}
|
||||
node->view = views_find_view(vs, str2, 0 /* get read lock*/);
|
||||
if(!node->view) {
|
||||
log_err("no view with name: %s", str2);
|
||||
@@ -192,13 +269,17 @@ acl_list_view_cfg(struct acl_list* acl, const char* str, const char* str2,
|
||||
/** apply acl_tag_action string */
|
||||
static int
|
||||
acl_list_tag_action_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||
const char* str, const char* tag, const char* action)
|
||||
const char* str, const char* tag, const char* action,
|
||||
int is_interface, int port)
|
||||
{
|
||||
struct acl_addr* node;
|
||||
int tagid;
|
||||
enum localzone_type t;
|
||||
if(!(node=acl_find_or_create(acl, str)))
|
||||
if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
|
||||
if(is_interface)
|
||||
log_err("non-configured interface: %s", str);
|
||||
return 0;
|
||||
}
|
||||
/* allocate array if not yet */
|
||||
if(!node->tag_actions) {
|
||||
node->tag_actions = (uint8_t*)regional_alloc_zero(acl->region,
|
||||
@@ -281,13 +362,17 @@ check_data(const char* data, const struct config_strlist* head)
|
||||
/** apply acl_tag_data string */
|
||||
static int
|
||||
acl_list_tag_data_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||
const char* str, const char* tag, const char* data)
|
||||
const char* str, const char* tag, const char* data,
|
||||
int is_interface, int port)
|
||||
{
|
||||
struct acl_addr* node;
|
||||
int tagid;
|
||||
char* dupdata;
|
||||
if(!(node=acl_find_or_create(acl, str)))
|
||||
if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
|
||||
if(is_interface)
|
||||
log_err("non-configured interface: %s", str);
|
||||
return 0;
|
||||
}
|
||||
/* allocate array if not yet */
|
||||
if(!node->tag_datas) {
|
||||
node->tag_datas = (struct config_strlist**)regional_alloc_zero(
|
||||
@@ -329,11 +414,11 @@ acl_list_tag_data_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||
}
|
||||
|
||||
/** read acl_list config */
|
||||
static int
|
||||
read_acl_list(struct acl_list* acl, struct config_file* cfg)
|
||||
static int
|
||||
read_acl_list(struct acl_list* acl, struct config_str2list* acls)
|
||||
{
|
||||
struct config_str2list* p;
|
||||
for(p = cfg->acls; p; p = p->next) {
|
||||
for(p = acls; p; p = p->next) {
|
||||
log_assert(p->str && p->str2);
|
||||
if(!acl_list_str_cfg(acl, p->str, p->str2, 1))
|
||||
return 0;
|
||||
@@ -341,15 +426,38 @@ read_acl_list(struct acl_list* acl, struct config_file* cfg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl tags config */
|
||||
static int
|
||||
read_acl_tags(struct acl_list* acl, struct config_file* cfg)
|
||||
/** read acl view config */
|
||||
static int
|
||||
read_acl_view(struct acl_list* acl, struct config_str2list** acl_view,
|
||||
struct views* v)
|
||||
{
|
||||
struct config_strbytelist* np, *p = cfg->acl_tags;
|
||||
cfg->acl_tags = NULL;
|
||||
struct config_str2list* np, *p = *acl_view;
|
||||
*acl_view = NULL;
|
||||
while(p) {
|
||||
log_assert(p->str && p->str2);
|
||||
if(!acl_list_tags_cfg(acl, p->str, p->str2, p->str2len)) {
|
||||
if(!acl_list_view_cfg(acl, p->str, p->str2, v, 0, 0)) {
|
||||
config_deldblstrlist(p);
|
||||
return 0;
|
||||
}
|
||||
/* free the items as we go to free up memory */
|
||||
np = p->next;
|
||||
free(p->str);
|
||||
free(p->str2);
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl tags config */
|
||||
static int
|
||||
read_acl_tags(struct acl_list* acl, struct config_strbytelist** acl_tags)
|
||||
{
|
||||
struct config_strbytelist* np, *p = *acl_tags;
|
||||
*acl_tags = NULL;
|
||||
while(p) {
|
||||
log_assert(p->str && p->str2);
|
||||
if(!acl_list_tags_cfg(acl, p->str, p->str2, p->str2len, 0, 0)) {
|
||||
config_del_strbytelist(p);
|
||||
return 0;
|
||||
}
|
||||
@@ -363,38 +471,18 @@ read_acl_tags(struct acl_list* acl, struct config_file* cfg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl view config */
|
||||
static int
|
||||
read_acl_view(struct acl_list* acl, struct config_file* cfg, struct views* v)
|
||||
{
|
||||
struct config_str2list* np, *p = cfg->acl_view;
|
||||
cfg->acl_view = NULL;
|
||||
while(p) {
|
||||
log_assert(p->str && p->str2);
|
||||
if(!acl_list_view_cfg(acl, p->str, p->str2, v)) {
|
||||
return 0;
|
||||
}
|
||||
/* free the items as we go to free up memory */
|
||||
np = p->next;
|
||||
free(p->str);
|
||||
free(p->str2);
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl tag actions config */
|
||||
static int
|
||||
read_acl_tag_actions(struct acl_list* acl, struct config_file* cfg)
|
||||
static int
|
||||
read_acl_tag_actions(struct acl_list* acl, struct config_file* cfg,
|
||||
struct config_str3list** acl_tag_actions)
|
||||
{
|
||||
struct config_str3list* p, *np;
|
||||
p = cfg->acl_tag_actions;
|
||||
cfg->acl_tag_actions = NULL;
|
||||
p = *acl_tag_actions;
|
||||
*acl_tag_actions = NULL;
|
||||
while(p) {
|
||||
log_assert(p->str && p->str2 && p->str3);
|
||||
if(!acl_list_tag_action_cfg(acl, cfg, p->str, p->str2,
|
||||
p->str3)) {
|
||||
p->str3, 0, 0)) {
|
||||
config_deltrplstrlist(p);
|
||||
return 0;
|
||||
}
|
||||
@@ -410,15 +498,17 @@ read_acl_tag_actions(struct acl_list* acl, struct config_file* cfg)
|
||||
}
|
||||
|
||||
/** read acl tag datas config */
|
||||
static int
|
||||
read_acl_tag_datas(struct acl_list* acl, struct config_file* cfg)
|
||||
static int
|
||||
read_acl_tag_datas(struct acl_list* acl, struct config_file* cfg,
|
||||
struct config_str3list** acl_tag_datas)
|
||||
{
|
||||
struct config_str3list* p, *np;
|
||||
p = cfg->acl_tag_datas;
|
||||
cfg->acl_tag_datas = NULL;
|
||||
p = *acl_tag_datas;
|
||||
*acl_tag_datas = NULL;
|
||||
while(p) {
|
||||
log_assert(p->str && p->str2 && p->str3);
|
||||
if(!acl_list_tag_data_cfg(acl, cfg, p->str, p->str2, p->str3)) {
|
||||
if(!acl_list_tag_data_cfg(acl, cfg, p->str, p->str2, p->str3,
|
||||
0, 0)) {
|
||||
config_deltrplstrlist(p);
|
||||
return 0;
|
||||
}
|
||||
@@ -433,30 +523,27 @@ read_acl_tag_datas(struct acl_list* acl, struct config_file* cfg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||
struct views* v)
|
||||
{
|
||||
regional_free_all(acl->region);
|
||||
addr_tree_init(&acl->tree);
|
||||
if(!read_acl_list(acl, cfg))
|
||||
if(!read_acl_list(acl, cfg->acls))
|
||||
return 0;
|
||||
if(!read_acl_view(acl, cfg, v))
|
||||
if(!read_acl_view(acl, &cfg->acl_view, v))
|
||||
return 0;
|
||||
if(!read_acl_tags(acl, cfg))
|
||||
if(!read_acl_tags(acl, &cfg->acl_tags))
|
||||
return 0;
|
||||
if(!read_acl_tag_actions(acl, cfg))
|
||||
if(!read_acl_tag_actions(acl, cfg, &cfg->acl_tag_actions))
|
||||
return 0;
|
||||
if(!read_acl_tag_datas(acl, cfg))
|
||||
if(!read_acl_tag_datas(acl, cfg, &cfg->acl_tag_datas))
|
||||
return 0;
|
||||
/* insert defaults, with '0' to ignore them if they are duplicates */
|
||||
if(!acl_list_str_cfg(acl, "0.0.0.0/0", "refuse", 0))
|
||||
return 0;
|
||||
/* the 'refuse' defaults for /0 are now done per interface instead */
|
||||
if(!acl_list_str_cfg(acl, "127.0.0.0/8", "allow", 0))
|
||||
return 0;
|
||||
if(cfg->do_ip6) {
|
||||
if(!acl_list_str_cfg(acl, "::0/0", "refuse", 0))
|
||||
return 0;
|
||||
if(!acl_list_str_cfg(acl, "::1", "allow", 0))
|
||||
return 0;
|
||||
if(!acl_list_str_cfg(acl, "::ffff:127.0.0.1", "allow", 0))
|
||||
@@ -466,7 +553,212 @@ acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||
return 1;
|
||||
}
|
||||
|
||||
enum acl_access
|
||||
void
|
||||
acl_interface_init(struct acl_list* acl_interface)
|
||||
{
|
||||
regional_free_all(acl_interface->region);
|
||||
/* We want comparison in the tree to include only address and port.
|
||||
* We don't care about comparing node->net. All addresses in the
|
||||
* acl_interface->tree should have either 32 (ipv4) or 128 (ipv6).
|
||||
* Initialise with the appropriate compare function but keep treating
|
||||
* it as an addr_tree. */
|
||||
addr_tree_addrport_init(&acl_interface->tree);
|
||||
}
|
||||
|
||||
static int
|
||||
read_acl_interface_action(struct acl_list* acl_interface,
|
||||
struct config_str2list* acls, int port)
|
||||
{
|
||||
struct config_str2list* p;
|
||||
for(p = acls; p; p = p->next) {
|
||||
char** resif = NULL;
|
||||
int num_resif = 0;
|
||||
int i;
|
||||
log_assert(p->str && p->str2);
|
||||
if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif))
|
||||
return 0;
|
||||
for(i = 0; i<num_resif; i++) {
|
||||
if(!acl_interface_str_cfg(acl_interface, resif[i], p->str2, port)){
|
||||
config_del_strarray(resif, num_resif);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
config_del_strarray(resif, num_resif);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl view config for interface */
|
||||
static int
|
||||
read_acl_interface_view(struct acl_list* acl_interface,
|
||||
struct config_str2list** acl_view,
|
||||
struct views* v, int port)
|
||||
{
|
||||
struct config_str2list* np, *p = *acl_view;
|
||||
*acl_view = NULL;
|
||||
while(p) {
|
||||
char** resif = NULL;
|
||||
int num_resif = 0;
|
||||
int i;
|
||||
log_assert(p->str && p->str2);
|
||||
if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) {
|
||||
config_deldblstrlist(p);
|
||||
return 0;
|
||||
}
|
||||
for(i = 0; i<num_resif; i++) {
|
||||
if(!acl_list_view_cfg(acl_interface, resif[i], p->str2,
|
||||
v, 1, port)) {
|
||||
config_del_strarray(resif, num_resif);
|
||||
config_deldblstrlist(p);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
config_del_strarray(resif, num_resif);
|
||||
/* free the items as we go to free up memory */
|
||||
np = p->next;
|
||||
free(p->str);
|
||||
free(p->str2);
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl tags config for interface */
|
||||
static int
|
||||
read_acl_interface_tags(struct acl_list* acl_interface,
|
||||
struct config_strbytelist** acl_tags, int port)
|
||||
{
|
||||
struct config_strbytelist* np, *p = *acl_tags;
|
||||
*acl_tags = NULL;
|
||||
while(p) {
|
||||
char** resif = NULL;
|
||||
int num_resif = 0;
|
||||
int i;
|
||||
log_assert(p->str && p->str2);
|
||||
if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) {
|
||||
config_del_strbytelist(p);
|
||||
return 0;
|
||||
}
|
||||
for(i = 0; i<num_resif; i++) {
|
||||
if(!acl_list_tags_cfg(acl_interface, resif[i], p->str2,
|
||||
p->str2len, 1, port)) {
|
||||
config_del_strbytelist(p);
|
||||
config_del_strarray(resif, num_resif);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
config_del_strarray(resif, num_resif);
|
||||
/* free the items as we go to free up memory */
|
||||
np = p->next;
|
||||
free(p->str);
|
||||
free(p->str2);
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl tag actions config for interface*/
|
||||
static int
|
||||
read_acl_interface_tag_actions(struct acl_list* acl_interface,
|
||||
struct config_file* cfg,
|
||||
struct config_str3list** acl_tag_actions, int port)
|
||||
{
|
||||
struct config_str3list* p, *np;
|
||||
p = *acl_tag_actions;
|
||||
*acl_tag_actions = NULL;
|
||||
while(p) {
|
||||
char** resif = NULL;
|
||||
int num_resif = 0;
|
||||
int i;
|
||||
log_assert(p->str && p->str2 && p->str3);
|
||||
if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) {
|
||||
config_deltrplstrlist(p);
|
||||
return 0;
|
||||
}
|
||||
for(i = 0; i<num_resif; i++) {
|
||||
if(!acl_list_tag_action_cfg(acl_interface, cfg,
|
||||
resif[i], p->str2, p->str3, 1, port)) {
|
||||
config_deltrplstrlist(p);
|
||||
config_del_strarray(resif, num_resif);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
config_del_strarray(resif, num_resif);
|
||||
/* free the items as we go to free up memory */
|
||||
np = p->next;
|
||||
free(p->str);
|
||||
free(p->str2);
|
||||
free(p->str3);
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl tag datas config for interface */
|
||||
static int
|
||||
read_acl_interface_tag_datas(struct acl_list* acl_interface,
|
||||
struct config_file* cfg,
|
||||
struct config_str3list** acl_tag_datas, int port)
|
||||
{
|
||||
struct config_str3list* p, *np;
|
||||
p = *acl_tag_datas;
|
||||
*acl_tag_datas = NULL;
|
||||
while(p) {
|
||||
char** resif = NULL;
|
||||
int num_resif = 0;
|
||||
int i;
|
||||
log_assert(p->str && p->str2 && p->str3);
|
||||
if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) {
|
||||
config_deltrplstrlist(p);
|
||||
return 0;
|
||||
}
|
||||
for(i = 0; i<num_resif; i++) {
|
||||
if(!acl_list_tag_data_cfg(acl_interface, cfg,
|
||||
resif[i], p->str2, p->str3, 1, port)) {
|
||||
config_deltrplstrlist(p);
|
||||
config_del_strarray(resif, num_resif);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
config_del_strarray(resif, num_resif);
|
||||
/* free the items as we go to free up memory */
|
||||
np = p->next;
|
||||
free(p->str);
|
||||
free(p->str2);
|
||||
free(p->str3);
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
acl_interface_apply_cfg(struct acl_list* acl_interface, struct config_file* cfg,
|
||||
struct views* v)
|
||||
{
|
||||
if(!read_acl_interface_action(acl_interface, cfg->interface_actions,
|
||||
cfg->port))
|
||||
return 0;
|
||||
if(!read_acl_interface_view(acl_interface, &cfg->interface_view, v,
|
||||
cfg->port))
|
||||
return 0;
|
||||
if(!read_acl_interface_tags(acl_interface, &cfg->interface_tags,
|
||||
cfg->port))
|
||||
return 0;
|
||||
if(!read_acl_interface_tag_actions(acl_interface, cfg,
|
||||
&cfg->interface_tag_actions, cfg->port))
|
||||
return 0;
|
||||
if(!read_acl_interface_tag_datas(acl_interface, cfg,
|
||||
&cfg->interface_tag_datas, cfg->port))
|
||||
return 0;
|
||||
addr_tree_init_parents(&acl_interface->tree);
|
||||
return 1;
|
||||
}
|
||||
|
||||
enum acl_access
|
||||
acl_get_control(struct acl_addr* acl)
|
||||
{
|
||||
if(acl) return acl->control;
|
||||
@@ -481,9 +773,57 @@ acl_addr_lookup(struct acl_list* acl, struct sockaddr_storage* addr,
|
||||
addr, addrlen);
|
||||
}
|
||||
|
||||
size_t
|
||||
size_t
|
||||
acl_list_get_mem(struct acl_list* acl)
|
||||
{
|
||||
if(!acl) return 0;
|
||||
return sizeof(*acl) + regional_get_mem(acl->region);
|
||||
}
|
||||
|
||||
const char* acl_access_to_str(enum acl_access acl)
|
||||
{
|
||||
switch(acl) {
|
||||
case acl_deny: return "deny";
|
||||
case acl_refuse: return "refuse";
|
||||
case acl_deny_non_local: return "deny_non_local";
|
||||
case acl_refuse_non_local: return "refuse_non_local";
|
||||
case acl_allow: return "allow";
|
||||
case acl_allow_snoop: return "allow_snoop";
|
||||
case acl_allow_setrd: return "allow_setrd";
|
||||
default: break;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
void
|
||||
log_acl_action(const char* action, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, enum acl_access acl, struct acl_addr* acladdr)
|
||||
{
|
||||
char a[128], n[128];
|
||||
uint16_t port;
|
||||
addr_to_str(addr, addrlen, a, sizeof(a));
|
||||
port = ntohs(((struct sockaddr_in*)addr)->sin_port);
|
||||
if(acladdr) {
|
||||
addr_to_str(&acladdr->node.addr, acladdr->node.addrlen,
|
||||
n, sizeof(n));
|
||||
verbose(VERB_ALGO, "%s query from %s port %d because of "
|
||||
"%s/%d %s%s", action, a, (int)port, n,
|
||||
acladdr->node.net,
|
||||
acladdr->is_interface?"(ACL on interface IP) ":"",
|
||||
acl_access_to_str(acl));
|
||||
} else {
|
||||
verbose(VERB_ALGO, "%s query from %s port %d", action, a,
|
||||
(int)port);
|
||||
}
|
||||
}
|
||||
|
||||
void acl_list_swap_tree(struct acl_list* acl, struct acl_list* data)
|
||||
{
|
||||
/* swap tree and region */
|
||||
rbtree_type oldtree = acl->tree;
|
||||
struct regional* oldregion = acl->region;
|
||||
acl->tree = data->tree;
|
||||
acl->region = data->region;
|
||||
data->tree = oldtree;
|
||||
data->region = oldregion;
|
||||
}
|
||||
|
||||
+60
-5
@@ -36,7 +36,7 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file keeps track of the list of clients that are allowed to
|
||||
* This file keeps track of the list of clients that are allowed to
|
||||
* access the server.
|
||||
*/
|
||||
|
||||
@@ -64,8 +64,12 @@ enum acl_access {
|
||||
acl_allow,
|
||||
/** allow full access for all queries, recursion and cache snooping */
|
||||
acl_allow_snoop,
|
||||
/** allow full access for recursion queries and set RD flag regardless of request */
|
||||
acl_allow_setrd
|
||||
/** allow full access for recursion queries and set RD flag regardless
|
||||
* of request */
|
||||
acl_allow_setrd,
|
||||
/** allow full access for recursion (+RD) queries if valid cookie
|
||||
* present or stateful transport */
|
||||
acl_allow_cookie
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -74,7 +78,7 @@ enum acl_access {
|
||||
struct acl_list {
|
||||
/** regional for allocation */
|
||||
struct regional* region;
|
||||
/**
|
||||
/**
|
||||
* Tree of the addresses that are allowed/blocked.
|
||||
* contents of type acl_addr.
|
||||
*/
|
||||
@@ -103,12 +107,14 @@ struct acl_addr {
|
||||
struct config_strlist** tag_datas;
|
||||
/** size of the tag_datas array */
|
||||
size_t tag_datas_size;
|
||||
/* If the acl node is for an interface */
|
||||
int is_interface;
|
||||
/* view element, NULL if none */
|
||||
struct view* view;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create acl structure
|
||||
* Create acl structure
|
||||
* @return new structure or NULL on error.
|
||||
*/
|
||||
struct acl_list* acl_list_create(void);
|
||||
@@ -119,6 +125,20 @@ struct acl_list* acl_list_create(void);
|
||||
*/
|
||||
void acl_list_delete(struct acl_list* acl);
|
||||
|
||||
/**
|
||||
* Insert interface in the acl_list. This should happen when the listening
|
||||
* interface is setup.
|
||||
* @param acl_interface: acl_list to insert to.
|
||||
* @param addr: interface IP.
|
||||
* @param addrlen: length of the interface IP.
|
||||
* @param control: acl_access.
|
||||
* @return new structure or NULL on error.
|
||||
*/
|
||||
struct acl_addr*
|
||||
acl_interface_insert(struct acl_list* acl_interface,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
enum acl_access control);
|
||||
|
||||
/**
|
||||
* Process access control config.
|
||||
* @param acl: where to store.
|
||||
@@ -129,6 +149,22 @@ void acl_list_delete(struct acl_list* acl);
|
||||
int acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||
struct views* v);
|
||||
|
||||
/**
|
||||
* Initialise (also clean) the acl_interface struct.
|
||||
* @param acl_interface: where to store.
|
||||
*/
|
||||
void acl_interface_init(struct acl_list* acl_interface);
|
||||
|
||||
/**
|
||||
* Process interface control config.
|
||||
* @param acl_interface: where to store.
|
||||
* @param cfg: config options.
|
||||
* @param v: views structure
|
||||
* @return 0 on error.
|
||||
*/
|
||||
int acl_interface_apply_cfg(struct acl_list* acl_interface, struct config_file* cfg,
|
||||
struct views* v);
|
||||
|
||||
/**
|
||||
* Lookup access control status for acl structure.
|
||||
* @param acl: structure for acl storage.
|
||||
@@ -154,4 +190,23 @@ acl_addr_lookup(struct acl_list* acl, struct sockaddr_storage* addr,
|
||||
*/
|
||||
size_t acl_list_get_mem(struct acl_list* acl);
|
||||
|
||||
/*
|
||||
* Get string for acl access specification
|
||||
* @param acl: access type value
|
||||
* @return string
|
||||
*/
|
||||
const char* acl_access_to_str(enum acl_access acl);
|
||||
|
||||
/* log acl and addr for action */
|
||||
void log_acl_action(const char* action, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, enum acl_access acl, struct acl_addr* acladdr);
|
||||
|
||||
/**
|
||||
* Swap internal tree with preallocated entries.
|
||||
* @param acl: the acl structure.
|
||||
* @param data: the data structure used to take elements from. This contains
|
||||
* the old elements on return.
|
||||
*/
|
||||
void acl_list_swap_tree(struct acl_list* acl, struct acl_list* data);
|
||||
|
||||
#endif /* DAEMON_ACL_LIST_H */
|
||||
|
||||
+281
-125
@@ -47,10 +47,12 @@
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/outside_network.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/config_file.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "iterator/iter_delegpt.h"
|
||||
#include "iterator/iter_utils.h"
|
||||
@@ -60,84 +62,231 @@
|
||||
#include "sldns/wire2str.h"
|
||||
#include "sldns/str2wire.h"
|
||||
|
||||
/** dump one rrset zonefile line */
|
||||
static int
|
||||
dump_rrset_line(RES* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i)
|
||||
static void spool_txt_printf(struct config_strlist_head* txt,
|
||||
const char* format, ...) ATTR_FORMAT(printf, 2, 3);
|
||||
|
||||
/** Append to strlist at end, and log error if out of memory. */
|
||||
static void
|
||||
spool_txt_string(struct config_strlist_head* txt, char* str)
|
||||
{
|
||||
char s[65535];
|
||||
if(!packed_rr_to_string(k, i, now, s, sizeof(s))) {
|
||||
return ssl_printf(ssl, "BADRR\n");
|
||||
if(!cfg_strlist_append(txt, strdup(str))) {
|
||||
log_err("out of memory in spool text");
|
||||
}
|
||||
return ssl_printf(ssl, "%s", s);
|
||||
}
|
||||
|
||||
/** Spool txt to spool list. */
|
||||
static void
|
||||
spool_txt_vmsg(struct config_strlist_head* txt, const char* format,
|
||||
va_list args)
|
||||
{
|
||||
char msg[65535];
|
||||
vsnprintf(msg, sizeof(msg), format, args);
|
||||
spool_txt_string(txt, msg);
|
||||
}
|
||||
|
||||
/** Print item to spool list. On alloc failure the list is as before. */
|
||||
static void
|
||||
spool_txt_printf(struct config_strlist_head* txt, const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
spool_txt_vmsg(txt, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/** dump one rrset zonefile line */
|
||||
static void
|
||||
dump_rrset_line(struct config_strlist_head* txt, struct ub_packed_rrset_key* k,
|
||||
time_t now, size_t i)
|
||||
{
|
||||
char s[65535*4+2048];
|
||||
if(!packed_rr_to_string(k, i, now, s, sizeof(s))) {
|
||||
spool_txt_string(txt, "BADRR\n");
|
||||
return;
|
||||
}
|
||||
spool_txt_string(txt, s);
|
||||
}
|
||||
|
||||
/** dump rrset key and data info */
|
||||
static int
|
||||
dump_rrset(RES* ssl, struct ub_packed_rrset_key* k,
|
||||
static void
|
||||
dump_rrset(struct config_strlist_head* txt, 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 */
|
||||
if(!k || !d) return;
|
||||
if(k->id == 0) return; /* deleted */
|
||||
if(d->ttl < now) return; /* expired */
|
||||
|
||||
/* meta line */
|
||||
if(!ssl_printf(ssl, ";rrset%s " ARG_LL "d %u %u %d %d\n",
|
||||
spool_txt_printf(txt, ";rrset%s " ARG_LL "d %u %u %d %d\n",
|
||||
(k->rk.flags & PACKED_RRSET_NSEC_AT_APEX)?" nsec_apex":"",
|
||||
(long long)(d->ttl - now),
|
||||
(unsigned)d->count, (unsigned)d->rrsig_count,
|
||||
(int)d->trust, (int)d->security
|
||||
))
|
||||
return 0;
|
||||
);
|
||||
for(i=0; i<d->count + d->rrsig_count; i++) {
|
||||
if(!dump_rrset_line(ssl, k, now, i))
|
||||
dump_rrset_line(txt, k, now, i);
|
||||
}
|
||||
}
|
||||
|
||||
/** Spool strlist to the output. */
|
||||
static int
|
||||
spool_strlist(RES* ssl, struct config_strlist* list)
|
||||
{
|
||||
struct config_strlist* s;
|
||||
for(s=list; s; s=s->next) {
|
||||
if(!ssl_printf(ssl, "%s", s->str))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** dump lruhash rrset cache */
|
||||
/** dump lruhash cache and call callback for every item. */
|
||||
static int
|
||||
dump_rrset_lruhash(RES* ssl, struct lruhash* h, time_t now)
|
||||
dump_lruhash(struct lruhash* table,
|
||||
void (*func)(struct lruhash_entry*, struct config_strlist_head*, void*),
|
||||
RES* ssl, void* arg)
|
||||
{
|
||||
struct lruhash_entry* e;
|
||||
/* lruhash already locked by caller */
|
||||
/* walk in order of lru; best first */
|
||||
for(e=h->lru_start; e; e = e->lru_next) {
|
||||
lock_rw_rdlock(&e->lock);
|
||||
if(!dump_rrset(ssl, (struct ub_packed_rrset_key*)e->key,
|
||||
(struct packed_rrset_data*)e->data, now)) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
int just_started = 1;
|
||||
int not_done = 1;
|
||||
hashvalue_type hash;
|
||||
size_t num = 0; /* number of entries processed. */
|
||||
size_t max = 2; /* number of entries after which it unlocks. */
|
||||
struct config_strlist_head txt; /* Text strings spooled. */
|
||||
memset(&txt, 0, sizeof(txt));
|
||||
|
||||
while(not_done) {
|
||||
size_t i; /* hash bin. */
|
||||
/* Process a number of items. */
|
||||
num = 0;
|
||||
lock_quick_lock(&table->lock);
|
||||
if(just_started) {
|
||||
i = 0;
|
||||
} else {
|
||||
i = hash&table->size_mask;
|
||||
}
|
||||
while(num < max) {
|
||||
/* Process bin. */
|
||||
int found = 0;
|
||||
size_t num_bin = 0;
|
||||
struct lruhash_bin* bin = &table->array[i];
|
||||
struct lruhash_entry* e;
|
||||
lock_quick_lock(&bin->lock);
|
||||
for(e = bin->overflow_list; e; e = e->overflow_next) {
|
||||
/* Entry e is locked by the func. */
|
||||
func(e, &txt, arg);
|
||||
num_bin++;
|
||||
}
|
||||
lock_quick_unlock(&bin->lock);
|
||||
/* This addition of bin number of entries may take
|
||||
* it over the max. */
|
||||
num += num_bin;
|
||||
|
||||
/* Move to next bin. */
|
||||
/* Find one with an entry, with a hash value, so we
|
||||
* can continue from the hash value. The hash value
|
||||
* can be indexed also if the array changes size. */
|
||||
i++;
|
||||
while(i < table->size) {
|
||||
bin = &table->array[i];
|
||||
lock_quick_lock(&bin->lock);
|
||||
if(bin->overflow_list) {
|
||||
hash = bin->overflow_list->hash;
|
||||
lock_quick_unlock(&bin->lock);
|
||||
found = 1;
|
||||
just_started = 0;
|
||||
break;
|
||||
}
|
||||
lock_quick_unlock(&bin->lock);
|
||||
i++;
|
||||
}
|
||||
if(!found) {
|
||||
not_done = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
lock_quick_unlock(&table->lock);
|
||||
/* Print the spooled items, that are collected while the
|
||||
* locks are locked. The print happens while they are not
|
||||
* locked. */
|
||||
if(txt.first) {
|
||||
if(!spool_strlist(ssl, txt.first)) {
|
||||
config_delstrlist(txt.first);
|
||||
return 0;
|
||||
}
|
||||
config_delstrlist(txt.first);
|
||||
memset(&txt, 0, sizeof(txt));
|
||||
}
|
||||
}
|
||||
/* Print the final spooled items. */
|
||||
if(txt.first) {
|
||||
if(!spool_strlist(ssl, txt.first)) {
|
||||
config_delstrlist(txt.first);
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
config_delstrlist(txt.first);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** dump slabhash cache and call callback for every item. */
|
||||
static int
|
||||
dump_slabhash(struct slabhash* sh,
|
||||
void (*func)(struct lruhash_entry*, struct config_strlist_head*, void*),
|
||||
RES* ssl, void* arg)
|
||||
{
|
||||
/* Process a number of items at a time, then unlock the cache,
|
||||
* so that ordinary processing can continue. Keep an iteration marker
|
||||
* to continue the loop. That means the cache can change, items
|
||||
* could be inserted and deleted. And, for example, the hash table
|
||||
* can grow. */
|
||||
size_t slab;
|
||||
for(slab=0; slab<sh->size; slab++) {
|
||||
if(!dump_lruhash(sh->array[slab], func, ssl, arg))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Struct for dump information. */
|
||||
struct dump_info {
|
||||
/** The worker. */
|
||||
struct worker* worker;
|
||||
/** The printout connection. */
|
||||
RES* ssl;
|
||||
};
|
||||
|
||||
/** Dump the rrset cache entry */
|
||||
static void
|
||||
dump_rrset_entry(struct lruhash_entry* e, struct config_strlist_head* txt,
|
||||
void* arg)
|
||||
{
|
||||
struct dump_info* dump_info = (struct dump_info*)arg;
|
||||
lock_rw_rdlock(&e->lock);
|
||||
dump_rrset(txt, (struct ub_packed_rrset_key*)e->key,
|
||||
(struct packed_rrset_data*)e->data,
|
||||
*dump_info->worker->env.now);
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
|
||||
/** dump rrset cache */
|
||||
static int
|
||||
dump_rrset_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
struct rrset_cache* r = worker->env.rrset_cache;
|
||||
size_t slab;
|
||||
struct dump_info dump_info;
|
||||
dump_info.worker = worker;
|
||||
dump_info.ssl = ssl;
|
||||
if(!ssl_printf(ssl, "START_RRSET_CACHE\n")) return 0;
|
||||
for(slab=0; slab<r->table.size; slab++) {
|
||||
lock_quick_lock(&r->table.array[slab]->lock);
|
||||
if(!dump_rrset_lruhash(ssl, r->table.array[slab],
|
||||
*worker->env.now)) {
|
||||
lock_quick_unlock(&r->table.array[slab]->lock);
|
||||
return 0;
|
||||
}
|
||||
lock_quick_unlock(&r->table.array[slab]->lock);
|
||||
}
|
||||
if(!dump_slabhash(&r->table, &dump_rrset_entry, ssl, &dump_info))
|
||||
return 0;
|
||||
return ssl_printf(ssl, "END_RRSET_CACHE\n");
|
||||
}
|
||||
|
||||
/** dump message to rrset reference */
|
||||
static int
|
||||
dump_msg_ref(RES* ssl, struct ub_packed_rrset_key* k)
|
||||
static void
|
||||
dump_msg_ref(struct config_strlist_head* txt, struct ub_packed_rrset_key* k)
|
||||
{
|
||||
char* nm, *tp, *cl;
|
||||
nm = sldns_wire2str_dname(k->rk.dname, k->rk.dname_len);
|
||||
@@ -147,31 +296,25 @@ dump_msg_ref(RES* ssl, struct ub_packed_rrset_key* k)
|
||||
free(nm);
|
||||
free(tp);
|
||||
free(cl);
|
||||
return ssl_printf(ssl, "BADREF\n");
|
||||
}
|
||||
if(!ssl_printf(ssl, "%s %s %s %d\n", nm, cl, tp, (int)k->rk.flags)) {
|
||||
free(nm);
|
||||
free(tp);
|
||||
free(cl);
|
||||
return 0;
|
||||
spool_txt_string(txt, "BADREF\n");
|
||||
return;
|
||||
}
|
||||
spool_txt_printf(txt, "%s %s %s %d\n", nm, cl, tp, (int)k->rk.flags);
|
||||
free(nm);
|
||||
free(tp);
|
||||
free(cl);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** dump message entry */
|
||||
static int
|
||||
dump_msg(RES* ssl, struct query_info* k, struct reply_info* d,
|
||||
time_t now)
|
||||
static void
|
||||
dump_msg(struct config_strlist_head* txt, struct query_info* k,
|
||||
struct reply_info* d, time_t now)
|
||||
{
|
||||
size_t i;
|
||||
char* nm, *tp, *cl;
|
||||
if(!k || !d) return 1;
|
||||
if(d->ttl < now) return 1; /* expired */
|
||||
|
||||
if(!k || !d) return;
|
||||
if(d->ttl < now) return; /* expired */
|
||||
|
||||
nm = sldns_wire2str_dname(k->qname, k->qname_len);
|
||||
tp = sldns_wire2str_type(k->qtype);
|
||||
cl = sldns_wire2str_class(k->qclass);
|
||||
@@ -179,43 +322,35 @@ dump_msg(RES* ssl, struct query_info* k, struct reply_info* d,
|
||||
free(nm);
|
||||
free(tp);
|
||||
free(cl);
|
||||
return 1; /* skip this entry */
|
||||
return; /* skip this entry */
|
||||
}
|
||||
if(!rrset_array_lock(d->ref, d->rrset_count, now)) {
|
||||
/* rrsets have timed out or do not exist */
|
||||
free(nm);
|
||||
free(tp);
|
||||
free(cl);
|
||||
return 1; /* skip this entry */
|
||||
return; /* skip this entry */
|
||||
}
|
||||
|
||||
|
||||
/* meta line */
|
||||
if(!ssl_printf(ssl, "msg %s %s %s %d %d " ARG_LL "d %d %u %u %u\n",
|
||||
nm, cl, tp,
|
||||
(int)d->flags, (int)d->qdcount,
|
||||
(long long)(d->ttl-now), (int)d->security,
|
||||
(unsigned)d->an_numrrsets,
|
||||
(unsigned)d->ns_numrrsets,
|
||||
(unsigned)d->ar_numrrsets)) {
|
||||
free(nm);
|
||||
free(tp);
|
||||
free(cl);
|
||||
rrset_array_unlock(d->ref, d->rrset_count);
|
||||
return 0;
|
||||
}
|
||||
spool_txt_printf(txt,
|
||||
"msg %s %s %s %d %d " ARG_LL "d %d %u %u %u %d %s\n",
|
||||
nm, cl, tp,
|
||||
(int)d->flags, (int)d->qdcount,
|
||||
(long long)(d->ttl-now), (int)d->security,
|
||||
(unsigned)d->an_numrrsets,
|
||||
(unsigned)d->ns_numrrsets,
|
||||
(unsigned)d->ar_numrrsets,
|
||||
(int)d->reason_bogus,
|
||||
d->reason_bogus_str?d->reason_bogus_str:"");
|
||||
free(nm);
|
||||
free(tp);
|
||||
free(cl);
|
||||
|
||||
for(i=0; i<d->rrset_count; i++) {
|
||||
if(!dump_msg_ref(ssl, d->rrsets[i])) {
|
||||
rrset_array_unlock(d->ref, d->rrset_count);
|
||||
return 0;
|
||||
}
|
||||
dump_msg_ref(txt, d->rrsets[i]);
|
||||
}
|
||||
rrset_array_unlock(d->ref, d->rrset_count);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** copy msg to worker pad */
|
||||
@@ -244,49 +379,40 @@ copy_msg(struct regional* region, struct lruhash_entry* e,
|
||||
return (*k)->qname != NULL;
|
||||
}
|
||||
|
||||
/** dump lruhash msg cache */
|
||||
static int
|
||||
dump_msg_lruhash(RES* ssl, struct worker* worker, struct lruhash* h)
|
||||
/** Dump the msg entry. */
|
||||
static void
|
||||
dump_msg_entry(struct lruhash_entry* e, struct config_strlist_head* txt,
|
||||
void* arg)
|
||||
{
|
||||
struct lruhash_entry* e;
|
||||
struct dump_info* dump_info = (struct dump_info*)arg;
|
||||
struct query_info* k;
|
||||
struct reply_info* d;
|
||||
|
||||
/* lruhash already locked by caller */
|
||||
/* walk in order of lru; best first */
|
||||
for(e=h->lru_start; e; e = e->lru_next) {
|
||||
regional_free_all(worker->scratchpad);
|
||||
lock_rw_rdlock(&e->lock);
|
||||
/* make copy of rrset in worker buffer */
|
||||
if(!copy_msg(worker->scratchpad, e, &k, &d)) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 0;
|
||||
}
|
||||
regional_free_all(dump_info->worker->scratchpad);
|
||||
/* Make copy of rrset in worker buffer. */
|
||||
lock_rw_rdlock(&e->lock);
|
||||
if(!copy_msg(dump_info->worker->scratchpad, e, &k, &d)) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
/* release lock so we can lookup the rrset references
|
||||
* in the rrset cache */
|
||||
if(!dump_msg(ssl, k, d, *worker->env.now)) {
|
||||
return 0;
|
||||
}
|
||||
log_err("out of memory in dump_msg_entry");
|
||||
return;
|
||||
}
|
||||
return 1;
|
||||
lock_rw_unlock(&e->lock);
|
||||
/* Release lock so we can lookup the rrset references
|
||||
* in the rrset cache. */
|
||||
dump_msg(txt, k, d, *dump_info->worker->env.now);
|
||||
}
|
||||
|
||||
/** dump msg cache */
|
||||
static int
|
||||
dump_msg_cache(RES* ssl, struct worker* worker)
|
||||
{
|
||||
struct slabhash* sh = worker->env.msg_cache;
|
||||
size_t slab;
|
||||
struct dump_info dump_info;
|
||||
dump_info.worker = worker;
|
||||
dump_info.ssl = ssl;
|
||||
if(!ssl_printf(ssl, "START_MSG_CACHE\n")) return 0;
|
||||
for(slab=0; slab<sh->size; slab++) {
|
||||
lock_quick_lock(&sh->array[slab]->lock);
|
||||
if(!dump_msg_lruhash(ssl, worker, sh->array[slab])) {
|
||||
lock_quick_unlock(&sh->array[slab]->lock);
|
||||
return 0;
|
||||
}
|
||||
lock_quick_unlock(&sh->array[slab]->lock);
|
||||
}
|
||||
if(!dump_slabhash(worker->env.msg_cache, &dump_msg_entry, ssl,
|
||||
&dump_info))
|
||||
return 0;
|
||||
return ssl_printf(ssl, "END_MSG_CACHE\n");
|
||||
}
|
||||
|
||||
@@ -329,7 +455,7 @@ load_rr(RES* ssl, sldns_buffer* buf, struct regional* region,
|
||||
/* read the line */
|
||||
if(!ssl_read_buf(ssl, buf))
|
||||
return 0;
|
||||
if(strncmp((char*)sldns_buffer_begin(buf), "BADRR\n", 6) == 0) {
|
||||
if(strcmp((char*)sldns_buffer_begin(buf), "BADRR") == 0) {
|
||||
*go_on = 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -385,7 +511,7 @@ move_into_cache(struct ub_packed_rrset_key* k,
|
||||
struct rrset_ref ref;
|
||||
uint8_t* p;
|
||||
|
||||
ak = alloc_special_obtain(&worker->alloc);
|
||||
ak = alloc_special_obtain(worker->alloc);
|
||||
if(!ak) {
|
||||
log_warn("error out of memory");
|
||||
return 0;
|
||||
@@ -396,7 +522,7 @@ move_into_cache(struct ub_packed_rrset_key* k,
|
||||
ak->rk.dname = (uint8_t*)memdup(k->rk.dname, k->rk.dname_len);
|
||||
if(!ak->rk.dname) {
|
||||
log_warn("error out of memory");
|
||||
ub_packed_rrset_parsedelete(ak, &worker->alloc);
|
||||
ub_packed_rrset_parsedelete(ak, worker->alloc);
|
||||
return 0;
|
||||
}
|
||||
s = sizeof(*ad) + (sizeof(size_t) + sizeof(uint8_t*) +
|
||||
@@ -406,7 +532,7 @@ move_into_cache(struct ub_packed_rrset_key* k,
|
||||
ad = (struct packed_rrset_data*)malloc(s);
|
||||
if(!ad) {
|
||||
log_warn("error out of memory");
|
||||
ub_packed_rrset_parsedelete(ak, &worker->alloc);
|
||||
ub_packed_rrset_parsedelete(ak, worker->alloc);
|
||||
return 0;
|
||||
}
|
||||
p = (uint8_t*)ad;
|
||||
@@ -429,7 +555,8 @@ move_into_cache(struct ub_packed_rrset_key* k,
|
||||
ref.key = ak;
|
||||
ref.id = ak->id;
|
||||
(void)rrset_cache_update(worker->env.rrset_cache, &ref,
|
||||
&worker->alloc, *worker->env.now);
|
||||
worker->alloc, *worker->env.now);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -630,6 +757,9 @@ load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
long long ttl;
|
||||
size_t i;
|
||||
int go_on = 1;
|
||||
int ede;
|
||||
int consumed = 0;
|
||||
char* ede_str = NULL;
|
||||
|
||||
regional_free_all(region);
|
||||
|
||||
@@ -644,11 +774,16 @@ load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
}
|
||||
|
||||
/* read remainder of line */
|
||||
if(sscanf(s, " %u %u " ARG_LL "d %u %u %u %u", &flags, &qdcount, &ttl,
|
||||
&security, &an, &ns, &ar) != 7) {
|
||||
/* note the last space before any possible EDE text */
|
||||
if(sscanf(s, " %u %u " ARG_LL "d %u %u %u %u %d %n", &flags, &qdcount, &ttl,
|
||||
&security, &an, &ns, &ar, &ede, &consumed) != 8) {
|
||||
log_warn("error cannot parse numbers: %s", s);
|
||||
return 0;
|
||||
}
|
||||
/* there may be EDE text after the numbers */
|
||||
if(consumed > 0 && (size_t)consumed < strlen(s))
|
||||
ede_str = s + consumed;
|
||||
memset(&rep, 0, sizeof(rep));
|
||||
rep.flags = (uint16_t)flags;
|
||||
rep.qdcount = (uint16_t)qdcount;
|
||||
rep.ttl = (time_t)ttl;
|
||||
@@ -663,6 +798,8 @@ load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
rep.ns_numrrsets = (size_t)ns;
|
||||
rep.ar_numrrsets = (size_t)ar;
|
||||
rep.rrset_count = (size_t)an+(size_t)ns+(size_t)ar;
|
||||
rep.reason_bogus = (sldns_ede_code)ede;
|
||||
rep.reason_bogus_str = ede_str?(char*)regional_strdup(region, ede_str):NULL;
|
||||
rep.rrsets = (struct ub_packed_rrset_key**)regional_alloc_zero(
|
||||
region, sizeof(struct ub_packed_rrset_key*)*rep.rrset_count);
|
||||
|
||||
@@ -677,7 +814,8 @@ load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
if(!go_on)
|
||||
return 1; /* skip this one, not all references satisfied */
|
||||
|
||||
if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL, flags)) {
|
||||
if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL, flags,
|
||||
*worker->env.now, 1)) {
|
||||
log_warn("error out of memory");
|
||||
return 0;
|
||||
}
|
||||
@@ -796,12 +934,18 @@ print_dp_main(RES* ssl, struct delegpt* dp, struct dns_msg* msg)
|
||||
struct ub_packed_rrset_key* k = msg->rep->rrsets[i];
|
||||
struct packed_rrset_data* d =
|
||||
(struct packed_rrset_data*)k->entry.data;
|
||||
struct config_strlist_head txt;
|
||||
memset(&txt, 0, sizeof(txt));
|
||||
if(d->security == sec_status_bogus) {
|
||||
if(!ssl_printf(ssl, "Address is BOGUS:\n"))
|
||||
return;
|
||||
}
|
||||
if(!dump_rrset(ssl, k, d, 0))
|
||||
dump_rrset(&txt, k, d, 0);
|
||||
if(!spool_strlist(ssl, txt.first)) {
|
||||
config_delstrlist(txt.first);
|
||||
return;
|
||||
}
|
||||
config_delstrlist(txt.first);
|
||||
}
|
||||
delegpt_count_ns(dp, &n_ns, &n_miss);
|
||||
delegpt_count_addr(dp, &n_addr, &n_res, &n_avail);
|
||||
@@ -821,9 +965,10 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
||||
struct delegpt* dp;
|
||||
struct dns_msg* msg;
|
||||
struct regional* region = worker->scratchpad;
|
||||
char b[260];
|
||||
char b[LDNS_MAX_DOMAINLEN];
|
||||
struct query_info qinfo;
|
||||
struct iter_hints_stub* stub;
|
||||
int nolock = 0;
|
||||
regional_free_all(region);
|
||||
qinfo.qname = nm;
|
||||
qinfo.qname_len = nmlen;
|
||||
@@ -835,26 +980,32 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
||||
if(!ssl_printf(ssl, "The following name servers are used for lookup "
|
||||
"of %s\n", b))
|
||||
return 0;
|
||||
|
||||
dp = forwards_lookup(worker->env.fwds, nm, qinfo.qclass);
|
||||
|
||||
dp = forwards_lookup(worker->env.fwds, nm, qinfo.qclass, nolock);
|
||||
if(dp) {
|
||||
if(!ssl_printf(ssl, "forwarding request:\n"))
|
||||
if(!ssl_printf(ssl, "forwarding request:\n")) {
|
||||
lock_rw_unlock(&worker->env.fwds->lock);
|
||||
return 0;
|
||||
}
|
||||
print_dp_main(ssl, dp, NULL);
|
||||
print_dp_details(ssl, worker, dp);
|
||||
lock_rw_unlock(&worker->env.fwds->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while(1) {
|
||||
dp = dns_cache_find_delegation(&worker->env, nm, nmlen,
|
||||
qinfo.qtype, qinfo.qclass, region, &msg,
|
||||
*worker->env.now);
|
||||
*worker->env.now, 0, NULL, 0);
|
||||
if(!dp) {
|
||||
return ssl_printf(ssl, "no delegation from "
|
||||
"cache; goes to configured roots\n");
|
||||
}
|
||||
/* go up? */
|
||||
if(iter_dp_is_useless(&qinfo, BIT_RD, dp)) {
|
||||
if(iter_dp_is_useless(&qinfo, BIT_RD, dp,
|
||||
(worker->env.cfg->do_ip4 && worker->back->num_ip4 != 0),
|
||||
(worker->env.cfg->do_ip6 && worker->back->num_ip6 != 0),
|
||||
worker->env.cfg->do_nat64)) {
|
||||
print_dp_main(ssl, dp, msg);
|
||||
print_dp_details(ssl, worker, dp);
|
||||
if(!ssl_printf(ssl, "cache delegation was "
|
||||
@@ -874,21 +1025,26 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
stub = hints_lookup_stub(worker->env.hints, nm, qinfo.qclass,
|
||||
dp);
|
||||
dp, nolock);
|
||||
if(stub) {
|
||||
if(stub->noprime) {
|
||||
if(!ssl_printf(ssl, "The noprime stub servers "
|
||||
"are used:\n"))
|
||||
"are used:\n")) {
|
||||
lock_rw_unlock(&worker->env.hints->lock);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if(!ssl_printf(ssl, "The stub is primed "
|
||||
"with servers:\n"))
|
||||
"with servers:\n")) {
|
||||
lock_rw_unlock(&worker->env.hints->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
print_dp_main(ssl, stub->dp, NULL);
|
||||
print_dp_details(ssl, worker, stub->dp);
|
||||
lock_rw_unlock(&worker->env.hints->lock);
|
||||
} else {
|
||||
print_dp_main(ssl, dp, msg);
|
||||
print_dp_details(ssl, worker, dp);
|
||||
|
||||
+568
-46
@@ -79,6 +79,7 @@
|
||||
#include "util/tcp_conn_limit.h"
|
||||
#include "util/edns.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "services/outside_network.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/localzone.h"
|
||||
@@ -91,11 +92,19 @@
|
||||
#include "util/net_help.h"
|
||||
#include "sldns/keyraw.h"
|
||||
#include "respip/respip.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef HAVE_SYSTEMD
|
||||
#include <systemd/sd-daemon.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
#include "cachedb/cachedb.h"
|
||||
#endif
|
||||
|
||||
/** How many quit requests happened. */
|
||||
static int sig_record_quit = 0;
|
||||
@@ -191,6 +200,267 @@ signal_handling_playback(struct worker* wrk)
|
||||
sig_record_reload = 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
/* setup a listening ssl context, fatal_exit() on any failure */
|
||||
static void
|
||||
setup_listen_sslctx(void** ctx, int is_dot, int is_doh,
|
||||
struct config_file* cfg, char* chroot)
|
||||
{
|
||||
char* key = cfg->ssl_service_key;
|
||||
char* pem = cfg->ssl_service_pem;
|
||||
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
|
||||
key += strlen(chroot);
|
||||
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
|
||||
pem += strlen(chroot);
|
||||
if(!(*ctx = listen_sslctx_create(key, pem, NULL,
|
||||
cfg->tls_ciphers, cfg->tls_ciphersuites,
|
||||
(cfg->tls_session_ticket_keys.first &&
|
||||
cfg->tls_session_ticket_keys.first->str[0] != 0),
|
||||
is_dot, is_doh, cfg->tls_protocols))) {
|
||||
log_err("could not set up listen SSL_CTX");
|
||||
*ctx = NULL;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
void* daemon_setup_listen_dot_sslctx(struct daemon* daemon,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
void* ctx;
|
||||
(void)setup_listen_sslctx(&ctx, 1, 0, cfg, daemon->chroot);
|
||||
return ctx;
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
#ifdef HAVE_NGHTTP2_NGHTTP2_H
|
||||
void* daemon_setup_listen_doh_sslctx(struct daemon* daemon,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
void* ctx;
|
||||
(void)setup_listen_sslctx(&ctx, 0, 1, cfg, daemon->chroot);
|
||||
return ctx;
|
||||
}
|
||||
#endif /* HAVE_NGHTTP2_NGHTTP2_H */
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
#ifdef HAVE_NGTCP2
|
||||
void* daemon_setup_listen_quic_sslctx(struct daemon* daemon,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
void* ctx;
|
||||
char* chroot = daemon->chroot;
|
||||
char* key = cfg->ssl_service_key;
|
||||
char* pem = cfg->ssl_service_pem;
|
||||
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
|
||||
key += strlen(chroot);
|
||||
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
|
||||
pem += strlen(chroot);
|
||||
|
||||
if(!(ctx = quic_sslctx_create(key, pem, NULL))) {
|
||||
log_err("could not set up quic SSL_CTX");
|
||||
return NULL;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
#endif /* HAVE_NGTCP2 */
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
void* daemon_setup_connect_dot_sslctx(struct daemon* daemon,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
void* ctx;
|
||||
char* bundle, *chroot = daemon->chroot;
|
||||
bundle = cfg->tls_cert_bundle;
|
||||
if(chroot && bundle && strncmp(bundle, chroot, strlen(chroot)) == 0)
|
||||
bundle += strlen(chroot);
|
||||
|
||||
if(!(ctx = connect_sslctx_create(NULL, NULL, bundle,
|
||||
cfg->tls_win_cert))) {
|
||||
log_err("could not set up connect SSL_CTX");
|
||||
return NULL;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
/* setups the needed ssl contexts, fatal_exit() on any failure */
|
||||
void
|
||||
daemon_setup_sslctxs(struct daemon* daemon, struct config_file* cfg)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
char* chroot = daemon->chroot;
|
||||
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
|
||||
char* key = cfg->ssl_service_key;
|
||||
char* pem = cfg->ssl_service_pem;
|
||||
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
|
||||
key += strlen(chroot);
|
||||
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
|
||||
pem += strlen(chroot);
|
||||
|
||||
/* setup the session keys; the callback to use them will be
|
||||
* attached to each sslctx separately */
|
||||
if(cfg->tls_session_ticket_keys.first &&
|
||||
cfg->tls_session_ticket_keys.first->str[0] != 0) {
|
||||
if(!listen_sslctx_setup_ticket_keys(
|
||||
cfg->tls_session_ticket_keys.first, chroot)) {
|
||||
fatal_exit("could not set session ticket SSL_CTX");
|
||||
}
|
||||
}
|
||||
daemon->listen_dot_sslctx = daemon_setup_listen_dot_sslctx(
|
||||
daemon, cfg);
|
||||
if(!daemon->listen_dot_sslctx)
|
||||
fatal_exit("Could not set up listen dot sslctx");
|
||||
#ifdef HAVE_NGHTTP2_NGHTTP2_H
|
||||
if(cfg_has_https(cfg)) {
|
||||
daemon->listen_doh_sslctx =
|
||||
daemon_setup_listen_doh_sslctx(daemon, cfg);
|
||||
if(!daemon->listen_doh_sslctx)
|
||||
fatal_exit("Could not set up listen doh sslctx");
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
if(cfg_has_quic(cfg)) {
|
||||
daemon->listen_quic_sslctx =
|
||||
daemon_setup_listen_quic_sslctx(daemon, cfg);
|
||||
if(!daemon->listen_quic_sslctx)
|
||||
fatal_exit("Could not set up listen quic sslctx");
|
||||
}
|
||||
#endif /* HAVE_NGTCP2 */
|
||||
|
||||
/* Store the file name and mtime to detect changes later. */
|
||||
daemon->ssl_service_key = strdup(cfg->ssl_service_key);
|
||||
if(!daemon->ssl_service_key)
|
||||
fatal_exit("could not setup ssl ctx: out of memory");
|
||||
if(cfg->ssl_service_pem) {
|
||||
daemon->ssl_service_pem = strdup(cfg->ssl_service_pem);
|
||||
if(!daemon->ssl_service_pem)
|
||||
fatal_exit("could not setup ssl ctx: out of memory");
|
||||
} else {
|
||||
daemon->ssl_service_pem = NULL;
|
||||
}
|
||||
if(!file_get_mtime(key,
|
||||
&daemon->mtime_ssl_service_key,
|
||||
&daemon->mtime_ns_ssl_service_key, NULL))
|
||||
log_err("Could not stat(%s): %s",
|
||||
key, strerror(errno));
|
||||
if(pem) {
|
||||
if(!file_get_mtime(pem,
|
||||
&daemon->mtime_ssl_service_pem,
|
||||
&daemon->mtime_ns_ssl_service_pem, NULL))
|
||||
log_err("Could not stat(%s): %s",
|
||||
pem, strerror(errno));
|
||||
} else {
|
||||
daemon->mtime_ssl_service_pem = 0;
|
||||
daemon->mtime_ns_ssl_service_pem = 0;
|
||||
}
|
||||
}
|
||||
daemon->connect_dot_sslctx = daemon_setup_connect_dot_sslctx(
|
||||
daemon, cfg);
|
||||
if(!daemon->connect_dot_sslctx)
|
||||
fatal_exit("could not setup connect dot sslctx");
|
||||
#else /* HAVE_SSL */
|
||||
(void)daemon;(void)cfg;
|
||||
#endif /* HAVE_SSL */
|
||||
}
|
||||
|
||||
/** Delete the ssl ctxs */
|
||||
static void
|
||||
daemon_delete_sslctxs(struct daemon* daemon)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
listen_sslctx_delete_ticket_keys();
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_dot_sslctx);
|
||||
daemon->listen_dot_sslctx = NULL;
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_doh_sslctx);
|
||||
daemon->listen_doh_sslctx = NULL;
|
||||
SSL_CTX_free((SSL_CTX*)daemon->connect_dot_sslctx);
|
||||
daemon->connect_dot_sslctx = NULL;
|
||||
free(daemon->ssl_service_key);
|
||||
daemon->ssl_service_key = NULL;
|
||||
free(daemon->ssl_service_pem);
|
||||
daemon->ssl_service_pem = NULL;
|
||||
#else
|
||||
(void)daemon;
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_quic_sslctx);
|
||||
daemon->listen_quic_sslctx = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
ssl_cert_changed(struct daemon* daemon, struct config_file* cfg)
|
||||
{
|
||||
time_t mtime = 0;
|
||||
long ns = 0;
|
||||
char* chroot = daemon->chroot;
|
||||
char* key = cfg->ssl_service_key;
|
||||
char* pem = cfg->ssl_service_pem;
|
||||
log_assert(daemon->ssl_service_key && cfg->ssl_service_key);
|
||||
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
|
||||
key += strlen(chroot);
|
||||
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
|
||||
pem += strlen(chroot);
|
||||
|
||||
if(strcmp(daemon->ssl_service_key, cfg->ssl_service_key) != 0)
|
||||
return 1;
|
||||
if(daemon->ssl_service_pem && cfg->ssl_service_pem &&
|
||||
strcmp(daemon->ssl_service_pem, cfg->ssl_service_pem) != 0)
|
||||
return 1;
|
||||
if(!file_get_mtime(key, &mtime, &ns, NULL)) {
|
||||
log_err("Could not stat(%s): %s",
|
||||
key, strerror(errno));
|
||||
/* It has probably changed, but file read is likely going to
|
||||
* fail. */
|
||||
return 0;
|
||||
}
|
||||
if(mtime != daemon->mtime_ssl_service_key ||
|
||||
ns != daemon->mtime_ns_ssl_service_key)
|
||||
return 1;
|
||||
if(pem) {
|
||||
if(!file_get_mtime(pem, &mtime, &ns, NULL)) {
|
||||
log_err("Could not stat(%s): %s",
|
||||
pem, strerror(errno));
|
||||
/* It has probably changed, but file read is likely going to
|
||||
* fail. */
|
||||
return 0;
|
||||
}
|
||||
if(mtime != daemon->mtime_ssl_service_pem ||
|
||||
ns != daemon->mtime_ns_ssl_service_pem)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Reload the sslctxs if they have changed */
|
||||
static void
|
||||
daemon_reload_sslctxs(struct daemon* daemon)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
if(daemon->cfg->ssl_service_key && daemon->cfg->ssl_service_key[0]) {
|
||||
/* See if changed */
|
||||
if(!daemon->ssl_service_key ||
|
||||
ssl_cert_changed(daemon,daemon->cfg)) {
|
||||
verbose(VERB_ALGO, "Reloading certificates");
|
||||
daemon_delete_sslctxs(daemon);
|
||||
daemon_setup_sslctxs(daemon, daemon->cfg);
|
||||
}
|
||||
} else {
|
||||
/* See if sslctxs are removed from config. */
|
||||
if(daemon->ssl_service_key) {
|
||||
verbose(VERB_ALGO, "Removing certificates");
|
||||
daemon_delete_sslctxs(daemon);
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)daemon;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct daemon*
|
||||
daemon_init(void)
|
||||
{
|
||||
@@ -210,7 +480,6 @@ daemon_init(void)
|
||||
}
|
||||
#endif /* USE_WINSOCK */
|
||||
signal_handling_record();
|
||||
checklock_start();
|
||||
#ifdef HAVE_SSL
|
||||
# ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
|
||||
ERR_load_crypto_strings();
|
||||
@@ -228,7 +497,11 @@ daemon_init(void)
|
||||
# else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
# endif
|
||||
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS
|
||||
/* grab the COMP method ptr because openssl leaks it */
|
||||
@@ -237,7 +510,11 @@ daemon_init(void)
|
||||
# if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
# else
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
# endif
|
||||
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
|
||||
if(!ub_openssl_lock_init())
|
||||
@@ -258,6 +535,7 @@ daemon_init(void)
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
daemon->env->modstack = &daemon->mods;
|
||||
/* init edns_known_options */
|
||||
if(!edns_known_options_init(daemon->env)) {
|
||||
free(daemon->env);
|
||||
@@ -272,18 +550,29 @@ daemon_init(void)
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
daemon->tcl = tcl_list_create();
|
||||
if(!daemon->tcl) {
|
||||
daemon->acl_interface = acl_list_create();
|
||||
if(!daemon->acl_interface) {
|
||||
acl_list_delete(daemon->acl);
|
||||
edns_known_options_delete(daemon->env);
|
||||
free(daemon->env);
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
daemon->tcl = tcl_list_create();
|
||||
if(!daemon->tcl) {
|
||||
acl_list_delete(daemon->acl_interface);
|
||||
acl_list_delete(daemon->acl);
|
||||
edns_known_options_delete(daemon->env);
|
||||
free(daemon->env);
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
listen_setup_locks();
|
||||
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_interface);
|
||||
acl_list_delete(daemon->acl);
|
||||
tcl_list_delete(daemon->tcl);
|
||||
edns_known_options_delete(daemon->env);
|
||||
@@ -293,6 +582,7 @@ daemon_init(void)
|
||||
}
|
||||
if(!(daemon->env->edns_strings = edns_strings_create())) {
|
||||
auth_zones_delete(daemon->env->auth_zones);
|
||||
acl_list_delete(daemon->acl_interface);
|
||||
acl_list_delete(daemon->acl);
|
||||
tcl_list_delete(daemon->tcl);
|
||||
edns_known_options_delete(daemon->env);
|
||||
@@ -303,7 +593,27 @@ daemon_init(void)
|
||||
return daemon;
|
||||
}
|
||||
|
||||
int
|
||||
int setup_acl_for_ports(struct acl_list* list, struct listen_port* port_list)
|
||||
{
|
||||
struct acl_addr* acl_node;
|
||||
for(; port_list; port_list=port_list->next) {
|
||||
if(!port_list->socket) {
|
||||
/* This is mainly for testbound where port_list is
|
||||
* empty. */
|
||||
continue;
|
||||
}
|
||||
if(!(acl_node = acl_interface_insert(list,
|
||||
(struct sockaddr_storage*)port_list->socket->addr,
|
||||
port_list->socket->addrlen,
|
||||
acl_refuse))) {
|
||||
return 0;
|
||||
}
|
||||
port_list->socket->acl = acl_node;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
daemon_open_shared_ports(struct daemon* daemon)
|
||||
{
|
||||
log_assert(daemon);
|
||||
@@ -320,6 +630,8 @@ daemon_open_shared_ports(struct daemon* daemon)
|
||||
free(daemon->ports);
|
||||
daemon->ports = NULL;
|
||||
}
|
||||
/* clean acl_interface */
|
||||
acl_interface_init(daemon->acl_interface);
|
||||
if(!resolve_interface_names(daemon->cfg->ifs,
|
||||
daemon->cfg->num_ifs, NULL, &resif, &num_resif))
|
||||
return 0;
|
||||
@@ -329,7 +641,8 @@ daemon_open_shared_ports(struct daemon* daemon)
|
||||
daemon->reuseport = 1;
|
||||
#endif
|
||||
/* try to use reuseport */
|
||||
p0 = listening_ports_open(daemon->cfg, resif, num_resif, &daemon->reuseport);
|
||||
p0 = listening_ports_open(daemon->cfg, resif, num_resif,
|
||||
&daemon->reuseport);
|
||||
if(!p0) {
|
||||
listening_ports_free(p0);
|
||||
config_del_strarray(resif, num_resif);
|
||||
@@ -350,6 +663,12 @@ daemon_open_shared_ports(struct daemon* daemon)
|
||||
return 0;
|
||||
}
|
||||
daemon->ports[0] = p0;
|
||||
if(!setup_acl_for_ports(daemon->acl_interface,
|
||||
daemon->ports[0])) {
|
||||
listening_ports_free(p0);
|
||||
config_del_strarray(resif, num_resif);
|
||||
return 0;
|
||||
}
|
||||
if(daemon->reuseport) {
|
||||
/* continue to use reuseport */
|
||||
for(i=1; i<daemon->num_ports; i++) {
|
||||
@@ -365,6 +684,15 @@ daemon_open_shared_ports(struct daemon* daemon)
|
||||
config_del_strarray(resif, num_resif);
|
||||
return 0;
|
||||
}
|
||||
if(!setup_acl_for_ports(daemon->acl_interface,
|
||||
daemon->ports[i])) {
|
||||
for(i=0; i<daemon->num_ports; i++)
|
||||
listening_ports_free(daemon->ports[i]);
|
||||
free(daemon->ports);
|
||||
daemon->ports = NULL;
|
||||
config_del_strarray(resif, num_resif);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
config_del_strarray(resif, num_resif);
|
||||
@@ -385,6 +713,19 @@ daemon_open_shared_ports(struct daemon* daemon)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
daemon_privileged(struct daemon* daemon)
|
||||
{
|
||||
daemon->env->cfg = daemon->cfg;
|
||||
daemon->env->alloc = &daemon->superalloc;
|
||||
daemon->env->worker = NULL;
|
||||
if(!modstack_call_startup(&daemon->mods, daemon->cfg->module_conf,
|
||||
daemon->env)) {
|
||||
fatal_exit("failed to startup modules");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup modules. setup module stack.
|
||||
* @param daemon: the daemon
|
||||
@@ -394,11 +735,15 @@ static void daemon_setup_modules(struct daemon* daemon)
|
||||
daemon->env->cfg = daemon->cfg;
|
||||
daemon->env->alloc = &daemon->superalloc;
|
||||
daemon->env->worker = NULL;
|
||||
daemon->env->need_to_validate = 0; /* set by module init below */
|
||||
if(!modstack_setup(&daemon->mods, daemon->cfg->module_conf,
|
||||
daemon->env)) {
|
||||
fatal_exit("failed to setup modules");
|
||||
if(daemon->mods_inited) {
|
||||
modstack_call_deinit(&daemon->mods, daemon->env);
|
||||
}
|
||||
daemon->env->need_to_validate = 0; /* set by module init below */
|
||||
if(!modstack_call_init(&daemon->mods, daemon->cfg->module_conf,
|
||||
daemon->env)) {
|
||||
fatal_exit("failed to init modules");
|
||||
}
|
||||
daemon->mods_inited = 1;
|
||||
log_edns_known_options(VERB_ALGO, daemon->env);
|
||||
}
|
||||
|
||||
@@ -433,6 +778,30 @@ static int daemon_get_shufport(struct daemon* daemon, int* shufport)
|
||||
return avail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear and delete per-worker alloc caches, and free memory maintained in
|
||||
* superalloc.
|
||||
* The rrset and message caches must be empty at the time of call.
|
||||
* @param daemon: the daemon that maintains the alloc caches to be cleared.
|
||||
*/
|
||||
static void
|
||||
daemon_clear_allocs(struct daemon* daemon)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* daemon->num may be different during reloads (after configuration
|
||||
* read). Use old_num which has the correct value used to setup the
|
||||
* worker_allocs */
|
||||
for(i=0; i<daemon->old_num; i++) {
|
||||
alloc_clear(daemon->worker_allocs[i]);
|
||||
free(daemon->worker_allocs[i]);
|
||||
}
|
||||
free(daemon->worker_allocs);
|
||||
daemon->worker_allocs = NULL;
|
||||
|
||||
alloc_clear_special(&daemon->superalloc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate empty worker structures. With backptr and thread-number,
|
||||
* from 0..numthread initialised. Used as user arguments to new threads.
|
||||
@@ -457,6 +826,18 @@ daemon_create_workers(struct daemon* daemon)
|
||||
fatal_exit("out of memory during daemon init");
|
||||
numport = daemon_get_shufport(daemon, shufport);
|
||||
verbose(VERB_ALGO, "total of %d outgoing ports available", numport);
|
||||
if(!(daemon->shared_ports = shared_ports_create(daemon->cfg->out_ifs,
|
||||
daemon->cfg->num_out_ifs, daemon->cfg->do_ip4,
|
||||
daemon->cfg->do_ip6, shufport, numport)))
|
||||
fatal_exit("could not setup shared ports: out of memory");
|
||||
|
||||
#ifdef HAVE_NGTCP2
|
||||
if (cfg_has_quic(daemon->cfg)) {
|
||||
daemon->doq_table = doq_table_create(daemon->cfg, daemon->rand);
|
||||
if(!daemon->doq_table)
|
||||
fatal_exit("could not create doq_table: out of memory");
|
||||
}
|
||||
#endif
|
||||
|
||||
daemon->num = (daemon->cfg->num_threads?daemon->cfg->num_threads:1);
|
||||
if(daemon->reuseport && (int)daemon->num < (int)daemon->num_ports) {
|
||||
@@ -479,12 +860,24 @@ daemon_create_workers(struct daemon* daemon)
|
||||
#endif
|
||||
}
|
||||
for(i=0; i<daemon->num; i++) {
|
||||
if(!(daemon->workers[i] = worker_create(daemon, i,
|
||||
shufport+numport*i/daemon->num,
|
||||
numport*(i+1)/daemon->num - numport*i/daemon->num)))
|
||||
/* the above is not ports/numthr, due to rounding */
|
||||
if(!(daemon->workers[i] = worker_create(daemon, i)))
|
||||
fatal_exit("could not create worker");
|
||||
}
|
||||
/* create per-worker alloc caches if not reusing existing ones. */
|
||||
if(!daemon->worker_allocs) {
|
||||
daemon->worker_allocs = (struct alloc_cache**)calloc(
|
||||
(size_t)daemon->num, sizeof(struct alloc_cache*));
|
||||
if(!daemon->worker_allocs)
|
||||
fatal_exit("could not allocate worker allocs");
|
||||
for(i=0; i<daemon->num; i++) {
|
||||
struct alloc_cache* alloc = calloc(1,
|
||||
sizeof(struct alloc_cache));
|
||||
if (!alloc)
|
||||
fatal_exit("could not allocate worker alloc");
|
||||
alloc_init(alloc, &daemon->superalloc, i);
|
||||
daemon->worker_allocs[i] = alloc;
|
||||
}
|
||||
}
|
||||
free(shufport);
|
||||
}
|
||||
|
||||
@@ -511,6 +904,25 @@ static void close_other_pipes(struct daemon* daemon, int thr)
|
||||
}
|
||||
#endif /* THREADS_DISABLED */
|
||||
|
||||
/**
|
||||
* Function to set the thread local log ID.
|
||||
* Either the internal thread number, or the LWP ID on Linux based on
|
||||
* configuration.
|
||||
*/
|
||||
static void
|
||||
set_log_thread_id(struct worker* worker, struct config_file* cfg)
|
||||
{
|
||||
(void)cfg;
|
||||
log_assert(worker);
|
||||
#if defined(HAVE_GETTID) && !defined(THREADS_DISABLED)
|
||||
worker->thread_tid = gettid();
|
||||
if(cfg->log_thread_id)
|
||||
log_thread_set(&worker->thread_tid);
|
||||
else
|
||||
#endif
|
||||
log_thread_set(&worker->thread_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to start one thread.
|
||||
* @param arg: user argument.
|
||||
@@ -521,7 +933,15 @@ thread_start(void* arg)
|
||||
{
|
||||
struct worker* worker = (struct worker*)arg;
|
||||
int port_num = 0;
|
||||
log_thread_set(&worker->thread_num);
|
||||
set_log_thread_id(worker, worker->daemon->cfg);
|
||||
{
|
||||
char name[16]; /* seems to be the safest size between
|
||||
different OSes */
|
||||
snprintf(name, sizeof(name), "unbound/%u", worker->thread_num);
|
||||
/* worker->thr_id can be written to after the thread was made
|
||||
* by the creating thread, so this uses pthread_self. */
|
||||
ub_thread_setname(ub_thread_self(), name);
|
||||
}
|
||||
ub_thread_blocksigs();
|
||||
#ifdef THREADS_DISABLED
|
||||
/* close pipe ends used by main */
|
||||
@@ -535,8 +955,9 @@ thread_start(void* arg)
|
||||
port_num = 0;
|
||||
#endif
|
||||
if(!worker_init(worker, worker->daemon->cfg,
|
||||
worker->daemon->ports[port_num], 0))
|
||||
worker->daemon->ports[port_num], 0)) {
|
||||
fatal_exit("Could not initialize thread");
|
||||
}
|
||||
|
||||
worker_work(worker);
|
||||
return NULL;
|
||||
@@ -596,14 +1017,18 @@ daemon_fork(struct daemon* daemon)
|
||||
#endif
|
||||
|
||||
log_assert(daemon);
|
||||
if(!(daemon->views = views_create()))
|
||||
daemon_reload_sslctxs(daemon);
|
||||
if(!(daemon->env->views = views_create()))
|
||||
fatal_exit("Could not create views: out of memory");
|
||||
/* create individual views and their localzone/data trees */
|
||||
if(!views_apply_cfg(daemon->views, daemon->cfg))
|
||||
if(!views_apply_cfg(daemon->env->views, daemon->cfg))
|
||||
fatal_exit("Could not set up views");
|
||||
|
||||
if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->views))
|
||||
if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->env->views))
|
||||
fatal_exit("Could not setup access control list");
|
||||
if(!acl_interface_apply_cfg(daemon->acl_interface, daemon->cfg,
|
||||
daemon->env->views))
|
||||
fatal_exit("Could not setup interface control list");
|
||||
if(!tcl_list_apply_cfg(daemon->tcl, daemon->cfg))
|
||||
fatal_exit("Could not setup TCP connection limits");
|
||||
if(daemon->cfg->dnscrypt) {
|
||||
@@ -617,22 +1042,36 @@ daemon_fork(struct daemon* daemon)
|
||||
"dnscrypt support");
|
||||
#endif
|
||||
}
|
||||
if(daemon->cfg->cookie_secret_file &&
|
||||
daemon->cfg->cookie_secret_file[0]) {
|
||||
if(!(daemon->cookie_secrets = cookie_secrets_create()))
|
||||
fatal_exit("Could not create cookie_secrets: out of memory");
|
||||
if(!cookie_secrets_apply_cfg(daemon->cookie_secrets,
|
||||
daemon->cfg->cookie_secret_file))
|
||||
fatal_exit("Could not setup cookie_secrets");
|
||||
}
|
||||
/* 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");
|
||||
if(!(daemon->env->fwds = forwards_create()) ||
|
||||
!forwards_apply_cfg(daemon->env->fwds, daemon->cfg))
|
||||
fatal_exit("Could not set forward zones");
|
||||
if(!(daemon->env->hints = hints_create()) ||
|
||||
!hints_apply_cfg(daemon->env->hints, daemon->cfg))
|
||||
fatal_exit("Could not set root or stub hints");
|
||||
|
||||
/* process raw response-ip configuration data */
|
||||
if(!(daemon->respip_set = respip_set_create()))
|
||||
if(!(daemon->env->respip_set = respip_set_create()))
|
||||
fatal_exit("Could not create response IP set");
|
||||
if(!respip_global_apply_cfg(daemon->respip_set, daemon->cfg))
|
||||
if(!respip_global_apply_cfg(daemon->env->respip_set, daemon->cfg))
|
||||
fatal_exit("Could not set up response IP set");
|
||||
if(!respip_views_apply_cfg(daemon->views, daemon->cfg,
|
||||
if(!respip_views_apply_cfg(daemon->env->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;
|
||||
daemon->use_response_ip = !respip_set_is_empty(
|
||||
daemon->env->respip_set) || have_view_respip_cfg;
|
||||
|
||||
/* setup modules */
|
||||
daemon_setup_modules(daemon);
|
||||
@@ -646,6 +1085,10 @@ daemon_fork(struct daemon* daemon)
|
||||
if(!edns_strings_apply_cfg(daemon->env->edns_strings, daemon->cfg))
|
||||
fatal_exit("Could not set up EDNS strings");
|
||||
|
||||
#ifdef USE_CACHEDB
|
||||
daemon->env->cachedb_enabled = cachedb_is_enabled(&daemon->mods,
|
||||
daemon->env);
|
||||
#endif
|
||||
/* response-ip-xxx options don't work as expected without the respip
|
||||
* module. To avoid run-time operational surprise we reject such
|
||||
* configuration. */
|
||||
@@ -660,14 +1103,25 @@ daemon_fork(struct daemon* daemon)
|
||||
fatal_exit("RPZ requires the respip module");
|
||||
|
||||
/* first create all the worker structures, so we can pass
|
||||
* them to the newly created threads.
|
||||
* them to the newly created threads.
|
||||
*/
|
||||
daemon_create_workers(daemon);
|
||||
/* Set it for the first (main) worker since it does not take part in
|
||||
* the thread_start() procedure.
|
||||
*/
|
||||
set_log_thread_id(daemon->workers[0], daemon->cfg);
|
||||
/* If shm stats need an offset, calculate it */
|
||||
if(daemon->cfg->shm_enable && daemon->cfg->stat_interval > 0) {
|
||||
daemon->stat_time_specific = 1;
|
||||
daemon->stat_time_offset =
|
||||
((int)time(NULL))%daemon->cfg->stat_interval;
|
||||
}
|
||||
|
||||
#if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
|
||||
/* in libev the first inited base gets signals */
|
||||
if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1))
|
||||
if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1)) {
|
||||
fatal_exit("Could not initialize main thread");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now create the threads and init the workers.
|
||||
@@ -680,8 +1134,9 @@ daemon_fork(struct daemon* daemon)
|
||||
*/
|
||||
#if !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP))
|
||||
/* libevent has the last inited base get signals (or any base) */
|
||||
if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1))
|
||||
if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1)) {
|
||||
fatal_exit("Could not initialize main thread");
|
||||
}
|
||||
#endif
|
||||
signal_handling_playback(daemon->workers[0]);
|
||||
|
||||
@@ -713,6 +1168,7 @@ daemon_fork(struct daemon* daemon)
|
||||
/* Shutdown SHM */
|
||||
shm_main_shutdown(daemon);
|
||||
|
||||
daemon->reuse_cache = daemon->workers[0]->reuse_cache;
|
||||
daemon->need_to_exit = daemon->workers[0]->need_to_exit;
|
||||
}
|
||||
|
||||
@@ -724,28 +1180,49 @@ daemon_cleanup(struct daemon* daemon)
|
||||
/* before stopping main worker, handle signals ourselves, so we
|
||||
don't die on multiple reload signals for example. */
|
||||
signal_handling_record();
|
||||
log_thread_set(NULL);
|
||||
/* clean up caches because
|
||||
* a) RRset IDs will be recycled after a reload, causing collisions
|
||||
* b) validation config can change, thus rrset, msg, keycache clear */
|
||||
slabhash_clear(&daemon->env->rrset_cache->table);
|
||||
slabhash_clear(daemon->env->msg_cache);
|
||||
* b) validation config can change, thus rrset, msg, keycache clear
|
||||
*
|
||||
* If we are trying to keep the cache as long as possible, we should
|
||||
* defer the cleanup until we know whether the new configuration allows
|
||||
* the reuse. (If we're exiting, cleanup should be done here). */
|
||||
if(!daemon->reuse_cache || daemon->need_to_exit) {
|
||||
slabhash_clear(&daemon->env->rrset_cache->table);
|
||||
slabhash_clear(daemon->env->msg_cache);
|
||||
}
|
||||
daemon->old_num = daemon->num; /* save the current num */
|
||||
forwards_delete(daemon->env->fwds);
|
||||
daemon->env->fwds = NULL;
|
||||
hints_delete(daemon->env->hints);
|
||||
daemon->env->hints = NULL;
|
||||
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;
|
||||
respip_set_delete(daemon->env->respip_set);
|
||||
daemon->env->respip_set = NULL;
|
||||
views_delete(daemon->env->views);
|
||||
daemon->env->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() */
|
||||
/* key cache is cleared by module deinit during next daemon_fork() */
|
||||
daemon_remote_clear(daemon->rc);
|
||||
if(daemon->fast_reload_thread)
|
||||
fast_reload_thread_stop(daemon->fast_reload_thread);
|
||||
if(daemon->fast_reload_printq_list)
|
||||
fast_reload_printq_list_delete(daemon->fast_reload_printq_list);
|
||||
for(i=0; i<daemon->num; i++)
|
||||
worker_delete(daemon->workers[i]);
|
||||
free(daemon->workers);
|
||||
daemon->workers = NULL;
|
||||
/* Unless we're trying to keep the cache, worker alloc_caches should be
|
||||
* cleared and freed here. We do this after deleting workers to
|
||||
* guarantee that the alloc caches are valid throughout the lifetime
|
||||
* of workers. */
|
||||
if(!daemon->reuse_cache || daemon->need_to_exit)
|
||||
daemon_clear_allocs(daemon);
|
||||
daemon->num = 0;
|
||||
alloc_clear_special(&daemon->superalloc);
|
||||
shared_ports_delete(daemon->shared_ports);
|
||||
daemon->shared_ports = NULL;
|
||||
#ifdef USE_DNSTAP
|
||||
dt_delete(daemon->dtenv);
|
||||
daemon->dtenv = NULL;
|
||||
@@ -753,6 +1230,12 @@ daemon_cleanup(struct daemon* daemon)
|
||||
#ifdef USE_DNSCRYPT
|
||||
dnsc_delete(daemon->dnscenv);
|
||||
daemon->dnscenv = NULL;
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
if (daemon->doq_table) {
|
||||
doq_table_delete(daemon->doq_table);
|
||||
daemon->doq_table = NULL;
|
||||
}
|
||||
#endif
|
||||
daemon->cfg = NULL;
|
||||
}
|
||||
@@ -763,7 +1246,9 @@ daemon_delete(struct daemon* daemon)
|
||||
size_t i;
|
||||
if(!daemon)
|
||||
return;
|
||||
modstack_desetup(&daemon->mods, daemon->env);
|
||||
modstack_call_deinit(&daemon->mods, daemon->env);
|
||||
modstack_call_destartup(&daemon->mods, daemon->env);
|
||||
modstack_free(&daemon->mods);
|
||||
daemon_remote_delete(daemon->rc);
|
||||
for(i = 0; i < daemon->num_ports; i++)
|
||||
listening_ports_free(daemon->ports[i]);
|
||||
@@ -780,27 +1265,27 @@ daemon_delete(struct daemon* daemon)
|
||||
ub_randfree(daemon->rand);
|
||||
alloc_clear(&daemon->superalloc);
|
||||
acl_list_delete(daemon->acl);
|
||||
acl_list_delete(daemon->acl_interface);
|
||||
tcl_list_delete(daemon->tcl);
|
||||
cookie_secrets_delete(daemon->cookie_secrets);
|
||||
listen_desetup_locks();
|
||||
free(daemon->chroot);
|
||||
free(daemon->pidfile);
|
||||
free(daemon->cfgfile);
|
||||
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
|
||||
daemon_delete_sslctxs(daemon);
|
||||
free(daemon);
|
||||
/* lex cleanup */
|
||||
ub_c_lex_destroy();
|
||||
/* libcrypto cleanup */
|
||||
#ifdef HAVE_SSL
|
||||
# if defined(USE_GOST) && defined(HAVE_LDNS_KEY_EVP_UNLOAD_GOST)
|
||||
# if defined(USE_GOST)
|
||||
sldns_key_EVP_unload_gost();
|
||||
# endif
|
||||
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS && HAVE_DECL_SK_SSL_COMP_POP_FREE
|
||||
# ifndef S_SPLINT_S
|
||||
# if OPENSSL_VERSION_NUMBER < 0x10100000
|
||||
sk_SSL_COMP_pop_free(comp_meth, (void(*)())CRYPTO_free);
|
||||
sk_SSL_COMP_pop_free(comp_meth, (void(*)(SSL_COMP*))CRYPTO_free);
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
@@ -823,6 +1308,9 @@ daemon_delete(struct daemon* daemon)
|
||||
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
|
||||
ub_openssl_lock_delete();
|
||||
# endif
|
||||
#ifdef HAVE_OPENSSL_CLEANUP
|
||||
OPENSSL_cleanup();
|
||||
#endif
|
||||
#ifndef HAVE_ARC4RANDOM
|
||||
_ARC4_LOCK_DESTROY();
|
||||
#endif
|
||||
@@ -840,8 +1328,42 @@ daemon_delete(struct daemon* daemon)
|
||||
|
||||
void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg)
|
||||
{
|
||||
int new_num = cfg->num_threads?cfg->num_threads:1;
|
||||
|
||||
daemon->cfg = cfg;
|
||||
config_apply(cfg);
|
||||
|
||||
/* If this is a reload and we deferred the decision on whether to
|
||||
* reuse the alloc, RRset, and message caches, then check to see if
|
||||
* it's safe to keep the caches:
|
||||
* - changing the number of threads is obviously incompatible with
|
||||
* keeping the per-thread alloc caches. It also means we have to
|
||||
* clear RRset and message caches. (note that 'new_num' may be
|
||||
* adjusted in daemon_create_workers, but for our purpose we can
|
||||
* simply compare it with 'old_num'; if they are equal here,
|
||||
* 'new_num' won't be adjusted to a different value than 'old_num').
|
||||
* - changing RRset cache size effectively clears any remaining cache
|
||||
* entries. We could keep their keys in alloc caches, but it would
|
||||
* be more consistent with the sense of the change to clear allocs
|
||||
* and free memory. To do so we also have to clear message cache.
|
||||
* - only changing message cache size does not necessarily affect
|
||||
* RRset or alloc cache. But almost all new subsequent queries will
|
||||
* require recursive resolution anyway, so it doesn't help much to
|
||||
* just keep RRset and alloc caches. For simplicity we clear/free
|
||||
* the other two, too. */
|
||||
if(daemon->worker_allocs &&
|
||||
(new_num != daemon->old_num ||
|
||||
!slabhash_is_size(daemon->env->msg_cache, cfg->msg_cache_size,
|
||||
cfg->msg_cache_slabs) ||
|
||||
!slabhash_is_size(&daemon->env->rrset_cache->table,
|
||||
cfg->rrset_cache_size, cfg->rrset_cache_slabs)))
|
||||
{
|
||||
log_warn("cannot reuse caches due to critical config change");
|
||||
slabhash_clear(&daemon->env->rrset_cache->table);
|
||||
slabhash_clear(daemon->env->msg_cache);
|
||||
daemon_clear_allocs(daemon);
|
||||
}
|
||||
|
||||
if(!slabhash_is_size(daemon->env->msg_cache, cfg->msg_cache_size,
|
||||
cfg->msg_cache_slabs)) {
|
||||
slabhash_delete(daemon->env->msg_cache);
|
||||
|
||||
+98
-6
@@ -58,6 +58,11 @@ struct ub_randstate;
|
||||
struct daemon_remote;
|
||||
struct respip_set;
|
||||
struct shm_main_info;
|
||||
struct doq_table;
|
||||
struct cookie_secrets;
|
||||
struct fast_reload_thread;
|
||||
struct fast_reload_printq;
|
||||
struct shared_ports;
|
||||
|
||||
#include "dnstap/dnstap_config.h"
|
||||
#ifdef USE_DNSTAP
|
||||
@@ -93,14 +98,38 @@ struct daemon {
|
||||
int rc_port;
|
||||
/** listening ports for remote control */
|
||||
struct listen_port* rc_ports;
|
||||
/** the shared ports structure, with random ports numbers. */
|
||||
struct shared_ports* shared_ports;
|
||||
/** remote control connections management (for first worker) */
|
||||
struct daemon_remote* rc;
|
||||
/** ssl context for listening to dnstcp over ssl, and connecting ssl */
|
||||
void* listen_sslctx, *connect_sslctx;
|
||||
/** ssl context for listening to dnstcp over ssl */
|
||||
void* listen_dot_sslctx;
|
||||
/** ssl context for connecting to dnstcp over ssl */
|
||||
void* connect_dot_sslctx;
|
||||
/** ssl context for listening to DoH */
|
||||
void* listen_doh_sslctx;
|
||||
/** ssl context for listening to quic */
|
||||
void* listen_quic_sslctx;
|
||||
/** the file name that the ssl context is made with, private key. */
|
||||
char* ssl_service_key;
|
||||
/** the file name that the ssl context is made with, certificate. */
|
||||
char* ssl_service_pem;
|
||||
/** modification time for ssl_service_key, in sec and ns. Like
|
||||
* in a struct timespec, but without that for portability. */
|
||||
time_t mtime_ssl_service_key;
|
||||
long mtime_ns_ssl_service_key;
|
||||
/** modification time for ssl_service_pem, in sec and ns. Like
|
||||
* in a struct timespec, but without that for portability. */
|
||||
time_t mtime_ssl_service_pem;
|
||||
long mtime_ns_ssl_service_pem;
|
||||
/** num threads allocated */
|
||||
int num;
|
||||
/** num threads allocated in the previous config or 0 at first */
|
||||
int old_num;
|
||||
/** the worker entries */
|
||||
struct worker** workers;
|
||||
/** per-worker allocation cache */
|
||||
struct alloc_cache **worker_allocs;
|
||||
/** do we need to exit unbound (or is it only a reload?) */
|
||||
int need_to_exit;
|
||||
/** master random table ; used for port div between threads on reload*/
|
||||
@@ -111,8 +140,12 @@ struct daemon {
|
||||
struct module_env* env;
|
||||
/** stack of module callbacks */
|
||||
struct module_stack mods;
|
||||
/** The module stack has been inited */
|
||||
int mods_inited;
|
||||
/** access control, which client IPs are allowed to connect */
|
||||
struct acl_list* acl;
|
||||
/** access control, which interfaces are allowed to connect */
|
||||
struct acl_list* acl_interface;
|
||||
/** TCP connection limit, limit connections from client IPs */
|
||||
struct tcl_list* tcl;
|
||||
/** local authority zones */
|
||||
@@ -121,15 +154,18 @@ struct daemon {
|
||||
struct timeval time_last_stat;
|
||||
/** time when daemon started */
|
||||
struct timeval time_boot;
|
||||
/** views structure containing view tree */
|
||||
struct views* views;
|
||||
#ifdef USE_DNSTAP
|
||||
/** the dnstap environment master value, copied and changed by threads*/
|
||||
struct dt_env* dtenv;
|
||||
#endif
|
||||
/** The SHM info for shared memory stats. */
|
||||
struct shm_main_info* shm_info;
|
||||
/** response-ip set with associated actions and tags. */
|
||||
struct respip_set* respip_set;
|
||||
/** if the timeout for statistics is attempted at specific offset.
|
||||
* If it is true, the stat timeout is the interval+offset, and that
|
||||
* picks (roughly) the same time offset every time period. */
|
||||
int stat_time_specific;
|
||||
/** if the timeout is specific, what offset in the period. */
|
||||
int stat_time_offset;
|
||||
/** some response-ip tags or actions are configured if true */
|
||||
int use_response_ip;
|
||||
/** some RPZ policies are configured */
|
||||
@@ -138,6 +174,23 @@ struct daemon {
|
||||
/** the dnscrypt environment */
|
||||
struct dnsc_env* dnscenv;
|
||||
#endif
|
||||
/** the doq connection table */
|
||||
struct doq_table* doq_table;
|
||||
/** reuse existing cache on reload if other conditions allow it. */
|
||||
int reuse_cache;
|
||||
/** the EDNS cookie secrets from the cookie-secret-file */
|
||||
struct cookie_secrets* cookie_secrets;
|
||||
/** the fast reload thread, or NULL */
|
||||
struct fast_reload_thread* fast_reload_thread;
|
||||
/** the fast reload printq list */
|
||||
struct fast_reload_printq* fast_reload_printq_list;
|
||||
/** the fast reload option to drop mesh queries, true if so. */
|
||||
int fast_reload_drop_mesh;
|
||||
/** for fast reload, if the tcl, tcp connection limits, has
|
||||
* changes for workers */
|
||||
int fast_reload_tcl_has_changes;
|
||||
/** config file name */
|
||||
char* cfgfile;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -154,6 +207,15 @@ struct daemon* daemon_init(void);
|
||||
*/
|
||||
int daemon_open_shared_ports(struct daemon* daemon);
|
||||
|
||||
/**
|
||||
* Do daemon setup that needs privileges
|
||||
* like opening privileged ports or opening device files.
|
||||
* The cfg member pointer must have been set for the daemon.
|
||||
* @param daemon: the daemon.
|
||||
* @return: false on error.
|
||||
*/
|
||||
int daemon_privileged(struct daemon* daemon);
|
||||
|
||||
/**
|
||||
* Fork workers and start service.
|
||||
* When the routine exits, it is no longer forked.
|
||||
@@ -181,4 +243,34 @@ void daemon_delete(struct daemon* daemon);
|
||||
*/
|
||||
void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Setup acl list to have entries for the port list.
|
||||
* @param list: the acl interface
|
||||
* @param port_list: list of open ports, or none.
|
||||
* @return false on failure
|
||||
*/
|
||||
int setup_acl_for_ports(struct acl_list* list, struct listen_port* port_list);
|
||||
|
||||
/* setups the needed ssl contexts, fatal_exit() on any failure */
|
||||
void daemon_setup_sslctxs(struct daemon* daemon, struct config_file* cfg);
|
||||
|
||||
/** See if the SSL cert files have changed */
|
||||
int ssl_cert_changed(struct daemon* daemon, struct config_file* cfg);
|
||||
|
||||
/** Setup the listening DoT SSL_CTX, returns the ssl ctx. */
|
||||
void* daemon_setup_listen_dot_sslctx(struct daemon* daemon,
|
||||
struct config_file* cfg);
|
||||
|
||||
/** Setup the listening DoH SSL_CTX, returns the ssl ctx. */
|
||||
void* daemon_setup_listen_doh_sslctx(struct daemon* daemon,
|
||||
struct config_file* cfg);
|
||||
|
||||
/** Setup the listening Quic SSL_CTX, returns the ssl ctx */
|
||||
void* daemon_setup_listen_quic_sslctx(struct daemon* daemon,
|
||||
struct config_file* cfg);
|
||||
|
||||
/** Setup the connect DoT SSL_CTX, returns the ssl ctx */
|
||||
void* daemon_setup_connect_dot_sslctx(struct daemon* daemon,
|
||||
struct config_file* cfg);
|
||||
|
||||
#endif /* DAEMON_H */
|
||||
|
||||
+5784
-348
File diff suppressed because it is too large
Load Diff
+170
-1
@@ -46,8 +46,10 @@
|
||||
#ifndef DAEMON_REMOTE_H
|
||||
#define DAEMON_REMOTE_H
|
||||
#ifdef HAVE_OPENSSL_SSL_H
|
||||
#include "openssl/ssl.h"
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
#include "util/locks.h"
|
||||
#include "libunbound/remote.h"
|
||||
struct config_file;
|
||||
struct listen_list;
|
||||
struct listen_port;
|
||||
@@ -55,6 +57,7 @@ struct worker;
|
||||
struct comm_reply;
|
||||
struct comm_point;
|
||||
struct daemon_remote;
|
||||
struct config_strlist_head;
|
||||
|
||||
/** number of milliseconds timeout on incoming remote control handshake */
|
||||
#define REMOTE_CONTROL_TCP_TIMEOUT 120000
|
||||
@@ -118,6 +121,145 @@ struct remote_stream {
|
||||
};
|
||||
typedef struct remote_stream RES;
|
||||
|
||||
/**
|
||||
* Notification status. This is exchanged between the fast reload thread
|
||||
* and the server thread, over the commpair sockets.
|
||||
*/
|
||||
enum fast_reload_notification {
|
||||
/** nothing, not used */
|
||||
fast_reload_notification_none = 0,
|
||||
/** the fast reload thread is done */
|
||||
fast_reload_notification_done = 1,
|
||||
/** the fast reload thread is done but with an error, it failed */
|
||||
fast_reload_notification_done_error = 2,
|
||||
/** the fast reload thread is told to exit by the server thread.
|
||||
* Sent on server quit while the reload is running. */
|
||||
fast_reload_notification_exit = 3,
|
||||
/** the fast reload thread has exited, after being told to exit */
|
||||
fast_reload_notification_exited = 4,
|
||||
/** the fast reload thread has information to print out */
|
||||
fast_reload_notification_printout = 5,
|
||||
/** stop as part of the reload the thread and other threads */
|
||||
fast_reload_notification_reload_stop = 6,
|
||||
/** ack the stop as part of the reload, and also ack start */
|
||||
fast_reload_notification_reload_ack = 7,
|
||||
/** resume from stop as part of the reload */
|
||||
fast_reload_notification_reload_start = 8,
|
||||
/** the fast reload thread wants the mainthread to poll workers,
|
||||
* after the reload, sent when nopause is used */
|
||||
fast_reload_notification_reload_nopause_poll = 9
|
||||
};
|
||||
|
||||
/**
|
||||
* Fast reload printout queue. Contains a list of strings, that need to be
|
||||
* printed over the file descriptor.
|
||||
*/
|
||||
struct fast_reload_printq {
|
||||
/** if this item is in a list, the previous and next */
|
||||
struct fast_reload_printq *prev, *next;
|
||||
/** if this item is in a list, it is true. */
|
||||
int in_list;
|
||||
/** list of strings to printout */
|
||||
struct config_strlist_head* to_print;
|
||||
/** the current item to print. It is malloced. NULL if none. */
|
||||
char* client_item;
|
||||
/** The length, strlen, of the client_item, that has to be sent. */
|
||||
int client_len;
|
||||
/** The number of bytes sent of client_item. */
|
||||
int client_byte_count;
|
||||
/** the comm point for the client connection, the remote control
|
||||
* client. */
|
||||
struct comm_point* client_cp;
|
||||
/** the remote control connection to print output to. */
|
||||
struct remote_stream remote;
|
||||
/** the worker that the event is added in */
|
||||
struct worker* worker;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fast reload auth zone change. Keeps track if an auth zone was removed,
|
||||
* added or changed. This is needed because workers can have events for
|
||||
* dealing with auth zones, like transfers, and those have to be removed
|
||||
* too, not just the auth zone structure from the tree. */
|
||||
struct fast_reload_auth_change {
|
||||
/** next in the list of auth zone changes. */
|
||||
struct fast_reload_auth_change* next;
|
||||
/** the zone in the old config */
|
||||
struct auth_zone* old_z;
|
||||
/** the zone in the new config */
|
||||
struct auth_zone* new_z;
|
||||
/** if the zone was deleted */
|
||||
int is_deleted;
|
||||
/** if the zone was added */
|
||||
int is_added;
|
||||
/** if the zone has been changed */
|
||||
int is_changed;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fast reload thread structure
|
||||
*/
|
||||
struct fast_reload_thread {
|
||||
/** the thread number for the dtio thread,
|
||||
* must be first to cast thread arg to int* in checklock code. */
|
||||
int threadnum;
|
||||
/** communication socket pair, that sends commands */
|
||||
int commpair[2];
|
||||
/** thread id, of the io thread */
|
||||
ub_thread_type tid;
|
||||
#ifdef HAVE_GETTID
|
||||
/** thread tid, the LWP id */
|
||||
pid_t thread_tid;
|
||||
/** if logging should include the LWP id */
|
||||
int thread_tid_log;
|
||||
#endif
|
||||
/** if the io processing has started */
|
||||
int started;
|
||||
/** if the thread has to quit */
|
||||
int need_to_quit;
|
||||
/** verbosity of the fast_reload command, the number of +v options */
|
||||
int fr_verb;
|
||||
/** option to not pause threads during reload */
|
||||
int fr_nopause;
|
||||
/** option to drop mesh queries */
|
||||
int fr_drop_mesh;
|
||||
|
||||
/** the event that listens on the remote service worker to the
|
||||
* commpair, it receives content from the fast reload thread. */
|
||||
void* service_event;
|
||||
/** if the event that listens on the remote service worker has
|
||||
* been added to the comm base. */
|
||||
int service_event_is_added;
|
||||
/** the service event can read a cmd, nonblocking, so it can
|
||||
* save the partial read cmd here */
|
||||
uint32_t service_read_cmd;
|
||||
/** the number of bytes in service_read_cmd */
|
||||
int service_read_cmd_count;
|
||||
/** the worker that the service_event is added in */
|
||||
struct worker* worker;
|
||||
|
||||
/** the printout of output to the remote client. */
|
||||
struct fast_reload_printq *printq;
|
||||
|
||||
/** lock on fr_output, to stop race when both remote control thread
|
||||
* and fast reload thread use fr_output list. */
|
||||
lock_basic_type fr_output_lock;
|
||||
/** list of strings, that the fast reload thread produces that have
|
||||
* to be printed. The remote control thread can pick them up with
|
||||
* the lock. */
|
||||
struct config_strlist_head* fr_output;
|
||||
|
||||
/** communication socket pair, to respond to the reload request */
|
||||
int commreload[2];
|
||||
|
||||
/** the list of auth zone changes. */
|
||||
struct fast_reload_auth_change* auth_zone_change_list;
|
||||
/** the old tree of auth zones, to lookup. */
|
||||
struct auth_zones* old_auth_zones;
|
||||
/** If the ssl ctxs have changed. */
|
||||
int sslctxs_changed;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create new remote control state for the daemon.
|
||||
* @param cfg: config file with key file settings.
|
||||
@@ -203,4 +345,31 @@ int ssl_printf(RES* ssl, const char* format, ...)
|
||||
int ssl_read_line(RES* ssl, char* buf, size_t max);
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
/**
|
||||
* Start fast reload thread
|
||||
* @param ssl: the RES connection to print to.
|
||||
* @param worker: the remote servicing worker.
|
||||
* @param s: the rc_state that is servicing the remote control connection to
|
||||
* the remote control client. It needs to be moved away to stay connected
|
||||
* while the fast reload is running.
|
||||
* @param fr_verb: verbosity to print output at. 0 is nothing, 1 is some
|
||||
* and 2 is more detail.
|
||||
* @param fr_nopause: option to not pause threads during reload.
|
||||
* @param fr_drop_mesh: option to drop mesh queries.
|
||||
*/
|
||||
void fast_reload_thread_start(RES* ssl, struct worker* worker,
|
||||
struct rc_state* s, int fr_verb, int fr_nopause, int fr_drop_mesh);
|
||||
|
||||
/**
|
||||
* Stop fast reload thread
|
||||
* @param fast_reload_thread: the thread struct.
|
||||
*/
|
||||
void fast_reload_thread_stop(struct fast_reload_thread* fast_reload_thread);
|
||||
|
||||
/** fast reload printq delete list */
|
||||
void fast_reload_printq_list_delete(struct fast_reload_printq* list);
|
||||
|
||||
/** Pick up per worker changes after a fast reload. */
|
||||
void fast_reload_worker_pickup_changes(struct worker* worker);
|
||||
|
||||
#endif /* DAEMON_REMOTE_H */
|
||||
|
||||
+136
-37
@@ -4,22 +4,22 @@
|
||||
* Copyright (c) 2007, 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
|
||||
@@ -70,6 +70,9 @@
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
|
||||
/** How long to wait for threads to transmit statistics, in msec. */
|
||||
#define STATS_THREAD_WAIT 60000
|
||||
|
||||
/** add timers and the values do not overflow or become negative */
|
||||
static void
|
||||
stats_timeval_add(long long* d_sec, long long* d_usec, long long add_sec, long long add_usec)
|
||||
@@ -113,8 +116,8 @@ void server_stats_log(struct ub_server_stats* stats, struct worker* worker,
|
||||
log_info("server stats for thread %d: %u queries, "
|
||||
"%u answers from cache, %u recursions, %u prefetch, %u rejected by "
|
||||
"ip ratelimiting",
|
||||
threadnum, (unsigned)stats->num_queries,
|
||||
(unsigned)(stats->num_queries -
|
||||
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,
|
||||
@@ -137,7 +140,7 @@ static void
|
||||
set_subnet_stats(struct worker* worker, struct ub_server_stats* svr,
|
||||
int reset)
|
||||
{
|
||||
int m = modstack_find(&worker->env.mesh->mods, "subnet");
|
||||
int m = modstack_find(&worker->env.mesh->mods, "subnetcache");
|
||||
struct subnet_env* sne;
|
||||
if(m == -1)
|
||||
return;
|
||||
@@ -259,6 +262,7 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
s->svr = worker->stats;
|
||||
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_num_reply_addrs = (long long)worker->env.mesh->num_reply_addrs;
|
||||
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;
|
||||
@@ -270,17 +274,27 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
/* add in the values from the mesh */
|
||||
s->svr.ans_secure += (long long)worker->env.mesh->ans_secure;
|
||||
s->svr.ans_bogus += (long long)worker->env.mesh->ans_bogus;
|
||||
s->svr.val_ops += (long long)worker->env.mesh->val_ops;
|
||||
s->svr.ans_rcode_nodata += (long long)worker->env.mesh->ans_nodata;
|
||||
s->svr.ans_expired += (long long)worker->env.mesh->ans_expired;
|
||||
for(i=0; i<UB_STATS_RCODE_NUM; i++)
|
||||
s->svr.ans_rcode[i] += (long long)worker->env.mesh->ans_rcode[i];
|
||||
for(i=0; i<UB_STATS_RPZ_ACTION_NUM; i++)
|
||||
s->svr.rpz_action[i] += (long long)worker->env.mesh->rpz_action[i];
|
||||
timehist_export(worker->env.mesh->histogram, s->svr.hist,
|
||||
timehist_export(worker->env.mesh->histogram, s->svr.hist,
|
||||
NUM_BUCKETS_HIST);
|
||||
s->svr.num_queries_discard_timeout +=
|
||||
(long long)worker->env.mesh->num_queries_discard_timeout;
|
||||
s->svr.num_queries_replyaddr_limit +=
|
||||
(long long)worker->env.mesh->num_queries_replyaddr_limit;
|
||||
s->svr.num_queries_wait_limit +=
|
||||
(long long)worker->env.mesh->num_queries_wait_limit;
|
||||
s->svr.num_dns_error_reports +=
|
||||
(long long)worker->env.mesh->num_dns_error_reports;
|
||||
/* values from outside network */
|
||||
s->svr.unwanted_replies = (long long)worker->back->unwanted_replies;
|
||||
s->svr.qtcp_outgoing = (long long)worker->back->num_tcp_outgoing;
|
||||
s->svr.qudp_outgoing = (long long)worker->back->num_udp_outgoing;
|
||||
|
||||
/* get and reset validator rrset bogus number */
|
||||
s->svr.rrset_bogus = (long long)get_rrset_bogus(worker, reset);
|
||||
@@ -289,8 +303,10 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
s->svr.queries_ratelimited = (long long)get_queries_ratelimit(worker, reset);
|
||||
|
||||
/* get cache sizes */
|
||||
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);
|
||||
get_slabhash_stats(worker->env.msg_cache,
|
||||
&s->svr.msg_cache_count, &s->svr.msg_cache_max_collisions);
|
||||
get_slabhash_stats(&worker->env.rrset_cache->table,
|
||||
&s->svr.rrset_cache_count, &s->svr.rrset_cache_max_collisions);
|
||||
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 = (long long)count_slabhash_entries(worker->env.key_cache->slab);
|
||||
@@ -319,20 +335,8 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
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.num_query_authzone_up += (long long)worker->env.mesh->num_query_authzone_up;
|
||||
s->svr.num_query_authzone_down += (long long)worker->env.mesh->num_query_authzone_down;
|
||||
}
|
||||
s->svr.mem_stream_wait =
|
||||
(long long)tcp_req_info_get_stream_buffer_size();
|
||||
@@ -340,6 +344,12 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
(long long)http2_get_query_buffer_size();
|
||||
s->svr.mem_http2_response_buffer =
|
||||
(long long)http2_get_response_buffer_size();
|
||||
#ifdef HAVE_NGTCP2
|
||||
s->svr.mem_quic = (long long)doq_table_quic_size_get(
|
||||
worker->daemon->doq_table);
|
||||
#else
|
||||
s->svr.mem_quic = 0;
|
||||
#endif /* HAVE_NGTCP2 */
|
||||
|
||||
/* Set neg cache usage numbers */
|
||||
set_neg_cache_stats(worker, &s->svr, reset);
|
||||
@@ -350,6 +360,11 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
s->svr.num_query_subnet = 0;
|
||||
s->svr.num_query_subnet_cache = 0;
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
s->svr.num_query_cachedb = (long long)worker->env.mesh->ans_cachedb;
|
||||
#else
|
||||
s->svr.num_query_cachedb = 0;
|
||||
#endif
|
||||
|
||||
/* get tcp accept usage */
|
||||
s->svr.tcp_accept_usage = 0;
|
||||
@@ -379,11 +394,56 @@ void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
worker_send_cmd(who, worker_cmd_stats);
|
||||
else worker_send_cmd(who, worker_cmd_stats_noreset);
|
||||
verbose(VERB_ALGO, "wait for stats reply");
|
||||
if(!tube_read_msg(worker->cmd, &reply, &len, 0))
|
||||
fatal_exit("failed to read stats over cmd channel");
|
||||
if(len != (uint32_t)sizeof(*s))
|
||||
fatal_exit("stats on cmd channel wrong length %d %d",
|
||||
(int)len, (int)sizeof(*s));
|
||||
if(tube_wait_timeout(worker->cmd, STATS_THREAD_WAIT) == 0) {
|
||||
#if defined(HAVE_PTHREAD) && defined(SIZEOF_PTHREAD_T) && defined(SIZEOF_UNSIGNED_LONG)
|
||||
# if SIZEOF_PTHREAD_T == SIZEOF_UNSIGNED_LONG
|
||||
unsigned long pthid = 0;
|
||||
if(verbosity >= VERB_OPS)
|
||||
memcpy(&pthid, &who->thr_id, sizeof(unsigned long));
|
||||
# endif
|
||||
#endif
|
||||
verbose(VERB_OPS, "no response from thread %d"
|
||||
#ifdef HAVE_GETTID
|
||||
" LWP %u"
|
||||
#endif
|
||||
#if defined(HAVE_PTHREAD) && defined(SIZEOF_PTHREAD_T) && defined(SIZEOF_UNSIGNED_LONG)
|
||||
# if SIZEOF_PTHREAD_T == SIZEOF_UNSIGNED_LONG
|
||||
" pthread 0x%lx"
|
||||
# endif
|
||||
#endif
|
||||
,
|
||||
who->thread_num
|
||||
#ifdef HAVE_GETTID
|
||||
, (unsigned)who->thread_tid
|
||||
#endif
|
||||
#if defined(HAVE_PTHREAD) && defined(SIZEOF_PTHREAD_T) && defined(SIZEOF_UNSIGNED_LONG)
|
||||
# if SIZEOF_PTHREAD_T == SIZEOF_UNSIGNED_LONG
|
||||
, pthid
|
||||
# endif
|
||||
#endif
|
||||
);
|
||||
log_err("server_stats_obtain: no response from worker %d "
|
||||
"(stats timeout); returning zero stats for this worker",
|
||||
who->thread_num);
|
||||
/* A later reply from the worker, would be sizeof stats reply,
|
||||
* and the worker_handle_control_cmd routine discards if
|
||||
* it is not a 4byte command, when that is received here. */
|
||||
memset(s, 0, sizeof(*s));
|
||||
return;
|
||||
}
|
||||
if(!tube_read_msg(worker->cmd, &reply, &len, 0)) {
|
||||
log_err("server_stats_obtain: failed to read stats from worker "
|
||||
"(tube read error); returning zero stats for this worker");
|
||||
memset(s, 0, sizeof(*s));
|
||||
return;
|
||||
}
|
||||
if(len != (uint32_t)sizeof(*s)) {
|
||||
log_err("server_stats_obtain: wrong stats length %d (expected %d); "
|
||||
"discarding", (int)len, (int)sizeof(*s));
|
||||
free(reply);
|
||||
memset(s, 0, sizeof(*s));
|
||||
return;
|
||||
}
|
||||
memcpy(s, reply, (size_t)len);
|
||||
free(reply);
|
||||
}
|
||||
@@ -393,25 +453,39 @@ void server_stats_reply(struct worker* worker, int reset)
|
||||
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,
|
||||
if(!tube_write_msg(worker->daemon->workers[0]->cmd,
|
||||
(uint8_t*)&s, sizeof(s), 0))
|
||||
fatal_exit("could not write stat values over cmd channel");
|
||||
log_err("could not write stat values over cmd channel");
|
||||
}
|
||||
|
||||
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_cookie_valid += a->svr.num_queries_cookie_valid;
|
||||
total->svr.num_queries_cookie_client += a->svr.num_queries_cookie_client;
|
||||
total->svr.num_queries_cookie_invalid += a->svr.num_queries_cookie_invalid;
|
||||
total->svr.num_queries_discard_timeout +=
|
||||
a->svr.num_queries_discard_timeout;
|
||||
total->svr.num_queries_replyaddr_limit +=
|
||||
a->svr.num_queries_replyaddr_limit;
|
||||
total->svr.num_queries_wait_limit += a->svr.num_queries_wait_limit;
|
||||
total->svr.num_dns_error_reports += a->svr.num_dns_error_reports;
|
||||
total->svr.num_queries_missed_cache += a->svr.num_queries_missed_cache;
|
||||
total->svr.num_queries_prefetch += a->svr.num_queries_prefetch;
|
||||
total->svr.num_queries_timed_out += a->svr.num_queries_timed_out;
|
||||
total->svr.num_query_authzone_up += a->svr.num_query_authzone_up;
|
||||
total->svr.num_query_authzone_down += a->svr.num_query_authzone_down;
|
||||
if (total->svr.max_query_time_us < a->svr.max_query_time_us)
|
||||
total->svr.max_query_time_us = a->svr.max_query_time_us;
|
||||
total->svr.sum_query_list_size += a->svr.sum_query_list_size;
|
||||
total->svr.ans_expired += a->svr.ans_expired;
|
||||
#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 += \
|
||||
total->svr.num_query_dnscrypt_cleartext +=
|
||||
a->svr.num_query_dnscrypt_cleartext;
|
||||
total->svr.num_query_dnscrypt_crypted_malformed += \
|
||||
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 */
|
||||
@@ -424,9 +498,11 @@ void server_stats_add(struct ub_stats_info* total, struct ub_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.qudp_outgoing += a->svr.qudp_outgoing;
|
||||
total->svr.qtls += a->svr.qtls;
|
||||
total->svr.qtls_resume += a->svr.qtls_resume;
|
||||
total->svr.qhttps += a->svr.qhttps;
|
||||
total->svr.qquic += a->svr.qquic;
|
||||
total->svr.qipv6 += a->svr.qipv6;
|
||||
total->svr.qbit_QR += a->svr.qbit_QR;
|
||||
total->svr.qbit_AA += a->svr.qbit_AA;
|
||||
@@ -441,9 +517,13 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
||||
total->svr.ans_rcode_nodata += a->svr.ans_rcode_nodata;
|
||||
total->svr.ans_secure += a->svr.ans_secure;
|
||||
total->svr.ans_bogus += a->svr.ans_bogus;
|
||||
total->svr.val_ops += a->svr.val_ops;
|
||||
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;
|
||||
#ifdef USE_CACHEDB
|
||||
total->svr.num_query_cachedb += a->svr.num_query_cachedb;
|
||||
#endif
|
||||
for(i=0; i<UB_STATS_QTYPE_NUM; i++)
|
||||
total->svr.qtype[i] += a->svr.qtype[i];
|
||||
for(i=0; i<UB_STATS_QCLASS_NUM; i++)
|
||||
@@ -460,6 +540,7 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
||||
|
||||
total->mesh_num_states += a->mesh_num_states;
|
||||
total->mesh_num_reply_states += a->mesh_num_reply_states;
|
||||
total->mesh_num_reply_addrs += a->mesh_num_reply_addrs;
|
||||
total->mesh_jostled += a->mesh_jostled;
|
||||
total->mesh_dropped += a->mesh_dropped;
|
||||
total->mesh_replies_sent += a->mesh_replies_sent;
|
||||
@@ -483,18 +564,23 @@ void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
|
||||
else stats->qclass_big++;
|
||||
stats->qopcode[ LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) ]++;
|
||||
if(c->type != comm_udp) {
|
||||
stats->qtcp++;
|
||||
if(c->type != comm_doq)
|
||||
stats->qtcp++;
|
||||
if(c->ssl != NULL) {
|
||||
stats->qtls++;
|
||||
#ifdef HAVE_SSL
|
||||
if(SSL_session_reused(c->ssl))
|
||||
if(SSL_session_reused(c->ssl))
|
||||
stats->qtls_resume++;
|
||||
#endif
|
||||
if(c->type == comm_http)
|
||||
stats->qhttps++;
|
||||
#ifdef HAVE_NGTCP2
|
||||
else if(c->type == comm_doq)
|
||||
stats->qquic++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if(repinfo && addr_is_ip6(&repinfo->addr, repinfo->addrlen))
|
||||
if(repinfo && addr_is_ip6(&repinfo->remote_addr, repinfo->remote_addrlen))
|
||||
stats->qipv6++;
|
||||
if( (flags&BIT_QR) )
|
||||
stats->qbit_QR++;
|
||||
@@ -528,3 +614,16 @@ void server_stats_insrcode(struct ub_server_stats* stats, sldns_buffer* buf)
|
||||
stats->ans_rcode_nodata ++;
|
||||
}
|
||||
}
|
||||
|
||||
void server_stats_downstream_cookie(struct ub_server_stats* stats,
|
||||
struct edns_data* edns)
|
||||
{
|
||||
if(!(edns->edns_present && edns->cookie_present)) return;
|
||||
if(edns->cookie_valid) {
|
||||
stats->num_queries_cookie_valid++;
|
||||
} else if(edns->cookie_client) {
|
||||
stats->num_queries_cookie_client++;
|
||||
} else {
|
||||
stats->num_queries_cookie_invalid++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,4 +126,11 @@ void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
|
||||
*/
|
||||
void server_stats_insrcode(struct ub_server_stats* stats, struct sldns_buffer* buf);
|
||||
|
||||
/**
|
||||
* Add DNS Cookie stats for this query
|
||||
* @param stats: the stats
|
||||
* @param edns: edns record
|
||||
*/
|
||||
void server_stats_downstream_cookie(struct ub_server_stats* stats,
|
||||
struct edns_data* edns);
|
||||
#endif /* DAEMON_STATS_H */
|
||||
|
||||
+43
-51
@@ -174,7 +174,7 @@ static void
|
||||
checkrlimits(struct config_file* cfg)
|
||||
{
|
||||
#ifndef S_SPLINT_S
|
||||
#ifdef HAVE_GETRLIMIT
|
||||
#if defined(HAVE_GETRLIMIT) && !defined(unbound_testbound)
|
||||
/* list has number of ports to listen to, ifs number addresses */
|
||||
int list = ((cfg->do_udp?1:0) + (cfg->do_tcp?1 +
|
||||
(int)cfg->incoming_num_tcp:0));
|
||||
@@ -366,9 +366,8 @@ readpid (const char* file)
|
||||
/** write pid to file.
|
||||
* @param pidfile: file name of pid file.
|
||||
* @param pid: pid to write to file.
|
||||
* @return false on failure
|
||||
*/
|
||||
static int
|
||||
static void
|
||||
writepid (const char* pidfile, pid_t pid)
|
||||
{
|
||||
int fd;
|
||||
@@ -383,7 +382,7 @@ writepid (const char* pidfile, pid_t pid)
|
||||
, 0644)) == -1) {
|
||||
log_err("cannot open pidfile %s: %s",
|
||||
pidfile, strerror(errno));
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
while(count < strlen(pidbuf)) {
|
||||
ssize_t r = write(fd, pidbuf+count, strlen(pidbuf)-count);
|
||||
@@ -393,17 +392,16 @@ writepid (const char* pidfile, pid_t pid)
|
||||
log_err("cannot write to pidfile %s: %s",
|
||||
pidfile, strerror(errno));
|
||||
close(fd);
|
||||
return 0;
|
||||
return;
|
||||
} else if(r == 0) {
|
||||
log_err("cannot write any bytes to pidfile %s: "
|
||||
"write returns 0 bytes written", pidfile);
|
||||
close(fd);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
count += r;
|
||||
}
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -465,6 +463,18 @@ detach(void)
|
||||
#endif /* HAVE_DAEMON */
|
||||
}
|
||||
|
||||
/** setup the remote and ticket keys */
|
||||
static void
|
||||
setup_sslctx_remote(struct daemon* daemon, struct config_file* cfg)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
if(!(daemon->rc = daemon_remote_create(cfg)))
|
||||
fatal_exit("could not set up remote-control");
|
||||
#else /* HAVE_SSL */
|
||||
(void)daemon;(void)cfg;
|
||||
#endif /* HAVE_SSL */
|
||||
}
|
||||
|
||||
/** daemonize, drop user privileges and chroot if needed */
|
||||
static void
|
||||
perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
@@ -475,7 +485,11 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
#endif
|
||||
#ifdef HAVE_GETPWNAM
|
||||
struct passwd *pwd = NULL;
|
||||
#endif
|
||||
|
||||
if(!daemon_privileged(daemon))
|
||||
fatal_exit("could not do privileged setup");
|
||||
#ifdef HAVE_GETPWNAM
|
||||
if(cfg->username && cfg->username[0]) {
|
||||
if((pwd = getpwnam(cfg->username)) == NULL)
|
||||
fatal_exit("user '%s' does not exist.", cfg->username);
|
||||
@@ -487,36 +501,8 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
#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
|
||||
setup_sslctx_remote(daemon, cfg);
|
||||
daemon_setup_sslctxs(daemon, cfg);
|
||||
|
||||
/* init syslog (as root) if needed, before daemonize, otherwise
|
||||
* a fork error could not be printed since daemonize closed stderr.*/
|
||||
@@ -545,7 +531,15 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
cfg, 1);
|
||||
if(!daemon->pidfile)
|
||||
fatal_exit("pidfile alloc: out of memory");
|
||||
checkoldpid(daemon->pidfile, pidinchroot);
|
||||
/* Check old pid if there is no username configured.
|
||||
* With a username, the assumption is that the privilege
|
||||
* drop makes a pidfile not removed when the server stopped
|
||||
* last time. The server does not chown the pidfile for it,
|
||||
* because that creates privilege escape problems, with the
|
||||
* pidfile writable by unprivileged users, but used by
|
||||
* privileged users. */
|
||||
if(!(cfg->username && cfg->username[0]))
|
||||
checkoldpid(daemon->pidfile, pidinchroot);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -557,18 +551,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] && need_pidfile) {
|
||||
if(writepid(daemon->pidfile, getpid())) {
|
||||
if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1 &&
|
||||
pidinchroot) {
|
||||
# ifdef HAVE_CHOWN
|
||||
if(chown(daemon->pidfile, cfg_uid, cfg_gid) == -1) {
|
||||
verbose(VERB_QUERY, "cannot chown %u.%u %s: %s",
|
||||
(unsigned)cfg_uid, (unsigned)cfg_gid,
|
||||
daemon->pidfile, strerror(errno));
|
||||
}
|
||||
# endif /* HAVE_CHOWN */
|
||||
}
|
||||
}
|
||||
writepid(daemon->pidfile, getpid());
|
||||
}
|
||||
#else
|
||||
(void)daemon;
|
||||
@@ -682,6 +665,9 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
* it would succeed on SIGHUP as well */
|
||||
if(!cfg->use_syslog)
|
||||
log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
|
||||
daemon->cfgfile = strdup(*cfgfile);
|
||||
if(!daemon->cfgfile)
|
||||
fatal_exit("out of memory in daemon cfgfile strdup");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -716,6 +702,7 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pi
|
||||
"the commandline to see more errors, "
|
||||
"or unbound-checkconf", cfgfile);
|
||||
log_warn("Continuing with default config settings");
|
||||
config_auto_slab_values(cfg);
|
||||
}
|
||||
apply_settings(daemon, cfg, cmdline_verbose, debug_mode);
|
||||
if(!done_setup)
|
||||
@@ -746,7 +733,11 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pi
|
||||
if(daemon->pidfile) {
|
||||
int fd;
|
||||
/* truncate pidfile */
|
||||
fd = open(daemon->pidfile, O_WRONLY | O_TRUNC, 0644);
|
||||
fd = open(daemon->pidfile, O_WRONLY | O_TRUNC
|
||||
#ifdef O_NOFOLLOW
|
||||
| O_NOFOLLOW
|
||||
#endif
|
||||
, 0644);
|
||||
if(fd != -1)
|
||||
close(fd);
|
||||
/* delete pidfile */
|
||||
@@ -781,6 +772,7 @@ main(int argc, char* argv[])
|
||||
int cmdline_cfg = 0;
|
||||
#endif
|
||||
|
||||
checklock_start();
|
||||
log_init(NULL, 0, NULL);
|
||||
log_ident_default = strrchr(argv[0],'/')?strrchr(argv[0],'/')+1:argv[0];
|
||||
log_ident_set_default(log_ident_default);
|
||||
|
||||
+949
-365
File diff suppressed because it is too large
Load Diff
+15
-9
@@ -72,7 +72,13 @@ enum worker_commands {
|
||||
/** obtain statistics without statsclear */
|
||||
worker_cmd_stats_noreset,
|
||||
/** execute remote control command */
|
||||
worker_cmd_remote
|
||||
worker_cmd_remote,
|
||||
/** for fast-reload, perform stop */
|
||||
worker_cmd_reload_stop,
|
||||
/** for fast-reload, start again */
|
||||
worker_cmd_reload_start,
|
||||
/** for fast-reload, poll to make sure worker has released data */
|
||||
worker_cmd_reload_poll
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -86,6 +92,10 @@ struct worker {
|
||||
struct daemon* daemon;
|
||||
/** thread id */
|
||||
ub_thread_type thr_id;
|
||||
#ifdef HAVE_GETTID
|
||||
/** thread tid, the LWP id. */
|
||||
pid_t thread_tid;
|
||||
#endif
|
||||
/** pipe, for commands for this worker */
|
||||
struct tube* cmd;
|
||||
/** the event base this worker works with */
|
||||
@@ -94,10 +104,6 @@ struct worker {
|
||||
struct listen_dnsport* front;
|
||||
/** the backside outside network interface to the auth servers */
|
||||
struct outside_network* back;
|
||||
/** ports to be used by this worker. */
|
||||
int* ports;
|
||||
/** number of ports for this worker */
|
||||
int numports;
|
||||
/** the signal handler */
|
||||
struct comm_signal* comsig;
|
||||
/** commpoint to listen to commands. */
|
||||
@@ -114,7 +120,7 @@ struct worker {
|
||||
/** do we need to restart or quit (on signal) */
|
||||
int need_to_exit;
|
||||
/** allocation cache for this thread */
|
||||
struct alloc_cache alloc;
|
||||
struct alloc_cache *alloc;
|
||||
/** per thread statistics */
|
||||
struct ub_server_stats stats;
|
||||
/** thread scratch regional */
|
||||
@@ -127,6 +133,8 @@ struct worker {
|
||||
/** dnstap environment, changed for this thread */
|
||||
struct dt_env dtenv;
|
||||
#endif
|
||||
/** reuse existing cache on reload if other conditions allow it. */
|
||||
int reuse_cache;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -134,11 +142,9 @@ struct worker {
|
||||
* with backpointers only. Use worker_init on it later.
|
||||
* @param daemon: the daemon that this worker thread is part of.
|
||||
* @param id: the thread number from 0.. numthreads-1.
|
||||
* @param ports: the ports it is allowed to use, array.
|
||||
* @param n: the number of ports.
|
||||
* @return: the new worker or NULL on alloc failure.
|
||||
*/
|
||||
struct worker* worker_create(struct daemon* daemon, int id, int* ports, int n);
|
||||
struct worker* worker_create(struct daemon* daemon, int id);
|
||||
|
||||
/**
|
||||
* Initialize worker.
|
||||
|
||||
+144
-68
@@ -59,7 +59,7 @@
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* This is the default DNS64 prefix that is used whent he dns64 module is listed
|
||||
* This is the default DNS64 prefix that is used when the dns64 module is listed
|
||||
* in module-config but when the dns64-prefix variable is not present.
|
||||
*/
|
||||
static const char DEFAULT_DNS64_PREFIX[] = "64:ff9b::/96";
|
||||
@@ -366,22 +366,23 @@ 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,
|
||||
const char* dns64_prefix = cfg->dns64_prefix ?
|
||||
cfg->dns64_prefix : DEFAULT_DNS64_PREFIX;
|
||||
verbose(VERB_ALGO, "dns64-prefix: %s", dns64_prefix);
|
||||
if (!netblockstrtoaddr(dns64_prefix, 0, &dns64_env->prefix_addr,
|
||||
&dns64_env->prefix_addrlen, &dns64_env->prefix_net)) {
|
||||
log_err("cannot parse dns64-prefix netblock: %s", cfg->dns64_prefix);
|
||||
log_err("cannot parse dns64-prefix netblock: %s", dns64_prefix);
|
||||
return 0;
|
||||
}
|
||||
if (!addr_is_ip6(&dns64_env->prefix_addr, dns64_env->prefix_addrlen)) {
|
||||
log_err("dns64_prefix is not IPv6: %s", cfg->dns64_prefix);
|
||||
log_err("dns64_prefix is not IPv6: %s", dns64_prefix);
|
||||
return 0;
|
||||
}
|
||||
if (dns64_env->prefix_net != 32 && dns64_env->prefix_net != 40 &&
|
||||
dns64_env->prefix_net != 48 && dns64_env->prefix_net != 56 &&
|
||||
dns64_env->prefix_net != 64 && dns64_env->prefix_net != 96 ) {
|
||||
log_err("dns64-prefix length it not 32, 40, 48, 56, 64 or 96: %s",
|
||||
cfg->dns64_prefix);
|
||||
log_err("dns64-prefix length is not 32, 40, 48, 56, 64 or 96: %s",
|
||||
dns64_prefix);
|
||||
return 0;
|
||||
}
|
||||
for(s = cfg->dns64_ignore_aaaa; s; s = s->next) {
|
||||
@@ -496,8 +497,8 @@ handle_ipv6_ptr(struct module_qstate* qstate, int id)
|
||||
|
||||
/* Create the new sub-query. */
|
||||
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
|
||||
if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0, 0,
|
||||
&subq))
|
||||
if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->client_info,
|
||||
qstate->query_flags, 0, 0, &subq))
|
||||
return module_error;
|
||||
if (subq) {
|
||||
subq->curmod = id;
|
||||
@@ -522,8 +523,8 @@ generate_type_A_query(struct module_qstate* qstate, int id)
|
||||
|
||||
/* Start the sub-query. */
|
||||
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
|
||||
if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0,
|
||||
0, &subq))
|
||||
if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->client_info,
|
||||
qstate->query_flags, 0, 0, &subq))
|
||||
{
|
||||
verbose(VERB_ALGO, "dns64: sub-query creation failed");
|
||||
return module_error;
|
||||
@@ -573,28 +574,29 @@ static enum module_ext_state
|
||||
handle_event_pass(struct module_qstate* qstate, int id)
|
||||
{
|
||||
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"))
|
||||
/* Handle PTR queries for IPv6 addresses. */
|
||||
return handle_ipv6_ptr(qstate, id);
|
||||
int synth_all_cfg = qstate->env->cfg->dns64_synthall;
|
||||
int synth_qname = 0;
|
||||
|
||||
if (qstate->env->cfg->dns64_synthall &&
|
||||
iq && iq->state == DNS64_NEW_QUERY
|
||||
&& qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA)
|
||||
return generate_type_A_query(qstate, 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")) {
|
||||
/* Handle PTR queries for IPv6 addresses. */
|
||||
return handle_ipv6_ptr(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");
|
||||
if(iq && iq->state == DNS64_NEW_QUERY &&
|
||||
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA &&
|
||||
(synth_all_cfg ||
|
||||
(synth_qname=(dns64_always_synth_for_qname(qstate, id)
|
||||
&& !(qstate->query_flags & BIT_CD))))) {
|
||||
if(synth_qname)
|
||||
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 (iq && iq->state == DNS64_SUBQUERY_FINISHED)
|
||||
if(iq && iq->state == DNS64_SUBQUERY_FINISHED)
|
||||
return module_finished;
|
||||
|
||||
/* Otherwise, pass request to next module. */
|
||||
@@ -627,32 +629,47 @@ 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((!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)))
|
||||
/* 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);
|
||||
|
||||
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");
|
||||
/* When an AAAA query completes check if we want to perform DNS64
|
||||
* synthesis. We skip queries with DNSSEC enabled (!CD) and
|
||||
* ones generated by us to retrieve the A/PTR record to use for
|
||||
* synth. */
|
||||
int could_synth =
|
||||
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA &&
|
||||
(!iq || iq->state != DNS64_INTERNAL_QUERY) &&
|
||||
!(qstate->query_flags & BIT_CD);
|
||||
int has_data = /* whether query returned non-empty rrset */
|
||||
qstate->return_msg &&
|
||||
qstate->return_msg->rep &&
|
||||
reply_find_answer_rrset(&qstate->qinfo, qstate->return_msg->rep);
|
||||
int synth_qname = 0;
|
||||
if(could_synth && !has_data && qstate->env->need_to_validate &&
|
||||
qstate->return_msg && qstate->return_msg->rep &&
|
||||
qstate->return_msg->rep->security == sec_status_bogus) {
|
||||
verbose(VERB_ALGO, "dns64: bogus AAAA reply not synthesized");
|
||||
could_synth = 0;
|
||||
}
|
||||
|
||||
if(could_synth &&
|
||||
(!has_data ||
|
||||
(synth_qname=dns64_always_synth_for_qname(qstate, id)))) {
|
||||
if(synth_qname)
|
||||
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))
|
||||
if( (!iq || !iq->started_no_cache_store) &&
|
||||
!qstate->rpz_applied && !qstate->rpz_passthru &&
|
||||
!qstate->is_subnet_answer &&
|
||||
qstate->return_msg &&
|
||||
qstate->return_msg->rep &&
|
||||
!qstate->fwd_stub_no_cache &&
|
||||
!dns_cache_store(
|
||||
qstate->env, &qstate->qinfo, qstate->return_msg->rep,
|
||||
0, qstate->prefetch_leeway, 0, NULL,
|
||||
qstate->query_flags, qstate->qstarttime,
|
||||
qstate->is_valrec))
|
||||
log_err("out of memory");
|
||||
|
||||
/* do nothing */
|
||||
@@ -685,12 +702,17 @@ 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. */
|
||||
iq = (struct dns64_qstate*)regional_alloc(
|
||||
qstate->region, sizeof(*iq));
|
||||
if (!(iq = (struct dns64_qstate*)regional_alloc(
|
||||
qstate->region, sizeof(*iq)))) {
|
||||
log_err("out of memory");
|
||||
qstate->ext_state[id] = module_error;
|
||||
return;
|
||||
}
|
||||
qstate->minfo[id] = iq;
|
||||
iq->state = DNS64_NEW_QUERY;
|
||||
iq->started_no_cache_store = qstate->no_cache_store;
|
||||
qstate->no_cache_store = 1;
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
case module_event_pass:
|
||||
qstate->ext_state[id] = handle_event_pass(qstate, id);
|
||||
@@ -704,8 +726,15 @@ dns64_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
}
|
||||
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;
|
||||
if(iq && iq->state != DNS64_INTERNAL_QUERY) {
|
||||
if(qstate->fwd_stub_no_cache) {
|
||||
/* If the forward/stub has no cache, then
|
||||
* continue with the query with no cache. */
|
||||
qstate->no_cache_store = qstate->fwd_stub_no_cache;
|
||||
} else {
|
||||
qstate->no_cache_store = iq->started_no_cache_store;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -812,6 +841,7 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
||||
size_t i, s;
|
||||
struct packed_rrset_data* fd, *dd;
|
||||
struct ub_packed_rrset_key* fk, *dk;
|
||||
int allocated_return_msg = 0;
|
||||
|
||||
verbose(VERB_ALGO, "converting A answers to AAAA answers");
|
||||
|
||||
@@ -827,6 +857,7 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
||||
return;
|
||||
memset(super->return_msg, 0, sizeof(*super->return_msg));
|
||||
super->return_msg->qinfo = super->qinfo;
|
||||
allocated_return_msg = 1;
|
||||
}
|
||||
|
||||
rep = qstate->return_msg->rep;
|
||||
@@ -836,13 +867,17 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
||||
*/
|
||||
cp = construct_reply_info_base(super->region, rep->flags, rep->qdcount,
|
||||
rep->ttl, rep->prefetch_ttl, rep->serve_expired_ttl,
|
||||
rep->serve_expired_norec_ttl,
|
||||
rep->an_numrrsets, rep->ns_numrrsets, rep->ar_numrrsets,
|
||||
rep->rrset_count, rep->security);
|
||||
if(!cp)
|
||||
rep->rrset_count, rep->security, LDNS_EDE_NONE);
|
||||
if(!cp) {
|
||||
if(allocated_return_msg) super->return_msg = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* allocate ub_key structures special or not */
|
||||
if(!reply_info_alloc_rrset_keys(cp, NULL, super->region)) {
|
||||
if(allocated_return_msg) super->return_msg = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -857,8 +892,10 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
||||
if(i<rep->an_numrrsets && fk->rk.type == htons(LDNS_RR_TYPE_A)) {
|
||||
/* also sets dk->entry.hash */
|
||||
dns64_synth_aaaa_data(fk, fd, dk, &dd, super->region, dns64_env);
|
||||
if(!dd)
|
||||
if(!dd) {
|
||||
if(allocated_return_msg) super->return_msg = NULL;
|
||||
return;
|
||||
}
|
||||
/* Delete negative AAAA record from cache stored by
|
||||
* the iterator module */
|
||||
rrset_cache_remove(super->env->rrset_cache, dk->rk.dname,
|
||||
@@ -875,15 +912,19 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
||||
dk->rk.dname = (uint8_t*)regional_alloc_init(super->region,
|
||||
fk->rk.dname, fk->rk.dname_len);
|
||||
|
||||
if(!dk->rk.dname)
|
||||
if(!dk->rk.dname) {
|
||||
if(allocated_return_msg) super->return_msg = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
s = packed_rrset_sizeof(fd);
|
||||
dd = (struct packed_rrset_data*)regional_alloc_init(
|
||||
super->region, fd, s);
|
||||
|
||||
if(!dd)
|
||||
if(!dd) {
|
||||
if(allocated_return_msg) super->return_msg = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
packed_rrset_ptr_fixup(dd);
|
||||
@@ -913,8 +954,11 @@ dns64_adjust_ptr(struct module_qstate* qstate, struct module_qstate* super)
|
||||
sizeof(struct dns_msg))))
|
||||
return;
|
||||
super->return_msg->qinfo = super->qinfo;
|
||||
super->return_msg->rep = reply_info_copy(qstate->return_msg->rep, NULL,
|
||||
super->region);
|
||||
if (!(super->return_msg->rep = reply_info_copy(qstate->return_msg->rep,
|
||||
NULL, super->region))) {
|
||||
super->return_msg = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust the domain name of the answer RR set so that it matches the
|
||||
@@ -964,16 +1008,40 @@ dns64_inform_super(struct module_qstate* qstate, int id,
|
||||
}
|
||||
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) {
|
||||
/* If there is no successful answer, we're done.
|
||||
* Guarantee that we have at least a NOERROR reply further on. */
|
||||
if(qstate->return_rcode != LDNS_RCODE_NOERROR
|
||||
|| !qstate->return_msg
|
||||
|| !qstate->return_msg->rep) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* When no A record is found for synthesis fall back to AAAA again. */
|
||||
if(qstate->qinfo.qtype == LDNS_RR_TYPE_A &&
|
||||
!reply_find_answer_rrset(&qstate->qinfo,
|
||||
qstate->return_msg->rep)) {
|
||||
super_dq->state = DNS64_INTERNAL_QUERY;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Use return code from A query in response to client. */
|
||||
if (super->return_rcode != LDNS_RCODE_NOERROR)
|
||||
super->return_rcode = qstate->return_rcode;
|
||||
/* RPZ applied to the subquery need to then change (not cache)
|
||||
* the super query. With the super query not cached, it is
|
||||
* going to run the state machine modules on incoming queries,
|
||||
* that fetch the subquery (cache) response, and modify it
|
||||
* according to the rpz policy. That makes the synthesized
|
||||
* super query also adjusted by rpz policies. But loses cache
|
||||
* hits. Even though the subquery likely is answered from cache,
|
||||
* internally in its state machine process. */
|
||||
if(qstate->rpz_applied)
|
||||
super->rpz_applied = 1;
|
||||
if(qstate->rpz_passthru)
|
||||
super->rpz_passthru = 1;
|
||||
|
||||
/* Since the super qstate has a new response, its errinf is removed. */
|
||||
super->errinf = NULL;
|
||||
|
||||
/* Generate a response suitable for the original query. */
|
||||
if (qstate->qinfo.qtype == LDNS_RR_TYPE_A) {
|
||||
@@ -982,11 +1050,19 @@ dns64_inform_super(struct module_qstate* qstate, int id,
|
||||
log_assert(qstate->qinfo.qtype == LDNS_RR_TYPE_PTR);
|
||||
dns64_adjust_ptr(qstate, super);
|
||||
}
|
||||
/* If the sub-query has no cache store, then also the super query. */
|
||||
if(qstate->fwd_stub_no_cache)
|
||||
super->fwd_stub_no_cache = 1;
|
||||
|
||||
/* Store the generated response in cache. */
|
||||
if ( (!super_dq || !super_dq->started_no_cache_store) &&
|
||||
if ( super->return_msg && super->return_msg->rep &&
|
||||
(!super_dq || !super_dq->started_no_cache_store) &&
|
||||
!qstate->fwd_stub_no_cache &&
|
||||
!super->rpz_applied && !super->rpz_passthru &&
|
||||
!super->is_subnet_answer &&
|
||||
!dns_cache_store(super->env, &super->qinfo, super->return_msg->rep,
|
||||
0, 0, 0, NULL, super->query_flags))
|
||||
0, super->prefetch_leeway, 0, NULL, super->query_flags,
|
||||
qstate->qstarttime, qstate->is_valrec))
|
||||
log_err("out of memory");
|
||||
}
|
||||
|
||||
@@ -1024,8 +1100,8 @@ dns64_get_mem(struct module_env* env, int id)
|
||||
*/
|
||||
static struct module_func_block dns64_block = {
|
||||
"dns64",
|
||||
&dns64_init, &dns64_deinit, &dns64_operate, &dns64_inform_super,
|
||||
&dns64_clear, &dns64_get_mem
|
||||
NULL, NULL, &dns64_init, &dns64_deinit, &dns64_operate,
|
||||
&dns64_inform_super, &dns64_clear, &dns64_get_mem
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+34
-7
@@ -361,7 +361,7 @@ dnscrypt_server_uncurve(struct dnsc_env* env,
|
||||
|
||||
len -= DNSCRYPT_QUERY_HEADER_SIZE;
|
||||
|
||||
while (*sldns_buffer_at(buffer, --len) == 0)
|
||||
while (len>0 && *sldns_buffer_at(buffer, --len) == 0)
|
||||
;
|
||||
|
||||
if (*sldns_buffer_at(buffer, len) != 0x80) {
|
||||
@@ -435,7 +435,7 @@ dnscrypt_hrtime(void)
|
||||
|
||||
/**
|
||||
* Add the server nonce part to once.
|
||||
* The nonce is made half of client nonce and the seconf half of the server
|
||||
* The nonce is made half of client nonce and the second half of the server
|
||||
* nonce, both of them of size crypto_box_HALF_NONCEBYTES.
|
||||
* \param[in] nonce: a uint8_t* of size crypto_box_NONCEBYTES
|
||||
*/
|
||||
@@ -474,10 +474,18 @@ dnscrypt_server_curve(const dnsccert *cert,
|
||||
uint8_t *const buf = sldns_buffer_begin(buffer);
|
||||
size_t len = sldns_buffer_limit(buffer);
|
||||
|
||||
if(len + DNSCRYPT_REPLY_HEADER_SIZE > sldns_buffer_capacity(buffer))
|
||||
return -1;
|
||||
sldns_buffer_clear(buffer);
|
||||
|
||||
if(udp){
|
||||
if (max_len > max_reply_size)
|
||||
max_len = max_reply_size;
|
||||
}
|
||||
if(max_len > sldns_buffer_capacity(buffer))
|
||||
max_len = sldns_buffer_capacity(buffer);
|
||||
if(max_len > 65535)
|
||||
max_len = 65535;
|
||||
|
||||
|
||||
memcpy(nonce, client_nonce, crypto_box_HALF_NONCEBYTES);
|
||||
@@ -520,6 +528,7 @@ dnscrypt_server_curve(const dnsccert *cert,
|
||||
DNSCRYPT_MAGIC_HEADER_LEN,
|
||||
nonce,
|
||||
crypto_box_NONCEBYTES);
|
||||
sldns_buffer_flip(buffer);
|
||||
sldns_buffer_set_limit(buffer, len + DNSCRYPT_REPLY_HEADER_SIZE);
|
||||
return 0;
|
||||
}
|
||||
@@ -663,6 +672,8 @@ dnsc_find_cert(struct dnsc_env* dnscenv, struct sldns_buffer* buffer)
|
||||
}
|
||||
dnscrypt_header = (struct dnscrypt_query_header *)sldns_buffer_begin(buffer);
|
||||
for (i = 0U; i < dnscenv->signed_certs_count; i++) {
|
||||
if(!certs[i].keypair)
|
||||
continue;
|
||||
if (memcmp(certs[i].magic_query, dnscrypt_header->magic_query,
|
||||
DNSCRYPT_MAGIC_HEADER_LEN) == 0) {
|
||||
return &certs[i];
|
||||
@@ -674,7 +685,7 @@ dnsc_find_cert(struct dnsc_env* dnscenv, struct sldns_buffer* buffer)
|
||||
/**
|
||||
* Insert local-zone and local-data into configuration.
|
||||
* In order to be able to serve certs over TXT, we can reuse the local-zone and
|
||||
* local-data config option. The zone and qname are infered from the
|
||||
* local-data config option. The zone and qname are inferred from the
|
||||
* provider_name and the content of the TXT record from the certificate content.
|
||||
* returns the number of certificate TXT record that were loaded.
|
||||
* < 0 in case of error.
|
||||
@@ -804,6 +815,7 @@ dnsc_parse_keys(struct dnsc_env *env, struct config_file *cfg)
|
||||
sizeof *env->keypairs);
|
||||
env->certs = sodium_allocarray(env->signed_certs_count,
|
||||
sizeof *env->certs);
|
||||
memset(env->certs, 0, env->signed_certs_count * sizeof(*env->certs));
|
||||
|
||||
cert_id = 0U;
|
||||
keypair_id = 0U;
|
||||
@@ -830,7 +842,14 @@ dnsc_parse_keys(struct dnsc_env *env, struct config_file *cfg)
|
||||
if(memcmp(current_keypair->crypt_publickey,
|
||||
env->signed_certs[c].server_publickey,
|
||||
crypto_box_PUBLICKEYBYTES) == 0) {
|
||||
dnsccert *current_cert = &env->certs[cert_id++];
|
||||
dnsccert* current_cert;
|
||||
if(cert_id >= env->signed_certs_count) {
|
||||
log_err("dnscrypt: secret key %s matches a cert that "
|
||||
"is already bound to another key (duplicate "
|
||||
"dnscrypt-secret-key?)", head->str);
|
||||
return -1;
|
||||
}
|
||||
current_cert = &env->certs[cert_id++];
|
||||
found_cert = 1;
|
||||
current_cert->keypair = current_keypair;
|
||||
memcpy(current_cert->magic_query,
|
||||
@@ -912,12 +931,13 @@ dnsc_handle_curved_request(struct dnsc_env* dnscenv,
|
||||
}
|
||||
|
||||
int
|
||||
dnsc_handle_uncurved_request(struct comm_reply *repinfo)
|
||||
dnsc_handle_uncurved_request(struct comm_reply *repinfo,
|
||||
struct sldns_buffer* buffer)
|
||||
{
|
||||
if(!repinfo->c->dnscrypt) {
|
||||
return 1;
|
||||
}
|
||||
sldns_buffer_copy(repinfo->c->dnscrypt_buffer, repinfo->c->buffer);
|
||||
sldns_buffer_copy(repinfo->c->dnscrypt_buffer, buffer);
|
||||
if(!repinfo->is_dnscrypted) {
|
||||
return 1;
|
||||
}
|
||||
@@ -963,12 +983,19 @@ dnsc_create(void)
|
||||
int
|
||||
dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg)
|
||||
{
|
||||
int nkeys;
|
||||
if(dnsc_parse_certs(env, cfg) <= 0) {
|
||||
fatal_exit("dnsc_apply_cfg: no cert file loaded");
|
||||
}
|
||||
if(dnsc_parse_keys(env, cfg) <= 0) {
|
||||
nkeys = dnsc_parse_keys(env, cfg);
|
||||
if(nkeys <= 0) {
|
||||
fatal_exit("dnsc_apply_cfg: no key file loaded");
|
||||
}
|
||||
if((size_t)nkeys < env->signed_certs_count) {
|
||||
fatal_exit("dnsc_apply_cfg: %u dnscrypt-provider-cert file(s) have no "
|
||||
"matching dnscrypt-secret-key",
|
||||
(unsigned)(env->signed_certs_count - (size_t)nkeys));
|
||||
}
|
||||
randombytes_buf(env->hash_key, sizeof env->hash_key);
|
||||
env->provider_name = cfg->dnscrypt_provider;
|
||||
|
||||
|
||||
+4
-3
@@ -114,7 +114,7 @@ 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
|
||||
* Determine whether 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.
|
||||
*/
|
||||
@@ -122,13 +122,14 @@ 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
|
||||
* Determine whether 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);
|
||||
int dnsc_handle_uncurved_request(struct comm_reply *repinfo,
|
||||
struct sldns_buffer* buffer);
|
||||
|
||||
/**
|
||||
* Computes the size of the shared secret cache entry.
|
||||
|
||||
+127
-34
@@ -86,6 +86,31 @@ dt_pack(const Dnstap__Dnstap *d, void **buf, size_t *sz)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** See if the message is sent due to dnstap sample rate */
|
||||
static int
|
||||
dt_sample_rate_limited(struct dt_env* env)
|
||||
{
|
||||
lock_basic_lock(&env->sample_lock);
|
||||
/* Sampling is every [n] packets. Where n==1, every packet is sent */
|
||||
if(env->sample_rate > 1) {
|
||||
int submit = 0;
|
||||
/* if sampling is engaged... */
|
||||
if (env->sample_rate_count > env->sample_rate) {
|
||||
/* once the count passes the limit */
|
||||
/* submit the message */
|
||||
submit = 1;
|
||||
/* and reset the count */
|
||||
env->sample_rate_count = 0;
|
||||
}
|
||||
/* increment count regardless */
|
||||
env->sample_rate_count++;
|
||||
lock_basic_unlock(&env->sample_lock);
|
||||
return !submit;
|
||||
}
|
||||
lock_basic_unlock(&env->sample_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
dt_send(const struct dt_env *env, void *buf, size_t len_buf)
|
||||
{
|
||||
@@ -146,71 +171,89 @@ dt_create(struct config_file* cfg)
|
||||
env = (struct dt_env *) calloc(1, sizeof(struct dt_env));
|
||||
if (!env)
|
||||
return NULL;
|
||||
lock_basic_init(&env->sample_lock);
|
||||
|
||||
env->dtio = dt_io_thread_create();
|
||||
if(!env->dtio) {
|
||||
log_err("malloc failure");
|
||||
free(env);
|
||||
dt_delete(env);
|
||||
return NULL;
|
||||
}
|
||||
if(!dt_io_thread_apply_cfg(env->dtio, cfg)) {
|
||||
dt_io_thread_delete(env->dtio);
|
||||
free(env);
|
||||
dt_delete(env);
|
||||
return NULL;
|
||||
}
|
||||
if(!dt_apply_cfg(env, cfg)) {
|
||||
dt_delete(env);
|
||||
return NULL;
|
||||
}
|
||||
dt_apply_cfg(env, cfg);
|
||||
return env;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
dt_apply_identity(struct dt_env *env, struct config_file *cfg)
|
||||
{
|
||||
char buf[MAXHOSTNAMELEN+1];
|
||||
if (!cfg->dnstap_send_identity)
|
||||
return;
|
||||
if (!cfg->dnstap_send_identity) {
|
||||
free(env->identity);
|
||||
env->identity = NULL;
|
||||
env->len_identity = 0;
|
||||
return 1;
|
||||
}
|
||||
free(env->identity);
|
||||
if (cfg->dnstap_identity == NULL || cfg->dnstap_identity[0] == 0) {
|
||||
if (gethostname(buf, MAXHOSTNAMELEN) == 0) {
|
||||
buf[MAXHOSTNAMELEN] = 0;
|
||||
env->identity = strdup(buf);
|
||||
} else {
|
||||
fatal_exit("dt_apply_identity: gethostname() failed");
|
||||
log_err("dt_apply_identity: gethostname() failed: %s",
|
||||
strerror(errno));
|
||||
env->identity = NULL;
|
||||
env->len_identity = 0;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
env->identity = strdup(cfg->dnstap_identity);
|
||||
}
|
||||
if (env->identity == NULL)
|
||||
fatal_exit("dt_apply_identity: strdup() failed");
|
||||
if (env->identity == NULL) {
|
||||
log_err("dt_apply_identity: strdup() failed");
|
||||
env->len_identity = 0;
|
||||
return 0;
|
||||
}
|
||||
env->len_identity = (unsigned int)strlen(env->identity);
|
||||
verbose(VERB_OPS, "dnstap identity field set to \"%s\"",
|
||||
env->identity);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
dt_apply_version(struct dt_env *env, struct config_file *cfg)
|
||||
{
|
||||
if (!cfg->dnstap_send_version)
|
||||
return;
|
||||
if (!cfg->dnstap_send_version) {
|
||||
free(env->version);
|
||||
env->version = NULL;
|
||||
env->len_version = 0;
|
||||
return 1;
|
||||
}
|
||||
free(env->version);
|
||||
if (cfg->dnstap_version == NULL || cfg->dnstap_version[0] == 0)
|
||||
env->version = strdup(PACKAGE_STRING);
|
||||
else
|
||||
env->version = strdup(cfg->dnstap_version);
|
||||
if (env->version == NULL)
|
||||
fatal_exit("dt_apply_version: strdup() failed");
|
||||
if (env->version == NULL) {
|
||||
log_err("dt_apply_version: strdup() failed");
|
||||
env->len_version = 0;
|
||||
return 0;
|
||||
}
|
||||
env->len_version = (unsigned int)strlen(env->version);
|
||||
verbose(VERB_OPS, "dnstap version field set to \"%s\"",
|
||||
env->version);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
|
||||
dt_apply_logcfg(struct dt_env *env, struct config_file *cfg)
|
||||
{
|
||||
if (!cfg->dnstap)
|
||||
return;
|
||||
|
||||
dt_apply_identity(env, cfg);
|
||||
dt_apply_version(env, cfg);
|
||||
if ((env->log_resolver_query_messages = (unsigned int)
|
||||
cfg->dnstap_log_resolver_query_messages))
|
||||
{
|
||||
@@ -241,6 +284,26 @@ dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
|
||||
{
|
||||
verbose(VERB_OPS, "dnstap Message/FORWARDER_RESPONSE enabled");
|
||||
}
|
||||
lock_basic_lock(&env->sample_lock);
|
||||
if((env->sample_rate = (unsigned int)cfg->dnstap_sample_rate))
|
||||
{
|
||||
verbose(VERB_OPS, "dnstap SAMPLE_RATE enabled and set to \"%d\"", (int)env->sample_rate);
|
||||
}
|
||||
lock_basic_unlock(&env->sample_lock);
|
||||
}
|
||||
|
||||
int
|
||||
dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
|
||||
{
|
||||
if (!cfg->dnstap)
|
||||
return 1;
|
||||
|
||||
dt_apply_logcfg(env, cfg);
|
||||
if(!dt_apply_identity(env, cfg))
|
||||
return 0;
|
||||
if(!dt_apply_version(env, cfg))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -273,6 +336,7 @@ dt_delete(struct dt_env *env)
|
||||
if (!env)
|
||||
return;
|
||||
dt_io_thread_delete(env->dtio);
|
||||
lock_basic_destroy(&env->sample_lock);
|
||||
free(env->identity);
|
||||
free(env->version);
|
||||
free(env);
|
||||
@@ -305,6 +369,7 @@ dt_msg_fill_net(struct dt_msg *dm,
|
||||
struct sockaddr_storage *qs,
|
||||
struct sockaddr_storage *rs,
|
||||
enum comm_point_type cptype,
|
||||
void *cpssl,
|
||||
ProtobufCBinaryData *qaddr, protobuf_c_boolean *has_qaddr,
|
||||
uint32_t *qport, protobuf_c_boolean *has_qport,
|
||||
ProtobufCBinaryData *raddr, protobuf_c_boolean *has_raddr,
|
||||
@@ -371,13 +436,26 @@ dt_msg_fill_net(struct dt_msg *dm,
|
||||
*has_rport = 1;
|
||||
}
|
||||
|
||||
log_assert(cptype == comm_udp || cptype == comm_tcp);
|
||||
if (cptype == comm_udp) {
|
||||
/* socket_protocol */
|
||||
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__UDP;
|
||||
dm->m.has_socket_protocol = 1;
|
||||
} else if (cptype == comm_tcp) {
|
||||
if (cpssl == NULL) {
|
||||
/* socket_protocol */
|
||||
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP;
|
||||
dm->m.has_socket_protocol = 1;
|
||||
} else {
|
||||
/* socket_protocol */
|
||||
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOT;
|
||||
dm->m.has_socket_protocol = 1;
|
||||
}
|
||||
} else if (cptype == comm_http) {
|
||||
/* socket_protocol */
|
||||
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOH;
|
||||
dm->m.has_socket_protocol = 1;
|
||||
} else {
|
||||
/* other socket protocol */
|
||||
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP;
|
||||
dm->m.has_socket_protocol = 1;
|
||||
}
|
||||
@@ -388,12 +466,19 @@ dt_msg_send_client_query(struct dt_env *env,
|
||||
struct sockaddr_storage *qsock,
|
||||
struct sockaddr_storage *rsock,
|
||||
enum comm_point_type cptype,
|
||||
sldns_buffer *qmsg)
|
||||
void *cpssl,
|
||||
sldns_buffer *qmsg,
|
||||
struct timeval* tstamp)
|
||||
{
|
||||
struct dt_msg dm;
|
||||
struct timeval qtime;
|
||||
|
||||
gettimeofday(&qtime, NULL);
|
||||
if(dt_sample_rate_limited(env))
|
||||
return;
|
||||
|
||||
if(tstamp)
|
||||
memcpy(&qtime, tstamp, sizeof(qtime));
|
||||
else gettimeofday(&qtime, NULL);
|
||||
|
||||
/* type */
|
||||
dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_QUERY);
|
||||
@@ -407,8 +492,7 @@ dt_msg_send_client_query(struct dt_env *env,
|
||||
dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message);
|
||||
|
||||
/* socket_family, socket_protocol, query_address, query_port, response_address, response_port */
|
||||
log_assert(cptype == comm_udp || cptype == comm_tcp);
|
||||
dt_msg_fill_net(&dm, qsock, rsock, cptype,
|
||||
dt_msg_fill_net(&dm, qsock, rsock, cptype, cpssl,
|
||||
&dm.m.query_address, &dm.m.has_query_address,
|
||||
&dm.m.query_port, &dm.m.has_query_port,
|
||||
&dm.m.response_address, &dm.m.has_response_address,
|
||||
@@ -424,11 +508,15 @@ dt_msg_send_client_response(struct dt_env *env,
|
||||
struct sockaddr_storage *qsock,
|
||||
struct sockaddr_storage *rsock,
|
||||
enum comm_point_type cptype,
|
||||
void *cpssl,
|
||||
sldns_buffer *rmsg)
|
||||
{
|
||||
struct dt_msg dm;
|
||||
struct timeval rtime;
|
||||
|
||||
if(dt_sample_rate_limited(env))
|
||||
return;
|
||||
|
||||
gettimeofday(&rtime, NULL);
|
||||
|
||||
/* type */
|
||||
@@ -443,8 +531,7 @@ dt_msg_send_client_response(struct dt_env *env,
|
||||
dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message);
|
||||
|
||||
/* socket_family, socket_protocol, query_address, query_port, response_address, response_port */
|
||||
log_assert(cptype == comm_udp || cptype == comm_tcp);
|
||||
dt_msg_fill_net(&dm, qsock, rsock, cptype,
|
||||
dt_msg_fill_net(&dm, qsock, rsock, cptype, cpssl,
|
||||
&dm.m.query_address, &dm.m.has_query_address,
|
||||
&dm.m.query_port, &dm.m.has_query_port,
|
||||
&dm.m.response_address, &dm.m.has_response_address,
|
||||
@@ -459,6 +546,7 @@ dt_msg_send_outside_query(struct dt_env *env,
|
||||
struct sockaddr_storage *rsock,
|
||||
struct sockaddr_storage *qsock,
|
||||
enum comm_point_type cptype,
|
||||
void *cpssl,
|
||||
uint8_t *zone, size_t zone_len,
|
||||
sldns_buffer *qmsg)
|
||||
{
|
||||
@@ -466,11 +554,14 @@ dt_msg_send_outside_query(struct dt_env *env,
|
||||
struct timeval qtime;
|
||||
uint16_t qflags;
|
||||
|
||||
if(dt_sample_rate_limited(env))
|
||||
return;
|
||||
|
||||
gettimeofday(&qtime, NULL);
|
||||
qflags = sldns_buffer_read_u16_at(qmsg, 2);
|
||||
|
||||
/* type */
|
||||
if (qflags & BIT_RD) {
|
||||
if ((qflags & BIT_RD)) {
|
||||
if (!env->log_forwarder_query_messages)
|
||||
return;
|
||||
dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY);
|
||||
@@ -494,8 +585,7 @@ dt_msg_send_outside_query(struct dt_env *env,
|
||||
dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message);
|
||||
|
||||
/* socket_family, socket_protocol, response_address, response_port, query_address, query_port */
|
||||
log_assert(cptype == comm_udp || cptype == comm_tcp);
|
||||
dt_msg_fill_net(&dm, rsock, qsock, cptype,
|
||||
dt_msg_fill_net(&dm, rsock, qsock, cptype, cpssl,
|
||||
&dm.m.response_address, &dm.m.has_response_address,
|
||||
&dm.m.response_port, &dm.m.has_response_port,
|
||||
&dm.m.query_address, &dm.m.has_query_address,
|
||||
@@ -510,6 +600,7 @@ dt_msg_send_outside_response(struct dt_env *env,
|
||||
struct sockaddr_storage *rsock,
|
||||
struct sockaddr_storage *qsock,
|
||||
enum comm_point_type cptype,
|
||||
void *cpssl,
|
||||
uint8_t *zone, size_t zone_len,
|
||||
uint8_t *qbuf, size_t qbuf_len,
|
||||
const struct timeval *qtime,
|
||||
@@ -519,12 +610,15 @@ dt_msg_send_outside_response(struct dt_env *env,
|
||||
struct dt_msg dm;
|
||||
uint16_t qflags;
|
||||
|
||||
if(dt_sample_rate_limited(env))
|
||||
return;
|
||||
|
||||
(void)qbuf_len; log_assert(qbuf_len >= sizeof(qflags));
|
||||
memcpy(&qflags, qbuf, sizeof(qflags));
|
||||
qflags = ntohs(qflags);
|
||||
|
||||
/* type */
|
||||
if (qflags & BIT_RD) {
|
||||
if ((qflags & BIT_RD)) {
|
||||
if (!env->log_forwarder_response_messages)
|
||||
return;
|
||||
dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE);
|
||||
@@ -553,8 +647,7 @@ dt_msg_send_outside_response(struct dt_env *env,
|
||||
dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message);
|
||||
|
||||
/* socket_family, socket_protocol, response_address, response_port, query_address, query_port */
|
||||
log_assert(cptype == comm_udp || cptype == comm_tcp);
|
||||
dt_msg_fill_net(&dm, rsock, qsock, cptype,
|
||||
dt_msg_fill_net(&dm, rsock, qsock, cptype, cpssl,
|
||||
&dm.m.response_address, &dm.m.has_response_address,
|
||||
&dm.m.response_port, &dm.m.has_response_port,
|
||||
&dm.m.query_address, &dm.m.has_query_address,
|
||||
|
||||
+24
-3
@@ -39,6 +39,7 @@
|
||||
|
||||
#ifdef USE_DNSTAP
|
||||
|
||||
#include "util/locks.h"
|
||||
struct config_file;
|
||||
struct sldns_buffer;
|
||||
struct dt_msg_queue;
|
||||
@@ -75,6 +76,13 @@ struct dt_env {
|
||||
unsigned log_forwarder_query_messages : 1;
|
||||
/** whether to log Message/FORWARDER_RESPONSE */
|
||||
unsigned log_forwarder_response_messages : 1;
|
||||
|
||||
/** lock on sample count */
|
||||
lock_basic_type sample_lock;
|
||||
/** rate limit value from config, samples 1/N messages */
|
||||
unsigned int sample_rate;
|
||||
/** rate limit counter */
|
||||
unsigned int sample_rate_count;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -94,9 +102,16 @@ dt_create(struct config_file* cfg);
|
||||
* Apply config settings.
|
||||
* @param env: dnstap environment object.
|
||||
* @param cfg: new config settings.
|
||||
* @return false on failure.
|
||||
*/
|
||||
void
|
||||
dt_apply_cfg(struct dt_env *env, struct config_file *cfg);
|
||||
int dt_apply_cfg(struct dt_env *env, struct config_file *cfg);
|
||||
|
||||
/**
|
||||
* Apply config settings for log enable for message types.
|
||||
* @param env: dnstap environment object.
|
||||
* @param cfg: new config settings.
|
||||
*/
|
||||
void dt_apply_logcfg(struct dt_env *env, struct config_file *cfg);
|
||||
|
||||
/**
|
||||
* Initialize per-worker state in dnstap environment object.
|
||||
@@ -126,13 +141,16 @@ dt_delete(struct dt_env *env);
|
||||
* @param rsock: local (service) address/port.
|
||||
* @param cptype: comm_udp or comm_tcp.
|
||||
* @param qmsg: query message.
|
||||
* @param tstamp: timestamp or NULL if none provided.
|
||||
*/
|
||||
void
|
||||
dt_msg_send_client_query(struct dt_env *env,
|
||||
struct sockaddr_storage *qsock,
|
||||
struct sockaddr_storage *rsock,
|
||||
enum comm_point_type cptype,
|
||||
struct sldns_buffer *qmsg);
|
||||
void *cpssl,
|
||||
struct sldns_buffer *qmsg,
|
||||
struct timeval* tstamp);
|
||||
|
||||
/**
|
||||
* Create and send a new dnstap "Message" event of type CLIENT_RESPONSE.
|
||||
@@ -147,6 +165,7 @@ dt_msg_send_client_response(struct dt_env *env,
|
||||
struct sockaddr_storage *qsock,
|
||||
struct sockaddr_storage *rsock,
|
||||
enum comm_point_type cptype,
|
||||
void *cpssl,
|
||||
struct sldns_buffer *rmsg);
|
||||
|
||||
/**
|
||||
@@ -166,6 +185,7 @@ dt_msg_send_outside_query(struct dt_env *env,
|
||||
struct sockaddr_storage *rsock,
|
||||
struct sockaddr_storage *qsock,
|
||||
enum comm_point_type cptype,
|
||||
void *cpssl,
|
||||
uint8_t *zone, size_t zone_len,
|
||||
struct sldns_buffer *qmsg);
|
||||
|
||||
@@ -190,6 +210,7 @@ dt_msg_send_outside_response(struct dt_env *env,
|
||||
struct sockaddr_storage *rsock,
|
||||
struct sockaddr_storage *qsock,
|
||||
enum comm_point_type cptype,
|
||||
void *cpssl,
|
||||
uint8_t *zone, size_t zone_len,
|
||||
uint8_t *qbuf, size_t qbuf_len,
|
||||
const struct timeval *qtime,
|
||||
|
||||
+97
-38
@@ -5,45 +5,104 @@
|
||||
# Check for required dnstap libraries and add dnstap configure args.
|
||||
AC_DEFUN([dt_DNSTAP],
|
||||
[
|
||||
AC_ARG_ENABLE([dnstap],
|
||||
AS_HELP_STRING([--enable-dnstap],
|
||||
[Enable dnstap support (requires protobuf-c)]),
|
||||
[opt_dnstap=$enableval], [opt_dnstap=no])
|
||||
AC_ARG_ENABLE([dnstap],
|
||||
AS_HELP_STRING([--enable-dnstap],
|
||||
[Enable dnstap support (requires protobuf-c)]),
|
||||
[opt_dnstap=$enableval],
|
||||
[opt_dnstap=no])
|
||||
|
||||
AC_ARG_WITH([dnstap-socket-path],
|
||||
AS_HELP_STRING([--with-dnstap-socket-path=pathname],
|
||||
[set default dnstap socket path]),
|
||||
[opt_dnstap_socket_path=$withval], [opt_dnstap_socket_path="$1"])
|
||||
AC_ARG_WITH([dnstap-socket-path],
|
||||
AS_HELP_STRING([--with-dnstap-socket-path=pathname],
|
||||
[set default dnstap socket path]),
|
||||
[opt_dnstap_socket_path=$withval],
|
||||
[opt_dnstap_socket_path="$1"])
|
||||
|
||||
if test "x$opt_dnstap" != "xno"; then
|
||||
AC_PATH_PROG([PROTOC_C], [protoc-c])
|
||||
if test -z "$PROTOC_C"; then
|
||||
AC_MSG_ERROR([The protoc-c program was not found. Please install protobuf-c!])
|
||||
if test "x$opt_dnstap" != "xno"; then
|
||||
AC_PATH_PROG([PROTOC], [protoc])
|
||||
# 'protoc-c' is deprecated. We use 'protoc' instead. If it can not be
|
||||
# found, try 'protoc-c'.
|
||||
if test -z "$PROTOC"; then
|
||||
AC_PATH_PROG([PROTOC_C], [protoc-c])
|
||||
else
|
||||
PROTOC_C="$PROTOC"
|
||||
fi
|
||||
if test -z "$PROTOC_C"; then
|
||||
AC_MSG_ERROR([[The protoc or protoc-c program was not found. It is needed for dnstap, use --disable-dnstap, or install protobuf-c to provide protoc or protoc-c]])
|
||||
fi
|
||||
|
||||
# Check for protoc-gen-c plugin
|
||||
AC_PATH_PROG([PROTOC_GEN_C], [protoc-gen-c])
|
||||
if test -z "$PROTOC_GEN_C"; then
|
||||
AC_MSG_ERROR([[The protoc-gen-c plugin was not found. It is needed for dnstap, use --disable-dnstap, or install protobuf-c-compiler to provide protoc-gen-c]])
|
||||
fi
|
||||
|
||||
# Test that protoc-gen-c actually works
|
||||
AC_MSG_CHECKING([if protoc-gen-c plugin works])
|
||||
cat > conftest.proto << EOF
|
||||
syntax = "proto2";
|
||||
message TestMessage {
|
||||
optional string test_field = 1;
|
||||
}
|
||||
EOF
|
||||
if $PROTOC_C --c_out=. conftest.proto >/dev/null 2>&1; then
|
||||
AC_MSG_RESULT([yes])
|
||||
rm -f conftest.proto conftest.pb-c.c conftest.pb-c.h
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
rm -f conftest.proto conftest.pb-c.c conftest.pb-c.h
|
||||
AC_MSG_ERROR([[The protoc-gen-c plugin is not working properly. Please ensure protobuf-c-compiler is properly installed]])
|
||||
fi
|
||||
|
||||
AC_ARG_WITH([protobuf-c],
|
||||
AS_HELP_STRING([--with-protobuf-c=path], [Path where protobuf-c is installed, for dnstap]),
|
||||
[
|
||||
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
|
||||
if test -f $withval/include/google/protobuf-c/protobuf-c.h; then
|
||||
CFLAGS="$CFLAGS -I$withval/include/google"
|
||||
else
|
||||
CFLAGS="$CFLAGS -I$withval/include"
|
||||
fi
|
||||
LDFLAGS="$LDFLAGS -L$withval/lib"
|
||||
],
|
||||
[
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
PKG_CHECK_MODULES([PROTOBUFC], [libprotobuf-c],
|
||||
[
|
||||
CFLAGS="$CFLAGS $PROTOBUFC_CFLAGS"
|
||||
LIBS="$LIBS $PROTOBUFC_LIBS"
|
||||
],
|
||||
[
|
||||
# pkg-config failed; try falling back to known values
|
||||
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
|
||||
if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
|
||||
CFLAGS="$CFLAGS -I/usr/include/google"
|
||||
else
|
||||
if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
|
||||
CFLAGS="$CFLAGS -I/usr/local/include/google"
|
||||
LDFLAGS="$LDFLAGS -L/usr/local/lib"
|
||||
else
|
||||
AC_MSG_ERROR([The protobuf-c package was not found with pkg-config. Please install protobuf-c!])
|
||||
fi
|
||||
fi
|
||||
]
|
||||
)
|
||||
else
|
||||
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
|
||||
if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
|
||||
CFLAGS="$CFLAGS -I/usr/include/google"
|
||||
else
|
||||
if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
|
||||
CFLAGS="$CFLAGS -I/usr/local/include/google"
|
||||
LDFLAGS="$LDFLAGS -L/usr/local/lib"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
]
|
||||
)
|
||||
AC_SEARCH_LIBS([protobuf_c_message_pack], [protobuf-c], [],
|
||||
AC_MSG_ERROR([The protobuf-c library was not found. Please install the development libraries for protobuf-c!]))
|
||||
$2
|
||||
else
|
||||
$3
|
||||
fi
|
||||
AC_ARG_WITH([protobuf-c], AS_HELP_STRING([--with-protobuf-c=path],
|
||||
[Path where protobuf-c is installed, for dnstap]), [
|
||||
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
|
||||
if test -f $withval/include/google/protobuf-c/protobuf-c.h; then
|
||||
CFLAGS="$CFLAGS -I$withval/include/google"
|
||||
else
|
||||
CFLAGS="$CFLAGS -I$withval/include"
|
||||
fi
|
||||
LDFLAGS="$LDFLAGS -L$withval/lib"
|
||||
], [
|
||||
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
|
||||
if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
|
||||
CFLAGS="$CFLAGS -I/usr/include/google"
|
||||
else
|
||||
if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
|
||||
CFLAGS="$CFLAGS -I/usr/local/include/google"
|
||||
LDFLAGS="$LDFLAGS -L/usr/local/lib"
|
||||
fi
|
||||
fi
|
||||
])
|
||||
AC_SEARCH_LIBS([protobuf_c_message_pack], [protobuf-c], [],
|
||||
AC_MSG_ERROR([The protobuf-c library was not found. Please install protobuf-c!]))
|
||||
$2
|
||||
else
|
||||
$3
|
||||
fi
|
||||
])
|
||||
|
||||
+75
-7
@@ -13,8 +13,8 @@
|
||||
// with this file. If not, see:
|
||||
//
|
||||
// <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
syntax = "proto2";
|
||||
|
||||
syntax = "proto2";
|
||||
package dnstap;
|
||||
|
||||
// "Dnstap": this is the top-level dnstap type, which is a "union" type that
|
||||
@@ -56,11 +56,60 @@ enum SocketFamily {
|
||||
INET6 = 2; // IPv6 (RFC 2460)
|
||||
}
|
||||
|
||||
// SocketProtocol: the transport protocol of a socket. This specifies how to
|
||||
// interpret "transport port" fields.
|
||||
// SocketProtocol: the protocol used to transport a DNS message.
|
||||
enum SocketProtocol {
|
||||
UDP = 1; // User Datagram Protocol (RFC 768)
|
||||
TCP = 2; // Transmission Control Protocol (RFC 793)
|
||||
UDP = 1; // DNS over UDP transport (RFC 1035 section 4.2.1)
|
||||
TCP = 2; // DNS over TCP transport (RFC 1035 section 4.2.2)
|
||||
DOT = 3; // DNS over TLS (RFC 7858)
|
||||
DOH = 4; // DNS over HTTPS (RFC 8484)
|
||||
DNSCryptUDP = 5; // DNSCrypt over UDP (https://dnscrypt.info/protocol)
|
||||
DNSCryptTCP = 6; // DNSCrypt over TCP (https://dnscrypt.info/protocol)
|
||||
DOQ = 7; // DNS over QUIC (RFC 9250)
|
||||
}
|
||||
|
||||
// Policy: information about any name server operator policy
|
||||
// applied to the processing of a DNS message.
|
||||
message Policy {
|
||||
|
||||
// Match: what aspect of the message or message exchange
|
||||
// triggered the application of the Policy.
|
||||
enum Match {
|
||||
QNAME = 1; // Name in question section of query
|
||||
CLIENT_IP = 2; // Client IP address
|
||||
RESPONSE_IP = 3; // Address in A/AAAA RRSet
|
||||
NS_NAME = 4; // Authoritative name server, by name
|
||||
NS_IP = 5; // Authoritative name server, by IP address
|
||||
}
|
||||
|
||||
// The Action taken to implement the Policy.
|
||||
enum Action {
|
||||
NXDOMAIN = 1; // Respond with NXDOMAIN
|
||||
NODATA = 2; // Respond with empty answer section
|
||||
PASS = 3; // Do not alter the response (passthrough)
|
||||
DROP = 4; // Do not respond.
|
||||
TRUNCATE = 5; // Truncate UDP response, forcing TCP retry
|
||||
LOCAL_DATA = 6; // Respond with local data from policy
|
||||
}
|
||||
|
||||
// type: the type of policy applied, e.g. "RPZ" for a
|
||||
// policy from a Response Policy Zone.
|
||||
optional string type = 1;
|
||||
|
||||
// rule: the rule matched by the message.
|
||||
//
|
||||
// In a RPZ context, this is the owner name of the rule in
|
||||
// the Response Policy Zone in wire format.
|
||||
optional bytes rule = 2;
|
||||
|
||||
// action: the policy action taken in response to the
|
||||
// rule match.
|
||||
optional Action action = 3;
|
||||
|
||||
// match: the feature of the message exchange which matched the rule.
|
||||
optional Match match = 4;
|
||||
|
||||
// The matched value. Format depends on the matched feature .
|
||||
optional bytes value = 5;
|
||||
}
|
||||
|
||||
// Message: a wire-format (RFC 1035 section 4) DNS message and associated
|
||||
@@ -158,6 +207,24 @@ message Message {
|
||||
// STUB_RESPONSE is a DNS response message sent from a DNS server to a
|
||||
// stub resolver, from the perspective of the stub resolver.
|
||||
STUB_RESPONSE = 10;
|
||||
|
||||
// TOOL_QUERY is a DNS query message sent from a DNS software tool to a
|
||||
// DNS server, from the perspective of the tool.
|
||||
TOOL_QUERY = 11;
|
||||
|
||||
// TOOL_RESPONSE is a DNS response message received by a DNS software
|
||||
// tool from a DNS server, from the perspective of the tool.
|
||||
TOOL_RESPONSE = 12;
|
||||
|
||||
// UPDATE_QUERY is a Dynamic DNS Update request (RFC 2136) received
|
||||
// by an authoritative name server, from the perspective of the
|
||||
// authoritative name server.
|
||||
UPDATE_QUERY = 13;
|
||||
|
||||
// UPDATE_RESPONSE is a Dynamic DNS Update response (RFC 2136) sent
|
||||
// from an authoritative name server, from the perspective of the
|
||||
// authoritative name server.
|
||||
UPDATE_RESPONSE = 14;
|
||||
}
|
||||
|
||||
// One of the Type values described above.
|
||||
@@ -215,6 +282,9 @@ message Message {
|
||||
|
||||
// The responder's original wire-format DNS response message, verbatim.
|
||||
optional bytes response_message = 14;
|
||||
|
||||
// Operator policy applied to the processing of this message, if any.
|
||||
optional Policy policy = 15;
|
||||
}
|
||||
|
||||
// All fields except for 'type' in the Message schema are optional.
|
||||
@@ -236,7 +306,6 @@ message Message {
|
||||
|
||||
// RESOLVER_QUERY:
|
||||
// socket_family, socket_protocol
|
||||
// query_name, query_type, query_class
|
||||
// query_message
|
||||
// query_time_sec, query_time_nsec
|
||||
// query_zone
|
||||
@@ -244,7 +313,6 @@ message Message {
|
||||
|
||||
// RESOLVER_RESPONSE:
|
||||
// socket_family, socket_protocol
|
||||
// query_name, query_type, query_class
|
||||
// query_time_sec, query_time_nsec
|
||||
// query_zone
|
||||
// response_address, response_port
|
||||
|
||||
+85
-29
@@ -176,10 +176,7 @@ void
|
||||
mq_wakeup_cb(void* arg)
|
||||
{
|
||||
struct dt_msg_queue* mq = (struct dt_msg_queue*)arg;
|
||||
/* even if the dtio is already active, because perhaps much
|
||||
* traffic suddenly, we leave the timer running to save on
|
||||
* managing it, the once a second timer is less work then
|
||||
* starting and stopping the timer frequently */
|
||||
|
||||
lock_basic_lock(&mq->dtio->wakeup_timer_lock);
|
||||
mq->dtio->wakeup_timer_enabled = 0;
|
||||
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
|
||||
@@ -188,9 +185,9 @@ mq_wakeup_cb(void* arg)
|
||||
|
||||
/** start timer to wakeup dtio because there is content in the queue */
|
||||
static void
|
||||
dt_msg_queue_start_timer(struct dt_msg_queue* mq)
|
||||
dt_msg_queue_start_timer(struct dt_msg_queue* mq, int wakeupnow)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct timeval tv = {0};
|
||||
/* Start a timer to process messages to be logged.
|
||||
* If we woke up the dtio thread for every message, the wakeup
|
||||
* messages take up too much processing power. If the queue
|
||||
@@ -204,19 +201,34 @@ dt_msg_queue_start_timer(struct dt_msg_queue* mq)
|
||||
|
||||
/* do not start the timer if a timer already exists, perhaps
|
||||
* in another worker. So this variable is protected by a lock in
|
||||
* dtio */
|
||||
* dtio. */
|
||||
|
||||
/* If we need to wakeupnow, 0 the timer to force the callback. */
|
||||
lock_basic_lock(&mq->dtio->wakeup_timer_lock);
|
||||
if(mq->dtio->wakeup_timer_enabled) {
|
||||
if(wakeupnow) {
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
comm_timer_set(mq->wakeup_timer, &tv);
|
||||
}
|
||||
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
|
||||
return;
|
||||
}
|
||||
mq->dtio->wakeup_timer_enabled = 1; /* we are going to start one */
|
||||
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
|
||||
|
||||
/* start the timer, in mq, in the event base of our worker */
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
comm_timer_set(mq->wakeup_timer, &tv);
|
||||
if(!wakeupnow) {
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
/* If it is already set, keep it running. */
|
||||
if(!comm_timer_is_set(mq->wakeup_timer))
|
||||
comm_timer_set(mq->wakeup_timer, &tv);
|
||||
} else {
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
comm_timer_set(mq->wakeup_timer, &tv);
|
||||
}
|
||||
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -251,10 +263,11 @@ dt_msg_queue_submit(struct dt_msg_queue* mq, void* buf, size_t len)
|
||||
entry->buf = buf;
|
||||
entry->len = len;
|
||||
|
||||
/* aqcuire lock */
|
||||
/* acquire lock */
|
||||
lock_basic_lock(&mq->lock);
|
||||
/* if list was empty, start timer for (eventual) wakeup */
|
||||
if(mq->first == NULL)
|
||||
/* if list was empty, start timer for (eventual) wakeup,
|
||||
* or if dtio is not writing now an eventual wakeup is needed. */
|
||||
if(mq->first == NULL || !mq->dtio->event_added_is_write)
|
||||
wakeupstarttimer = 1;
|
||||
/* if list contains more than wakeupnum elements, wakeup now,
|
||||
* or if list is (going to be) almost full */
|
||||
@@ -283,10 +296,8 @@ dt_msg_queue_submit(struct dt_msg_queue* mq, void* buf, size_t len)
|
||||
/* release lock */
|
||||
lock_basic_unlock(&mq->lock);
|
||||
|
||||
if(wakeupnow) {
|
||||
dtio_wakeup(mq->dtio);
|
||||
} else if(wakeupstarttimer) {
|
||||
dt_msg_queue_start_timer(mq);
|
||||
if(wakeupnow || wakeupstarttimer) {
|
||||
dt_msg_queue_start_timer(mq, wakeupnow);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,6 +448,9 @@ int dt_io_thread_apply_cfg(struct dt_io_thread* dtio, struct config_file *cfg)
|
||||
dtio->tls_use_sni = cfg->tls_use_sni;
|
||||
#endif /* HAVE_SSL */
|
||||
}
|
||||
#ifdef HAVE_GETTID
|
||||
dtio->thread_tid_log = cfg->log_thread_id;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -783,7 +797,7 @@ static int dtio_write_ssl(struct dt_io_thread* dtio, uint8_t* buf,
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
log_crypto_err("dnstap io, could not SSL_write");
|
||||
log_crypto_err_io("dnstap io, could not SSL_write", want);
|
||||
return -1;
|
||||
}
|
||||
return r;
|
||||
@@ -930,7 +944,7 @@ static int dtio_write_more_of_data(struct dt_io_thread* dtio)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** write more of the current messsage. false if incomplete, true if
|
||||
/** write more of the current message. false if incomplete, true if
|
||||
* the message is done */
|
||||
static int dtio_write_more(struct dt_io_thread* dtio)
|
||||
{
|
||||
@@ -949,7 +963,7 @@ static int dtio_write_more(struct dt_io_thread* dtio)
|
||||
* -1: continue, >0: number of bytes read into buffer */
|
||||
static ssize_t receive_bytes(struct dt_io_thread* dtio, void* buf, size_t len) {
|
||||
ssize_t r;
|
||||
r = recv(dtio->fd, (void*)buf, len, 0);
|
||||
r = recv(dtio->fd, (void*)buf, len, MSG_DONTWAIT);
|
||||
if(r == -1) {
|
||||
char* to = dtio->socket_path;
|
||||
if(!to) to = dtio->ip_str;
|
||||
@@ -1024,7 +1038,7 @@ static int ssl_read_bytes(struct dt_io_thread* dtio, void* buf, size_t len)
|
||||
"other side");
|
||||
return 0;
|
||||
}
|
||||
log_crypto_err("could not SSL_read");
|
||||
log_crypto_err_io("could not SSL_read", want);
|
||||
verbose(VERB_DETAIL, "dnstap io: output closed by the "
|
||||
"other side");
|
||||
return 0;
|
||||
@@ -1181,7 +1195,7 @@ static int dtio_read_accept_frame(struct dt_io_thread* dtio)
|
||||
goto close_connection;
|
||||
return 1;
|
||||
} else {
|
||||
/* unknow content type */
|
||||
/* unknown content type */
|
||||
verbose(VERB_ALGO, "dnstap: ACCEPT frame "
|
||||
"contains unknown content type, "
|
||||
"closing connection");
|
||||
@@ -1254,6 +1268,13 @@ static void dtio_sleep(struct dt_io_thread* dtio)
|
||||
/* unregister the event polling for write, because there is
|
||||
* nothing to be written */
|
||||
(void)dtio_add_output_event_read(dtio);
|
||||
|
||||
/* Set wakeuptimer enabled off; so that the next worker thread that
|
||||
* wants to log starts a timer if needed, since the writer thread
|
||||
* has gone to sleep. */
|
||||
lock_basic_lock(&dtio->wakeup_timer_lock);
|
||||
dtio->wakeup_timer_enabled = 0;
|
||||
lock_basic_unlock(&dtio->wakeup_timer_lock);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
@@ -1317,7 +1338,11 @@ static int dtio_ssl_check_peer(struct dt_io_thread* dtio)
|
||||
if((SSL_get_verify_mode(dtio->ssl)&SSL_VERIFY_PEER)) {
|
||||
/* verification */
|
||||
if(SSL_get_verify_result(dtio->ssl) == X509_V_OK) {
|
||||
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
||||
X509* x = SSL_get1_peer_certificate(dtio->ssl);
|
||||
#else
|
||||
X509* x = SSL_get_peer_certificate(dtio->ssl);
|
||||
#endif
|
||||
if(!x) {
|
||||
verbose(VERB_ALGO, "dnstap io, %s, SSL "
|
||||
"connection failed no certificate",
|
||||
@@ -1342,7 +1367,11 @@ static int dtio_ssl_check_peer(struct dt_io_thread* dtio)
|
||||
#endif
|
||||
X509_free(x);
|
||||
} else {
|
||||
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
||||
X509* x = SSL_get1_peer_certificate(dtio->ssl);
|
||||
#else
|
||||
X509* x = SSL_get_peer_certificate(dtio->ssl);
|
||||
#endif
|
||||
if(x) {
|
||||
log_cert(VERB_ALGO, "dnstap io, peer "
|
||||
"certificate", x);
|
||||
@@ -1426,8 +1455,8 @@ static int dtio_ssl_handshake(struct dt_io_thread* dtio,
|
||||
} else {
|
||||
unsigned long err = ERR_get_error();
|
||||
if(!squelch_err_ssl_handshake(err)) {
|
||||
log_crypto_err_code("dnstap io, ssl handshake failed",
|
||||
err);
|
||||
log_crypto_err_io_code("dnstap io, ssl handshake failed",
|
||||
want, err);
|
||||
verbose(VERB_OPS, "dnstap io, ssl handshake failed "
|
||||
"from %s", dtio->ip_str);
|
||||
}
|
||||
@@ -1483,9 +1512,11 @@ void dtio_output_cb(int ATTR_UNUSED(fd), short bits, void* arg)
|
||||
}
|
||||
#endif
|
||||
|
||||
if((bits&UB_EV_READ || dtio->ssl_brief_write)) {
|
||||
if((bits&UB_EV_READ) || dtio->ssl_brief_write) {
|
||||
#ifdef HAVE_SSL
|
||||
if(dtio->ssl_brief_write)
|
||||
(void)dtio_disable_brief_write(dtio);
|
||||
#endif
|
||||
if(dtio->ready_frame_sent && !dtio->accept_frame_received) {
|
||||
if(dtio_read_accept_frame(dtio) <= 0)
|
||||
return;
|
||||
@@ -1508,8 +1539,22 @@ void dtio_output_cb(int ATTR_UNUSED(fd), short bits, void* arg)
|
||||
/* no messages on the first iteration,
|
||||
* the queues are all empty */
|
||||
dtio_sleep(dtio);
|
||||
/* After putting to sleep, see if
|
||||
* a message is in a message queue,
|
||||
* if so, resume service. Stops a
|
||||
* race condition where a thread could
|
||||
* have one message but the dtio
|
||||
* also just went to sleep. With the
|
||||
* message queued between the
|
||||
* dtio_find_msg and dtio_sleep
|
||||
* calls. */
|
||||
if(dtio_find_msg(dtio)) {
|
||||
if(!dtio_add_output_event_write(dtio))
|
||||
return;
|
||||
}
|
||||
}
|
||||
return; /* nothing to do */
|
||||
if(!dtio->cur_msg)
|
||||
return; /* nothing to do */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1955,7 +2000,7 @@ static int dtio_open_output_tcp(struct dt_io_thread* dtio)
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addrlen = (socklen_t)sizeof(addr);
|
||||
|
||||
if(!extstrtoaddr(dtio->ip_str, &addr, &addrlen)) {
|
||||
if(!extstrtoaddr(dtio->ip_str, &addr, &addrlen, UNBOUND_DNS_PORT)) {
|
||||
log_err("could not parse IP '%s'", dtio->ip_str);
|
||||
return 0;
|
||||
}
|
||||
@@ -2088,7 +2133,18 @@ static void* dnstap_io(void* arg)
|
||||
struct dt_io_thread* dtio = (struct dt_io_thread*)arg;
|
||||
time_t secs = 0;
|
||||
struct timeval now;
|
||||
log_thread_set(&dtio->threadnum);
|
||||
const char name[16] = "unbound/dnstap"; /* seems to be the safest size
|
||||
between different OSes */
|
||||
|
||||
#if defined(HAVE_GETTID) && !defined(THREADS_DISABLED)
|
||||
dtio->thread_tid = gettid();
|
||||
if(dtio->thread_tid_log)
|
||||
log_thread_set(&dtio->thread_tid);
|
||||
else
|
||||
#endif
|
||||
log_thread_set(&dtio->threadnum);
|
||||
|
||||
ub_thread_setname(ub_thread_self(), name);
|
||||
|
||||
/* setup */
|
||||
verbose(VERB_ALGO, "start dnstap io thread");
|
||||
|
||||
@@ -131,6 +131,12 @@ struct dt_io_thread {
|
||||
struct dt_io_list_item* io_list_iter;
|
||||
/** thread id, of the io thread */
|
||||
ub_thread_type tid;
|
||||
#ifdef HAVE_GETTID
|
||||
/** thread tid, the LWP id */
|
||||
pid_t thread_tid;
|
||||
/** if logging should include the LWP id */
|
||||
int thread_tid_log;
|
||||
#endif
|
||||
/** if the io processing has started */
|
||||
int started;
|
||||
/** ssl context for the io thread, for tls connections. type SSL_CTX* */
|
||||
|
||||
+355
-73
@@ -61,6 +61,7 @@
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#include "sldns/pkthdr.h"
|
||||
#ifdef USE_DNSTAP
|
||||
#include <protobuf-c/protobuf-c.h>
|
||||
#include "dnstap/dnstap.pb-c.h"
|
||||
@@ -74,17 +75,18 @@
|
||||
static void usage(char* argv[])
|
||||
{
|
||||
printf("usage: %s [options]\n", argv[0]);
|
||||
printf(" Listen to dnstap messages\n");
|
||||
printf(" Listen to dnstap messages\n");
|
||||
printf("stdout has dnstap log, stderr has verbose server log\n");
|
||||
printf("-u <socketpath> listen to unix socket with this file name\n");
|
||||
printf("-s <serverip[@port]> listen for TCP on the IP and port\n");
|
||||
printf("-t <serverip[@port]> listen for TLS on IP and port\n");
|
||||
printf("-x <server.key> server key file for TLS service\n");
|
||||
printf("-y <server.pem> server cert file for TLS service\n");
|
||||
printf("-z <verify.pem> cert file to verify client connections\n");
|
||||
printf("-l long format for DNS printout\n");
|
||||
printf("-v more verbose log output\n");
|
||||
printf("-h this help text\n");
|
||||
printf("-u <socketpath> listen to unix socket with this file name\n");
|
||||
printf("-s <serverip[@port]> listen for TCP on the IP and port\n");
|
||||
printf("-t <serverip[@port]> listen for TLS on IP and port\n");
|
||||
printf("-x <server.key> server key file for TLS service\n");
|
||||
printf("-y <server.pem> server cert file for TLS service\n");
|
||||
printf("-z <verify.pem> cert file to verify client connections\n");
|
||||
printf("-l long format for DNS printout\n");
|
||||
printf("-v more verbose log output\n");
|
||||
printf("-c internal unit test and exit\n");
|
||||
printf("-h this help text\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -101,6 +103,14 @@ struct main_tap_data {
|
||||
struct tap_socket_list* acceptlist;
|
||||
};
|
||||
|
||||
/* list of data */
|
||||
struct tap_data_list {
|
||||
/** next in list */
|
||||
struct tap_data_list* next;
|
||||
/** the data */
|
||||
struct tap_data* d;
|
||||
};
|
||||
|
||||
/** tap callback variables */
|
||||
struct tap_data {
|
||||
/** the fd */
|
||||
@@ -127,6 +137,10 @@ struct tap_data {
|
||||
uint8_t* frame;
|
||||
/** length of this frame */
|
||||
size_t len;
|
||||
/** back pointer to the tap_data_list entry;
|
||||
* used to NULL the forward pointer to this data
|
||||
* when this data is freed. */
|
||||
struct tap_data_list* data_list;
|
||||
};
|
||||
|
||||
/** list of sockets */
|
||||
@@ -155,8 +169,89 @@ struct tap_socket {
|
||||
char* ip;
|
||||
/** for a TLS socket, the tls context */
|
||||
SSL_CTX* sslctx;
|
||||
/** dumb way to deal with memory leaks:
|
||||
* tap_data was only freed on errors and not during exit leading to
|
||||
* false positives when testing for memory leaks. */
|
||||
struct tap_data_list* data_list;
|
||||
};
|
||||
|
||||
/** try to delete tail entries from the list if all of them have no data */
|
||||
static void tap_data_list_try_to_free_tail(struct tap_data_list* list)
|
||||
{
|
||||
struct tap_data_list* current = list;
|
||||
log_assert(!list->d);
|
||||
if(!list->next) /* we are the last, we can't remove ourselves */
|
||||
return;
|
||||
list = list->next;
|
||||
while(list) {
|
||||
if(list->d) /* a tail entry still has data; return */
|
||||
return;
|
||||
list = list->next;
|
||||
}
|
||||
/* keep the next */
|
||||
list = current->next;
|
||||
/* the tail will be removed; but not ourselves */
|
||||
current->next = NULL;
|
||||
while(list) {
|
||||
current = list;
|
||||
list = list->next;
|
||||
free(current);
|
||||
}
|
||||
}
|
||||
|
||||
/** delete the tap structure */
|
||||
static void tap_data_free(struct tap_data* data, int free_tail)
|
||||
{
|
||||
if(!data)
|
||||
return;
|
||||
if(data->ev) {
|
||||
ub_event_del(data->ev);
|
||||
ub_event_free(data->ev);
|
||||
}
|
||||
#ifdef HAVE_SSL
|
||||
SSL_free(data->ssl);
|
||||
#endif
|
||||
sock_close(data->fd);
|
||||
free(data->id);
|
||||
free(data->frame);
|
||||
if(data->data_list) {
|
||||
data->data_list->d = NULL;
|
||||
if(free_tail)
|
||||
tap_data_list_try_to_free_tail(data->data_list);
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
|
||||
/** insert tap_data in the tap_data_list */
|
||||
static int tap_data_list_insert(struct tap_data_list** liststart,
|
||||
struct tap_data* d)
|
||||
{
|
||||
struct tap_data_list* entry = (struct tap_data_list*)
|
||||
malloc(sizeof(*entry));
|
||||
if(!entry)
|
||||
return 0;
|
||||
entry->next = *liststart;
|
||||
entry->d = d;
|
||||
d->data_list = entry;
|
||||
*liststart = entry;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** delete the tap_data_list and free any remaining tap_data */
|
||||
static void tap_data_list_delete(struct tap_data_list* list)
|
||||
{
|
||||
struct tap_data_list* e = list, *next;
|
||||
while(e) {
|
||||
next = e->next;
|
||||
if(e->d) {
|
||||
tap_data_free(e->d, 0);
|
||||
e->d = NULL;
|
||||
}
|
||||
free(e);
|
||||
e = next;
|
||||
}
|
||||
}
|
||||
|
||||
/** del the tap event */
|
||||
static void tap_socket_delev(struct tap_socket* s)
|
||||
{
|
||||
@@ -172,7 +267,7 @@ static void tap_socket_close(struct tap_socket* s)
|
||||
{
|
||||
if(!s) return;
|
||||
if(s->fd == -1) return;
|
||||
close(s->fd);
|
||||
sock_close(s->fd);
|
||||
s->fd = -1;
|
||||
}
|
||||
|
||||
@@ -183,6 +278,7 @@ static void tap_socket_delete(struct tap_socket* s)
|
||||
#ifdef HAVE_SSL
|
||||
SSL_CTX_free(s->sslctx);
|
||||
#endif
|
||||
tap_data_list_delete(s->data_list);
|
||||
ub_event_free(s->ev);
|
||||
free(s->socketpath);
|
||||
free(s->ip);
|
||||
@@ -234,7 +330,7 @@ static struct tap_socket* tap_socket_new_tcpaccept(char* ip,
|
||||
/** create new socket (unconnected, not base-added), or NULL malloc fail */
|
||||
static struct tap_socket* tap_socket_new_tlsaccept(char* ip,
|
||||
void (*ev_cb)(int, short, void*), void* data, char* server_key,
|
||||
char* server_cert, char* verifypem)
|
||||
char* server_cert, char* verifypem, char* tls_protocols)
|
||||
{
|
||||
struct tap_socket* s = calloc(1, sizeof(*s));
|
||||
if(!s) {
|
||||
@@ -250,7 +346,8 @@ static struct tap_socket* tap_socket_new_tlsaccept(char* ip,
|
||||
s->fd = -1;
|
||||
s->ev_cb = ev_cb;
|
||||
s->data = data;
|
||||
s->sslctx = listen_sslctx_create(server_key, server_cert, verifypem);
|
||||
s->sslctx = listen_sslctx_create(server_key, server_cert, verifypem,
|
||||
NULL, NULL, 0, 0, 0, tls_protocols);
|
||||
if(!s->sslctx) {
|
||||
log_err("could not create ssl context");
|
||||
free(s->ip);
|
||||
@@ -272,7 +369,7 @@ static int make_tcp_accept(char* ip)
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
len = (socklen_t)sizeof(addr);
|
||||
if(!extstrtoaddr(ip, &addr, &len)) {
|
||||
if(!extstrtoaddr(ip, &addr, &len, UNBOUND_DNS_PORT)) {
|
||||
log_err("could not parse IP '%s'", ip);
|
||||
return -1;
|
||||
}
|
||||
@@ -448,6 +545,7 @@ static char* q_of_msg(ProtobufCBinaryData message)
|
||||
char buf[300];
|
||||
/* header, name, type, class minimum to get the query tuple */
|
||||
if(message.len < 12 + 1 + 4 + 4) return NULL;
|
||||
if(LDNS_QDCOUNT(message.data) < 1) return NULL;
|
||||
if(sldns_wire2str_rrquestion_buf(message.data+12, message.len-12,
|
||||
buf, sizeof(buf)) != 0) {
|
||||
/* remove trailing newline, tabs to spaces */
|
||||
@@ -502,7 +600,7 @@ static char* tv_to_str(protobuf_c_boolean has_time_sec, uint64_t time_sec,
|
||||
time_t time_t_sec;
|
||||
memset(&tv, 0, sizeof(tv));
|
||||
if(has_time_sec) tv.tv_sec = time_sec;
|
||||
if(has_time_nsec) tv.tv_usec = time_nsec;
|
||||
if(has_time_nsec) tv.tv_usec = time_nsec/1000;
|
||||
|
||||
buf[0]=0;
|
||||
time_t_sec = tv.tv_sec;
|
||||
@@ -617,7 +715,7 @@ static void log_data_frame(uint8_t* pkt, size_t len)
|
||||
static ssize_t receive_bytes(struct tap_data* data, int fd, void* buf,
|
||||
size_t len)
|
||||
{
|
||||
ssize_t ret = recv(fd, buf, len, 0);
|
||||
ssize_t ret = recv(fd, buf, len, MSG_DONTWAIT);
|
||||
if(ret == 0) {
|
||||
/* closed */
|
||||
if(verbosity) log_info("dnstap client stream closed from %s",
|
||||
@@ -706,7 +804,7 @@ static ssize_t ssl_read_bytes(struct tap_data* data, void* buf, size_t len)
|
||||
(data->id?data->id:""));
|
||||
return 0;
|
||||
}
|
||||
log_crypto_err("could not SSL_read");
|
||||
log_crypto_err_io("could not SSL_read", want);
|
||||
if(verbosity) log_info("dnstap client stream closed from %s",
|
||||
(data->id?data->id:""));
|
||||
return 0;
|
||||
@@ -726,27 +824,12 @@ static ssize_t tap_receive(struct tap_data* data, void* buf, size_t len)
|
||||
return receive_bytes(data, data->fd, buf, len);
|
||||
}
|
||||
|
||||
/** delete the tap structure */
|
||||
static void tap_data_free(struct tap_data* data)
|
||||
{
|
||||
ub_event_del(data->ev);
|
||||
ub_event_free(data->ev);
|
||||
#ifdef HAVE_SSL
|
||||
SSL_free(data->ssl);
|
||||
#endif
|
||||
close(data->fd);
|
||||
free(data->id);
|
||||
free(data->frame);
|
||||
free(data);
|
||||
}
|
||||
|
||||
/** reply with ACCEPT control frame to bidirectional client,
|
||||
* returns 0 on error */
|
||||
static int reply_with_accept(struct tap_data* data)
|
||||
{
|
||||
#ifdef USE_DNSTAP
|
||||
/* len includes the escape and framelength */
|
||||
int r;
|
||||
size_t len = 0;
|
||||
void* acceptframe = fstrm_create_control_frame_accept(
|
||||
DNSTAP_CONTENT_TYPE, &len);
|
||||
@@ -757,15 +840,19 @@ static int reply_with_accept(struct tap_data* data)
|
||||
|
||||
fd_set_block(data->fd);
|
||||
if(data->ssl) {
|
||||
#ifdef HAVE_SSL
|
||||
int r;
|
||||
if((r=SSL_write(data->ssl, acceptframe, len)) <= 0) {
|
||||
if(SSL_get_error(data->ssl, r) == SSL_ERROR_ZERO_RETURN)
|
||||
int r2;
|
||||
if((r2=SSL_get_error(data->ssl, r)) == SSL_ERROR_ZERO_RETURN)
|
||||
log_err("SSL_write, peer closed connection");
|
||||
else
|
||||
log_err("could not SSL_write");
|
||||
log_crypto_err_io("could not SSL_write", r2);
|
||||
fd_set_nonblock(data->fd);
|
||||
free(acceptframe);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if(send(data->fd, acceptframe, len, 0) == -1) {
|
||||
log_err("send failed: %s", sock_strerror(errno));
|
||||
@@ -789,7 +876,7 @@ static int reply_with_accept(struct tap_data* data)
|
||||
|
||||
/** reply with FINISH control frame to bidirectional client,
|
||||
* returns 0 on error */
|
||||
static int reply_with_finish(int fd)
|
||||
static int reply_with_finish(struct tap_data* data)
|
||||
{
|
||||
#ifdef USE_DNSTAP
|
||||
size_t len = 0;
|
||||
@@ -799,21 +886,37 @@ static int reply_with_finish(int fd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd_set_block(fd);
|
||||
if(send(fd, finishframe, len, 0) == -1) {
|
||||
log_err("send failed: %s", sock_strerror(errno));
|
||||
fd_set_nonblock(fd);
|
||||
free(finishframe);
|
||||
return 0;
|
||||
fd_set_block(data->fd);
|
||||
if(data->ssl) {
|
||||
#ifdef HAVE_SSL
|
||||
int r;
|
||||
if((r=SSL_write(data->ssl, finishframe, len)) <= 0) {
|
||||
int r2;
|
||||
if((r2=SSL_get_error(data->ssl, r)) == SSL_ERROR_ZERO_RETURN)
|
||||
log_err("SSL_write, peer closed connection");
|
||||
else
|
||||
log_crypto_err_io("could not SSL_write", r2);
|
||||
fd_set_nonblock(data->fd);
|
||||
free(finishframe);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if(send(data->fd, finishframe, len, 0) == -1) {
|
||||
log_err("send failed: %s", sock_strerror(errno));
|
||||
fd_set_nonblock(data->fd);
|
||||
free(finishframe);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if(verbosity) log_info("sent control frame(finish)");
|
||||
|
||||
fd_set_nonblock(fd);
|
||||
fd_set_nonblock(data->fd);
|
||||
free(finishframe);
|
||||
return 1;
|
||||
#else
|
||||
log_err("no dnstap compiled, no reply");
|
||||
(void)fd;
|
||||
(void)data;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@@ -825,7 +928,11 @@ static int tap_check_peer(struct tap_data* data)
|
||||
if((SSL_get_verify_mode(data->ssl)&SSL_VERIFY_PEER)) {
|
||||
/* verification */
|
||||
if(SSL_get_verify_result(data->ssl) == X509_V_OK) {
|
||||
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
||||
X509* x = SSL_get1_peer_certificate(data->ssl);
|
||||
#else
|
||||
X509* x = SSL_get_peer_certificate(data->ssl);
|
||||
#endif
|
||||
if(!x) {
|
||||
if(verbosity) log_info("SSL connection %s"
|
||||
" failed no certificate", data->id);
|
||||
@@ -847,7 +954,11 @@ static int tap_check_peer(struct tap_data* data)
|
||||
#endif
|
||||
X509_free(x);
|
||||
} else {
|
||||
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
||||
X509* x = SSL_get1_peer_certificate(data->ssl);
|
||||
#else
|
||||
X509* x = SSL_get_peer_certificate(data->ssl);
|
||||
#endif
|
||||
if(x) {
|
||||
if(verbosity)
|
||||
log_cert(VERB_ALGO, "peer certificate", x);
|
||||
@@ -889,7 +1000,7 @@ static int tap_handshake(struct tap_data* data)
|
||||
return 0;
|
||||
} else if(r == 0) {
|
||||
/* closed */
|
||||
tap_data_free(data);
|
||||
tap_data_free(data, 1);
|
||||
return 0;
|
||||
} else if(want == SSL_ERROR_SYSCALL) {
|
||||
/* SYSCALL and errno==0 means closed uncleanly */
|
||||
@@ -907,7 +1018,7 @@ static int tap_handshake(struct tap_data* data)
|
||||
if(!silent)
|
||||
log_err("SSL_handshake syscall: %s",
|
||||
strerror(errno));
|
||||
tap_data_free(data);
|
||||
tap_data_free(data, 1);
|
||||
return 0;
|
||||
} else {
|
||||
unsigned long err = ERR_get_error();
|
||||
@@ -917,7 +1028,7 @@ static int tap_handshake(struct tap_data* data)
|
||||
verbose(VERB_OPS, "ssl handshake failed "
|
||||
"from %s", data->id);
|
||||
}
|
||||
tap_data_free(data);
|
||||
tap_data_free(data, 1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -925,7 +1036,7 @@ static int tap_handshake(struct tap_data* data)
|
||||
data->ssl_handshake_done = 1;
|
||||
if(!tap_check_peer(data)) {
|
||||
/* closed */
|
||||
tap_data_free(data);
|
||||
tap_data_free(data, 1);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -933,7 +1044,7 @@ static int tap_handshake(struct tap_data* data)
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
/** callback for dnstap listener */
|
||||
void dtio_tap_callback(int fd, short ATTR_UNUSED(bits), void* arg)
|
||||
void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg)
|
||||
{
|
||||
struct tap_data* data = (struct tap_data*)arg;
|
||||
if(verbosity>=3) log_info("tap callback");
|
||||
@@ -951,7 +1062,7 @@ void dtio_tap_callback(int fd, short ATTR_UNUSED(bits), void* arg)
|
||||
if(verbosity>=4) log_info("s recv %d", (int)ret);
|
||||
if(ret == 0) {
|
||||
/* closed or error */
|
||||
tap_data_free(data);
|
||||
tap_data_free(data, 1);
|
||||
return;
|
||||
} else if(ret == -1) {
|
||||
/* continue later */
|
||||
@@ -973,7 +1084,7 @@ void dtio_tap_callback(int fd, short ATTR_UNUSED(bits), void* arg)
|
||||
data->frame = calloc(1, data->len);
|
||||
if(!data->frame) {
|
||||
log_err("out of memory");
|
||||
tap_data_free(data);
|
||||
tap_data_free(data, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -986,7 +1097,7 @@ void dtio_tap_callback(int fd, short ATTR_UNUSED(bits), void* arg)
|
||||
if(verbosity>=4) log_info("f recv %d", (int)r);
|
||||
if(r == 0) {
|
||||
/* closed or error */
|
||||
tap_data_free(data);
|
||||
tap_data_free(data, 1);
|
||||
return;
|
||||
} else if(r == -1) {
|
||||
/* continue later */
|
||||
@@ -1011,13 +1122,13 @@ void dtio_tap_callback(int fd, short ATTR_UNUSED(bits), void* arg)
|
||||
data->is_bidirectional = 1;
|
||||
if(verbosity) log_info("bidirectional stream");
|
||||
if(!reply_with_accept(data)) {
|
||||
tap_data_free(data);
|
||||
tap_data_free(data, 1);
|
||||
return;
|
||||
}
|
||||
} else if(data->len >= 4 && sldns_read_uint32(data->frame) ==
|
||||
FSTRM_CONTROL_FRAME_STOP && data->is_bidirectional) {
|
||||
if(!reply_with_finish(fd)) {
|
||||
tap_data_free(data);
|
||||
if(!reply_with_finish(data)) {
|
||||
tap_data_free(data, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1029,7 +1140,6 @@ void dtio_tap_callback(int fd, short ATTR_UNUSED(bits), void* arg)
|
||||
data->len = 0;
|
||||
data->len_done = 0;
|
||||
data->data_done = 0;
|
||||
|
||||
}
|
||||
|
||||
/** callback for main listening file descriptor */
|
||||
@@ -1042,7 +1152,9 @@ void dtio_mainfdcallback(int fd, short ATTR_UNUSED(bits), void* arg)
|
||||
char* id = NULL;
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen = (socklen_t)sizeof(addr);
|
||||
int s = accept(fd, (struct sockaddr*)&addr, &addrlen);
|
||||
int s;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
s = accept(fd, (struct sockaddr*)&addr, &addrlen);
|
||||
if(s == -1) {
|
||||
#ifndef USE_WINSOCK
|
||||
/* EINTR is signal interrupt. others are closed connection. */
|
||||
@@ -1112,6 +1224,8 @@ void dtio_mainfdcallback(int fd, short ATTR_UNUSED(bits), void* arg)
|
||||
&dtio_tap_callback, data);
|
||||
if(!data->ev) fatal_exit("could not ub_event_new");
|
||||
if(ub_event_add(data->ev, NULL) != 0) fatal_exit("could not ub_event_add");
|
||||
if(!tap_data_list_insert(&tap_sock->data_list, data))
|
||||
fatal_exit("could not tap_data_list_insert");
|
||||
}
|
||||
|
||||
/** setup local accept sockets */
|
||||
@@ -1147,13 +1261,13 @@ static void setup_tcp_list(struct main_tap_data* maindata,
|
||||
/** setup tls accept sockets */
|
||||
static void setup_tls_list(struct main_tap_data* maindata,
|
||||
struct config_strlist_head* tls_list, char* server_key,
|
||||
char* server_cert, char* verifypem)
|
||||
char* server_cert, char* verifypem, char* tls_protocols)
|
||||
{
|
||||
struct config_strlist* item;
|
||||
for(item = tls_list->first; item; item = item->next) {
|
||||
struct tap_socket* s;
|
||||
s = tap_socket_new_tlsaccept(item->str, &dtio_mainfdcallback,
|
||||
maindata, server_key, server_cert, verifypem);
|
||||
maindata, server_key, server_cert, verifypem, tls_protocols);
|
||||
if(!s) fatal_exit("out of memory");
|
||||
if(!tap_socket_list_insert(&maindata->acceptlist, s))
|
||||
fatal_exit("out of memory");
|
||||
@@ -1186,7 +1300,7 @@ static void
|
||||
setup_and_run(struct config_strlist_head* local_list,
|
||||
struct config_strlist_head* tcp_list,
|
||||
struct config_strlist_head* tls_list, char* server_key,
|
||||
char* server_cert, char* verifypem)
|
||||
char* server_cert, char* verifypem, char* tls_protocols)
|
||||
{
|
||||
time_t secs = 0;
|
||||
struct timeval now;
|
||||
@@ -1212,7 +1326,7 @@ setup_and_run(struct config_strlist_head* local_list,
|
||||
setup_local_list(maindata, local_list);
|
||||
setup_tcp_list(maindata, tcp_list);
|
||||
setup_tls_list(maindata, tls_list, server_key, server_cert,
|
||||
verifypem);
|
||||
verifypem, tls_protocols);
|
||||
if(!tap_socket_list_addevs(maindata->acceptlist, base))
|
||||
fatal_exit("could not setup accept events");
|
||||
if(verbosity) log_info("start of service");
|
||||
@@ -1226,6 +1340,114 @@ setup_and_run(struct config_strlist_head* local_list,
|
||||
free(maindata);
|
||||
}
|
||||
|
||||
/* internal unit tests */
|
||||
static int internal_unittest()
|
||||
{
|
||||
/* unit test tap_data_list_try_to_free_tail() */
|
||||
#define unit_tap_datas_max 5
|
||||
struct tap_data* datas[unit_tap_datas_max];
|
||||
struct tap_data_list* list;
|
||||
struct tap_socket* socket = calloc(1, sizeof(*socket));
|
||||
size_t i = 0;
|
||||
log_assert(socket);
|
||||
log_assert(unit_tap_datas_max>2); /* needed for the test */
|
||||
for(i=0; i<unit_tap_datas_max; i++) {
|
||||
datas[i] = calloc(1, sizeof(struct tap_data));
|
||||
log_assert(datas[i]);
|
||||
log_assert(tap_data_list_insert(&socket->data_list, datas[i]));
|
||||
}
|
||||
/* sanity base check */
|
||||
list = socket->data_list;
|
||||
for(i=0; list; i++) list = list->next;
|
||||
log_assert(i==unit_tap_datas_max);
|
||||
|
||||
/* Free the last data, tail cannot be erased */
|
||||
list = socket->data_list;
|
||||
while(list->next) list = list->next;
|
||||
free(list->d);
|
||||
list->d = NULL;
|
||||
tap_data_list_try_to_free_tail(list);
|
||||
list = socket->data_list;
|
||||
for(i=0; list; i++) list = list->next;
|
||||
log_assert(i==unit_tap_datas_max);
|
||||
|
||||
/* Free the third to last data, tail cannot be erased */
|
||||
list = socket->data_list;
|
||||
for(i=0; i<unit_tap_datas_max-3; i++) list = list->next;
|
||||
free(list->d);
|
||||
list->d = NULL;
|
||||
tap_data_list_try_to_free_tail(list);
|
||||
list = socket->data_list;
|
||||
for(i=0; list; i++) list = list->next;
|
||||
log_assert(i==unit_tap_datas_max);
|
||||
|
||||
/* Free the second to last data, try to remove tail from the third
|
||||
* again, tail (last 2) should be removed */
|
||||
list = socket->data_list;
|
||||
for(i=0; i<unit_tap_datas_max-2; i++) list = list->next;
|
||||
free(list->d);
|
||||
list->d = NULL;
|
||||
list = socket->data_list;
|
||||
while(list->d) list = list->next;
|
||||
tap_data_list_try_to_free_tail(list);
|
||||
list = socket->data_list;
|
||||
for(i=0; list; i++) list = list->next;
|
||||
log_assert(i==unit_tap_datas_max-2);
|
||||
|
||||
/* Free all the remaining data, try to remove tail from the start,
|
||||
* only the start should remain */
|
||||
list = socket->data_list;
|
||||
while(list) {
|
||||
free(list->d);
|
||||
list->d = NULL;
|
||||
list = list->next;
|
||||
}
|
||||
tap_data_list_try_to_free_tail(socket->data_list);
|
||||
list = socket->data_list;
|
||||
for(i=0; list; i++) list = list->next;
|
||||
log_assert(i==1);
|
||||
|
||||
/* clean up */
|
||||
tap_data_list_delete(socket->data_list);
|
||||
free(socket);
|
||||
|
||||
/* Start again. Add two elements */
|
||||
socket = calloc(1, sizeof(*socket));
|
||||
log_assert(socket);
|
||||
for(i=0; i<2; i++) {
|
||||
datas[i] = calloc(1, sizeof(struct tap_data));
|
||||
log_assert(datas[i]);
|
||||
log_assert(tap_data_list_insert(&socket->data_list, datas[i]));
|
||||
}
|
||||
/* sanity base check */
|
||||
list = socket->data_list;
|
||||
for(i=0; list; i++) list = list->next;
|
||||
log_assert(i==2);
|
||||
|
||||
/* Free the last data, tail cannot be erased */
|
||||
list = socket->data_list;
|
||||
while(list->next) list = list->next;
|
||||
free(list->d);
|
||||
list->d = NULL;
|
||||
tap_data_list_try_to_free_tail(list);
|
||||
list = socket->data_list;
|
||||
for(i=0; list; i++) list = list->next;
|
||||
log_assert(i==2);
|
||||
|
||||
/* clean up */
|
||||
tap_data_list_delete(socket->data_list);
|
||||
free(socket);
|
||||
|
||||
if(log_get_lock()) {
|
||||
lock_basic_destroy((lock_basic_type*)log_get_lock());
|
||||
}
|
||||
checklock_stop();
|
||||
#ifdef USE_WINSOCK
|
||||
WSACleanup();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** getopt global, in case header files fail to declare it. */
|
||||
extern int optind;
|
||||
/** getopt global, in case header files fail to declare it. */
|
||||
@@ -1240,6 +1462,8 @@ int main(int argc, char** argv)
|
||||
struct config_strlist_head tcp_list;
|
||||
struct config_strlist_head tls_list;
|
||||
char* server_key = NULL, *server_cert = NULL, *verifypem = NULL;
|
||||
|
||||
char* tls_protocols = "TLSv1.2 TLSv1.3";
|
||||
#ifdef USE_WINSOCK
|
||||
WSADATA wsa_data;
|
||||
if(WSAStartup(MAKEWORD(2,2), &wsa_data) != 0) {
|
||||
@@ -1264,9 +1488,9 @@ int main(int argc, char** argv)
|
||||
memset(&tls_list, 0, sizeof(tls_list));
|
||||
|
||||
/* lock debug start (if any) */
|
||||
checklock_start();
|
||||
log_ident_set("unbound-dnstap-socket");
|
||||
log_init(0, 0, 0);
|
||||
checklock_start();
|
||||
|
||||
#ifdef SIGPIPE
|
||||
if(signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
|
||||
@@ -1276,7 +1500,7 @@ int main(int argc, char** argv)
|
||||
#endif
|
||||
|
||||
/* command line options */
|
||||
while( (c=getopt(argc, argv, "hls:t:u:vx:y:z:")) != -1) {
|
||||
while( (c=getopt(argc, argv, "hcls:t:u:vx:y:z:")) != -1) {
|
||||
switch(c) {
|
||||
case 'u':
|
||||
if(!cfg_strlist_append(&local_list,
|
||||
@@ -1312,14 +1536,20 @@ int main(int argc, char** argv)
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
case 'c':
|
||||
#ifndef UNBOUND_DEBUG
|
||||
fatal_exit("-c option needs compilation with "
|
||||
"--enable-debug");
|
||||
#endif
|
||||
return internal_unittest();
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
usage(argv);
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
/* argc -= optind; not using further arguments */
|
||||
/* argv += optind; not using further arguments */
|
||||
|
||||
if(usessl) {
|
||||
#ifdef HAVE_SSL
|
||||
@@ -1333,21 +1563,32 @@ int main(int argc, char** argv)
|
||||
#else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
#else
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
#endif
|
||||
#endif /* HAVE_SSL */
|
||||
}
|
||||
setup_and_run(&local_list, &tcp_list, &tls_list, server_key,
|
||||
server_cert, verifypem);
|
||||
server_cert, verifypem, tls_protocols);
|
||||
config_delstrlist(local_list.first);
|
||||
config_delstrlist(tcp_list.first);
|
||||
config_delstrlist(tls_list.first);
|
||||
|
||||
if(log_get_lock()) {
|
||||
lock_basic_destroy((lock_basic_type*)log_get_lock());
|
||||
}
|
||||
checklock_stop();
|
||||
#ifdef USE_WINSOCK
|
||||
WSACleanup();
|
||||
@@ -1413,10 +1654,13 @@ void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg))
|
||||
struct outbound_entry* worker_send_query(
|
||||
struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags),
|
||||
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
|
||||
int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
int ATTR_UNUSED(nocaps), int ATTR_UNUSED(check_ratelimit),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
||||
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(ssl_upstream),
|
||||
char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q))
|
||||
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
|
||||
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
|
||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited),
|
||||
int* ATTR_UNUSED(ratelimit_incremented))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
@@ -1445,10 +1689,13 @@ worker_alloc_cleanup(void* ATTR_UNUSED(arg))
|
||||
struct outbound_entry* libworker_send_query(
|
||||
struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags),
|
||||
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
|
||||
int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
int ATTR_UNUSED(nocaps), int ATTR_UNUSED(check_ratelimit),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
||||
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(ssl_upstream),
|
||||
char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q))
|
||||
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
|
||||
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
|
||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited),
|
||||
int* ATTR_UNUSED(ratelimit_incremented))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
@@ -1490,6 +1737,11 @@ void libworker_event_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void libworker_alloc_cleanup(void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||
{
|
||||
log_assert(0);
|
||||
@@ -1551,3 +1803,33 @@ void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void fast_reload_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
int fast_reload_client_callback(struct comm_point* ATTR_UNUSED(c),
|
||||
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
|
||||
struct comm_reply* ATTR_UNUSED(repinfo))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_NGTCP2
|
||||
void doq_client_event_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NGTCP2
|
||||
void doq_client_timer_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
+3586
-19
File diff suppressed because it is too large
Load Diff
+4
-5
@@ -19,11 +19,10 @@ The DNSTAP code has BSD license in dnstap/dnstap.c.
|
||||
* Make and install: ./configure; make; make install
|
||||
* --with-libevent=/path/to/libevent
|
||||
Can be set to either the system install or the build directory.
|
||||
--with-libevent=no (default) gives a builtin alternative
|
||||
implementation. libevent is useful when having many (thousands)
|
||||
of outgoing ports. This improves randomization and spoof
|
||||
resistance. For the default of 16 ports the builtin alternative
|
||||
works well and is a little faster.
|
||||
--with-libevent=no gives a builtin alternative implementation.
|
||||
Libevent is enabled by default, it is useful when having many
|
||||
(thousands) of outgoing ports. This improves randomization and spoof
|
||||
resistance. It also allows a higher number of outgoing queries.
|
||||
* --with-libexpat=/path/to/libexpat
|
||||
Can be set to the install directory of libexpat.
|
||||
* --without-pthreads
|
||||
|
||||
+21
-1
@@ -13,7 +13,7 @@ If you're not using DNSSEC then you may remove "validator".
|
||||
|
||||
2. The "dns64-prefix" directive indicates your DNS64 prefix. For example:
|
||||
|
||||
dns64-prefix: 64:FF9B::/96
|
||||
dns64-prefix: 64:ff9b::/96
|
||||
|
||||
The prefix must be a /96 or shorter.
|
||||
|
||||
@@ -28,3 +28,23 @@ prefix. For example:
|
||||
;; ANSWER SECTION:
|
||||
jazz-v4.viagenie.ca. 86400 IN AAAA 64:ff9b::ce7b:1f02
|
||||
|
||||
|
||||
NAT64 support was added by David Lamparter in 2022; license(s) of the
|
||||
surrounding code apply. Note that NAT64 is closely related but functionally
|
||||
orthogonal to DNS64; it allows Unbound to send outgoing queries to IPv4-only
|
||||
servers over IPv6 through the configured NAT64 prefix. This allows running
|
||||
an Unbound instance on an IPv6-only host without breaking every single domain
|
||||
that only has IPv4 servers. Whether that Unbound instance also does DNS64 is
|
||||
an independent choice.
|
||||
|
||||
To enable NAT64 in Unbound, add to unbound.conf's "server" section:
|
||||
|
||||
do-nat64: yes
|
||||
|
||||
The NAT64 prefix defaults to the DNS64 prefix, which in turn defaults to the
|
||||
standard 64:ff9b::/96 prefix. You can reconfigure it with:
|
||||
|
||||
nat64-prefix: 64:ff9b::/96
|
||||
|
||||
To test NAT64 operation, pick a domain that only has IPv4 reachability for its
|
||||
nameservers and try resolving any names in that domain.
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
After Unbound 1.23.0, the source of the man pages is in reStructuredText format.
|
||||
|
||||
This helps with the online documentation at https://unbound.docs.nlnetlabs.nl
|
||||
and makes it easier to maintain and contribute to the documentation.
|
||||
|
||||
The templated man pages (*.in) are still part of the code repository as to not
|
||||
alter current procedures that could be in place by users/packagers.
|
||||
|
||||
These man pages (*.in) are still the ones being used when
|
||||
configuring/installing Unbound.
|
||||
Packagers/users do not have to generate any man pages themselves, this is done
|
||||
by the core developers during development and upon releasing new versions.
|
||||
|
||||
The templated man pages (*.in) are generated by Sphinx (used for the online
|
||||
documentation).
|
||||
The online documentation has its own repository at
|
||||
https://github.com/NLnetLabs/unbound-manual.
|
||||
|
||||
In that README.md (https://github.com/NLnetLabs/unbound-manual/README.md)
|
||||
there are further simple instructions on how to generate the templated man
|
||||
pages there and update them in this repository.
|
||||
@@ -15,6 +15,14 @@ You need to have the following programs installed and in your PATH.
|
||||
* xxd and nc (optional) - for (malformed) packet transmission.
|
||||
The optional programs are detected and can be omitted.
|
||||
|
||||
You can also use prepared Dockerfile to run tests inside docker based on latest gcc image:
|
||||
* build container: docker build -t unbound-tester -f contrib/Dockerfile.tests .
|
||||
* run container: docker run -it --mount type=bind,source="$(pwd)",target=/usr/src/unbound --rm unbound-tester
|
||||
* configure environment: ./configure
|
||||
* run test: make test
|
||||
* run long tests: make longtest
|
||||
It is worth to mention that you need to enable [ipv6 in your docker daemon configuration](https://docs.docker.com/config/daemon/ipv6/) because some tests need ipv6 network stack.
|
||||
|
||||
testdata/ contains the data for tests.
|
||||
testcode/ contains scripts and c code for the tests.
|
||||
|
||||
|
||||
+366
-70
@@ -17,7 +17,7 @@ server:
|
||||
# whitespace is not necessary, but looks cleaner.
|
||||
|
||||
# verbosity number, 0 is least verbose. 1 is default.
|
||||
verbosity: 1
|
||||
# verbosity: 1
|
||||
|
||||
# print statistics to the log (for every thread) every N seconds.
|
||||
# Set to "" or 0 to disable. Default is disabled.
|
||||
@@ -35,9 +35,14 @@ server:
|
||||
# statistics-cumulative: no
|
||||
|
||||
# enable extended statistics (query types, answer codes, status)
|
||||
# printed from unbound-control. default off, because of speed.
|
||||
# printed from unbound-control. Default off, because of speed.
|
||||
# extended-statistics: no
|
||||
|
||||
# Inhibits selected extended statistics (qtype, qclass, qopcode, rcode,
|
||||
# rpz-actions) from printing if their value is 0.
|
||||
# Default on.
|
||||
# statistics-inhibit-zero: yes
|
||||
|
||||
# number of threads to create. 1 disables threading.
|
||||
# num-threads: 1
|
||||
|
||||
@@ -49,12 +54,17 @@ server:
|
||||
# interface: 192.0.2.153
|
||||
# interface: 192.0.2.154
|
||||
# interface: 192.0.2.154@5003
|
||||
# interface: 2001:DB8::5
|
||||
# interface: 2001:db8::5
|
||||
# interface: eth0@5003
|
||||
|
||||
# enable this feature to copy the source address of queries to reply.
|
||||
# Socket options are not supported on all platforms. experimental.
|
||||
# interface-automatic: no
|
||||
|
||||
# instead of the default port, open additional ports separated by
|
||||
# spaces when interface-automatic is enabled, by listing them here.
|
||||
# interface-automatic-ports: ""
|
||||
|
||||
# port to answer queries from
|
||||
# port: 53
|
||||
|
||||
@@ -62,12 +72,12 @@ server:
|
||||
# server from by ip-address. If none, the default (all) interface
|
||||
# is used. Specify every interface on a 'outgoing-interface:' line.
|
||||
# outgoing-interface: 192.0.2.153
|
||||
# outgoing-interface: 2001:DB8::5
|
||||
# outgoing-interface: 2001:DB8::6
|
||||
# outgoing-interface: 2001:db8::5
|
||||
# outgoing-interface: 2001:db8::6
|
||||
|
||||
# Specify a netblock to use remainder 64 bits as random bits for
|
||||
# upstream queries. Uses freebind option (Linux).
|
||||
# outgoing-interface: 2001:DB8::/64
|
||||
# outgoing-interface: 2001:db8::/64
|
||||
# Also (Linux:) ip -6 addr add 2001:db8::/64 dev lo
|
||||
# And: ip -6 route add local 2001:db8::/64 dev lo
|
||||
# And set prefer-ip6: yes to use the ip6 randomness from a netblock.
|
||||
@@ -82,13 +92,13 @@ server:
|
||||
# num-queries-per-thread, or, use as many as the OS will allow you.
|
||||
# outgoing-range: 4096
|
||||
|
||||
# permit unbound to use this port number or port range for
|
||||
# permit Unbound to use this port number or port range for
|
||||
# making outgoing queries, using an outgoing interface.
|
||||
# outgoing-port-permit: 32768
|
||||
|
||||
# deny unbound the use this of port number or port range for
|
||||
# deny Unbound the use this of port number or port range for
|
||||
# making outgoing queries, using an outgoing interface.
|
||||
# Use this to make sure unbound does not grab a UDP port that some
|
||||
# Use this to make sure Unbound does not grab a UDP port that some
|
||||
# other server on this computer needs. The default is to avoid
|
||||
# IANA-assigned port numbers.
|
||||
# If multiple outgoing-port-permit and outgoing-port-avoid options
|
||||
@@ -106,8 +116,8 @@ server:
|
||||
# so-rcvbuf: 0
|
||||
|
||||
# buffer size for UDP port 53 outgoing (SO_SNDBUF socket option).
|
||||
# 0 is system default. Use 4m to handle spikes on very busy servers.
|
||||
# so-sndbuf: 0
|
||||
# 0 is system default. Set larger to handle spikes on very busy servers.
|
||||
# so-sndbuf: 4m
|
||||
|
||||
# use SO_REUSEPORT to distribute queries over threads.
|
||||
# at extreme load it could be better to turn it off to distribute even.
|
||||
@@ -133,8 +143,8 @@ server:
|
||||
# edns-buffer-size: 1232
|
||||
|
||||
# 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
|
||||
# Suggested values are 512 to 4096. Default is 1232. 65536 disables it.
|
||||
# max-udp-size: 1232
|
||||
|
||||
# max memory to use for stream(tcp and tls) waiting result buffers.
|
||||
# stream-wait-size: 4m
|
||||
@@ -153,7 +163,7 @@ server:
|
||||
# msg-cache-slabs: 4
|
||||
|
||||
# the number of queries that a thread gets to service.
|
||||
# num-queries-per-thread: 1024
|
||||
# num-queries-per-thread: 2048
|
||||
|
||||
# if very busy, 50% queries run to completion, 50% get timeout in msec
|
||||
# jostle-timeout: 200
|
||||
@@ -164,10 +174,60 @@ server:
|
||||
# perform connect for UDP sockets to mitigate ICMP side channel.
|
||||
# udp-connect: yes
|
||||
|
||||
# The number of retries, per upstream nameserver in a delegation, when
|
||||
# a throwaway response (also timeouts) is received.
|
||||
# outbound-msg-retry: 5
|
||||
|
||||
# Hard limit on the number of outgoing queries Unbound will make while
|
||||
# resolving a name, making sure large NS sets do not loop.
|
||||
# It resets on query restarts (e.g., CNAME) and referrals.
|
||||
# max-sent-count: 32
|
||||
|
||||
# Hard limit on the number of times Unbound is allowed to restart a
|
||||
# query upon encountering a CNAME record.
|
||||
# max-query-restarts: 11
|
||||
|
||||
# Limit on number of NS records in NS RRset for incoming packets.
|
||||
# iter-scrub-ns: 20
|
||||
|
||||
# Limit on number of CNAME, DNAME records for incoming packets.
|
||||
# iter-scrub-cname: 11
|
||||
|
||||
# Limit on number of RRSIGs for an RRset for incoming packets.
|
||||
# iter-scrub-rrsig: 8
|
||||
|
||||
# Limit on upstream queries for an incoming query and its recursion.
|
||||
# max-global-quota: 200
|
||||
|
||||
# Should the scrubber remove promiscuous NS from positive answers,
|
||||
# protects against poison attempts.
|
||||
# iter-scrub-promiscuous: yes
|
||||
|
||||
# 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
|
||||
|
||||
# msec before recursion replies are dropped. The work item continues.
|
||||
# discard-timeout: 1900
|
||||
|
||||
# Max number of replies waiting for recursion per IP address.
|
||||
# wait-limit: 1000
|
||||
|
||||
# Max replies waiting for recursion for IP address with cookie.
|
||||
# wait-limit-cookie: 10000
|
||||
|
||||
# Apart from the default, the wait limit can be set for a netblock.
|
||||
# wait-limit-netblock: 192.0.2.0/24 50000
|
||||
|
||||
# Apart from the default, the wait limit with cookie can be adjusted.
|
||||
# wait-limit-cookie-netblock: 192.0.2.0/24 50000
|
||||
|
||||
# Defaults for loopback, it has no wait limit.
|
||||
# wait-limit-netblock: 127.0.0.0/8 -1
|
||||
# wait-limit-netblock: ::1/128 -1
|
||||
# wait-limit-cookie-netblock: 127.0.0.0/8 -1
|
||||
# wait-limit-cookie-netblock: ::1/128 -1
|
||||
|
||||
# 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
|
||||
@@ -188,6 +248,11 @@ server:
|
||||
# the time to live (TTL) value cap for negative responses in the cache
|
||||
# cache-max-negative-ttl: 3600
|
||||
|
||||
# the time to live (TTL) value lower bound, in seconds. Default 0.
|
||||
# For negative responses in the cache. If disabled, default,
|
||||
# cache-min-ttl applies if configured.
|
||||
# cache-min-negative-ttl: 0
|
||||
|
||||
# the time to live (TTL) value for cached roundtrip times, lameness and
|
||||
# EDNS version information for hosts. In seconds.
|
||||
# infra-host-ttl: 900
|
||||
@@ -195,6 +260,9 @@ server:
|
||||
# minimum wait time for responses, increase if uplink is long. In msec.
|
||||
# infra-cache-min-rtt: 50
|
||||
|
||||
# maximum wait time for responses. In msec.
|
||||
# infra-cache-max-rtt: 120000
|
||||
|
||||
# enable to make server probe down hosts more frequently.
|
||||
# infra-keep-probing: no
|
||||
|
||||
@@ -206,7 +274,8 @@ server:
|
||||
# the maximum number of hosts that are cached (roundtrip, EDNS, lame).
|
||||
# infra-cache-numhosts: 10000
|
||||
|
||||
# define a number of tags here, use with local-zone, access-control.
|
||||
# define a number of tags here, use with local-zone, access-control,
|
||||
# interface-*.
|
||||
# repeat the define-tag statement to add additional tags.
|
||||
# define-tag: "tag1 tag2 tag3"
|
||||
|
||||
@@ -216,6 +285,18 @@ server:
|
||||
# Enable IPv6, "yes" or "no".
|
||||
# do-ip6: yes
|
||||
|
||||
# If running unbound on an IPv6-only host, domains that only have
|
||||
# IPv4 servers would become unresolvable. If NAT64 is available in
|
||||
# the network, unbound can use NAT64 to reach these servers with
|
||||
# the following option. This is NOT needed for enabling DNS64 on a
|
||||
# system that has IPv4 connectivity.
|
||||
# Consider also enabling prefer-ip6 to prefer native IPv6 connections
|
||||
# to nameservers.
|
||||
# do-nat64: no
|
||||
|
||||
# NAT64 prefix. Defaults to using dns64-prefix value.
|
||||
# nat64-prefix: 64:ff9b::0/96
|
||||
|
||||
# Enable UDP, "yes" or "no".
|
||||
# do-udp: yes
|
||||
|
||||
@@ -244,14 +325,19 @@ server:
|
||||
# Enable EDNS TCP keepalive option.
|
||||
# edns-tcp-keepalive: no
|
||||
|
||||
# Timeout for EDNS TCP keepalive, in msec.
|
||||
# Timeout for EDNS TCP keepalive, in msec. Overrides tcp-idle-timeout
|
||||
# if edns-tcp-keepalive is set.
|
||||
# edns-tcp-keepalive-timeout: 120000
|
||||
|
||||
# UDP queries that have waited in the socket buffer for a long time
|
||||
# can be dropped. Default is 0, disabled. In seconds, such as 3.
|
||||
# sock-queue-timeout: 0
|
||||
|
||||
# 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.
|
||||
# Set the value to "no" when Unbound runs as systemd service.
|
||||
# do-daemonize: yes
|
||||
|
||||
# control which clients are allowed to make (recursive) queries
|
||||
@@ -260,11 +346,10 @@ server:
|
||||
# Choose deny (drop message), refuse (polite error reply),
|
||||
# allow (recursive ok), allow_setrd (recursive ok, rd bit is forced on),
|
||||
# allow_snoop (recursive and nonrecursive ok)
|
||||
# allow_cookie (allow UDP with valid cookie or stateful transport)
|
||||
# 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
|
||||
# access-control: 127.0.0.0/8 allow
|
||||
# access-control: ::0/0 refuse
|
||||
# access-control: ::1 allow
|
||||
# access-control: ::ffff:127.0.0.1 allow
|
||||
|
||||
@@ -273,7 +358,7 @@ server:
|
||||
# are tagged with one of these tags.
|
||||
# access-control-tag: 192.0.2.0/24 "tag2 tag3"
|
||||
|
||||
# set action for particular tag for given access control element
|
||||
# set action for particular tag for given access control element.
|
||||
# if you have multiple tag values, the tag used to lookup the action
|
||||
# is the first tag match between access-control-tag and local-zone-tag
|
||||
# where "first" comes from the order of the define-tag values.
|
||||
@@ -285,6 +370,58 @@ server:
|
||||
# Set view for access control element
|
||||
# access-control-view: 192.0.2.0/24 viewname
|
||||
|
||||
# Similar to 'access-control:' but for interfaces.
|
||||
# Control which listening interfaces are allowed to accept (recursive)
|
||||
# queries for this server.
|
||||
# The specified interfaces should be the same as the ones specified in
|
||||
# 'interface:' followed by the action.
|
||||
# The actions are the same as 'access-control:' above.
|
||||
# By default all the interfaces configured are refused.
|
||||
# Note: any 'access-control*:' setting overrides all 'interface-*:'
|
||||
# settings for targeted clients.
|
||||
# interface-action: 192.0.2.153 allow
|
||||
# interface-action: 192.0.2.154 allow
|
||||
# interface-action: 192.0.2.154@5003 allow
|
||||
# interface-action: 2001:db8::5 allow
|
||||
# interface-action: eth0@5003 allow
|
||||
|
||||
# Similar to 'access-control-tag:' but for interfaces.
|
||||
# Tag interfaces with a list of tags (in "" with spaces between).
|
||||
# Interfaces using these tags use localzones that are tagged with one
|
||||
# of these tags.
|
||||
# The specified interfaces should be the same as the ones specified in
|
||||
# 'interface:' followed by the list of tags.
|
||||
# Note: any 'access-control*:' setting overrides all 'interface-*:'
|
||||
# settings for targeted clients.
|
||||
# interface-tag: eth0@5003 "tag2 tag3"
|
||||
|
||||
# Similar to 'access-control-tag-action:' but for interfaces.
|
||||
# Set action for particular tag for a given interface element.
|
||||
# If you have multiple tag values, the tag used to lookup the action
|
||||
# is the first tag match between interface-tag and local-zone-tag
|
||||
# where "first" comes from the order of the define-tag values.
|
||||
# The specified interfaces should be the same as the ones specified in
|
||||
# 'interface:' followed by the tag and action.
|
||||
# Note: any 'access-control*:' setting overrides all 'interface-*:'
|
||||
# settings for targeted clients.
|
||||
# interface-tag-action: eth0@5003 tag3 refuse
|
||||
|
||||
# Similar to 'access-control-tag-data:' but for interfaces.
|
||||
# Set redirect data for a particular tag for an interface element.
|
||||
# The specified interfaces should be the same as the ones specified in
|
||||
# 'interface:' followed by the tag and the redirect data.
|
||||
# Note: any 'access-control*:' setting overrides all 'interface-*:'
|
||||
# settings for targeted clients.
|
||||
# interface-tag-data: eth0@5003 tag2 "A 127.0.0.1"
|
||||
|
||||
# Similar to 'access-control-view:' but for interfaces.
|
||||
# Set view for an interface element.
|
||||
# The specified interfaces should be the same as the ones specified in
|
||||
# 'interface:' followed by the view name.
|
||||
# Note: any 'access-control*:' setting overrides all 'interface-*:'
|
||||
# settings for targeted clients.
|
||||
# interface-view: eth0@5003 viewname
|
||||
|
||||
# if given, a chroot(2) is done to the given directory.
|
||||
# i.e. you can chroot to the working directory, for example,
|
||||
# for extra security, but make sure all files are in that directory.
|
||||
@@ -304,7 +441,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/urandom (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 /.
|
||||
@@ -337,6 +474,10 @@ server:
|
||||
# print UTC timestamp in ascii to logfile, default is epoch in seconds.
|
||||
# log-time-ascii: no
|
||||
|
||||
# log timestamp in ISO8601 format if also log-time-ascii is enabled.
|
||||
# (y-m-dTh:m:s.msec[+-]tzhours:tzminutes)
|
||||
# log-time-iso: no
|
||||
|
||||
# print one line with time, IP, name, type, class for every query.
|
||||
# log-queries: no
|
||||
|
||||
@@ -348,6 +489,9 @@ server:
|
||||
# filtering log-queries and log-replies from the log.
|
||||
# log-tag-queryreply: no
|
||||
|
||||
# log with destination address, port and type for log-replies.
|
||||
# log-destaddr: no
|
||||
|
||||
# log the local-zone actions, like local-zone type inform is enabled
|
||||
# also for the other local zone types.
|
||||
# log-local-actions: no
|
||||
@@ -355,6 +499,10 @@ server:
|
||||
# print log lines that say why queries return SERVFAIL to clients.
|
||||
# log-servfail: no
|
||||
|
||||
# log system-wide Linux thread ID, insted of Unbound's internal thread
|
||||
# counter. Only on Linux and only when threads are available.
|
||||
# log-thread-id: no
|
||||
|
||||
# the pid file. Can be an absolute path outside of chroot/work dir.
|
||||
# pidfile: "@UNBOUND_PIDFILE@"
|
||||
|
||||
@@ -406,6 +554,9 @@ server:
|
||||
# Harden against out of zone rrsets, to avoid spoofing attempts.
|
||||
# harden-glue: yes
|
||||
|
||||
# Harden against unverified (outside-zone, including sibling zone) glue rrsets
|
||||
# harden-unverified-glue: no
|
||||
|
||||
# Harden against receiving dnssec-stripped data. If you turn it
|
||||
# off, failing to validate dnskey data for a trustanchor will
|
||||
# trigger insecure mode for that zone (like without a trustanchor).
|
||||
@@ -422,10 +573,15 @@ server:
|
||||
# harden-referral-path: no
|
||||
|
||||
# Harden against algorithm downgrade when multiple algorithms are
|
||||
# advertised in the DS record. If no, allows the weakest algorithm
|
||||
# to validate the zone.
|
||||
# advertised in the DS record. If no, allows any algorithm
|
||||
# to validate the zone which is the standard behavior for validators.
|
||||
# Check the manpage for detailed information.
|
||||
# harden-algo-downgrade: no
|
||||
|
||||
# Harden against unknown records in the authority section and the
|
||||
# additional section.
|
||||
# harden-unknown-additional: no
|
||||
|
||||
# Sent minimum amount of information to upstream servers to enhance
|
||||
# privacy. Only sent minimum required labels of the QNAME and set QTYPE
|
||||
# to A when possible.
|
||||
@@ -439,7 +595,7 @@ server:
|
||||
|
||||
# Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN
|
||||
# and other denials, using information from previous NXDOMAINs answers.
|
||||
# aggressive-nsec: no
|
||||
# aggressive-nsec: yes
|
||||
|
||||
# Use 0x20-encoded random bits in the query to foil spoof attempts.
|
||||
# This feature is an experimental implementation of draft dns-0x20.
|
||||
@@ -509,12 +665,12 @@ server:
|
||||
# or, just before the iterator).
|
||||
# module-config: "validator iterator"
|
||||
|
||||
# File with trusted keys, kept uptodate using RFC5011 probes,
|
||||
# File with trusted keys, kept up-to-date using RFC5011 probes,
|
||||
# initial file like trust-anchor-file, then it stores metadata.
|
||||
# Use several entries, one per domain name, to track multiple zones.
|
||||
#
|
||||
# If you want to perform DNSSEC validation, run unbound-anchor before
|
||||
# you start unbound (i.e. in the system boot scripts).
|
||||
# you start Unbound (i.e. in the system boot scripts).
|
||||
# And then enable the auto-trust-anchor-file config item.
|
||||
# Please note usage of unbound-anchor root anchor is at your own risk
|
||||
# and under the terms of our LICENSE (see that file in the source).
|
||||
@@ -569,7 +725,7 @@ server:
|
||||
# val-max-restart: 5
|
||||
|
||||
# Should additional section of secure message also be kept clean of
|
||||
# unsecure data. Useful to shield the users of this validator from
|
||||
# non-secure data. Useful to shield the users of this validator from
|
||||
# potential bogus data in the additional section. All unsigned data
|
||||
# in the additional section is removed from secure messages.
|
||||
# val-clean-additional: yes
|
||||
@@ -582,17 +738,23 @@ server:
|
||||
# val-permissive-mode: no
|
||||
|
||||
# Ignore the CD flag in incoming queries and refuse them bogus data.
|
||||
# Enable it if the only clients of unbound are legacy servers (w2008)
|
||||
# Enable it if the only clients of Unbound are legacy servers (w2008)
|
||||
# that set CD but cannot validate themselves.
|
||||
# ignore-cd-flag: no
|
||||
|
||||
# Disable the DO flag in outgoing requests. It is helpful for upstream
|
||||
# devices that cannot handle DNSSEC information. But do not enable it
|
||||
# otherwise, because it would stop DNSSEC validation.
|
||||
# disable-edns-do: no
|
||||
|
||||
# Serve expired responses from cache, with serve-expired-reply-ttl in
|
||||
# the response, and then attempt to fetch the data afresh.
|
||||
# the response. By default it first tries to refresh an expired answer.
|
||||
# Can be configured with serve-expired-client-timeout.
|
||||
# serve-expired: no
|
||||
#
|
||||
# Limit serving of expired responses to configured seconds after
|
||||
# expiration. 0 disables the limit.
|
||||
# serve-expired-ttl: 0
|
||||
# serve-expired-ttl: 86400
|
||||
#
|
||||
# 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
|
||||
@@ -601,18 +763,18 @@ server:
|
||||
# serve-expired-ttl-reset: no
|
||||
#
|
||||
# TTL value to use when replying with expired data.
|
||||
# Capped by the original TTL of the record.
|
||||
# serve-expired-reply-ttl: 30
|
||||
#
|
||||
# Time in milliseconds before replying to the client with expired data.
|
||||
# This essentially enables the serve-stale behavior as specified in
|
||||
# RFC 8767 that first tries to resolve before
|
||||
# immediately responding with expired data. 0 disables this behavior.
|
||||
# A recommended value is 1800.
|
||||
# serve-expired-client-timeout: 0
|
||||
# RFC 8767 that first tries to resolve before immediately responding
|
||||
# with expired data. 0 disables this behavior.
|
||||
# serve-expired-client-timeout: 1800
|
||||
|
||||
# Return the original TTL as received from the upstream name server rather
|
||||
# than the decrementing TTL as stored in the cache. Enabling this feature
|
||||
# does not impact cache expiry, it only changes the TTL unbound embeds in
|
||||
# does not impact cache expiry, it only changes the TTL Unbound embeds in
|
||||
# responses to queries. Note that enabling this feature implicitly disables
|
||||
# enforcement of the configured minimum and maximum TTL.
|
||||
# serve-original-ttl: no
|
||||
@@ -666,6 +828,9 @@ server:
|
||||
# local-zone: "localhost." nodefault
|
||||
# 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: "home.arpa." nodefault
|
||||
# local-zone: "resolver.arpa." nodefault
|
||||
# local-zone: "service.arpa." nodefault
|
||||
# local-zone: "onion." nodefault
|
||||
# local-zone: "test." nodefault
|
||||
# local-zone: "invalid." nodefault
|
||||
@@ -705,9 +870,9 @@ server:
|
||||
# Add example.com into ipset
|
||||
# local-zone: "example.com" ipset
|
||||
|
||||
# If unbound is running service for the local host then it is useful
|
||||
# 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
|
||||
# long list of local-zones above. If this Unbound is a dns server
|
||||
# for a network of computers, disabled is better and stops information
|
||||
# leakage of local lan information.
|
||||
# unblock-lan-zones: no
|
||||
@@ -732,6 +897,12 @@ server:
|
||||
# o always_transparent, always_refuse, always_nxdomain, always_nodata,
|
||||
# always_deny resolve in that way but ignore local data for
|
||||
# that name
|
||||
# o block_a resolves all records normally but returns
|
||||
# NODATA for A queries and ignores local data for that name
|
||||
# o block_aaaa similarly to block_a, resolves all records normally but
|
||||
# returns NODATA for AAAA queries and ignores local data for that name
|
||||
# o block_a_wdata like block_a but uses local data if present.
|
||||
# o block_aaaa_wdata like block_aaaa but uses local data if present.
|
||||
# o always_null returns 0.0.0.0 or ::0 for any name in the zone.
|
||||
# o noview breaks out of that view towards global local-zones.
|
||||
#
|
||||
@@ -766,6 +937,22 @@ server:
|
||||
# add a netblock specific override to a localzone, with zone type
|
||||
# local-zone-override: "example.com" 192.0.2.0/24 refuse
|
||||
|
||||
# Action to apply when the IP address in an AAAA or A RR in the answer
|
||||
# section of a response matches the specified IP netblock.
|
||||
# Requires use of the respip module.
|
||||
# response-ip: 192.0.2.0/24 redirect
|
||||
|
||||
# Redirect as specified by the "resource record string" when the IP
|
||||
# address in an AAAA or A RR in the answer section of a response
|
||||
# matches the specified IP netblock.
|
||||
# Requires use of the respip module.
|
||||
# response-ip-data: 192.0.2.0/24 "example. A 192.0.2.1"
|
||||
|
||||
# Apply tag(s) when the IP address in an AAAA or A RR in the answer
|
||||
# section of a response matches the specified IP netblock.
|
||||
# Requires use of the respip module.
|
||||
# response-ip-tag: 192.0.2.0/24 "tag1 tag2"
|
||||
|
||||
# service clients over TLS (on the TCP sockets) with plain DNS inside
|
||||
# the TLS stream, and over HTTPS using HTTP/2 as specified in RFC8484.
|
||||
# Give the certificate to use and private key.
|
||||
@@ -774,22 +961,24 @@ server:
|
||||
# tls-service-pem: "path/to/publiccertfile.pem"
|
||||
# tls-port: 853
|
||||
# https-port: 443
|
||||
# quic-port: 853
|
||||
|
||||
# Also serve tls on these port numbers (eg. 443, ...), by listing
|
||||
# tls-additional-port: portno for each of the port numbers.
|
||||
|
||||
# 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"
|
||||
|
||||
# Pad responses to padded queries received over TLS
|
||||
# pad-responses: yes
|
||||
|
||||
# Padded responses will be padded to the closest multiple of this size.
|
||||
# pad-responses-block-size: 468
|
||||
|
||||
# Use the SNI extension for TLS connections. Default is yes.
|
||||
# Changing the value requires a reload.
|
||||
# Changing the value requires a restart.
|
||||
# tls-use-sni: yes
|
||||
|
||||
# TLS protocols.
|
||||
# Changing the value requires a restart.
|
||||
# tls-protocols: "TLSv1.2 TLSv1.3"
|
||||
|
||||
# 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.
|
||||
@@ -807,6 +996,14 @@ server:
|
||||
|
||||
# Add system certs to the cert bundle, from the Windows Cert Store
|
||||
# tls-win-cert: no
|
||||
# and on other systems, the default openssl certificates
|
||||
# tls-system-cert: no
|
||||
|
||||
# Pad responses to padded queries received over TLS
|
||||
# pad-responses: yes
|
||||
|
||||
# Padded responses will be padded to the closest multiple of this size.
|
||||
# pad-responses-block-size: 468
|
||||
|
||||
# Pad queries over TLS upstreams
|
||||
# pad-queries: yes
|
||||
@@ -814,9 +1011,6 @@ server:
|
||||
# Padded queries will be padded to the closest multiple of this size.
|
||||
# pad-queries-block-size: 128
|
||||
|
||||
# Also serve tls on these port numbers (eg. 443, ...), by listing
|
||||
# tls-additional-port: portno for each of the port numbers.
|
||||
|
||||
# HTTP endpoint to provide DNS-over-HTTPS service on.
|
||||
# http-endpoint: "/dns-query"
|
||||
|
||||
@@ -836,6 +1030,13 @@ server:
|
||||
# Disable TLS for DNS-over-HTTP downstream service.
|
||||
# http-notls-downstream: no
|
||||
|
||||
# Maximum number of bytes used for QUIC buffers.
|
||||
# quic-size: 8m
|
||||
|
||||
# The interfaces that use these listed port numbers will support and
|
||||
# expect PROXYv2. For UDP and TCP/TLS interfaces.
|
||||
# proxy-protocol-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
|
||||
@@ -856,6 +1057,10 @@ server:
|
||||
# 0 blocks when ratelimited, otherwise let 1/xth traffic through
|
||||
# ratelimit-factor: 10
|
||||
|
||||
# Aggressive rate limit when the limit is reached and until demand has
|
||||
# decreased in a 2 second rate window.
|
||||
# ratelimit-backoff: no
|
||||
|
||||
# override the ratelimit for a specific domain name.
|
||||
# give this setting multiple times to have multiple overrides.
|
||||
# ratelimit-for-domain: example.com 1000
|
||||
@@ -868,6 +1073,13 @@ server:
|
||||
# if 0(default) it is disabled, otherwise states qps allowed per ip address
|
||||
# ip-ratelimit: 0
|
||||
|
||||
# global query ratelimit for all ip addresses with a valid DNS Cookie.
|
||||
# feature is experimental.
|
||||
# if 0(default) it is disabled, otherwise states qps allowed per ip address
|
||||
# useful in combination with 'allow_cookie'.
|
||||
# If used, suggested to be higher than ip-ratelimit, tenfold.
|
||||
# ip-ratelimit-cookie: 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.
|
||||
@@ -876,6 +1088,10 @@ server:
|
||||
# 0 blocks when ip is ratelimited, otherwise let 1/xth traffic through
|
||||
# ip-ratelimit-factor: 10
|
||||
|
||||
# Aggressive rate limit when the limit is reached and until demand has
|
||||
# decreased in a 2 second rate window.
|
||||
# ip-ratelimit-backoff: no
|
||||
|
||||
# Limit the number of connections simultaneous from a netblock
|
||||
# tcp-connection-limit: 192.0.2.0/24 12
|
||||
|
||||
@@ -885,7 +1101,33 @@ server:
|
||||
# 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
|
||||
# reply to requests containing DNS Cookies as specified in RFC 7873 and RFC 9018.
|
||||
# answer-cookie: no
|
||||
|
||||
# secret for DNS Cookie generation.
|
||||
# useful for anycast deployments.
|
||||
# example value "000102030405060708090a0b0c0d0e0f".
|
||||
# cookie-secret: <128 bit random hex string>
|
||||
|
||||
# File with cookie secrets, the 'cookie-secret:' option is ignored
|
||||
# and the file can be managed to have staging and active secrets
|
||||
# with remote control commands. Disabled with "". Default is "".
|
||||
# cookie-secret-file: "/usr/local/etc/unbound_cookiesecrets.txt"
|
||||
|
||||
# Enable to attach Extended DNS Error codes (RFC8914) to responses.
|
||||
# ede: no
|
||||
|
||||
# Enable to attach an Extended DNS Error (RFC8914) Code 3 - Stale
|
||||
# Answer as EDNS0 option to expired responses.
|
||||
# Note that the ede option above needs to be enabled for this to work.
|
||||
# ede-serve-expired: no
|
||||
|
||||
# Enable DNS Error Reporting (RFC9567).
|
||||
# qname-minimisation is advised to be turned on as well to increase
|
||||
# privacy on the outgoing reports.
|
||||
# dns-error-reporting: no
|
||||
|
||||
# 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
|
||||
@@ -897,7 +1139,7 @@ server:
|
||||
# listed in module-config (above).
|
||||
# ipsecmod-hook: "./my_executable"
|
||||
#
|
||||
# When enabled unbound will reply with SERVFAIL if the return value of
|
||||
# When enabled Unbound will reply with SERVFAIL if the return value of
|
||||
# the ipsecmod-hook is not 0.
|
||||
# ipsecmod-strict: no
|
||||
#
|
||||
@@ -962,10 +1204,10 @@ remote-control:
|
||||
# For local sockets this option is ignored, and TLS is not used.
|
||||
# control-use-cert: "yes"
|
||||
|
||||
# unbound server key file.
|
||||
# Unbound server key file.
|
||||
# server-key-file: "@UNBOUND_RUN_DIR@/unbound_server.key"
|
||||
|
||||
# unbound server certificate file.
|
||||
# Unbound server certificate file.
|
||||
# server-cert-file: "@UNBOUND_RUN_DIR@/unbound_server.pem"
|
||||
|
||||
# unbound-control key file.
|
||||
@@ -987,6 +1229,7 @@ remote-control:
|
||||
# stub-addr: 192.0.2.68
|
||||
# stub-prime: no
|
||||
# stub-first: no
|
||||
# stub-tcp-upstream: no
|
||||
# stub-tls-upstream: no
|
||||
# stub-no-cache: no
|
||||
# stub-zone:
|
||||
@@ -1004,6 +1247,7 @@ remote-control:
|
||||
# forward-addr: 192.0.2.68
|
||||
# forward-addr: 192.0.2.73@5355 # forward to port 5355.
|
||||
# forward-first: no
|
||||
# forward-tcp-upstream: no
|
||||
# forward-tls-upstream: no
|
||||
# forward-no-cache: no
|
||||
# forward-zone:
|
||||
@@ -1017,11 +1261,11 @@ remote-control:
|
||||
# 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), primary: fetches with AXFR and IXFR, or url to zonefile.
|
||||
# With allow-notify: you can give additional (apart from primaries) sources of
|
||||
# notifies.
|
||||
# With allow-notify: you can give additional (apart from primaries and urls)
|
||||
# sources of notifies.
|
||||
# auth-zone:
|
||||
# name: "."
|
||||
# primary: 199.9.14.201 # b.root-servers.net
|
||||
# primary: 170.247.170.2 # b.root-servers.net
|
||||
# primary: 192.33.4.12 # c.root-servers.net
|
||||
# primary: 199.7.91.13 # d.root-servers.net
|
||||
# primary: 192.5.5.241 # f.root-servers.net
|
||||
@@ -1029,7 +1273,7 @@ remote-control:
|
||||
# primary: 193.0.14.129 # k.root-servers.net
|
||||
# primary: 192.0.47.132 # xfr.cjr.dns.icann.org
|
||||
# primary: 192.0.32.132 # xfr.lax.dns.icann.org
|
||||
# primary: 2001:500:200::b # b.root-servers.net
|
||||
# primary: 2801:1b8:10::b # b.root-servers.net
|
||||
# primary: 2001:500:2::c # c.root-servers.net
|
||||
# primary: 2001:500:2d::d # d.root-servers.net
|
||||
# primary: 2001:500:2f::f # f.root-servers.net
|
||||
@@ -1047,12 +1291,16 @@ remote-control:
|
||||
# zonemd-check: no
|
||||
# zonemd-reject-absence: no
|
||||
# zonefile: "example.org.zone"
|
||||
# max-transfer-size: 0
|
||||
# max-transfer-time: 0
|
||||
|
||||
|
||||
# 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
|
||||
# and local-data options. Options from matching views will override global
|
||||
# options. Global options will be used if no matching view is found.
|
||||
# Create named views. Name must be unique.
|
||||
# Map views to requests using the access-control-view/interface-view options.
|
||||
# Views can contain zero or more local-zone and local-data options.
|
||||
# Options from matching views will override global options.
|
||||
# Global options will be used if no matching view is found.
|
||||
# With view-first yes, it will try to answer using the global local-zone and
|
||||
# local-data elements if there is no view specific match.
|
||||
# view:
|
||||
@@ -1060,14 +1308,17 @@ remote-control:
|
||||
# local-zone: "example.com" redirect
|
||||
# local-data: "example.com A 192.0.2.3"
|
||||
# local-data-ptr: "192.0.2.3 www.example.com"
|
||||
# response-ip: 192.0.2.0/24 redirect
|
||||
# response-ip-data: 192.0.2.0/24 "example. A 192.0.2.1"
|
||||
# view-first: no
|
||||
# view:
|
||||
# name: "anotherview"
|
||||
# local-zone: "example.com" refuse
|
||||
|
||||
# DNSCrypt
|
||||
# To enable, use --enable-dnscrypt to configure before compiling.
|
||||
# Caveats:
|
||||
# 1. the keys/certs cannot be produced by unbound. You can use dnscrypt-wrapper
|
||||
# 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:
|
||||
@@ -1086,7 +1337,9 @@ remote-control:
|
||||
# dnscrypt-provider-cert: /path/unbound-conf/keys2/1.cert
|
||||
|
||||
# CacheDB
|
||||
# Enable external backend DB as auxiliary cache. Specify the backend name
|
||||
# External backend DB as auxiliary cache.
|
||||
# To enable, use --enable-cachedb to configure before compiling.
|
||||
# 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.
|
||||
@@ -1094,20 +1347,54 @@ remote-control:
|
||||
# backend: "testframe"
|
||||
# # secret seed string to calculate hashed keys
|
||||
# secret-seed: "default"
|
||||
# # if the backend should be read from, but not written to.
|
||||
# cachedb-no-store: no
|
||||
# # if the cachedb should be checked before a serve-expired response is
|
||||
# # given, when serve-expired is enabled.
|
||||
# cachedb-check-when-serve-expired: yes
|
||||
#
|
||||
# # For "redis" backend:
|
||||
# # (to enable, use --with-libhiredis to configure before compiling)
|
||||
# # redis server's IP address or host name
|
||||
# redis-server-host: 127.0.0.1
|
||||
# # redis server's TCP port
|
||||
# redis-server-port: 6379
|
||||
# # if the server uses a unix socket, set its path, or "" when not used.
|
||||
# redis-server-path: "/var/lib/redis/redis-server.sock"
|
||||
# # if the server uses an AUTH password, specify here, or "" when not used.
|
||||
# redis-server-password: ""
|
||||
# # timeout (in ms) for communication with the redis server
|
||||
# redis-timeout: 100
|
||||
# # timeout (in ms) for commands, if 0, uses redis-timeout.
|
||||
# redis-command-timeout: 0
|
||||
# # timeout (in ms) for connection set up, if 0, uses redis-timeout.
|
||||
# redis-connect-timeout: 0
|
||||
# # set timeout on redis records based on DNS response TTL
|
||||
# redis-expire-records: no
|
||||
# # redis logical database to use, 0 is the default database.
|
||||
# redis-logical-db: 0
|
||||
# # redis replica server's IP address or host name
|
||||
# redis-replica-server-host: 127.0.0.1
|
||||
# # redis replica server's TCP port
|
||||
# redis-replica-server-port: 6379
|
||||
# # if the replica server uses a unix socket, set its path, or "" when not used.
|
||||
# redis-replica-server-path: "/var/lib/redis/redis-server.sock"
|
||||
# # if the replica server uses an AUTH password, specify here, or "" when not used.
|
||||
# redis-replica-server-password: ""
|
||||
# # timeout (in ms) for communication with the redis replica server
|
||||
# redis-replica-timeout: 100
|
||||
# # timeout (in ms) for redis replica commands, if 0, uses redis-replica-timeout.
|
||||
# redis-replica-command-timeout: 0
|
||||
# # timeout (in ms) for redis replica connection set up, if 0, uses redis-replica-timeout.
|
||||
# redis-replica-connect-timeout: 0
|
||||
# # redis logical database to use for the replica server, 0 is the default database.
|
||||
# redis-replica-logical-db: 0
|
||||
|
||||
# IPSet
|
||||
# Add specify domain into set via ipset.
|
||||
# Note: To enable ipset unbound needs to run as root user.
|
||||
# To enable:
|
||||
# o use --enable-ipset to configure before compiling;
|
||||
# o Unbound then needs to run as root user.
|
||||
# ipset:
|
||||
# # set name for ip v4 addresses
|
||||
# name-v4: "list-v4"
|
||||
@@ -1115,9 +1402,10 @@ remote-control:
|
||||
# name-v6: "list-v6"
|
||||
#
|
||||
|
||||
# Dnstap logging support, if compiled in. To enable, set the dnstap-enable
|
||||
# to yes and also some of dnstap-log-..-messages to yes. And select an
|
||||
# upstream log destination, by socket path, TCP or TLS destination.
|
||||
# Dnstap logging support, if compiled in by using --enable-dnstap to configure.
|
||||
# To enable, set the dnstap-enable to yes and also some of
|
||||
# dnstap-log-..-messages to yes. And select an upstream log destination, by
|
||||
# socket path, TCP or TLS destination.
|
||||
# dnstap:
|
||||
# dnstap-enable: no
|
||||
# # if set to yes frame streams will be used in bidirectional mode
|
||||
@@ -1130,7 +1418,7 @@ remote-control:
|
||||
# dnstap-tls: yes
|
||||
# # name for authenticating the upstream server. or "" disabled.
|
||||
# dnstap-tls-server-name: ""
|
||||
# # if "", it uses the cert bundle from the main unbound config.
|
||||
# # if "", it uses the cert bundle from the main Unbound config.
|
||||
# dnstap-tls-cert-bundle: ""
|
||||
# # key file for client authentication, or "" disabled.
|
||||
# dnstap-tls-client-key-file: ""
|
||||
@@ -1142,6 +1430,8 @@ remote-control:
|
||||
# dnstap-identity: ""
|
||||
# # if "" it uses the package version.
|
||||
# dnstap-version: ""
|
||||
# # log only 1/N messages, if 0 it is disabled. default 0.
|
||||
# dnstap-sample-rate: 0
|
||||
# dnstap-log-resolver-query-messages: no
|
||||
# dnstap-log-resolver-response-messages: no
|
||||
# dnstap-log-client-query-messages: no
|
||||
@@ -1150,10 +1440,12 @@ remote-control:
|
||||
# dnstap-log-forwarder-response-messages: no
|
||||
|
||||
# Response Policy Zones
|
||||
# RPZ policies. Applied in order of configuration. QNAME and Response IP
|
||||
# Address trigger are the only supported triggers. Supported actions are:
|
||||
# NXDOMAIN, NODATA, PASSTHRU, DROP and Local Data. Policies can be loaded from
|
||||
# file, using zone transfer, or using HTTP. The respip module needs to be added
|
||||
# RPZ policies. Applied in order of configuration. Any match from an earlier
|
||||
# RPZ zone will terminate the RPZ lookup. QNAME, Response IP
|
||||
# Address, nsdname, nsip and clientip triggers are supported. Supported
|
||||
# actions are: NXDOMAIN, NODATA, PASSTHRU, DROP, Local Data, tcp-only
|
||||
# and drop. Policies can be loaded from a file, or using zone
|
||||
# transfer, or using HTTP. The respip module needs to be added
|
||||
# to the module-config, e.g.: module-config: "respip validator iterator".
|
||||
# rpz:
|
||||
# name: "rpz.example.com"
|
||||
@@ -1165,4 +1457,8 @@ remote-control:
|
||||
# rpz-cname-override: www.example.org
|
||||
# rpz-log: yes
|
||||
# rpz-log-name: "example policy"
|
||||
# rpz-signal-nxdomain-ra: no
|
||||
# for-downstream: no
|
||||
# tags: "example"
|
||||
# max-transfer-size: 0
|
||||
# max-transfer-time: 0
|
||||
|
||||
+330
-343
@@ -1,335 +1,306 @@
|
||||
.TH "libunbound" "3" "@date@" "NLnet Labs" "unbound @version@"
|
||||
.\"
|
||||
.\" libunbound.3 -- unbound library functions manual
|
||||
.\"
|
||||
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
|
||||
.\"
|
||||
.\" See LICENSE for the license.
|
||||
.\"
|
||||
.\"
|
||||
.SH "NAME"
|
||||
.B libunbound,
|
||||
.B unbound.h,
|
||||
.B ub_ctx,
|
||||
.B ub_result,
|
||||
.B ub_callback_type,
|
||||
.B ub_ctx_create,
|
||||
.B ub_ctx_delete,
|
||||
.B ub_ctx_set_option,
|
||||
.B ub_ctx_get_option,
|
||||
.B ub_ctx_config,
|
||||
.B ub_ctx_set_fwd,
|
||||
.B ub_ctx_set_stub,
|
||||
.B ub_ctx_set_tls,
|
||||
.B ub_ctx_resolvconf,
|
||||
.B ub_ctx_hosts,
|
||||
.B ub_ctx_add_ta,
|
||||
.B ub_ctx_add_ta_autr,
|
||||
.B ub_ctx_add_ta_file,
|
||||
.B ub_ctx_trustedkeys,
|
||||
.B ub_ctx_debugout,
|
||||
.B ub_ctx_debuglevel,
|
||||
.B ub_ctx_async,
|
||||
.B ub_poll,
|
||||
.B ub_wait,
|
||||
.B ub_fd,
|
||||
.B ub_process,
|
||||
.B ub_resolve,
|
||||
.B ub_resolve_async,
|
||||
.B ub_cancel,
|
||||
.B ub_resolve_free,
|
||||
.B ub_strerror,
|
||||
.B ub_ctx_print_local_zones,
|
||||
.B ub_ctx_zone_add,
|
||||
.B ub_ctx_zone_remove,
|
||||
.B ub_ctx_data_add,
|
||||
.B ub_ctx_data_remove
|
||||
\- Unbound DNS validating resolver @version@ functions.
|
||||
.SH "SYNOPSIS"
|
||||
.B #include <unbound.h>
|
||||
.LP
|
||||
\fIstruct ub_ctx *\fR
|
||||
\fBub_ctx_create\fR(\fIvoid\fR);
|
||||
.LP
|
||||
\fIvoid\fR
|
||||
\fBub_ctx_delete\fR(\fIstruct ub_ctx*\fR ctx);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_set_option\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR opt, \fIchar*\fR val);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_get_option\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR opt, \fIchar**\fR val);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_config\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_set_fwd\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR addr);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_set_stub\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR zone,
|
||||
\fIchar*\fR addr,
|
||||
.br
|
||||
\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
|
||||
\fBub_ctx_hosts\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_add_ta\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR ta);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_add_ta_autr\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_add_ta_file\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_trustedkeys\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_debugout\fR(\fIstruct ub_ctx*\fR ctx, \fIFILE*\fR out);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_debuglevel\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR d);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_async\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR dothread);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_poll\fR(\fIstruct ub_ctx*\fR ctx);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_wait\fR(\fIstruct ub_ctx*\fR ctx);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_fd\fR(\fIstruct ub_ctx*\fR ctx);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_process\fR(\fIstruct ub_ctx*\fR ctx);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_resolve\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR name,
|
||||
.br
|
||||
\fIint\fR rrtype, \fIint\fR rrclass, \fIstruct ub_result**\fR result);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_resolve_async\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR name,
|
||||
.br
|
||||
\fIint\fR rrtype, \fIint\fR rrclass, \fIvoid*\fR mydata,
|
||||
.br
|
||||
\fIub_callback_type\fR callback, \fIint*\fR async_id);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_cancel\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR async_id);
|
||||
.LP
|
||||
\fIvoid\fR
|
||||
\fBub_resolve_free\fR(\fIstruct ub_result*\fR result);
|
||||
.LP
|
||||
\fIconst char *\fR
|
||||
\fBub_strerror\fR(\fIint\fR err);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_print_local_zones\fR(\fIstruct ub_ctx*\fR ctx);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_zone_add\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR zone_name, \fIchar*\fR zone_type);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_zone_remove\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR zone_name);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_data_add\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR data);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_ctx_data_remove\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR data);
|
||||
.SH "DESCRIPTION"
|
||||
.B Unbound
|
||||
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 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
|
||||
The library uses a variable of type \fIstruct ub_ctx\fR to keep context
|
||||
between calls. The user must maintain it, creating it with
|
||||
.B ub_ctx_create
|
||||
and deleting it with
|
||||
.B ub_ctx_delete\fR.
|
||||
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 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
|
||||
can go on, while the results become available later.
|
||||
.P
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.
|
||||
.nr rst2man-indent-level 0
|
||||
.
|
||||
.de1 rstReportMargin
|
||||
\\$1 \\n[an-margin]
|
||||
level \\n[rst2man-indent-level]
|
||||
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
-
|
||||
\\n[rst2man-indent0]
|
||||
\\n[rst2man-indent1]
|
||||
\\n[rst2man-indent2]
|
||||
..
|
||||
.de1 INDENT
|
||||
.\" .rstReportMargin pre:
|
||||
. RS \\$1
|
||||
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
|
||||
. nr rst2man-indent-level +1
|
||||
.\" .rstReportMargin post:
|
||||
..
|
||||
.de UNINDENT
|
||||
. RE
|
||||
.\" indent \\n[an-margin]
|
||||
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.nr rst2man-indent-level -1
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "LIBUNBOUND" "3" "@date@" "@version@" "Unbound"
|
||||
.SH NAME
|
||||
libunbound \- Unbound DNS validating resolver @version@ functions.
|
||||
.SH SYNOPSIS
|
||||
.sp
|
||||
\fB#include <unbound.h>\fP
|
||||
.sp
|
||||
struct ub_ctx * \fBub_ctx_create\fP(void);
|
||||
.sp
|
||||
void \fBub_ctx_delete\fP(struct ub_ctx* ctx);
|
||||
.sp
|
||||
int \fBub_ctx_set_option\fP(struct ub_ctx* ctx, char* opt, char* val);
|
||||
.sp
|
||||
int \fBub_ctx_get_option\fP(struct ub_ctx* ctx, char* opt, char** val);
|
||||
.sp
|
||||
int \fBub_ctx_config\fP(struct ub_ctx* ctx, char* fname);
|
||||
.sp
|
||||
int \fBub_ctx_set_fwd\fP(struct ub_ctx* ctx, char* addr);
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
int \fBub_ctx_set_stub\fP(struct ub_ctx* ctx, char* zone, char* addr,
|
||||
int isprime);
|
||||
.UNINDENT
|
||||
.sp
|
||||
int \fBub_ctx_set_tls\fP(struct ub_ctx* ctx, int tls);
|
||||
.sp
|
||||
int \fBub_ctx_resolvconf\fP(struct ub_ctx* ctx, char* fname);
|
||||
.sp
|
||||
int \fBub_ctx_hosts\fP(struct ub_ctx* ctx, char* fname);
|
||||
.sp
|
||||
int \fBub_ctx_add_ta\fP(struct ub_ctx* ctx, char* ta);
|
||||
.sp
|
||||
int \fBub_ctx_add_ta_autr\fP(struct ub_ctx* ctx, char* fname);
|
||||
.sp
|
||||
int \fBub_ctx_add_ta_file\fP(struct ub_ctx* ctx, char* fname);
|
||||
.sp
|
||||
int \fBub_ctx_trustedkeys\fP(struct ub_ctx* ctx, char* fname);
|
||||
.sp
|
||||
int \fBub_ctx_debugout\fP(struct ub_ctx* ctx, FILE* out);
|
||||
.sp
|
||||
int \fBub_ctx_debuglevel\fP(struct ub_ctx* ctx, int d);
|
||||
.sp
|
||||
int \fBub_ctx_async\fP(struct ub_ctx* ctx, int dothread);
|
||||
.sp
|
||||
int \fBub_poll\fP(struct ub_ctx* ctx);
|
||||
.sp
|
||||
int \fBub_wait\fP(struct ub_ctx* ctx);
|
||||
.sp
|
||||
int \fBub_fd\fP(struct ub_ctx* ctx);
|
||||
.sp
|
||||
int \fBub_process\fP(struct ub_ctx* ctx);
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
int \fBub_resolve\fP(struct ub_ctx* ctx, char* name,
|
||||
int rrtype, int rrclass, struct ub_result** result);
|
||||
.TP
|
||||
int \fBub_resolve_async\fP(struct ub_ctx* ctx, char* name,
|
||||
int rrtype, int rrclass, void* mydata,
|
||||
ub_callback_type* callback, int* async_id);
|
||||
.UNINDENT
|
||||
.sp
|
||||
int \fBub_cancel\fP(struct ub_ctx* ctx, int async_id);
|
||||
.sp
|
||||
void \fBub_resolve_free\fP(struct ub_result* result);
|
||||
.sp
|
||||
const char * \fBub_strerror\fP(int err);
|
||||
.sp
|
||||
int \fBub_ctx_print_local_zones\fP(struct ub_ctx* ctx);
|
||||
.sp
|
||||
int \fBub_ctx_zone_add\fP(struct ub_ctx* ctx, char* zone_name, char* zone_type);
|
||||
.sp
|
||||
int \fBub_ctx_zone_remove\fP(struct ub_ctx* ctx, char* zone_name);
|
||||
.sp
|
||||
int \fBub_ctx_data_add\fP(struct ub_ctx* ctx, char* data);
|
||||
.sp
|
||||
int \fBub_ctx_data_remove\fP(struct ub_ctx* ctx, char* data);
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
Unbound is an implementation of a DNS resolver, that does caching and DNSSEC
|
||||
validation.
|
||||
This is the library API, for using the \fB\-lunbound\fP library.
|
||||
The server daemon is described in \fI\%unbound(8)\fP\&.
|
||||
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.
|
||||
.sp
|
||||
The library uses a variable of type \fIstruct ub_ctx\fP to keep context between
|
||||
calls.
|
||||
The user must maintain it, creating it with \fBub_ctx_create\fP and deleting it
|
||||
with \fBub_ctx_delete\fP\&.
|
||||
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.
|
||||
.sp
|
||||
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 can go
|
||||
on, while the results become available later.
|
||||
.sp
|
||||
The functions are discussed in turn below.
|
||||
.SH "FUNCTIONS"
|
||||
.TP
|
||||
.SH FUNCTIONS
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B ub_ctx_create
|
||||
Create a new context, initialised with defaults.
|
||||
The information from /etc/resolv.conf and /etc/hosts is not utilised
|
||||
by default. Use
|
||||
.B ub_ctx_resolvconf
|
||||
and
|
||||
.B ub_ctx_hosts
|
||||
to read them.
|
||||
Before you call this, use the openssl functions CRYPTO_set_id_callback and
|
||||
CRYPTO_set_locking_callback to set up asynchronous operation if you use
|
||||
lib openssl (the application calls these functions once for initialisation).
|
||||
Openssl 1.0.0 or later uses the CRYPTO_THREADID_set_callback function.
|
||||
The information from \fB/etc/resolv.conf\fP and \fB/etc/hosts\fP is
|
||||
not utilised by default.
|
||||
Use \fBub_ctx_resolvconf\fP and \fBub_ctx_hosts\fP to read them.
|
||||
Before you call this, use the openssl functions
|
||||
\fBCRYPTO_set_id_callback\fP and \fBCRYPTO_set_locking_callback\fP to set
|
||||
up asynchronous operation if you use lib openssl (the application calls
|
||||
these functions once for initialisation).
|
||||
Openssl 1.0.0 or later uses the \fBCRYPTO_THREADID_set_callback\fP
|
||||
function.
|
||||
.TP
|
||||
.B ub_ctx_delete
|
||||
Delete validation context and free associated resources.
|
||||
Outstanding async queries are killed and callbacks are not called for them.
|
||||
Outstanding async queries are killed and callbacks are not called for
|
||||
them.
|
||||
.TP
|
||||
.B ub_ctx_set_option
|
||||
A power\-user interface that lets you specify one of the options from the
|
||||
config file format, see \fIunbound.conf\fR(5). Not all options are
|
||||
relevant. For some specific options, such as adding trust anchors, special
|
||||
routines exist. Pass the option name with the trailing ':'.
|
||||
A power\-user interface that lets you specify one of the options from
|
||||
the config file format, see \fI\%unbound.conf(5)\fP\&.
|
||||
Not all options are relevant.
|
||||
For some specific options, such as adding trust anchors, special
|
||||
routines exist.
|
||||
Pass the option name with the trailing \fB\(aq:\(aq\fP\&.
|
||||
.TP
|
||||
.B ub_ctx_get_option
|
||||
A power\-user interface that gets an option value. Some options cannot be
|
||||
gotten, and others return a newline separated list. Pass the option name
|
||||
without trailing ':'. The returned value must be free(2)d by the caller.
|
||||
A power\-user interface that gets an option value.
|
||||
Some options cannot be gotten, and others return a newline separated
|
||||
list.
|
||||
Pass the option name without trailing \fB\(aq:\(aq\fP\&.
|
||||
The returned value must be free(2)d by the caller.
|
||||
.TP
|
||||
.B ub_ctx_config
|
||||
A power\-user interface that lets you specify an unbound config file, see
|
||||
\fIunbound.conf\fR(5), which is read for configuration. Not all options are
|
||||
relevant. For some specific options, such as adding trust anchors, special
|
||||
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.
|
||||
A power\-user interface that lets you specify an unbound config file,
|
||||
see \fI\%unbound.conf(5)\fP, which is read for
|
||||
configuration.
|
||||
Not all options are relevant.
|
||||
For some specific options, such as adding trust anchors, special
|
||||
routines exist.
|
||||
This function is thread\-safe only if a single instance of \fBub_ctx\fP*
|
||||
exists in the application.
|
||||
If several instances exist the application has to ensure that
|
||||
\fBub_ctx_config\fP 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.
|
||||
IP4 or IP6 address. Forwards all DNS requests to that machine, which
|
||||
is expected to run a recursive resolver. If the proxy is not
|
||||
DNSSEC capable, validation may fail. Can be called several times, in
|
||||
that case the addresses are used as backup servers.
|
||||
At this time it is only possible to set configuration before the
|
||||
first resolve is done.
|
||||
Set machine to forward DNS queries to, the caching resolver to use.
|
||||
IP4 or IP6 address.
|
||||
Forwards all DNS requests to that machine, which is expected to run a
|
||||
recursive resolver.
|
||||
If the proxy is not DNSSEC capable, validation may fail.
|
||||
Can be called several times, in that case the addresses are used as
|
||||
backup servers.
|
||||
At this time it is only possible to set configuration before the first
|
||||
resolve is done.
|
||||
.TP
|
||||
.B ub_ctx_set_stub
|
||||
Set a stub zone, authoritative dns servers to use for a particular zone.
|
||||
IP4 or IP6 address. If the address is NULL the stub entry is removed.
|
||||
Set isprime true if you configure root hints with it. Otherwise similar to
|
||||
the stub zone item from unbound's config file. Can be called several times,
|
||||
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.
|
||||
Set a stub zone, authoritative dns servers to use for a particular
|
||||
zone.
|
||||
IP4 or IP6 address.
|
||||
If the address is NULL the stub entry is removed.
|
||||
Set isprime true if you configure root hints with it.
|
||||
Otherwise similar to the stub zone item from unbound\(aqs config file.
|
||||
Can be called several times, 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.
|
||||
Enable DNS over TLS (DoT) for machines set with \fBub_ctx_set_fwd\fP\&.
|
||||
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
|
||||
filename given.
|
||||
Usually "/etc/resolv.conf". Uses those nameservers as caching proxies.
|
||||
By default the root servers are queried and full resolver mode is used,
|
||||
but you can use this call to read the list of nameservers to use from
|
||||
the filename given.
|
||||
Usually \fB\(dq/etc/resolv.conf\(dq\fP\&.
|
||||
Uses those nameservers as caching proxies.
|
||||
If they do not support DNSSEC, validation may fail.
|
||||
Only nameservers are picked up, the searchdomain, ndots and other
|
||||
settings from \fIresolv.conf\fR(5) are ignored.
|
||||
If fname NULL is passed, "/etc/resolv.conf" is used (if on Windows,
|
||||
the system\-wide configured nameserver is picked instead).
|
||||
At this time it is only possible to set configuration before the
|
||||
first resolve is done.
|
||||
settings from \fIresolv.conf(5)\fP are ignored.
|
||||
If fname NULL is passed, \fB\(dq/etc/resolv.conf\(dq\fP is used (if on
|
||||
Windows, the system\-wide configured nameserver is picked instead).
|
||||
At this time it is only possible to set configuration before the first
|
||||
resolve is done.
|
||||
.TP
|
||||
.B ub_ctx_hosts
|
||||
Read list of hosts from the filename given.
|
||||
Usually "/etc/hosts". When queried for, these addresses are not marked
|
||||
DNSSEC secure. If fname NULL is passed, "/etc/hosts" is used
|
||||
(if on Windows, etc/hosts from WINDIR is picked instead).
|
||||
At this time it is only possible to set configuration before the
|
||||
first resolve is done.
|
||||
Usually \fB\(dq/etc/hosts\(dq\fP\&.
|
||||
When queried for, these addresses are not marked DNSSEC secure.
|
||||
If fname NULL is passed, \fB\(dq/etc/hosts\(dq\fP is used (if on Windows,
|
||||
\fBetc/hosts\fP from WINDIR is picked instead).
|
||||
At this time it is only possible to set configuration before the first
|
||||
resolve is done.
|
||||
.TP
|
||||
.B
|
||||
ub_ctx_add_ta
|
||||
.B ub_ctx_add_ta
|
||||
Add a trust anchor to the given context.
|
||||
At this time it is only possible to add trusted keys before the
|
||||
first resolve is done.
|
||||
At this time it is only possible to add trusted keys before the first
|
||||
resolve is done.
|
||||
The format is a string, similar to the zone\-file format,
|
||||
[domainname] [type] [rdata contents]. Both DS and DNSKEY records are accepted.
|
||||
\fB[domainname]\fP \fB[type]\fP \fB[rdata contents]\fP\&.
|
||||
Both DS and DNSKEY records are accepted.
|
||||
.TP
|
||||
.B ub_ctx_add_ta_autr
|
||||
Add filename with automatically tracked trust anchor to the given context.
|
||||
Pass name of a file with the managed trust anchor. You can create this
|
||||
file with \fIunbound\-anchor\fR(8) for the root anchor. You can also
|
||||
create it with an initial file with one line with a DNSKEY or DS record.
|
||||
Add filename with automatically tracked trust anchor to the given
|
||||
context.
|
||||
Pass name of a file with the managed trust anchor.
|
||||
You can create this file with
|
||||
\fI\%unbound\-anchor(8)\fP for the root anchor.
|
||||
You can also create it with an initial file with one line with a DNSKEY
|
||||
or DS record.
|
||||
If the file is writable, it is updated when the trust anchor changes.
|
||||
At this time it is only possible to add trusted keys before the
|
||||
first resolve is done.
|
||||
At this time it is only possible to add trusted keys before the first
|
||||
resolve is done.
|
||||
.TP
|
||||
.B ub_ctx_add_ta_file
|
||||
Add trust anchors to the given context.
|
||||
Pass name of a file with DS and DNSKEY records in zone file format.
|
||||
At this time it is only possible to add trusted keys before the
|
||||
first resolve is done.
|
||||
At this time it is only possible to add trusted keys before the first
|
||||
resolve is done.
|
||||
.TP
|
||||
.B ub_ctx_trustedkeys
|
||||
Add trust anchors to the given context.
|
||||
Pass the name of a bind\-style config file with trusted\-keys{}.
|
||||
At this time it is only possible to add trusted keys before the
|
||||
first resolve is done.
|
||||
Pass the name of a bind\-style config file with \fBtrusted\-keys{}\fP\&.
|
||||
At this time it is only possible to add trusted keys before the first
|
||||
resolve is done.
|
||||
.TP
|
||||
.B ub_ctx_debugout
|
||||
Set debug and error log output to the given stream. Pass NULL to disable
|
||||
output. Default is stderr. File\-names or using syslog can be enabled
|
||||
using config options, this routine is for using your own stream.
|
||||
Set debug and error log output to the given stream.
|
||||
Pass NULL to disable output.
|
||||
Default is stderr.
|
||||
File\-names or using syslog can be enabled using config options, this
|
||||
routine is for using your own stream.
|
||||
.TP
|
||||
.B ub_ctx_debuglevel
|
||||
Set debug verbosity for the context. Output is directed to stderr.
|
||||
Set debug verbosity for the context.
|
||||
Output is directed to stderr.
|
||||
Higher debug level gives more output.
|
||||
.TP
|
||||
.B ub_ctx_async
|
||||
Set a context behaviour for asynchronous action.
|
||||
if set to true, enables threading and a call to
|
||||
.B ub_resolve_async
|
||||
if set to true, enables threading and a call to \fBub_resolve_async\fP
|
||||
creates a thread to handle work in the background.
|
||||
If false, a process is forked to handle work in the background.
|
||||
Changes to this setting after
|
||||
.B ub_resolve_async
|
||||
calls have been made have no effect (delete and re\-create the context
|
||||
to change).
|
||||
Changes to this setting after \fBub_resolve_async\fP calls have been made
|
||||
have no effect (delete and re\-create the context to change).
|
||||
.TP
|
||||
.B ub_poll
|
||||
Poll a context to see if it has any new results.
|
||||
Do not poll in a loop, instead extract the fd below to poll for readiness,
|
||||
and then check, or wait using the wait routine.
|
||||
Do not poll in a loop, instead extract the \fBfd\fP below to poll for
|
||||
readiness, and then check, or wait using the wait routine.
|
||||
Returns 0 if nothing to read, or nonzero if a result is available.
|
||||
If nonzero, call
|
||||
.B ub_process
|
||||
to do callbacks.
|
||||
If nonzero, call \fBub_process\fP to do callbacks.
|
||||
.TP
|
||||
.B ub_wait
|
||||
Wait for a context to finish with results. Calls
|
||||
.B ub_process
|
||||
after the wait for you. After the wait, there are no more outstanding
|
||||
asynchronous queries.
|
||||
Wait for a context to finish with results.
|
||||
Calls \fBub_process\fP after the wait for you.
|
||||
After the wait, there are no more outstanding asynchronous queries.
|
||||
.TP
|
||||
.B ub_fd
|
||||
Get file descriptor. Wait for it to become readable, at this point
|
||||
answers are returned from the asynchronous validating resolver.
|
||||
Then call the \fBub_process\fR to continue processing.
|
||||
Get file descriptor.
|
||||
Wait for it to become readable, at this point answers are returned from
|
||||
the asynchronous validating resolver.
|
||||
Then call the \fBub_process\fP to continue processing.
|
||||
.TP
|
||||
.B ub_process
|
||||
Call this routine to continue processing results from the validating
|
||||
resolver (when the fd becomes readable).
|
||||
resolver (when the \fBfd\fP becomes readable).
|
||||
Will perform necessary callbacks.
|
||||
.TP
|
||||
.B ub_resolve
|
||||
@@ -340,95 +311,111 @@ The result structure is newly allocated with the resulting data.
|
||||
.TP
|
||||
.B ub_resolve_async
|
||||
Perform asynchronous resolution and validation of the target name.
|
||||
Arguments mean the same as for \fBub_resolve\fR except no
|
||||
data is returned immediately, instead a callback is called later.
|
||||
The callback receives a copy of the mydata pointer, that you can use to pass
|
||||
information to the callback. The callback type is a function pointer to
|
||||
a function declared as
|
||||
.IP
|
||||
void my_callback_function(void* my_arg, int err,
|
||||
.br
|
||||
struct ub_result* result);
|
||||
.IP
|
||||
The async_id is returned so you can (at your option) decide to track it
|
||||
and cancel the request if needed. If you pass a NULL pointer the async_id
|
||||
is not returned.
|
||||
Arguments mean the same as for \fBub_resolve\fP except no data is
|
||||
returned immediately, instead a callback is called later.
|
||||
The callback receives a copy of the mydata pointer, that you can use to
|
||||
pass information to the callback.
|
||||
The callback type is a function pointer to a function declared as:
|
||||
.INDENT 7.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.nf
|
||||
.ft C
|
||||
void my_callback_function(void* my_arg, int err,
|
||||
struct ub_result* result);
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
The \fBasync_id\fP is returned so you can (at your option) decide to
|
||||
track it and cancel the request if needed.
|
||||
If you pass a NULL pointer the \fBasync_id\fP is not returned.
|
||||
.TP
|
||||
.B ub_cancel
|
||||
Cancel an async query in progress. This may return an error if the query
|
||||
does not exist, or the query is already being delivered, in that case you
|
||||
may still get a callback for the query.
|
||||
Cancel an async query in progress.
|
||||
This may return an error if the query does not exist, or the query is
|
||||
already being delivered, in that case you may still get a callback for
|
||||
the query.
|
||||
.TP
|
||||
.B ub_resolve_free
|
||||
Free struct ub_result contents after use.
|
||||
Free struct \fBub_result\fP contents after use.
|
||||
.TP
|
||||
.B ub_strerror
|
||||
Convert error value from one of the unbound library functions
|
||||
to a human readable string.
|
||||
Convert error value from one of the unbound library functions to a
|
||||
human readable string.
|
||||
.TP
|
||||
.B ub_ctx_print_local_zones
|
||||
Debug printout the local authority information to debug output.
|
||||
.TP
|
||||
.B ub_ctx_zone_add
|
||||
Add new zone to local authority info, like local\-zone \fIunbound.conf\fR(5)
|
||||
statement.
|
||||
Add new zone to local authority info, like local\-zone
|
||||
\fI\%unbound.conf(5)\fP statement.
|
||||
.TP
|
||||
.B ub_ctx_zone_remove
|
||||
Delete zone from local authority info.
|
||||
.TP
|
||||
.B ub_ctx_data_add
|
||||
Add resource record data to local authority info, like local\-data
|
||||
\fIunbound.conf\fR(5) statement.
|
||||
\fI\%unbound.conf(5)\fP statement.
|
||||
.TP
|
||||
.B ub_ctx_data_remove
|
||||
Delete local authority data from the name given.
|
||||
.SH "RESULT DATA STRUCTURE"
|
||||
The result of the DNS resolution and validation is returned as
|
||||
\fIstruct ub_result\fR. The result structure contains the following entries.
|
||||
.P
|
||||
.UNINDENT
|
||||
.SH RESULT DATA STRUCTURE
|
||||
.sp
|
||||
The result of the DNS resolution and validation is returned as \fIstruct
|
||||
ub_result\fP\&.
|
||||
The result structure contains the following entries:
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.nf
|
||||
struct ub_result {
|
||||
char* qname; /* text string, original question */
|
||||
int qtype; /* type code asked for */
|
||||
int qclass; /* class code asked for */
|
||||
char** data; /* array of rdata items, NULL terminated*/
|
||||
int* len; /* array with lengths of rdata items */
|
||||
char* canonname; /* canonical name of result */
|
||||
int rcode; /* additional error code in case of no data */
|
||||
void* answer_packet; /* full network format answer packet */
|
||||
int answer_len; /* length of packet in octets */
|
||||
int havedata; /* true if there is data */
|
||||
int nxdomain; /* true if nodata because name does not exist */
|
||||
int secure; /* true if result is secure */
|
||||
int bogus; /* true if a security failure happened */
|
||||
char* why_bogus; /* string with error if bogus */
|
||||
int was_ratelimited; /* true if the query was ratelimited (SERVFAIL) by unbound */
|
||||
int ttl; /* number of seconds the result is valid */
|
||||
};
|
||||
.ft C
|
||||
struct ub_result {
|
||||
char* qname; /* text string, original question */
|
||||
int qtype; /* type code asked for */
|
||||
int qclass; /* class code asked for */
|
||||
char** data; /* array of rdata items, NULL terminated*/
|
||||
int* len; /* array with lengths of rdata items */
|
||||
char* canonname; /* canonical name of result */
|
||||
int rcode; /* additional error code in case of no data */
|
||||
void* answer_packet; /* full network format answer packet */
|
||||
int answer_len; /* length of packet in octets */
|
||||
int havedata; /* true if there is data */
|
||||
int nxdomain; /* true if nodata because name does not exist */
|
||||
int secure; /* true if result is secure */
|
||||
int bogus; /* true if a security failure happened */
|
||||
char* why_bogus; /* string with error if bogus */
|
||||
int was_ratelimited; /* true if the query was ratelimited (SERVFAIL) by unbound */
|
||||
int ttl; /* number of seconds the result is valid */
|
||||
};
|
||||
.ft P
|
||||
.fi
|
||||
.P
|
||||
If both secure and bogus are false, security was not enabled for the
|
||||
domain of the query. Else, they are not both true, one of them is true.
|
||||
.SH "RETURN VALUES"
|
||||
Many routines return an error code. The value 0 (zero) denotes no error
|
||||
happened. Other values can be passed to
|
||||
.B ub_strerror
|
||||
to obtain a readable error string.
|
||||
.B ub_strerror
|
||||
returns a zero terminated string.
|
||||
.B ub_ctx_create
|
||||
returns NULL on an error (a malloc failure).
|
||||
.B ub_poll
|
||||
returns true if some information may be available, false otherwise.
|
||||
.B ub_fd
|
||||
returns a file descriptor or \-1 on error.
|
||||
.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).
|
||||
.SH "AUTHORS"
|
||||
.B Unbound
|
||||
developers are mentioned in the CREDITS file in the distribution.
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
If both secure and bogus are false, security was not enabled for the domain of
|
||||
the query.
|
||||
Else, they are not both true, one of them is true.
|
||||
.SH RETURN VALUES
|
||||
.sp
|
||||
Many routines return an error code.
|
||||
The value 0 (zero) denotes no error happened.
|
||||
Other values can be passed to \fBub_strerror\fP to obtain a readable error
|
||||
string.
|
||||
\fBub_strerror\fP returns a zero terminated string.
|
||||
\fBub_ctx_create\fP returns NULL on an error (a malloc failure).
|
||||
\fBub_poll\fP returns true if some information may be available, false otherwise.
|
||||
\fBub_fd\fP returns a file descriptor or \-1 on error.
|
||||
\fBub_ctx_config\fP and \fBub_ctx_resolvconf\fP attempt to leave errno informative
|
||||
on a function return with file read failure.
|
||||
.SH SEE ALSO
|
||||
.sp
|
||||
\fI\%unbound.conf(5)\fP, \fI\%unbound(8)\fP\&.
|
||||
.SH AUTHOR
|
||||
Unbound developers are mentioned in the CREDITS file in the distribution.
|
||||
.SH COPYRIGHT
|
||||
1999-2026, NLnet Labs
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
|
||||
@@ -0,0 +1,491 @@
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
libunbound(3)
|
||||
=============
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
.. only:: html
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include <unbound.h>
|
||||
|
||||
struct ub_ctx * ub_ctx_create(void);
|
||||
|
||||
void ub_ctx_delete(struct ub_ctx* ctx);
|
||||
|
||||
int ub_ctx_set_option(struct ub_ctx* ctx, char* opt, char* val);
|
||||
|
||||
int ub_ctx_get_option(struct ub_ctx* ctx, char* opt, char** val);
|
||||
|
||||
int ub_ctx_config(struct ub_ctx* ctx, char* fname);
|
||||
|
||||
int ub_ctx_set_fwd(struct ub_ctx* ctx, char* addr);
|
||||
|
||||
int ub_ctx_set_stub(struct ub_ctx* ctx, char* zone, char* addr,
|
||||
int isprime);
|
||||
|
||||
int ub_ctx_set_tls(struct ub_ctx* ctx, int tls);
|
||||
|
||||
int ub_ctx_resolvconf(struct ub_ctx* ctx, char* fname);
|
||||
|
||||
int ub_ctx_hosts(struct ub_ctx* ctx, char* fname);
|
||||
|
||||
int ub_ctx_add_ta(struct ub_ctx* ctx, char* ta);
|
||||
|
||||
int ub_ctx_add_ta_autr(struct ub_ctx* ctx, char* fname);
|
||||
|
||||
int ub_ctx_add_ta_file(struct ub_ctx* ctx, char* fname);
|
||||
|
||||
int ub_ctx_trustedkeys(struct ub_ctx* ctx, char* fname);
|
||||
|
||||
int ub_ctx_debugout(struct ub_ctx* ctx, FILE* out);
|
||||
|
||||
int ub_ctx_debuglevel(struct ub_ctx* ctx, int d);
|
||||
|
||||
int ub_ctx_async(struct ub_ctx* ctx, int dothread);
|
||||
|
||||
int ub_poll(struct ub_ctx* ctx);
|
||||
|
||||
int ub_wait(struct ub_ctx* ctx);
|
||||
|
||||
int ub_fd(struct ub_ctx* ctx);
|
||||
|
||||
int ub_process(struct ub_ctx* ctx);
|
||||
|
||||
int ub_resolve(struct ub_ctx* ctx, char* name, int rrtype,
|
||||
int rrclass, struct ub_result** result);
|
||||
|
||||
int ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype,
|
||||
int rrclass, void* mydata, ub_callback_type callback,
|
||||
int* async_id);
|
||||
|
||||
int ub_cancel(struct ub_ctx* ctx, int async_id);
|
||||
|
||||
void ub_resolve_free(struct ub_result* result);
|
||||
|
||||
const char * ub_strerror(int err);
|
||||
|
||||
int ub_ctx_print_local_zones(struct ub_ctx* ctx);
|
||||
|
||||
int ub_ctx_zone_add(struct ub_ctx* ctx, char* zone_name, char* zone_type);
|
||||
|
||||
int ub_ctx_zone_remove(struct ub_ctx* ctx, char* zone_name);
|
||||
|
||||
int ub_ctx_data_add(struct ub_ctx* ctx, char* data);
|
||||
|
||||
int ub_ctx_data_remove(struct ub_ctx* ctx, char* data);
|
||||
|
||||
.. only:: man
|
||||
|
||||
**#include <unbound.h>**
|
||||
|
||||
struct ub_ctx \* **ub_ctx_create**\ (void);
|
||||
|
||||
void **ub_ctx_delete**\ (struct ub_ctx\* ctx);
|
||||
|
||||
int **ub_ctx_set_option**\ (struct ub_ctx\* ctx, char\* opt, char\* val);
|
||||
|
||||
int **ub_ctx_get_option**\ (struct ub_ctx\* ctx, char\* opt, char\*\* val);
|
||||
|
||||
int **ub_ctx_config**\ (struct ub_ctx\* ctx, char* fname);
|
||||
|
||||
int **ub_ctx_set_fwd**\ (struct ub_ctx\* ctx, char\* addr);
|
||||
|
||||
int **ub_ctx_set_stub**\ (struct ub_ctx\* ctx, char\* zone, char\* addr,
|
||||
int isprime);
|
||||
|
||||
int **ub_ctx_set_tls**\ (struct ub_ctx\* ctx, int tls);
|
||||
|
||||
int **ub_ctx_resolvconf**\ (struct ub_ctx\* ctx, char\* fname);
|
||||
|
||||
int **ub_ctx_hosts**\ (struct ub_ctx\* ctx, char\* fname);
|
||||
|
||||
int **ub_ctx_add_ta**\ (struct ub_ctx\* ctx, char\* ta);
|
||||
|
||||
int **ub_ctx_add_ta_autr**\ (struct ub_ctx\* ctx, char\* fname);
|
||||
|
||||
int **ub_ctx_add_ta_file**\ (struct ub_ctx\* ctx, char\* fname);
|
||||
|
||||
int **ub_ctx_trustedkeys**\ (struct ub_ctx\* ctx, char\* fname);
|
||||
|
||||
int **ub_ctx_debugout**\ (struct ub_ctx\* ctx, FILE\* out);
|
||||
|
||||
int **ub_ctx_debuglevel**\ (struct ub_ctx\* ctx, int d);
|
||||
|
||||
int **ub_ctx_async**\ (struct ub_ctx\* ctx, int dothread);
|
||||
|
||||
int **ub_poll**\ (struct ub_ctx\* ctx);
|
||||
|
||||
int **ub_wait**\ (struct ub_ctx\* ctx);
|
||||
|
||||
int **ub_fd**\ (struct ub_ctx\* ctx);
|
||||
|
||||
int **ub_process**\ (struct ub_ctx\* ctx);
|
||||
|
||||
int **ub_resolve**\ (struct ub_ctx\* ctx, char\* name,
|
||||
int rrtype, int rrclass, struct ub_result\*\* result);
|
||||
|
||||
int **ub_resolve_async**\ (struct ub_ctx\* ctx, char\* name,
|
||||
int rrtype, int rrclass, void\* mydata,
|
||||
ub_callback_type\* callback, int\* async_id);
|
||||
|
||||
int **ub_cancel**\ (struct ub_ctx\* ctx, int async_id);
|
||||
|
||||
void **ub_resolve_free**\ (struct ub_result\* result);
|
||||
|
||||
const char \* **ub_strerror**\ (int err);
|
||||
|
||||
int **ub_ctx_print_local_zones**\ (struct ub_ctx\* ctx);
|
||||
|
||||
int **ub_ctx_zone_add**\ (struct ub_ctx\* ctx, char\* zone_name, char\* zone_type);
|
||||
|
||||
int **ub_ctx_zone_remove**\ (struct ub_ctx\* ctx, char\* zone_name);
|
||||
|
||||
int **ub_ctx_data_add**\ (struct ub_ctx\* ctx, char\* data);
|
||||
|
||||
int **ub_ctx_data_remove**\ (struct ub_ctx\* ctx, char\* data);
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
Unbound 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 :doc:`unbound(8)</manpages/unbound>`.
|
||||
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.
|
||||
|
||||
The library uses a variable of type *struct ub_ctx* to keep context between
|
||||
calls.
|
||||
The user must maintain it, creating it with **ub_ctx_create** and deleting it
|
||||
with **ub_ctx_delete**.
|
||||
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.
|
||||
|
||||
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 can go
|
||||
on, while the results become available later.
|
||||
|
||||
The functions are discussed in turn below.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. glossary::
|
||||
|
||||
ub_ctx_create
|
||||
Create a new context, initialised with defaults.
|
||||
The information from :file:`/etc/resolv.conf` and :file:`/etc/hosts` is
|
||||
not utilised by default.
|
||||
Use **ub_ctx_resolvconf** and **ub_ctx_hosts** to read them.
|
||||
Before you call this, use the openssl functions
|
||||
**CRYPTO_set_id_callback** and **CRYPTO_set_locking_callback** to set
|
||||
up asynchronous operation if you use lib openssl (the application calls
|
||||
these functions once for initialisation).
|
||||
Openssl 1.0.0 or later uses the **CRYPTO_THREADID_set_callback**
|
||||
function.
|
||||
|
||||
ub_ctx_delete
|
||||
Delete validation context and free associated resources.
|
||||
Outstanding async queries are killed and callbacks are not called for
|
||||
them.
|
||||
|
||||
ub_ctx_set_option
|
||||
A power-user interface that lets you specify one of the options from
|
||||
the config file format, see :doc:`unbound.conf(5)</manpages/unbound.conf>`.
|
||||
Not all options are relevant.
|
||||
For some specific options, such as adding trust anchors, special
|
||||
routines exist.
|
||||
Pass the option name with the trailing ``':'``.
|
||||
|
||||
ub_ctx_get_option
|
||||
A power-user interface that gets an option value.
|
||||
Some options cannot be gotten, and others return a newline separated
|
||||
list.
|
||||
Pass the option name without trailing ``':'``.
|
||||
The returned value must be free(2)d by the caller.
|
||||
|
||||
ub_ctx_config
|
||||
A power-user interface that lets you specify an unbound config file,
|
||||
see :doc:`unbound.conf(5)</manpages/unbound.conf>`, which is read for
|
||||
configuration.
|
||||
Not all options are relevant.
|
||||
For some specific options, such as adding trust anchors, special
|
||||
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.
|
||||
|
||||
ub_ctx_set_fwd
|
||||
Set machine to forward DNS queries to, the caching resolver to use.
|
||||
IP4 or IP6 address.
|
||||
Forwards all DNS requests to that machine, which is expected to run a
|
||||
recursive resolver.
|
||||
If the proxy is not DNSSEC capable, validation may fail.
|
||||
Can be called several times, in that case the addresses are used as
|
||||
backup servers.
|
||||
At this time it is only possible to set configuration before the first
|
||||
resolve is done.
|
||||
|
||||
ub_ctx_set_stub
|
||||
Set a stub zone, authoritative dns servers to use for a particular
|
||||
zone.
|
||||
IP4 or IP6 address.
|
||||
If the address is NULL the stub entry is removed.
|
||||
Set isprime true if you configure root hints with it.
|
||||
Otherwise similar to the stub zone item from unbound's config file.
|
||||
Can be called several times, 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.
|
||||
|
||||
ub_ctx_set_tls
|
||||
Enable DNS over TLS (DoT) for machines set with **ub_ctx_set_fwd**.
|
||||
At this time it is only possible to set configuration before the first
|
||||
resolve is done.
|
||||
|
||||
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 filename given.
|
||||
Usually :file:`"/etc/resolv.conf"`.
|
||||
Uses those nameservers as caching proxies.
|
||||
If they do not support DNSSEC, validation may fail.
|
||||
Only nameservers are picked up, the searchdomain, ndots and other
|
||||
settings from *resolv.conf(5)* are ignored.
|
||||
If fname NULL is passed, :file:`"/etc/resolv.conf"` is used (if on
|
||||
Windows, the system-wide configured nameserver is picked instead).
|
||||
At this time it is only possible to set configuration before the first
|
||||
resolve is done.
|
||||
|
||||
ub_ctx_hosts
|
||||
Read list of hosts from the filename given.
|
||||
Usually :file:`"/etc/hosts"`.
|
||||
When queried for, these addresses are not marked DNSSEC secure.
|
||||
If fname NULL is passed, :file:`"/etc/hosts"` is used (if on Windows,
|
||||
:file:`etc/hosts` from WINDIR is picked instead).
|
||||
At this time it is only possible to set configuration before the first
|
||||
resolve is done.
|
||||
|
||||
ub_ctx_add_ta
|
||||
Add a trust anchor to the given context.
|
||||
At this time it is only possible to add trusted keys before the first
|
||||
resolve is done.
|
||||
The format is a string, similar to the zone-file format,
|
||||
**[domainname]** **[type]** **[rdata contents]**.
|
||||
Both DS and DNSKEY records are accepted.
|
||||
|
||||
ub_ctx_add_ta_autr
|
||||
Add filename with automatically tracked trust anchor to the given
|
||||
context.
|
||||
Pass name of a file with the managed trust anchor.
|
||||
You can create this file with
|
||||
:doc:`unbound-anchor(8)</manpages/unbound-anchor>` for the root anchor.
|
||||
You can also create it with an initial file with one line with a DNSKEY
|
||||
or DS record.
|
||||
If the file is writable, it is updated when the trust anchor changes.
|
||||
At this time it is only possible to add trusted keys before the first
|
||||
resolve is done.
|
||||
|
||||
ub_ctx_add_ta_file
|
||||
Add trust anchors to the given context.
|
||||
Pass name of a file with DS and DNSKEY records in zone file format.
|
||||
At this time it is only possible to add trusted keys before the first
|
||||
resolve is done.
|
||||
|
||||
ub_ctx_trustedkeys
|
||||
Add trust anchors to the given context.
|
||||
Pass the name of a bind-style config file with ``trusted-keys{}``.
|
||||
At this time it is only possible to add trusted keys before the first
|
||||
resolve is done.
|
||||
|
||||
ub_ctx_debugout
|
||||
Set debug and error log output to the given stream.
|
||||
Pass NULL to disable output.
|
||||
Default is stderr.
|
||||
File-names or using syslog can be enabled using config options, this
|
||||
routine is for using your own stream.
|
||||
|
||||
ub_ctx_debuglevel
|
||||
Set debug verbosity for the context.
|
||||
Output is directed to stderr.
|
||||
Higher debug level gives more output.
|
||||
|
||||
ub_ctx_async
|
||||
Set a context behaviour for asynchronous action.
|
||||
if set to true, enables threading and a call to **ub_resolve_async**
|
||||
creates a thread to handle work in the background.
|
||||
If false, a process is forked to handle work in the background.
|
||||
Changes to this setting after **ub_resolve_async** calls have been made
|
||||
have no effect (delete and re-create the context to change).
|
||||
|
||||
ub_poll
|
||||
Poll a context to see if it has any new results.
|
||||
Do not poll in a loop, instead extract the **fd** below to poll for
|
||||
readiness, and then check, or wait using the wait routine.
|
||||
Returns 0 if nothing to read, or nonzero if a result is available.
|
||||
If nonzero, call **ub_process** to do callbacks.
|
||||
|
||||
ub_wait
|
||||
Wait for a context to finish with results.
|
||||
Calls **ub_process** after the wait for you.
|
||||
After the wait, there are no more outstanding asynchronous queries.
|
||||
|
||||
ub_fd
|
||||
Get file descriptor.
|
||||
Wait for it to become readable, at this point answers are returned from
|
||||
the asynchronous validating resolver.
|
||||
Then call the **ub_process** to continue processing.
|
||||
|
||||
ub_process
|
||||
Call this routine to continue processing results from the validating
|
||||
resolver (when the **fd** becomes readable).
|
||||
Will perform necessary callbacks.
|
||||
|
||||
ub_resolve
|
||||
Perform resolution and validation of the target name.
|
||||
The name is a domain name in a zero terminated text string.
|
||||
The rrtype and rrclass are DNS type and class codes.
|
||||
The result structure is newly allocated with the resulting data.
|
||||
|
||||
ub_resolve_async
|
||||
Perform asynchronous resolution and validation of the target name.
|
||||
Arguments mean the same as for **ub_resolve** except no data is
|
||||
returned immediately, instead a callback is called later.
|
||||
The callback receives a copy of the mydata pointer, that you can use to
|
||||
pass information to the callback.
|
||||
The callback type is a function pointer to a function declared as:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void my_callback_function(void* my_arg, int err,
|
||||
struct ub_result* result);
|
||||
|
||||
The **async_id** is returned so you can (at your option) decide to
|
||||
track it and cancel the request if needed.
|
||||
If you pass a NULL pointer the **async_id** is not returned.
|
||||
|
||||
ub_cancel
|
||||
Cancel an async query in progress.
|
||||
This may return an error if the query does not exist, or the query is
|
||||
already being delivered, in that case you may still get a callback for
|
||||
the query.
|
||||
|
||||
ub_resolve_free
|
||||
Free struct **ub_result** contents after use.
|
||||
|
||||
ub_strerror
|
||||
Convert error value from one of the unbound library functions to a
|
||||
human readable string.
|
||||
|
||||
ub_ctx_print_local_zones
|
||||
Debug printout the local authority information to debug output.
|
||||
|
||||
ub_ctx_zone_add
|
||||
Add new zone to local authority info, like local-zone
|
||||
:doc:`unbound.conf(5)</manpages/unbound.conf>` statement.
|
||||
|
||||
ub_ctx_zone_remove
|
||||
Delete zone from local authority info.
|
||||
|
||||
ub_ctx_data_add
|
||||
Add resource record data to local authority info, like local-data
|
||||
:doc:`unbound.conf(5)</manpages/unbound.conf>` statement.
|
||||
|
||||
ub_ctx_data_remove
|
||||
Delete local authority data from the name given.
|
||||
|
||||
Result Data structure
|
||||
---------------------
|
||||
|
||||
The result of the DNS resolution and validation is returned as *struct
|
||||
ub_result*.
|
||||
The result structure contains the following entries:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
struct ub_result {
|
||||
char* qname; /* text string, original question */
|
||||
int qtype; /* type code asked for */
|
||||
int qclass; /* class code asked for */
|
||||
char** data; /* array of rdata items, NULL terminated*/
|
||||
int* len; /* array with lengths of rdata items */
|
||||
char* canonname; /* canonical name of result */
|
||||
int rcode; /* additional error code in case of no data */
|
||||
void* answer_packet; /* full network format answer packet */
|
||||
int answer_len; /* length of packet in octets */
|
||||
int havedata; /* true if there is data */
|
||||
int nxdomain; /* true if nodata because name does not exist */
|
||||
int secure; /* true if result is secure */
|
||||
int bogus; /* true if a security failure happened */
|
||||
char* why_bogus; /* string with error if bogus */
|
||||
int was_ratelimited; /* true if the query was ratelimited (SERVFAIL) by unbound */
|
||||
int ttl; /* number of seconds the result is valid */
|
||||
};
|
||||
|
||||
If both secure and bogus are false, security was not enabled for the domain of
|
||||
the query.
|
||||
Else, they are not both true, one of them is true.
|
||||
|
||||
Return Values
|
||||
-------------
|
||||
|
||||
Many routines return an error code.
|
||||
The value 0 (zero) denotes no error happened.
|
||||
Other values can be passed to **ub_strerror** to obtain a readable error
|
||||
string.
|
||||
**ub_strerror** returns a zero terminated string.
|
||||
**ub_ctx_create** returns NULL on an error (a malloc failure).
|
||||
**ub_poll** returns true if some information may be available, false otherwise.
|
||||
**ub_fd** returns a file descriptor or -1 on error.
|
||||
**ub_ctx_config** and **ub_ctx_resolvconf** attempt to leave errno informative
|
||||
on a function return with file read failure.
|
||||
|
||||
See Also
|
||||
--------
|
||||
|
||||
:doc:`unbound.conf(5)</manpages/unbound.conf>`, :doc:`unbound(8)</manpages/unbound>`.
|
||||
+255
-135
@@ -1,189 +1,309 @@
|
||||
.TH "unbound-anchor" "8" "@date@" "NLnet Labs" "unbound @version@"
|
||||
.\"
|
||||
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
|
||||
.\"
|
||||
.\" Copyright (c) 2008, NLnet Labs. All rights reserved.
|
||||
.\"
|
||||
.\" See LICENSE for the license.
|
||||
.\"
|
||||
.\"
|
||||
.SH "NAME"
|
||||
.B unbound\-anchor
|
||||
\- Unbound anchor utility.
|
||||
.SH "SYNOPSIS"
|
||||
.B unbound\-anchor
|
||||
.RB [ opts ]
|
||||
.SH "DESCRIPTION"
|
||||
.B Unbound\-anchor
|
||||
performs setup or update of the root trust anchor for DNSSEC validation.
|
||||
The program fetches the trust anchor with the method from RFC7958 when
|
||||
regular RFC5011 update fails to bring it up to date.
|
||||
It can be run (as root) from the commandline, or run as part of startup
|
||||
scripts. Before you start the \fIunbound\fR(8) DNS server.
|
||||
.P
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.
|
||||
.nr rst2man-indent-level 0
|
||||
.
|
||||
.de1 rstReportMargin
|
||||
\\$1 \\n[an-margin]
|
||||
level \\n[rst2man-indent-level]
|
||||
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
-
|
||||
\\n[rst2man-indent0]
|
||||
\\n[rst2man-indent1]
|
||||
\\n[rst2man-indent2]
|
||||
..
|
||||
.de1 INDENT
|
||||
.\" .rstReportMargin pre:
|
||||
. RS \\$1
|
||||
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
|
||||
. nr rst2man-indent-level +1
|
||||
.\" .rstReportMargin post:
|
||||
..
|
||||
.de UNINDENT
|
||||
. RE
|
||||
.\" indent \\n[an-margin]
|
||||
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.nr rst2man-indent-level -1
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "UNBOUND-ANCHOR" "8" "@date@" "@version@" "Unbound"
|
||||
.SH NAME
|
||||
unbound-anchor \- Unbound @version@ anchor utility.
|
||||
.SH SYNOPSIS
|
||||
.sp
|
||||
\fBunbound\-anchor\fP [\fBopts\fP]
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
\fBunbound\-anchor\fP performs setup or update of the root trust anchor for DNSSEC
|
||||
validation.
|
||||
The program fetches the trust anchor with the method from \fI\%RFC 7958\fP when
|
||||
regular \fI\%RFC 5011\fP update fails to bring it up to date.
|
||||
It can be run from the commandline, or run as part of startup scripts before
|
||||
you start the \fI\%unbound(8)\fP DNS server.
|
||||
.sp
|
||||
Note that if you want to use \fI\%RFC 5011\fP with Unbound (i.e., the
|
||||
\fI\%auto\-trust\-anchor\-file\fP option) so
|
||||
that trust anchor information is automatically tracked by Unbound during
|
||||
operation, the user that Unbound runs under (by default \(aqunbound\(aq) must have
|
||||
write permissions to the file and the directory the file lives in (for creating
|
||||
temporary files).
|
||||
In this case you would probably want to run this program as the designated
|
||||
Unbound user.
|
||||
.sp
|
||||
Suggested usage:
|
||||
.P
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.nf
|
||||
# in the init scripts.
|
||||
# provide or update the root anchor (if necessary)
|
||||
unbound-anchor \-a "@UNBOUND_ROOTKEY_FILE@"
|
||||
# Please note usage of this root anchor is at your own risk
|
||||
# and under the terms of our LICENSE (see source).
|
||||
#
|
||||
# start validating resolver
|
||||
# the unbound.conf contains:
|
||||
# auto-trust-anchor-file: "@UNBOUND_ROOTKEY_FILE@"
|
||||
unbound \-c unbound.conf
|
||||
.ft C
|
||||
# in the init scripts.
|
||||
# provide or update the root anchor (if necessary)
|
||||
unbound\-anchor \-a \(dq@UNBOUND_ROOTKEY_FILE@\(dq
|
||||
|
||||
# Please note usage of this root anchor is at your own risk
|
||||
# and under the terms of our LICENSE (see source).
|
||||
#
|
||||
# start validating resolver
|
||||
# the unbound.conf contains:
|
||||
# auto\-trust\-anchor\-file: \(dq@UNBOUND_ROOTKEY_FILE@\(dq
|
||||
unbound \-c unbound.conf
|
||||
.ft P
|
||||
.fi
|
||||
.P
|
||||
This tool provides builtin default contents for the root anchor and root
|
||||
update certificate files.
|
||||
.P
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
This tool provides builtin default contents for the root anchor and root update
|
||||
certificate files.
|
||||
.sp
|
||||
It tests if the root anchor file works, and if not, and an update is possible,
|
||||
attempts to update the root anchor using the root update certificate.
|
||||
It performs a https fetch of root-anchors.xml and checks the results (RFC7958),
|
||||
if all checks are successful, it updates the root anchor file. Otherwise
|
||||
the root anchor file is unchanged. It performs RFC5011 tracking if the
|
||||
DNSSEC information available via the DNS makes that possible.
|
||||
.P
|
||||
It does not perform an update if the certificate is expired, if the network
|
||||
is down or other errors occur.
|
||||
.P
|
||||
It performs a https fetch of
|
||||
\fI\%root\-anchors.xml\fP
|
||||
and checks the results (\fI\%RFC 7958\fP); if all checks are successful, it updates
|
||||
the root anchor file.
|
||||
Otherwise the root anchor file is unchanged.
|
||||
It performs \fI\%RFC 5011\fP tracking if the DNSSEC information available via the
|
||||
DNS makes that possible.
|
||||
.sp
|
||||
It does not perform an update if the certificate is expired, if the network is
|
||||
down or other errors occur.
|
||||
.sp
|
||||
The available options are:
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-a \fIfile
|
||||
.B \-a <file>
|
||||
The root anchor key file, that is read in and written out.
|
||||
Default is @UNBOUND_ROOTKEY_FILE@.
|
||||
If the file does not exist, or is empty, a builtin root key is written to it.
|
||||
Default is \fB@UNBOUND_ROOTKEY_FILE@\fP\&.
|
||||
If the file does not exist, or is empty, a builtin root key is written
|
||||
to it.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-c \fIfile
|
||||
.B \-c <file>
|
||||
The root update certificate file, that is read in.
|
||||
Default is @UNBOUND_ROOTCERT_FILE@.
|
||||
Default is \fB@UNBOUND_ROOTCERT_FILE@\fP\&.
|
||||
If the file does not exist, or is empty, a builtin certificate is used.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-l
|
||||
List the builtin root key and builtin root update certificate on stdout.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-u \fIname
|
||||
The server name, it connects to https://name. Specify without https:// prefix.
|
||||
The default is "data.iana.org". It connects to the port specified with \-P.
|
||||
.B \-u <name>
|
||||
The server name, it connects to \fBhttps://name\fP\&.
|
||||
Specify without \fBhttps://\fP prefix.
|
||||
The default is \fB\(dqdata.iana.org\(dq\fP\&.
|
||||
It connects to the port specified with \fI\%\-P\fP\&.
|
||||
You can pass an IPv4 address or IPv6 address (no brackets) if you want.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-S
|
||||
Do not use SNI for the HTTPS connection. Default is to use SNI.
|
||||
Do not use SNI for the HTTPS connection.
|
||||
Default is to use SNI.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.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).
|
||||
.B \-b <address>
|
||||
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).
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.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.
|
||||
.B \-x <path>
|
||||
The pathname to the root\-anchors.xml file on the server.
|
||||
(forms URL with \fI\%\-u\fP).
|
||||
The default is \fB/root\-anchors/root\-anchors.xml\fP\&.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-s \fIpath
|
||||
The pathname to the root\-anchors.p7s file on the server. (forms URL with \-u).
|
||||
The default is /root\-anchors/root\-anchors.p7s. This file has to be a PKCS7
|
||||
signature over the xml file, using the pem file (\-c) as trust anchor.
|
||||
.B \-s <path>
|
||||
The pathname to the root\-anchors.p7s file on the server.
|
||||
(forms URL with \fI\%\-u\fP).
|
||||
The default is \fB/root\-anchors/root\-anchors.p7s\fP\&.
|
||||
This file has to be a PKCS7 signature over the xml file, using the pem
|
||||
file (\fI\%\-c\fP) as trust anchor.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-n \fIname
|
||||
The emailAddress for the Subject of the signer's certificate from the p7s
|
||||
signature file. Only signatures from this name are allowed. default is
|
||||
dnssec@iana.org. If you pass "" then the emailAddress is not checked.
|
||||
.B \-n <name>
|
||||
The emailAddress for the Subject of the signer\(aqs certificate from the
|
||||
p7s signature file.
|
||||
Only signatures from this name are allowed.
|
||||
The default is \fBdnssec@iana.org\fP\&.
|
||||
If you pass \fB\(dq\(dq\fP then the emailAddress is not checked.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-4
|
||||
Use IPv4 for domain resolution and contacting the server on https. Default is
|
||||
to use IPv4 and IPv6 where appropriate.
|
||||
Use IPv4 for domain resolution and contacting the server on
|
||||
https.
|
||||
Default is to use IPv4 and IPv6 where appropriate.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-6
|
||||
Use IPv6 for domain resolution and contacting the server on https. Default is
|
||||
to use IPv4 and IPv6 where appropriate.
|
||||
Use IPv6 for domain resolution and contacting the server on https.
|
||||
Default is to use IPv4 and IPv6 where appropriate.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-f \fIresolv.conf
|
||||
Use the given resolv.conf file. Not enabled by default, but you could try to
|
||||
pass /etc/resolv.conf on some systems. It contains the IP addresses of the
|
||||
recursive nameservers to use. However, since this tool could be used to
|
||||
bootstrap that very recursive nameserver, it would not be useful (since
|
||||
that server is not up yet, since we are bootstrapping it). It could be
|
||||
useful in a situation where you know an upstream cache is deployed (and
|
||||
running) and in captive portal situations.
|
||||
.B \-f <resolv.conf>
|
||||
Use the given resolv.conf file.
|
||||
Not enabled by default, but you could try to pass
|
||||
\fB/etc/resolv.conf\fP on some systems.
|
||||
It contains the IP addresses of the recursive nameservers to use.
|
||||
However, since this tool could be used to bootstrap that very recursive
|
||||
nameserver, it would not be useful (since that server is not up yet,
|
||||
since we are bootstrapping it).
|
||||
It could be useful in a situation where you know an upstream cache is
|
||||
deployed (and running) and in captive portal situations.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-r \fIroot.hints
|
||||
Use the given root.hints file (same syntax as the BIND and Unbound root hints
|
||||
file) to bootstrap domain resolution. By default a list of builtin root
|
||||
hints is used. Unbound\-anchor goes to the network itself for these roots,
|
||||
to resolve the server (\-u option) and to check the root DNSKEY records.
|
||||
.B \-r <root.hints>
|
||||
Use the given root.hints file (same syntax as the BIND and Unbound root
|
||||
hints file) to bootstrap domain resolution.
|
||||
By default a list of builtin root hints is used.
|
||||
unbound\-anchor goes to the network itself for these roots, to resolve
|
||||
the server (\fI\%\-u\fP option) and to check the root DNSKEY records.
|
||||
It does so, because the tool when used for bootstrapping the recursive
|
||||
resolver, cannot use that recursive resolver itself because it is bootstrapping
|
||||
that server.
|
||||
resolver, cannot use that recursive resolver itself because it is
|
||||
bootstrapping that server.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.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.
|
||||
Allow fallback from \fI\%\-f\fP \fB<resolv.conf>\fP 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.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-v
|
||||
More verbose. Once prints informational messages, multiple times may enable
|
||||
large debug amounts (such as full certificates or byte\-dumps of downloaded
|
||||
files). By default it prints almost nothing. It also prints nothing on
|
||||
errors by default; in that case the original root anchor file is simply
|
||||
left undisturbed, so that a recursive server can start right after it.
|
||||
More verbose.
|
||||
Once prints informational messages, multiple times may enable large
|
||||
debug amounts (such as full certificates or byte\-dumps of downloaded
|
||||
files).
|
||||
By default it prints almost nothing.
|
||||
It also prints nothing on errors by default; in that case the original
|
||||
root anchor file is simply left undisturbed, so that a recursive server
|
||||
can start right after it.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-C \fIunbound.conf
|
||||
Debug option to read unbound.conf into the resolver process used.
|
||||
.B \-C <unbound.conf>
|
||||
Debug option to read \fB<unbound.conf>\fP into the resolver process
|
||||
used.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-P \fIport
|
||||
Set the port number to use for the https connection. The default is 443.
|
||||
.B \-P <port>
|
||||
Set the port number to use for the https connection.
|
||||
The default is 443.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-F
|
||||
Debug option to force update of the root anchor through downloading the xml
|
||||
file and verifying it with the certificate. By default it first tries to
|
||||
update by contacting the DNS, which uses much less bandwidth, is much
|
||||
faster (200 msec not 2 sec), and is nicer to the deployed infrastructure.
|
||||
With this option, it still attempts to do so (and may verbosely tell you),
|
||||
but then ignores the result and goes on to use the xml fallback method.
|
||||
Debug option to force update of the root anchor through downloading the
|
||||
xml file and verifying it with the certificate.
|
||||
By default it first tries to update by contacting the DNS, which uses
|
||||
much less bandwidth, is much faster (200 msec not 2 sec), and is nicer
|
||||
to the deployed infrastructure.
|
||||
With this option, it still attempts to do so (and may verbosely tell
|
||||
you), but then ignores the result and goes on to use the xml fallback
|
||||
method.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-h
|
||||
Show the version and commandline option help.
|
||||
.SH "EXIT CODE"
|
||||
.UNINDENT
|
||||
.SH EXIT CODE
|
||||
.sp
|
||||
This tool exits with value 1 if the root anchor was updated using the
|
||||
certificate or if the builtin root-anchor was used. It exits with code
|
||||
0 if no update was necessary, if the update was possible with RFC5011
|
||||
tracking, or if an error occurred.
|
||||
.P
|
||||
certificate or if the builtin root\-anchor was used.
|
||||
It exits with code 0 if no update was necessary, if the update was possible
|
||||
with \fI\%RFC 5011\fP tracking, or if an error occurred.
|
||||
.sp
|
||||
You can check the exit value in this manner:
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.nf
|
||||
unbound-anchor \-a "root.key" || logger "Please check root.key"
|
||||
.ft C
|
||||
unbound\-anchor \-a \(dqroot.key\(dq || logger \(dqPlease check root.key\(dq
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
Or something more suitable for your operational environment.
|
||||
.SH "TRUST"
|
||||
The root keys and update certificate included in this tool
|
||||
are provided for convenience and under the terms of our
|
||||
license (see the LICENSE file in the source distribution or
|
||||
http://unbound.nlnetlabs.nl/svn/trunk/LICENSE) and might be stale or
|
||||
not suitable to your purpose.
|
||||
.P
|
||||
By running "unbound\-anchor \-l" the keys and certificate that are
|
||||
.SH TRUST
|
||||
.sp
|
||||
The root keys and update certificate included in this tool are provided for
|
||||
convenience and under the terms of our license (see the LICENSE file in the
|
||||
source distribution or \fI\%https://github.com/NLnetLabs/unbound/blob/master/LICENSE\fP
|
||||
and might be stale or not suitable to your purpose.
|
||||
.sp
|
||||
By running \fI\%unbound\-anchor \-l\fP the keys and certificate that are
|
||||
configured in the code are printed for your convenience.
|
||||
.P
|
||||
The build\-in configuration can be overridden by providing a root\-cert
|
||||
file and a rootkey file.
|
||||
.SH "FILES"
|
||||
.sp
|
||||
The built\-in configuration can be overridden by providing a root\-cert file and
|
||||
a rootkey file.
|
||||
.SH FILES
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.I @UNBOUND_ROOTKEY_FILE@
|
||||
The root anchor file, updated with 5011 tracking, and read and written to.
|
||||
.B @UNBOUND_ROOTKEY_FILE@
|
||||
The root anchor file, updated with 5011 tracking, and read and written
|
||||
to.
|
||||
The file is created if it does not exist.
|
||||
.TP
|
||||
.I @UNBOUND_ROOTCERT_FILE@
|
||||
The trusted self\-signed certificate that is used to verify the downloaded
|
||||
DNSSEC root trust anchor. You can update it by fetching it from
|
||||
https://data.iana.org/root\-anchors/icannbundle.pem (and validate it).
|
||||
.B @UNBOUND_ROOTCERT_FILE@
|
||||
The trusted self\-signed certificate that is used to verify the
|
||||
downloaded DNSSEC root trust anchor.
|
||||
You can update it by fetching it from
|
||||
\fI\%https://data.iana.org/root\-anchors/icannbundle.pem\fP (and validate it).
|
||||
If the file does not exist or is empty, a builtin version is used.
|
||||
.TP
|
||||
.I https://data.iana.org/root\-anchors/root\-anchors.xml
|
||||
.B \fI\%https://data.iana.org/root\-anchors/root\-anchors.xml\fP
|
||||
Source for the root key information.
|
||||
.TP
|
||||
.I https://data.iana.org/root\-anchors/root\-anchors.p7s
|
||||
.B \fI\%https://data.iana.org/root\-anchors/root\-anchors.p7s\fP
|
||||
Signature on the root key information.
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound\fR(8).
|
||||
.UNINDENT
|
||||
.SH SEE ALSO
|
||||
.sp
|
||||
\fI\%unbound.conf(5)\fP,
|
||||
\fI\%unbound(8)\fP\&.
|
||||
.SH AUTHOR
|
||||
Unbound developers are mentioned in the CREDITS file in the distribution.
|
||||
.SH COPYRIGHT
|
||||
1999-2026, NLnet Labs
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
|
||||
@@ -0,0 +1,290 @@
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
.. program:: unbound-anchor
|
||||
|
||||
unbound-anchor(8)
|
||||
=================
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
**unbound-anchor** [``opts``]
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
``unbound-anchor`` performs setup or update of the root trust anchor for DNSSEC
|
||||
validation.
|
||||
The program fetches the trust anchor with the method from :rfc:`7958` when
|
||||
regular :rfc:`5011` update fails to bring it up to date.
|
||||
It can be run from the commandline, or run as part of startup scripts before
|
||||
you start the :doc:`unbound(8)</manpages/unbound>` DNS server.
|
||||
|
||||
Note that if you want to use :rfc:`5011` with Unbound (i.e., the
|
||||
:ref:`auto-trust-anchor-file<unbound.conf.auto-trust-anchor-file>` option) so
|
||||
that trust anchor information is automatically tracked by Unbound during
|
||||
operation, the user that Unbound runs under (by default 'unbound') must have
|
||||
write permissions to the file and the directory the file lives in (for creating
|
||||
temporary files).
|
||||
In this case you would probably want to run this program as the designated
|
||||
Unbound user.
|
||||
|
||||
Suggested usage:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
# in the init scripts.
|
||||
# provide or update the root anchor (if necessary)
|
||||
unbound-anchor -a "@UNBOUND_ROOTKEY_FILE@"
|
||||
|
||||
# Please note usage of this root anchor is at your own risk
|
||||
# and under the terms of our LICENSE (see source).
|
||||
#
|
||||
# start validating resolver
|
||||
# the unbound.conf contains:
|
||||
# auto-trust-anchor-file: "@UNBOUND_ROOTKEY_FILE@"
|
||||
unbound -c unbound.conf
|
||||
|
||||
This tool provides builtin default contents for the root anchor and root update
|
||||
certificate files.
|
||||
|
||||
It tests if the root anchor file works, and if not, and an update is possible,
|
||||
attempts to update the root anchor using the root update certificate.
|
||||
It performs a https fetch of
|
||||
`root-anchors.xml <http://data.iana.org/root-anchors/root-anchors.xml>`__
|
||||
and checks the results (:rfc:`7958`); if all checks are successful, it updates
|
||||
the root anchor file.
|
||||
Otherwise the root anchor file is unchanged.
|
||||
It performs :rfc:`5011` tracking if the DNSSEC information available via the
|
||||
DNS makes that possible.
|
||||
|
||||
It does not perform an update if the certificate is expired, if the network is
|
||||
down or other errors occur.
|
||||
|
||||
The available options are:
|
||||
|
||||
.. option:: -a <file>
|
||||
|
||||
The root anchor key file, that is read in and written out.
|
||||
Default is :file:`@UNBOUND_ROOTKEY_FILE@`.
|
||||
If the file does not exist, or is empty, a builtin root key is written
|
||||
to it.
|
||||
|
||||
.. option:: -c <file>
|
||||
|
||||
The root update certificate file, that is read in.
|
||||
Default is :file:`@UNBOUND_ROOTCERT_FILE@`.
|
||||
If the file does not exist, or is empty, a builtin certificate is used.
|
||||
|
||||
.. option:: -l
|
||||
|
||||
List the builtin root key and builtin root update certificate on stdout.
|
||||
|
||||
.. option:: -u <name>
|
||||
|
||||
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 :option:`-P`.
|
||||
You can pass an IPv4 address or IPv6 address (no brackets) if you want.
|
||||
|
||||
.. option:: -S
|
||||
|
||||
Do not use SNI for the HTTPS connection.
|
||||
Default is to use SNI.
|
||||
|
||||
.. option:: -b <address>
|
||||
|
||||
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).
|
||||
|
||||
.. option:: -x <path>
|
||||
|
||||
The pathname to the root-anchors.xml file on the server.
|
||||
(forms URL with :option:`-u`).
|
||||
The default is :file:`/root-anchors/root-anchors.xml`.
|
||||
|
||||
.. option:: -s <path>
|
||||
|
||||
The pathname to the root-anchors.p7s file on the server.
|
||||
(forms URL with :option:`-u`).
|
||||
The default is :file:`/root-anchors/root-anchors.p7s`.
|
||||
This file has to be a PKCS7 signature over the xml file, using the pem
|
||||
file (:option:`-c`) as trust anchor.
|
||||
|
||||
.. option:: -n <name>
|
||||
|
||||
The emailAddress for the Subject of the signer's certificate from the
|
||||
p7s signature file.
|
||||
Only signatures from this name are allowed.
|
||||
The default is ``dnssec@iana.org``.
|
||||
If you pass ``""`` then the emailAddress is not checked.
|
||||
|
||||
.. option:: -4
|
||||
|
||||
Use IPv4 for domain resolution and contacting the server on
|
||||
https.
|
||||
Default is to use IPv4 and IPv6 where appropriate.
|
||||
|
||||
.. option:: -6
|
||||
|
||||
Use IPv6 for domain resolution and contacting the server on https.
|
||||
Default is to use IPv4 and IPv6 where appropriate.
|
||||
|
||||
.. option:: -f <resolv.conf>
|
||||
|
||||
Use the given resolv.conf file.
|
||||
Not enabled by default, but you could try to pass
|
||||
:file:`/etc/resolv.conf` on some systems.
|
||||
It contains the IP addresses of the recursive nameservers to use.
|
||||
However, since this tool could be used to bootstrap that very recursive
|
||||
nameserver, it would not be useful (since that server is not up yet,
|
||||
since we are bootstrapping it).
|
||||
It could be useful in a situation where you know an upstream cache is
|
||||
deployed (and running) and in captive portal situations.
|
||||
|
||||
.. option:: -r <root.hints>
|
||||
|
||||
Use the given root.hints file (same syntax as the BIND and Unbound root
|
||||
hints file) to bootstrap domain resolution.
|
||||
By default a list of builtin root hints is used.
|
||||
unbound-anchor goes to the network itself for these roots, to resolve
|
||||
the server (:option:`-u` option) and to check the root DNSKEY records.
|
||||
It does so, because the tool when used for bootstrapping the recursive
|
||||
resolver, cannot use that recursive resolver itself because it is
|
||||
bootstrapping that server.
|
||||
|
||||
.. option:: -R
|
||||
|
||||
Allow fallback from :option:`-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.
|
||||
|
||||
.. option:: -v
|
||||
|
||||
More verbose.
|
||||
Once prints informational messages, multiple times may enable large
|
||||
debug amounts (such as full certificates or byte-dumps of downloaded
|
||||
files).
|
||||
By default it prints almost nothing.
|
||||
It also prints nothing on errors by default; in that case the original
|
||||
root anchor file is simply left undisturbed, so that a recursive server
|
||||
can start right after it.
|
||||
|
||||
.. option:: -C <unbound.conf>
|
||||
|
||||
Debug option to read :file:`<unbound.conf>` into the resolver process
|
||||
used.
|
||||
|
||||
.. option:: -P <port>
|
||||
|
||||
Set the port number to use for the https connection.
|
||||
The default is 443.
|
||||
|
||||
.. option:: -F
|
||||
|
||||
Debug option to force update of the root anchor through downloading the
|
||||
xml file and verifying it with the certificate.
|
||||
By default it first tries to update by contacting the DNS, which uses
|
||||
much less bandwidth, is much faster (200 msec not 2 sec), and is nicer
|
||||
to the deployed infrastructure.
|
||||
With this option, it still attempts to do so (and may verbosely tell
|
||||
you), but then ignores the result and goes on to use the xml fallback
|
||||
method.
|
||||
|
||||
.. option:: -h
|
||||
|
||||
Show the version and commandline option help.
|
||||
|
||||
Exit Code
|
||||
---------
|
||||
|
||||
This tool exits with value 1 if the root anchor was updated using the
|
||||
certificate or if the builtin root-anchor was used.
|
||||
It exits with code 0 if no update was necessary, if the update was possible
|
||||
with :rfc:`5011` tracking, or if an error occurred.
|
||||
|
||||
You can check the exit value in this manner:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
unbound-anchor -a "root.key" || logger "Please check root.key"
|
||||
|
||||
Or something more suitable for your operational environment.
|
||||
|
||||
Trust
|
||||
-----
|
||||
|
||||
The root keys and update certificate included in this tool are provided for
|
||||
convenience and under the terms of our license (see the LICENSE file in the
|
||||
source distribution or https://github.com/NLnetLabs/unbound/blob/master/LICENSE
|
||||
and might be stale or not suitable to your purpose.
|
||||
|
||||
By running :option:`unbound-anchor -l` the keys and certificate that are
|
||||
configured in the code are printed for your convenience.
|
||||
|
||||
The built-in configuration can be overridden by providing a root-cert file and
|
||||
a rootkey file.
|
||||
|
||||
Files
|
||||
-----
|
||||
|
||||
@UNBOUND_ROOTKEY_FILE@
|
||||
The root anchor file, updated with 5011 tracking, and read and written
|
||||
to.
|
||||
The file is created if it does not exist.
|
||||
|
||||
@UNBOUND_ROOTCERT_FILE@
|
||||
The trusted self-signed certificate that is used to verify the
|
||||
downloaded DNSSEC root trust anchor.
|
||||
You can update it by fetching it from
|
||||
https://data.iana.org/root-anchors/icannbundle.pem (and validate it).
|
||||
If the file does not exist or is empty, a builtin version is used.
|
||||
|
||||
https://data.iana.org/root-anchors/root-anchors.xml
|
||||
Source for the root key information.
|
||||
|
||||
https://data.iana.org/root-anchors/root-anchors.p7s
|
||||
Signature on the root key information.
|
||||
|
||||
See Also
|
||||
--------
|
||||
|
||||
:doc:`unbound.conf(5)</manpages/unbound.conf>`,
|
||||
:doc:`unbound(8)</manpages/unbound>`.
|
||||
+83
-42
@@ -1,52 +1,93 @@
|
||||
.TH "unbound-checkconf" "8" "@date@" "NLnet Labs" "unbound @version@"
|
||||
.\"
|
||||
.\" unbound-checkconf.8 -- unbound configuration checker manual
|
||||
.\"
|
||||
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
|
||||
.\"
|
||||
.\" See LICENSE for the license.
|
||||
.\"
|
||||
.\"
|
||||
.SH "NAME"
|
||||
unbound\-checkconf
|
||||
\- Check unbound configuration file for errors.
|
||||
.SH "SYNOPSIS"
|
||||
.B unbound\-checkconf
|
||||
.RB [ \-h ]
|
||||
.RB [ \-f ]
|
||||
.RB [ \-o
|
||||
.IR option ]
|
||||
.RI [ cfgfile ]
|
||||
.SH "DESCRIPTION"
|
||||
.B Unbound\-checkconf
|
||||
checks the configuration file for the
|
||||
\fIunbound\fR(8)
|
||||
DNS resolver for syntax and other errors.
|
||||
The config file syntax is described in
|
||||
\fIunbound.conf\fR(5).
|
||||
.P
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.
|
||||
.nr rst2man-indent-level 0
|
||||
.
|
||||
.de1 rstReportMargin
|
||||
\\$1 \\n[an-margin]
|
||||
level \\n[rst2man-indent-level]
|
||||
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
-
|
||||
\\n[rst2man-indent0]
|
||||
\\n[rst2man-indent1]
|
||||
\\n[rst2man-indent2]
|
||||
..
|
||||
.de1 INDENT
|
||||
.\" .rstReportMargin pre:
|
||||
. RS \\$1
|
||||
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
|
||||
. nr rst2man-indent-level +1
|
||||
.\" .rstReportMargin post:
|
||||
..
|
||||
.de UNINDENT
|
||||
. RE
|
||||
.\" indent \\n[an-margin]
|
||||
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.nr rst2man-indent-level -1
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "UNBOUND-CHECKCONF" "8" "@date@" "@version@" "Unbound"
|
||||
.SH NAME
|
||||
unbound-checkconf \- Check Unbound @version@ configuration file for errors.
|
||||
.SH SYNOPSIS
|
||||
.sp
|
||||
\fBunbound\-checkconf\fP [\fB\-hf\fP] [\fB\-o option\fP] [cfgfile]
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
\fBunbound\-checkconf\fP checks the configuration file for the
|
||||
\fI\%unbound(8)\fP DNS resolver for syntax and other errors.
|
||||
The config file syntax is described in
|
||||
\fI\%unbound.conf(5)\fP\&.
|
||||
.sp
|
||||
The available options are:
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-h
|
||||
Show the version and commandline option help.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-f
|
||||
Print full pathname, with chroot applied to it. Use with the \-o option.
|
||||
Print full pathname, with chroot applied to it.
|
||||
Use with the \fI\%\-o\fP option.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-o\fI option
|
||||
If given, after checking the config file the value of this option is
|
||||
printed to stdout. For "" (disabled) options an empty line is printed.
|
||||
.B \-q
|
||||
Make the operation quiet, suppress output on success.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.I cfgfile
|
||||
The config file to read with settings for unbound. It is checked.
|
||||
.B \-o <option>
|
||||
If given, after checking the config file the value of this option is
|
||||
printed to stdout.
|
||||
For \fB\(dq\(dq\fP (disabled) options an empty line is printed.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B cfgfile
|
||||
The config file to read with settings for Unbound.
|
||||
It is checked.
|
||||
If omitted, the config file at the default location is checked.
|
||||
.SH "EXIT CODE"
|
||||
The unbound\-checkconf program exits with status code 1 on error,
|
||||
0 for a correct config file.
|
||||
.SH "FILES"
|
||||
.UNINDENT
|
||||
.SH EXIT CODE
|
||||
.sp
|
||||
The \fBunbound\-checkconf\fP program exits with status code 1 on error, 0 for a
|
||||
correct config file.
|
||||
.SH FILES
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.I @ub_conf_file@
|
||||
unbound configuration file.
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound\fR(8).
|
||||
.B @ub_conf_file@
|
||||
Unbound configuration file.
|
||||
.UNINDENT
|
||||
.SH SEE ALSO
|
||||
.sp
|
||||
\fI\%unbound.conf(5)\fP,
|
||||
\fI\%unbound(8)\fP\&.
|
||||
.SH AUTHOR
|
||||
Unbound developers are mentioned in the CREDITS file in the distribution.
|
||||
.SH COPYRIGHT
|
||||
1999-2026, NLnet Labs
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
.. program:: unbound-checkconf
|
||||
|
||||
unbound-checkconf(8)
|
||||
====================
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
**unbound-checkconf** [``-hf``] [``-o option``] [cfgfile]
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
``unbound-checkconf`` checks the configuration file for the
|
||||
:doc:`unbound(8)</manpages/unbound>` DNS resolver for syntax and other errors.
|
||||
The config file syntax is described in
|
||||
:doc:`unbound.conf(5)</manpages/unbound.conf>`.
|
||||
|
||||
The available options are:
|
||||
|
||||
.. option:: -h
|
||||
|
||||
Show the version and commandline option help.
|
||||
|
||||
.. option:: -f
|
||||
|
||||
Print full pathname, with chroot applied to it.
|
||||
Use with the :option:`-o` option.
|
||||
|
||||
.. option:: -q
|
||||
|
||||
Make the operation quiet, suppress output on success.
|
||||
|
||||
.. option:: -o <option>
|
||||
|
||||
If given, after checking the config file the value of this option is
|
||||
printed to stdout.
|
||||
For ``""`` (disabled) options an empty line is printed.
|
||||
|
||||
.. option:: cfgfile
|
||||
|
||||
The config file to read with settings for Unbound.
|
||||
It is checked.
|
||||
If omitted, the config file at the default location is checked.
|
||||
|
||||
Exit Code
|
||||
---------
|
||||
|
||||
The ``unbound-checkconf`` program exits with status code 1 on error, 0 for a
|
||||
correct config file.
|
||||
|
||||
Files
|
||||
-----
|
||||
|
||||
@ub_conf_file@
|
||||
Unbound configuration file.
|
||||
|
||||
See Also
|
||||
--------
|
||||
|
||||
:doc:`unbound.conf(5)</manpages/unbound.conf>`,
|
||||
:doc:`unbound(8)</manpages/unbound>`.
|
||||
+1334
-444
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+157
-85
@@ -1,118 +1,190 @@
|
||||
.TH "unbound\-host" "1" "@date@" "NLnet Labs" "unbound @version@"
|
||||
.\"
|
||||
.\" unbound-host.1 -- unbound DNS lookup utility
|
||||
.\"
|
||||
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
|
||||
.\"
|
||||
.\" See LICENSE for the license.
|
||||
.\"
|
||||
.\"
|
||||
.SH "NAME"
|
||||
.B unbound\-host
|
||||
\- unbound DNS lookup utility
|
||||
.SH "SYNOPSIS"
|
||||
.B unbound\-host
|
||||
.RB [ \-C
|
||||
.IR configfile ]
|
||||
.RB [ \-vdhr46D ]
|
||||
.RB [ \-c
|
||||
.IR class ]
|
||||
.RB [ \-t
|
||||
.IR type ]
|
||||
.RB [ \-y
|
||||
.IR key ]
|
||||
.RB [ \-f
|
||||
.IR keyfile ]
|
||||
.RB [ \-F
|
||||
.IR namedkeyfile ]
|
||||
.I hostname
|
||||
.SH "DESCRIPTION"
|
||||
.B Unbound\-host
|
||||
uses the unbound validating resolver to query for the hostname and display
|
||||
results. With the \fB\-v\fR option it displays validation
|
||||
status: secure, insecure, bogus (security failure).
|
||||
.P
|
||||
By default it reads no configuration file whatsoever. It attempts to reach
|
||||
the internet root servers. With \fB\-C\fR an unbound config file and with
|
||||
\fB\-r\fR resolv.conf can be read.
|
||||
.P
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.
|
||||
.nr rst2man-indent-level 0
|
||||
.
|
||||
.de1 rstReportMargin
|
||||
\\$1 \\n[an-margin]
|
||||
level \\n[rst2man-indent-level]
|
||||
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
-
|
||||
\\n[rst2man-indent0]
|
||||
\\n[rst2man-indent1]
|
||||
\\n[rst2man-indent2]
|
||||
..
|
||||
.de1 INDENT
|
||||
.\" .rstReportMargin pre:
|
||||
. RS \\$1
|
||||
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
|
||||
. nr rst2man-indent-level +1
|
||||
.\" .rstReportMargin post:
|
||||
..
|
||||
.de UNINDENT
|
||||
. RE
|
||||
.\" indent \\n[an-margin]
|
||||
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.nr rst2man-indent-level -1
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "UNBOUND-HOST" "1" "@date@" "@version@" "Unbound"
|
||||
.SH NAME
|
||||
unbound-host \- Unbound @version@ DNS lookup utility.
|
||||
.SH SYNOPSIS
|
||||
.sp
|
||||
\fBunbound\-host\fP [\fB\-C configfile\fP] [\fB\-vdhr46D\fP] [\fB\-c class\fP]
|
||||
[\fB\-t type\fP] [\fB\-y key\fP] [\fB\-f keyfile\fP] [\fB\-F namedkeyfile\fP] hostname
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
\fBunbound\-host\fP uses the Unbound validating resolver to query for the hostname
|
||||
and display results.
|
||||
With the \fI\%\-v\fP option it displays validation status: secure, insecure,
|
||||
bogus (security failure).
|
||||
.sp
|
||||
By default it reads no configuration file whatsoever.
|
||||
It attempts to reach the internet root servers.
|
||||
With \fI\%\-C\fP an unbound config file and with \fI\%\-r\fP \fBresolv.conf\fP
|
||||
can be read.
|
||||
.sp
|
||||
The available options are:
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.I hostname
|
||||
.B hostname
|
||||
This name is resolved (looked up in the DNS).
|
||||
If a IPv4 or IPv6 address is given, a reverse lookup is performed.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-h
|
||||
Show the version and commandline option help.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-v
|
||||
Enable verbose output and it shows validation results, on every line.
|
||||
Secure means that the NXDOMAIN (no such domain name), nodata (no such data)
|
||||
or positive data response validated correctly with one of the keys.
|
||||
Secure means that the NXDOMAIN (no such domain name), nodata (no such
|
||||
data) or positive data response validated correctly with one of the
|
||||
keys.
|
||||
Insecure means that that domain name has no security set up for it.
|
||||
Bogus (security failure) means that the response failed one or more checks,
|
||||
it is likely wrong, outdated, tampered with, or broken.
|
||||
Bogus (security failure) means that the response failed one or more
|
||||
checks, it is likely wrong, outdated, tampered with, or broken.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-d
|
||||
Enable debug output to stderr. One \-d shows what the resolver and validator
|
||||
are doing and may tell you what is going on. More times, \-d \-d, gives a
|
||||
lot of output, with every packet sent and received.
|
||||
Enable debug output to stderr.
|
||||
One \fI\%\-d\fP shows what the resolver and validator are doing and may
|
||||
tell you what is going on.
|
||||
More times, \fI\%\-d\fP \fI\%\-d\fP, gives a lot of output, with every
|
||||
packet sent and received.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-c \fIclass
|
||||
Specify the class to lookup for, the default is IN the internet class.
|
||||
.B \-c <class>
|
||||
Specify the class to lookup for, the default is IN the internet
|
||||
class.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-t \fItype
|
||||
Specify the type of data to lookup. The default looks for IPv4, IPv6 and
|
||||
mail handler data, or domain name pointers for reverse queries.
|
||||
.B \-t <type>
|
||||
Specify the type of data to lookup.
|
||||
The default looks for IPv4, IPv6 and mail handler data, or domain name
|
||||
pointers for reverse queries.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-y \fIkey
|
||||
Specify a public key to use as trust anchor. This is the base for a chain
|
||||
of trust that is built up from the trust anchor to the response, in order
|
||||
to validate the response message. Can be given as a DS or DNSKEY record.
|
||||
For example \-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD".
|
||||
.B \-y <key>
|
||||
Specify a public key to use as trust anchor.
|
||||
This is the base for a chain of trust that is built up from the trust
|
||||
anchor to the response, in order to validate the response message.
|
||||
Can be given as a DS or DNSKEY record.
|
||||
For example:
|
||||
.INDENT 7.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.nf
|
||||
.ft C
|
||||
\-y \(dqexample.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD\(dq
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-D
|
||||
Enables DNSSEC validation. Reads the root anchor from the default configured
|
||||
root anchor at the default location, \fI@UNBOUND_ROOTKEY_FILE@\fR.
|
||||
Enables DNSSEC validation.
|
||||
Reads the root anchor from the default configured root anchor at the
|
||||
default location, \fB@UNBOUND_ROOTKEY_FILE@\fP\&.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-f \fIkeyfile
|
||||
Reads keys from a file. Every line has a DS or DNSKEY record, in the format
|
||||
as for \-y. The zone file format, the same as dig and drill produce.
|
||||
.B \-f <keyfile>
|
||||
Reads keys from a file.
|
||||
Every line has a DS or DNSKEY record, in the format as for \fI\%\-y\fP\&.
|
||||
The zone file format, the same as \fBdig\fP and \fBdrill\fP produce.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-F \fInamedkeyfile
|
||||
Reads keys from a BIND\-style named.conf file. Only the trusted\-key {}; entries
|
||||
are read.
|
||||
.B \-F <namedkeyfile>
|
||||
Reads keys from a BIND\-style \fBnamed.conf\fP file.
|
||||
Only the \fBtrusted\-key {};\fP entries are read.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-C \fIconfigfile
|
||||
Uses the specified unbound.conf to prime
|
||||
.IR libunbound (3).
|
||||
.B \-C <configfile>
|
||||
Uses the specified unbound.conf to prime \fI\%libunbound(3)\fP\&.
|
||||
Pass it as first argument if you want to override some options from the
|
||||
config file with further arguments on the commandline.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-r
|
||||
Read /etc/resolv.conf, and use the forward DNS servers from there (those could
|
||||
have been set by DHCP). More info in
|
||||
.IR resolv.conf (5).
|
||||
Read \fB/etc/resolv.conf\fP, and use the forward DNS servers from
|
||||
there (those could have been set by DHCP).
|
||||
More info in \fIresolv.conf(5)\fP\&.
|
||||
Breaks validation if those servers do not support DNSSEC.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-4
|
||||
Use solely the IPv4 network for sending packets.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-6
|
||||
Use solely the IPv6 network for sending packets.
|
||||
.SH "EXAMPLES"
|
||||
Some examples of use. The keys shown below are fakes, thus a security failure
|
||||
is encountered.
|
||||
.P
|
||||
.UNINDENT
|
||||
.SH EXAMPLES
|
||||
.sp
|
||||
Some examples of use.
|
||||
The keys shown below are fakes, thus a security failure is encountered.
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.nf
|
||||
.ft C
|
||||
$ unbound\-host www.example.com
|
||||
.P
|
||||
$ unbound\-host \-v \-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD" www.example.com
|
||||
.P
|
||||
$ unbound\-host \-v \-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD" 192.0.2.153
|
||||
.SH "EXIT CODE"
|
||||
The unbound\-host program exits with status code 1 on error,
|
||||
0 on no error. The data may not be available on exit code 0, exit code 1
|
||||
means the lookup encountered a fatal error.
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound\fR(8).
|
||||
|
||||
$ unbound\-host \-v \-y \(dqexample.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD\(dq www.example.com
|
||||
|
||||
$ unbound\-host \-v \-y \(dqexample.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD\(dq 192.0.2.153
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.SH EXIT CODE
|
||||
.sp
|
||||
The \fBunbound\-host\fP program exits with status code 1 on error, 0 on no error.
|
||||
The data may not be available on exit code 0, exit code 1 means the lookup
|
||||
encountered a fatal error.
|
||||
.SH SEE ALSO
|
||||
.sp
|
||||
\fI\%unbound.conf(5)\fP,
|
||||
\fI\%unbound(8)\fP\&.
|
||||
.SH AUTHOR
|
||||
Unbound developers are mentioned in the CREDITS file in the distribution.
|
||||
.SH COPYRIGHT
|
||||
1999-2026, NLnet Labs
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
.. program:: unbound-host
|
||||
|
||||
unbound-host(1)
|
||||
===============
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
**unbound-host** [``-C configfile``] [``-vdhr46D``] [``-c class``]
|
||||
[``-t type``] [``-y key``] [``-f keyfile``] [``-F namedkeyfile``] hostname
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
``unbound-host`` uses the Unbound validating resolver to query for the hostname
|
||||
and display results.
|
||||
With the :option:`-v` option it displays validation status: secure, insecure,
|
||||
bogus (security failure).
|
||||
|
||||
By default it reads no configuration file whatsoever.
|
||||
It attempts to reach the internet root servers.
|
||||
With :option:`-C` an unbound config file and with :option:`-r` ``resolv.conf``
|
||||
can be read.
|
||||
|
||||
The available options are:
|
||||
|
||||
.. option:: hostname
|
||||
|
||||
This name is resolved (looked up in the DNS).
|
||||
If a IPv4 or IPv6 address is given, a reverse lookup is performed.
|
||||
|
||||
.. option:: -h
|
||||
|
||||
Show the version and commandline option help.
|
||||
|
||||
.. option:: -v
|
||||
|
||||
Enable verbose output and it shows validation results, on every line.
|
||||
Secure means that the NXDOMAIN (no such domain name), nodata (no such
|
||||
data) or positive data response validated correctly with one of the
|
||||
keys.
|
||||
Insecure means that that domain name has no security set up for it.
|
||||
Bogus (security failure) means that the response failed one or more
|
||||
checks, it is likely wrong, outdated, tampered with, or broken.
|
||||
|
||||
.. option:: -d
|
||||
|
||||
Enable debug output to stderr.
|
||||
One :option:`-d` shows what the resolver and validator are doing and may
|
||||
tell you what is going on.
|
||||
More times, :option:`-d` :option:`-d`, gives a lot of output, with every
|
||||
packet sent and received.
|
||||
|
||||
.. option:: -c <class>
|
||||
|
||||
Specify the class to lookup for, the default is IN the internet
|
||||
class.
|
||||
|
||||
.. option:: -t <type>
|
||||
|
||||
Specify the type of data to lookup.
|
||||
The default looks for IPv4, IPv6 and mail handler data, or domain name
|
||||
pointers for reverse queries.
|
||||
|
||||
.. option:: -y <key>
|
||||
|
||||
Specify a public key to use as trust anchor.
|
||||
This is the base for a chain of trust that is built up from the trust
|
||||
anchor to the response, in order to validate the response message.
|
||||
Can be given as a DS or DNSKEY record.
|
||||
For example:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD"
|
||||
|
||||
.. option:: -D
|
||||
|
||||
Enables DNSSEC validation.
|
||||
Reads the root anchor from the default configured root anchor at the
|
||||
default location, :file:`@UNBOUND_ROOTKEY_FILE@`.
|
||||
|
||||
.. option:: -f <keyfile>
|
||||
|
||||
Reads keys from a file.
|
||||
Every line has a DS or DNSKEY record, in the format as for :option:`-y`.
|
||||
The zone file format, the same as ``dig`` and ``drill`` produce.
|
||||
|
||||
.. option:: -F <namedkeyfile>
|
||||
|
||||
Reads keys from a BIND-style :file:`named.conf` file.
|
||||
Only the ``trusted-key {};`` entries are read.
|
||||
|
||||
.. option:: -C <configfile>
|
||||
|
||||
Uses the specified unbound.conf to prime :doc:`libunbound(3)</manpages/libunbound>`.
|
||||
Pass it as first argument if you want to override some options from the
|
||||
config file with further arguments on the commandline.
|
||||
|
||||
.. option:: -r
|
||||
|
||||
Read :file:`/etc/resolv.conf`, and use the forward DNS servers from
|
||||
there (those could have been set by DHCP).
|
||||
More info in *resolv.conf(5)*.
|
||||
Breaks validation if those servers do not support DNSSEC.
|
||||
|
||||
.. option:: -4
|
||||
|
||||
Use solely the IPv4 network for sending packets.
|
||||
|
||||
.. option:: -6
|
||||
|
||||
Use solely the IPv6 network for sending packets.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Some examples of use.
|
||||
The keys shown below are fakes, thus a security failure is encountered.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ unbound-host www.example.com
|
||||
|
||||
$ unbound-host -v -y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD" www.example.com
|
||||
|
||||
$ unbound-host -v -y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD" 192.0.2.153
|
||||
|
||||
Exit Code
|
||||
---------
|
||||
|
||||
The ``unbound-host`` program exits with status code 1 on error, 0 on no error.
|
||||
The data may not be available on exit code 0, exit code 1 means the lookup
|
||||
encountered a fatal error.
|
||||
|
||||
See Also
|
||||
--------
|
||||
|
||||
:doc:`unbound.conf(5)</manpages/unbound.conf>`,
|
||||
:doc:`unbound(8)</manpages/unbound>`.
|
||||
+100
-65
@@ -1,88 +1,123 @@
|
||||
.TH "unbound" "8" "@date@" "NLnet Labs" "unbound @version@"
|
||||
.\"
|
||||
.\" unbound.8 -- unbound manual
|
||||
.\"
|
||||
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
|
||||
.\"
|
||||
.\" See LICENSE for the license.
|
||||
.\"
|
||||
.\"
|
||||
.SH "NAME"
|
||||
.B unbound
|
||||
\- Unbound DNS validating resolver @version@.
|
||||
.SH "SYNOPSIS"
|
||||
.B unbound
|
||||
.RB [ \-h ]
|
||||
.RB [ \-d ]
|
||||
.RB [ \-p ]
|
||||
.RB [ \-v ]
|
||||
.RB [ \-c
|
||||
.IR cfgfile ]
|
||||
.SH "DESCRIPTION"
|
||||
.B Unbound
|
||||
is a caching DNS resolver.
|
||||
.P
|
||||
It uses a built in list of authoritative nameservers for the root zone (.),
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.
|
||||
.nr rst2man-indent-level 0
|
||||
.
|
||||
.de1 rstReportMargin
|
||||
\\$1 \\n[an-margin]
|
||||
level \\n[rst2man-indent-level]
|
||||
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
-
|
||||
\\n[rst2man-indent0]
|
||||
\\n[rst2man-indent1]
|
||||
\\n[rst2man-indent2]
|
||||
..
|
||||
.de1 INDENT
|
||||
.\" .rstReportMargin pre:
|
||||
. RS \\$1
|
||||
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
|
||||
. nr rst2man-indent-level +1
|
||||
.\" .rstReportMargin post:
|
||||
..
|
||||
.de UNINDENT
|
||||
. RE
|
||||
.\" indent \\n[an-margin]
|
||||
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.nr rst2man-indent-level -1
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "UNBOUND" "8" "@date@" "@version@" "Unbound"
|
||||
.SH NAME
|
||||
unbound \- Unbound DNS validating resolver @version@.
|
||||
.SH SYNOPSIS
|
||||
.sp
|
||||
\fBunbound\fP [\fB\-hdpVv\fP] [\fB\-c <cfgfile>\fP]
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
\fBunbound\fP is a caching DNS resolver.
|
||||
.sp
|
||||
It uses a built in list of authoritative nameservers for the root zone (\fB\&.\fP),
|
||||
the so called root hints.
|
||||
On receiving a DNS query it will ask the root nameservers for
|
||||
an answer and will in almost all cases receive a delegation to a top level
|
||||
domain (TLD) authoritative nameserver.
|
||||
On receiving a DNS query it will ask the root nameservers for an answer and
|
||||
will in almost all cases receive a delegation to a top level domain (TLD)
|
||||
authoritative nameserver.
|
||||
It will then ask that nameserver for an answer.
|
||||
It will recursively continue until an answer is found or no answer is
|
||||
available (NXDOMAIN).
|
||||
For performance and efficiency reasons that answer is cached for a
|
||||
certain time (the answer's time\-to\-live or TTL).
|
||||
It will recursively continue until an answer is found or no answer is available
|
||||
(NXDOMAIN).
|
||||
For performance and efficiency reasons that answer is cached for a certain time
|
||||
(the answer\(aqs time\-to\-live or TTL).
|
||||
A second query for the same name will then be answered from the cache.
|
||||
Unbound can also do DNSSEC validation.
|
||||
.P
|
||||
To use a locally running
|
||||
.B Unbound
|
||||
for resolving put
|
||||
.sp
|
||||
.RS 6n
|
||||
To use a locally running Unbound for resolving put:
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.nf
|
||||
.ft C
|
||||
nameserver 127.0.0.1
|
||||
.RE
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
into \fIresolv.conf(5)\fP\&.
|
||||
.sp
|
||||
If authoritative DNS is needed as well using \fI\%nsd(8)\fP,
|
||||
careful setup is required because authoritative nameservers and resolvers are
|
||||
using the same port number (53).
|
||||
.sp
|
||||
into
|
||||
.IR resolv.conf (5).
|
||||
.P
|
||||
If authoritative DNS is needed as well using
|
||||
.IR nsd (8),
|
||||
careful setup is required because authoritative nameservers and
|
||||
resolvers are using the same port number (53).
|
||||
.P
|
||||
The available options are:
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-h
|
||||
Show the version number and commandline option help, and exit.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-c\fI cfgfile
|
||||
.B \-c <cfgfile>
|
||||
Set the config file with settings for unbound to read instead of reading the
|
||||
file at the default location, @ub_conf_file@. The syntax is
|
||||
described in \fIunbound.conf\fR(5).
|
||||
file at the default location, \fB@ub_conf_file@\fP\&.
|
||||
The syntax is described in \fI\%unbound.conf(5)\fP\&.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-d
|
||||
Debug flag: do not fork into the background, but stay attached to
|
||||
the console. This flag will also delay writing to the log file until
|
||||
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.
|
||||
Debug flag: do not fork into the background, but stay attached to the
|
||||
console.
|
||||
This flag will also delay writing to the log file until 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.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.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.
|
||||
Don\(aqt use a pidfile.
|
||||
This argument should only be used by supervision systems which can ensure
|
||||
that only one instance of Unbound will run concurrently.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-v
|
||||
Increase verbosity. If given multiple times, more information is logged.
|
||||
Increase verbosity.
|
||||
If given multiple times, more information is logged.
|
||||
This is in addition to the verbosity (if any) from the config file.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-V
|
||||
Show the version number and build options, and exit.
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound\-checkconf\fR(8),
|
||||
\fInsd\fR(8).
|
||||
.SH "AUTHORS"
|
||||
.B Unbound
|
||||
developers are mentioned in the CREDITS file in the distribution.
|
||||
.UNINDENT
|
||||
.SH SEE ALSO
|
||||
.sp
|
||||
\fI\%unbound.conf(5)\fP,
|
||||
\fI\%unbound\-checkconf(8)\fP,
|
||||
\fI\%nsd(8)\fP\&.
|
||||
.SH AUTHOR
|
||||
Unbound developers are mentioned in the CREDITS file in the distribution.
|
||||
.SH COPYRIGHT
|
||||
1999-2026, NLnet Labs
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
|
||||
+5617
-2145
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+2007
-886
File diff suppressed because it is too large
Load Diff
+119
@@ -0,0 +1,119 @@
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
..
|
||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
||||
|
||||
..
|
||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
||||
|
||||
..
|
||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
||||
|
||||
.. program:: unbound
|
||||
|
||||
unbound(8)
|
||||
==========
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
**unbound** [``-hdpVv``] [``-c <cfgfile>``]
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
``unbound`` is a caching DNS resolver.
|
||||
|
||||
It uses a built in list of authoritative nameservers for the root zone (``.``),
|
||||
the so called root hints.
|
||||
On receiving a DNS query it will ask the root nameservers for an answer and
|
||||
will in almost all cases receive a delegation to a top level domain (TLD)
|
||||
authoritative nameserver.
|
||||
It will then ask that nameserver for an answer.
|
||||
It will recursively continue until an answer is found or no answer is available
|
||||
(NXDOMAIN).
|
||||
For performance and efficiency reasons that answer is cached for a certain time
|
||||
(the answer's time-to-live or TTL).
|
||||
A second query for the same name will then be answered from the cache.
|
||||
Unbound can also do DNSSEC validation.
|
||||
|
||||
To use a locally running Unbound for resolving put:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
nameserver 127.0.0.1
|
||||
|
||||
into *resolv.conf(5)*.
|
||||
|
||||
If authoritative DNS is needed as well using :external+nsd:doc:`manpages/nsd`,
|
||||
careful setup is required because authoritative nameservers and resolvers are
|
||||
using the same port number (53).
|
||||
|
||||
The available options are:
|
||||
|
||||
.. option:: -h
|
||||
|
||||
Show the version number and commandline option help, and exit.
|
||||
|
||||
.. option:: -c <cfgfile>
|
||||
|
||||
Set the config file with settings for unbound to read instead of reading the
|
||||
file at the default location, :file:`@ub_conf_file@`.
|
||||
The syntax is described in :doc:`unbound.conf(5)</manpages/unbound.conf>`.
|
||||
|
||||
.. option:: -d
|
||||
|
||||
Debug flag: do not fork into the background, but stay attached to the
|
||||
console.
|
||||
This flag will also delay writing to the log file until 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.
|
||||
|
||||
.. option:: -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.
|
||||
|
||||
.. option:: -v
|
||||
|
||||
Increase verbosity.
|
||||
If given multiple times, more information is logged.
|
||||
This is in addition to the verbosity (if any) from the config file.
|
||||
|
||||
.. option:: -V
|
||||
|
||||
Show the version number and build options, and exit.
|
||||
|
||||
See Also
|
||||
--------
|
||||
|
||||
:doc:`unbound.conf(5)</manpages/unbound.conf>`,
|
||||
:doc:`unbound-checkconf(8)</manpages/unbound-checkconf>`,
|
||||
:external+nsd:doc:`manpages/nsd`.
|
||||
@@ -75,6 +75,7 @@ int dynlibmod_init(struct module_env* env, int id) {
|
||||
struct config_strlist* cfg_item = env->cfg->dynlib_file;
|
||||
struct dynlibmod_env* de = (struct dynlibmod_env*)calloc(1, sizeof(struct dynlibmod_env));
|
||||
__DYNMOD dynamic_library;
|
||||
int i;
|
||||
if (!de)
|
||||
{
|
||||
log_err("dynlibmod[%d]: malloc failure", dynlib_mod_idx);
|
||||
@@ -84,7 +85,7 @@ int dynlibmod_init(struct module_env* env, int id) {
|
||||
env->modinfo[id] = (void*) de;
|
||||
|
||||
de->fname = NULL;
|
||||
for(int i = dynlib_mod_idx;
|
||||
for(i = dynlib_mod_idx;
|
||||
i != 0 && cfg_item != NULL;
|
||||
i--, cfg_item = cfg_item->next) {}
|
||||
|
||||
@@ -296,8 +297,8 @@ inplace_cb_delete_wrapped(struct module_env* env, enum inplace_cb_list_type type
|
||||
*/
|
||||
static struct module_func_block dynlibmod_block = {
|
||||
"dynlib",
|
||||
&dynlibmod_init, &dynlibmod_deinit, &dynlibmod_operate, &dynlibmod_inform_super,
|
||||
&dynlibmod_clear, &dynlibmod_get_mem
|
||||
NULL, NULL, &dynlibmod_init, &dynlibmod_deinit, &dynlibmod_operate,
|
||||
&dynlibmod_inform_super, &dynlibmod_clear, &dynlibmod_get_mem
|
||||
};
|
||||
|
||||
struct module_func_block* dynlibmod_get_funcblock(void)
|
||||
|
||||
@@ -97,6 +97,7 @@ node_create(struct addrtree *tree, void *elem, addrlen_t scope,
|
||||
tree->node_count++;
|
||||
node->scope = scope;
|
||||
node->ttl = ttl;
|
||||
node->only_match_scope_zero = 0;
|
||||
node->edge[0] = NULL;
|
||||
node->edge[1] = NULL;
|
||||
node->parent_edge = NULL;
|
||||
@@ -155,6 +156,7 @@ 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->only_match_scope_zero = 0;
|
||||
node->elem = NULL;
|
||||
}
|
||||
|
||||
@@ -358,7 +360,7 @@ issub(const addrkey_t *s1, addrlen_t 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)
|
||||
time_t now, int only_match_scope_zero)
|
||||
{
|
||||
struct addrnode *newnode, *node;
|
||||
struct addredge *edge;
|
||||
@@ -381,6 +383,7 @@ addrtree_insert(struct addrtree *tree, const addrkey_t *addr,
|
||||
/* update this node's scope and data */
|
||||
clean_node(tree, node);
|
||||
node->ttl = ttl;
|
||||
node->only_match_scope_zero = only_match_scope_zero;
|
||||
node->elem = elem;
|
||||
node->scope = scope;
|
||||
tree->size_bytes += tree->sizefunc(elem);
|
||||
@@ -447,6 +450,7 @@ addrtree_insert(struct addrtree *tree, const addrkey_t *addr,
|
||||
newnode->elem = elem;
|
||||
newnode->scope = scope;
|
||||
newnode->ttl = ttl;
|
||||
newnode->only_match_scope_zero = only_match_scope_zero;
|
||||
}
|
||||
|
||||
tree->size_bytes += node_size(tree, newnode);
|
||||
@@ -455,6 +459,7 @@ addrtree_insert(struct addrtree *tree, const addrkey_t *addr,
|
||||
/* Data is stored in other leafnode */
|
||||
node = newnode;
|
||||
newnode = node_create(tree, elem, scope, ttl);
|
||||
if (!newnode) return;
|
||||
if (!edge_create(newnode, addr, sourcemask, node,
|
||||
index^1)) {
|
||||
clean_node(tree, newnode);
|
||||
@@ -483,7 +488,8 @@ addrtree_find(struct addrtree *tree, const addrkey_t *addr,
|
||||
/* 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) {
|
||||
if (node->elem && node->ttl >= now &&
|
||||
!(sourcemask != 0 && node->only_match_scope_zero)) {
|
||||
/* saved at wrong depth */;
|
||||
log_assert(node->scope >= depth);
|
||||
if (depth == node->scope ||
|
||||
|
||||
@@ -95,6 +95,10 @@ struct addrnode {
|
||||
time_t ttl;
|
||||
/** Number of significant bits in address. */
|
||||
addrlen_t scope;
|
||||
/** Only use the element for queries for subnet/0. Set if the query
|
||||
* for /0 was answered with scope 0. For query /x answer scope 0,
|
||||
* they can match anything and this is false. */
|
||||
int only_match_scope_zero;
|
||||
/** A node can have 0-2 edges, set to NULL for unused */
|
||||
struct addredge *edge[2];
|
||||
/** edge between this node and parent */
|
||||
@@ -112,7 +116,7 @@ struct addredge {
|
||||
addrlen_t len;
|
||||
/** child node this edge is connected to */
|
||||
struct addrnode *node;
|
||||
/** Parent node this ege is connected to */
|
||||
/** Parent node this edge is connected to */
|
||||
struct addrnode *parent_node;
|
||||
/** Index of this edge in parent_node */
|
||||
int parent_index;
|
||||
@@ -157,11 +161,12 @@ void addrtree_delete(struct addrtree *tree);
|
||||
* @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 only_match_scope_zero: set for when query /0 has scope /0 answer.
|
||||
* @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);
|
||||
time_t now, int only_match_scope_zero);
|
||||
|
||||
/**
|
||||
* Find a node containing an element in the tree.
|
||||
|
||||
@@ -59,7 +59,7 @@ struct ecs_data {
|
||||
|
||||
/**
|
||||
* copy the first n BITS from src to dst iff both src and dst
|
||||
* are large enough, return 0 on succes
|
||||
* are large enough, return 0 on success
|
||||
*/
|
||||
int
|
||||
copy_clear(uint8_t* dst, size_t dstlen, uint8_t* src, size_t srclen, size_t n);
|
||||
|
||||
+447
-62
@@ -51,11 +51,16 @@
|
||||
#include "services/cache/dns.h"
|
||||
#include "util/module.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#include "iterator/iter_utils.h"
|
||||
#ifdef USE_CACHEDB
|
||||
#include "cachedb/cachedb.h"
|
||||
#endif
|
||||
|
||||
/** externally called */
|
||||
void
|
||||
@@ -65,6 +70,7 @@ subnet_data_delete(void *d, void *ATTR_UNUSED(arg))
|
||||
r = (struct subnet_msg_cache_data*)d;
|
||||
addrtree_delete(r->tree4);
|
||||
addrtree_delete(r->tree6);
|
||||
free(r->reason_fail);
|
||||
free(r);
|
||||
}
|
||||
|
||||
@@ -79,6 +85,8 @@ msg_cache_sizefunc(void *k, void *d)
|
||||
+ q->key.qname_len + lock_get_mem(&q->entry.lock);
|
||||
s += addrtree_size(r->tree4);
|
||||
s += addrtree_size(r->tree6);
|
||||
if(r->reason_fail)
|
||||
s += strlen(r->reason_fail)+1;
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -93,13 +101,14 @@ subnet_new_qstate(struct module_qstate *qstate, int id)
|
||||
qstate->minfo[id] = sq;
|
||||
memset(sq, 0, sizeof(*sq));
|
||||
sq->started_no_cache_store = qstate->no_cache_store;
|
||||
sq->started_no_cache_lookup = qstate->no_cache_lookup;
|
||||
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)
|
||||
void
|
||||
subnet_ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
|
||||
struct module_qstate *qstate, struct regional *region)
|
||||
{
|
||||
size_t sn_octs, sn_octs_remainder;
|
||||
sldns_buffer* buf = qstate->env->scratch_buffer;
|
||||
@@ -131,7 +140,7 @@ ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
|
||||
edns_opt_list_append(list,
|
||||
qstate->env->cfg->client_subnet_opcode,
|
||||
sn_octs + sn_octs_remainder + 4,
|
||||
sldns_buffer_begin(buf), qstate->region);
|
||||
sldns_buffer_begin(buf), region);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +148,7 @@ 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 regional *region, int id, void* ATTR_UNUSED(cbargs))
|
||||
{
|
||||
struct subnet_qstate *sq;
|
||||
struct subnet_env *sn_env;
|
||||
@@ -148,12 +157,36 @@ int ecs_whitelist_check(struct query_info* qinfo,
|
||||
return 1;
|
||||
sn_env = (struct subnet_env*)qstate->env->modinfo[id];
|
||||
|
||||
if(sq->is_subquery_nonsubnet) {
|
||||
if(sq->is_subquery_scopezero) {
|
||||
/* Check if the result can be stored in the global cache,
|
||||
* this is okay if the address and name are not configured
|
||||
* as subnet address and subnet zone. */
|
||||
if(!ecs_is_whitelisted(sn_env->whitelist,
|
||||
addr, addrlen, qinfo->qname, qinfo->qname_len,
|
||||
qinfo->qclass)) {
|
||||
/* The stub or forward can have no_cache set.*/
|
||||
if(iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0)) {
|
||||
verbose(VERB_ALGO, "subnet subquery is not stored globally, stuborfwd is no_cache");
|
||||
} else {
|
||||
verbose(VERB_ALGO, "subnet store subquery global, name and addr have no subnet treatment.%s",
|
||||
(sq->started_no_cache_store?
|
||||
" But the subnet module was started with no_cache_store for the super query, and that is still applied to this query":""));
|
||||
qstate->no_cache_store = sq->started_no_cache_store;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Cache by default, might be disabled after parsing EDNS option
|
||||
* received from nameserver. */
|
||||
if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL)) {
|
||||
if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0)
|
||||
&& sq->ecs_client_in.subnet_validdata) {
|
||||
qstate->no_cache_store = 0;
|
||||
}
|
||||
|
||||
sq->subnet_sent_no_subnet = 0;
|
||||
if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream &&
|
||||
qstate->env->cfg->client_subnet_always_forward) ||
|
||||
ecs_is_whitelisted(sn_env->whitelist,
|
||||
@@ -162,17 +195,35 @@ int ecs_whitelist_check(struct query_info* qinfo,
|
||||
/* 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;
|
||||
if(!edns_opt_list_find(qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode)) {
|
||||
/* if the client is not wanting an EDNS subnet option,
|
||||
* omit it and store that we omitted it but actually
|
||||
* are doing EDNS subnet to the server. */
|
||||
if(sq->ecs_server_out.subnet_source_mask == 0) {
|
||||
sq->subnet_sent_no_subnet = 1;
|
||||
sq->subnet_sent = 0;
|
||||
/* The result should end up in subnet cache,
|
||||
* not in global cache. */
|
||||
qstate->no_cache_store = 1;
|
||||
return 1;
|
||||
}
|
||||
subnet_ecs_opt_list_append(&sq->ecs_server_out,
|
||||
&qstate->edns_opts_back_out, qstate, region);
|
||||
}
|
||||
sq->subnet_sent = 1;
|
||||
/* Do not store servfails in global cache, since the subnet
|
||||
* option is sent out. */
|
||||
qstate->no_cache_store = 1;
|
||||
}
|
||||
else if(sq->subnet_sent) {
|
||||
else {
|
||||
/* 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);
|
||||
if(edns_opt_list_find(qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode)) {
|
||||
edns_opt_list_remove(&qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode);
|
||||
}
|
||||
sq->subnet_sent = 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -198,18 +249,29 @@ subnetmod_init(struct module_env *env, int id)
|
||||
}
|
||||
alloc_init(&sn_env->alloc, NULL, 0);
|
||||
env->modinfo[id] = (void*)sn_env;
|
||||
|
||||
/* Warn that serve-expired and prefetch do not work with the subnet
|
||||
* module cache. */
|
||||
if(env->cfg->serve_expired)
|
||||
log_warn(
|
||||
"subnetcache: serve-expired is set but not working "
|
||||
"for data originating from the subnet module cache.");
|
||||
if(env->cfg->prefetch)
|
||||
log_warn(
|
||||
"subnetcache: prefetch is set but not working "
|
||||
"for data originating from the subnet module cache.");
|
||||
/* 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("subnetcache: could not create cache");
|
||||
free(sn_env);
|
||||
env->modinfo[id] = NULL;
|
||||
return 0;
|
||||
}
|
||||
slabhash_setmarkdel(sn_env->subnet_msg_cache, &subnet_markdel);
|
||||
/* whitelist for edns subnet capable servers */
|
||||
sn_env->whitelist = ecs_whitelist_create();
|
||||
if(!sn_env->whitelist ||
|
||||
@@ -227,7 +289,7 @@ subnetmod_init(struct module_env *env, int id)
|
||||
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)) {
|
||||
1 /* no aggregation */, env)) {
|
||||
log_err("subnetcache: could not register opcode");
|
||||
ecs_whitelist_delete(sn_env->whitelist);
|
||||
slabhash_delete(sn_env->subnet_msg_cache);
|
||||
@@ -284,9 +346,18 @@ delfunc(void *envptr, void *elemptr) {
|
||||
static size_t
|
||||
sizefunc(void *elemptr) {
|
||||
struct reply_info *elem = (struct reply_info *)elemptr;
|
||||
return sizeof (struct reply_info) - sizeof (struct rrset_ref)
|
||||
size_t s = sizeof (struct reply_info) - sizeof (struct rrset_ref)
|
||||
+ elem->rrset_count * sizeof (struct rrset_ref)
|
||||
+ elem->rrset_count * sizeof (struct ub_packed_rrset_key *);
|
||||
size_t i;
|
||||
for (i = 0; i < elem->rrset_count; i++) {
|
||||
struct ub_packed_rrset_key *key = elem->rrsets[i];
|
||||
struct packed_rrset_data *data = key->entry.data;
|
||||
s += ub_rrset_sizefunc(key, data);
|
||||
}
|
||||
if(elem->reason_bogus_str)
|
||||
s += strlen(elem->reason_bogus_str)+1;
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -326,13 +397,16 @@ update_cache(struct module_qstate *qstate, int id)
|
||||
struct slabhash *subnet_msg_cache = sne->subnet_msg_cache;
|
||||
struct ecs_data *edns = &sq->ecs_client_in;
|
||||
size_t i;
|
||||
int only_match_scope_zero, diff_size;
|
||||
|
||||
/* We already calculated hash upon lookup */
|
||||
hashvalue_type h = qstate->minfo[id] ?
|
||||
((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash :
|
||||
/* We already calculated hash upon lookup (lookup_and_reply) if we were
|
||||
* allowed to look in the ECS cache */
|
||||
hashvalue_type h = qstate->minfo[id] &&
|
||||
((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash_calculated?
|
||||
((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,
|
||||
struct lruhash_entry* lru_entry = slabhash_lookup(subnet_msg_cache, h,
|
||||
&qstate->qinfo, 1);
|
||||
int need_to_insert = (lru_entry == NULL);
|
||||
if (!lru_entry) {
|
||||
@@ -362,6 +436,35 @@ update_cache(struct module_qstate *qstate, int id)
|
||||
}
|
||||
/* lru_entry->lock is locked regardless of how we got here,
|
||||
* either from the slabhash_lookup, or above in the new allocated */
|
||||
if(!qstate->return_msg && qstate->error_response_cache) {
|
||||
struct subnet_msg_cache_data *data =
|
||||
(struct subnet_msg_cache_data*)lru_entry->data;
|
||||
data->ttl_servfail = *qstate->env->now + NORR_TTL;
|
||||
data->ede_fail = errinf_to_reason_bogus(qstate);
|
||||
diff_size = (data->reason_fail?strlen(data->reason_fail)+1:0);
|
||||
if(qstate->errinf) {
|
||||
char* str = errinf_to_str_misc(qstate);
|
||||
free(data->reason_fail);
|
||||
data->reason_fail = NULL;
|
||||
if(str)
|
||||
data->reason_fail = strdup(str);
|
||||
}
|
||||
diff_size = (data->reason_fail?strlen(data->reason_fail)+1:0)
|
||||
- diff_size;
|
||||
lock_rw_unlock(&lru_entry->lock);
|
||||
if (need_to_insert) {
|
||||
slabhash_insert(subnet_msg_cache, h, lru_entry,
|
||||
lru_entry->data, NULL);
|
||||
} else {
|
||||
slabhash_update_space_used(subnet_msg_cache, h, NULL,
|
||||
diff_size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(!qstate->return_msg) {
|
||||
lock_rw_unlock(&lru_entry->lock);
|
||||
return;
|
||||
}
|
||||
/* Step 2, find the correct tree */
|
||||
if (!(tree = get_tree(lru_entry->data, edns, sne, qstate->env->cfg))) {
|
||||
lock_rw_unlock(&lru_entry->lock);
|
||||
@@ -376,29 +479,53 @@ update_cache(struct module_qstate *qstate, int id)
|
||||
log_err("subnetcache: 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);
|
||||
reply_info_sortref(rep);
|
||||
rep->flags |= (BIT_RA | BIT_QR); /* fix flags to be sensible for */
|
||||
rep->flags &= ~(BIT_AA | BIT_CD);/* a reply based on the cache */
|
||||
if(edns->subnet_source_mask == 0 && edns->subnet_scope_mask == 0)
|
||||
only_match_scope_zero = 1;
|
||||
else only_match_scope_zero = 0;
|
||||
diff_size = (int)tree->size_bytes;
|
||||
addrtree_insert(tree, (addrkey_t*)edns->subnet_addr,
|
||||
edns->subnet_source_mask, sq->max_scope, rep,
|
||||
rep->ttl, *qstate->env->now);
|
||||
rep->ttl, *qstate->env->now, only_match_scope_zero);
|
||||
diff_size = (int)tree->size_bytes - diff_size;
|
||||
|
||||
lock_rw_unlock(&lru_entry->lock);
|
||||
if (need_to_insert) {
|
||||
slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data,
|
||||
NULL);
|
||||
} else {
|
||||
slabhash_update_space_used(subnet_msg_cache, h, NULL,
|
||||
diff_size);
|
||||
}
|
||||
}
|
||||
|
||||
/** See if there is a stored servfail, returns true if so, and sets reply. */
|
||||
static int
|
||||
lookup_check_servfail(struct module_qstate *qstate,
|
||||
struct subnet_msg_cache_data *data)
|
||||
{
|
||||
struct module_env *env = qstate->env;
|
||||
if(!data)
|
||||
return 0;
|
||||
if(!data->ttl_servfail || TTL_IS_EXPIRED(data->ttl_servfail, *env->now))
|
||||
return 0;
|
||||
qstate->return_rcode = LDNS_RCODE_SERVFAIL;
|
||||
errinf_ede(qstate, data->reason_fail, data->ede_fail);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** 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)
|
||||
lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq, int prefetch)
|
||||
{
|
||||
struct lruhash_entry *e;
|
||||
struct module_env *env = qstate->env;
|
||||
@@ -409,22 +536,35 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
struct addrtree *tree;
|
||||
struct addrnode *node;
|
||||
uint8_t scope;
|
||||
int must_validate = (!(qstate->query_flags&BIT_CD)
|
||||
|| qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate;
|
||||
|
||||
memset(&sq->ecs_client_out, 0, sizeof(sq->ecs_client_out));
|
||||
|
||||
if (sq) sq->qinfo_hash = h; /* Might be useful on cache miss */
|
||||
if (sq) {
|
||||
sq->qinfo_hash = h; /* Might be useful on cache miss */
|
||||
sq->qinfo_hash_calculated = 1;
|
||||
}
|
||||
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 */
|
||||
if(lookup_check_servfail(qstate, data)) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 1;
|
||||
}
|
||||
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 */
|
||||
if(lookup_check_servfail(qstate, data)) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 1;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 0;
|
||||
}
|
||||
@@ -433,12 +573,24 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
(struct reply_info *)node->elem, qstate->region, *env->now, 0,
|
||||
env->scratch);
|
||||
scope = (uint8_t)node->scope;
|
||||
lock_rw_unlock(&e->lock);
|
||||
|
||||
if (!qstate->return_msg) { /* Failed allocation or expired TTL */
|
||||
if(lookup_check_servfail(qstate, data)) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 1;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lock_rw_unlock(&e->lock);
|
||||
if(qstate->return_msg->rep->security == sec_status_unchecked
|
||||
&& must_validate) {
|
||||
/* The message has to be validated first. */
|
||||
verbose(VERB_ALGO, "subnet: unchecked cache entry needs "
|
||||
"validation");
|
||||
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;
|
||||
@@ -447,6 +599,10 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
INET6_SIZE);
|
||||
sq->ecs_client_out.subnet_validdata = 1;
|
||||
}
|
||||
|
||||
if (prefetch && *qstate->env->now >= ((struct reply_info *)node->elem)->prefetch_ttl) {
|
||||
qstate->need_refetch = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -465,6 +621,87 @@ common_prefix(uint8_t *a, uint8_t *b, uint8_t net)
|
||||
return !memcmp(a, b, n) && ((net % 8) == 0 || a[n] == b[n]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create sub request that looks up the query.
|
||||
* @param qstate: query state
|
||||
* @param id: module id.
|
||||
* @param sq: subnet qstate
|
||||
* @return false on failure.
|
||||
*/
|
||||
static int
|
||||
generate_sub_request(struct module_qstate *qstate, int id, struct subnet_qstate* sq)
|
||||
{
|
||||
struct module_qstate* subq = NULL;
|
||||
uint16_t qflags = 0; /* OPCODE QUERY, no flags */
|
||||
int prime = 0;
|
||||
int valrec = 0;
|
||||
struct query_info qinf;
|
||||
qinf.qname = qstate->qinfo.qname;
|
||||
qinf.qname_len = qstate->qinfo.qname_len;
|
||||
qinf.qtype = qstate->qinfo.qtype;
|
||||
qinf.qclass = qstate->qinfo.qclass;
|
||||
qinf.local_alias = NULL;
|
||||
|
||||
qflags |= BIT_RD;
|
||||
if((qstate->query_flags & BIT_CD)!=0) {
|
||||
qflags |= BIT_CD;
|
||||
/* The valrec is left off. Leave out: valrec = 1;
|
||||
* So that the cache is protected with DNSSEC validation.
|
||||
* Just like the global cache. DNSSEC validation is performed
|
||||
* regardless of the setting of the querier's CD flag. */
|
||||
}
|
||||
|
||||
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
|
||||
if(!(*qstate->env->attach_sub)(qstate, &qinf, qstate->client_info,
|
||||
qflags, prime, valrec, &subq)) {
|
||||
return 0;
|
||||
}
|
||||
if(subq) {
|
||||
/* It is possible to access the subquery module state. */
|
||||
struct subnet_qstate* subsq;
|
||||
if(!subnet_new_qstate(subq, id)) {
|
||||
verbose(VERB_ALGO, "Could not allocate new subnet qstate");
|
||||
return 0;
|
||||
}
|
||||
subsq = (struct subnet_qstate*)subq->minfo[id];
|
||||
subsq->is_subquery_nonsubnet = 1;
|
||||
subsq->started_no_cache_store = sq->started_no_cache_store;
|
||||
|
||||
/* When the client asks 0.0.0.0/0 and the name is not treated
|
||||
* as subnet, it is to be stored in the global cache.
|
||||
* Store that the client asked for that, if so. */
|
||||
if(sq->ecs_client_in.subnet_source_mask == 0 &&
|
||||
edns_opt_list_find(qstate->edns_opts_front_in,
|
||||
qstate->env->cfg->client_subnet_opcode)) {
|
||||
subq->no_cache_store = 1;
|
||||
subsq->is_subquery_scopezero = 1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the query without subnet
|
||||
* @param qstate: query state
|
||||
* @param id: module id.
|
||||
* @param sq: subnet qstate
|
||||
* @return module state
|
||||
*/
|
||||
static enum module_ext_state
|
||||
generate_lookup_without_subnet(struct module_qstate *qstate, int id,
|
||||
struct subnet_qstate* sq)
|
||||
{
|
||||
verbose(VERB_ALGO, "subnetcache: make subquery to look up without subnet");
|
||||
if(!generate_sub_request(qstate, id, sq)) {
|
||||
verbose(VERB_ALGO, "Could not generate sub query");
|
||||
qstate->return_rcode = LDNS_RCODE_SERVFAIL;
|
||||
qstate->return_msg = NULL;
|
||||
return module_finished;
|
||||
}
|
||||
sq->wait_subquery = 1;
|
||||
return module_wait_subquery;
|
||||
}
|
||||
|
||||
static enum module_ext_state
|
||||
eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
{
|
||||
@@ -481,52 +718,64 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
/* already an answer and its not a message, but retain
|
||||
* the actual rcode, instead of module_error, so send
|
||||
* module_finished */
|
||||
if(qstate->error_response_cache) {
|
||||
verbose(VERB_ALGO, "subnet: store error response");
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
update_cache(qstate, id);
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
}
|
||||
return module_finished;
|
||||
}
|
||||
|
||||
|
||||
/* We have not asked for subnet data */
|
||||
if (!sq->subnet_sent) {
|
||||
if (!sq->subnet_sent && !sq->subnet_sent_no_subnet) {
|
||||
if (s_in->subnet_validdata)
|
||||
verbose(VERB_QUERY, "subnetcache: 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) {
|
||||
if (!s_in->subnet_validdata && !sq->subnet_sent_no_subnet) {
|
||||
/* 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
|
||||
* is still useful to put it in the edns subnet cache for
|
||||
* when a client explicitly asks for subnet specific answer. */
|
||||
verbose(VERB_QUERY, "subnetcache: 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;
|
||||
return generate_lookup_without_subnet(qstate, id, sq);
|
||||
}
|
||||
|
||||
|
||||
/* Purposefully there was no sent subnet, and there is consequently
|
||||
* no subnet in the answer. If there was, use the subnet in the answer
|
||||
* anyway. But if there is not, treat it as a prefix 0 answer. */
|
||||
if(sq->subnet_sent_no_subnet && !s_in->subnet_validdata) {
|
||||
/* Fill in 0.0.0.0/0 scope 0, or ::0/0 scope 0, for caching. */
|
||||
s_in->subnet_addr_fam = s_out->subnet_addr_fam;
|
||||
s_in->subnet_source_mask = 0;
|
||||
s_in->subnet_scope_mask = 0;
|
||||
memset(s_in->subnet_addr, 0, INET6_SIZE);
|
||||
s_in->subnet_validdata = 1;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
/* we can not accept, perform query without option */
|
||||
verbose(VERB_QUERY, "subnetcache: 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;
|
||||
sq->subnet_sent_no_subnet = 0;
|
||||
return generate_lookup_without_subnet(qstate, id, sq);
|
||||
}
|
||||
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
@@ -535,7 +784,21 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
}
|
||||
sne->num_msg_nocache++;
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
|
||||
|
||||
/* If there is an expired answer in the global cache, remove that,
|
||||
* because expired answers would otherwise resurface once the ecs data
|
||||
* expires, giving once in a while global data responses for ecs
|
||||
* domains, with serve expired enabled. */
|
||||
if(qstate->env->cfg->serve_expired) {
|
||||
msg_cache_remove(qstate->env, qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len, qstate->qinfo.qtype,
|
||||
qstate->qinfo.qclass, 0);
|
||||
#ifdef USE_CACHEDB
|
||||
if(qstate->env->cachedb_enabled)
|
||||
cachedb_msg_remove(qstate);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (sq->subnet_downstream) {
|
||||
/* Client wants to see the answer, echo option back
|
||||
* and adjust the scope. */
|
||||
@@ -598,7 +861,7 @@ parse_subnet_option(struct edns_option* ecs_option, struct ecs_data* ecs)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
@@ -646,6 +909,7 @@ ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
|
||||
edns_opt_list_remove(&qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode);
|
||||
sq->subnet_sent = 0;
|
||||
sq->subnet_sent_no_subnet = 0;
|
||||
memset(&sq->ecs_server_out, 0, sizeof(sq->ecs_server_out));
|
||||
} else if (!sq->track_max_scope &&
|
||||
FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_NOERROR &&
|
||||
@@ -664,6 +928,24 @@ ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** verbose print edns subnet option in pretty print */
|
||||
static void
|
||||
subnet_log_print(const char* s, struct edns_option* ecs_opt)
|
||||
{
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char buf[256];
|
||||
char* str = buf;
|
||||
size_t str_len = sizeof(buf);
|
||||
if(!ecs_opt) {
|
||||
verbose(VERB_ALGO, "%s (null)", s);
|
||||
return;
|
||||
}
|
||||
(void)sldns_wire2str_edns_subnet_print(&str, &str_len,
|
||||
ecs_opt->opt_data, ecs_opt->opt_len);
|
||||
verbose(VERB_ALGO, "%s %s", s, buf);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ecs_edns_back_parsed(struct module_qstate* qstate, int id,
|
||||
void* ATTR_UNUSED(cbargs))
|
||||
@@ -678,6 +960,7 @@ ecs_edns_back_parsed(struct module_qstate* qstate, int id,
|
||||
qstate->env->cfg->client_subnet_opcode)) &&
|
||||
parse_subnet_option(ecs_opt, &sq->ecs_server_in) &&
|
||||
sq->subnet_sent && sq->ecs_server_in.subnet_validdata) {
|
||||
subnet_log_print("answer has edns subnet", ecs_opt);
|
||||
/* 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
|
||||
@@ -688,6 +971,14 @@ ecs_edns_back_parsed(struct module_qstate* qstate, int id,
|
||||
sq->ecs_server_in.subnet_scope_mask >
|
||||
sq->max_scope))
|
||||
sq->max_scope = sq->ecs_server_in.subnet_scope_mask;
|
||||
} else if(sq->subnet_sent_no_subnet) {
|
||||
/* The answer can be stored as scope 0, not in global cache. */
|
||||
/* This was already set in ecs_whitelist_check */
|
||||
qstate->no_cache_store = 1;
|
||||
} else if(sq->subnet_sent) {
|
||||
/* Need another query to be able to store in global cache. */
|
||||
/* This was already set in ecs_whitelist_check */
|
||||
qstate->no_cache_store = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -705,6 +996,33 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
strmodulevent(event));
|
||||
log_query_info(VERB_QUERY, "subnetcache operate: query", &qstate->qinfo);
|
||||
|
||||
if(sq && sq->wait_subquery_done) {
|
||||
/* The subquery lookup returned. */
|
||||
if(sq->ecs_client_in.subnet_source_mask == 0 &&
|
||||
edns_opt_list_find(qstate->edns_opts_front_in,
|
||||
qstate->env->cfg->client_subnet_opcode)) {
|
||||
if(!sq->started_no_cache_store &&
|
||||
qstate->return_msg) {
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
update_cache(qstate, id);
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
}
|
||||
if (sq->subnet_downstream)
|
||||
cp_edns_bad_response(&sq->ecs_client_out,
|
||||
&sq->ecs_client_in);
|
||||
/* It is a scope zero lookup, append edns subnet
|
||||
* option to the querier. */
|
||||
subnet_ecs_opt_list_append(&sq->ecs_client_out,
|
||||
&qstate->edns_opts_front_out, qstate,
|
||||
qstate->region);
|
||||
qstate->is_subnet_answer = 1;
|
||||
}
|
||||
sq->wait_subquery_done = 0;
|
||||
qstate->ext_state[id] = module_finished;
|
||||
qstate->no_cache_store = sq->started_no_cache_store;
|
||||
qstate->no_cache_lookup = sq->started_no_cache_lookup;
|
||||
return;
|
||||
}
|
||||
if((event == module_event_new || event == module_event_pass) &&
|
||||
sq == NULL) {
|
||||
struct edns_option* ecs_opt;
|
||||
@@ -715,6 +1033,8 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
}
|
||||
|
||||
sq = (struct subnet_qstate*)qstate->minfo[id];
|
||||
if(sq->wait_subquery)
|
||||
return; /* Wait for that subquery to return */
|
||||
|
||||
if((ecs_opt = edns_opt_list_find(
|
||||
qstate->edns_opts_front_in,
|
||||
@@ -726,11 +1046,17 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
subnet_log_print("query has edns subnet", ecs_opt);
|
||||
sq->subnet_downstream = 1;
|
||||
}
|
||||
else if(qstate->mesh_info->reply_list) {
|
||||
subnet_option_from_ss(
|
||||
&qstate->mesh_info->reply_list->query_reply.addr,
|
||||
&qstate->mesh_info->reply_list->query_reply.client_addr,
|
||||
&sq->ecs_client_in, qstate->env->cfg);
|
||||
}
|
||||
else if(qstate->client_addr.ss_family != AF_UNSPEC) {
|
||||
subnet_option_from_ss(
|
||||
&qstate->client_addr,
|
||||
&sq->ecs_client_in, qstate->env->cfg);
|
||||
}
|
||||
|
||||
@@ -738,6 +1064,14 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
/* 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;
|
||||
if(edns_opt_list_find(qstate->edns_opts_front_in,
|
||||
qstate->env->cfg->client_subnet_opcode)) {
|
||||
/* aggregated this deaggregated state */
|
||||
qstate->ext_state[id] =
|
||||
generate_lookup_without_subnet(
|
||||
qstate, id, sq);
|
||||
return;
|
||||
}
|
||||
verbose(VERB_ALGO, "subnetcache: pass to next module");
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
@@ -754,18 +1088,39 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
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, "subnetcache: answered from cache");
|
||||
qstate->ext_state[id] = module_finished;
|
||||
if(!sq->started_no_cache_lookup && !qstate->blacklist) {
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
if(qstate->mesh_info->reply_list &&
|
||||
lookup_and_reply(qstate, id, sq,
|
||||
qstate->env->cfg->prefetch)) {
|
||||
sne->num_msg_cache++;
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
qstate->is_subnet_answer = 1;
|
||||
verbose(VERB_QUERY, "subnetcache: answered from cache");
|
||||
qstate->ext_state[id] = module_finished;
|
||||
|
||||
ecs_opt_list_append(&sq->ecs_client_out,
|
||||
&qstate->edns_opts_front_out, qstate);
|
||||
subnet_ecs_opt_list_append(&sq->ecs_client_out,
|
||||
&qstate->edns_opts_front_out, qstate,
|
||||
qstate->region);
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
subnet_log_print("reply has edns subnet",
|
||||
edns_opt_list_find(
|
||||
qstate->edns_opts_front_out,
|
||||
qstate->env->cfg->
|
||||
client_subnet_opcode));
|
||||
}
|
||||
return;
|
||||
}
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
}
|
||||
if(sq->ecs_client_in.subnet_source_mask == 0 &&
|
||||
edns_opt_list_find(qstate->edns_opts_front_in,
|
||||
qstate->env->cfg->client_subnet_opcode)) {
|
||||
/* client asked for resolution without edns subnet */
|
||||
qstate->ext_state[id] = generate_lookup_without_subnet(
|
||||
qstate, id, sq);
|
||||
return;
|
||||
}
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
|
||||
sq->ecs_server_out.subnet_addr_fam =
|
||||
sq->ecs_client_in.subnet_addr_fam;
|
||||
@@ -783,7 +1138,7 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
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.
|
||||
* configuration. subnet_ecs_opt_list_append() will limit the address.
|
||||
* */
|
||||
memcpy(&sq->ecs_server_out.subnet_addr,
|
||||
sq->ecs_client_in.subnet_addr, INET6_SIZE);
|
||||
@@ -802,15 +1157,27 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
if(sq && sq->wait_subquery)
|
||||
return; /* Wait for that subquery to 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);
|
||||
subnet_ecs_opt_list_append(&sq->ecs_client_out,
|
||||
&qstate->edns_opts_front_out, qstate,
|
||||
qstate->region);
|
||||
qstate->is_subnet_answer = 1;
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
subnet_log_print("reply has edns subnet",
|
||||
edns_opt_list_find(
|
||||
qstate->edns_opts_front_out,
|
||||
qstate->env->cfg->
|
||||
client_subnet_opcode));
|
||||
}
|
||||
}
|
||||
qstate->no_cache_store = sq->started_no_cache_store;
|
||||
qstate->no_cache_lookup = sq->started_no_cache_lookup;
|
||||
return;
|
||||
}
|
||||
if(sq && outbound) {
|
||||
@@ -841,10 +1208,27 @@ subnetmod_clear(struct module_qstate *ATTR_UNUSED(qstate),
|
||||
}
|
||||
|
||||
void
|
||||
subnetmod_inform_super(struct module_qstate *ATTR_UNUSED(qstate),
|
||||
int ATTR_UNUSED(id), struct module_qstate *ATTR_UNUSED(super))
|
||||
subnetmod_inform_super(struct module_qstate *qstate, int id,
|
||||
struct module_qstate *super)
|
||||
{
|
||||
/* Not used */
|
||||
struct subnet_qstate* super_sq =
|
||||
(struct subnet_qstate*)super->minfo[id];
|
||||
log_query_info(VERB_ALGO, "subnetcache inform_super: query",
|
||||
&super->qinfo);
|
||||
super_sq->wait_subquery = 0;
|
||||
super_sq->wait_subquery_done = 1;
|
||||
if(qstate->return_rcode != LDNS_RCODE_NOERROR ||
|
||||
!qstate->return_msg) {
|
||||
super->return_msg = NULL;
|
||||
super->return_rcode = LDNS_RCODE_SERVFAIL;
|
||||
return;
|
||||
}
|
||||
super->return_rcode = LDNS_RCODE_NOERROR;
|
||||
super->return_msg = dns_copy_msg(qstate->return_msg, super->region);
|
||||
if(!super->return_msg) {
|
||||
log_err("subnetcache: copy response, out of memory");
|
||||
super->return_rcode = LDNS_RCODE_SERVFAIL;
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -861,7 +1245,8 @@ subnetmod_get_mem(struct module_env *env, int id)
|
||||
* The module function block
|
||||
*/
|
||||
static struct module_func_block subnetmod_block = {
|
||||
"subnetcache", &subnetmod_init, &subnetmod_deinit, &subnetmod_operate,
|
||||
"subnetcache",
|
||||
NULL, NULL, &subnetmod_init, &subnetmod_deinit, &subnetmod_operate,
|
||||
&subnetmod_inform_super, &subnetmod_clear, &subnetmod_get_mem
|
||||
};
|
||||
|
||||
|
||||
@@ -69,13 +69,24 @@ struct subnet_env {
|
||||
};
|
||||
|
||||
struct subnet_msg_cache_data {
|
||||
/** Tree for nodes with IPv4 subnets. */
|
||||
struct addrtree* tree4;
|
||||
/** Tree for nodes with IPv6 subnets. */
|
||||
struct addrtree* tree6;
|
||||
/** If servfail is stored, for how long. Abs time in seconds.
|
||||
* This protects against too much recusion on the item when
|
||||
* resolution fails, for a couple of seconds. */
|
||||
time_t ttl_servfail;
|
||||
/** servfail ede */
|
||||
sldns_ede_code ede_fail;
|
||||
/** servfail reason */
|
||||
char* reason_fail;
|
||||
};
|
||||
|
||||
struct subnet_qstate {
|
||||
/** We need the hash for both cache lookup and insert */
|
||||
hashvalue_type qinfo_hash;
|
||||
int qinfo_hash_calculated;
|
||||
/** ecs_data for client communication */
|
||||
struct ecs_data ecs_client_in;
|
||||
struct ecs_data ecs_client_out;
|
||||
@@ -84,6 +95,13 @@ struct subnet_qstate {
|
||||
struct ecs_data ecs_server_out;
|
||||
int subnet_downstream;
|
||||
int subnet_sent;
|
||||
/**
|
||||
* If there was no subnet sent because the client used source prefix
|
||||
* length 0 for omitting the information. Then the answer is cached
|
||||
* like subnet was a /0 scope. Like the subnet_sent flag, but when
|
||||
* the EDNS subnet option is omitted because the client asked.
|
||||
*/
|
||||
int subnet_sent_no_subnet;
|
||||
/** keep track of longest received scope, set after receiving CNAME for
|
||||
* incoming QNAME. */
|
||||
int track_max_scope;
|
||||
@@ -92,6 +110,16 @@ struct subnet_qstate {
|
||||
uint8_t max_scope;
|
||||
/** has the subnet module been started with no_cache_store? */
|
||||
int started_no_cache_store;
|
||||
/** has the subnet module been started with no_cache_lookup? */
|
||||
int started_no_cache_lookup;
|
||||
/** Wait for subquery that has been started for nonsubnet lookup. */
|
||||
int wait_subquery;
|
||||
/** The subquery waited for is done. */
|
||||
int wait_subquery_done;
|
||||
/** The subnet state is a subquery state for nonsubnet lookup. */
|
||||
int is_subquery_nonsubnet;
|
||||
/** This is a subquery, and it is made due to a scope zero request. */
|
||||
int is_subquery_scopezero;
|
||||
};
|
||||
|
||||
void subnet_data_delete(void* d, void* ATTR_UNUSED(arg));
|
||||
@@ -143,4 +171,11 @@ int ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
|
||||
/** mark subnet msg to be deleted */
|
||||
void subnet_markdel(void* key);
|
||||
|
||||
/** Add ecs struct to edns list, after parsing it to wire format. */
|
||||
void subnet_ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
|
||||
struct module_qstate *qstate, struct regional *region);
|
||||
|
||||
/** Create ecs_data from the sockaddr_storage information. */
|
||||
void subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs,
|
||||
struct config_file* cfg);
|
||||
#endif /* SUBNETMOD_H */
|
||||
|
||||
@@ -100,6 +100,8 @@ ipsecmod_whitelist_apply_cfg(struct ipsecmod_env* ie,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
ie->whitelist = rbtree_create(name_tree_compare);
|
||||
if (!ie->whitelist)
|
||||
return 0;
|
||||
if(!read_whitelist(ie->whitelist, cfg))
|
||||
return 0;
|
||||
name_tree_init_parents(ie->whitelist);
|
||||
|
||||
+90
-39
@@ -37,7 +37,7 @@
|
||||
* \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
|
||||
* by also querying for the IPSECKEY for A/AAAA queries and calling a
|
||||
* configurable hook (eg. signaling an IKE daemon) before replying.
|
||||
*/
|
||||
|
||||
@@ -51,6 +51,9 @@
|
||||
#include "util/config_file.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#ifdef HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
/** Apply configuration to ipsecmod module 'global' state. */
|
||||
static int
|
||||
@@ -60,6 +63,11 @@ ipsecmod_apply_cfg(struct ipsecmod_env* ipsecmod_env, struct config_file* cfg)
|
||||
log_err("ipsecmod: missing ipsecmod-hook.");
|
||||
return 0;
|
||||
}
|
||||
if(access(cfg->ipsecmod_hook, X_OK) != 0) {
|
||||
log_err("ipsecmod: ipsecmod-hook '%s' is not an executable file: %s",
|
||||
cfg->ipsecmod_hook, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if(cfg->ipsecmod_whitelist &&
|
||||
!ipsecmod_whitelist_apply_cfg(ipsecmod_env, cfg))
|
||||
return 0;
|
||||
@@ -163,7 +171,7 @@ generate_request(struct module_qstate* qstate, int id, uint8_t* name,
|
||||
}
|
||||
|
||||
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
|
||||
if(!(*qstate->env->attach_sub)(qstate, &ask,
|
||||
if(!(*qstate->env->attach_sub)(qstate, &ask, NULL,
|
||||
(uint16_t)(BIT_RD|flags), 0, 0, &newq)){
|
||||
log_err("Could not generate request: out of memory");
|
||||
return 0;
|
||||
@@ -250,27 +258,16 @@ 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;
|
||||
char qname_s[LDNS_MAX_DOMAINLEN*5+16], ttl_s[32], a_s[32768], k_s[32768];
|
||||
char *s, *tempstring;
|
||||
int w = 0, w_temp, qtype;
|
||||
struct ub_packed_rrset_key* rrset_key;
|
||||
struct packed_rrset_data* rrset_data;
|
||||
uint8_t *tempdata;
|
||||
pid_t pid;
|
||||
int st;
|
||||
char* argv[6];
|
||||
|
||||
/* 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);
|
||||
@@ -283,17 +280,24 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
|
||||
free(tempstring);
|
||||
return 0;
|
||||
}
|
||||
w += sldns_str_print(&s, &slen, "\"%s\"", tempstring);
|
||||
if(strlen(tempstring)+1 > sizeof(qname_s)) {
|
||||
log_err("ipsecmod: string too long");
|
||||
free(tempstring);
|
||||
return 0;
|
||||
}
|
||||
snprintf(qname_s, sizeof(qname_s), "%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, " ");
|
||||
snprintf(ttl_s, sizeof(ttl_s), "%ld", (long)rrset_data->ttl);
|
||||
|
||||
rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
if(!rrset_key) {
|
||||
log_err("ipsecmod: could not find answer rrset for A/AAAA");
|
||||
return 0;
|
||||
}
|
||||
/* 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
|
||||
@@ -304,9 +308,15 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
|
||||
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, "\"");
|
||||
if(!rrset_data) {
|
||||
log_err("ipsecmod: Answer has no data");
|
||||
return 0;
|
||||
}
|
||||
/* Copy the A/AAAA record(s) into the buffer. */
|
||||
w = 0;
|
||||
s = a_s;
|
||||
slen = sizeof(a_s);
|
||||
memset(s, 0, slen);
|
||||
for(i=0; i<rrset_data->count; i++) {
|
||||
if(i > 0) {
|
||||
/* Put space into the buffer. */
|
||||
@@ -322,7 +332,7 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
|
||||
} 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");
|
||||
log_err("ipsecmod: command addr argument too long");
|
||||
return 0;
|
||||
} else {
|
||||
s += w_temp;
|
||||
@@ -330,12 +340,17 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
|
||||
w += w_temp;
|
||||
}
|
||||
}
|
||||
w += sldns_str_print(&s, &slen, "\"");
|
||||
/* Put space into the buffer. */
|
||||
w += sldns_str_print(&s, &slen, " ");
|
||||
if(w >= (int)sizeof(a_s)) {
|
||||
log_err("ipsecmod: command addr argument too long");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy the IPSECKEY record(s) into the buffer. Start and end this section
|
||||
* with a double quote. */
|
||||
w += sldns_str_print(&s, &slen, "\"");
|
||||
w = 0;
|
||||
s = k_s;
|
||||
slen = sizeof(k_s);
|
||||
memset(s, 0, slen);
|
||||
rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data;
|
||||
for(i=0; i<rrset_data->count; i++) {
|
||||
if(i > 0) {
|
||||
@@ -362,15 +377,44 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
|
||||
w += w_temp;
|
||||
}
|
||||
}
|
||||
w += sldns_str_print(&s, &slen, "\"");
|
||||
if(w >= (int)sizeof(str)) {
|
||||
log_err("ipsecmod: shell command too long");
|
||||
if(w >= (int)sizeof(k_s)) {
|
||||
log_err("ipsecmod: command ipseckey argument too long");
|
||||
return 0;
|
||||
}
|
||||
verbose(VERB_ALGO, "ipsecmod: shell command: '%s'", str);
|
||||
|
||||
/* ipsecmod-hook should return 0 on success. */
|
||||
if(system(str) != 0)
|
||||
/* exec the ipsecmod-hook */
|
||||
argv[0] = qstate->env->cfg->ipsecmod_hook;
|
||||
argv[1] = qname_s;
|
||||
argv[2] = ttl_s;
|
||||
argv[3] = a_s;
|
||||
argv[4] = k_s;
|
||||
argv[5] = NULL;
|
||||
verbose(VERB_ALGO, "ipsecmod: exec %s \"%s\" %s \"%s\" \"%s\"",
|
||||
argv[0], argv[1], argv[2], argv[3], argv[4]);
|
||||
if((pid = fork()) < 0) {
|
||||
log_err("ipsecmod: for exec, can not fork: %s",
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if(pid == 0) {
|
||||
if(execv(argv[0], argv) < 0)
|
||||
fprintf(stderr, "ipsecmod: execv: %s\n",
|
||||
strerror(errno));
|
||||
_exit(127);
|
||||
}
|
||||
while(1) {
|
||||
if(waitpid(pid, &st, 0) < 0) {
|
||||
if(errno == EINTR)
|
||||
continue;
|
||||
log_err("ipsecmod: wait_pid: %s", strerror(errno));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(!(WIFEXITED(st) && WEXITSTATUS(st) == 0)) {
|
||||
/* the command failed */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -435,6 +479,12 @@ ipsecmod_handle_query(struct module_qstate* qstate,
|
||||
* ipsecmod_max_ttl. */
|
||||
rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
if(!rrset_key) {
|
||||
log_err("ipsecmod: reply-find-answer failed");
|
||||
errinf(qstate, "ipsecmod: reply-find-answer failed");
|
||||
ipsecmod_error(qstate, id);
|
||||
return;
|
||||
}
|
||||
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. */
|
||||
@@ -456,7 +506,8 @@ ipsecmod_handle_query(struct module_qstate* qstate,
|
||||
/* 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)) {
|
||||
0, qstate->region, qstate->query_flags, qstate->qstarttime,
|
||||
qstate->is_valrec)) {
|
||||
log_err("ipsecmod: out of memory caching record");
|
||||
}
|
||||
qstate->ext_state[id] = module_finished;
|
||||
@@ -615,7 +666,7 @@ ipsecmod_get_mem(struct module_env* env, int id)
|
||||
*/
|
||||
static struct module_func_block ipsecmod_block = {
|
||||
"ipsecmod",
|
||||
&ipsecmod_init, &ipsecmod_deinit, &ipsecmod_operate,
|
||||
NULL, NULL, &ipsecmod_init, &ipsecmod_deinit, &ipsecmod_operate,
|
||||
&ipsecmod_inform_super, &ipsecmod_clear, &ipsecmod_get_mem
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@
|
||||
* \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
|
||||
* by also querying for the IPSECKEY for A/AAAA queries and calling a
|
||||
* configurable hook (eg. signaling an IKE daemon) before replying.
|
||||
*/
|
||||
|
||||
|
||||
+199
-78
@@ -17,9 +17,19 @@
|
||||
#include "sldns/wire2str.h"
|
||||
#include "sldns/parseutil.h"
|
||||
|
||||
#ifdef HAVE_NET_PFVAR_H
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#include <net/pfvar.h>
|
||||
typedef intptr_t filter_dev;
|
||||
#else
|
||||
#include <libmnl/libmnl.h>
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/netfilter/ipset/ip_set.h>
|
||||
typedef struct mnl_socket * filter_dev;
|
||||
#endif
|
||||
|
||||
#define BUFF_LEN 256
|
||||
|
||||
@@ -41,28 +51,99 @@ static int error_response(struct module_qstate* qstate, int id, int rcode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mnl_socket * open_mnl_socket() {
|
||||
struct mnl_socket *mnl;
|
||||
#ifdef HAVE_NET_PFVAR_H
|
||||
static void * open_filter() {
|
||||
filter_dev dev;
|
||||
|
||||
mnl = mnl_socket_open(NETLINK_NETFILTER);
|
||||
if (!mnl) {
|
||||
dev = open("/dev/pf", O_RDWR);
|
||||
if (dev == -1) {
|
||||
log_err("open(\"/dev/pf\") failed: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return (void *)dev;
|
||||
}
|
||||
#else
|
||||
static void * open_filter() {
|
||||
filter_dev dev;
|
||||
|
||||
dev = mnl_socket_open(NETLINK_NETFILTER);
|
||||
if (!dev) {
|
||||
log_err("ipset: could not open netfilter.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(mnl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||
mnl_socket_close(mnl);
|
||||
if (mnl_socket_bind(dev, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||
mnl_socket_close(dev);
|
||||
log_err("ipset: could not bind netfilter.");
|
||||
return NULL;
|
||||
}
|
||||
return mnl;
|
||||
return (void *)dev;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int add_to_ipset(struct mnl_socket *mnl, const char *setname, const void *ipaddr, int af) {
|
||||
#ifdef HAVE_NET_PFVAR_H
|
||||
static int add_to_ipset(filter_dev dev, const char *setname, const void *ipaddr, int af) {
|
||||
struct pfioc_table io;
|
||||
struct pfr_addr addr;
|
||||
const char *p;
|
||||
int i;
|
||||
|
||||
bzero(&io, sizeof(io));
|
||||
bzero(&addr, sizeof(addr));
|
||||
|
||||
p = strrchr(setname, '/');
|
||||
if (p) {
|
||||
i = p - setname;
|
||||
if (i >= PATH_MAX) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
memcpy(io.pfrio_table.pfrt_anchor, setname, i);
|
||||
if (i < PATH_MAX)
|
||||
io.pfrio_table.pfrt_anchor[i] = '\0';
|
||||
p++;
|
||||
}
|
||||
else
|
||||
p = setname;
|
||||
|
||||
if (strlen(p) >= PF_TABLE_NAME_SIZE) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
strlcpy(io.pfrio_table.pfrt_name, p, PF_TABLE_NAME_SIZE);
|
||||
|
||||
io.pfrio_buffer = &addr;
|
||||
io.pfrio_size = 1;
|
||||
io.pfrio_esize = sizeof(addr);
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
addr.pfra_ip4addr = *(struct in_addr *)ipaddr;
|
||||
addr.pfra_net = 32;
|
||||
break;
|
||||
case AF_INET6:
|
||||
addr.pfra_ip6addr = *(struct in6_addr *)ipaddr;
|
||||
addr.pfra_net = 128;
|
||||
break;
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
return -1;
|
||||
}
|
||||
addr.pfra_af = af;
|
||||
|
||||
if (ioctl(dev, DIOCRADDADDRS, &io) == -1) {
|
||||
log_err("ioctl failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int add_to_ipset(filter_dev dev, const char *setname, const void *ipaddr, int af) {
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfg;
|
||||
struct nlattr *nested[2];
|
||||
static char buffer[BUFF_LEN];
|
||||
char buffer[BUFF_LEN];
|
||||
|
||||
if (strlen(setname) >= IPSET_MAXNAMELEN) {
|
||||
errno = ENAMETOOLONG;
|
||||
@@ -91,14 +172,15 @@ static int add_to_ipset(struct mnl_socket *mnl, const char *setname, const void
|
||||
mnl_attr_nest_end(nlh, nested[1]);
|
||||
mnl_attr_nest_end(nlh, nested[0]);
|
||||
|
||||
if (mnl_socket_sendto(mnl, nlh, nlh->nlmsg_len) < 0) {
|
||||
if (mnl_socket_sendto(dev, nlh, nlh->nlmsg_len) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl,
|
||||
ipset_add_rrset_data(struct ipset_env *ie,
|
||||
struct packed_rrset_data *d, const char* setname, int af,
|
||||
const char* dname)
|
||||
{
|
||||
@@ -123,12 +205,9 @@ ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl,
|
||||
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);
|
||||
ret = add_to_ipset((filter_dev)ie->dev, 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;
|
||||
}
|
||||
}
|
||||
@@ -137,85 +216,97 @@ ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl,
|
||||
|
||||
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,
|
||||
struct ub_packed_rrset_key *rrset, const char *qname, int qlen,
|
||||
const char *setname, int af)
|
||||
{
|
||||
static char dname[BUFF_LEN];
|
||||
const char *s;
|
||||
char dname[LDNS_MAX_DOMAINLEN*4+16];
|
||||
const char *ds, *qs;
|
||||
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) {
|
||||
dlen = sldns_wire2str_dname_buf(rrset->rk.dname, rrset->rk.dname_len, dname, sizeof(dname));
|
||||
if (dlen == 0 || dlen >= (int)sizeof(dname)) {
|
||||
log_err("bad domain name");
|
||||
return -1;
|
||||
}
|
||||
if (dname[dlen - 1] == '.') {
|
||||
dlen--;
|
||||
}
|
||||
if (qname[qlen - 1] == '.') {
|
||||
qlen--;
|
||||
}
|
||||
|
||||
for (p = env->cfg->local_zones_ipset; p; p = p->next) {
|
||||
ds = NULL;
|
||||
qs = NULL;
|
||||
plen = strlen(p->str);
|
||||
if (p->str[plen - 1] == '.') {
|
||||
plen--;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if (dlen == plen || (dlen > plen && dname[dlen - plen - 1] == '.' )) {
|
||||
ds = dname + (dlen - plen);
|
||||
}
|
||||
if (qlen == plen || (qlen > plen && qname[qlen - plen - 1] == '.' )) {
|
||||
qs = qname + (qlen - plen);
|
||||
}
|
||||
if ((ds && strncasecmp(p->str, ds, plen) == 0)
|
||||
|| (qs && strncasecmp(p->str, qs, plen) == 0)) {
|
||||
d = (struct packed_rrset_data*)rrset->entry.data;
|
||||
ipset_add_rrset_data(ie, 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;
|
||||
|
||||
static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
|
||||
struct query_info qinfo, struct ipset_env *ie)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
const char *setname;
|
||||
|
||||
struct ub_packed_rrset_key *rrset;
|
||||
|
||||
int af;
|
||||
char qname[LDNS_MAX_DOMAINLEN*4+16];
|
||||
int qlen;
|
||||
|
||||
|
||||
mnl = (struct mnl_socket *)ie->mnl;
|
||||
if (!mnl) {
|
||||
// retry to create mnl socket
|
||||
mnl = open_mnl_socket();
|
||||
if (!mnl) {
|
||||
#ifdef HAVE_NET_PFVAR_H
|
||||
#else
|
||||
if (!ie->dev) {
|
||||
/* retry to create mnl socket */
|
||||
ie->dev = open_filter();
|
||||
if (!ie->dev) {
|
||||
log_warn("ipset open_filter failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ie->mnl = mnl;
|
||||
qlen = sldns_wire2str_dname_buf(qinfo.qname, qinfo.qname_len,
|
||||
qname, sizeof(qname));
|
||||
if(qlen == 0 || qlen >= (int)sizeof(qname)) {
|
||||
log_err("bad domain name");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < return_msg->rep->rrset_count; ++i) {
|
||||
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)) {
|
||||
if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A &&
|
||||
ie->v4_enabled == 1) {
|
||||
af = AF_INET;
|
||||
if ((ie->v4_enabled == 1)) {
|
||||
setname = ie->name_v4;
|
||||
}
|
||||
} else {
|
||||
setname = ie->name_v4;
|
||||
} else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA &&
|
||||
ie->v6_enabled == 1) {
|
||||
af = AF_INET6;
|
||||
if ((ie->v6_enabled == 1)) {
|
||||
setname = ie->name_v6;
|
||||
}
|
||||
setname = ie->name_v6;
|
||||
}
|
||||
|
||||
if (setname) {
|
||||
if(ipset_check_zones_for_rrset(env, ie, mnl, rrset,
|
||||
setname, af) == -1)
|
||||
if(ipset_check_zones_for_rrset(env, ie, rrset, qname,
|
||||
qlen, setname, af) == -1)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -223,7 +314,7 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg, stru
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipset_init(struct module_env* env, int id) {
|
||||
int ipset_startup(struct module_env* env, int id) {
|
||||
struct ipset_env *ipset_env;
|
||||
|
||||
ipset_env = (struct ipset_env *)calloc(1, sizeof(struct ipset_env));
|
||||
@@ -234,10 +325,56 @@ int ipset_init(struct module_env* env, int id) {
|
||||
|
||||
env->modinfo[id] = (void *)ipset_env;
|
||||
|
||||
ipset_env->mnl = NULL;
|
||||
#ifdef HAVE_NET_PFVAR_H
|
||||
ipset_env->dev = open_filter();
|
||||
if (!ipset_env->dev) {
|
||||
log_err("ipset open_filter failed");
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
ipset_env->dev = NULL;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ipset_destartup(struct module_env* env, int id) {
|
||||
filter_dev dev;
|
||||
struct ipset_env *ipset_env;
|
||||
|
||||
if (!env || !env->modinfo[id]) {
|
||||
return;
|
||||
}
|
||||
ipset_env = (struct ipset_env*)env->modinfo[id];
|
||||
|
||||
dev = (filter_dev)ipset_env->dev;
|
||||
if (dev) {
|
||||
#if HAVE_NET_PFVAR_H
|
||||
close(dev);
|
||||
#else
|
||||
mnl_socket_close(dev);
|
||||
#endif
|
||||
ipset_env->dev = NULL;
|
||||
}
|
||||
|
||||
free(ipset_env);
|
||||
env->modinfo[id] = NULL;
|
||||
}
|
||||
|
||||
int ipset_init(struct module_env* env, int id) {
|
||||
struct ipset_env *ipset_env = env->modinfo[id];
|
||||
|
||||
ipset_env->name_v4 = env->cfg->ipset_name_v4;
|
||||
ipset_env->name_v6 = env->cfg->ipset_name_v6;
|
||||
#ifndef HAVE_NET_PFVAR_H
|
||||
if (ipset_env->name_v4 && strlen(ipset_env->name_v4) >= IPSET_MAXNAMELEN) {
|
||||
log_err("ipset: name-v4 exceeds IPSET_MAXNAMELEN (%d)", IPSET_MAXNAMELEN);
|
||||
return 0;
|
||||
}
|
||||
if (ipset_env->name_v6 && strlen(ipset_env->name_v6) >= IPSET_MAXNAMELEN) {
|
||||
log_err("ipset: name-v6 exceeds IPSET_MAXNAMELEN (%d)", IPSET_MAXNAMELEN);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
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;
|
||||
@@ -250,24 +387,8 @@ int ipset_init(struct module_env* env, int id) {
|
||||
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;
|
||||
void ipset_deinit(struct module_env *ATTR_UNUSED(env), int ATTR_UNUSED(id)) {
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
static int ipset_new(struct module_qstate* qstate, int id) {
|
||||
@@ -311,7 +432,7 @@ void ipset_operate(struct module_qstate *qstate, enum module_ev event, int id,
|
||||
|
||||
if (iq && (event == module_event_moddone)) {
|
||||
if (qstate->return_msg && qstate->return_msg->rep) {
|
||||
ipset_update(qstate->env, qstate->return_msg, ie);
|
||||
ipset_update(qstate->env, qstate->return_msg, qstate->qinfo, ie);
|
||||
}
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
@@ -373,8 +494,8 @@ size_t ipset_get_mem(struct module_env *env, int id) {
|
||||
*/
|
||||
static struct module_func_block ipset_block = {
|
||||
"ipset",
|
||||
&ipset_init, &ipset_deinit, &ipset_operate,
|
||||
&ipset_inform_super, &ipset_clear, &ipset_get_mem
|
||||
&ipset_startup, &ipset_destartup, &ipset_init, &ipset_deinit,
|
||||
&ipset_operate, &ipset_inform_super, &ipset_clear, &ipset_get_mem
|
||||
};
|
||||
|
||||
struct module_func_block * ipset_get_funcblock(void) {
|
||||
|
||||
+5
-1
@@ -37,7 +37,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
struct ipset_env {
|
||||
void* mnl;
|
||||
void* dev;
|
||||
|
||||
int v4_enabled;
|
||||
int v6_enabled;
|
||||
@@ -50,6 +50,10 @@ struct ipset_qstate {
|
||||
int dummy;
|
||||
};
|
||||
|
||||
/** Startup the ipset module */
|
||||
int ipset_startup(struct module_env* env, int id);
|
||||
/** Destartup the ipset module */
|
||||
void ipset_destartup(struct module_env* env, int id);
|
||||
/** Init the ipset module */
|
||||
int ipset_init(struct module_env* env, int id);
|
||||
/** Deinit the ipset module */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user