mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-03 18:35:06 -05:00
Compare commits
1011 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a030ed4f39 | ||
|
|
9fc15394de | ||
|
|
34ea8770d0 | ||
|
|
a5897840a0 | ||
|
|
59087dd0ff | ||
|
|
1924481077 | ||
|
|
da1f7563e9 | ||
|
|
7496a14d2d | ||
|
|
6e6dead680 | ||
|
|
55dbbab5eb | ||
|
|
d6b6461658 | ||
|
|
85f7a4054d | ||
|
|
01965d147a | ||
|
|
6a84126c28 | ||
|
|
32f8bec92d | ||
|
|
00a6394b48 | ||
|
|
ca5a791d09 | ||
|
|
6a9c756cf0 | ||
|
|
1714d3e8ae | ||
|
|
25b7d47b34 | ||
|
|
9e8b4bae11 | ||
|
|
a466395a19 | ||
|
|
a3cb3fc490 | ||
|
|
3396778061 | ||
|
|
01cef64070 | ||
|
|
a9bfaf9e54 | ||
|
|
cec7c44f61 | ||
|
|
38ac2b39ce | ||
|
|
967e358dbc | ||
|
|
60721d2cc1 | ||
|
|
b698184939 | ||
|
|
c6c833fb9c | ||
|
|
3eb43f4619 | ||
|
|
440c159217 | ||
|
|
b49dcfbef7 | ||
|
|
a4d9cfaaeb | ||
|
|
7b2430fc3c | ||
|
|
bd8be7133d | ||
|
|
692ef0549b | ||
|
|
d6fdae5f1d | ||
|
|
8feb37df2b | ||
|
|
1d2b481069 | ||
|
|
c062fa2fa9 | ||
|
|
f444561a10 | ||
|
|
046f219a0e | ||
|
|
3cd32ed660 | ||
|
|
4f172f6f9f | ||
|
|
22fc0a6846 | ||
|
|
71e596b443 | ||
|
|
98c245ed7b | ||
|
|
bf57222e96 | ||
|
|
c075c070f0 | ||
|
|
4bc6950632 | ||
|
|
bde279c093 | ||
|
|
4f6ab8ac93 | ||
|
|
d2d82e2e5f | ||
|
|
1b2510e4b2 | ||
|
|
e735be59a7 | ||
|
|
5190539ce1 | ||
|
|
5776eb35b6 | ||
|
|
f102acd423 | ||
|
|
06486f3162 | ||
|
|
1619453b2b | ||
|
|
5a40950ffd | ||
|
|
16eb18e797 | ||
|
|
7bf0684557 | ||
|
|
961c490436 | ||
|
|
d8b0a4a288 | ||
|
|
76d12ac136 | ||
|
|
434faeecb8 | ||
|
|
ea2858b323 | ||
|
|
3391d5f846 | ||
|
|
7d6de7afe6 | ||
|
|
67ce6bd279 | ||
|
|
770db1fe02 | ||
|
|
d73394dde1 | ||
|
|
eb0c7e33d2 | ||
|
|
b9cfdaf666 | ||
|
|
5039f959e0 | ||
|
|
b7a54f8cd8 | ||
|
|
7b6435b2b8 | ||
|
|
8854c00d48 | ||
|
|
c0867b58f5 | ||
|
|
05183748a8 | ||
|
|
e56154a687 | ||
|
|
e5784c1ca8 | ||
|
|
282a9c7d7c | ||
|
|
b11ca92ca6 | ||
|
|
49846b3e68 | ||
|
|
0887824324 | ||
|
|
fbe65f2c71 | ||
|
|
eb5a412bed | ||
|
|
0cc8f68754 | ||
|
|
7079ca2718 | ||
|
|
70ad0bc573 | ||
|
|
22345c5ddf | ||
|
|
28b0a23949 | ||
|
|
1b57a796b1 | ||
|
|
0abb470022 | ||
|
|
b7a4b84f0a | ||
|
|
794a1e6cfe | ||
|
|
7c4db99d44 | ||
|
|
30b6213910 | ||
|
|
b6a27df5b9 | ||
|
|
18d514d552 | ||
|
|
f1ed08abf0 | ||
|
|
6d42dd8603 | ||
|
|
e7100e106d | ||
|
|
6402350c83 | ||
|
|
236576c124 | ||
|
|
9a83cab2f8 | ||
|
|
92706b158e | ||
|
|
ad34b26955 | ||
|
|
12c434fdc0 | ||
|
|
9ceaef6479 | ||
|
|
abb56bded2 | ||
|
|
0bcd10560a | ||
|
|
46b7148f3b | ||
|
|
37732130e1 | ||
|
|
7a3b1414cd | ||
|
|
a4a21c1dca | ||
|
|
206e597b04 | ||
|
|
ceef8ad2d8 | ||
|
|
2d581a6a86 | ||
|
|
82f7fa3887 | ||
|
|
f88a01e8c7 | ||
|
|
ca8e03b785 | ||
|
|
15932c9d7b | ||
|
|
0fc0f906e1 | ||
|
|
7f58852ec0 | ||
|
|
85a9a53e69 | ||
|
|
aa0c0fc401 | ||
|
|
0e694e08fc | ||
|
|
c2ddcc9f36 | ||
|
|
7a7cf6a5ce | ||
|
|
c2f83bd8a4 | ||
|
|
1f0e6296c6 | ||
|
|
ab1f01bacd | ||
|
|
b9b896d8e7 | ||
|
|
6be54f366c | ||
|
|
802cdb3230 | ||
|
|
7e27880cb6 | ||
|
|
d3ad85aa43 | ||
|
|
59192fc695 | ||
|
|
9095b80c5b | ||
|
|
ed5b78bf09 | ||
|
|
d6aafa3f64 | ||
|
|
8de04a808d | ||
|
|
2a299233b3 | ||
|
|
64f83c8861 | ||
|
|
1009fe3d9c | ||
|
|
ba341fe81a | ||
|
|
36e8cb6530 | ||
|
|
273da62aec | ||
|
|
41788184a7 | ||
|
|
fb9c2c7dc8 | ||
|
|
43116be122 | ||
|
|
ee038d5de5 | ||
|
|
ea7fae5277 | ||
|
|
70b108ab69 | ||
|
|
08b152d6a2 | ||
|
|
83c6213c67 | ||
|
|
4253075a97 | ||
|
|
0abdc2a350 | ||
|
|
31669f343a | ||
|
|
438b881ab4 | ||
|
|
27863146a3 | ||
|
|
cd4b73612b | ||
|
|
3c217a9e37 | ||
|
|
cde3a003ea | ||
|
|
2c35f56612 | ||
|
|
4295db25d7 | ||
|
|
3c06e57f24 | ||
|
|
e949cf5967 | ||
|
|
4eeaf34295 | ||
|
|
2212a90698 | ||
|
|
dc52b61dad | ||
|
|
bbf4c3186b | ||
|
|
f72016a78e | ||
|
|
29b587a9c5 | ||
|
|
cec4f2b140 | ||
|
|
05278c3b4c | ||
|
|
1769b8ea0f | ||
|
|
5686bd87d7 | ||
|
|
1cda2db45d | ||
|
|
fdf9640349 | ||
|
|
8f2d5d99f1 | ||
|
|
61272e7ce8 | ||
|
|
88b76f49cc | ||
|
|
ad942e352d | ||
|
|
39c2bcd462 | ||
|
|
ae10664b24 | ||
|
|
074dac4195 | ||
|
|
a8239b865a | ||
|
|
f6a9c5c1b7 | ||
|
|
42774ee851 | ||
|
|
4e26f48781 | ||
|
|
aec97397e8 | ||
|
|
183a648d01 | ||
|
|
27f8ad7fd1 | ||
|
|
a79fbef21e | ||
|
|
565976acbe | ||
|
|
54bbd2b1c0 | ||
|
|
10b2b53aa7 | ||
|
|
e18ee0bb46 | ||
|
|
857d51ea8e | ||
|
|
ba85544611 | ||
|
|
293806d52d | ||
|
|
7f45eb7957 | ||
|
|
f0c48680fe | ||
|
|
78283dd822 | ||
|
|
bbdf708d1a | ||
|
|
08195d7e41 | ||
|
|
9ff0dbb7a4 | ||
|
|
6ba97f9161 | ||
|
|
4eca60e7dc | ||
|
|
2af6f8cf78 | ||
|
|
d9a84d24cf | ||
|
|
09ce631e21 | ||
|
|
f93f2a15af | ||
|
|
47839b7701 | ||
|
|
41e99afe54 | ||
|
|
80af04040a | ||
|
|
3caa1e2f71 | ||
|
|
ddbbe30b9e | ||
|
|
802a98e7fc | ||
|
|
bb21841659 | ||
|
|
3f9691baff | ||
|
|
f8db832491 | ||
|
|
c68a92ba80 | ||
|
|
e5cf4645fe | ||
|
|
fad97e12da | ||
|
|
2f6152a580 | ||
|
|
7446da8c9b | ||
|
|
00eecd3a1d | ||
|
|
46a178cf48 | ||
|
|
ddcc28f726 | ||
|
|
04f86aa2ff | ||
|
|
72f0f99ac3 | ||
|
|
c8fe0fe992 | ||
|
|
be5c3b0b90 | ||
|
|
5194101c8b | ||
|
|
0ee27c6ef6 | ||
|
|
46a0aab6b9 | ||
|
|
55fb7abc39 | ||
|
|
407e47b306 | ||
|
|
4e54770f18 | ||
|
|
f9a31f36a0 | ||
|
|
547272e66c | ||
|
|
35e11ffe60 | ||
|
|
52e12e42e5 | ||
|
|
5214d42c07 | ||
|
|
40bbe2539b | ||
|
|
6d1dda0fad | ||
|
|
7a90dab8ff | ||
|
|
395c89cff2 | ||
|
|
aad242d54b | ||
|
|
220ef264fb | ||
|
|
f64dcc0ac2 | ||
|
|
e57abae138 | ||
|
|
fc73accfe5 | ||
|
|
c4d57f0e3d | ||
|
|
eadabfe890 | ||
|
|
02cbe5e1ad | ||
|
|
2645e632a8 | ||
|
|
e14a03a172 | ||
|
|
513e65900c | ||
|
|
4b81cda521 | ||
|
|
6688f40325 | ||
|
|
42dd5caa1b | ||
|
|
308bcae257 | ||
|
|
f2c80cae44 | ||
|
|
aaf744dfab | ||
|
|
7534ffee64 | ||
|
|
ed862c8d08 | ||
|
|
1d977e021d | ||
|
|
dccd61966a | ||
|
|
93aeecefeb | ||
|
|
df63790bb3 | ||
|
|
c743ecbf50 | ||
|
|
29c1df4610 | ||
|
|
40f8591257 | ||
|
|
4d1a754ec6 | ||
|
|
699680807d | ||
|
|
ccaf0874e1 | ||
|
|
1afcb4f29a | ||
|
|
1bb2732056 | ||
|
|
6744ad392d | ||
|
|
1aecc51c70 | ||
|
|
c9571e55f5 | ||
|
|
aba4596ba9 | ||
|
|
bd3cfeae92 | ||
|
|
9ef723eb97 | ||
|
|
7958b1764e | ||
|
|
44f612acbc | ||
|
|
5d7df69116 | ||
|
|
8f06245428 | ||
|
|
0f8368bcf1 | ||
|
|
5d0356a75e | ||
|
|
5f68941241 | ||
|
|
63af4889f6 | ||
|
|
6f84d2fac1 | ||
|
|
049eae661a | ||
|
|
e930d94728 | ||
|
|
819b8eb73d | ||
|
|
a78bf0c34e | ||
|
|
e0059bcc6b | ||
|
|
af0b83a2c3 | ||
|
|
2c033989b6 | ||
|
|
8fbfe55e92 | ||
|
|
740e8130dd | ||
|
|
5bddaf6820 | ||
|
|
c36230e21b | ||
|
|
15d8c08eaa | ||
|
|
2f738d5805 | ||
|
|
e05b687009 | ||
|
|
55a22656b8 | ||
|
|
2db20adc3e | ||
|
|
c7eeb57a32 | ||
|
|
361726b3ae | ||
|
|
c404786b92 | ||
|
|
2ff4eca7bf | ||
|
|
1eca83ff22 | ||
|
|
2575fa8f83 | ||
|
|
b7e86192ee | ||
|
|
078f0f511e | ||
|
|
4963b931d0 | ||
|
|
75fd327222 | ||
|
|
9e71932c2e | ||
|
|
d92583ed33 | ||
|
|
cd27860e55 | ||
|
|
ba875fc04a | ||
|
|
b5a85bd2fe | ||
|
|
4e0df8c2a6 | ||
|
|
37bc30c8d9 | ||
|
|
f6ed7844e1 | ||
|
|
d466390233 | ||
|
|
336473398a | ||
|
|
bb16c81e7b | ||
|
|
f955b46c13 | ||
|
|
b54711252b | ||
|
|
f2710d5b55 | ||
|
|
285fae856d | ||
|
|
111b63bb16 | ||
|
|
767a8b19a9 | ||
|
|
cb28d6cdb7 | ||
|
|
a0d5abef88 | ||
|
|
ebab36e859 | ||
|
|
3988a1e9a8 | ||
|
|
949ef3e1dc | ||
|
|
dd12303276 | ||
|
|
f1379a6574 | ||
|
|
ad58384760 | ||
|
|
0e786f5907 | ||
|
|
e1accce498 | ||
|
|
28db0fdde9 | ||
|
|
584bf9382b | ||
|
|
0168b405a3 | ||
|
|
b5e0d76337 | ||
|
|
c924fba4fa | ||
|
|
8ec43a39af | ||
|
|
9f16445464 | ||
|
|
1a795b04ee | ||
|
|
b862f3e64d | ||
|
|
4e66b5ce8a | ||
|
|
d446950c6a | ||
|
|
e3c77f9b4b | ||
|
|
090ec985f3 | ||
|
|
e63bd490b0 | ||
|
|
badf97d4ba | ||
|
|
ba283e6b6e | ||
|
|
0bdac2c7b3 | ||
|
|
58b211d707 | ||
|
|
068ce237af | ||
|
|
a5e9e5d0df | ||
|
|
e0af8069c1 | ||
|
|
696b05d6e6 | ||
|
|
7e1a699616 | ||
|
|
716d73d982 | ||
|
|
38ac081114 | ||
|
|
5fce101f85 | ||
|
|
c6e064200d | ||
|
|
c52e9085d1 | ||
|
|
d0fb17d70c | ||
|
|
713153b610 | ||
|
|
09d039fba6 | ||
|
|
07f7f28058 | ||
|
|
a2b40f527d | ||
|
|
6d8ffeefd6 | ||
|
|
9ce25bab04 | ||
|
|
cd5105b1db | ||
|
|
ff4abc69c3 | ||
|
|
192f74f0a1 | ||
|
|
be203d9af0 | ||
|
|
f8af299321 | ||
|
|
474b2af1a6 | ||
|
|
cb88cea3c4 | ||
|
|
fc2892fbb0 | ||
|
|
36b25cbd2b | ||
|
|
d18c071849 | ||
|
|
61b629fdad | ||
|
|
29647c8280 | ||
|
|
97b15cb3ae | ||
|
|
f725921dfb | ||
|
|
a4b4d0c0d8 | ||
|
|
f59ade7f80 | ||
|
|
a9b9e7befe | ||
|
|
ead9394a31 | ||
|
|
80129fa9ab | ||
|
|
18796a3c18 | ||
|
|
f632b6d4cb | ||
|
|
7799e14770 | ||
|
|
20aab86e12 | ||
|
|
b7766478a6 | ||
|
|
3d57b7a44d | ||
|
|
51a2b436f4 | ||
|
|
88015081f2 | ||
|
|
20cc1f6550 | ||
|
|
43cca04c33 | ||
|
|
17d944c333 | ||
|
|
6789b5165c | ||
|
|
d631d7e81f | ||
|
|
c6245dc616 | ||
|
|
4b36799ce1 | ||
|
|
d26bb9b4eb | ||
|
|
698404b02f | ||
|
|
d46d7ad947 | ||
|
|
7c6630905d | ||
|
|
129aa587c6 | ||
|
|
cc1c6c94e3 | ||
|
|
41266cbaa0 | ||
|
|
fbfd261da6 | ||
|
|
71602b8ee6 | ||
|
|
14cae239f6 | ||
|
|
2e9e309a0d | ||
|
|
3fba33d5f5 | ||
|
|
77a7162361 | ||
|
|
75efa5174c | ||
|
|
c62afbe77b | ||
|
|
a6f0688f46 | ||
|
|
5762d33e38 | ||
|
|
9c6d1c214f | ||
|
|
a5c865937f | ||
|
|
f48fd84d76 | ||
|
|
a8693a21f8 | ||
|
|
9b630a0664 | ||
|
|
79ac20c161 | ||
|
|
cb74f3e7ad | ||
|
|
c4865e2cb6 | ||
|
|
20d2363fb7 | ||
|
|
64ba5a5b65 | ||
|
|
9913851413 | ||
|
|
e9a8503c6b | ||
|
|
a02d7555c2 | ||
|
|
779b341b61 | ||
|
|
a646cf7923 | ||
|
|
0dea8d97f4 | ||
|
|
97ba9e4d47 | ||
|
|
3f3ebd3b3b | ||
|
|
571669ad6c | ||
|
|
855eb09d58 | ||
|
|
ead3ca14a0 | ||
|
|
34f12c0864 | ||
|
|
28876d6afa | ||
|
|
cea68ebc6f | ||
|
|
a33a955163 | ||
|
|
a3e60c93da | ||
|
|
44c9744d69 | ||
|
|
b69b648d18 | ||
|
|
3ebebac695 | ||
|
|
13d734c8d2 | ||
|
|
c903c5f72b | ||
|
|
b03c7581f2 | ||
|
|
2ed9853bcc | ||
|
|
26e00ffbeb | ||
|
|
b745b6d546 | ||
|
|
e147f2f11e | ||
|
|
14687d003d | ||
|
|
e8bb95ba55 | ||
|
|
a43810533f | ||
|
|
98bbfdf73c | ||
|
|
ee53d816ce | ||
|
|
e176587e96 | ||
|
|
8210be0f17 | ||
|
|
f88a712d01 | ||
|
|
9cf78b974a | ||
|
|
3e1dc801b0 | ||
|
|
cf3c7b3bd6 | ||
|
|
0b7f64cb33 | ||
|
|
ec4542bbe4 | ||
|
|
fc235a3f16 | ||
|
|
4cf8395470 | ||
|
|
fd03d823f2 | ||
|
|
e65fa1aa7b | ||
|
|
3de72917c3 | ||
|
|
b3b2f67d2f | ||
|
|
c2dc25e062 | ||
|
|
ad9c360845 | ||
|
|
a65686e83f | ||
|
|
fe35de6931 | ||
|
|
3f1aea2f53 | ||
|
|
0c542dcd3d | ||
|
|
5483567190 | ||
|
|
d243f1f8fe | ||
|
|
9b137b2e37 | ||
|
|
6ee357d230 | ||
|
|
779e40ed66 | ||
|
|
be3439fef1 | ||
|
|
ed96b4d49d | ||
|
|
5ca8aa7840 | ||
|
|
1eede1bc08 | ||
|
|
cc86461d9b | ||
|
|
29c5ca9091 | ||
|
|
86fbcdc62b | ||
|
|
e82220974e | ||
|
|
46951b8598 | ||
|
|
08faca03b7 | ||
|
|
3217421797 | ||
|
|
7fa22d4c25 | ||
|
|
8671002bd7 | ||
|
|
bc6b40568d | ||
|
|
3888b9dcec | ||
|
|
ae104b5c28 | ||
|
|
5cb7e6c9c3 | ||
|
|
ff31702f74 | ||
|
|
3edd3fe5a4 | ||
|
|
4f3fb95981 | ||
|
|
7c7ab95e2e | ||
|
|
70feea48f8 | ||
|
|
c546c48d0d | ||
|
|
0baf00e1c0 | ||
|
|
788e7fcd89 | ||
|
|
7c45b1d2a3 | ||
|
|
93b66ac141 | ||
|
|
610284dcc3 | ||
|
|
60d8586b6d | ||
|
|
70928dba52 | ||
|
|
7fda9c6723 | ||
|
|
4932f9d077 | ||
|
|
0094128ca6 | ||
|
|
de5178575f | ||
|
|
9eac078c18 | ||
|
|
05c5445fe2 | ||
|
|
f9d8b6f99e | ||
|
|
597a37d66e | ||
|
|
73e4986866 | ||
|
|
91e74c704b | ||
|
|
727bf195d1 | ||
|
|
b13836e9cc | ||
|
|
cf12d72f21 | ||
|
|
5c2bbaca3b | ||
|
|
b717904f9e | ||
|
|
f2c4ab09a8 | ||
|
|
9a657cd4a3 | ||
|
|
308de81221 | ||
|
|
6823109cfb | ||
|
|
a02149cf65 | ||
|
|
7aa4bbf621 | ||
|
|
5afddad0d2 | ||
|
|
0380cf0c76 | ||
|
|
6c2a1e62e0 | ||
|
|
6560628209 | ||
|
|
3cc81376a6 | ||
|
|
8d02e5f680 | ||
|
|
f9e2213afd | ||
|
|
8b362ba3e7 | ||
|
|
eecec8fffa | ||
|
|
a26058d425 | ||
|
|
c14b81f3a9 | ||
|
|
0059a43254 | ||
|
|
7dd3cc354d | ||
|
|
ce34aa0763 | ||
|
|
7a512ad9c3 | ||
|
|
0a56c0e8c1 | ||
|
|
0b71504ee9 | ||
|
|
9479c6451e | ||
|
|
115e83f3aa | ||
|
|
ea526b96dd | ||
|
|
726cf84e19 | ||
|
|
dc8a46363f | ||
|
|
916ca7ab86 | ||
|
|
be036ed58a | ||
|
|
2afdd4544d | ||
|
|
c4e61835d3 | ||
|
|
e15ce69d08 | ||
|
|
d537ed11fd | ||
|
|
dba458d50c | ||
|
|
3e23430926 | ||
|
|
3f507b782c | ||
|
|
2fc3525fdf | ||
|
|
0f3e464202 | ||
|
|
925d7119ec | ||
|
|
f456cd57b9 | ||
|
|
ea58500cef | ||
|
|
4048b200ed | ||
|
|
54211f0f6e | ||
|
|
4b5f465026 | ||
|
|
7efd1151cb | ||
|
|
19dbe52930 | ||
|
|
2a981b7d39 | ||
|
|
d34ebdb431 | ||
|
|
60d0fa2993 | ||
|
|
8545ba733a | ||
|
|
04c8a8c75d | ||
|
|
b7ed44f113 | ||
|
|
46a39716b6 | ||
|
|
e77b0070af | ||
|
|
3c5cf81e32 | ||
|
|
be14dbffef | ||
|
|
b4f6a0f94a | ||
|
|
c15acff39a | ||
|
|
ed0ac6e3f6 | ||
|
|
6cc9c4940c | ||
|
|
0e8b27556d | ||
|
|
162c6a49b5 | ||
|
|
61dbdd80b9 | ||
|
|
8df1bedb1b | ||
|
|
b55e914273 | ||
|
|
1c3aff37de | ||
|
|
4bbc5520b8 | ||
|
|
0731cd6950 | ||
|
|
f88e96599c | ||
|
|
cd7bfa2510 | ||
|
|
ea418b2e18 | ||
|
|
c00d93a897 | ||
|
|
bc361c48a0 | ||
|
|
1f39169be3 | ||
|
|
030833087d | ||
|
|
c38dbcc6b5 | ||
|
|
ba1d548cc8 | ||
|
|
7261d11bb0 | ||
|
|
f38872eab3 | ||
|
|
1939aae70e | ||
|
|
3f85d1dcc1 | ||
|
|
922e2fe23b | ||
|
|
d5a9c1535e | ||
|
|
169eee6792 | ||
|
|
9c398051bb | ||
|
|
1d289787b6 | ||
|
|
b5658f4d9c | ||
|
|
ad58baa13b | ||
|
|
c6fdeeb6bb | ||
|
|
7712455d9a | ||
|
|
a9a5f98406 | ||
|
|
9ac8f64d89 | ||
|
|
0da5cf9163 | ||
|
|
f6a39d75a7 | ||
|
|
25aa9f5b42 | ||
|
|
829b3adac3 | ||
|
|
4847a3a259 | ||
|
|
551541d9c8 | ||
|
|
f996f4c9fb | ||
|
|
ac78ad60f3 | ||
|
|
42d7cf8922 | ||
|
|
e811ba7b4c | ||
|
|
cb464cac4d | ||
|
|
fa409ddc8f | ||
|
|
821226e473 | ||
|
|
0e298bedf6 | ||
|
|
aa76760268 | ||
|
|
8bf87bbfde | ||
|
|
38e889c85c | ||
|
|
d5b737cce8 | ||
|
|
6ba764b5be | ||
|
|
707b857b68 | ||
|
|
f8d609fee5 | ||
|
|
01f797ac05 | ||
|
|
6fa11a853a | ||
|
|
9c78ad708b | ||
|
|
57f8160d6c | ||
|
|
8d80ce444f | ||
|
|
95c3acf67e | ||
|
|
561f7a66dd | ||
|
|
0193688671 | ||
|
|
6d7605a3d0 | ||
|
|
e0171f6e96 | ||
|
|
4ef1c6f2c8 | ||
|
|
f7e2d7c2ec | ||
|
|
3d1be1cd75 | ||
|
|
2d509eb8bd | ||
|
|
6ca73bf670 | ||
|
|
f7802f0111 | ||
|
|
2f3ef235a1 | ||
|
|
1ad22e9a02 | ||
|
|
6d2fb9f782 | ||
|
|
22e5ed44c2 | ||
|
|
9666831818 | ||
|
|
ff8e04f9ba | ||
|
|
52272f4dc5 | ||
|
|
18a66a2ba8 | ||
|
|
8aa9eb19c8 | ||
|
|
62027f1b47 | ||
|
|
41805d572f | ||
|
|
58f768928a | ||
|
|
0074135097 | ||
|
|
8eb7ce8581 | ||
|
|
2ceb3c89ca | ||
|
|
d46e2a69a1 | ||
|
|
20f9454be3 | ||
|
|
8092366897 | ||
|
|
066254b6c8 | ||
|
|
79811bf3e2 | ||
|
|
32bf32e7d5 | ||
|
|
df968ca47c | ||
|
|
cce7a5f15e | ||
|
|
288043c13b | ||
|
|
78ae4ebfaa | ||
|
|
cf700a0084 | ||
|
|
60a25f6e71 | ||
|
|
3eff836b2e | ||
|
|
2b9fe764d5 | ||
|
|
030e3b2dab | ||
|
|
5079f6bbff | ||
|
|
afceb9d24e | ||
|
|
a2656a20bc | ||
|
|
359d444343 | ||
|
|
d510154ba2 | ||
|
|
1c901b82dc | ||
|
|
ea3672df4e | ||
|
|
72d0b3c913 | ||
|
|
51a2d8dfd8 | ||
|
|
bc25380950 | ||
|
|
ae1e3bf73c | ||
|
|
9673a2726c | ||
|
|
02524397c1 | ||
|
|
5e5dde1a67 | ||
|
|
0f8def4ca4 | ||
|
|
182ec04e24 | ||
|
|
ebae435398 | ||
|
|
52657945d8 | ||
|
|
12166f8a47 | ||
|
|
c5f1dd8615 | ||
|
|
10e67e3c1d | ||
|
|
4e8ceaae86 | ||
|
|
73d4eaafbb | ||
|
|
cf00179964 | ||
|
|
edda0c60b3 | ||
|
|
f2eb6b165a | ||
|
|
4933c216b2 | ||
|
|
0655def57f | ||
|
|
6eafff2450 | ||
|
|
0bb772c575 | ||
|
|
b261693095 | ||
|
|
129db63e30 | ||
|
|
1759d89d8a | ||
|
|
0540b17fb9 | ||
|
|
8893dda350 | ||
|
|
b14689d59b | ||
|
|
1ca844af98 | ||
|
|
3059747c35 | ||
|
|
bbbb3633a7 | ||
|
|
df6c2a432f | ||
|
|
d0acfc2652 | ||
|
|
711cda6aed | ||
|
|
0c738d84af | ||
|
|
be1e1dc441 | ||
|
|
2a305d8e16 | ||
|
|
15b6ab77ea | ||
|
|
6199822783 | ||
|
|
0b72b2940a | ||
|
|
d4ce3f19c3 | ||
|
|
824e86a82f | ||
|
|
2a5c045c3d | ||
|
|
f7c65a4b88 | ||
|
|
a8956f2f56 | ||
|
|
91c9f84a01 | ||
|
|
2be89bc6f2 | ||
|
|
d6c447a445 | ||
|
|
a60586eaad | ||
|
|
d77356837a | ||
|
|
d6842301dd | ||
|
|
19b3c5be26 | ||
|
|
5fb5a89f02 | ||
|
|
9367e7b9af | ||
|
|
6673cadfa2 | ||
|
|
b485051b65 | ||
|
|
9a01ccc07f | ||
|
|
1b8deaf354 | ||
|
|
c7d0232bb1 | ||
|
|
79e5f2be13 | ||
|
|
9ab181eb9c | ||
|
|
3cc6021e03 | ||
|
|
375389fa1e | ||
|
|
777303f130 | ||
|
|
6015f99d98 | ||
|
|
78fc17c661 | ||
|
|
d42addf746 | ||
|
|
f570eb76b3 | ||
|
|
cc3f5962b8 | ||
|
|
6ab3d1daa3 | ||
|
|
b088b70f82 | ||
|
|
fbbb6bbc00 | ||
|
|
5c36342958 | ||
|
|
f1a0cacc5a | ||
|
|
1d2a0856b4 | ||
|
|
7fb50d9a3e | ||
|
|
919b5b5a7d | ||
|
|
1e35b26826 | ||
|
|
27b0b5824a | ||
|
|
1d72d22bc5 | ||
|
|
e0c9ed44f9 | ||
|
|
411f4da340 | ||
|
|
4fac84098e | ||
|
|
21b2063a6f | ||
|
|
917c191650 | ||
|
|
2bfce03d29 | ||
|
|
1cb8167be0 | ||
|
|
40d33cc64d | ||
|
|
95433e9639 | ||
|
|
bbe1a09e7e | ||
|
|
dce2366b3a | ||
|
|
bab7ba22cf | ||
|
|
d6a91057ae | ||
|
|
c6e9065498 | ||
|
|
22fda21eae | ||
|
|
103a520aa6 | ||
|
|
86531a51a7 | ||
|
|
2b7e4d645f | ||
|
|
a5f63180fc | ||
|
|
934d4e04b5 | ||
|
|
1b8547059a | ||
|
|
91279a0f28 | ||
|
|
31ba3144c8 | ||
|
|
0bf34725e3 | ||
|
|
91749ebb2b | ||
|
|
4ba3dd66ad | ||
|
|
d40696f7f3 | ||
|
|
4a401a9e83 | ||
|
|
6a2a837ede | ||
|
|
eca08a281c | ||
|
|
9fd8f76fa0 | ||
|
|
50de930730 | ||
|
|
da1097095c | ||
|
|
ec7d302a6c | ||
|
|
8cc7ebffa9 | ||
|
|
de4d14843f | ||
|
|
18605795a7 | ||
|
|
da2c8d9076 | ||
|
|
3120f8adb6 | ||
|
|
2dcc16169b | ||
|
|
a8efd8c398 | ||
|
|
bb40f4aff4 | ||
|
|
66c7ac4d24 | ||
|
|
7f12919fea | ||
|
|
55e0c6a0a1 | ||
|
|
20f306602b | ||
|
|
70735d8d79 | ||
|
|
165e6805ab | ||
|
|
2a0c35646c | ||
|
|
28710e0449 | ||
|
|
c5587b60b2 | ||
|
|
bb95c39356 | ||
|
|
20a43409c6 | ||
|
|
4699f7ca0b | ||
|
|
bc7586b3f4 | ||
|
|
8d3d45ea1a | ||
|
|
21ba1d3761 | ||
|
|
e79584bb9e | ||
|
|
bca7819247 | ||
|
|
0ecabae2c3 | ||
|
|
598c04eea2 | ||
|
|
faec23f6bd | ||
|
|
896dad9224 | ||
|
|
680612cf09 | ||
|
|
3fbd4bb15f | ||
|
|
cb9055072d | ||
|
|
0fc9b555f1 | ||
|
|
6ed58628f5 | ||
|
|
efff149988 | ||
|
|
b02d4092f1 | ||
|
|
9dc7ea7c62 | ||
|
|
546a3cdd50 | ||
|
|
e8c5d15690 | ||
|
|
e63cba05b2 | ||
|
|
e8fe1dc415 | ||
|
|
9cf08fc780 | ||
|
|
b712b3a979 | ||
|
|
a931b2eece | ||
|
|
2e74beebbf | ||
|
|
db510a9558 | ||
|
|
222198acf3 | ||
|
|
bc4d5df94e | ||
|
|
9d35b5deac | ||
|
|
59c68d240c | ||
|
|
930a41b845 | ||
|
|
323f0d187e | ||
|
|
0078705bbe | ||
|
|
3b3ca4afdc | ||
|
|
1d6b94b458 | ||
|
|
30c038c3c3 | ||
|
|
05e002cd42 | ||
|
|
7f6ed73145 | ||
|
|
0c4968ec51 | ||
|
|
ff69e86559 | ||
|
|
98f79404d6 | ||
|
|
eec438a614 | ||
|
|
c88801065f | ||
|
|
833022b745 | ||
|
|
d1b820e7e3 | ||
|
|
4373918a2f | ||
|
|
6e96b4ba33 | ||
|
|
2d326bfc48 | ||
|
|
a6988b2a79 | ||
|
|
8b93e1a780 | ||
|
|
4e318c1abc | ||
|
|
3cb6840d2d | ||
|
|
6ed5a65064 | ||
|
|
b977c95be4 | ||
|
|
feb8811f37 | ||
|
|
0de82a70a6 | ||
|
|
cc3a8918f0 | ||
|
|
63ef2badd6 | ||
|
|
e98080b8bb | ||
|
|
bed5b72cbe | ||
|
|
7ab2c0e4a5 | ||
|
|
7a6ee1d729 | ||
|
|
d9596334c3 | ||
|
|
16676ae726 | ||
|
|
fd3702f973 | ||
|
|
d674d23b45 | ||
|
|
5b8835f46b | ||
|
|
ddb2cf3b8b | ||
|
|
f924862e89 | ||
|
|
061d497df0 | ||
|
|
3a222336d7 | ||
|
|
78300d018a | ||
|
|
e95676f65f | ||
|
|
c8fe69c956 | ||
|
|
fe4b661fe7 | ||
|
|
5344028c40 | ||
|
|
e591e3622b | ||
|
|
d8fc5fee0a | ||
|
|
eeb73b3670 | ||
|
|
2f2e524bc6 | ||
|
|
6b0198c2d7 | ||
|
|
2a64b75893 | ||
|
|
034e172033 | ||
|
|
1faeb45063 | ||
|
|
fa84496423 | ||
|
|
a3d47ffc81 | ||
|
|
d841c86a6e | ||
|
|
3b4e4b785d | ||
|
|
7ba6b617a1 | ||
|
|
100f732e20 | ||
|
|
cb28aeeacc | ||
|
|
7994b31de4 | ||
|
|
6dcf3238f6 | ||
|
|
f6320e7050 | ||
|
|
597bb80d18 | ||
|
|
9775f3a030 | ||
|
|
a080d00352 | ||
|
|
5fb0a9d53b | ||
|
|
40d82675bd | ||
|
|
f851e1f90e | ||
|
|
73d775c8b4 | ||
|
|
97f3e9404a | ||
|
|
83da131e99 | ||
|
|
7973aef7b7 | ||
|
|
9a3bdcc20b | ||
|
|
aa91c608f4 | ||
|
|
3d260d41b3 | ||
|
|
2458325c09 | ||
|
|
ab68a9d1d3 | ||
|
|
93b5b08bed | ||
|
|
be4369936b | ||
|
|
1a7415a6ab | ||
|
|
c15db71f9e | ||
|
|
74cb1c877c | ||
|
|
a949ab6935 | ||
|
|
f0fd7099c0 | ||
|
|
e0009f9f40 | ||
|
|
14d2576924 | ||
|
|
c386d11765 | ||
|
|
f12bc10917 | ||
|
|
99d18abf59 | ||
|
|
bc29c84610 | ||
|
|
e78e65ef22 | ||
|
|
f9103531c4 | ||
|
|
2ea87490f4 | ||
|
|
5fb5551c36 | ||
|
|
b9b0326d15 | ||
|
|
97f2f16fd6 | ||
|
|
fc1514db04 | ||
|
|
7fb0598b50 | ||
|
|
fd375ca55b | ||
|
|
0f70959d8e | ||
|
|
8cb6fcad7e | ||
|
|
20d898d182 | ||
|
|
10c9a7d4b7 | ||
|
|
441e42c276 | ||
|
|
fe2dbfb6cb | ||
|
|
032ac800aa | ||
|
|
5e86eeacfb | ||
|
|
75b7d33fb7 | ||
|
|
a6e532442b | ||
|
|
a123a12f59 | ||
|
|
f261251a9b | ||
|
|
a0e1154bfb | ||
|
|
e261278a5c | ||
|
|
dbb550e6db | ||
|
|
27a9b0e7b1 | ||
|
|
8a00758cf5 | ||
|
|
15e154c09d | ||
|
|
52d0c9a057 | ||
|
|
4593471ad5 | ||
|
|
a3288d4284 | ||
|
|
22f0da4da6 | ||
|
|
baa977a3ed | ||
|
|
b4b2491015 | ||
|
|
902ed3c694 | ||
|
|
4a9205b341 |
28
.gitignore
vendored
28
.gitignore
vendored
@@ -1,6 +1,24 @@
|
||||
*.swp
|
||||
.deps
|
||||
.vimrc
|
||||
*.o
|
||||
Makefile
|
||||
chronyc
|
||||
chronyd
|
||||
version.h
|
||||
*.swp
|
||||
*.dSYM
|
||||
*.DS_Store
|
||||
tags
|
||||
/RELEASES
|
||||
/Makefile
|
||||
/chrony.conf.5
|
||||
/chrony.info
|
||||
/chrony.html
|
||||
/chrony.texi
|
||||
/chrony.txt
|
||||
/chronyc
|
||||
/chronyc.1
|
||||
/chronyd
|
||||
/chronyd.8
|
||||
/config.h
|
||||
/config.log
|
||||
/getdate.c
|
||||
/version.h
|
||||
/test/simulation/clknetsim
|
||||
/test/simulation/tmp
|
||||
|
||||
93
INSTALL
93
INSTALL
@@ -1,93 +0,0 @@
|
||||
The software is distributed as source code which has to be compiled.
|
||||
|
||||
PARTS OF THE SOFTWARE ARE HIGHLY SYSTEM-SPECIFIC AND NON-PORTABLE.
|
||||
UNLESS YOU ARE RUNNING A SUPPORTED SYSTEM, BE PREPARED FOR SOME
|
||||
PROGRAMMING!
|
||||
|
||||
After unpacking the source code, change directory into it, and type
|
||||
|
||||
./configure
|
||||
|
||||
This is a shell script that automatically determines the system type.
|
||||
There is a single optional parameter, --prefix which indicates the
|
||||
directory tree where the software should be installed. For example,
|
||||
|
||||
./configure --prefix=/opt/free
|
||||
|
||||
will install the chronyd daemon into /opt/free/sbin and the chronyc
|
||||
control program into /opt/free/bin. The default value for the prefix
|
||||
is /usr/local.
|
||||
|
||||
The configure script assumes you want to use gcc as your compiler.
|
||||
If you want to use a different compiler, you can configure this way:
|
||||
|
||||
CC=cc CFLAGS=-O ./configure --prefix=/opt/free
|
||||
|
||||
for Bourne-family shells, or
|
||||
|
||||
setenv CC cc
|
||||
setenv CFLAGS -O
|
||||
./configure --prefix=/opt/free
|
||||
|
||||
for C-family shells.
|
||||
|
||||
If the software cannot (yet) be built on your system, an error message
|
||||
will be shown. Otherwise, `Makefile' will be generated.
|
||||
|
||||
If editline or readline library is available, chronyc will be built
|
||||
with line editing support. If you don't want this, specify the
|
||||
--disable-readline flag to configure. Please refer to the chrony.txt
|
||||
file for more information.
|
||||
|
||||
If a `timepps.h' header is available, chronyd will be built with PPS
|
||||
API reference clock driver. If the header is installed in a location
|
||||
that isn't normally searched by the compiler, you can add it to the
|
||||
searched locations by setting CPPFLAGS variable to -I/path/to/timepps.
|
||||
|
||||
Now type
|
||||
|
||||
make
|
||||
|
||||
to build the programs.
|
||||
|
||||
If you want to build the manual in plain text, HTML and info versions, type
|
||||
|
||||
make docs
|
||||
|
||||
Once the programs have been successfully compiled, they need to be
|
||||
installed in their target locations. This step normally needs to be
|
||||
performed by the superuser, and requires the following command to be
|
||||
entered.
|
||||
|
||||
make install
|
||||
|
||||
This will install the binaries, plain text manual and manpages.
|
||||
|
||||
To install the HTML and info versions of the manual as well, enter the command
|
||||
|
||||
make install-docs
|
||||
|
||||
If you want chrony to appear in the top level info directory listing, you need
|
||||
to run the install-info command manually after this step. install-info takes 2
|
||||
arguments. The first is the path to the chrony.info file you have just
|
||||
installed. This will be the argument you gave to --prefix when you configured
|
||||
(/usr/local by default), with /share/info/chrony.info on the end. The second
|
||||
argument is the location of the file called 'dir'. This will typically be
|
||||
/usr/share/info/dir. So the typical command line would be
|
||||
|
||||
install-info /usr/local/share/info/chrony.info /usr/share/info/dir
|
||||
|
||||
Now that the software is successfully installed, the next step is to
|
||||
set up a configuration file. The contents of this depend on the
|
||||
network environment in which the computer operates. Typical scenarios
|
||||
are described in the manual. The simplest case is for a computer with
|
||||
a permanent Internet connection - suppose you want to use the NTP
|
||||
server ntp1.foobar.com as your time reference. You would create an
|
||||
/etc/chrony.conf file containing
|
||||
|
||||
server ntp1.foobar.com
|
||||
driftfile /etc/chrony.drift
|
||||
|
||||
and then run /usr/local/sbin/chronyd.
|
||||
|
||||
|
||||
102
Makefile.in
102
Makefile.in
@@ -1,9 +1,5 @@
|
||||
##################################################
|
||||
#
|
||||
# $Header: /cvs/src/chrony/Makefile.in,v 1.48 2003/09/19 22:48:26 richard Exp $
|
||||
#
|
||||
# =======================================================================
|
||||
#
|
||||
# chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
#
|
||||
# Copyright (C) Richard P. Curnow 1997-2003
|
||||
@@ -31,32 +27,27 @@ SBINDIR=@SBINDIR@
|
||||
MANDIR=@MANDIR@
|
||||
INFODIR=@INFODIR@
|
||||
DOCDIR=@DOCDIR@
|
||||
LOCALSTATEDIR=@LOCALSTATEDIR@
|
||||
CHRONYVARDIR=@CHRONYVARDIR@
|
||||
|
||||
CC = @CC@
|
||||
CCWARNFLAGS = @CCWARNFLAGS@
|
||||
OPTFLAGS = @CFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@ @SYSDEFS@ @EXTRA_DEFS@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
|
||||
DESTDIR=
|
||||
|
||||
OBJS = util.o sched.o regress.o local.o \
|
||||
sys.o main.o ntp_io.o ntp_core.o ntp_sources.o \
|
||||
sources.o sourcestats.o reference.o \
|
||||
logging.o conf.o cmdmon.o md5.o keys.o \
|
||||
nameserv.o acquire.o manual.o addrfilt.o \
|
||||
cmdparse.o mkdirpp.o rtc.o pktlength.o clientlog.o \
|
||||
broadcast.o refclock.o refclock_shm.o refclock_sock.o \
|
||||
refclock_pps.o
|
||||
HASH_OBJ = @HASH_OBJ@
|
||||
|
||||
OBJS = array.o cmdparse.o conf.o local.o logging.o main.o memory.o \
|
||||
reference.o regress.o rtc.o sched.o sources.o sourcestats.o stubs.o \
|
||||
sys.o smooth.o tempcomp.o util.o $(HASH_OBJ)
|
||||
|
||||
EXTRA_OBJS=@EXTRA_OBJECTS@
|
||||
|
||||
CLI_OBJS = client.o md5.o nameserv.o getdate.o cmdparse.o \
|
||||
pktlength.o util.o
|
||||
CLI_OBJS = array.o client.o cmdparse.o getdate.o memory.o nameserv.o \
|
||||
pktlength.o util.o $(HASH_OBJ)
|
||||
|
||||
SRCS = $(patsubst %.o,%.c,$(OBJS))
|
||||
EXTRA_SRCS = $(patsubst %.o,%.c,$(EXTRA_OBJS))
|
||||
|
||||
CLI_SRCS = $(patsubst %.o,%.c,$(CLI_OBJS))
|
||||
ALL_OBJS = $(OBJS) $(EXTRA_OBJS) $(CLI_OBJS)
|
||||
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBS = @LIBS@
|
||||
@@ -64,38 +55,37 @@ LIBS = @LIBS@
|
||||
EXTRA_LIBS=@EXTRA_LIBS@
|
||||
EXTRA_CLI_LIBS=@EXTRA_CLI_LIBS@
|
||||
|
||||
CFLAGS = $(CCWARNFLAGS) $(OPTFLAGS)
|
||||
|
||||
# Until we have a main procedure we can link, just build object files
|
||||
# to test compilation
|
||||
|
||||
all : chronyd chronyc
|
||||
|
||||
chronyd : $(OBJS) $(EXTRA_OBJS)
|
||||
$(CC) $(OPTFLAGS) -o chronyd $(OBJS) $(EXTRA_OBJS) $(LDFLAGS) $(LIBS) $(EXTRA_LIBS)
|
||||
$(CC) $(CFLAGS) -o chronyd $(OBJS) $(EXTRA_OBJS) $(LDFLAGS) $(LIBS) $(EXTRA_LIBS)
|
||||
|
||||
chronyc : $(CLI_OBJS)
|
||||
$(CC) $(OPTFLAGS) -o chronyc $(CLI_OBJS) $(LDFLAGS) @READLINE_LINK@ $(LIBS) $(EXTRA_CLI_LIBS)
|
||||
|
||||
conf.o : conf.c
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -DDEFAULT_CONF_DIR=\"$(SYSCONFDIR)\" -c $<
|
||||
$(CC) $(CFLAGS) -o chronyc $(CLI_OBJS) $(LDFLAGS) $(LIBS) $(EXTRA_CLI_LIBS)
|
||||
|
||||
client.o : client.c
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) @READLINE_COMPILE@ -c $<
|
||||
|
||||
.depend :
|
||||
gcc -MM $(SRCS) $(EXTRA_SRCS) > .depend
|
||||
$(HASH_OBJ) : $(patsubst %.o,%.c,$(HASH_OBJ))
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) @HASH_COMPILE@ -c $<
|
||||
|
||||
distclean :
|
||||
-rm -f *.o *.s chronyc chronyd core options.h Makefile *~
|
||||
distclean : clean
|
||||
-rm -f .DS_Store
|
||||
-rm -f Makefile
|
||||
-rm -f chrony.conf.5 chrony.texi chronyc.1 chronyd.8
|
||||
|
||||
clean :
|
||||
-rm -f *.o *.s chronyc chronyd core *~
|
||||
-rm -f *.o *.s chronyc chronyd core *~ chrony.info chrony.html chrony.txt
|
||||
-rm -rf .deps
|
||||
-rm -rf *.dSYM
|
||||
|
||||
version.h : version.txt
|
||||
./mkversion
|
||||
getdate.c : getdate.y
|
||||
bison -o getdate.c getdate.y
|
||||
|
||||
getdate.c : ;
|
||||
# This can be used to force regeneration of getdate.c
|
||||
getdate :
|
||||
bison -o getdate.c getdate.y
|
||||
|
||||
@@ -103,27 +93,19 @@ getdate :
|
||||
# seem to vary between systems.
|
||||
|
||||
install: chronyd chronyc
|
||||
[ -d $(DESTDIR)$(SYSCONFDIR) ] || mkdir -p $(DESTDIR)$(SYSCONFDIR)
|
||||
[ -d $(DESTDIR)$(SBINDIR) ] || mkdir -p $(DESTDIR)$(SBINDIR)
|
||||
[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
|
||||
[ -d $(DESTDIR)$(DOCDIR) ] || mkdir -p $(DESTDIR)$(DOCDIR)
|
||||
[ -d $(DESTDIR)$(MANDIR)/man1 ] || mkdir -p $(DESTDIR)$(MANDIR)/man1
|
||||
[ -d $(DESTDIR)$(MANDIR)/man5 ] || mkdir -p $(DESTDIR)$(MANDIR)/man5
|
||||
[ -d $(DESTDIR)$(MANDIR)/man8 ] || mkdir -p $(DESTDIR)$(MANDIR)/man8
|
||||
[ -d $(DESTDIR)$(DOCDIR) ] || mkdir -p $(DESTDIR)$(DOCDIR)
|
||||
[ -d $(DESTDIR)$(CHRONYVARDIR) ] || mkdir -p $(DESTDIR)$(CHRONYVARDIR)
|
||||
if [ -f $(DESTDIR)$(SBINDIR)/chronyd ]; then rm -f $(DESTDIR)$(SBINDIR)/chronyd ; fi
|
||||
if [ -f $(DESTDIR)$(BINDIR)/chronyc ]; then rm -f $(DESTDIR)$(BINDIR)/chronyc ; fi
|
||||
cp chronyd $(DESTDIR)$(SBINDIR)/chronyd
|
||||
chmod 755 $(DESTDIR)$(SBINDIR)/chronyd
|
||||
cp chronyc $(DESTDIR)$(BINDIR)/chronyc
|
||||
chmod 755 $(DESTDIR)$(BINDIR)/chronyc
|
||||
cp chrony.txt $(DESTDIR)$(DOCDIR)/chrony.txt
|
||||
chmod 644 $(DESTDIR)$(DOCDIR)/chrony.txt
|
||||
cp COPYING $(DESTDIR)$(DOCDIR)/COPYING
|
||||
chmod 644 $(DESTDIR)$(DOCDIR)/COPYING
|
||||
cp README $(DESTDIR)$(DOCDIR)/README
|
||||
chmod 644 $(DESTDIR)$(DOCDIR)/README
|
||||
cp chrony.1 $(DESTDIR)$(MANDIR)/man1
|
||||
chmod 644 $(DESTDIR)$(MANDIR)/man1/chrony.1
|
||||
cp chronyc.1 $(DESTDIR)$(MANDIR)/man1
|
||||
chmod 644 $(DESTDIR)$(MANDIR)/man1/chronyc.1
|
||||
cp chronyd.8 $(DESTDIR)$(MANDIR)/man8
|
||||
@@ -137,10 +119,8 @@ install: chronyd chronyc
|
||||
%.s : %.c
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -S $<
|
||||
|
||||
main.o logging.o client.o : version.h
|
||||
|
||||
# makeinfo v4 required to generate plain text and html
|
||||
MAKEINFO:=makeinfo
|
||||
check : chronyd chronyc
|
||||
cd test/simulation && ./run
|
||||
|
||||
install-docs : docs
|
||||
[ -d $(DESTDIR)$(DOCDIR) ] || mkdir -p $(DESTDIR)$(DOCDIR)
|
||||
@@ -155,15 +135,25 @@ install-docs : docs
|
||||
docs : chrony.txt chrony.html chrony.info
|
||||
|
||||
chrony.txt : chrony.texi
|
||||
$(MAKEINFO) --no-headers --number-sections -o chrony.txt chrony.texi
|
||||
makeinfo --no-headers --number-sections -o chrony.txt chrony.texi
|
||||
|
||||
chrony.html : chrony.texi
|
||||
$(MAKEINFO) --no-split --html --number-sections -o chrony.html chrony.texi
|
||||
command -v texi2html > /dev/null 2>&1 && texi2html chrony.texi || \
|
||||
makeinfo --no-split --html --number-sections -o chrony.html chrony.texi
|
||||
|
||||
chrony.info : chrony.texi
|
||||
$(MAKEINFO) chrony.texi
|
||||
makeinfo chrony.texi
|
||||
|
||||
# This is only relevant if you're maintaining the website!
|
||||
faq.php : faq.txt faqgen.pl
|
||||
perl faqgen.pl < faq.txt > faq.php
|
||||
Makefile : Makefile.in configure
|
||||
@echo
|
||||
@echo Makefile needs to be regenerated, run ./configure
|
||||
@echo
|
||||
@exit 1
|
||||
|
||||
.deps:
|
||||
@mkdir .deps
|
||||
|
||||
.deps/%.d: %.c | .deps
|
||||
@$(CC) -MM $(CPPFLAGS) -MT '$(<:%.c=%.o) $@' $< -o $@
|
||||
|
||||
-include $(ALL_OBJS:%.o=.deps/%.d)
|
||||
|
||||
305
NEWS
305
NEWS
@@ -1,6 +1,307 @@
|
||||
New in version 2.2
|
||||
==================
|
||||
|
||||
Enhancements
|
||||
------------
|
||||
* Add support for configuration and monitoring over Unix domain socket
|
||||
(accessible by root or chrony user when root privileges are dropped)
|
||||
* Add support for system call filtering with seccomp on Linux (experimental)
|
||||
* Add support for dropping root privileges on NetBSD
|
||||
* Control frequency of system clock on FreeBSD, NetBSD, Solaris
|
||||
* Add system leap second handling mode on FreeBSD, NetBSD, Solaris
|
||||
* Add dynamic drift removal on Mac OS X
|
||||
* Add support for setting real-time priority on Mac OS X
|
||||
* Add maxdistance directive to limit source selection by root distance
|
||||
(3 seconds by default)
|
||||
* Add refresh command to get new addresses of NTP sources
|
||||
* Allow wildcard patterns in include directive
|
||||
* Restore time from driftfile with -s option if later than RTC time
|
||||
* Add configure option to set default hwclockfile
|
||||
* Add -d option to chronyc to enable debug messages
|
||||
* Allow multiple addresses to be specified for chronyc with -h option
|
||||
and reconnect when no valid reply is received
|
||||
* Make check interval in waitsync command configurable
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
* Fix building on NetBSD, Solaris
|
||||
* Restore time from driftfile with -s option if reading RTC failed
|
||||
|
||||
Removed features
|
||||
----------------
|
||||
* Drop support for authentication with command key (run-time configuration
|
||||
is now allowed only for local users that can access the Unix domain socket)
|
||||
|
||||
New in version 2.1.1
|
||||
====================
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
* Fix clock stepping by integer number of seconds on Linux
|
||||
|
||||
New in version 2.1
|
||||
==================
|
||||
|
||||
Enhancements
|
||||
------------
|
||||
* Add support for Mac OS X
|
||||
* Try to replace unreachable and falseticker servers/peers specified
|
||||
by name like pool sources
|
||||
* Add leaponly option to smoothtime directive to allow synchronised
|
||||
leap smear between multiple servers
|
||||
* Use specific reference ID when smoothing served time
|
||||
* Add smoothing command to report time smoothing status
|
||||
* Add smoothtime command to activate or reset time smoothing
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
* Fix crash in source selection with preferred sources
|
||||
* Fix resetting of time smoothing
|
||||
* Include packet precision in peer dispersion
|
||||
* Fix crash in chronyc on invalid command syntax
|
||||
|
||||
New in version 2.0
|
||||
==================
|
||||
|
||||
Enhancements
|
||||
------------
|
||||
* Update to NTP version 4 (RFC 5905)
|
||||
* Add pool directive to specify pool of NTP servers
|
||||
* Add leapsecmode directive to select how to correct clock for leap second
|
||||
* Add smoothtime directive to smooth served time and enable leap smear
|
||||
* Add minsources directive to set required number of selectable sources
|
||||
* Add minsamples and maxsamples options for all sources
|
||||
* Add tempcomp configuration with list of points
|
||||
* Allow unlimited number of NTP sources, refclocks and keys
|
||||
* Allow unreachable sources to remain selected
|
||||
* Improve source selection
|
||||
* Handle offline sources as unreachable
|
||||
* Open NTP server port only when necessary (client access is allowed by
|
||||
allow directive/command or peer/broadcast is configured)
|
||||
* Change default bindcmdaddress to loopback address
|
||||
* Change default maxdelay to 3 seconds
|
||||
* Change default stratumweight to 0.001
|
||||
* Update adjtimex synchronisation status
|
||||
* Use system headers for adjtimex
|
||||
* Check for memory allocation errors
|
||||
* Reduce memory usage
|
||||
* Add configure options to compile without NTP, cmdmon, refclock support
|
||||
* Extend makestep command to set automatic clock stepping
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
* Add sanity checks for time and frequency offset
|
||||
* Don't report synchronised status during leap second
|
||||
* Don't combine reference clocks with close NTP sources
|
||||
* Fix accepting requests from configured sources
|
||||
* Fix initial fallback drift setting
|
||||
|
||||
New in version 1.31.1
|
||||
=====================
|
||||
|
||||
Security fixes
|
||||
--------------
|
||||
* Protect authenticated symmetric NTP associations against DoS attacks
|
||||
(CVE-2015-1853)
|
||||
* Fix access configuration with subnet size indivisible by 4 (CVE-2015-1821)
|
||||
* Fix initialization of reply slots for authenticated commands (CVE-2015-1822)
|
||||
|
||||
New in version 1.31
|
||||
===================
|
||||
|
||||
Enhancements
|
||||
------------
|
||||
* Support operation in other NTP eras (next era begins in 2036),
|
||||
NTP time is mapped to [-50, +86] years around build date by default
|
||||
* Restore time from driftfile with -s when RTC is missing/unsupported
|
||||
* Close connected client sockets when not waiting for reply
|
||||
* Use one client socket with random port when acquisitionport is 0
|
||||
* Use NTP packets instead of UDP echo for presend
|
||||
* Don't adjust polling interval when sending fails
|
||||
* Allow binding to addresses that don't exist yet
|
||||
* Ignore measurements around leap second
|
||||
* Improve detection of unexpected time jumps
|
||||
* Include example of logrotate configuration, systemd services and
|
||||
NetworkManager dispatcher script
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
* Reconnect client sockets for each request to follow changes
|
||||
in network configuration automatically
|
||||
* Restart timer when polling interval is changed on reset
|
||||
|
||||
New in version 1.30
|
||||
===================
|
||||
|
||||
Enhancements
|
||||
------------
|
||||
* Add asynchronous name resolving with POSIX threads
|
||||
* Add PTP hardware clock (PHC) refclock driver
|
||||
* Add new generic clock driver to slew by adjusting frequency only
|
||||
(without kernel PLL or adjtime) and use it on Linux
|
||||
* Add rtcautotrim directive to trim RTC automatically
|
||||
* Add hwclockfile directive to share RTC LOCAL/UTC setting with hwclock
|
||||
* Add maxslewrate directive to set maximum allowed slew rate
|
||||
* Add maxdispersion option for refclocks
|
||||
* Add -q/-Q options to set clock/print offset once and exit
|
||||
* Allow directives to be specified on chronyd command line
|
||||
* Replace frequency scaling in Linux driver with retaining of tick
|
||||
* Try to detect unexpected forward time jumps and reset state
|
||||
* Exit with non-zero code when maxchange limit is reached
|
||||
* Improve makestep to not start and stop slew unnecessarily
|
||||
* Change default corrtimeratio to 3.0 to improve frequency accuracy
|
||||
* Announce leap second only on last day of June and December
|
||||
* Use separate connected client sockets for each NTP server
|
||||
* Remove separate NTP implementation used for initstepslew
|
||||
* Limit maximum minpoll set by KoD RATE to default maxpoll
|
||||
* Don't send NTP requests with unknown key
|
||||
* Print warning when source is added with unknown key
|
||||
* Take leap second in PPS refclock from locked source
|
||||
* Make reading of RTC for initial trim more reliable
|
||||
* Don't create cmdmon sockets when cmdport is 0
|
||||
* Add configure option to set default user to drop root privileges
|
||||
* Add configure option to compile with debug messages
|
||||
* Print debug messages when -d is used more than once
|
||||
* Change format of messages written to terminal with -d
|
||||
* Write fatal messages also to stderr with -n
|
||||
* Use IP_RECVERR socket option in chronyc to not wait unnecessarily
|
||||
* Shorten default chronyc timeout for localhost
|
||||
* Change default hostname in chronyc from localhost to 127.0.0.1
|
||||
* Print error message on invalid syntax with all chronyc commands
|
||||
* Include simulation test suite using clknetsim
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
* Fix crash when selecting with multiple preferred sources
|
||||
* Fix frequency calculation with large frequency offsets
|
||||
* Fix code writing drift and RTC files to compile correctly
|
||||
* Fix -4/-6 options in chronyc to not reset hostname set by -h
|
||||
* Fix refclock sample validation with sub-second polling interval
|
||||
* Set stratum correctly with non-PPS SOCK refclock and local stratum
|
||||
* Modify dispersion accounting in refclocks to prevent PPS getting
|
||||
stuck with large dispersion and not accepting new samples
|
||||
|
||||
New in version 1.29.1
|
||||
=====================
|
||||
|
||||
Security fixes
|
||||
--------------
|
||||
* Modify chronyc protocol to prevent amplification attacks (CVE-2014-0021)
|
||||
(incompatible with previous protocol version, chronyc supports both)
|
||||
|
||||
New in version 1.29
|
||||
===================
|
||||
|
||||
Security fixes
|
||||
--------------
|
||||
* Fix crash when processing crafted commands (CVE-2012-4502)
|
||||
(possible with IP addresses allowed by cmdallow and localhost)
|
||||
* Don't send uninitialized data in SUBNETS_ACCESSED and CLIENT_ACCESSES
|
||||
replies (CVE-2012-4503) (not used by chronyc)
|
||||
|
||||
Other changes
|
||||
-------------
|
||||
* Drop support for SUBNETS_ACCESSED and CLIENT_ACCESSES commands
|
||||
|
||||
New in version 1.28
|
||||
===================
|
||||
|
||||
* Combine sources to improve accuracy
|
||||
* Make config and command parser strict
|
||||
* Add -a option to chronyc to authenticate automatically
|
||||
* Add -R option to ignore initstepslew and makestep directives
|
||||
* Add generatecommandkey, minsamples, maxsamples and user directives
|
||||
* Improve compatibility with NTPv1 and NTPv2 clients
|
||||
* Create sockets only in selected family with -4/-6 option
|
||||
* Treat address bind errors as non-fatal
|
||||
* Extend tracking log
|
||||
* Accept float values as initstepslew threshold
|
||||
* Allow hostnames in offline, online and burst commands
|
||||
* Fix and improve peer polling
|
||||
* Fix crash in config parsing with too many servers
|
||||
* Fix crash with duplicated initstepslew address
|
||||
* Fix delta calculation with extreme frequency offsets
|
||||
* Set local stratum correctly
|
||||
* Remove unnecessary adjtimex calls
|
||||
* Set paths in documentation by configure
|
||||
* Update chrony.spec
|
||||
|
||||
New in version 1.27
|
||||
===================
|
||||
|
||||
* Support for stronger keys via NSS or libtomcrypt library
|
||||
* Support reading leap second data from tz database
|
||||
* Support for precise clock stepping on Linux
|
||||
* Support for nanoseconds in SHM refclock
|
||||
* Make offset corrections smoother on Linux
|
||||
* Make transmit timestamps random below clock precision
|
||||
* Add corrtimeratio and maxchange directives
|
||||
* Extend tracking, sources and activity reports
|
||||
* Wait in foreground process until daemon is fully initialized
|
||||
* Fix crash with slow name resolving
|
||||
* Fix iburst with jittery sources
|
||||
* Fix offset stored in rtc data right after trimrtc
|
||||
* Fix crash and hang with RTC or manual samples
|
||||
* Don't use readonly adjtime on Linux kernels before 2.6.28
|
||||
* Changed chronyc protocol, incompatible with older versions
|
||||
|
||||
New in version 1.26
|
||||
===================
|
||||
|
||||
* Add compatibility with Linux 3.0 and later
|
||||
* Use proper source address in NTP replies on multihomed IPv6 hosts
|
||||
* Accept NTP packets with versions 4, 3 and 2
|
||||
* Cope with unexpected backward time jumps
|
||||
* Don't reset kernel frequency on start without drift file
|
||||
* Retry on permanent DNS error by default
|
||||
* Add waitsync command
|
||||
|
||||
New in version 1.25
|
||||
===================
|
||||
|
||||
* Improve accuracy with NTP sources
|
||||
* Improve accuracy with reference clocks
|
||||
* Improve polling interval adjustment
|
||||
* Improve stability with temporary asymmetric delays
|
||||
* Improve source selection
|
||||
* Improve initial synchronisation
|
||||
* Add delayed server name resolving
|
||||
* Add temperature compensation
|
||||
* Add nanosecond slewing to Linux driver
|
||||
* Add fallback drifts
|
||||
* Add iburst, minstratum, maxdelaydevratio, polltarget,
|
||||
prefer, noselect options
|
||||
* Add rtcsync directive to enable Linux 11-minute mode
|
||||
* Add reselectdist, stratumweight, logbanner, maxclockerror,
|
||||
include directives
|
||||
* Add -n option to not detach daemon from terminal
|
||||
* Fix pidfile directive
|
||||
* Fix name resolving with disabled IPv6 support
|
||||
* Fix reloading sample histories with reference clocks
|
||||
* Fix crash with auto_offline option
|
||||
* Fix online command on auto_offline sources
|
||||
* Fix file descriptor leaks
|
||||
* Increase burst polling interval and stop on KoD RATE
|
||||
* Set maxupdateskew to 1000 ppm by default
|
||||
* Require password for clients command
|
||||
* Update drift file at most once per hour
|
||||
* Use system headers for Linux RTC support
|
||||
* Reduce default chronyc timeout and make it configurable
|
||||
* Avoid large values in chronyc sources and sourcestats output
|
||||
* Add reselect command to force reselecting best source
|
||||
* Add -m option to allow multiple commands on command line
|
||||
|
||||
New in version 1.24
|
||||
===================
|
||||
|
||||
Security fixes
|
||||
--------------
|
||||
* Don't reply to invalid cmdmon packets (CVE-2010-0292)
|
||||
* Limit client log memory size (CVE-2010-0293)
|
||||
* Limit rate of syslog messages (CVE-2010-0294)
|
||||
|
||||
Bug fixes/Enhancements
|
||||
----------------------
|
||||
* Support for reference clocks (SHM, SOCK, PPS drivers)
|
||||
* IPv6 support
|
||||
* Linux capabilities support (to drop root privileges)
|
||||
@@ -12,8 +313,10 @@ New in version 1.24
|
||||
* NTP client support for KoD RATE
|
||||
* Read kernel timestamps for received NTP packets
|
||||
* Reply to NTP requests with correct address on multihomed hosts
|
||||
* Add option to limit client log memory size
|
||||
* Retry name resolving after temporary failure
|
||||
* Fix makestep command, make it available on all systems
|
||||
* Add makestep directive for automatic clock stepping
|
||||
* Don't require _bigadj kernel symbol on NetBSD
|
||||
* Avoid blocking read in Linux RTC driver
|
||||
* Support for Linux on S/390 and PowerPC
|
||||
* Fix various bugs on 64-bit systems
|
||||
|
||||
122
README
122
README
@@ -2,69 +2,36 @@ This is the README for chrony.
|
||||
|
||||
What is chrony?
|
||||
===============
|
||||
Chrony is a pair of programs for maintaining the accuracy of computer
|
||||
clocks.
|
||||
|
||||
chronyd is a (background) daemon program that can be started at boot
|
||||
time. This does most of the work.
|
||||
chrony is a versatile implementation of the Network Time Protocol (NTP).
|
||||
It can synchronize the system clock with NTP servers, reference clocks
|
||||
(e.g. GPS receiver), and manual input using wristwatch and keyboard.
|
||||
It can also operate as an NTPv4 (RFC 5905) server and peer to provide
|
||||
a time service to other computers in the network.
|
||||
|
||||
chronyc is a command-line interface program which can be used to
|
||||
monitor chronyd's performance and to change various operating
|
||||
parateters whilst it is running.
|
||||
It is designed to perform well in a wide range of conditions, including
|
||||
intermittent network connections, heavily congested networks, changing
|
||||
temperatures (ordinary computer clocks are sensitive to temperature),
|
||||
and systems that do not run continuosly, or run on a virtual machine.
|
||||
|
||||
chronyd's main function is to obtain measurements of the true (UTC)
|
||||
time from one of several sources, and correct the system clock
|
||||
accordingly. It also works out the rate at which the system clock
|
||||
gains or loses time and uses this information to keep it accurate
|
||||
between measurements from the reference.
|
||||
|
||||
The reference time can be derived from Network Time Protocol (NTP)
|
||||
servers, reference clocks, or wristwatch-and-keyboard (via chronyc).
|
||||
The main source of information about the Network Time Protocol is
|
||||
http://www.eecis.udel.edu/~ntp.
|
||||
|
||||
It is designed so that it can work on computers which only have
|
||||
intermittent access to reference sources, for example computers which
|
||||
use a dial-up account to access the Internet. Of course, it will work
|
||||
on computers with permanent connections too.
|
||||
|
||||
In addition, on Linux it can monitor the system's real time clock
|
||||
performance, so the system can maintain accurate time even across
|
||||
reboots.
|
||||
|
||||
Typical accuracies available between 2 machines are
|
||||
|
||||
On an ethernet LAN : 100-200 microseconds, often much better
|
||||
On a V32bis dial-up modem connection : 10's of milliseconds (from one
|
||||
session to the next)
|
||||
|
||||
With a good reference clock the accuracy can reach one microsecond.
|
||||
|
||||
chronyd can also operate as an RFC1305-compatible NTP server and peer.
|
||||
Typical accuracy between two machines on a LAN is in tens, or a few
|
||||
hundreds, of microseconds; over the Internet, accuracy is typically
|
||||
within a few milliseconds. With a good hardware reference clock
|
||||
sub-microsecond accuracy is possible.
|
||||
|
||||
Two programs are included in chrony, chronyd is a daemon that can be
|
||||
started at boot time and chronyc is a command-line interface program
|
||||
which can be used to monitor chronyd's performance and to change various
|
||||
operating parameters whilst it is running.
|
||||
|
||||
What will chrony run on?
|
||||
========================
|
||||
|
||||
Chrony can be successfully built and run on
|
||||
|
||||
1. Linux v1.2.13, v2.0.x, 2.1.x (partially), 2.2.x, 2.3.x, 2.4.x, 2.6.x.
|
||||
Real time clock support is limited to 2.0.32 onwards and to 2.2, 2.3,
|
||||
2.4 and 2.6 series only. i386, x86_64, PowerPC are known to be
|
||||
supported.
|
||||
|
||||
2. Solaris 2.5/2.5.1/2.6/2.7/2.8 (various platforms)
|
||||
|
||||
3. SunOS 4.1.4 (Sparc 2 and Sparc 20)
|
||||
|
||||
4. BSD/386 v1.1 has been reported to work using the SunOS 4.1 driver.
|
||||
|
||||
5. NetBSD.
|
||||
|
||||
Any other system will require a porting exercise. You would need to
|
||||
start from one of the existing system-specific drivers and look into
|
||||
the quirks of certain system calls and the kernel on your target
|
||||
system. (This is described in the manual).
|
||||
The software is known to work on Linux, FreeBSD, NetBSD, Mac OS X and
|
||||
Solaris. Closely related systems may work too. Any other system will
|
||||
likely require a porting exercise. You would need to start from one
|
||||
of the existing system-specific drivers and look into the quirks of
|
||||
certain system calls and the kernel on your target system.
|
||||
|
||||
How do I set it up?
|
||||
===================
|
||||
@@ -88,12 +55,6 @@ through the URL
|
||||
|
||||
http://chrony.tuxfamily.org/
|
||||
|
||||
What can chrony not do?
|
||||
=======================
|
||||
|
||||
Compared to the `reference' RFC1305 implementation xntpd, chronyd does
|
||||
not support broadcast modes.
|
||||
|
||||
Where are new versions announced?
|
||||
=================================
|
||||
|
||||
@@ -103,8 +64,7 @@ by sending mail with the subject "subscribe" to
|
||||
|
||||
chrony-announce-request@chrony.tuxfamily.org
|
||||
|
||||
These messages will be copied to chrony-users (see below). New versions
|
||||
are announced also on Freshmeat (http://freshmeat.net/).
|
||||
These messages will be copied to chrony-users (see below).
|
||||
|
||||
How can I get support for chrony?
|
||||
and where can I discuss new features, possible bugs etc?
|
||||
@@ -124,6 +84,11 @@ chrony-dev-request@chrony.tuxfamily.org
|
||||
|
||||
as applicable.
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
chrony is distributed under the GNU General Public License version 2.
|
||||
|
||||
|
||||
Author
|
||||
======
|
||||
@@ -134,7 +99,6 @@ Richard P. Curnow <rc@rc0.org.uk>
|
||||
Maintainers
|
||||
===========
|
||||
|
||||
John Hasler <john@dhh.gt.org>
|
||||
Miroslav Lichvar <mlichvar@redhat.com>
|
||||
|
||||
|
||||
@@ -144,6 +108,9 @@ Acknowledgements
|
||||
The following people have provided patches and other major contributions
|
||||
to the program :
|
||||
|
||||
Benny Lyne Amorsen <benny@amorsen.dk>
|
||||
Patch to add minstratum option
|
||||
|
||||
Andrew Bishop <amb@gedanken.demon.co.uk>
|
||||
Fixes for bugs in logging when in daemon mode
|
||||
Fixes for compiler warnings
|
||||
@@ -161,6 +128,9 @@ Stephan I. Boettcher <stephan@nevis1.columbia.edu>
|
||||
Erik Bryer <ebryer@spots.ab.ca>
|
||||
Entries in contrib directory
|
||||
|
||||
Bryan Christianson <bryan@whatroute.net>
|
||||
Support for Mac OS X
|
||||
|
||||
Juliusz Chroboczek <jch@pps.jussieu.fr>
|
||||
Fix install rule in Makefile if chronyd file is in use.
|
||||
|
||||
@@ -175,6 +145,9 @@ Alexander Gretencord <arutha@gmx.de>
|
||||
Changes to installation directory system to make it easier for
|
||||
package builders.
|
||||
|
||||
Andrew Griffiths <agriffit@redhat.com>
|
||||
Patch to add support for seccomp filter
|
||||
|
||||
Walter Haidinger <walter.haidinger@gmx.at>
|
||||
Providing me with login access to a Linux installation where v1.12
|
||||
wouldn't compile, so I could develop the fixes for v1.13. Also, for
|
||||
@@ -185,6 +158,7 @@ Juergen Hannken-Illjes <hannken@eis.cs.tu-bs.de>
|
||||
Port to NetBSD
|
||||
|
||||
John Hasler <john@dhh.gt.org>
|
||||
Project and website at tuxfamily.org
|
||||
Changes to support 64 bit machines (i.e. those where
|
||||
sizeof(unsigned long) > 4)
|
||||
Bug fix to initstepslew directive
|
||||
@@ -192,12 +166,20 @@ John Hasler <john@dhh.gt.org>
|
||||
Memory locking and real-time scheduler support
|
||||
Fix fault where chronyd enters an endless loop
|
||||
|
||||
Tjalling Hattink <t.hattink@fugro.nl>
|
||||
Fix scheduler to allow stepping clock from timeout handler
|
||||
Patch to take leap second in PPS refclock from locked source
|
||||
Patch to make reading of RTC for initial trim more reliable
|
||||
|
||||
Liam Hatton <me@liamhatton.com>
|
||||
Advice on configuring for Linux on PPC
|
||||
|
||||
Jachym Holecek <jakym@volny.cz>
|
||||
Patch to make Linux real time clock work with devfs
|
||||
|
||||
Håkan Johansson <f96hajo@chalmers.se>
|
||||
Patch to avoid large values in sources and sourcestats output
|
||||
|
||||
Jim Knoble <jmknoble@pobox.com>
|
||||
Fixes for compiler warnings
|
||||
|
||||
@@ -209,7 +191,12 @@ Miroslav Lichvar <mlichvar@redhat.com>
|
||||
IPv6 support
|
||||
Linux capabilities support
|
||||
Leap second support
|
||||
Various bug fixes and improvements
|
||||
Improved source selection
|
||||
Improved sample history trimming
|
||||
Improved polling interval adjustment
|
||||
Improved stability with temporary asymmetric delays
|
||||
Temperature compensation
|
||||
Many other bug fixes and improvements
|
||||
|
||||
Victor Moroz <vim@prv.adlum.ru>
|
||||
Patch to support Linux with HZ!=100
|
||||
@@ -220,6 +207,9 @@ Kalle Olavi Niemitalo <tosi@stekt.oulu.fi>
|
||||
Frank Otto <sandwichmacher@web.de>
|
||||
Handling arbitrary HZ values
|
||||
|
||||
Gautier PHILIPPON <gautier.philippon@ensimag.grenoble-inp.fr>
|
||||
Patch to add refresh command to chronyc
|
||||
|
||||
Andreas Piesk <apiesk@virbus.de>
|
||||
Patch to make chronyc use the readline library if available
|
||||
|
||||
@@ -241,5 +231,3 @@ Doug Woodward <dougw@whistler.com>
|
||||
|
||||
Many other people have contributed bug reports and suggestions. I'm
|
||||
sorry I can't identify all of you individually.
|
||||
|
||||
vim:tw=72
|
||||
|
||||
784
acquire.c
784
acquire.c
@@ -1,784 +0,0 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/acquire.c,v 1.24 2003/09/22 21:22:30 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
=======================================================================
|
||||
|
||||
Processing to perform the equivalent of what ntpdate does. That is,
|
||||
make a rapid-fire set of measurements to a designated set of
|
||||
sources, and step or slew the local clock to bring it into line with
|
||||
the result.
|
||||
|
||||
This is kept completely separate of the main chronyd processing, by
|
||||
using a separate socket for sending/receiving the measurement
|
||||
packets. That way, ntp_core.c can be kept completely independent of
|
||||
this functionality.
|
||||
|
||||
A few of the finer points of how to construct valid RFC1305 packets
|
||||
and validate responses for this case have been cribbed from the
|
||||
ntpdate source.
|
||||
|
||||
*/
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "acquire.h"
|
||||
#include "memory.h"
|
||||
#include "sched.h"
|
||||
#include "local.h"
|
||||
#include "logging.h"
|
||||
#include "ntp.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include "conf.h"
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
/* Interval between firing off the first sample to successive sources */
|
||||
#define INTER_SOURCE_START (0.2)
|
||||
|
||||
#define MAX_SAMPLES 8
|
||||
|
||||
#define MAX_DEAD_PROBES 4
|
||||
#define N_GOOD_SAMPLES 4
|
||||
|
||||
#define RETRANSMISSION_TIMEOUT (1.0)
|
||||
|
||||
typedef struct {
|
||||
IPAddr ip_addr; /* Address of the server */
|
||||
int sanity; /* Flag indicating whether source
|
||||
looks sane or not */
|
||||
int n_dead_probes; /* Number of probes sent to the server
|
||||
since a good one */
|
||||
int n_samples; /* Number of samples accumulated */
|
||||
int n_total_samples; /* Total number of samples received
|
||||
including useless ones */
|
||||
double offsets[MAX_SAMPLES]; /* In seconds, positive means local
|
||||
clock is fast of reference */
|
||||
double root_distances[MAX_SAMPLES]; /* in seconds */
|
||||
double inter_lo; /* Low end of estimated range of offset */
|
||||
double inter_hi; /* High end of estimated range of offset */
|
||||
|
||||
NTP_int64 last_tx; /* Transmit timestamp in last packet
|
||||
transmitted to source. */
|
||||
|
||||
int timer_running;
|
||||
SCH_TimeoutID timeout_id;
|
||||
} SourceRecord;
|
||||
|
||||
static SourceRecord *sources;
|
||||
static int n_sources;
|
||||
static int n_started_sources;
|
||||
static int n_completed_sources;
|
||||
|
||||
static int init_slew_threshold = -1;
|
||||
|
||||
union sockaddr_in46 {
|
||||
struct sockaddr_in in4;
|
||||
#ifdef HAVE_IPV6
|
||||
struct sockaddr_in6 in6;
|
||||
#endif
|
||||
struct sockaddr u;
|
||||
};
|
||||
|
||||
static int sock_fd4 = -1;
|
||||
#ifdef HAVE_IPV6
|
||||
static int sock_fd6 = -1;
|
||||
#endif
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void (*saved_after_hook)(void *) = NULL;
|
||||
static void *saved_after_hook_anything = NULL;
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
typedef struct {
|
||||
double offset;
|
||||
enum {LO, HIGH} type;
|
||||
int index;
|
||||
} Endpoint;
|
||||
|
||||
typedef struct {
|
||||
double lo;
|
||||
double hi;
|
||||
} Interval;
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void read_from_socket(void *anything);
|
||||
static void transmit_timeout(void *x);
|
||||
static void wind_up_acquisition(void);
|
||||
static void start_source_timeout_handler(void *not_used);
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static SCH_TimeoutID source_start_timeout_id;
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
ACQ_Initialise(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
ACQ_Finalise(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
prepare_socket(int family)
|
||||
{
|
||||
unsigned short port_number = CNF_GetAcquisitionPort();
|
||||
int sock_fd;
|
||||
socklen_t addrlen;
|
||||
|
||||
sock_fd = socket(family, SOCK_DGRAM, 0);
|
||||
|
||||
if (sock_fd < 0) {
|
||||
LOG_FATAL(LOGF_Acquire, "Could not open socket : %s", strerror(errno));
|
||||
}
|
||||
|
||||
if (port_number == 0) {
|
||||
/* Don't bother binding this socket - we're not fussed what port
|
||||
number it gets */
|
||||
} else {
|
||||
union sockaddr_in46 my_addr;
|
||||
|
||||
memset(&my_addr, 0, sizeof (my_addr));
|
||||
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
my_addr.in4.sin_family = family;
|
||||
my_addr.in4.sin_port = htons(port_number);
|
||||
my_addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
addrlen = sizeof (my_addr.in4);
|
||||
break;
|
||||
#ifdef HAVE_IPV6
|
||||
case AF_INET6:
|
||||
my_addr.in6.sin6_family = family;
|
||||
my_addr.in6.sin6_port = htons(port_number);
|
||||
my_addr.in6.sin6_addr = in6addr_any;
|
||||
addrlen = sizeof (my_addr.in6);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (bind(sock_fd, &my_addr.u, addrlen) < 0) {
|
||||
LOG(LOGS_ERR, LOGF_Acquire, "Could not bind socket : %s\n", strerror(errno));
|
||||
/* but keep running */
|
||||
}
|
||||
}
|
||||
|
||||
SCH_AddInputFileHandler(sock_fd, read_from_socket, (void *)(long)sock_fd);
|
||||
|
||||
return sock_fd;
|
||||
}
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
initialise_io(int family)
|
||||
{
|
||||
if (family == IPADDR_INET4 || family == IPADDR_UNSPEC)
|
||||
sock_fd4 = prepare_socket(AF_INET);
|
||||
#ifdef HAVE_IPV6
|
||||
if (family == IPADDR_INET6 || family == IPADDR_UNSPEC)
|
||||
sock_fd6 = prepare_socket(AF_INET6);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
finalise_io(void)
|
||||
{
|
||||
if (sock_fd4 >= 0) {
|
||||
SCH_RemoveInputFileHandler(sock_fd4);
|
||||
close(sock_fd4);
|
||||
}
|
||||
sock_fd4 = -1;
|
||||
#ifdef HAVE_IPV6
|
||||
if (sock_fd6 >= 0) {
|
||||
SCH_RemoveInputFileHandler(sock_fd6);
|
||||
close(sock_fd6);
|
||||
}
|
||||
sock_fd6 = -1;
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
probe_source(SourceRecord *src)
|
||||
{
|
||||
NTP_Packet pkt;
|
||||
int version = 3;
|
||||
NTP_Mode my_mode = MODE_CLIENT;
|
||||
struct timeval cooked;
|
||||
double local_time_err;
|
||||
union sockaddr_in46 his_addr;
|
||||
int sock_fd;
|
||||
socklen_t addrlen;
|
||||
|
||||
#if 0
|
||||
printf("Sending probe to %s sent=%d samples=%d\n", UTI_IPToString(&src->ip_addr), src->n_probes_sent, src->n_samples);
|
||||
#endif
|
||||
|
||||
pkt.lvm = (((LEAP_Unsynchronised << 6) & 0xc0) |
|
||||
((version << 3) & 0x38) |
|
||||
((my_mode) & 0x7));
|
||||
|
||||
pkt.stratum = 0;
|
||||
pkt.poll = 4;
|
||||
pkt.precision = -6; /* as ntpdate */
|
||||
pkt.root_delay = double_to_int32(1.0); /* 1 second */
|
||||
pkt.root_dispersion = double_to_int32(1.0); /* likewise */
|
||||
pkt.reference_id = 0UL;
|
||||
pkt.reference_ts.hi = 0; /* Set to 0 */
|
||||
pkt.reference_ts.lo = 0; /* Set to 0 */
|
||||
pkt.originate_ts.hi = 0; /* Set to 0 */
|
||||
pkt.originate_ts.lo = 0; /* Set to 0 */
|
||||
pkt.receive_ts.hi = 0; /* Set to 0 */
|
||||
pkt.receive_ts.lo = 0; /* Set to 0 */
|
||||
|
||||
/* And do transmission */
|
||||
|
||||
memset(&his_addr, 0, sizeof (his_addr));
|
||||
switch (src->ip_addr.family) {
|
||||
case IPADDR_INET4:
|
||||
his_addr.in4.sin_addr.s_addr = htonl(src->ip_addr.addr.in4);
|
||||
his_addr.in4.sin_port = htons(123); /* Fixed for now */
|
||||
his_addr.in4.sin_family = AF_INET;
|
||||
addrlen = sizeof (his_addr.in4);
|
||||
sock_fd = sock_fd4;
|
||||
break;
|
||||
#ifdef HAVE_IPV6
|
||||
case IPADDR_INET6:
|
||||
memcpy(&his_addr.in6.sin6_addr.s6_addr, &src->ip_addr.addr.in6,
|
||||
sizeof (his_addr.in6.sin6_addr.s6_addr));
|
||||
his_addr.in6.sin6_port = htons(123); /* Fixed for now */
|
||||
his_addr.in6.sin6_family = AF_INET6;
|
||||
addrlen = sizeof (his_addr.in6);
|
||||
sock_fd = sock_fd6;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
LCL_ReadCookedTime(&cooked, &local_time_err);
|
||||
UTI_TimevalToInt64(&cooked, &pkt.transmit_ts);
|
||||
|
||||
if (sendto(sock_fd, (void *) &pkt, NTP_NORMAL_PACKET_SIZE,
|
||||
0,
|
||||
&his_addr.u, addrlen) < 0) {
|
||||
LOG(LOGS_WARN, LOGF_Acquire, "Could not send to %s : %s",
|
||||
UTI_IPToString(&src->ip_addr),
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
src->last_tx = pkt.transmit_ts;
|
||||
|
||||
++(src->n_dead_probes);
|
||||
src->timer_running = 1;
|
||||
src->timeout_id = SCH_AddTimeoutByDelay(RETRANSMISSION_TIMEOUT, transmit_timeout, (void *) src);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
transmit_timeout(void *x)
|
||||
{
|
||||
SourceRecord *src = (SourceRecord *) x;
|
||||
|
||||
src->timer_running = 0;
|
||||
|
||||
#if 0
|
||||
printf("Timeout expired for server %s\n", UTI_IPToString(&src->ip_addr));
|
||||
#endif
|
||||
|
||||
if (src->n_dead_probes < MAX_DEAD_PROBES) {
|
||||
probe_source(src);
|
||||
} else {
|
||||
/* Source has croaked or is taking too long to respond */
|
||||
++n_completed_sources;
|
||||
if (n_completed_sources == n_sources) {
|
||||
wind_up_acquisition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
#define MAX_STRATUM 15
|
||||
|
||||
static void
|
||||
process_receive(NTP_Packet *msg, SourceRecord *src, struct timeval *now)
|
||||
{
|
||||
|
||||
unsigned long lvm;
|
||||
int leap, version, mode;
|
||||
double root_delay, root_dispersion;
|
||||
double total_root_delay, total_root_dispersion, total_root_distance;
|
||||
|
||||
struct timeval local_orig, local_average, remote_rx, remote_tx, remote_average;
|
||||
double remote_interval, local_interval;
|
||||
double delta, theta, epsilon;
|
||||
int n;
|
||||
|
||||
/* Most of the checks are from ntpdate */
|
||||
|
||||
/* Need to do something about authentication */
|
||||
|
||||
lvm = msg->lvm;
|
||||
leap = (lvm >> 6) & 0x3;
|
||||
version = (lvm >> 3) & 0x7;
|
||||
mode = lvm & 0x7;
|
||||
|
||||
if ((leap == LEAP_Unsynchronised) ||
|
||||
(version != 3) ||
|
||||
(mode != MODE_SERVER && mode != MODE_PASSIVE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg->stratum > MAX_STRATUM) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check whether server is responding to our last request */
|
||||
if ((msg->originate_ts.hi != src->last_tx.hi) ||
|
||||
(msg->originate_ts.lo != src->last_tx.lo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check that the server is sane */
|
||||
if (((msg->originate_ts.hi == 0) && (msg->originate_ts.lo == 0)) ||
|
||||
((msg->receive_ts.hi == 0) && (msg->receive_ts.lo) == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
root_delay = int32_to_double(msg->root_delay);
|
||||
root_dispersion = int32_to_double(msg->root_dispersion);
|
||||
|
||||
UTI_Int64ToTimeval(&src->last_tx, &local_orig);
|
||||
UTI_Int64ToTimeval(&msg->receive_ts, &remote_rx);
|
||||
UTI_Int64ToTimeval(&msg->transmit_ts, &remote_tx);
|
||||
UTI_AverageDiffTimevals(&remote_rx, &remote_tx, &remote_average, &remote_interval);
|
||||
UTI_AverageDiffTimevals(&local_orig, now, &local_average, &local_interval);
|
||||
|
||||
delta = local_interval - remote_interval;
|
||||
|
||||
/* Defined as positive if we are fast. Note this sign convention is
|
||||
opposite to that used in ntp_core.c */
|
||||
|
||||
UTI_DiffTimevalsToDouble(&theta, &local_average, &remote_average);
|
||||
|
||||
/* Could work out epsilon - leave till later */
|
||||
epsilon = 0.0;
|
||||
|
||||
total_root_delay = fabs(delta) + root_delay;
|
||||
total_root_dispersion = epsilon + root_dispersion;
|
||||
total_root_distance = 0.5 * fabs(total_root_delay) + total_root_dispersion;
|
||||
|
||||
n = src->n_samples;
|
||||
#if 0
|
||||
printf("Sample %d theta=%.6f delta=%.6f root_del=%.6f root_disp=%.6f root_dist=%.6f\n",
|
||||
n, theta, delta, total_root_delay, total_root_dispersion, total_root_distance);
|
||||
#endif
|
||||
src->offsets[n] = theta;
|
||||
src->root_distances[n] = total_root_distance;
|
||||
++(src->n_samples);
|
||||
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
read_from_socket(void *anything)
|
||||
{
|
||||
int status;
|
||||
ReceiveBuffer msg;
|
||||
union sockaddr_in46 his_addr;
|
||||
int sock_fd;
|
||||
socklen_t his_addr_len;
|
||||
int flags;
|
||||
int message_length;
|
||||
IPAddr remote_ip;
|
||||
int i, ok;
|
||||
struct timeval now;
|
||||
SourceRecord *src;
|
||||
|
||||
flags = 0;
|
||||
message_length = sizeof(msg);
|
||||
his_addr_len = sizeof(his_addr);
|
||||
|
||||
/* Get timestamp */
|
||||
SCH_GetFileReadyTime(&now);
|
||||
|
||||
sock_fd = (long)anything;
|
||||
status = recvfrom (sock_fd, (char *)&msg, message_length, flags,
|
||||
&his_addr.u, &his_addr_len);
|
||||
|
||||
if (status < 0) {
|
||||
LOG(LOGS_WARN, LOGF_Acquire, "Error reading from socket, %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (his_addr.u.sa_family) {
|
||||
case AF_INET:
|
||||
remote_ip.family = IPADDR_INET4;
|
||||
remote_ip.addr.in4 = ntohl(his_addr.in4.sin_addr.s_addr);
|
||||
break;
|
||||
#ifdef HAVE_IPV6
|
||||
case AF_INET6:
|
||||
remote_ip.family = IPADDR_INET6;
|
||||
memcpy(&remote_ip.addr.in6, his_addr.in6.sin6_addr.s6_addr,
|
||||
sizeof (remote_ip.addr.in6));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("Got message from %s\n", UTI_IPToString(&remote_ip));
|
||||
#endif
|
||||
|
||||
/* Find matching host */
|
||||
ok = 0;
|
||||
for (i=0; i<n_sources; i++) {
|
||||
if (UTI_CompareIPs(&remote_ip, &sources[i].ip_addr, NULL) == 0) {
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
|
||||
src = sources + i;
|
||||
++src->n_total_samples;
|
||||
|
||||
src->n_dead_probes = 0; /* reset this when we actually receive something */
|
||||
|
||||
/* If we got into this function, we know the retransmission timeout has not
|
||||
expired for the source */
|
||||
if (src->timer_running) {
|
||||
SCH_RemoveTimeout(src->timeout_id);
|
||||
src->timer_running = 0;
|
||||
}
|
||||
|
||||
process_receive(&msg.ntp_pkt, src, &now);
|
||||
|
||||
/* Check if server done and requeue timeout */
|
||||
if ((src->n_samples >= N_GOOD_SAMPLES) ||
|
||||
(src->n_total_samples >= MAX_SAMPLES)) {
|
||||
++n_completed_sources;
|
||||
#if 0
|
||||
printf("Source %s completed\n", UTI_IPToString(&src->ip_addr));
|
||||
#endif
|
||||
if (n_completed_sources == n_sources) {
|
||||
wind_up_acquisition();
|
||||
}
|
||||
} else {
|
||||
|
||||
/* Send the next probe */
|
||||
probe_source(src);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
start_next_source(void)
|
||||
{
|
||||
probe_source(sources + n_started_sources);
|
||||
#if 0
|
||||
printf("Trying to start source %s\n", UTI_IPToString(&sources[n_started_sources].ip_addr));
|
||||
#endif
|
||||
n_started_sources++;
|
||||
|
||||
if (n_started_sources < n_sources) {
|
||||
source_start_timeout_id = SCH_AddTimeoutByDelay(INTER_SOURCE_START, start_source_timeout_handler, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
endpoint_compare(const void *a, const void *b)
|
||||
{
|
||||
const Endpoint *aa = (const Endpoint *) a;
|
||||
const Endpoint *bb = (const Endpoint *) b;
|
||||
|
||||
if (aa->offset < bb->offset) {
|
||||
return -1;
|
||||
} else if (aa->offset > bb->offset) {
|
||||
return +1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
process_measurements(void)
|
||||
{
|
||||
|
||||
SourceRecord *s;
|
||||
Endpoint *eps;
|
||||
int i, j;
|
||||
int n_sane_sources;
|
||||
double lo, hi;
|
||||
double inter_lo, inter_hi;
|
||||
|
||||
int depth;
|
||||
int best_depth;
|
||||
int n_at_best_depth;
|
||||
Interval *intervals;
|
||||
double estimated_offset;
|
||||
int index1, index2;
|
||||
|
||||
n_sane_sources = 0;
|
||||
|
||||
/* First, get a consistent interval for each source. Those for
|
||||
which this is not possible are considered to be insane. */
|
||||
|
||||
for (i=0; i<n_sources; i++) {
|
||||
s = sources + i;
|
||||
/* If we got no measurements, the source is insane */
|
||||
if (s->n_samples == 0) {
|
||||
s->sanity = 0;
|
||||
} else {
|
||||
s->sanity = 1; /* so far ... */
|
||||
lo = s->offsets[0] - s->root_distances[0];
|
||||
hi = s->offsets[0] + s->root_distances[0];
|
||||
inter_lo = lo;
|
||||
inter_hi = hi;
|
||||
for (j=1; j<s->n_samples; j++) {
|
||||
lo = s->offsets[j] - s->root_distances[j];
|
||||
hi = s->offsets[j] + s->root_distances[j];
|
||||
if ((inter_hi <= lo) || (inter_lo >= hi)) {
|
||||
/* Oh dear, we won't get an interval for this source */
|
||||
s->sanity = 0;
|
||||
break;
|
||||
} else {
|
||||
inter_lo = (lo < inter_lo) ? inter_lo : lo;
|
||||
inter_hi = (hi > inter_hi) ? inter_hi : hi;
|
||||
}
|
||||
}
|
||||
if (s->sanity) {
|
||||
s->inter_lo = inter_lo;
|
||||
s->inter_hi = inter_hi;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->sanity) {
|
||||
++n_sane_sources;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Now build the endpoint list, similar to the RFC1305 clock
|
||||
selection algorithm. */
|
||||
eps = MallocArray(Endpoint, 2*n_sane_sources);
|
||||
intervals = MallocArray(Interval, n_sane_sources);
|
||||
|
||||
j = 0;
|
||||
for (i=0; i<n_sources; i++) {
|
||||
s = sources + i;
|
||||
if (s->sanity) {
|
||||
eps[j].offset = s->inter_lo;
|
||||
eps[j].type = LO;
|
||||
eps[j].index = i;
|
||||
eps[j+1].offset = s->inter_hi;
|
||||
eps[j+1].type = HIGH;
|
||||
eps[j+1].index = i;
|
||||
j += 2;
|
||||
}
|
||||
}
|
||||
|
||||
qsort(eps, 2*n_sane_sources, sizeof(Endpoint), endpoint_compare);
|
||||
|
||||
/* Now do depth searching algorithm */
|
||||
n_at_best_depth = best_depth = depth = 0;
|
||||
for (i=0; i<2*n_sane_sources; i++) {
|
||||
|
||||
#if 0
|
||||
fprintf(stderr, "Endpoint type %s source index %d [ip=%s] offset=%.6f\n",
|
||||
(eps[i].type == LO) ? "LO" : "HIGH",
|
||||
eps[i].index,
|
||||
UTI_IPToString(&sources[eps[i].index].ip_addr),
|
||||
eps[i].offset);
|
||||
#endif
|
||||
|
||||
switch (eps[i].type) {
|
||||
case LO:
|
||||
depth++;
|
||||
if (depth > best_depth) {
|
||||
best_depth = depth;
|
||||
n_at_best_depth = 0;
|
||||
intervals[0].lo = eps[i].offset;
|
||||
} else if (depth == best_depth) {
|
||||
intervals[n_at_best_depth].lo = eps[i].offset;
|
||||
} else {
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case HIGH:
|
||||
if (depth == best_depth) {
|
||||
intervals[n_at_best_depth].hi = eps[i].offset;
|
||||
n_at_best_depth++;
|
||||
}
|
||||
|
||||
depth--;
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (best_depth > 0) {
|
||||
if ((n_at_best_depth % 2) == 1) {
|
||||
index1 = (n_at_best_depth - 1) / 2;
|
||||
estimated_offset = 0.5 * (intervals[index1].lo + intervals[index1].hi);
|
||||
} else {
|
||||
index2 = (n_at_best_depth / 2);
|
||||
index1 = index2 - 1;
|
||||
estimated_offset = 0.5 * (intervals[index1].lo + intervals[index2].hi);
|
||||
}
|
||||
|
||||
|
||||
/* Apply a step change to the system clock. As per sign
|
||||
convention in local.c and its children, a positive offset means
|
||||
the system clock is fast of the reference, i.e. it needs to be
|
||||
stepped backwards. */
|
||||
|
||||
if (fabs(estimated_offset) > (double) init_slew_threshold) {
|
||||
LOG(LOGS_INFO, LOGF_Acquire, "System's initial offset : %.6f seconds %s of true (step)",
|
||||
fabs(estimated_offset),
|
||||
(estimated_offset >= 0) ? "fast" : "slow");
|
||||
LCL_ApplyStepOffset(estimated_offset);
|
||||
} else {
|
||||
LOG(LOGS_INFO, LOGF_Acquire, "System's initial offset : %.6f seconds %s of true (slew)",
|
||||
fabs(estimated_offset),
|
||||
(estimated_offset >= 0) ? "fast" : "slow");
|
||||
LCL_AccumulateOffset(estimated_offset);
|
||||
}
|
||||
|
||||
} else {
|
||||
LOG(LOGS_WARN, LOGF_Acquire, "No intersecting endpoints found");
|
||||
}
|
||||
|
||||
Free(intervals);
|
||||
Free(eps);
|
||||
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
wind_up_acquisition(void)
|
||||
{
|
||||
|
||||
/* Now process measurements */
|
||||
process_measurements();
|
||||
|
||||
Free(sources);
|
||||
|
||||
finalise_io();
|
||||
|
||||
if (saved_after_hook) {
|
||||
(saved_after_hook)(saved_after_hook_anything);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
start_source_timeout_handler(void *not_used)
|
||||
{
|
||||
|
||||
start_next_source();
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
ACQ_StartAcquisition(int n, IPAddr *ip_addrs, int threshold, void (*after_hook)(void *), void *anything)
|
||||
{
|
||||
|
||||
int i, ip4, ip6;
|
||||
|
||||
saved_after_hook = after_hook;
|
||||
saved_after_hook_anything = anything;
|
||||
|
||||
init_slew_threshold = threshold;
|
||||
|
||||
n_started_sources = 0;
|
||||
n_completed_sources = 0;
|
||||
n_sources = n;
|
||||
sources = MallocArray(SourceRecord, n);
|
||||
|
||||
for (i = ip4 = ip6 = 0; i < n; i++) {
|
||||
sources[i].ip_addr = ip_addrs[i];
|
||||
sources[i].n_samples = 0;
|
||||
sources[i].n_total_samples = 0;
|
||||
sources[i].n_dead_probes = 0;
|
||||
if (ip_addrs[i].family == IPADDR_INET4)
|
||||
ip4++;
|
||||
else if (ip_addrs[i].family == IPADDR_INET6)
|
||||
ip6++;
|
||||
}
|
||||
|
||||
initialise_io((ip4 && ip6) ? IPADDR_UNSPEC : (ip4 ? IPADDR_INET4 : IPADDR_INET6));
|
||||
|
||||
/* Start sampling first source */
|
||||
start_next_source();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
10
addressing.h
10
addressing.h
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/addressing.h,v 1.7 2002/02/28 23:27:08 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
@@ -50,9 +46,13 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
IPAddr ip_addr;
|
||||
IPAddr local_ip_addr;
|
||||
unsigned short port;
|
||||
} NTP_Remote_Address;
|
||||
|
||||
typedef struct {
|
||||
IPAddr ip_addr;
|
||||
int sock_fd;
|
||||
} NTP_Local_Address;
|
||||
|
||||
#endif /* GOT_ADDRESSING_H */
|
||||
|
||||
|
||||
56
addrfilt.c
56
addrfilt.c
@@ -1,13 +1,9 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/addrfilt.c,v 1.8 2002/02/28 23:27:08 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997,1998,1999,2000,2001,2002,2005
|
||||
* Copyright (C) Miroslav Lichvar 2009
|
||||
* Copyright (C) Miroslav Lichvar 2009, 2015
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -32,6 +28,8 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "addrfilt.h"
|
||||
@@ -118,8 +116,6 @@ close_node(TableNode *node)
|
||||
Free(node->extended);
|
||||
node->extended = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +139,6 @@ open_node(TableNode *node)
|
||||
child_node->extended = NULL;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -204,7 +199,10 @@ set_subnet(TableNode *start_node,
|
||||
|
||||
/* How many subnet entries to set : 1->8, 2->4, 3->2 */
|
||||
N = 1 << (NBITS-bits_to_go);
|
||||
subnet = get_subnet(ip, bits_consumed);
|
||||
|
||||
subnet = get_subnet(ip, bits_consumed) & ~(N - 1);
|
||||
assert(subnet + N <= TABLE_SIZE);
|
||||
|
||||
if (!(node->extended)) {
|
||||
open_node(node);
|
||||
}
|
||||
@@ -368,6 +366,44 @@ ADF_IsAllowed(ADF_AuthTable table,
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
is_any_allowed(TableNode *node, State parent)
|
||||
{
|
||||
State state;
|
||||
int i;
|
||||
|
||||
state = node->state != AS_PARENT ? node->state : parent;
|
||||
assert(state != AS_PARENT);
|
||||
|
||||
if (node->extended) {
|
||||
for (i = 0; i < TABLE_SIZE; i++) {
|
||||
if (is_any_allowed(&node->extended[i], state))
|
||||
return 1;
|
||||
}
|
||||
} else if (state == ALLOW) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
ADF_IsAnyAllowed(ADF_AuthTable table, int family)
|
||||
{
|
||||
switch (family) {
|
||||
case IPADDR_INET4:
|
||||
return is_any_allowed(&table->base4, AS_PARENT);
|
||||
case IPADDR_INET6:
|
||||
return is_any_allowed(&table->base6, AS_PARENT);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
#if defined TEST
|
||||
|
||||
static void print_node(TableNode *node, uint32_t *addr, int ip_len, int shift, int subnet_bits)
|
||||
@@ -410,7 +446,6 @@ static void print_node(TableNode *node, uint32_t *addr, int ip_len, int shift, i
|
||||
print_node(sub_node, new_addr, ip_len, shift - 4, subnet_bits + 4);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -425,7 +460,6 @@ static void print_table(ADF_AuthTable table)
|
||||
memset(addr, 0, sizeof (addr));
|
||||
printf("IPv6 table:\n");
|
||||
print_node(&table->base6, addr, 4, 124, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/addrfilt.h,v 1.6 2002/02/28 23:27:08 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
@@ -76,4 +72,9 @@ extern void ADF_DestroyTable(ADF_AuthTable table);
|
||||
extern int ADF_IsAllowed(ADF_AuthTable table,
|
||||
IPAddr *ip);
|
||||
|
||||
/* Check if at least one address from a given family is allowed by
|
||||
the rules in the table */
|
||||
extern int ADF_IsAnyAllowed(ADF_AuthTable table,
|
||||
int family);
|
||||
|
||||
#endif /* GOT_ADDRFILT_H */
|
||||
|
||||
129
array.c
Normal file
129
array.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Miroslav Lichvar 2014
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
=======================================================================
|
||||
|
||||
Functions implementing an array with automatic memory allocation.
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "array.h"
|
||||
#include "memory.h"
|
||||
|
||||
struct ARR_Instance_Record {
|
||||
void *data;
|
||||
unsigned int elem_size;
|
||||
unsigned int used;
|
||||
unsigned int allocated;
|
||||
};
|
||||
|
||||
ARR_Instance
|
||||
ARR_CreateInstance(unsigned int elem_size)
|
||||
{
|
||||
ARR_Instance array;
|
||||
|
||||
assert(elem_size > 0);
|
||||
|
||||
array = MallocNew(struct ARR_Instance_Record);
|
||||
|
||||
array->data = NULL;
|
||||
array->elem_size = elem_size;
|
||||
array->used = 0;
|
||||
array->allocated = 0;
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
void
|
||||
ARR_DestroyInstance(ARR_Instance array)
|
||||
{
|
||||
Free(array->data);
|
||||
Free(array);
|
||||
}
|
||||
|
||||
static void
|
||||
realloc_array(ARR_Instance array, unsigned int min_size)
|
||||
{
|
||||
size_t data_size;
|
||||
|
||||
assert(min_size <= 2 * min_size);
|
||||
if (array->allocated >= min_size && array->allocated <= 2 * min_size)
|
||||
return;
|
||||
|
||||
if (array->allocated < min_size) {
|
||||
while (array->allocated < min_size)
|
||||
array->allocated = array->allocated ? 2 * array->allocated : 1;
|
||||
} else {
|
||||
array->allocated = min_size;
|
||||
}
|
||||
|
||||
data_size = (size_t)array->elem_size * array->allocated;
|
||||
assert(data_size / array->elem_size == array->allocated);
|
||||
|
||||
array->data = Realloc(array->data, data_size);
|
||||
}
|
||||
|
||||
void *
|
||||
ARR_GetNewElement(ARR_Instance array)
|
||||
{
|
||||
array->used++;
|
||||
realloc_array(array, array->used);
|
||||
return ARR_GetElement(array, array->used - 1);
|
||||
}
|
||||
|
||||
void *
|
||||
ARR_GetElement(ARR_Instance array, unsigned int index)
|
||||
{
|
||||
assert(index < array->used);
|
||||
return (void *)((char *)array->data + (size_t)index * array->elem_size);
|
||||
}
|
||||
|
||||
void *
|
||||
ARR_GetElements(ARR_Instance array)
|
||||
{
|
||||
return array->data;
|
||||
}
|
||||
|
||||
void
|
||||
ARR_AppendElement(ARR_Instance array, void *element)
|
||||
{
|
||||
void *e;
|
||||
|
||||
e = ARR_GetNewElement(array);
|
||||
memcpy(e, element, array->elem_size);
|
||||
}
|
||||
|
||||
void
|
||||
ARR_SetSize(ARR_Instance array, unsigned int size)
|
||||
{
|
||||
realloc_array(array, size);
|
||||
array->used = size;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
ARR_GetSize(ARR_Instance array)
|
||||
{
|
||||
return array->used;
|
||||
}
|
||||
56
array.h
Normal file
56
array.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Miroslav Lichvar 2014
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
=======================================================================
|
||||
|
||||
Header file for array functions.
|
||||
*/
|
||||
|
||||
#ifndef GOT_ARRAY_H
|
||||
#define GOT_ARRAY_H
|
||||
|
||||
typedef struct ARR_Instance_Record *ARR_Instance;
|
||||
|
||||
/* Create a new array with given element size */
|
||||
extern ARR_Instance ARR_CreateInstance(unsigned int elem_size);
|
||||
|
||||
/* Destroy the array */
|
||||
extern void ARR_DestroyInstance(ARR_Instance array);
|
||||
|
||||
/* Return pointer to a new element added to the end of the array */
|
||||
extern void *ARR_GetNewElement(ARR_Instance array);
|
||||
|
||||
/* Return element with given index */
|
||||
extern void *ARR_GetElement(ARR_Instance array, unsigned int index);
|
||||
|
||||
/* Return pointer to the internal array of elements */
|
||||
extern void *ARR_GetElements(ARR_Instance array);
|
||||
|
||||
/* Add a new element to the end of the array */
|
||||
extern void ARR_AppendElement(ARR_Instance array, void *element);
|
||||
|
||||
/* Set the size of the array */
|
||||
extern void ARR_SetSize(ARR_Instance array, unsigned int size);
|
||||
|
||||
/* Return current size of the array */
|
||||
extern unsigned int ARR_GetSize(ARR_Instance array);
|
||||
|
||||
#endif
|
||||
160
broadcast.c
160
broadcast.c
@@ -1,160 +0,0 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/broadcast.c,v 1.3 2002/02/28 23:27:08 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2002
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
=======================================================================
|
||||
|
||||
Deal with broadcast server functions.
|
||||
*/
|
||||
|
||||
#include "sysincl.h"
|
||||
#include "memory.h"
|
||||
|
||||
#include "addressing.h"
|
||||
#include "broadcast.h"
|
||||
#include "sched.h"
|
||||
#include "ntp.h"
|
||||
#include "local.h"
|
||||
#include "reference.h"
|
||||
#include "util.h"
|
||||
#include "ntp_io.h"
|
||||
|
||||
typedef struct {
|
||||
NTP_Remote_Address addr;
|
||||
int interval;
|
||||
} Destination;
|
||||
static Destination *destinations = 0;
|
||||
static int n_destinations = 0;
|
||||
static int max_destinations = 0;
|
||||
|
||||
void
|
||||
BRD_Initialise(void)
|
||||
{
|
||||
return; /* Nothing to do */
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
BRD_Finalise(void)
|
||||
{
|
||||
return; /* Nothing to do */
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
/* This is a cut-down version of what transmit_packet in ntp_core.c does */
|
||||
|
||||
static void
|
||||
timeout_handler(void *arbitrary)
|
||||
{
|
||||
Destination *d = (Destination *) arbitrary;
|
||||
NTP_Packet message;
|
||||
/* Parameters read from reference module */
|
||||
int version;
|
||||
int leap;
|
||||
int are_we_synchronised, our_stratum;
|
||||
NTP_Leap leap_status;
|
||||
unsigned long our_ref_id;
|
||||
struct timeval our_ref_time;
|
||||
double our_root_delay, our_root_dispersion;
|
||||
double local_time_err;
|
||||
struct timeval local_transmit;
|
||||
|
||||
version = 3;
|
||||
|
||||
LCL_ReadCookedTime(&local_transmit, &local_time_err);
|
||||
REF_GetReferenceParams(&local_transmit,
|
||||
&are_we_synchronised, &leap_status,
|
||||
&our_stratum,
|
||||
&our_ref_id, &our_ref_time,
|
||||
&our_root_delay, &our_root_dispersion);
|
||||
|
||||
|
||||
if (are_we_synchronised) {
|
||||
leap = (int) leap_status;
|
||||
} else {
|
||||
leap = 3;
|
||||
}
|
||||
|
||||
message.lvm = ((leap << 6) &0xc0) | ((version << 3) & 0x38) | (MODE_BROADCAST & 0x07);
|
||||
message.stratum = our_stratum;
|
||||
message.poll = 6; /* FIXME: what should this be? */
|
||||
message.precision = LCL_GetSysPrecisionAsLog();
|
||||
|
||||
/* If we're sending a client mode packet and we aren't synchronized yet,
|
||||
we might have to set up artificial values for some of these parameters */
|
||||
message.root_delay = double_to_int32(our_root_delay);
|
||||
message.root_dispersion = double_to_int32(our_root_dispersion);
|
||||
|
||||
message.reference_id = htonl((NTP_int32) our_ref_id);
|
||||
|
||||
/* Now fill in timestamps */
|
||||
UTI_TimevalToInt64(&our_ref_time, &message.reference_ts);
|
||||
message.originate_ts.hi = 0UL;
|
||||
message.originate_ts.lo = 0UL;
|
||||
message.receive_ts.hi = 0UL;
|
||||
message.receive_ts.lo = 0UL;
|
||||
|
||||
LCL_ReadCookedTime(&local_transmit, &local_time_err);
|
||||
UTI_TimevalToInt64(&local_transmit, &message.transmit_ts);
|
||||
NIO_SendNormalPacket(&message, &d->addr);
|
||||
|
||||
/* Requeue timeout. Don't care if interval drifts gradually, so just do it
|
||||
* at the end. */
|
||||
SCH_AddTimeoutInClass((double) d->interval, 1.0,
|
||||
SCH_NtpBroadcastClass,
|
||||
timeout_handler, (void *) d);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
BRD_AddDestination(IPAddr *addr, unsigned short port, int interval)
|
||||
{
|
||||
if (max_destinations == n_destinations) {
|
||||
/* Expand array */
|
||||
max_destinations += 8;
|
||||
if (destinations) {
|
||||
destinations = ReallocArray(Destination, max_destinations, destinations);
|
||||
} else {
|
||||
destinations = MallocArray(Destination, max_destinations);
|
||||
}
|
||||
}
|
||||
|
||||
destinations[n_destinations].addr.ip_addr = *addr;
|
||||
destinations[n_destinations].addr.local_ip_addr.family = IPADDR_UNSPEC;
|
||||
destinations[n_destinations].addr.port = port;
|
||||
destinations[n_destinations].interval = interval;
|
||||
|
||||
SCH_AddTimeoutInClass((double) interval, 1.0,
|
||||
SCH_NtpBroadcastClass,
|
||||
timeout_handler, (void *)(destinations + n_destinations));
|
||||
|
||||
++n_destinations;
|
||||
|
||||
}
|
||||
|
||||
|
||||
229
candm.h
229
candm.h
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/candm.h,v 1.40 2003/09/22 21:22:30 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
@@ -86,7 +82,16 @@
|
||||
#define REQ_MANUAL_DELETE 42
|
||||
#define REQ_MAKESTEP 43
|
||||
#define REQ_ACTIVITY 44
|
||||
#define N_REQUEST_TYPES 45
|
||||
#define REQ_MODIFY_MINSTRATUM 45
|
||||
#define REQ_MODIFY_POLLTARGET 46
|
||||
#define REQ_MODIFY_MAXDELAYDEVRATIO 47
|
||||
#define REQ_RESELECT 48
|
||||
#define REQ_RESELECTDISTANCE 49
|
||||
#define REQ_MODIFY_MAKESTEP 50
|
||||
#define REQ_SMOOTHING 51
|
||||
#define REQ_SMOOTHTIME 52
|
||||
#define REQ_REFRESH 53
|
||||
#define N_REQUEST_TYPES 54
|
||||
|
||||
/* Special utoken value used to log on with first exchange being the
|
||||
password. (This time value has long since gone by) */
|
||||
@@ -113,6 +118,10 @@ typedef struct {
|
||||
pktlength.c, to get the number of bytes that ought to be
|
||||
transmitted for each packet type. */
|
||||
|
||||
typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_Null;
|
||||
|
||||
typedef struct {
|
||||
IPAddr mask;
|
||||
IPAddr address;
|
||||
@@ -162,11 +171,35 @@ typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_Modify_Maxdelayratio;
|
||||
|
||||
typedef struct {
|
||||
IPAddr address;
|
||||
Float new_max_delay_dev_ratio;
|
||||
int32_t EOR;
|
||||
} REQ_Modify_Maxdelaydevratio;
|
||||
|
||||
typedef struct {
|
||||
IPAddr address;
|
||||
int32_t new_min_stratum;
|
||||
int32_t EOR;
|
||||
} REQ_Modify_Minstratum;
|
||||
|
||||
typedef struct {
|
||||
IPAddr address;
|
||||
int32_t new_poll_target;
|
||||
int32_t EOR;
|
||||
} REQ_Modify_Polltarget;
|
||||
|
||||
typedef struct {
|
||||
Float new_max_update_skew;
|
||||
int32_t EOR;
|
||||
} REQ_Modify_Maxupdateskew;
|
||||
|
||||
typedef struct {
|
||||
int32_t limit;
|
||||
Float threshold;
|
||||
int32_t EOR;
|
||||
} REQ_Modify_Makestep;
|
||||
|
||||
typedef struct {
|
||||
Timeval ts;
|
||||
int32_t EOR;
|
||||
@@ -188,19 +221,11 @@ typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_Manual;
|
||||
|
||||
typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_N_Sources;
|
||||
|
||||
typedef struct {
|
||||
int32_t index;
|
||||
int32_t EOR;
|
||||
} REQ_Source_Data;
|
||||
|
||||
typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_Rekey;
|
||||
|
||||
typedef struct {
|
||||
IPAddr ip;
|
||||
int32_t subnet_bits;
|
||||
@@ -215,6 +240,9 @@ typedef struct {
|
||||
/* Flags used in NTP source requests */
|
||||
#define REQ_ADDSRC_ONLINE 0x1
|
||||
#define REQ_ADDSRC_AUTOOFFLINE 0x2
|
||||
#define REQ_ADDSRC_IBURST 0x4
|
||||
#define REQ_ADDSRC_PREFER 0x8
|
||||
#define REQ_ADDSRC_NOSELECT 0x10
|
||||
|
||||
typedef struct {
|
||||
IPAddr ip_addr;
|
||||
@@ -234,10 +262,6 @@ typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_Del_Source;
|
||||
|
||||
typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_WriteRtc;
|
||||
|
||||
typedef struct {
|
||||
Float dfreq;
|
||||
int32_t EOR;
|
||||
@@ -249,70 +273,38 @@ typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_Doffset;
|
||||
|
||||
typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_Tracking;
|
||||
|
||||
typedef struct {
|
||||
uint32_t index;
|
||||
int32_t EOR;
|
||||
} REQ_Sourcestats;
|
||||
|
||||
typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_RTCReport;
|
||||
|
||||
typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_TrimRTC;
|
||||
|
||||
typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_CycleLogs;
|
||||
|
||||
typedef struct {
|
||||
IPAddr ip;
|
||||
uint32_t bits_specd;
|
||||
} REQ_SubnetsAccessed_Subnet;
|
||||
|
||||
#define MAX_SUBNETS_ACCESSED 8
|
||||
|
||||
typedef struct {
|
||||
uint32_t n_subnets;
|
||||
REQ_SubnetsAccessed_Subnet subnets[MAX_SUBNETS_ACCESSED];
|
||||
} REQ_SubnetsAccessed;
|
||||
|
||||
/* This is based on the response size rather than the
|
||||
request size */
|
||||
#define MAX_CLIENT_ACCESSES 8
|
||||
|
||||
typedef struct {
|
||||
uint32_t n_clients;
|
||||
IPAddr client_ips[MAX_CLIENT_ACCESSES];
|
||||
} REQ_ClientAccesses;
|
||||
|
||||
typedef struct {
|
||||
uint32_t first_index;
|
||||
uint32_t n_indices;
|
||||
int32_t EOR;
|
||||
} REQ_ClientAccessesByIndex;
|
||||
|
||||
typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_ManualList;
|
||||
|
||||
typedef struct {
|
||||
int32_t index;
|
||||
int32_t EOR;
|
||||
} REQ_ManualDelete;
|
||||
|
||||
typedef struct {
|
||||
Float distance;
|
||||
int32_t EOR;
|
||||
} REQ_MakeStep;
|
||||
} REQ_ReselectDistance;
|
||||
|
||||
#define REQ_SMOOTHTIME_RESET 0
|
||||
#define REQ_SMOOTHTIME_ACTIVATE 1
|
||||
|
||||
typedef struct {
|
||||
int32_t option;
|
||||
int32_t EOR;
|
||||
} REQ_Activity;
|
||||
} REQ_SmoothTime;
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
@@ -334,15 +326,33 @@ typedef struct {
|
||||
Version 4 : IPv6 addressing added, 64-bit time values, sourcestats
|
||||
and tracking reports extended, added flags to NTP source request,
|
||||
trimmed source report, replaced fixed-point format with floating-point
|
||||
and used also instead of integer microseconds
|
||||
and used also instead of integer microseconds, new commands: modify stratum,
|
||||
modify polltarget, modify maxdelaydevratio, reselect, reselectdistance
|
||||
|
||||
Version 5 : auth data moved to the end of the packet to allow hashes with
|
||||
different sizes, extended sources, tracking and activity reports, dropped
|
||||
subnets accessed and client accesses
|
||||
|
||||
Version 6 : added padding to requests to prevent amplification attack,
|
||||
changed maximum number of samples in manual list to 16, new commands: modify
|
||||
makestep, smoothing report, smoothtime command
|
||||
|
||||
Authentication was removed later in version 6.
|
||||
*/
|
||||
|
||||
#define PROTO_VERSION_NUMBER 4
|
||||
#define PROTO_VERSION_NUMBER 6
|
||||
|
||||
/* The oldest protocol version that is compatible enough with
|
||||
the current version to report a version mismatch */
|
||||
#define PROTO_VERSION_MISMATCH_COMPAT 4
|
||||
/* The oldest protocol versions that are compatible enough with the current
|
||||
version to report a version mismatch for the server and the client */
|
||||
#define PROTO_VERSION_MISMATCH_COMPAT_SERVER 5
|
||||
#define PROTO_VERSION_MISMATCH_COMPAT_CLIENT 4
|
||||
|
||||
/* The first protocol version using padding in requests */
|
||||
#define PROTO_VERSION_PADDING 6
|
||||
|
||||
/* The maximum length of padding in request packet, currently
|
||||
defined by CLIENT_ACCESSES_BY_INDEX and MANUAL_LIST */
|
||||
#define MAX_PADDING_LENGTH 396
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
@@ -356,11 +366,11 @@ typedef struct {
|
||||
(count up from zero for same sequence
|
||||
number) */
|
||||
uint32_t sequence; /* Client's sequence number */
|
||||
uint32_t utoken; /* Unique token per incarnation of daemon */
|
||||
uint32_t token; /* Command token (to prevent replay attack) */
|
||||
uint32_t auth[4]; /* MD5 authentication of the packet */
|
||||
uint32_t pad1;
|
||||
uint32_t pad2;
|
||||
|
||||
union {
|
||||
REQ_Null null;
|
||||
REQ_Online online;
|
||||
REQ_Offline offline;
|
||||
REQ_Burst burst;
|
||||
@@ -369,35 +379,33 @@ typedef struct {
|
||||
REQ_Dump dump;
|
||||
REQ_Modify_Maxdelay modify_maxdelay;
|
||||
REQ_Modify_Maxdelayratio modify_maxdelayratio;
|
||||
REQ_Modify_Maxdelaydevratio modify_maxdelaydevratio;
|
||||
REQ_Modify_Minstratum modify_minstratum;
|
||||
REQ_Modify_Polltarget modify_polltarget;
|
||||
REQ_Modify_Maxupdateskew modify_maxupdateskew;
|
||||
REQ_Modify_Makestep modify_makestep;
|
||||
REQ_Logon logon;
|
||||
REQ_Settime settime;
|
||||
REQ_Local local;
|
||||
REQ_Manual manual;
|
||||
REQ_N_Sources n_sources;
|
||||
REQ_Source_Data source_data;
|
||||
REQ_Rekey rekey;
|
||||
REQ_Allow_Deny allow_deny;
|
||||
REQ_Ac_Check ac_check;
|
||||
REQ_NTP_Source ntp_source;
|
||||
REQ_Del_Source del_source;
|
||||
REQ_WriteRtc writertc;
|
||||
REQ_Dfreq dfreq;
|
||||
REQ_Doffset doffset;
|
||||
REQ_Tracking tracking;
|
||||
REQ_Sourcestats sourcestats;
|
||||
REQ_RTCReport rtcreport;
|
||||
REQ_TrimRTC trimrtc;
|
||||
REQ_CycleLogs cyclelogs;
|
||||
REQ_SubnetsAccessed subnets_accessed;
|
||||
REQ_ClientAccesses client_accesses;
|
||||
REQ_ClientAccessesByIndex client_accesses_by_index;
|
||||
REQ_ManualList manual_list;
|
||||
REQ_ManualDelete manual_delete;
|
||||
REQ_MakeStep make_step;
|
||||
REQ_Activity activity;
|
||||
REQ_ReselectDistance reselect_distance;
|
||||
REQ_SmoothTime smoothtime;
|
||||
} data; /* Command specific parameters */
|
||||
|
||||
/* Padding used to prevent traffic amplification. It only defines the
|
||||
maximum size of the packet, there is no hole after the data field. */
|
||||
uint8_t padding[MAX_PADDING_LENGTH];
|
||||
|
||||
} CMD_Request;
|
||||
|
||||
/* ================================================== */
|
||||
@@ -422,7 +430,8 @@ typedef struct {
|
||||
#define RPY_CLIENT_ACCESSES_BY_INDEX 10
|
||||
#define RPY_MANUAL_LIST 11
|
||||
#define RPY_ACTIVITY 12
|
||||
#define N_REPLY_TYPES 13
|
||||
#define RPY_SMOOTHING 13
|
||||
#define N_REPLY_TYPES 14
|
||||
|
||||
/* Status codes */
|
||||
#define STT_SUCCESS 0
|
||||
@@ -435,6 +444,7 @@ typedef struct {
|
||||
#define STT_BADSUBNET 7
|
||||
#define STT_ACCESSALLOWED 8
|
||||
#define STT_ACCESSDENIED 9
|
||||
/* Deprecated */
|
||||
#define STT_NOHOSTACCESS 10
|
||||
#define STT_SOURCEALREADYKNOWN 11
|
||||
#define STT_TOOMANYSOURCES 12
|
||||
@@ -463,14 +473,20 @@ typedef struct {
|
||||
#define RPY_SD_ST_UNREACH 1
|
||||
#define RPY_SD_ST_FALSETICKER 2
|
||||
#define RPY_SD_ST_JITTERY 3
|
||||
#define RPY_SD_ST_OTHER 4
|
||||
#define RPY_SD_ST_CANDIDATE 4
|
||||
#define RPY_SD_ST_OUTLIER 5
|
||||
|
||||
#define RPY_SD_FLAG_NOSELECT 0x1
|
||||
#define RPY_SD_FLAG_PREFER 0x2
|
||||
|
||||
typedef struct {
|
||||
IPAddr ip_addr;
|
||||
uint16_t poll;
|
||||
int16_t poll;
|
||||
uint16_t stratum;
|
||||
uint16_t state;
|
||||
uint16_t mode;
|
||||
uint16_t flags;
|
||||
uint16_t reachability;
|
||||
uint32_t since_sample;
|
||||
Float orig_latest_meas;
|
||||
Float latest_meas;
|
||||
@@ -481,14 +497,18 @@ typedef struct {
|
||||
typedef struct {
|
||||
uint32_t ref_id;
|
||||
IPAddr ip_addr;
|
||||
uint32_t stratum;
|
||||
uint16_t stratum;
|
||||
uint16_t leap_status;
|
||||
Timeval ref_time;
|
||||
Float current_correction;
|
||||
Float last_offset;
|
||||
Float rms_offset;
|
||||
Float freq_ppm;
|
||||
Float resid_freq_ppm;
|
||||
Float skew_ppm;
|
||||
Float root_delay;
|
||||
Float root_dispersion;
|
||||
Float last_update_interval;
|
||||
int32_t EOR;
|
||||
} RPY_Tracking;
|
||||
|
||||
@@ -523,17 +543,6 @@ typedef struct {
|
||||
int32_t EOR;
|
||||
} RPY_ManualTimestamp;
|
||||
|
||||
typedef struct {
|
||||
IPAddr ip;
|
||||
uint32_t bits_specd;
|
||||
uint32_t bitmap[8];
|
||||
} RPY_SubnetsAccessed_Subnet;
|
||||
|
||||
typedef struct {
|
||||
uint32_t n_subnets;
|
||||
RPY_SubnetsAccessed_Subnet subnets[MAX_SUBNETS_ACCESSED];
|
||||
} RPY_SubnetsAccessed;
|
||||
|
||||
typedef struct {
|
||||
IPAddr ip;
|
||||
uint32_t client_hits;
|
||||
@@ -545,19 +554,15 @@ typedef struct {
|
||||
uint32_t last_cmd_hit_ago;
|
||||
} RPY_ClientAccesses_Client;
|
||||
|
||||
typedef struct {
|
||||
uint32_t n_clients;
|
||||
RPY_ClientAccesses_Client clients[MAX_CLIENT_ACCESSES];
|
||||
} RPY_ClientAccesses;
|
||||
|
||||
typedef struct {
|
||||
uint32_t n_indices; /* how many indices there are in the server's table */
|
||||
uint32_t next_index; /* the index 1 beyond those processed on this call */
|
||||
uint32_t n_clients; /* the number of valid entries in the following array */
|
||||
RPY_ClientAccesses_Client clients[MAX_CLIENT_ACCESSES];
|
||||
int32_t EOR;
|
||||
} RPY_ClientAccessesByIndex;
|
||||
|
||||
#define MAX_MANUAL_LIST_SAMPLES 32
|
||||
#define MAX_MANUAL_LIST_SAMPLES 16
|
||||
|
||||
typedef struct {
|
||||
Timeval when;
|
||||
@@ -569,6 +574,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
uint32_t n_samples;
|
||||
RPY_ManualListSample samples[MAX_MANUAL_LIST_SAMPLES];
|
||||
int32_t EOR;
|
||||
} RPY_ManualList;
|
||||
|
||||
typedef struct {
|
||||
@@ -576,9 +582,23 @@ typedef struct {
|
||||
int32_t offline;
|
||||
int32_t burst_online;
|
||||
int32_t burst_offline;
|
||||
int32_t unresolved;
|
||||
int32_t EOR;
|
||||
} RPY_Activity;
|
||||
|
||||
#define RPY_SMT_FLAG_ACTIVE 0x1
|
||||
#define RPY_SMT_FLAG_LEAPONLY 0x2
|
||||
|
||||
typedef struct {
|
||||
uint32_t flags;
|
||||
Float offset;
|
||||
Float freq_ppm;
|
||||
Float wander_ppm;
|
||||
Float last_update_ago;
|
||||
Float remaining_time;
|
||||
int32_t EOR;
|
||||
} RPY_Smoothing;
|
||||
|
||||
typedef struct {
|
||||
uint8_t version;
|
||||
uint8_t pkt_type;
|
||||
@@ -587,14 +607,12 @@ typedef struct {
|
||||
uint16_t command; /* Which command is being replied to */
|
||||
uint16_t reply; /* Which format of reply this is */
|
||||
uint16_t status; /* Status of command processing */
|
||||
uint16_t number; /* Which packet this is in reply sequence */
|
||||
uint16_t total; /* Number of replies to expect in this sequence */
|
||||
uint16_t pad1; /* Get up to 4 byte alignment */
|
||||
uint16_t pad1; /* Padding for compatibility and 4 byte alignment */
|
||||
uint16_t pad2;
|
||||
uint16_t pad3;
|
||||
uint32_t sequence; /* Echo of client's sequence number */
|
||||
uint32_t utoken; /* Unique token per incarnation of daemon */
|
||||
uint32_t token; /* New command token (only if command was successfully
|
||||
authenticated) */
|
||||
uint32_t auth[4]; /* MD5 authentication of the packet */
|
||||
uint32_t pad4;
|
||||
uint32_t pad5;
|
||||
|
||||
union {
|
||||
RPY_Null null;
|
||||
@@ -604,11 +622,10 @@ typedef struct {
|
||||
RPY_Tracking tracking;
|
||||
RPY_Sourcestats sourcestats;
|
||||
RPY_Rtc rtc;
|
||||
RPY_SubnetsAccessed subnets_accessed;
|
||||
RPY_ClientAccesses client_accesses;
|
||||
RPY_ClientAccessesByIndex client_accesses_by_index;
|
||||
RPY_ManualList manual_list;
|
||||
RPY_Activity activity;
|
||||
RPY_Smoothing smoothing;
|
||||
} data; /* Reply specific parameters */
|
||||
|
||||
} CMD_Reply;
|
||||
|
||||
70
chrony.1
70
chrony.1
@@ -1,70 +0,0 @@
|
||||
.TH CHRONY 1 "December 04, 2009" chrony "User's Manual"
|
||||
.SH NAME
|
||||
chrony \- programs for keeping computer clocks accurate
|
||||
|
||||
.SH SYNOPSIS
|
||||
\fBchronyc\fR [\fIOPTIONS\fR]
|
||||
|
||||
\fBchronyd\fR [\fIOPTIONS\fR]
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBchrony\fR is a pair of programs for keeping computer clocks accurate.
|
||||
\fIchronyd\fR is a background (daemon) program and \fIchronyc\fR is a
|
||||
command-line interface to it. Time reference sources for chronyd can be
|
||||
RFC1305 NTP servers, human (via keyboard and \fIchronyc\fR), or the computer's
|
||||
real-time clock at boot time (Linux only). chronyd can determine the rate at
|
||||
which the computer gains or loses time and compensate for it while no external
|
||||
reference is present. Its use of NTP servers can be switched on and off
|
||||
(through \fIchronyc\fR) to support computers with dial-up/intermittent access
|
||||
to the Internet, and it can also act as an RFC1305-compatible NTP server.
|
||||
|
||||
.SH USAGE
|
||||
\fIchronyc\fR is a command-line interface program which can be used to
|
||||
monitor \fIchronyd\fR's performance and to change various operating
|
||||
parateters whilst it is running.
|
||||
|
||||
\fIchronyd\fR's main function is to obtain measurements of the true (UTC)
|
||||
time from one of several sources, and correct the system clock
|
||||
accordingly. It also works out the rate at which the system clock
|
||||
gains or loses time and uses this information to keep it accurate
|
||||
between measurements from the reference.
|
||||
|
||||
The reference time can be derived from either Network Time Protocol
|
||||
(NTP) servers, reference clocks, or wristwatch-and-keyboard (via \fIchronyc\fR).
|
||||
The main source of information about the Network Time Protocol is
|
||||
\fIhttp://www.eecis.udel.edu/~ntp\fR.
|
||||
|
||||
It is designed so that it can work on computers which only have
|
||||
intermittent access to reference sources, for example computers which
|
||||
use a dial-up account to access the Internet. Of course, it will work
|
||||
on computers with permanent connections too.
|
||||
|
||||
In addition, for Linux 2.0.x (for x >= 32) or 2.2 onwards, chronyd can monitor
|
||||
the system's real time clock performance, so the system can maintain accurate
|
||||
time even across reboots.
|
||||
|
||||
Typical accuracies available between 2 machines are
|
||||
|
||||
On an ethernet LAN : 100-200 microseconds, often much better
|
||||
On a V32bis dial-up modem connection : 10's of milliseconds (from one
|
||||
session to the next)
|
||||
|
||||
With a good reference clock the accuracy can reach one microsecond.
|
||||
|
||||
\fIchronyd\fR can also operate as an RFC1305-compatible NTP server and peer.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR chronyc(1),
|
||||
.BR chrony(1)
|
||||
|
||||
.I http://chrony.tuxfamily.org/
|
||||
|
||||
.SH AUTHOR
|
||||
Richard Curnow <rc@rc0.org.uk>
|
||||
|
||||
This man-page was written by Jan Schaumann <jschauma@netmeister.org> as part
|
||||
of "The Missing Man Pages Project". Please see
|
||||
\fIhttp://www.netmeister.org/misc/m2p2/index.html\fR for details.
|
||||
|
||||
The complete chrony documentation is supplied in texinfo format.
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
.TH chrony.conf 5 "December 04, 2009" chrony "Configuration Files"
|
||||
.SH NAME
|
||||
chrony.conf \- chronyd configuration file
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B /etc/chrony.conf
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fIchrony\fR is a pair of programs for maintaining the accuracy of computer
|
||||
clocks. \fIchronyd\fR is a background daemon program that can be started at
|
||||
boot time.
|
||||
|
||||
Assuming that you have found some servers, you need to set up a
|
||||
configuration file to run \fIchrony\fR. The (compiled-in) default location
|
||||
for this file is \fB/etc/chrony.conf\fR. Assuming that your ntp servers
|
||||
are called `a.b.c' and `d.e.f', your \fBchrony.conf\fR file could contain
|
||||
as a minimum
|
||||
|
||||
server a.b.c
|
||||
server d.e.f
|
||||
server g.h.i
|
||||
|
||||
However, you will probably want to include some of the other directives
|
||||
described in detail in the documentation supplied with the distribution
|
||||
(\fIchrony.txt\fR and \fIchrony.texi\fR). The following directives will be
|
||||
particularly useful : `driftfile', `commandkey', `keyfile'. The smallest
|
||||
useful configuration file would look something like
|
||||
|
||||
server a.b.c
|
||||
server d.e.f
|
||||
server g.h.i
|
||||
keyfile /etc/chrony.keys
|
||||
commandkey 1
|
||||
driftfile /etc/chrony.drift
|
||||
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR chrony(1),
|
||||
.BR chronyc(1),
|
||||
.BR chronyd(8)
|
||||
|
||||
.I http://chrony.tuxfamily.org/
|
||||
|
||||
.SH AUTHOR
|
||||
Richard Curnow <rc@rc0.org.uk>
|
||||
|
||||
This man-page was written by Jan Schaumann <jschauma@netmeister.org> as part of "The Missing
|
||||
Man Pages Project". Please see \fIhttp://www.netmeister.org/misc/m2p2/index.html\fR
|
||||
for details.
|
||||
|
||||
The complete chrony documentation is supplied in texinfo format.
|
||||
|
||||
67
chrony.conf.5.in
Normal file
67
chrony.conf.5.in
Normal file
@@ -0,0 +1,67 @@
|
||||
.TH chrony.conf 5 "@MAN_DATE@" "chrony @VERSION@" "Configuration Files"
|
||||
.SH NAME
|
||||
chrony.conf \- chronyd configuration file
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B @SYSCONFDIR@/chrony.conf
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fIchrony\fR is a pair of programs for maintaining the accuracy of computer
|
||||
clocks. \fIchronyd\fR is a background daemon program that can be started at
|
||||
boot time.
|
||||
|
||||
Assuming that you have found some servers, you need to set up a
|
||||
configuration file to run \fIchrony\fR. The (compiled-in) default location
|
||||
for this file is \fB@SYSCONFDIR@/chrony.conf\fR. Assuming that your NTP
|
||||
servers are called `foo.example.net', `bar.example.net' and `baz.example.net',
|
||||
your \fBchrony.conf\fR file could contain as a minimum
|
||||
|
||||
.EX
|
||||
server foo.example.net
|
||||
server bar.example.net
|
||||
server baz.example.net
|
||||
.EE
|
||||
|
||||
However, you will probably want to include some of the other directives
|
||||
described in detail in the documentation supplied with the distribution
|
||||
(\fIchrony.txt\fR and \fIchrony.texi\fR). The following directives may be
|
||||
particularly useful : `driftfile', `makestep', `rtcsync'. Also, the `iburst'
|
||||
server option is useful to speed up the initial synchronization. The smallest
|
||||
useful configuration file would look something like
|
||||
|
||||
.EX
|
||||
server foo.example.net iburst
|
||||
server bar.example.net iburst
|
||||
server baz.example.net iburst
|
||||
driftfile @CHRONYVARDIR@/drift
|
||||
makestep 1.0 3
|
||||
rtcsync
|
||||
.EE
|
||||
|
||||
When using a pool of NTP servers (one name is used for multiple servers which
|
||||
may change over time), it's better to specify them with the `pool' directive
|
||||
instead of multiple `server' directives. The configuration file could in this
|
||||
case look like
|
||||
|
||||
.EX
|
||||
pool pool.ntp.org iburst
|
||||
driftfile @CHRONYVARDIR@/drift
|
||||
makestep 1.0 3
|
||||
rtcsync
|
||||
.EE
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR chronyc(1),
|
||||
.BR chronyd(8)
|
||||
|
||||
.I http://chrony.tuxfamily.org/
|
||||
|
||||
.SH AUTHOR
|
||||
Richard Curnow <rc@rc0.org.uk>
|
||||
|
||||
This man-page was written by Jan Schaumann <jschauma@netmeister.org> as part of "The Missing
|
||||
Man Pages Project". Please see \fIhttp://www.netmeister.org/misc/m2p2/index.html\fR
|
||||
for details.
|
||||
|
||||
The complete chrony documentation is supplied in texinfo format.
|
||||
|
||||
29
chrony.lsm
29
chrony.lsm
@@ -1,29 +0,0 @@
|
||||
Begin3
|
||||
Title: chrony
|
||||
Version: 1.18
|
||||
Entered-date: 01APR02
|
||||
Description: A pair of programs for keeping computer clocks accurate.
|
||||
chronyd is a background (daemon) program and chronyc is a
|
||||
command-line interface to it. Time reference sources for
|
||||
chronyd can be RFC1305 NTP servers, human (via keyboard and
|
||||
chronyc), and the computer's real-time clock at boot time
|
||||
(Linux only). chronyd can determine the rate at which the
|
||||
computer gains or loses time and compensate for it whilst no
|
||||
external reference is present. chronyd's use of NTP servers
|
||||
can be switched on and off (through chronyc) to support
|
||||
computers with dial-up/intermittent access to the
|
||||
Internet. chronyd can also act as an RFC1305-compatible NTP
|
||||
server.
|
||||
Keywords: time NTP RFC1305 RTC adjtime
|
||||
Author: rc@rc0.org.uk (Richard Curnow)
|
||||
Maintained-by: rc@rc0.org.uk (Richard Curnow)
|
||||
Primary-site: chrony.tuxfamily.org
|
||||
295k chrony-1.18.tar.gz
|
||||
2k chrony.lsm
|
||||
Platforms: Linux 2.0/2.1/2.2/2.3/2.4 (x86, powerpc)
|
||||
Solaris 2.5/6/7/8, SunOS 4.1.4. (Sparc)
|
||||
BSDI/386.
|
||||
NetBSD
|
||||
Solaris 2.8 (x86)
|
||||
Copying-policy: GPL
|
||||
End
|
||||
@@ -1,52 +0,0 @@
|
||||
Summary: An NTP client/server
|
||||
Name: chrony
|
||||
Version: @@VERSION@@
|
||||
Release: 1
|
||||
Source: chrony-%{version}.tar.gz
|
||||
Copyright: GPL
|
||||
Group: Applications/Utilities
|
||||
Packager: Richard P. Curnow <rc@rc0.org.uk>
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-root-%(id -u -n)
|
||||
Requires: info
|
||||
|
||||
%description
|
||||
A pair of programs for keeping computer clocks accurate. chronyd is a
|
||||
background (daemon) program and chronyc is a command-line interface to it.
|
||||
Time reference sources for chronyd can be RFC1305 NTP servers, human (via
|
||||
keyboard and chronyc), and the computer's real-time clock at boot time (Linux
|
||||
only). chronyd can determine the rate at which the computer gains or loses
|
||||
time and compensate for it whilst no external reference is present. chronyd's
|
||||
use of NTP servers can be switched on and off (through chronyc) to support
|
||||
computers with dial-up/intermittent access to the Internet. chronyd can also
|
||||
act as an RFC1305-compatible NTP server.
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
./configure --prefix=%{_prefix} --mandir=%{_mandir}
|
||||
make CC=gcc CFLAGS=-O2 prefix=%{_prefix}
|
||||
make chrony.txt prefix=%{_prefix}
|
||||
make chrony.info prefix=%{_prefix}
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
cd $RPM_BUILD_DIR/chrony-%{version}
|
||||
make install DESTDIR=$RPM_BUILD_ROOT prefix=%{_prefix}
|
||||
mkdir -p $RPM_BUILD_ROOT%{_infodir}
|
||||
cp chrony.info* $RPM_BUILD_ROOT%{_infodir}
|
||||
|
||||
%files
|
||||
%{_sbindir}/chronyd
|
||||
%{_bindir}/chronyc
|
||||
%{_infodir}/chrony.info*
|
||||
%{_mandir}/man1/chrony.1.gz
|
||||
%{_mandir}/man1/chronyc.1.gz
|
||||
%{_mandir}/man5/chrony.conf.5.gz
|
||||
%{_mandir}/man8/chronyd.8.gz
|
||||
%doc README
|
||||
%doc chrony.txt
|
||||
%doc COPYING
|
||||
%doc examples/chrony.conf.example
|
||||
%doc examples/chrony.keys.example
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,67 +0,0 @@
|
||||
/* Taken from /usr/include/linux/timex.h. Avoids the need to
|
||||
* include kernel header files. */
|
||||
|
||||
#ifndef CHRONY_TIMEX_H
|
||||
#define CHRONY_TIMEX_H
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
struct timex {
|
||||
unsigned int modes; /* mode selector */
|
||||
long offset; /* time offset (usec) */
|
||||
long freq; /* frequency offset (scaled ppm) */
|
||||
long maxerror; /* maximum error (usec) */
|
||||
long esterror; /* estimated error (usec) */
|
||||
int status; /* clock command/status */
|
||||
long constant; /* pll time constant */
|
||||
long precision; /* clock precision (usec) (read only) */
|
||||
long tolerance; /* clock frequency tolerance (ppm)
|
||||
* (read only)
|
||||
*/
|
||||
struct timeval time; /* (read only) */
|
||||
long tick; /* (modified) usecs between clock ticks */
|
||||
|
||||
long ppsfreq; /* pps frequency (scaled ppm) (ro) */
|
||||
long jitter; /* pps jitter (us) (ro) */
|
||||
int shift; /* interval duration (s) (shift) (ro) */
|
||||
long stabil; /* pps stability (scaled ppm) (ro) */
|
||||
long jitcnt; /* jitter limit exceeded (ro) */
|
||||
long calcnt; /* calibration intervals (ro) */
|
||||
long errcnt; /* calibration errors (ro) */
|
||||
long stbcnt; /* stability limit exceeded (ro) */
|
||||
|
||||
int :32; int :32; int :32; int :32;
|
||||
int :32; int :32; int :32; int :32;
|
||||
int :32; int :32; int :32; int :32;
|
||||
};
|
||||
|
||||
#define ADJ_FREQUENCY 0x0002 /* frequency offset */
|
||||
#define ADJ_STATUS 0x0010 /* clock status */
|
||||
#define ADJ_TICK 0x4000 /* tick value */
|
||||
#define ADJ_OFFSET_SINGLESHOT 0x8001 /* old-fashioned adjtime */
|
||||
#define ADJ_OFFSET_SS_READ 0xa001 /* read-only adjtime */
|
||||
|
||||
#define SHIFT_USEC 16 /* frequency offset scale (shift) */
|
||||
|
||||
#define STA_PLL 0x0001 /* enable PLL updates (rw) */
|
||||
#define STA_PPSFREQ 0x0002 /* enable PPS freq discipline (rw) */
|
||||
#define STA_PPSTIME 0x0004 /* enable PPS time discipline (rw) */
|
||||
#define STA_FLL 0x0008 /* select frequency-lock mode (rw) */
|
||||
|
||||
#define STA_INS 0x0010 /* insert leap (rw) */
|
||||
#define STA_DEL 0x0020 /* delete leap (rw) */
|
||||
#define STA_UNSYNC 0x0040 /* clock unsynchronized (rw) */
|
||||
#define STA_FREQHOLD 0x0080 /* hold frequency (rw) */
|
||||
|
||||
#define STA_PPSSIGNAL 0x0100 /* PPS signal present (ro) */
|
||||
#define STA_PPSJITTER 0x0200 /* PPS signal jitter exceeded (ro) */
|
||||
#define STA_PPSWANDER 0x0400 /* PPS signal wander exceeded (ro) */
|
||||
#define STA_PPSERROR 0x0800 /* PPS signal calibration error (ro) */
|
||||
|
||||
#define STA_CLOCKERR 0x1000 /* clock hardware fault (ro) */
|
||||
|
||||
/* This doesn't seem to be in any include files !! */
|
||||
|
||||
extern int adjtimex(struct timex *);
|
||||
|
||||
#endif /* CHRONY_TIMEX_H */
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH CHRONYC 1 "December 04, 2009" chrony "User's Manual"
|
||||
.TH CHRONYC 1 "@MAN_DATE@" "chrony @VERSION@" "User's Manual"
|
||||
.SH NAME
|
||||
chronyc \- command-line interface for chronyd
|
||||
|
||||
@@ -12,7 +12,7 @@ clocks.
|
||||
|
||||
\fBchronyc\fR is a command-line interface program which can be used to
|
||||
monitor \fIchronyd\fR's performance and to change various operating
|
||||
parateters whilst it is running.
|
||||
parameters whilst it is running.
|
||||
|
||||
.SH USAGE
|
||||
A detailed description of all commands supported by \fBchronyc\fR is available
|
||||
@@ -24,7 +24,8 @@ A summary of the options supported by \fBchronyc\fR is included below.
|
||||
|
||||
.TP
|
||||
\fB\-h\fR \fIhostname\fR
|
||||
specify hostname
|
||||
specify hostname or comma-separated list of addresses
|
||||
(default @CHRONYSOCKDIR@/chronyd.sock,127.0.0.1,::1)
|
||||
.TP
|
||||
\fB\-p\fR \fIport-number\fR
|
||||
specify port-number
|
||||
@@ -32,26 +33,34 @@ specify port-number
|
||||
\fB\-n\fR
|
||||
display raw IP addresses (don't attempt to look up hostnames)
|
||||
.TP
|
||||
\fB\-d\fR
|
||||
print debugging messages (if compiled with debugging support)
|
||||
.TP
|
||||
\fB\-4\fR
|
||||
resolve hostnames only to IPv4 addresses
|
||||
.TP
|
||||
\fB\-6\fR
|
||||
resolve hostnames only to IPv6 addresses
|
||||
.TP
|
||||
\fB\-m\fR
|
||||
allow multiple commands to be specified on the command line. Each argument
|
||||
will be interpreted as a whole command.
|
||||
.TP
|
||||
\fB\-f\fR \fIconf-file\fR
|
||||
this option is ignored and is provided only for compatibility.
|
||||
.TP
|
||||
\fB\-a\fR
|
||||
this option is ignored and is provided only for compatibility.
|
||||
.TP
|
||||
\fIcommand\fR
|
||||
specify command. If no command is given, chronyc will read commands
|
||||
interactively.
|
||||
|
||||
|
||||
.SH VERSION
|
||||
1.24
|
||||
|
||||
.SH BUGS
|
||||
To report bugs, please visit \fIhttp://chrony.tuxfamily.org\fR
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR chronyd(8),
|
||||
.BR chrony(1)
|
||||
.BR chronyd(8)
|
||||
|
||||
.I http://chrony.tuxfamily.org/
|
||||
|
||||
@@ -63,4 +72,3 @@ Man Pages Project". Please see \fIhttp://www.netmeister.org/misc/m2p2/index.htm
|
||||
for details.
|
||||
|
||||
The complete chrony documentation is supplied in texinfo format.
|
||||
|
||||
133
chronyd.8
133
chronyd.8
@@ -1,133 +0,0 @@
|
||||
.TH CHRONYD 8 "December 04, 2009" chrony "System Administration"
|
||||
.SH NAME
|
||||
chronyd \- chrony background daemon
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B chronyd
|
||||
[\fIOPTIONS\fR]
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fIchrony\fR is a pair of programs for maintaining the accuracy of computer
|
||||
clocks. \fBchronyd\fR is a background daemon program that can be started at boot
|
||||
time.
|
||||
|
||||
\fBchronyd\fR is a daemon which runs in background on the
|
||||
system. It obtains measurements (e.g. via the network) of the
|
||||
system's offset relative to other systems, and adjusts the system
|
||||
time accordingly. For isolated systems, the user can periodically
|
||||
enter the correct time by hand (using \fIchronyc\fR). In either case,
|
||||
\fBchronyd\fR determines the rate at which the computer
|
||||
gains or loses time, and compensates for this.
|
||||
|
||||
.SH USAGE
|
||||
\fBchronyd\fR is usually started at boot-time and requires superuser
|
||||
priviliges.
|
||||
|
||||
If \fBchronyd\fR has been installed to its default location
|
||||
\fI/usr/local/sbin/chronyd\fR, starting it is simply a matter of entering the
|
||||
command:
|
||||
|
||||
\fI/usr/local/sbin/chronyd\fR
|
||||
|
||||
Information messages and warnings will be logged to syslog.
|
||||
|
||||
|
||||
.SH OPTIONS
|
||||
A summary of the options supported by \fBchronyd\fR is included below.
|
||||
|
||||
.TP
|
||||
\fB\-P\fR \fIpriority\fR
|
||||
This option will select the SCHED_FIFO real-time scheduler at the specified
|
||||
priority (which must be between 0 and 100). This mode is supported only on
|
||||
Linux.
|
||||
.TP
|
||||
.B \-m
|
||||
This option will lock chronyd into RAM so that it will never be paged out.
|
||||
This mode is only supported on Linux.
|
||||
.TP
|
||||
.B \-d
|
||||
When run in this mode, the program will not detach itself from the
|
||||
terminal, and all messages will be sent to the terminal instead of
|
||||
to syslog.
|
||||
.TP
|
||||
\fB\-f\fR \fIconf-file\fR
|
||||
This option can be used to specify an alternate location for the
|
||||
configuration file (default \fI/etc/chrony.conf\fR).
|
||||
.TP
|
||||
.B \-r
|
||||
This option will reload sample histories for each of the servers being used.
|
||||
These histories are created by using the \fIdump\fR command in \fIchronyc\fR,
|
||||
or by setting the \fIdumponexit\fR directive in the configuration file. This
|
||||
option is useful if you want to stop and restart \fBchronyd\fR briefly for any
|
||||
reason, e.g. to install a new version. However, it only makes sense on
|
||||
systems where the kernel can maintain clock compensation whilst not under
|
||||
\fBchronyd\fR's control. The only version where this happens so far is Linux.
|
||||
On systems where this is not the case, e.g. Solaris and SunOS the option
|
||||
should not be used.
|
||||
.TP
|
||||
.B \-s
|
||||
This option will set the system clock from the computer's real-time
|
||||
clock. This is analogous to supplying the \fI-s\fR flag to the
|
||||
\fI/sbin/clock\fR program during the Linux boot sequence.
|
||||
|
||||
Support for real-time clocks is limited at present - the criteria
|
||||
are described in the section on the \fIrtcfile\fR directive in the
|
||||
documentation supplied with the distribution.
|
||||
|
||||
If \fBchronyd\fR cannot support the real time clock on your computer,
|
||||
this option cannot be used and a warning message will be logged to
|
||||
the syslog.
|
||||
|
||||
If used in conjunction with the \fB-r\fR flag, \fBchronyd\fR will attempt
|
||||
to preserve the old samples after setting the system clock from
|
||||
the real time clock. This can be used to allow \fBchronyd\fR to
|
||||
perform long term averaging of the gain or loss rate across system
|
||||
reboots, and is useful for dial-up systems that are shut down when
|
||||
not in use. For this to work well, it relies on \fBchronyd\fR having
|
||||
been able to determine accurate statistics for the difference
|
||||
between the real time clock and system clock last time the
|
||||
computer was on.
|
||||
.TP
|
||||
\fB\-u\fR \fIuser\fR
|
||||
When this option is used, chronyd will drop root privileges to the specified
|
||||
user. So far, it works only on Linux when compiled with capabilities support.
|
||||
.TP
|
||||
.B \-v
|
||||
This option displays \fBchronyd\fR's version number to the terminal and exits
|
||||
.TP
|
||||
.B \-4
|
||||
Resolve hostnames only to IPv4 addresses.
|
||||
.TP
|
||||
.B \-6
|
||||
Resolve hostnames only to IPv6 addresses.
|
||||
|
||||
.SH FILES
|
||||
\fI/etc/chrony.conf\fR
|
||||
|
||||
.SH VERSION
|
||||
Version 1.24
|
||||
|
||||
.SH BUGS
|
||||
To report bugs, please visit \fIhttp://chrony.tuxfamily.org/\fR
|
||||
|
||||
.SH "SEE ALSO"
|
||||
\fBchronyd\fR is documented in detail in the documentation supplied with the
|
||||
distribution (\fIchrony.txt\fR and \fIchrony.texi\fR) and is also available
|
||||
from \fIhttp://go.to/chrony\fR
|
||||
|
||||
.BR chrony(1),
|
||||
.BR chronyc(1),
|
||||
.BR chrony.conf(5),
|
||||
.BR clock(8),
|
||||
.BR xntpd(8),
|
||||
.BR ntpd(8)
|
||||
|
||||
.SH AUTHOR
|
||||
Richard Curnow <rc@rc0.org.uk>
|
||||
|
||||
This man-page was written by Jan Schaumann <jschauma@netmeister.org> as part
|
||||
of "The Missing Man Pages Project". Please see
|
||||
\fIhttp://www.netmeister.org/misc/m2p2/index.html\fR for details.
|
||||
|
||||
The complete chrony documentation is supplied in texinfo format.
|
||||
|
||||
156
chronyd.8.in
Normal file
156
chronyd.8.in
Normal file
@@ -0,0 +1,156 @@
|
||||
.TH CHRONYD 8 "@MAN_DATE@" "chrony @VERSION@" "System Administration"
|
||||
.SH NAME
|
||||
chronyd \- chrony background daemon
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B chronyd
|
||||
[\fIOPTIONS\fR] [\fIconfiguration commands\fR]
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fIchrony\fR is a pair of programs for maintaining the accuracy of computer
|
||||
clocks. \fBchronyd\fR is a background daemon program that can be started at boot
|
||||
time.
|
||||
|
||||
\fBchronyd\fR is a daemon which runs in background on the
|
||||
system. It obtains measurements (e.g. via the network) of the
|
||||
system's offset relative to other systems, and adjusts the system
|
||||
time accordingly. For isolated systems, the user can periodically
|
||||
enter the correct time by hand (using \fIchronyc\fR). In either case,
|
||||
\fBchronyd\fR determines the rate at which the computer
|
||||
gains or loses time, and compensates for this.
|
||||
|
||||
.SH USAGE
|
||||
\fBchronyd\fR is usually started at boot-time and requires superuser
|
||||
privileges.
|
||||
|
||||
If \fBchronyd\fR has been installed to its default location
|
||||
\fI@SBINDIR@/chronyd\fR, starting it is simply a matter of entering the
|
||||
command:
|
||||
|
||||
\fI@SBINDIR@/chronyd\fR
|
||||
|
||||
Information messages and warnings will be logged to syslog.
|
||||
|
||||
If no configuration commands are specified on the command line,
|
||||
\fBchronyd\fR will read the commands from the configuration file
|
||||
(default \fI@SYSCONFDIR@/chrony.conf\fR).
|
||||
|
||||
.SH OPTIONS
|
||||
A summary of the options supported by \fBchronyd\fR is included below.
|
||||
|
||||
.TP
|
||||
\fB\-P\fR \fIpriority\fR
|
||||
On Linux, this option will select the SCHED_FIFO real-time scheduler at the
|
||||
specified priority (which must be between 0 and 100). On Mac OS X, this
|
||||
option must have either a value of 0 (the default) to disable the thread
|
||||
time constraint policy or 1 for the policy to be enabled. Other systems do not
|
||||
support this option.
|
||||
.TP
|
||||
.B \-m
|
||||
This option will lock chronyd into RAM so that it will never be paged out.
|
||||
This mode is only supported on Linux.
|
||||
.TP
|
||||
.B \-n
|
||||
When run in this mode, the program will not detach itself from the
|
||||
terminal.
|
||||
.TP
|
||||
.B \-d
|
||||
When run in this mode, the program will not detach itself from the
|
||||
terminal, and all messages will be sent to the terminal instead of
|
||||
to syslog. When \fBchronyd\fR was compiled with debugging support,
|
||||
this option can be used twice to print also debugging messages.
|
||||
.TP
|
||||
\fB\-f\fR \fIconf-file\fR
|
||||
This option can be used to specify an alternate location for the
|
||||
configuration file (default \fI@SYSCONFDIR@/chrony.conf\fR).
|
||||
.TP
|
||||
.B \-r
|
||||
This option will reload sample histories for each of the servers being used.
|
||||
These histories are created by using the \fIdump\fR command in \fIchronyc\fR,
|
||||
or by setting the \fIdumponexit\fR directive in the configuration file. This
|
||||
option is useful if you want to stop and restart \fBchronyd\fR briefly for any
|
||||
reason, e.g. to install a new version. However, it should be used only on
|
||||
systems where the kernel can maintain clock compensation whilst not under
|
||||
\fBchronyd\fR's control (i.e. Linux, FreeBSD, NetBSD and Solaris).
|
||||
.TP
|
||||
.B \-R
|
||||
When this option is used, the \fIinitstepslew\fR directive and the
|
||||
\fImakestep\fR directive used with a positive limit will be ignored. This
|
||||
option is useful when restarting \fBchronyd\fR and can be used in conjunction
|
||||
with the \fB-r\fR option.
|
||||
.TP
|
||||
.B \-s
|
||||
This option will set the system clock from the computer's real-time clock or
|
||||
to the last modification time of the file specified by the \fIdriftfile\fR
|
||||
directive. Real-time clocks are supported only on Linux.
|
||||
|
||||
If used in conjunction with the \fB-r\fR flag, \fBchronyd\fR will attempt
|
||||
to preserve the old samples after setting the system clock from
|
||||
the real time clock (RTC). This can be used to allow \fBchronyd\fR to
|
||||
perform long term averaging of the gain or loss rate across system
|
||||
reboots, and is useful for dial-up systems that are shut down when
|
||||
not in use. For this to work well, it relies on \fBchronyd\fR having
|
||||
been able to determine accurate statistics for the difference
|
||||
between the RTC and system clock last time the computer was on.
|
||||
|
||||
If the last modification time of the drift file is later than the current time
|
||||
and the RTC time, the system time will be set to it to restore the time when
|
||||
\fBchronyd\fR was previously stopped. This is useful on computers that have no
|
||||
RTC or the RTC is broken (e.g. it has no battery).
|
||||
.TP
|
||||
\fB\-u\fR \fIuser\fR
|
||||
This option sets the name of the system user to which \fBchronyd\fR will switch
|
||||
after start in order to drop root privileges. It overrides the \fBuser\fR
|
||||
directive (default \fB@DEFAULT_USER@\fR). It may be set to a non-root user
|
||||
only when \fBchronyd\fR is compiled with support for Linux capabilities
|
||||
(libcap) or on NetBSD with the \fB/dev/clockctl\fR device.
|
||||
.TP
|
||||
\fB\-F\fR \fIlevel\fR
|
||||
This option configures a system call filter when \fBchronyd\fR is compiled with
|
||||
support for the Linux secure computing (seccomp) facility. In level 1 the
|
||||
process is killed when a forbidden system call is made, in level -1 the SYSSIG
|
||||
signal is thrown instead and in level 0 the filter is disabled (default 0).
|
||||
.TP
|
||||
.B \-q
|
||||
When run in this mode, chronyd will set the system clock once
|
||||
and exit. It will not detach from the terminal.
|
||||
.TP
|
||||
.B \-Q
|
||||
This option is similar to \fB\-q\fR, but it will only print the offset and
|
||||
not correct the clock.
|
||||
.TP
|
||||
.B \-v
|
||||
This option displays \fBchronyd\fR's version number to the terminal and exits
|
||||
.TP
|
||||
.B \-4
|
||||
Resolve hostnames only to IPv4 addresses and create only IPv4 sockets.
|
||||
.TP
|
||||
.B \-6
|
||||
Resolve hostnames only to IPv6 addresses and create only IPv6 sockets.
|
||||
|
||||
.SH FILES
|
||||
\fI@SYSCONFDIR@/chrony.conf\fR
|
||||
|
||||
.SH BUGS
|
||||
To report bugs, please visit \fIhttp://chrony.tuxfamily.org/\fR
|
||||
|
||||
.SH "SEE ALSO"
|
||||
\fBchronyd\fR is documented in detail in the documentation supplied with the
|
||||
distribution (\fIchrony.txt\fR and \fIchrony.texi\fR).
|
||||
|
||||
.BR chronyc(1),
|
||||
.BR chrony.conf(5),
|
||||
.BR hwclock(8),
|
||||
.BR ntpd(8)
|
||||
|
||||
.I http://chrony.tuxfamily.org/
|
||||
|
||||
.SH AUTHOR
|
||||
Richard Curnow <rc@rc0.org.uk>
|
||||
|
||||
This man-page was written by Jan Schaumann <jschauma@netmeister.org> as part
|
||||
of "The Missing Man Pages Project". Please see
|
||||
\fIhttp://www.netmeister.org/misc/m2p2/index.html\fR for details.
|
||||
|
||||
The complete chrony documentation is supplied in texinfo format.
|
||||
|
||||
170
clientlog.c
170
clientlog.c
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/clientlog.c,v 1.11 2003/09/22 21:22:30 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
@@ -35,6 +31,8 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysincl.h"
|
||||
#include "clientlog.h"
|
||||
#include "conf.h"
|
||||
@@ -176,7 +174,11 @@ CLG_Initialise(void)
|
||||
void
|
||||
CLG_Finalise(void)
|
||||
{
|
||||
return;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_nodes; i++)
|
||||
Free(nodes[i]);
|
||||
Free(nodes);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -259,28 +261,21 @@ find_subnet(Subnet *subnet, uint32_t *addr, int addr_len, int bits_consumed)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ================================================== */
|
||||
/* Search for the record for a particular subnet, but return NULL if
|
||||
one of the parents does not exist - never open a node out */
|
||||
|
||||
static void *
|
||||
find_subnet_dont_open(Subnet *subnet, uint32_t *addr, int addr_len, int bits_consumed)
|
||||
static Node *
|
||||
get_node(IPAddr *ip)
|
||||
{
|
||||
uint32_t this_subnet;
|
||||
uint32_t ip6[4];
|
||||
|
||||
if (bits_consumed >= 32 * addr_len) {
|
||||
return subnet;
|
||||
} else {
|
||||
|
||||
this_subnet = get_subnet(addr, bits_consumed);
|
||||
bits_consumed += NBITS;
|
||||
|
||||
if (!subnet->entry[this_subnet]) {
|
||||
switch (ip->family) {
|
||||
case IPADDR_INET4:
|
||||
return (Node *)find_subnet(&top_subnet4, &ip->addr.in4, 1, 0);
|
||||
case IPADDR_INET6:
|
||||
split_ip6(ip, ip6);
|
||||
return (Node *)find_subnet(&top_subnet6, ip6, 4, 0);
|
||||
default:
|
||||
return NULL;
|
||||
} else {
|
||||
return find_subnet_dont_open((Subnet *) subnet->entry[this_subnet], addr, addr_len, bits_consumed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,22 +284,10 @@ find_subnet_dont_open(Subnet *subnet, uint32_t *addr, int addr_len, int bits_con
|
||||
void
|
||||
CLG_LogNTPClientAccess (IPAddr *client, time_t now)
|
||||
{
|
||||
uint32_t ip6[4];
|
||||
Node *node;
|
||||
|
||||
if (active) {
|
||||
switch (client->family) {
|
||||
case IPADDR_INET4:
|
||||
node = (Node *) find_subnet(&top_subnet4, &client->addr.in4, 1, 0);
|
||||
break;
|
||||
case IPADDR_INET6:
|
||||
split_ip6(client, ip6);
|
||||
node = (Node *) find_subnet(&top_subnet6, ip6, 4, 0);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
node = get_node(client);
|
||||
if (node == NULL)
|
||||
return;
|
||||
|
||||
@@ -319,22 +302,10 @@ CLG_LogNTPClientAccess (IPAddr *client, time_t now)
|
||||
void
|
||||
CLG_LogNTPPeerAccess(IPAddr *client, time_t now)
|
||||
{
|
||||
uint32_t ip6[4];
|
||||
Node *node;
|
||||
|
||||
if (active) {
|
||||
switch (client->family) {
|
||||
case IPADDR_INET4:
|
||||
node = (Node *) find_subnet(&top_subnet4, &client->addr.in4, 1, 0);
|
||||
break;
|
||||
case IPADDR_INET6:
|
||||
split_ip6(client, ip6);
|
||||
node = (Node *) find_subnet(&top_subnet6, ip6, 4, 0);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
node = get_node(client);
|
||||
if (node == NULL)
|
||||
return;
|
||||
|
||||
@@ -349,22 +320,10 @@ CLG_LogNTPPeerAccess(IPAddr *client, time_t now)
|
||||
void
|
||||
CLG_LogCommandAccess(IPAddr *client, CLG_Command_Type type, time_t now)
|
||||
{
|
||||
uint32_t ip6[4];
|
||||
Node *node;
|
||||
|
||||
if (active) {
|
||||
switch (client->family) {
|
||||
case IPADDR_INET4:
|
||||
node = (Node *) find_subnet(&top_subnet4, &client->addr.in4, 1, 0);
|
||||
break;
|
||||
case IPADDR_INET6:
|
||||
split_ip6(client, ip6);
|
||||
node = (Node *) find_subnet(&top_subnet6, ip6, 4, 0);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
node = get_node(client);
|
||||
if (node == NULL)
|
||||
return;
|
||||
|
||||
@@ -389,95 +348,6 @@ CLG_LogCommandAccess(IPAddr *client, CLG_Command_Type type, time_t now)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
CLG_Status
|
||||
CLG_GetSubnetBitmap(IPAddr *subnet, int bits, CLG_Bitmap result)
|
||||
{
|
||||
Subnet *s;
|
||||
uint32_t ip6[4];
|
||||
unsigned long i;
|
||||
unsigned long word, bit, mask;
|
||||
|
||||
if (bits >= 0 && bits % 8 == 0) {
|
||||
memset (result, 0, TABLE_SIZE/8);
|
||||
if (active) {
|
||||
switch (subnet->family) {
|
||||
case IPADDR_INET4:
|
||||
if (bits >= 32)
|
||||
return CLG_BADSUBNET;
|
||||
s = find_subnet_dont_open(&top_subnet4, &subnet->addr.in4, 1, 32 - bits);
|
||||
break;
|
||||
case IPADDR_INET6:
|
||||
if (bits >= 128)
|
||||
return CLG_BADSUBNET;
|
||||
split_ip6(subnet, ip6);
|
||||
s = find_subnet_dont_open(&top_subnet6, ip6, 4, 128 - bits);
|
||||
break;
|
||||
default:
|
||||
return CLG_BADSUBNET;
|
||||
}
|
||||
|
||||
if (s) {
|
||||
for (i=0; i<256; i++) {
|
||||
if (s->entry[i]) {
|
||||
word = i / 32;
|
||||
bit = i % 32;
|
||||
mask = 1UL << bit;
|
||||
result[word] |= mask;
|
||||
}
|
||||
}
|
||||
return CLG_SUCCESS;
|
||||
} else {
|
||||
return CLG_EMPTYSUBNET;
|
||||
}
|
||||
} else {
|
||||
return CLG_INACTIVE;
|
||||
}
|
||||
} else {
|
||||
return CLG_BADSUBNET;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
CLG_Status
|
||||
CLG_GetClientAccessReportByIP(IPAddr *ip, RPT_ClientAccess_Report *report, time_t now)
|
||||
{
|
||||
uint32_t ip6[4];
|
||||
Node *node;
|
||||
|
||||
if (!active) {
|
||||
return CLG_INACTIVE;
|
||||
} else {
|
||||
switch (ip->family) {
|
||||
case IPADDR_INET4:
|
||||
node = (Node *) find_subnet_dont_open(&top_subnet4, &ip->addr.in4, 1, 0);
|
||||
break;
|
||||
case IPADDR_INET6:
|
||||
split_ip6(ip, ip6);
|
||||
node = (Node *) find_subnet_dont_open(&top_subnet6, ip6, 4, 0);
|
||||
break;
|
||||
default:
|
||||
return CLG_EMPTYSUBNET;
|
||||
}
|
||||
|
||||
if (!node) {
|
||||
return CLG_EMPTYSUBNET;
|
||||
} else {
|
||||
report->client_hits = node->client_hits;
|
||||
report->peer_hits = node->peer_hits;
|
||||
report->cmd_hits_auth = node->cmd_hits_auth;
|
||||
report->cmd_hits_normal = node->cmd_hits_normal;
|
||||
report->cmd_hits_bad = node->cmd_hits_bad;
|
||||
report->last_ntp_hit_ago = now - node->last_ntp_hit;
|
||||
report->last_cmd_hit_ago = now - node->last_cmd_hit;
|
||||
|
||||
return CLG_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
CLG_Status
|
||||
CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *report,
|
||||
time_t now, unsigned long *n_indices)
|
||||
|
||||
25
clientlog.h
25
clientlog.h
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/clientlog.h,v 1.9 2003/09/22 21:22:30 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
@@ -35,9 +31,6 @@
|
||||
#include "sysincl.h"
|
||||
#include "reports.h"
|
||||
|
||||
/* Enough to hold flags for 256 hosts in a class C */
|
||||
typedef uint32_t CLG_Bitmap[8];
|
||||
|
||||
extern void CLG_Initialise(void);
|
||||
extern void CLG_Finalise(void);
|
||||
extern void CLG_LogNTPClientAccess(IPAddr *client, time_t now);
|
||||
@@ -64,26 +57,8 @@ typedef enum {
|
||||
CLG_INDEXTOOLARGE /* Node index is higher than number of nodes present */
|
||||
} CLG_Status;
|
||||
|
||||
/* For bits=0, 8, 16, flag which immediate subnets of that subnet are
|
||||
known. For bits=24, flag which hosts in that subnet are known.
|
||||
Other values, return 0 (failed) */
|
||||
|
||||
extern CLG_Status CLG_GetSubnetBitmap(IPAddr *subnet, int bits, CLG_Bitmap result);
|
||||
|
||||
extern CLG_Status
|
||||
CLG_GetClientAccessReportByIP(IPAddr *ip, RPT_ClientAccess_Report *report, time_t now);
|
||||
|
||||
CLG_Status
|
||||
CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *report,
|
||||
time_t now, unsigned long *n_indices);
|
||||
|
||||
/* And an iterating function, to call 'fn' for each client or peer
|
||||
that has accessed us since 'since'. */
|
||||
|
||||
extern void CLG_IterateNTPClients
|
||||
(void (*fn)(IPAddr *client, void *arb),
|
||||
void *arb,
|
||||
time_t since);
|
||||
|
||||
|
||||
#endif /* GOT_CLIENTLOG_H */
|
||||
|
||||
7
cmdmon.h
7
cmdmon.h
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/cmdmon.h,v 1.8 2002/02/28 23:27:09 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
@@ -33,10 +29,11 @@
|
||||
|
||||
#include "addressing.h"
|
||||
|
||||
extern void CAM_Initialise(void);
|
||||
extern void CAM_Initialise(int family);
|
||||
|
||||
extern void CAM_Finalise(void);
|
||||
|
||||
extern void CAM_OpenUnixSocket(void);
|
||||
extern int CAM_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
|
||||
extern int CAM_CheckAccessRestriction(IPAddr *ip_addr);
|
||||
|
||||
|
||||
307
cmdparse.c
307
cmdparse.c
@@ -1,12 +1,9 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/cmdparse.c,v 1.12 2003/09/22 21:22:30 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2013-2014
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -30,122 +27,183 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "cmdparse.h"
|
||||
#include "memory.h"
|
||||
#include "nameserv.h"
|
||||
|
||||
#define MAXLEN 2047
|
||||
#define SMAXLEN "2047"
|
||||
#include "ntp.h"
|
||||
#include "util.h"
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
CPS_Status
|
||||
CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
|
||||
CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
|
||||
{
|
||||
int ok, n, done;
|
||||
char cmd[MAXLEN+1], hostname[MAXLEN+1];
|
||||
char *hostname, *cmd;
|
||||
int n, done;
|
||||
CPS_Status result;
|
||||
|
||||
src->port = 123;
|
||||
src->params.minpoll = 6;
|
||||
src->params.maxpoll = 10;
|
||||
src->params.presend_minpoll = 0;
|
||||
src->port = SRC_DEFAULT_PORT;
|
||||
src->params.minpoll = SRC_DEFAULT_MINPOLL;
|
||||
src->params.maxpoll = SRC_DEFAULT_MAXPOLL;
|
||||
src->params.presend_minpoll = SRC_DEFAULT_PRESEND_MINPOLL;
|
||||
src->params.authkey = INACTIVE_AUTHKEY;
|
||||
src->params.max_delay = 16.0;
|
||||
src->params.max_delay_ratio = 16384.0;
|
||||
src->params.max_delay = SRC_DEFAULT_MAXDELAY;
|
||||
src->params.max_delay_ratio = SRC_DEFAULT_MAXDELAYRATIO;
|
||||
src->params.max_delay_dev_ratio = SRC_DEFAULT_MAXDELAYDEVRATIO;
|
||||
src->params.online = 1;
|
||||
src->params.auto_offline = 0;
|
||||
src->params.iburst = 0;
|
||||
src->params.min_stratum = SRC_DEFAULT_MINSTRATUM;
|
||||
src->params.poll_target = SRC_DEFAULT_POLLTARGET;
|
||||
src->params.version = NTP_VERSION;
|
||||
src->params.max_sources = SRC_DEFAULT_MAXSOURCES;
|
||||
src->params.min_samples = SRC_DEFAULT_MINSAMPLES;
|
||||
src->params.max_samples = SRC_DEFAULT_MAXSAMPLES;
|
||||
src->params.sel_option = SRC_SelectNormal;
|
||||
|
||||
result = CPS_Success;
|
||||
|
||||
ok = 0;
|
||||
if (sscanf(line, "%" SMAXLEN "s%n", hostname, &n) == 1) {
|
||||
if (DNS_Name2IPAddress(hostname, &src->ip_addr, 1)) {
|
||||
ok = 1;
|
||||
}
|
||||
}
|
||||
hostname = line;
|
||||
line = CPS_SplitWord(line);
|
||||
|
||||
if (!ok) {
|
||||
if (!*hostname) {
|
||||
result = CPS_BadHost;
|
||||
} else {
|
||||
src->name = hostname;
|
||||
|
||||
line += n;
|
||||
|
||||
/* Parse subfields */
|
||||
ok = 1;
|
||||
done = 0;
|
||||
do {
|
||||
if (sscanf(line, "%" SMAXLEN "s%n", cmd, &n) == 1) {
|
||||
|
||||
line += n;
|
||||
|
||||
if (!strncasecmp(cmd, "port", 4)) {
|
||||
cmd = line;
|
||||
line = CPS_SplitWord(line);
|
||||
|
||||
if (*cmd) {
|
||||
if (!strcasecmp(cmd, "port")) {
|
||||
if (sscanf(line, "%hu%n", &src->port, &n) != 1) {
|
||||
result = CPS_BadPort;
|
||||
ok = 0;
|
||||
done = 1;
|
||||
} else {
|
||||
line += n;
|
||||
}
|
||||
} else if (!strncasecmp(cmd, "minpoll", 7)) {
|
||||
} else if (!strcasecmp(cmd, "minpoll")) {
|
||||
if (sscanf(line, "%d%n", &src->params.minpoll, &n) != 1) {
|
||||
result = CPS_BadMinpoll;
|
||||
ok = 0;
|
||||
done = 1;
|
||||
} else {
|
||||
line += n;
|
||||
}
|
||||
} else if (!strncasecmp(cmd, "maxpoll", 7)) {
|
||||
} else if (!strcasecmp(cmd, "maxpoll")) {
|
||||
if (sscanf(line, "%d%n", &src->params.maxpoll, &n) != 1) {
|
||||
result = CPS_BadMaxpoll;
|
||||
ok = 0;
|
||||
done = 1;
|
||||
} else {
|
||||
line += n;
|
||||
}
|
||||
} else if (!strncasecmp(cmd, "presend", 7)) {
|
||||
} else if (!strcasecmp(cmd, "presend")) {
|
||||
if (sscanf(line, "%d%n", &src->params.presend_minpoll, &n) != 1) {
|
||||
result = CPS_BadPresend;
|
||||
ok = 0;
|
||||
done = 1;
|
||||
} else {
|
||||
line += n;
|
||||
}
|
||||
/* This MUST come before the following one ! */
|
||||
} else if (!strncasecmp(cmd, "maxdelayratio", 13)) {
|
||||
} else if (!strcasecmp(cmd, "maxdelaydevratio")) {
|
||||
if (sscanf(line, "%lf%n", &src->params.max_delay_dev_ratio, &n) != 1) {
|
||||
result = CPS_BadMaxdelaydevratio;
|
||||
done = 1;
|
||||
} else {
|
||||
line += n;
|
||||
}
|
||||
} else if (!strcasecmp(cmd, "maxdelayratio")) {
|
||||
if (sscanf(line, "%lf%n", &src->params.max_delay_ratio, &n) != 1) {
|
||||
result = CPS_BadMaxdelayratio;
|
||||
ok = 0;
|
||||
done = 1;
|
||||
} else {
|
||||
line += n;
|
||||
}
|
||||
} else if (!strncasecmp(cmd, "maxdelay", 8)) {
|
||||
} else if (!strcasecmp(cmd, "maxdelay")) {
|
||||
if (sscanf(line, "%lf%n", &src->params.max_delay, &n) != 1) {
|
||||
result = CPS_BadMaxdelay;
|
||||
ok = 0;
|
||||
done = 1;
|
||||
} else {
|
||||
line += n;
|
||||
}
|
||||
} else if (!strncasecmp(cmd, "key", 3)) {
|
||||
if (sscanf(line, "%lu%n", &src->params.authkey, &n) != 1) {
|
||||
} else if (!strcasecmp(cmd, "key")) {
|
||||
if (sscanf(line, "%"SCNu32"%n", &src->params.authkey, &n) != 1 ||
|
||||
src->params.authkey == INACTIVE_AUTHKEY) {
|
||||
result = CPS_BadKey;
|
||||
ok = 0;
|
||||
done = 1;
|
||||
} else {
|
||||
line += n;
|
||||
}
|
||||
} else if (!strncasecmp(cmd, "offline", 7)) {
|
||||
} else if (!strcasecmp(cmd, "offline")) {
|
||||
src->params.online = 0;
|
||||
|
||||
} else if (!strncasecmp(cmd, "auto_offline", 12)) {
|
||||
} else if (!strcasecmp(cmd, "auto_offline")) {
|
||||
src->params.auto_offline = 1;
|
||||
|
||||
} else if (!strcasecmp(cmd, "iburst")) {
|
||||
src->params.iburst = 1;
|
||||
|
||||
} else if (!strcasecmp(cmd, "minstratum")) {
|
||||
if (sscanf(line, "%d%n", &src->params.min_stratum, &n) != 1) {
|
||||
result = CPS_BadMinstratum;
|
||||
done = 1;
|
||||
} else {
|
||||
line += n;
|
||||
}
|
||||
|
||||
} else if (!strcasecmp(cmd, "polltarget")) {
|
||||
if (sscanf(line, "%d%n", &src->params.poll_target, &n) != 1) {
|
||||
result = CPS_BadPolltarget;
|
||||
done = 1;
|
||||
} else {
|
||||
line += n;
|
||||
}
|
||||
|
||||
} else if (!strcasecmp(cmd, "noselect")) {
|
||||
src->params.sel_option = SRC_SelectNoselect;
|
||||
|
||||
} else if (!strcasecmp(cmd, "prefer")) {
|
||||
src->params.sel_option = SRC_SelectPrefer;
|
||||
|
||||
} else if (!strcasecmp(cmd, "version")) {
|
||||
if (sscanf(line, "%d%n", &src->params.version, &n) != 1) {
|
||||
result = CPS_BadVersion;
|
||||
done = 1;
|
||||
} else {
|
||||
line += n;
|
||||
}
|
||||
|
||||
} else if (!strcasecmp(cmd, "maxsources")) {
|
||||
if (sscanf(line, "%d%n", &src->params.max_sources, &n) != 1) {
|
||||
result = CPS_BadMaxsources;
|
||||
done = 1;
|
||||
} else {
|
||||
line += n;
|
||||
}
|
||||
|
||||
} else if (!strcasecmp(cmd, "minsamples")) {
|
||||
if (sscanf(line, "%d%n", &src->params.min_samples, &n) != 1) {
|
||||
result = CPS_BadMinsamples;
|
||||
done = 1;
|
||||
} else {
|
||||
line += n;
|
||||
}
|
||||
|
||||
} else if (!strcasecmp(cmd, "maxsamples")) {
|
||||
if (sscanf(line, "%d%n", &src->params.max_samples, &n) != 1) {
|
||||
result = CPS_BadMaxsamples;
|
||||
done = 1;
|
||||
} else {
|
||||
line += n;
|
||||
}
|
||||
|
||||
} else {
|
||||
result = CPS_BadOption;
|
||||
ok = 0;
|
||||
done = 1;
|
||||
}
|
||||
} else {
|
||||
@@ -155,8 +213,157 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
CPS_StatusToString(CPS_Status status, char *dest, int len)
|
||||
{
|
||||
const char *s = NULL;
|
||||
|
||||
if (len > 0)
|
||||
dest[0] = '\0';
|
||||
|
||||
switch (status) {
|
||||
case CPS_Success:
|
||||
return;
|
||||
case CPS_BadOption:
|
||||
s = "server/peer/pool option";
|
||||
break;
|
||||
case CPS_BadHost:
|
||||
s = "address";
|
||||
break;
|
||||
case CPS_BadPort:
|
||||
s = "port";
|
||||
break;
|
||||
case CPS_BadMinpoll:
|
||||
s = "minpoll";
|
||||
break;
|
||||
case CPS_BadMaxpoll:
|
||||
s = "maxpoll";
|
||||
break;
|
||||
case CPS_BadPresend:
|
||||
s = "presend";
|
||||
break;
|
||||
case CPS_BadMaxdelaydevratio:
|
||||
s = "maxdelaydevratio";
|
||||
break;
|
||||
case CPS_BadMaxdelayratio:
|
||||
s = "maxdelayratio";
|
||||
break;
|
||||
case CPS_BadMaxdelay:
|
||||
s = "maxdelay";
|
||||
break;
|
||||
case CPS_BadKey:
|
||||
s = "key";
|
||||
break;
|
||||
case CPS_BadMinstratum:
|
||||
s = "minstratum";
|
||||
break;
|
||||
case CPS_BadPolltarget:
|
||||
s = "polltarget";
|
||||
break;
|
||||
case CPS_BadVersion:
|
||||
s = "version";
|
||||
break;
|
||||
case CPS_BadMaxsources:
|
||||
s = "maxsources";
|
||||
break;
|
||||
case CPS_BadMinsamples:
|
||||
s = "minsamples";
|
||||
break;
|
||||
case CPS_BadMaxsamples:
|
||||
s = "maxsamples";
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(dest, len, "Invalid %s", s);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
CPS_NormalizeLine(char *line)
|
||||
{
|
||||
char *p, *q;
|
||||
int space = 1, first = 1;
|
||||
|
||||
/* Remove white-space at beginning and replace white-spaces with space char */
|
||||
for (p = q = line; *p; p++) {
|
||||
if (isspace((unsigned char)*p)) {
|
||||
if (!space)
|
||||
*q++ = ' ';
|
||||
space = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Discard comment lines */
|
||||
if (first && strchr("!;#%", *p))
|
||||
break;
|
||||
|
||||
*q++ = *p;
|
||||
space = first = 0;
|
||||
}
|
||||
|
||||
/* Strip trailing space */
|
||||
if (q > line && q[-1] == ' ')
|
||||
q--;
|
||||
|
||||
*q = '\0';
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
char *
|
||||
CPS_SplitWord(char *line)
|
||||
{
|
||||
char *p = line, *q = line;
|
||||
|
||||
/* Skip white-space before the word */
|
||||
while (*q && isspace((unsigned char)*q))
|
||||
q++;
|
||||
|
||||
/* Move the word to the beginning */
|
||||
while (*q && !isspace((unsigned char)*q))
|
||||
*p++ = *q++;
|
||||
|
||||
/* Find the next word */
|
||||
while (*q && isspace((unsigned char)*q))
|
||||
q++;
|
||||
|
||||
*p = '\0';
|
||||
|
||||
/* Return pointer to the next word or NUL */
|
||||
return q;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
CPS_ParseKey(char *line, uint32_t *id, const char **hash, char **key)
|
||||
{
|
||||
char *s1, *s2, *s3, *s4;
|
||||
|
||||
s1 = line;
|
||||
s2 = CPS_SplitWord(s1);
|
||||
s3 = CPS_SplitWord(s2);
|
||||
s4 = CPS_SplitWord(s3);
|
||||
|
||||
/* Require two or three words */
|
||||
if (!*s2 || *s4)
|
||||
return 0;
|
||||
|
||||
if (sscanf(s1, "%"SCNu32, id) != 1)
|
||||
return 0;
|
||||
|
||||
if (*s3) {
|
||||
*hash = s2;
|
||||
*key = s3;
|
||||
} else {
|
||||
*hash = "MD5";
|
||||
*key = s2;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
27
cmdparse.h
27
cmdparse.h
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/cmdparse.h,v 1.7 2002/02/28 23:27:09 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
@@ -42,20 +38,37 @@ typedef enum {
|
||||
CPS_BadMinpoll,
|
||||
CPS_BadMaxpoll,
|
||||
CPS_BadPresend,
|
||||
CPS_BadMaxdelaydevratio,
|
||||
CPS_BadMaxdelayratio,
|
||||
CPS_BadMaxdelay,
|
||||
CPS_BadKey
|
||||
CPS_BadKey,
|
||||
CPS_BadMinstratum,
|
||||
CPS_BadPolltarget,
|
||||
CPS_BadVersion,
|
||||
CPS_BadMaxsources,
|
||||
CPS_BadMinsamples,
|
||||
CPS_BadMaxsamples,
|
||||
} CPS_Status;
|
||||
|
||||
typedef struct {
|
||||
IPAddr ip_addr;
|
||||
char *name;
|
||||
unsigned short port;
|
||||
SourceParameters params;
|
||||
} CPS_NTP_Source;
|
||||
|
||||
/* Parse a command to add an NTP server or peer */
|
||||
extern CPS_Status CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src);
|
||||
extern CPS_Status CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src);
|
||||
|
||||
/* Get a string describing error status */
|
||||
extern void CPS_StatusToString(CPS_Status status, char *dest, int len);
|
||||
|
||||
/* Remove extra white-space and comments */
|
||||
extern void CPS_NormalizeLine(char *line);
|
||||
|
||||
/* Terminate first word and return pointer to the next word */
|
||||
extern char *CPS_SplitWord(char *line);
|
||||
|
||||
/* Parse a key from keyfile */
|
||||
extern int CPS_ParseKey(char *line, uint32_t *id, const char **hash, char **key);
|
||||
|
||||
#endif /* GOT_CMDPARSE_H */
|
||||
|
||||
59
conf.h
59
conf.h
@@ -1,12 +1,9 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/conf.h,v 1.25 2003/09/22 21:22:30 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2013-2014
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -32,46 +29,68 @@
|
||||
#define GOT_CONF_H
|
||||
|
||||
#include "addressing.h"
|
||||
#include "reference.h"
|
||||
|
||||
extern void CNF_Initialise(int restarted);
|
||||
extern void CNF_Finalise(void);
|
||||
|
||||
extern char *CNF_GetRtcDevice(void);
|
||||
|
||||
extern void CNF_ReadFile(const char *filename);
|
||||
extern void CNF_ParseLine(const char *filename, int number, char *line);
|
||||
|
||||
extern void CNF_CreateDirs(uid_t uid, gid_t gid);
|
||||
|
||||
extern void CNF_AddInitSources(void);
|
||||
extern void CNF_AddSources(void);
|
||||
extern void CNF_AddBroadcasts(void);
|
||||
extern void CNF_AddRefclocks(void);
|
||||
|
||||
extern void CNF_ProcessInitStepSlew(void (*after_hook)(void *), void *anything);
|
||||
|
||||
extern unsigned short CNF_GetAcquisitionPort(void);
|
||||
extern unsigned short CNF_GetNTPPort(void);
|
||||
extern int CNF_GetAcquisitionPort(void);
|
||||
extern int CNF_GetNTPPort(void);
|
||||
extern char *CNF_GetDriftFile(void);
|
||||
extern char *CNF_GetLogDir(void);
|
||||
extern char *CNF_GetDumpDir(void);
|
||||
extern int CNF_GetLogBanner(void);
|
||||
extern int CNF_GetLogMeasurements(void);
|
||||
extern int CNF_GetLogStatistics(void);
|
||||
extern int CNF_GetLogTracking(void);
|
||||
extern int CNF_GetLogRtc(void);
|
||||
extern int CNF_GetLogRefclocks(void);
|
||||
extern int CNF_GetLogTempComp(void);
|
||||
extern char *CNF_GetKeysFile(void);
|
||||
extern char *CNF_GetRtcFile(void);
|
||||
extern unsigned long CNF_GetCommandKey(void);
|
||||
extern int CNF_GetDumpOnExit(void);
|
||||
extern int CNF_GetManualEnabled(void);
|
||||
extern int CNF_GetCommandPort(void);
|
||||
extern int CNF_GetRTCOnUTC(void);
|
||||
extern int CNF_GetRtcOnUtc(void);
|
||||
extern int CNF_GetRtcSync(void);
|
||||
extern void CNF_GetMakeStep(int *limit, double *threshold);
|
||||
extern void CNF_GetMaxChange(int *delay, int *ignore, double *offset);
|
||||
extern void CNF_GetLogChange(int *enabled, double *threshold);
|
||||
extern void CNF_GetMailOnChange(int *enabled, double *threshold, char **user);
|
||||
extern int CNF_GetNoClientLog(void);
|
||||
extern unsigned long CNF_GetClientLogLimit(void);
|
||||
extern void CNF_GetFallbackDrifts(int *min, int *max);
|
||||
extern void CNF_GetBindAddress(int family, IPAddr *addr);
|
||||
extern void CNF_GetBindAcquisitionAddress(int family, IPAddr *addr);
|
||||
extern void CNF_GetBindCommandAddress(int family, IPAddr *addr);
|
||||
extern char *CNF_GetBindCommandPath(void);
|
||||
extern char *CNF_GetPidFile(void);
|
||||
extern void CNF_GetLinuxHz(int *set, int *hz);
|
||||
extern void CNF_GetLinuxFreqScale(int *set, double *freq_scale);
|
||||
extern REF_LeapMode CNF_GetLeapSecMode(void);
|
||||
extern char *CNF_GetLeapSecTimezone(void);
|
||||
|
||||
/* Value returned in ppm, as read from file */
|
||||
extern double CNF_GetMaxUpdateSkew(void);
|
||||
extern double CNF_GetMaxClockError(void);
|
||||
extern double CNF_GetCorrectionTimeRatio(void);
|
||||
extern double CNF_GetMaxSlewRate(void);
|
||||
|
||||
extern double CNF_GetMaxDistance(void);
|
||||
extern double CNF_GetReselectDistance(void);
|
||||
extern double CNF_GetStratumWeight(void);
|
||||
extern double CNF_GetCombineLimit(void);
|
||||
|
||||
extern int CNF_AllowLocalReference(int *stratum);
|
||||
|
||||
extern void CNF_SetupAccessRestrictions(void);
|
||||
@@ -79,4 +98,20 @@ extern void CNF_SetupAccessRestrictions(void);
|
||||
extern int CNF_GetSchedPriority(void);
|
||||
extern int CNF_GetLockMemory(void);
|
||||
|
||||
extern void CNF_GetSmooth(double *max_freq, double *max_wander, int *leap_only);
|
||||
extern void CNF_GetTempComp(char **file, double *interval, char **point_file, double *T0, double *k0, double *k1, double *k2);
|
||||
|
||||
extern char *CNF_GetUser(void);
|
||||
|
||||
extern int CNF_GetMaxSamples(void);
|
||||
extern int CNF_GetMinSamples(void);
|
||||
|
||||
extern int CNF_GetMinSources(void);
|
||||
|
||||
extern double CNF_GetRtcAutotrim(void);
|
||||
extern char *CNF_GetHwclockFile(void);
|
||||
|
||||
extern int CNF_GetInitSources(void);
|
||||
extern double CNF_GetInitStepThreshold(void);
|
||||
|
||||
#endif /* GOT_CONF_H */
|
||||
|
||||
636
configure
vendored
636
configure
vendored
@@ -4,31 +4,12 @@
|
||||
# chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
#
|
||||
# Copyright (C) Richard P. Curnow 1997-2003
|
||||
# Copyright (C) Miroslav Lichvar 2009, 2012-2015
|
||||
#
|
||||
# =======================================================================
|
||||
|
||||
# This configure script determines the operating system type and version
|
||||
|
||||
if [ "x${CC}" = "x" ]; then
|
||||
MYCC="gcc"
|
||||
else
|
||||
MYCC="${CC}"
|
||||
fi
|
||||
|
||||
if [ "x${CFLAGS}" = "x" ]; then
|
||||
MYCFLAGS="-O2 -g"
|
||||
else
|
||||
MYCFLAGS="${CFLAGS}"
|
||||
fi
|
||||
|
||||
MYCPPFLAGS="${CPPFLAGS}"
|
||||
|
||||
if [ "x${MYCC}" = "xgcc" ]; then
|
||||
CCWARNFLAGS="-Wmissing-prototypes -Wall"
|
||||
else
|
||||
CCWARNFLAGS=""
|
||||
fi
|
||||
|
||||
# ======================================================================
|
||||
# FUNCTIONS
|
||||
|
||||
@@ -40,7 +21,7 @@ test_code () {
|
||||
ldflags=$4
|
||||
code=$5
|
||||
|
||||
printf "Checking for $name : "
|
||||
printf "%s" "Checking for $name : "
|
||||
|
||||
(
|
||||
for h in $headers; do
|
||||
@@ -51,23 +32,30 @@ test_code () {
|
||||
echo "return 0; }"
|
||||
) > docheck.c
|
||||
|
||||
${MYCC} ${MYCFLAGS} ${MYCPPFLAGS} $cflags -o docheck docheck.c $ldflags >/dev/null 2>&1
|
||||
echo "docheck.c:" >> config.log
|
||||
cat docheck.c >> config.log
|
||||
echo $MYCC $MYCFLAGS $MYCPPFLAGS $cflags -o docheck docheck.c $ldflags \
|
||||
$MYLDFLAGS >> config.log
|
||||
$MYCC $MYCFLAGS $MYCPPFLAGS $cflags -o docheck docheck.c $ldflags \
|
||||
$MYLDFLAGS >> config.log 2>&1
|
||||
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
printf "Yes\n"
|
||||
echo "Yes"
|
||||
result=0
|
||||
else
|
||||
printf "No\n"
|
||||
echo "No"
|
||||
result=1
|
||||
fi
|
||||
rm -f docheck.c docheck
|
||||
echo >> config.log
|
||||
return $result
|
||||
}
|
||||
#}}}
|
||||
#{{{ usage
|
||||
usage () {
|
||||
cat <<EOF;
|
||||
\`configure' configures tdl to adapt to many kinds of systems.
|
||||
cat <<EOF
|
||||
\`configure' configures this package to adapt to many kinds of systems.
|
||||
|
||||
Usage: ./configure [OPTION]...
|
||||
|
||||
@@ -95,10 +83,28 @@ For better control, use the options below.
|
||||
--readline-inc-dir=DIR Specify where readline include directory is
|
||||
--readline-lib-dir=DIR Specify where readline lib directory is
|
||||
--with-ncurses-library=DIR Specify where ncurses lib directory is
|
||||
--disable-sechash Disable support for hashes other than MD5
|
||||
--without-nss Don't use NSS even if it is available
|
||||
--without-tomcrypt Don't use libtomcrypt even if it is available
|
||||
--disable-cmdmon Disable command and monitoring support
|
||||
--disable-ntp Disable NTP support
|
||||
--disable-refclock Disable reference clock support
|
||||
--disable-phc Disable PHC refclock driver
|
||||
--disable-pps Disable PPS refclock driver
|
||||
--disable-ipv6 Disable IPv6 support
|
||||
--disable-pps Disable PPS API support
|
||||
--disable-rtc Don't include RTC even on Linux
|
||||
--disable-linuxcaps Disable Linux capabilities support
|
||||
--disable-privdrop Disable support for dropping root privileges
|
||||
--without-libcap Don't use libcap even if it is available
|
||||
--enable-scfilter Enable support for system call filtering
|
||||
--without-seccomp Don't use seccomp even if it is available
|
||||
--disable-asyncdns Disable asynchronous name resolving
|
||||
--disable-forcednsretry Don't retry on permanent DNS error
|
||||
--with-ntp-era=SECONDS Specify earliest assumed NTP time in seconds
|
||||
since 1970-01-01 [50*365 days ago]
|
||||
--with-user=USER Specify default chronyd user [root]
|
||||
--with-hwclockfile=PATH Specify default path to hwclock(8) adjtime file
|
||||
--with-sendmail=PATH Path to sendmail binary [/usr/lib/sendmail]
|
||||
--enable-debug Enable debugging support
|
||||
|
||||
Fine tuning of the installation directories:
|
||||
--sysconfdir=DIR chrony.conf location [/etc]
|
||||
@@ -108,6 +114,9 @@ Fine tuning of the installation directories:
|
||||
--infodir=DIR info documentation [DATAROOTDIR/info]
|
||||
--mandir=DIR man documentation [DATAROOTDIR/man]
|
||||
--docdir=DIR documentation root [DATAROOTDIR/doc/chrony]
|
||||
--localstatedir=DIR modifiable single-machine data [/var]
|
||||
--chronysockdir=DIR location for chrony sockets [LOCALSTATEDIR/run/chrony]
|
||||
--chronyvardir=DIR location for chrony data [LOCALSTATEDIR/lib/chrony]
|
||||
|
||||
Overriding system detection when cross-compiling:
|
||||
--host-system=OS Specify system name (uname -s)
|
||||
@@ -129,6 +138,38 @@ EOF
|
||||
|
||||
}
|
||||
#}}}
|
||||
#{{{
|
||||
add_def () {
|
||||
if [ "x$2" = "x" ]; then
|
||||
echo "#define $1 1" >> config.h
|
||||
else
|
||||
echo "#define $1 $2" >> config.h
|
||||
fi
|
||||
}
|
||||
#}}}
|
||||
#{{{ pkg_config
|
||||
pkg_config () {
|
||||
type pkg-config > /dev/null 2> /dev/null || return 1
|
||||
|
||||
pkg-config $@ 2> /dev/null
|
||||
}
|
||||
#}}}
|
||||
#{{{ get_features
|
||||
get_features () {
|
||||
ff=1
|
||||
for f; do
|
||||
if [ "$ff" = "0" ]; then
|
||||
printf " "
|
||||
fi
|
||||
if grep "define FEAT_$f" config.h > /dev/null; then
|
||||
printf "%s" "+$f"
|
||||
else
|
||||
printf "%s" "-$f"
|
||||
fi
|
||||
ff=0
|
||||
done
|
||||
}
|
||||
#}}}
|
||||
|
||||
# ======================================================================
|
||||
|
||||
@@ -144,26 +185,44 @@ EXTRA_OBJECTS=""
|
||||
EXTRA_DEFS=""
|
||||
SYSDEFS=""
|
||||
|
||||
# Support for readline (on by default)
|
||||
feat_debug=0
|
||||
feat_cmdmon=1
|
||||
feat_ntp=1
|
||||
feat_refclock=1
|
||||
feat_readline=1
|
||||
try_readline=1
|
||||
try_editline=1
|
||||
feat_sechash=1
|
||||
try_nss=1
|
||||
try_tomcrypt=1
|
||||
feat_rtc=1
|
||||
feat_linuxcaps=1
|
||||
try_linuxcaps=0
|
||||
try_rtc=0
|
||||
feat_droproot=1
|
||||
try_libcap=-1
|
||||
try_clockctl=0
|
||||
feat_scfilter=0
|
||||
try_seccomp=-1
|
||||
readline_lib=""
|
||||
readline_inc=""
|
||||
ncurses_lib=""
|
||||
feat_ipv6=1
|
||||
feat_phc=1
|
||||
try_phc=0
|
||||
feat_pps=1
|
||||
try_setsched=0
|
||||
try_lockmem=0
|
||||
feat_asyncdns=1
|
||||
feat_forcednsretry=1
|
||||
ntp_era_split=""
|
||||
default_user="root"
|
||||
default_hwclockfile=""
|
||||
mail_program="/usr/lib/sendmail"
|
||||
|
||||
for option
|
||||
do
|
||||
case "$option" in
|
||||
--trace )
|
||||
EXTRA_DEFS="-DTRACEON"
|
||||
--enable-debug )
|
||||
feat_debug=1
|
||||
;;
|
||||
--disable-readline )
|
||||
feat_readline=0
|
||||
@@ -210,17 +269,77 @@ do
|
||||
--docdir=* )
|
||||
SETDOCDIR=`echo $option | sed -e 's/^.*=//;'`
|
||||
;;
|
||||
--localstatedir=* )
|
||||
SETLOCALSTATEDIR=`echo $option | sed -e 's/^.*=//;'`
|
||||
;;
|
||||
--chronysockdir=* )
|
||||
SETCHRONYSOCKDIR=`echo $option | sed -e 's/^.*=//;'`
|
||||
;;
|
||||
--chronyvardir=* )
|
||||
SETCHRONYVARDIR=`echo $option | sed -e 's/^.*=//;'`
|
||||
;;
|
||||
--disable-cmdmon)
|
||||
feat_cmdmon=0
|
||||
;;
|
||||
--disable-ntp)
|
||||
feat_ntp=0
|
||||
;;
|
||||
--disable-refclock)
|
||||
feat_refclock=0
|
||||
;;
|
||||
--disable-rtc)
|
||||
feat_rtc=0
|
||||
;;
|
||||
--disable-ipv6)
|
||||
feat_ipv6=0
|
||||
;;
|
||||
--disable-phc)
|
||||
feat_phc=0
|
||||
;;
|
||||
--disable-pps)
|
||||
feat_pps=0
|
||||
;;
|
||||
--disable-linuxcaps)
|
||||
feat_linuxcaps=0
|
||||
--disable-privdrop)
|
||||
feat_droproot=0
|
||||
;;
|
||||
--without-libcap|--disable-linuxcaps)
|
||||
try_libcap=0
|
||||
;;
|
||||
--enable-scfilter)
|
||||
feat_scfilter=1
|
||||
;;
|
||||
--disable-scfilter)
|
||||
feat_scfilter=0
|
||||
;;
|
||||
--without-seccomp)
|
||||
try_seccomp=0
|
||||
;;
|
||||
--disable-asyncdns)
|
||||
feat_asyncdns=0
|
||||
;;
|
||||
--disable-forcednsretry)
|
||||
feat_forcednsretry=0
|
||||
;;
|
||||
--with-ntp-era=* )
|
||||
ntp_era_split=`echo $option | sed -e 's/^.*=//;'`
|
||||
;;
|
||||
--with-user=* )
|
||||
default_user=`echo $option | sed -e 's/^.*=//;'`
|
||||
;;
|
||||
--with-hwclockfile=* )
|
||||
default_hwclockfile=`echo $option | sed -e 's/^.*=//;'`
|
||||
;;
|
||||
--with-sendmail=* )
|
||||
mail_program=`echo $option | sed -e 's/^.*=//;'`
|
||||
;;
|
||||
--disable-sechash )
|
||||
feat_sechash=0
|
||||
;;
|
||||
--without-nss )
|
||||
try_nss=0
|
||||
;;
|
||||
--without-tomcrypt )
|
||||
try_tomcrypt=0
|
||||
;;
|
||||
--host-system=* )
|
||||
OPERATINGSYSTEM=`echo $option | sed -e 's/^.*=//;'`
|
||||
@@ -240,83 +359,149 @@ do
|
||||
esac
|
||||
done
|
||||
|
||||
rm -f config.h config.log
|
||||
|
||||
SYSTEM=${OPERATINGSYSTEM}-${MACHINE}
|
||||
|
||||
case $SYSTEM in
|
||||
SunOS-sun4* )
|
||||
case $VERSION in
|
||||
4.* )
|
||||
EXTRA_OBJECTS="sys_sunos.o strerror.o"
|
||||
EXTRA_LIBS="-lkvm"
|
||||
SYSDEFS="-DSUNOS"
|
||||
echo "Configuring for SunOS (" $SYSTEM "version" $VERSION ")"
|
||||
;;
|
||||
5.* )
|
||||
EXTRA_OBJECTS="sys_solaris.o"
|
||||
EXTRA_LIBS="-lsocket -lnsl -lkvm -lelf"
|
||||
EXTRA_CLI_LIBS="-lsocket -lnsl"
|
||||
SYSDEFS="-DSOLARIS"
|
||||
echo "Configuring for Solaris (" $SYSTEM "SunOS version" $VERSION ")"
|
||||
if [ $VERSION = "5.3" ]; then
|
||||
SYSDEFS="$SYSDEFS -DHAS_NO_BZERO"
|
||||
echo "Using memset() instead of bzero()"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
Linux* )
|
||||
EXTRA_OBJECTS="sys_linux.o wrap_adjtimex.o"
|
||||
if [ $feat_rtc -eq 1 ] ; then
|
||||
EXTRA_OBJECTS="$EXTRA_OBJECTS rtc_linux.o"
|
||||
EXTRA_DEFS="$EXTRA_DEFS -DFEAT_RTC=1"
|
||||
fi
|
||||
try_linuxcaps=1
|
||||
case $OPERATINGSYSTEM in
|
||||
Linux)
|
||||
EXTRA_OBJECTS="sys_generic.o sys_linux.o sys_timex.o"
|
||||
[ $try_libcap != "0" ] && try_libcap=1
|
||||
try_rtc=1
|
||||
[ $try_seccomp != "0" ] && try_seccomp=1
|
||||
try_setsched=1
|
||||
try_lockmem=1
|
||||
SYSDEFS="-DLINUX"
|
||||
try_phc=1
|
||||
add_def LINUX
|
||||
echo "Configuring for " $SYSTEM
|
||||
if [ "${MACHINE}" = "alpha" ]; then
|
||||
echo "Enabling -mieee"
|
||||
# FIXME: Should really test for GCC
|
||||
SYSDEFS="$SYSDEFS -mieee -DALPHA"
|
||||
fi
|
||||
;;
|
||||
|
||||
BSD/386-i[3456]86|FreeBSD-i386|FreeBSD-amd64 )
|
||||
# Antti Jrvinen <costello@iki.fi> reported that this system can
|
||||
# be supported with the SunOS 4.x driver files.
|
||||
EXTRA_OBJECTS="sys_sunos.o strerror.o"
|
||||
EXTRA_LIBS="-lkvm"
|
||||
SYSDEFS="-DSUNOS"
|
||||
echo "Configuring for $SYSTEM (using SunOS driver)"
|
||||
;;
|
||||
NetBSD-* )
|
||||
EXTRA_OBJECTS="sys_netbsd.o"
|
||||
EXTRA_LIBS="-lkvm"
|
||||
SYSDEFS=""
|
||||
FreeBSD)
|
||||
EXTRA_OBJECTS="sys_generic.o sys_netbsd.o sys_timex.o"
|
||||
add_def FREEBSD
|
||||
echo "Configuring for $SYSTEM"
|
||||
;;
|
||||
SunOS-i86pc* )
|
||||
# Doug Woodward <dougw@whistler.com> reported that this configuration
|
||||
# works for Solaris 2.8 / SunOS 5.8 on x86 platforms
|
||||
EXTRA_OBJECTS="sys_solaris.o"
|
||||
EXTRA_LIBS="-lsocket -lnsl -lkvm -lelf"
|
||||
EXTRA_CLI_LIBS="-lsocket -lnsl"
|
||||
SYSDEFS="-DSOLARIS"
|
||||
NetBSD)
|
||||
EXTRA_OBJECTS="sys_generic.o sys_netbsd.o sys_timex.o"
|
||||
try_clockctl=1
|
||||
add_def NETBSD
|
||||
echo "Configuring for $SYSTEM"
|
||||
;;
|
||||
Darwin)
|
||||
EXTRA_OBJECTS="sys_macosx.o"
|
||||
EXTRA_LIBS="-lresolv"
|
||||
EXTRA_CLI_LIBS="-lresolv"
|
||||
add_def MACOSX
|
||||
echo "Configuring for MacOS X (" $SYSTEM "MacOS X version" $VERSION ")"
|
||||
;;
|
||||
SunOS)
|
||||
EXTRA_OBJECTS="sys_generic.o sys_solaris.o sys_timex.o"
|
||||
EXTRA_LIBS="-lsocket -lnsl -lresolv"
|
||||
EXTRA_CLI_LIBS="-lsocket -lnsl -lresolv"
|
||||
add_def SOLARIS
|
||||
# These are needed to have msg_control in struct msghdr
|
||||
add_def __EXTENSIONS__
|
||||
add_def _XOPEN_SOURCE 1
|
||||
add_def _XOPEN_SOURCE_EXTENDED 1
|
||||
echo "Configuring for Solaris (" $SYSTEM "SunOS version" $VERSION ")"
|
||||
;;
|
||||
CYGWIN32_NT-i[3456]86 )
|
||||
EXTRA_OBJECTS="sys_winnt.o"
|
||||
EXTRA_LIBS=""
|
||||
SYSDEFS="-DWINNT"
|
||||
echo "Configuring for Windows NT (Cygwin32)"
|
||||
;;
|
||||
* )
|
||||
echo "Sorry, I don't know how to build this software on your system."
|
||||
echo "error: $SYSTEM is not supported (yet?)"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ $feat_debug = "1" ]; then
|
||||
add_def FEAT_DEBUG
|
||||
fi
|
||||
add_def DEBUG $feat_debug
|
||||
|
||||
if [ $feat_cmdmon = "1" ]; then
|
||||
add_def FEAT_CMDMON
|
||||
EXTRA_OBJECTS="$EXTRA_OBJECTS cmdmon.o manual.o pktlength.o"
|
||||
fi
|
||||
|
||||
if [ $feat_ntp = "1" ]; then
|
||||
add_def FEAT_NTP
|
||||
EXTRA_OBJECTS="$EXTRA_OBJECTS ntp_core.o ntp_io.o ntp_sources.o"
|
||||
else
|
||||
feat_asyncdns=0
|
||||
fi
|
||||
|
||||
if [ "$feat_cmdmon" = "1" ] || [ $feat_ntp = "1" ]; then
|
||||
EXTRA_OBJECTS="$EXTRA_OBJECTS addrfilt.o clientlog.o keys.o nameserv.o"
|
||||
else
|
||||
feat_ipv6=0
|
||||
fi
|
||||
|
||||
if [ $feat_refclock = "1" ]; then
|
||||
add_def FEAT_REFCLOCK
|
||||
EXTRA_OBJECTS="$EXTRA_OBJECTS refclock.o refclock_phc.o refclock_pps.o refclock_shm.o refclock_sock.o"
|
||||
fi
|
||||
|
||||
MYCC="$CC"
|
||||
MYCFLAGS="$CFLAGS"
|
||||
MYCPPFLAGS="$CPPFLAGS"
|
||||
MYLDFLAGS="$LDFLAGS"
|
||||
|
||||
if [ "x$MYCC" = "x" ]; then
|
||||
MYCC=gcc
|
||||
if ! test_code "$MYCC" '' '' '' ''; then
|
||||
MYCC=cc
|
||||
if ! test_code "$MYCC" '' '' '' ''; then
|
||||
echo "error: no C compiler found"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if ! test_code "$MYCC" '' '' '' ''; then
|
||||
echo "error: C compiler $MYCC cannot create executables"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "x$MYCFLAGS" = "x" ]; then
|
||||
MYCFLAGS="-O2 -g"
|
||||
fi
|
||||
|
||||
if [ "x$MYCC" = "xgcc" ]; then
|
||||
MYCFLAGS="$MYCFLAGS -Wmissing-prototypes -Wall"
|
||||
fi
|
||||
|
||||
if test_code '64-bit time_t' 'time.h' '' '' '
|
||||
char x[sizeof(time_t) > 4 ? 1 : -1] = {0};
|
||||
return x[0];'
|
||||
then
|
||||
add_def HAVE_LONG_TIME_T 1
|
||||
|
||||
if [ "x$ntp_era_split" != "x" ]; then
|
||||
split_seconds=$ntp_era_split
|
||||
split_days=0
|
||||
else
|
||||
split_seconds=`date '+%s'`
|
||||
if [ "x$split_seconds" = "" ]; then
|
||||
echo "error: could not get current time, --with-ntp-era option is needed"
|
||||
exit 1
|
||||
fi
|
||||
split_days=$((50 * 365))
|
||||
fi
|
||||
|
||||
add_def NTP_ERA_SPLIT "(${split_seconds}LL - $split_days * 24 * 3600)"
|
||||
|
||||
date_format='+%Y-%m-%dT%H:%M:%SZ'
|
||||
|
||||
# Print the full NTP interval if a suitable date is found
|
||||
if [ "x`date -u -d '1970-01-01 UTC 9 days ago 5 seconds 3 seconds' \
|
||||
$date_format 2> /dev/null`" = "x1969-12-23T00:00:08Z" ]
|
||||
then
|
||||
time1="`date -u -d "1970-01-01 UTC $split_days days ago $split_seconds seconds" \
|
||||
$date_format`"
|
||||
time2="`date -u -d "1970-01-01 UTC $split_days days ago $split_seconds seconds 4294967296 seconds" \
|
||||
$date_format`"
|
||||
echo "NTP time mapped to $time1/$time2"
|
||||
fi
|
||||
fi
|
||||
|
||||
MATHCODE='return (int) pow(2.0, log(sqrt((double)argc)));'
|
||||
if test_code 'math' 'math.h' '' '' "$MATHCODE"; then
|
||||
LIBS=""
|
||||
@@ -324,48 +509,134 @@ else
|
||||
if test_code 'math in -lm' 'math.h' '' '-lm' "$MATHCODE"; then
|
||||
LIBS="-lm"
|
||||
else
|
||||
printf "Can't compile/link a program which uses sqrt(), log(), pow(), bailing out\n"
|
||||
echo "error: could not compile/link a program which uses sqrt(), log(), pow()"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test_code '<stdint.h>' 'stdint.h' '' '' ''; then
|
||||
SYSDEFS="${SYSDEFS} -DHAS_STDINT_H"
|
||||
add_def HAVE_STDINT_H
|
||||
fi
|
||||
|
||||
if test_code '<inttypes.h>' 'inttypes.h' '' '' ''; then
|
||||
SYSDEFS="${SYSDEFS} -DHAS_INTTYPES_H"
|
||||
add_def HAVE_INTTYPES_H
|
||||
fi
|
||||
|
||||
if test_code 'struct in_pktinfo' 'sys/socket.h netinet/in.h' '' '' '
|
||||
struct in_pktinfo ipi;
|
||||
return sizeof (ipi.ipi_spec_dst.s_addr) + IP_PKTINFO;'
|
||||
then
|
||||
add_def HAVE_IN_PKTINFO
|
||||
fi
|
||||
|
||||
if [ $feat_ipv6 = "1" ] && \
|
||||
test_code 'IPv6 support' 'arpa/inet.h sys/socket.h netinet/in.h' '' '' '
|
||||
test_code 'IPv6 support' 'arpa/inet.h sys/socket.h netinet/in.h' '' "$EXTRA_LIBS" '
|
||||
struct sockaddr_in6 n;
|
||||
char p[100];
|
||||
n.sin6_addr = in6addr_any;
|
||||
return !inet_ntop(AF_INET6, &n.sin6_addr.s6_addr, p, sizeof(p));'
|
||||
then
|
||||
SYSDEFS="${SYSDEFS} -DHAVE_IPV6"
|
||||
add_def FEAT_IPV6
|
||||
if test_code 'struct in6_pktinfo' 'sys/socket.h netinet/in.h' '' '' '
|
||||
return sizeof (struct in6_pktinfo) + IPV6_PKTINFO;'
|
||||
then
|
||||
add_def HAVE_IN6_PKTINFO
|
||||
else
|
||||
if test_code 'struct in6_pktinfo with _GNU_SOURCE' 'sys/socket.h netinet/in.h' \
|
||||
'-D_GNU_SOURCE' '' 'return sizeof (struct in6_pktinfo) + IPV6_PKTINFO;'
|
||||
then
|
||||
add_def _GNU_SOURCE
|
||||
add_def HAVE_IN6_PKTINFO
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $feat_pps = "1" ] && \
|
||||
test_code 'PPS API' 'timepps.h' '' '' '
|
||||
pps_handle_t h;
|
||||
if test_code 'getaddrinfo()' 'sys/types.h sys/socket.h netdb.h' '' "$EXTRA_LIBS" \
|
||||
'return getaddrinfo(0, 0, 0, 0);'
|
||||
then
|
||||
add_def HAVE_GETADDRINFO
|
||||
fi
|
||||
|
||||
if [ $feat_asyncdns = "1" ] && \
|
||||
test_code 'pthread' 'pthread.h' '-pthread' '' \
|
||||
'return pthread_create((void *)1, NULL, (void *)1, NULL);'
|
||||
then
|
||||
add_def FEAT_ASYNCDNS
|
||||
add_def USE_PTHREAD_ASYNCDNS
|
||||
EXTRA_OBJECTS="$EXTRA_OBJECTS nameserv_async.o"
|
||||
MYCFLAGS="$MYCFLAGS -pthread"
|
||||
fi
|
||||
|
||||
timepps_h=""
|
||||
if [ $feat_refclock = "1" ] && [ $feat_pps = "1" ]; then
|
||||
if test_code '<sys/timepps.h>' 'sys/timepps.h' '' '' ''; then
|
||||
timepps_h="sys/timepps.h"
|
||||
add_def HAVE_SYS_TIMEPPS_H
|
||||
else
|
||||
if test_code '<timepps.h>' 'timepps.h' '' '' ''; then
|
||||
timepps_h="timepps.h"
|
||||
add_def HAVE_TIMEPPS_H
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "x$timepps_h" != "x" ] && \
|
||||
test_code 'PPSAPI' "string.h $timepps_h" '' '' '
|
||||
pps_handle_t h = 0;
|
||||
pps_info_t i;
|
||||
struct timespec ts;
|
||||
return time_pps_fetch(&h, PPS_TSFMT_TSPEC, &i, &ts);'
|
||||
return time_pps_fetch(h, PPS_TSFMT_TSPEC, &i, &ts);'
|
||||
then
|
||||
SYSDEFS="${SYSDEFS} -DHAVE_PPSAPI"
|
||||
add_def FEAT_PPS
|
||||
fi
|
||||
|
||||
if [ $feat_linuxcaps = "1" ] && [ $try_linuxcaps = "1" ] && \
|
||||
if [ $feat_droproot = "1" ] && [ $try_libcap = "1" ] && \
|
||||
test_code \
|
||||
linuxcaps \
|
||||
libcap \
|
||||
'sys/types.h pwd.h sys/prctl.h sys/capability.h grp.h' \
|
||||
'' '-lcap' \
|
||||
'prctl(PR_SET_KEEPCAPS, 1);cap_set_proc(cap_from_text("cap_sys_time=ep"));'
|
||||
then
|
||||
EXTRA_DEFS="${EXTRA_DEFS} -DFEAT_LINUXCAPS=1"
|
||||
EXTRA_LIBS="-lcap"
|
||||
add_def FEAT_PRIVDROP
|
||||
EXTRA_LIBS="$EXTRA_LIBS -lcap"
|
||||
fi
|
||||
|
||||
if [ $feat_droproot = "1" ] && [ $try_clockctl = "1" ] && \
|
||||
test_code '<sys/clockctl.h>' 'sys/clockctl.h' '' '' ''
|
||||
then
|
||||
add_def FEAT_PRIVDROP
|
||||
fi
|
||||
|
||||
if [ $feat_scfilter = "1" ] && [ $try_seccomp = "1" ] && \
|
||||
test_code seccomp 'seccomp.h' '' '-lseccomp' \
|
||||
'seccomp_init(SCMP_ACT_KILL);'
|
||||
then
|
||||
add_def FEAT_SCFILTER
|
||||
EXTRA_LIBS="$EXTRA_LIBS -lseccomp"
|
||||
fi
|
||||
|
||||
if [ $feat_rtc = "1" ] && [ $try_rtc = "1" ] && \
|
||||
test_code '<linux/rtc.h>' 'sys/ioctl.h linux/rtc.h' '' '' \
|
||||
'ioctl(1, RTC_UIE_ON&RTC_UIE_OFF&RTC_RD_TIME&RTC_SET_TIME, 0&RTC_UF);'
|
||||
then
|
||||
EXTRA_OBJECTS="$EXTRA_OBJECTS rtc_linux.o"
|
||||
add_def FEAT_RTC
|
||||
fi
|
||||
|
||||
if [ $feat_refclock = "1" ] && [ $feat_phc = "1" ] && [ $try_phc = "1" ] && \
|
||||
test_code '<linux/ptp_clock.h>' 'sys/ioctl.h linux/ptp_clock.h' '' '' \
|
||||
'ioctl(1, PTP_CLOCK_GETCAPS, 0);'
|
||||
then
|
||||
if test_code 'clock_gettime()' 'time.h' '' '' 'clock_gettime(0, NULL);'; then
|
||||
add_def FEAT_PHC
|
||||
else
|
||||
if test_code 'clock_gettime() in -lrt' 'time.h' '' '-lrt' \
|
||||
'clock_gettime(0, NULL);'
|
||||
then
|
||||
EXTRA_LIBS="$EXTRA_LIBS -lrt"
|
||||
add_def FEAT_PHC
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $try_setsched = "1" ] && \
|
||||
@@ -376,7 +647,7 @@ if [ $try_setsched = "1" ] && \
|
||||
sched_get_priority_max(SCHED_FIFO);
|
||||
sched_setscheduler(0, SCHED_FIFO, &sched);'
|
||||
then
|
||||
SYSDEFS="${SYSDEFS} -DHAVE_SCHED_SETSCHEDULER"
|
||||
add_def HAVE_SCHED_SETSCHEDULER
|
||||
fi
|
||||
|
||||
if [ $try_lockmem = "1" ] && \
|
||||
@@ -387,7 +658,12 @@ if [ $try_lockmem = "1" ] && \
|
||||
setrlimit(RLIMIT_MEMLOCK, &rlim);
|
||||
mlockall(MCL_CURRENT|MCL_FUTURE);'
|
||||
then
|
||||
SYSDEFS="${SYSDEFS} -DHAVE_MLOCKALL"
|
||||
add_def HAVE_MLOCKALL
|
||||
fi
|
||||
|
||||
if [ $feat_forcednsretry = "1" ]
|
||||
then
|
||||
add_def FORCE_DNSRETRY
|
||||
fi
|
||||
|
||||
READLINE_COMPILE=""
|
||||
@@ -398,20 +674,68 @@ if [ $feat_readline = "1" ]; then
|
||||
"$readline_inc" "$readline_lib -ledit" \
|
||||
'add_history(readline("prompt"));'
|
||||
then
|
||||
READLINE_COMPILE="-DFEAT_READLINE=1 -DUSE_EDITLINE=1 $readline_inc"
|
||||
add_def FEAT_READLINE
|
||||
add_def USE_EDITLINE
|
||||
READLINE_COMPILE="$readline_inc"
|
||||
READLINE_LINK="$readline_lib -ledit"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "x$READLINE_LINK" = "x" ] && [ $try_readline = "1" ]; then
|
||||
if test_code readline 'stdio.h readline/readline.h readline/history.h' \
|
||||
"$readline_inc" "$readline_lib -lreadline" \
|
||||
'add_history(readline("prompt"));'
|
||||
then
|
||||
add_def FEAT_READLINE
|
||||
READLINE_COMPILE="$readline_inc"
|
||||
READLINE_LINK="$readline_lib -lreadline"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "x$READLINE_LINK" = "x" ] && [ $try_readline = "1" ]; then
|
||||
if test_code 'readline with -lncurses' \
|
||||
'stdio.h readline/readline.h readline/history.h' \
|
||||
"$readline_inc" "$readline_lib $ncurses_lib -lreadline -lncurses" \
|
||||
'add_history(readline("prompt"));'
|
||||
then
|
||||
READLINE_COMPILE="-DFEAT_READLINE=1 $readline_inc"
|
||||
add_def FEAT_READLINE
|
||||
READLINE_COMPILE="$readline_inc"
|
||||
READLINE_LINK="$readline_lib $ncurses_lib -lreadline -lncurses"
|
||||
fi
|
||||
fi
|
||||
|
||||
EXTRA_CLI_LIBS="$EXTRA_CLI_LIBS $READLINE_LINK"
|
||||
fi
|
||||
|
||||
HASH_OBJ="hash_intmd5.o"
|
||||
HASH_COMPILE=""
|
||||
HASH_LINK=""
|
||||
|
||||
if [ $feat_sechash = "1" ] && [ $try_nss = "1" ]; then
|
||||
test_cflags="`pkg_config --cflags nss`"
|
||||
test_link="`pkg_config --libs-only-L nss` -lfreebl3"
|
||||
if test_code 'NSS' 'nss.h hasht.h nsslowhash.h' \
|
||||
"$test_cflags" "$test_link" \
|
||||
'NSSLOWHASH_Begin(NSSLOWHASH_NewContext(NSSLOW_Init(), HASH_AlgSHA512));'
|
||||
then
|
||||
HASH_OBJ="hash_nss.o"
|
||||
HASH_COMPILE="$test_cflags"
|
||||
HASH_LINK="$test_link"
|
||||
LIBS="$LIBS $HASH_LINK"
|
||||
add_def FEAT_SECHASH
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $feat_sechash = "1" ] && [ "x$HASH_LINK" = "x" ] && [ $try_tomcrypt = "1" ]; then
|
||||
if test_code 'tomcrypt' 'tomcrypt.h' '-I/usr/include/tomcrypt' '-ltomcrypt' \
|
||||
'hash_memory_multi(find_hash("md5"), NULL, NULL, NULL, 0, NULL, 0);'
|
||||
then
|
||||
HASH_OBJ="hash_tomcrypt.o"
|
||||
HASH_COMPILE="-I/usr/include/tomcrypt"
|
||||
HASH_LINK="-ltomcrypt"
|
||||
LIBS="$LIBS $HASH_LINK"
|
||||
add_def FEAT_SECHASH
|
||||
fi
|
||||
fi
|
||||
|
||||
SYSCONFDIR=/etc
|
||||
@@ -459,26 +783,70 @@ if [ "x$SETDOCDIR" != "x" ]; then
|
||||
DOCDIR=$SETDOCDIR
|
||||
fi
|
||||
|
||||
sed -e "s%@EXTRA_OBJECTS@%${EXTRA_OBJECTS}%;\
|
||||
s%@CC@%${MYCC}%;\
|
||||
s%@CFLAGS@%${MYCFLAGS}%;\
|
||||
s%@CCWARNFLAGS@%${CCWARNFLAGS}%;\
|
||||
s%@CPPFLAGS@%${CPPFLAGS}%;\
|
||||
s%@LIBS@%${LIBS}%;\
|
||||
s%@LDFLAGS@%${LDFLAGS}%;\
|
||||
s%@EXTRA_LIBS@%${EXTRA_LIBS}%;\
|
||||
s%@SYSDEFS@%${SYSDEFS}%;\
|
||||
s%@EXTRA_DEFS@%${EXTRA_DEFS}%;\
|
||||
s%@EXTRA_CLI_LIBS@%${EXTRA_CLI_LIBS}%;\
|
||||
s%@READLINE_COMPILE@%${READLINE_COMPILE}%;\
|
||||
s%@READLINE_LINK@%${READLINE_LINK}%;\
|
||||
s%@SYSCONFDIR@%${SYSCONFDIR}%;\
|
||||
s%@BINDIR@%${BINDIR}%;\
|
||||
s%@SBINDIR@%${SBINDIR}%;\
|
||||
s%@DOCDIR@%${DOCDIR}%;\
|
||||
s%@MANDIR@%${MANDIR}%;\
|
||||
s%@INFODIR@%${INFODIR}%;"\
|
||||
< Makefile.in > Makefile
|
||||
LOCALSTATEDIR=/var
|
||||
if [ "x$SETLOCALSTATEDIR" != "x" ]; then
|
||||
LOCALSTATEDIR=$SETLOCALSTATEDIR
|
||||
fi
|
||||
|
||||
CHRONYSOCKDIR=${LOCALSTATEDIR}/run/chrony
|
||||
if [ "x$SETCHRONYSOCKDIR" != "x" ]; then
|
||||
CHRONYSOCKDIR=$SETCHRONYSOCKDIR
|
||||
fi
|
||||
|
||||
CHRONYVARDIR=${LOCALSTATEDIR}/lib/chrony
|
||||
if [ "x$SETCHRONYVARDIR" != "x" ]; then
|
||||
CHRONYVARDIR=$SETCHRONYVARDIR
|
||||
fi
|
||||
|
||||
add_def DEFAULT_CONF_FILE "\"$SYSCONFDIR/chrony.conf\""
|
||||
add_def DEFAULT_HWCLOCK_FILE "\"$default_hwclockfile\""
|
||||
add_def DEFAULT_USER "\"$default_user\""
|
||||
add_def DEFAULT_COMMAND_SOCKET "\"$CHRONYSOCKDIR/chronyd.sock\""
|
||||
add_def MAIL_PROGRAM "\"$mail_program\""
|
||||
|
||||
common_features="`get_features IPV6 DEBUG`"
|
||||
chronyc_features="`get_features READLINE`"
|
||||
chronyd_features="`get_features CMDMON NTP REFCLOCK RTC PRIVDROP SCFILTER SECHASH ASYNCDNS`"
|
||||
add_def CHRONYC_FEATURES "\"$chronyc_features $common_features\""
|
||||
add_def CHRONYD_FEATURES "\"$chronyd_features $common_features\""
|
||||
echo "Features : $chronyd_features $chronyc_features $common_features"
|
||||
|
||||
if [ -f version.txt ]; then
|
||||
CHRONY_VERSION="`cat version.txt`"
|
||||
else
|
||||
CHRONY_VERSION="DEVELOPMENT"
|
||||
fi
|
||||
|
||||
add_def CHRONY_VERSION "\"${CHRONY_VERSION}\""
|
||||
|
||||
for f in Makefile chrony.conf.5 chrony.texi chronyc.1 chronyd.8
|
||||
do
|
||||
echo Creating $f
|
||||
sed -e "s%@EXTRA_OBJECTS@%${EXTRA_OBJECTS}%;\
|
||||
s%@CC@%${MYCC}%;\
|
||||
s%@CFLAGS@%${MYCFLAGS}%;\
|
||||
s%@CPPFLAGS@%${MYCPPFLAGS}%;\
|
||||
s%@LIBS@%${LIBS}%;\
|
||||
s%@LDFLAGS@%${MYLDFLAGS}%;\
|
||||
s%@EXTRA_LIBS@%${EXTRA_LIBS}%;\
|
||||
s%@EXTRA_CLI_LIBS@%${EXTRA_CLI_LIBS}%;\
|
||||
s%@READLINE_COMPILE@%${READLINE_COMPILE}%;\
|
||||
s%@HASH_OBJ@%${HASH_OBJ}%;\
|
||||
s%@HASH_COMPILE@%${HASH_COMPILE}%;\
|
||||
s%@SYSCONFDIR@%${SYSCONFDIR}%;\
|
||||
s%@BINDIR@%${BINDIR}%;\
|
||||
s%@SBINDIR@%${SBINDIR}%;\
|
||||
s%@DOCDIR@%${DOCDIR}%;\
|
||||
s%@MANDIR@%${MANDIR}%;\
|
||||
s%@INFODIR@%${INFODIR}%;\
|
||||
s%@LOCALSTATEDIR@%${LOCALSTATEDIR}%;\
|
||||
s%@CHRONYSOCKDIR@%${CHRONYSOCKDIR}%;\
|
||||
s%@CHRONYVARDIR@%${CHRONYVARDIR}%;\
|
||||
s%@DEFAULT_HWCLOCK_FILE@%${default_hwclockfile}%;\
|
||||
s%@DEFAULT_USER@%${default_user}%;\
|
||||
s%@CHRONY_VERSION@%${CHRONY_VERSION}%;" \
|
||||
< ${f}.in > $f
|
||||
done
|
||||
|
||||
# =======================================================================
|
||||
# vim:et:sw=2:ht=2:sts=2:fdm=marker:cms=#%s
|
||||
|
||||
@@ -1,339 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
@@ -1,583 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
# Copyright (C) Paul Elliott 2002
|
||||
my($copyrighttext) = <<'EOF';
|
||||
# Copyright (C) Paul Elliott 2002
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
# SEE COPYING FOR DETAILS
|
||||
EOF
|
||||
|
||||
#modules we use.
|
||||
|
||||
use Socket;
|
||||
use Getopt::Std;
|
||||
use Net::DNS;
|
||||
use Tie::Syslog;
|
||||
use File::Temp qw/ :mktemp /;
|
||||
use File::Copy;
|
||||
|
||||
local($res) = new Net::DNS::Resolver;
|
||||
|
||||
#dns lookup of IP address.
|
||||
#returns ip or errorstring.
|
||||
sub gethostaddr($) #get ip address from host
|
||||
{
|
||||
my($host) = shift;
|
||||
$query = $res->search($host);
|
||||
if ($query) {
|
||||
foreach $rr ($query->answer) {
|
||||
next unless $rr->type eq "A";
|
||||
print $rr->address, "\n" if $pedebug;
|
||||
return $rr->address;
|
||||
}
|
||||
} else {
|
||||
print "query failed: ", $res->errorstring, "\n" if $pedebug;
|
||||
return $res->errorstring;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#send messages to syslog
|
||||
|
||||
sub Log($$)
|
||||
{
|
||||
if ($log) {
|
||||
my($level) = shift;
|
||||
my($mess) =shift;
|
||||
|
||||
tie *MYLOG, 'Tie::Syslog',$level,$0,'pid','unix';
|
||||
print MYLOG $mess;
|
||||
|
||||
untie *MYLOG;
|
||||
}
|
||||
}
|
||||
|
||||
#send message to output or syslog
|
||||
#and die.
|
||||
|
||||
sub BadDie($)
|
||||
{
|
||||
my($myerr) =$!;
|
||||
my($mess)=shift;
|
||||
|
||||
if($log){
|
||||
tie *MYLOG, 'Tie::Syslog','local0.err',$0,'pid','unix';
|
||||
print MYLOG $mess;
|
||||
print MYLOG $myerr;
|
||||
|
||||
untie *MYLOG;
|
||||
|
||||
} else {
|
||||
print "$mess\n$myerr\n";
|
||||
}
|
||||
die $mess;
|
||||
}
|
||||
|
||||
sub isIpAddr($) #return true if looks like ip address
|
||||
{
|
||||
my($ip) = shift;
|
||||
return 1 if ( $ip =~ m/$ipOnlyPAT/ );
|
||||
return 0;
|
||||
}
|
||||
sub isHostname($) #return true if looks like ip address
|
||||
{
|
||||
my($ip) = shift;
|
||||
return 1 if ( $ip =~ m/$hostnameOnlyPAT/ );
|
||||
return 0;
|
||||
}
|
||||
|
||||
#send commands to chronyc by piping.
|
||||
sub chronyc($) #send commands to chronyc
|
||||
{
|
||||
my($command) = shift;
|
||||
my($err) = "/var/tmp/chronyc.log";
|
||||
my($chronyP) = "/usr/local/bin/chronyc";
|
||||
open(CHRONY, "| $chronyP 1>$err 2>&1");
|
||||
|
||||
print CHRONY "$passwd$command\n";
|
||||
|
||||
close(CHRONY);
|
||||
|
||||
Log('local0.info',"chronyc command issued=$command");
|
||||
#look at status lines till return bad.
|
||||
open( IN, "<$err");
|
||||
my($status);
|
||||
while (<IN>) {
|
||||
$status = $_;
|
||||
|
||||
unless ( m/\A200 OK/ ) {
|
||||
last;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$status ="" if ( $status =~ m/\A200 OK/ );
|
||||
close(IN);
|
||||
unlink $err;
|
||||
Log('local0.info',"chronyc results=$status");
|
||||
return $status;
|
||||
|
||||
}
|
||||
|
||||
#common patterns
|
||||
|
||||
# an ip address patern
|
||||
local($ipPAT) = qr/\d{1,3}(?:\.\d{1,3}){3}/;
|
||||
# an hostname pattern
|
||||
local($hostnamePAT) = qr/\w+(?:\.\w+)*/;
|
||||
#line with hostname only
|
||||
local($hostnameOnlyPAT) = qr/\A$hostnamePAT\Z/;
|
||||
#line with ip address only
|
||||
local($ipOnlyPAT) =qr/\A$ipPAT\Z/;
|
||||
|
||||
#options hash
|
||||
my(%opts);
|
||||
|
||||
|
||||
getopts('nuadslPSC', \%opts);
|
||||
|
||||
local($log) = ( $opts{'l'} ) ? 1 : 0;
|
||||
|
||||
my($offline) = !( $opts{'n'} ) ;
|
||||
my($offlineS) = ( $opts{'n'} ) ? " " : " offline" ;
|
||||
|
||||
# paul elliotts secret debug var. no one will ever find out about it.
|
||||
local($pedebug)=( ($ENV{"PAULELLIOTTDEBUG"}) or ($opts{P}) );
|
||||
|
||||
if ($opts{C}) {
|
||||
|
||||
print $copyrighttext;
|
||||
exit 0;
|
||||
}
|
||||
|
||||
|
||||
print <<"EOF" unless $opts{'S'};
|
||||
$0, Copyright (C) 2002 Paul Elliott
|
||||
$0 comes with ABSOLUTELY NO WARRANTY; for details
|
||||
invoke $0 -C. This is free software, and you are welcome
|
||||
to redistribute it under certain conditions; invoke $0 -C
|
||||
for details.
|
||||
EOF
|
||||
|
||||
|
||||
|
||||
local($passwd);
|
||||
|
||||
# password to send to chronyc
|
||||
my($pl) = $ENV{"CHRONYPASSWORD"};
|
||||
|
||||
#password comand to send to chronyc
|
||||
if ( $pl ) {
|
||||
$passwd = "password $pl\n";
|
||||
} else {
|
||||
$passwd = "";
|
||||
}
|
||||
print "passwd=$passwd\n" if ($pedebug);
|
||||
|
||||
my(%host2ip);
|
||||
|
||||
# hash of arrays. host2ip{$host}[0] is ip address for this host
|
||||
# host2ip{$host}[1] is rest of paramenters for this host exc offline.
|
||||
|
||||
#if debuging do chrony.conf in current directory.
|
||||
my($listfile) =( ($pedebug) ? "./chrony.conf" : "/etc/chrony.conf") ;
|
||||
|
||||
# This section reads in the old data about
|
||||
# hostnames IP addresses and server parameters
|
||||
# data is stored as it would be in chrony.conf
|
||||
# file i.e.:
|
||||
#># HOSTNAME
|
||||
#>server IPADDR minpoll 5 maxpoll 10 maxdelay 0.4 offline
|
||||
#
|
||||
# the parameter offline is omitted if the -n switch is specified.
|
||||
# first parameter is the filename of the file usually
|
||||
# is /etc/DNSchrony.conf
|
||||
# this is where we store the list of DNS hosts.
|
||||
# hosts with static IP address shold be kept in chrony.conf
|
||||
|
||||
# this is header that marks dnyamic host section
|
||||
my($noedithead)=<<'EOF';
|
||||
## DNSchrony dynamic dns server section. DO NOT EDIT
|
||||
## per entry FORMAT:
|
||||
## |--------------------------------------------|
|
||||
## |#HOSTNAME |
|
||||
## |server IP-ADDRESS extra-params [ offline ] |
|
||||
## |--------------------------------------------|
|
||||
EOF
|
||||
#patern that recognizes above.
|
||||
my($noeditheadPAT) =
|
||||
qr/\#\#\s+DNSchrony\s+dynamic\s+dns\s+server\s+section\.\s+DO\s+NOT\s+EDIT\s*/;
|
||||
|
||||
#end of header marker.
|
||||
my($noeditheadend)=<<'EOF';
|
||||
## END OF DNSchrony dynamic dns server section.
|
||||
EOF
|
||||
|
||||
#pattern that matches above.
|
||||
my($noeditheadendPAT)=
|
||||
qr/\#\#\s+END\s+OF\s+DNSchrony\s+dynamic\s+dns\s+server\s+section.\s*/;
|
||||
|
||||
#array to hold non dns portion of chrony.conf
|
||||
my(@chronyDconf);
|
||||
|
||||
|
||||
my($ip);
|
||||
my($rest);
|
||||
my($host);
|
||||
|
||||
# for each entry in the list of hosts....
|
||||
open(READIN, "<$listfile") or BadDie("Can not open $listfile");
|
||||
|
||||
# read till dynamic patern read save in @chronyDconf
|
||||
|
||||
while ( <READIN> ) {
|
||||
|
||||
my($line) = $_;
|
||||
|
||||
last if ( m/\A$noeditheadPAT\Z/ );
|
||||
|
||||
push(@chronyDconf,$line);
|
||||
|
||||
}
|
||||
|
||||
while ( <READIN> ) {
|
||||
|
||||
#end loop when end of header encountered
|
||||
last if ( m/\A$noeditheadendPAT/ );
|
||||
|
||||
# parse the line giving ip address, extra pamamters, and host
|
||||
#do host comment line first
|
||||
($host) = m{
|
||||
\A\#\s*
|
||||
($hostnamePAT)
|
||||
\s*\z
|
||||
}xio;
|
||||
|
||||
#no match skip this line.
|
||||
next unless ( $host );
|
||||
|
||||
# read next line
|
||||
$_ = <READIN>;
|
||||
|
||||
# parse out ip address extra parameters.
|
||||
($ip,$rest) =
|
||||
m{
|
||||
\A
|
||||
\s*
|
||||
server #server comand
|
||||
\s+
|
||||
($ipPAT) #ip address
|
||||
(?ixo: \s )
|
||||
\s*
|
||||
(
|
||||
(?(?!
|
||||
(?iox: offline )? #skip to offline #
|
||||
\s* #or #
|
||||
\Z
|
||||
).)*
|
||||
)
|
||||
(?ixo:
|
||||
\s*
|
||||
(?ixo: offline )? #consume to #
|
||||
\s*
|
||||
\Z
|
||||
)
|
||||
}xio ;
|
||||
|
||||
#if failure again.
|
||||
next unless ( $ip );
|
||||
|
||||
$rest =~ s/\s*\z//; #remove trail blanks
|
||||
#from parameters
|
||||
# store the data in the list
|
||||
# key is host name value is
|
||||
# array [0] is ip address
|
||||
# [1] is other parameters
|
||||
$host2ip{$host} = [$ip,$rest] ;
|
||||
print "ip=$ip rest=$rest host=$host<\n" if $pedebug;
|
||||
|
||||
}
|
||||
#read trailing line into @chronyDconf
|
||||
while ( <READIN> ) {
|
||||
|
||||
push(@chronyDconf,$_);
|
||||
|
||||
}
|
||||
|
||||
close(READIN) or BadDie("can not close $listfile");
|
||||
|
||||
#if the add command:
|
||||
# command can be HOST=IPADDRESS OTHER_PARAMETERS
|
||||
# means add the server trust the ip address geven with out a dns lookup
|
||||
# good for when dns is down but we know the ip addres
|
||||
# or
|
||||
# HOST OTHER_PARAMETERS
|
||||
#we lookup the ip address with dns.
|
||||
|
||||
if ($opts{'a'}) {
|
||||
my($param)= shift;
|
||||
|
||||
|
||||
# parse the param is it hostname
|
||||
if ( ($host,$ip) = $param =~ m/\A($hostnamePAT)=($ipPAT)\Z/ ) {
|
||||
printf "ip=$ip host=$host\n" if ($pedebug);
|
||||
} else {
|
||||
|
||||
$host = $param;
|
||||
|
||||
# get the ip address
|
||||
$ip = gethostaddr($host);
|
||||
|
||||
if ( ! isIpAddr($ip) or ! isHostname($host) ) {
|
||||
print "query failed: ", $ip, "host=$host\n" if $pedebug;
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
printf "ip=$ip host=$host\n" if ($pedebug);
|
||||
|
||||
# add the server using chronyc
|
||||
my($status) = chronyc("add server $ip $rest");
|
||||
if ($status) { #chronyc error
|
||||
print "chronyc failed, status=$status\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
# get rest of arguements
|
||||
$rest = join( ' ', @ARGV);
|
||||
print "rest=$rest\n" if ($pedebug);
|
||||
|
||||
#save node in hash
|
||||
$host2ip{$host} = [$ip,$rest] ;
|
||||
print "ip=$ip rest=$rest host=$host<\n" if $pedebug;
|
||||
|
||||
}
|
||||
|
||||
#delete command if arguement is ip address
|
||||
#just delete it
|
||||
#if a hostname look it up
|
||||
#then delete it.
|
||||
|
||||
if ($opts{'d'}) {
|
||||
$host = shift;
|
||||
|
||||
#get host name is it ap address
|
||||
if ( isIpAddr($host) ) { # if ip address
|
||||
my($hostIT);
|
||||
my($found) =0;
|
||||
foreach $hostIT (keys(%host2ip) ) { #search for match
|
||||
if ( $host2ip{$hostIT}[0] eq $host) {
|
||||
$found=1; #record match
|
||||
}
|
||||
} #end of search
|
||||
if ($found) { #if match found
|
||||
my($status) = chronyc("delete $host"); #chronyc
|
||||
if ($status) { #chronyc error
|
||||
print "chronyc failed, status=$status\n";
|
||||
exit 1;
|
||||
} else { #reiterate
|
||||
foreach $hostIT (keys(%host2ip) ) {
|
||||
if ( $host2ip{$hostIT}[0] eq $host) {
|
||||
delete $host2ip{$hostIT}; #deleting match hosts
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} else { #else not ip address
|
||||
#must be hostname
|
||||
if ( ! $host2ip{$host} ) {
|
||||
print "No such host as $host listed\n";
|
||||
exit 1;
|
||||
}
|
||||
#get ip address
|
||||
$ip=gethostaddr($host);
|
||||
if ( ! isIpAddr($ip) ) { #no ip address
|
||||
print "query failed: ", $ip, "\n" if $pedebug;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
printf "ip=$ip host=$host\n" if ($pedebug);
|
||||
|
||||
my($listed_host_ip) = $host2ip{$host}[0]; # get the ip address saved
|
||||
|
||||
if ( $ip ne $listed_host_ip) {
|
||||
print
|
||||
"Info: listed host ip=>$listed_host_ip".
|
||||
"< is different from DNS ip=>$ip<\n";
|
||||
$ip = $listed_host_ip;
|
||||
}
|
||||
|
||||
# delete the server
|
||||
my($status) = chronyc("delete $listed_host_ip\n");
|
||||
|
||||
if ($status) {
|
||||
print "chronyc failed, status=$status\n";
|
||||
exit 1;
|
||||
}
|
||||
#delete table entry
|
||||
delete$host2ip{$host};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#update for each host who's dns ip address has changed
|
||||
#delete the old server and add the new. update the record.
|
||||
if ($opts{'u'}) {
|
||||
my($command);
|
||||
|
||||
my(%prospective); # store new IP address we
|
||||
#are thinking of changing.
|
||||
|
||||
Log('local0.info',
|
||||
"Now searching for modified DNS entries.");
|
||||
|
||||
foreach $host (keys(%host2ip)) { #for each listed host
|
||||
my($old_ip) = $host2ip{$host}[0]; #get old ip
|
||||
$rest = $host2ip{$host}[1]; #extra params
|
||||
|
||||
$ip = gethostaddr($host); #get new ip from dns
|
||||
#if error
|
||||
if ( ! isIpAddr($ip) or ! isHostname($host) ) {
|
||||
print "query failed: ", $ip, "host=$host\n";
|
||||
|
||||
Log('local0.err',"query failed: ". $ip . "host=$host");
|
||||
|
||||
exit 1;
|
||||
}
|
||||
|
||||
next if($ip eq $old_ip); #if ip not changed, skip
|
||||
|
||||
Log('local0.info',"Ip address for $host has changed. Old IP address=".
|
||||
"$old_ip, new IP address=$ip");
|
||||
# add command to delete old host, add the new.
|
||||
$command = $command . "delete $old_ip\n" .
|
||||
"add server $ip $rest\n";
|
||||
|
||||
# we are now thinking about changing this host ip
|
||||
$prospective{$host} = [$ip,$rest];
|
||||
}
|
||||
# submit all the accumulated chronyc commands if any.
|
||||
if ($command) {
|
||||
$status = chronyc($command);
|
||||
if ($status) {
|
||||
print "chronyc failed, status=$status\n";
|
||||
Log('local0.err',"query failed: ". $ip . "host=$host");
|
||||
exit 1;
|
||||
}
|
||||
} else { #if no commands exit
|
||||
exit 0; #because no rewrite of file needed
|
||||
}
|
||||
|
||||
#copy prospective modifications back into main table.
|
||||
#we now know that all these mods were done with chronyc
|
||||
foreach $host (keys(%prospective)) {
|
||||
my($ip) = $prospective{$host}[0];
|
||||
$rest = $prospective{$host}[1];
|
||||
$host2ip{$host} = [$ip,$rest];
|
||||
}
|
||||
}
|
||||
|
||||
#starting for each entry we have read in from the old list
|
||||
# add the server in chronyc
|
||||
# this option is seldom used.
|
||||
|
||||
if ($opts{'s'}) {
|
||||
my($command)="";
|
||||
|
||||
foreach $host (keys(%host2ip)) {
|
||||
$command = $command . "add server $host2ip{$host}[0] ".
|
||||
"$host2ip{$host}[1]\n";
|
||||
}
|
||||
my($status) = chronyc($command);
|
||||
if ($status) {
|
||||
print "chronyc failed, status=$status\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
}
|
||||
# write out the data file in format
|
||||
#># HOSTNAME
|
||||
#>server IPADDRESS extra parameters [offline]
|
||||
# offline is omitted if -n switch is specified.
|
||||
|
||||
my(@value);
|
||||
my($such);
|
||||
{
|
||||
# to start out we write to temporary file.
|
||||
(my($writeout) , my($outname)) = mkstemp( "${listfile}.outXXXXXXX");
|
||||
|
||||
$outname or BadDie("can not open for $listfile");
|
||||
|
||||
|
||||
# save the chrony.conf part!
|
||||
# and write the DYNAMIC header
|
||||
print $writeout @chronyDconf, $noedithead;
|
||||
|
||||
|
||||
# for each entry
|
||||
foreach $host (keys(%host2ip) ){
|
||||
|
||||
#write the record
|
||||
|
||||
# write the comment that indicates the hostname
|
||||
# and the server command.
|
||||
print $writeout
|
||||
"\# $host\nserver $host2ip{$host}[0] $host2ip{$host}[1]${offlineS}\n" ;
|
||||
|
||||
print
|
||||
"server $host2ip{$host}[0] $host2ip{$host}[1]${offlineS}\# $host\n"
|
||||
if $pedebug;
|
||||
|
||||
}
|
||||
|
||||
#WRITE THE end of dnyamic marker comment
|
||||
print $writeout $noeditheadend;
|
||||
|
||||
# close the output file which was a temporary file.
|
||||
close($writeout) or BadDie("can not close $outname");
|
||||
|
||||
# we now begin a intracate dance to make the the temporary
|
||||
# the main chrony.conf
|
||||
#
|
||||
# if there is a chrony.conf.BAK save it to a temporary.
|
||||
# rename chrony.conf to chrony.conf.BAK
|
||||
# rename the temporary to chrony.conf
|
||||
# if there already was a chrony.conf.BAK, unlink the copy of this.
|
||||
|
||||
my($backname) = "$listfile\.BAK";
|
||||
my($backplain) = ( -f $backname );
|
||||
my($saveback);
|
||||
#if chrony.conf.BAK exists rename to a temporary.
|
||||
if ($backplain ) {
|
||||
|
||||
$saveback = mktemp("${backname}.bakXXXXXXX");
|
||||
move($backname,$saveback) or
|
||||
BadDie "unable to move $backname to $savename";
|
||||
|
||||
}
|
||||
|
||||
# rename old chrony.conf to chrony.conf.BAK
|
||||
move($listfile,$backname) or
|
||||
BadDie "unable to move $listfile to $backname";
|
||||
|
||||
# rename our output to chrony.conf
|
||||
move($outname,$listfile) or
|
||||
BadDie "unable to move $outname to $listfile";
|
||||
|
||||
#if there was a temporary chrony.conf.BAK that we saved to temp
|
||||
#unlink it
|
||||
unlink($saveback) or BadDie "unable to unlink $saveback" if($backplain);
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
# $1 is chrony password.
|
||||
# $2 is hostname to add or hostname=ipaddres
|
||||
# $3-$9 is rest of extra server parameters
|
||||
|
||||
FIRST="$1"
|
||||
HOST="$2"
|
||||
shift 2
|
||||
|
||||
#remaining parameters a the other paramaters to server command
|
||||
#excluding "offline"
|
||||
ARGS="$*"
|
||||
|
||||
#if none use default taken from chrony documentation.
|
||||
DEF="minpoll 5 maxpoll 10 maxdelay 0.4"
|
||||
|
||||
DARGS=${ARGS:-$DEF}
|
||||
|
||||
CHRONYPASSWORD=$FIRST \
|
||||
/usr/local/bin/DNSchrony.pl -a "$HOST" "$DARGS"
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
# $1 is chrony password.
|
||||
# $2 host to be deleted if ip nn.n.n.n then no DNS used
|
||||
|
||||
CHRONYPASSWORD=$1 \
|
||||
/usr/local/bin/DNSchrony.pl -d $2
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
# $1 is chrony password.
|
||||
|
||||
|
||||
CHRONYPASSWORD=$1 \
|
||||
/usr/local/bin/DNSchrony.pl -ulS
|
||||
@@ -1,166 +0,0 @@
|
||||
Copyright (C) Paul Elliott 2002
|
||||
|
||||
|
||||
DNSchrony.pl version -2.0
|
||||
|
||||
Problem: If you look at the list of secondary NTP servers:
|
||||
http://www.eecis.udel.edu/~mills/ntp/clock2.htm
|
||||
|
||||
you will find statements like this:
|
||||
|
||||
"Note: IP addresses are subject to change; please use DNS"
|
||||
|
||||
These servers represent a problem for chrony. Chrony is a program
|
||||
designed to work on hosts with an intermittent connection to the
|
||||
internet. Often no DNS is available when chrony starts. As chrony
|
||||
is currently designed, chronyd never sees a DNS host name. If a
|
||||
user specifies one when using chronyc's "add server" command, the
|
||||
DNS lookup is done by chronyc and an IP address is passed to chronyd.
|
||||
|
||||
One can imagine I suppose, a redesign to chrony in which chronyd
|
||||
keeps track of DNS changes. But this has problems, all the time
|
||||
chronyd is fooling around with DNS, it would not be keeping track
|
||||
of its prime function, what the clocks and NTP servers are saying.
|
||||
This could result in poorer performance. Or perhaps you say that
|
||||
chronyd should be multi threaded. One thread to fool with DNS
|
||||
and another to keep track of time. But this introduces a great
|
||||
deal of complexity, and complexity is the enemy of elegant robust
|
||||
code. Besides, Richard probably has better things to do.
|
||||
|
||||
I have attempted to address this problem with a humble perl script,
|
||||
which I now release under the GPL: DNSchrony.pl
|
||||
|
||||
PLEA FOR HELP FROM EXPERIENCED PERL HACKERS.
|
||||
|
||||
Please go thru the code and find errors and improvements.
|
||||
I am not quite an polished perl hacker. Please fix bugs and
|
||||
make improvements. It needs better documentation. Someone
|
||||
who knows how, put in some POD.
|
||||
|
||||
END OF PLEA
|
||||
|
||||
Philosophy of DNSchrony.pl: keep a list of servers that use
|
||||
DNS. From time to time, hopefully when DNS is up, go thru
|
||||
the list lookup all the hostnames and see if any ip addresses have
|
||||
changed. If any have changed, update our list and do chronyc
|
||||
"delete" and "add server" commands so that chronyd now talks to
|
||||
the right NTP server.
|
||||
|
||||
Additional nuance: keep the list in /etc/chrony.conf in the
|
||||
form of comments starting with "#" and "server" commands
|
||||
legal in a chrony.conf file. Format of a list entry:
|
||||
|
||||
# hostname
|
||||
server IP-ADDRESS extra server parameters
|
||||
|
||||
These entries are delimited by special comments that allow
|
||||
DNSchrony.pl to find them and also tell humans not to mess with them.
|
||||
|
||||
Example of such a section of a chrony.conf file:
|
||||
|
||||
dumpdir /var/log/chrony
|
||||
rtcfile /etc/chrony.rtc
|
||||
|
||||
## DNSchrony dynamic dns server section. DO NOT EDIT
|
||||
## per entry FORMAT:
|
||||
## |--------------------------------------------|
|
||||
## |#HOSTNAME |
|
||||
## |server IP-ADDRESS extra-params [ offline ] |
|
||||
## |--------------------------------------------|
|
||||
# tock.greyware.com
|
||||
server 208.14.208.44 minpoll 5 maxpoll 10 maxdelay 0.4 offline
|
||||
# tick.greyware.com
|
||||
server 208.14.208.19 minpoll 5 maxpoll 10 maxdelay 0.4 offline
|
||||
# ntppub.tamu.edu
|
||||
server 128.194.254.9 minpoll 5 maxpoll 10 maxdelay 0.4 offline
|
||||
## END OF DNSchrony dynamic dns server section.
|
||||
|
||||
This allows the list of dynamic DNS servers to be preserved
|
||||
when chronyd is stoped/started.
|
||||
|
||||
All servers that do not have ip addresses subject to change
|
||||
should be put in the regular part of chrony.conf as described
|
||||
in the chrony documentation.
|
||||
|
||||
Security philosophy: DNSchrony does no security checking but
|
||||
relies on other security factors.
|
||||
|
||||
Users without the privilege to modify /etc/chrony.conf and the
|
||||
directory /etc will be unable to use DNSchrony to do so, because
|
||||
of file protections. DNSchrony passes thru passwords to chronyc.
|
||||
Users that do not know the correct chronyc password will be
|
||||
unable to get chronyd do do anything. Thus, DNSchrony passes
|
||||
the buck to these other security features.
|
||||
|
||||
INSTALLATION:
|
||||
|
||||
copy the files: DNSchronyADD DNSchronyUPDATE DNSchronyDELETE DNSchrony.pl
|
||||
to /usr/local/bin. Backup the file /etc/chrony.conf leave hosts
|
||||
with static ip addresses in this file.
|
||||
|
||||
DNSchrony uses the following perl modules. See that they are installed.
|
||||
Get them from CPAN if needed.
|
||||
|
||||
Net::DNS, Tie::Syslog, Getopt::Std, Socket, File.
|
||||
|
||||
Cause DNSchronyUPDATE bash script to run from time to time when DNS
|
||||
is working. If you have a dialup, one way to do this would be to
|
||||
modify your /etc/ppp/ip-up.local file as follows:
|
||||
|
||||
cat <<EOF | /usr/local/bin/chronyc
|
||||
password mysecret
|
||||
online
|
||||
EOF
|
||||
# update all of the dynamic servers and save the result.
|
||||
# do not wait for response
|
||||
|
||||
nohup /usr/local/bin/DNSchronyUPDATE mysecret >/dev/null 2>&1 &
|
||||
|
||||
Since this file contains the chronyc password you will want to set the
|
||||
file permissions so that just everybody will not be able to read
|
||||
it. But you already did that when you put in the chronyc command. Any
|
||||
other way to make DNSchronyUPDATE run perodicly when DNS is up will
|
||||
also work.
|
||||
|
||||
To add a server with a varying IP address one could run:
|
||||
/usr/local/bin/DNSchronyADD mysecret tock.greyware.com
|
||||
|
||||
or if you want to specify different server parameters you
|
||||
could say:
|
||||
|
||||
/usr/local/bin/DNSchronyADD mysecret tock.greyware.com "minpoll 10 maxpoll 20 maxdelay 0.8"
|
||||
|
||||
The DNSchronyADD's default for these parameters is:
|
||||
"minpoll 5 maxpoll 10 maxdelay 0.4" values that are often shown
|
||||
as examples in the chrony documentation.
|
||||
|
||||
If DNS is not running now but you know the IP address, you can say:
|
||||
/usr/local/bin/DNSchronyADD mysecret tock.greyware.com=208.14.208.44
|
||||
|
||||
Of course, the IP address will be checked next time DNSchronyUPDATE
|
||||
runs.
|
||||
|
||||
To delete dynamic DNS a server:
|
||||
/usr/local/bin/DNSchronyDELETE mysecret tock.greyware.com
|
||||
|
||||
To change parameters delete and re-add.
|
||||
|
||||
Of course, in all of the above "mysecret" is your chronyc password
|
||||
which SHOULD NOT BE "mysecret".
|
||||
----------------------------------------------
|
||||
DNSchrony.pl is covered by the GPL
|
||||
# Copyright (C) Paul Elliott 2002
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
# SEE COPYING FOR DETAILS
|
||||
@@ -1,22 +0,0 @@
|
||||
#example file /etc/ppp/ip-up.local
|
||||
#originally from SuSE distribution
|
||||
#modified for chrony
|
||||
cat <<EOF | /usr/local/bin/chronyc
|
||||
password mysecret
|
||||
online
|
||||
EOF
|
||||
# update all of the dynamic servers and save the result.
|
||||
# do not wait for response
|
||||
|
||||
nohup /usr/local/bin/DNSchronyUPDATE mysecret >/dev/null 2>&1 &
|
||||
#other stuff who knows?
|
||||
|
||||
# The following lines added for Linux-HA support # Heartbeat
|
||||
DEVFILE=`echo $DEVICE | sed -e 's!^/dev/!!' -e 's!/!.!g'` # Heartbeat
|
||||
OUTFILE=/var/run/ppp.d/$DEVFILE # Heartbeat
|
||||
( # Heartbeat
|
||||
echo "$IPREMOTE" # Heartbeat
|
||||
echo "$IFNAME" # Heartbeat
|
||||
echo "$PPPD_PID" # Heartbeat
|
||||
echo "$IPLOCAL" # Heartbeat
|
||||
) > $OUTFILE # Heartbeat
|
||||
103
contrib/bryan_christianson_1/README.txt
Normal file
103
contrib/bryan_christianson_1/README.txt
Normal file
@@ -0,0 +1,103 @@
|
||||
Notes for installing chrony on MacOS X
|
||||
Author: Bryan Christianson (bryan@whatroute.net)
|
||||
------------------------------------------------
|
||||
|
||||
These files are for those admins/users who would prefer to install chrony
|
||||
from the source distribution and are intended as guidelines rather than
|
||||
being definitive. They can be edited with a plain text editor, such as
|
||||
vi, emacs or your favourite IDE (xcode)
|
||||
|
||||
It is assumed you are comfortable with installing software from the
|
||||
terminal command line and know how to use sudo to acquire root access.
|
||||
|
||||
If you are not familiar with the MacOS X command line then
|
||||
please consider using ChronyControl from http://whatroute.net/chronycontrol.html
|
||||
|
||||
ChronyControl provides a gui wrapper for installing these files and sets the
|
||||
necessary permissions on each file.
|
||||
|
||||
|
||||
Install the chrony software
|
||||
---------------------------
|
||||
|
||||
You will need xcode and the commandline additions to build and install chrony.
|
||||
These can be obtained from Apple's website via the App Store.
|
||||
|
||||
cd to the chrony directory
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
|
||||
chrony is now installed in default locations (/usr/local/sbin/chronyd,
|
||||
/usr/local/bin/chronyc)
|
||||
|
||||
Create a chrony.conf file - see the chrony website for details
|
||||
|
||||
The support files here assume the following directives are specified in the
|
||||
chrony.conf file
|
||||
|
||||
keyfile /etc/chrony.d/chrony.keys
|
||||
driftfile /var/db/chrony/chrony.drift
|
||||
bindcmdaddress /var/db/chrony/chronyd.sock
|
||||
logdir /var/log/chrony
|
||||
dumpdir /var/db/chrony
|
||||
|
||||
Install this file as /etc/chrony.d/chrony.conf and create
|
||||
the directories specified in the above directives if they don't exist.
|
||||
You will need root permissions to create the directories.
|
||||
|
||||
|
||||
Running chronyd
|
||||
---------------
|
||||
At this point chronyd *could* be run as a daemon. Apple discourage running
|
||||
daemons and their preferred method uses the launchd facility. The
|
||||
support files here provide a launchd configuration file for chronyd and also
|
||||
a shell script and launchd configuration file to rotate the chronyd logs on a daily basis.
|
||||
|
||||
|
||||
Support files
|
||||
-------------
|
||||
Dates and sizes may differ
|
||||
-rw-r--r-- 1 yourname staff 2084 4 Aug 22:54 README.txt
|
||||
-rwxr-xr-x 1 yourname staff 676 4 Aug 21:18 chronylogrotate.sh
|
||||
-rw-r--r-- 1 yourname staff 543 18 Jul 20:10 org.tuxfamily.chronyc.plist
|
||||
-rw-r--r-- 1 yourname staff 511 19 Jun 18:30 org.tuxfamily.chronyd.plist
|
||||
|
||||
If you have used chrony support directories other than those suggested, you
|
||||
will need to edit each file and make the appropriate changes.
|
||||
|
||||
|
||||
Installing the support files
|
||||
----------------------------
|
||||
|
||||
1. chronylogrotate.sh
|
||||
This is a simple shell script that deletes old log files. Unfortunately because
|
||||
of the need to run chronyc, the standard MacOS X logrotation does not work with
|
||||
chrony logs.
|
||||
|
||||
This script runs on a daily basis under control of launchd and should be
|
||||
installed in the /usr/local/bin directory
|
||||
|
||||
sudo cp chronylogrotate.sh /usr/local/bin
|
||||
sudo chmod +x /usr/local/bin/chronylogrotate.sh
|
||||
sudo chown root:wheel /usr/local/bin/chronylogrotate.sh
|
||||
|
||||
|
||||
2. org.tuxfamily.chronyc.plist
|
||||
This file is the launchd plist that runs logrotation each day. You may
|
||||
wish to edit this file to change the time of day at which the rotation
|
||||
will run, currently 04:05 am
|
||||
|
||||
sudo cp org.tuxfamily.chronyc.plist /Library/LaunchDaemons
|
||||
sudo chown root:wheel /Library/LaunchDaemons/org.tuxfamily.chronyc.plist
|
||||
sudo chmod 0644 /Library/LaunchDaemons/org.tuxfamily.chronyc.plist
|
||||
sudo launchctl load -w /Library/LaunchDaemons/org.tuxfamily.chronyc.plist
|
||||
|
||||
|
||||
3. org.tuxfamily.chronyd.plist
|
||||
This file is the launchd plist that runs chronyd when the Macintosh starts.
|
||||
|
||||
sudo cp org.tuxfamily.chronyd.plist /Library/LaunchDaemons
|
||||
sudo chown root:wheel /Library/LaunchDaemons/org.tuxfamily.chronyd.plist
|
||||
sudo chmod 0644 /Library/LaunchDaemons/org.tuxfamily.chronyd.plist
|
||||
sudo launchctl load -w /Library/LaunchDaemons/org.tuxfamily.chronyd.plist
|
||||
45
contrib/bryan_christianson_1/chronylogrotate.sh
Executable file
45
contrib/bryan_christianson_1/chronylogrotate.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
|
||||
# chronylogrotate.sh
|
||||
# ChronyControl
|
||||
#
|
||||
# Created by Bryan Christianson on 12/07/15.
|
||||
#
|
||||
|
||||
LOGDIR=/var/log/chrony
|
||||
|
||||
if [ ! -e "$LOGDIR" ]; then
|
||||
echo "missing directory: $LOGDIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd $LOGDIR
|
||||
|
||||
rotate () {
|
||||
prefix=$1
|
||||
|
||||
rm -f $prefix.log.10
|
||||
|
||||
for (( count=9; count>= 0; count-- ))
|
||||
do
|
||||
next=$(( $count+1 ))
|
||||
if [ -f $prefix.log.$count ]; then
|
||||
mv $prefix.log.$count $prefix.log.$next
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -f $prefix.log ]; then
|
||||
mv $prefix.log $prefix.log.0
|
||||
fi
|
||||
}
|
||||
|
||||
rotate measurements
|
||||
rotate statistics
|
||||
rotate tracking
|
||||
|
||||
#
|
||||
# signal chronyd via chronyc
|
||||
|
||||
/usr/local/bin/chronyc -a -f /etc/chrony.d/chrony.conf cyclelogs > /dev/null
|
||||
|
||||
exit $?
|
||||
22
contrib/bryan_christianson_1/org.tuxfamily.chronyc.plist
Normal file
22
contrib/bryan_christianson_1/org.tuxfamily.chronyc.plist
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>org.tuxfamily.logrotate</string>
|
||||
<key>KeepAlive</key>
|
||||
<false/>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/sh</string>
|
||||
<string>/usr/local/bin/chronylogrotate.sh</string>
|
||||
</array>
|
||||
<key>StartCalendarInterval</key>
|
||||
<dict>
|
||||
<key>Minute</key>
|
||||
<integer>5</integer>
|
||||
<key>Hour</key>
|
||||
<integer>4</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
19
contrib/bryan_christianson_1/org.tuxfamily.chronyd.plist
Normal file
19
contrib/bryan_christianson_1/org.tuxfamily.chronyd.plist
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>org.tuxfamily.chronyd</string>
|
||||
<key>Program</key>
|
||||
<string>/usr/local/sbin/chronyd</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>chronyd</string>
|
||||
<string>-n</string>
|
||||
<string>-f</string>
|
||||
<string>/private/etc/chrony.d/chrony.conf</string>
|
||||
</array>
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
379
doc/faq.adoc
Normal file
379
doc/faq.adoc
Normal file
@@ -0,0 +1,379 @@
|
||||
:toc:
|
||||
:numbered:
|
||||
|
||||
Frequently Asked Questions
|
||||
==========================
|
||||
|
||||
== +chrony+ compared to other programs
|
||||
|
||||
=== How does +chrony+ compare to +ntpd+?
|
||||
|
||||
+chronyd+ was designed to work well in a wide range of conditions and it can
|
||||
usually synchronise the system clock faster and with better time accuracy. It
|
||||
doesn't implement some of the less useful NTP modes like broadcast client or
|
||||
multicast server/client.
|
||||
|
||||
For a more detailed comparison of features and performance, see the
|
||||
http://chrony.tuxfamily.org/comparison.html[comparison page] on the +chrony+
|
||||
website and the
|
||||
http://chrony.tuxfamily.org/manual.html#Comparison-with-ntpd[Comparison with
|
||||
ntpd] section in the manual.
|
||||
|
||||
If your computer is connected to the internet only for few minutes at a time,
|
||||
the network connection is often congested, you turn your computer off or
|
||||
suspend it frequently, the clock is not very stable (e.g. there are rapid
|
||||
changes in the temperature or it's a virtual machine), or you want to use NTP
|
||||
on an isolated network with no hardware reference clocks in sight, +chrony+
|
||||
will probably work much better for you.
|
||||
|
||||
The original reason +chrony+ was written was that +ntpd+ (called +xntpd+ at the
|
||||
time) could not to do anything sensible on a PC which was connected to the 'net
|
||||
only for about 5 minutes once or twice a day, mainly to upload/download email
|
||||
and news. The requirements were
|
||||
|
||||
* slew the time to correct it when going online and NTP servers
|
||||
become visible
|
||||
* determine the rate at which the computer gains or loses time and
|
||||
use this information to keep it reasonably correct between connects
|
||||
to the 'net. This has to be done using a method that does not care
|
||||
about the intermittent availability of the references or the fact
|
||||
the computer is turned off between groups of measurements.
|
||||
* maintain the time across reboots, by working out the error and
|
||||
drift rate of the computer's real-time clock and using this
|
||||
information to set the system clock correctly at boot up.
|
||||
|
||||
Also, when working with isolated networks with no true time references at all
|
||||
+ntpd+ was found to give no help with managing the local clock's gain/loss rate
|
||||
on the NTP master node (which was set from watch). Some automated support was
|
||||
added to +chrony+ to deal with this.
|
||||
|
||||
== Configuration issues
|
||||
|
||||
=== What is the minimum recommended configuration for an NTP client?
|
||||
|
||||
First, the client needs to know which NTP servers it should ask for the current
|
||||
time. They are specified by the +server+ or +pool+ directive. The +pool+
|
||||
directive can be used for names that resolve to multiple addresses. For good
|
||||
reliability the client should have at least three servers. The +iburst+ option
|
||||
speeds up the initial synchronisation.
|
||||
|
||||
To stabilize the initial synchronisation on the next start, the estimated drift
|
||||
of the system clock is saved by adding the +driftfile+ directive.
|
||||
|
||||
If the system clock can be far from the true time after boot for any reason,
|
||||
+chronyd+ should be allowed to correct it quickly by stepping instead of
|
||||
slewing, which would take a very long time. The +makestep+ directive does
|
||||
that.
|
||||
|
||||
In order to keep the real-time clock (RTC) close to the true time on Linux, so
|
||||
the system time is reasonably close to the true time when it's initialized on
|
||||
the next boot from the RTC, the +rtcsync+ directive enables a kernel mode in
|
||||
which the system time is copied to the RTC every 11 minutes.
|
||||
|
||||
If you want to use public NTP servers from the
|
||||
http://www.pool.ntp.org/[pool.ntp.org] project, the minimal 'chrony.conf' file
|
||||
could be:
|
||||
|
||||
----
|
||||
pool pool.ntp.org iburst
|
||||
driftfile /var/lib/chrony/drift
|
||||
makestep 1 3
|
||||
rtcsync
|
||||
----
|
||||
|
||||
=== How do I make an NTP server from an NTP client?
|
||||
|
||||
You need to add an +allow+ directive to the 'chrony.conf' file in order to open
|
||||
the NTP port and allow +chronyd+ to reply to client requests. +allow+ with no
|
||||
specified subnet allows all IPv4 and IPv6 addresses.
|
||||
|
||||
=== I have several computers on a LAN. Should be all clients of an external server?
|
||||
|
||||
The best configuration is usually to make one computer the master, with
|
||||
the others as clients of it. Add a +local+ directive to the master's
|
||||
'chrony.conf' file. This configuration will be better because
|
||||
|
||||
* the load on the external connection is less
|
||||
* the load on the external NTP server(s) is less
|
||||
* if your external connection goes down, the computers on the LAN
|
||||
will maintain a common time with each other.
|
||||
|
||||
=== Must I specify servers by IP address if DNS is not available on chronyd start?
|
||||
|
||||
No. Starting from version 1.25, +chronyd+ will keep trying to resolve
|
||||
the hostnames specified in the +server+ and +peer+ directives in
|
||||
increasing intervals until it succeeds. The +online+ command can be
|
||||
issued from +chronyc+ to try to resolve them immediately.
|
||||
|
||||
=== How can I make +chronyd+ more secure?
|
||||
|
||||
If you don't need to serve time to NTP clients or peers, you can add +port 0+
|
||||
to the 'chrony.conf' file to completely disable the NTP server functionality
|
||||
and prevent NTP requests from reaching +chronyd+. Starting from version 2.0,
|
||||
the NTP server port is open only when client access is allowed by the +allow+
|
||||
directive or command, an NTP peer is configured, or the +broadcast+ directive
|
||||
is used.
|
||||
|
||||
If you don't need to use +chronyc+ remotely, you can add the following
|
||||
directives to the configuration file to bind the command sockets to the
|
||||
loopback interface. This is done by default since version 2.0.
|
||||
|
||||
----
|
||||
bindcmdaddress 127.0.0.1
|
||||
bindcmdaddress ::1
|
||||
----
|
||||
|
||||
If you don't need to use +chronyc+ at all or you need to run +chronyc+ only
|
||||
under the root or chrony user (which can access +chronyd+ through a Unix domain
|
||||
socket since version 2.2), you can disable the internet command sockets
|
||||
completely by adding +cmdport 0+ to the configuration file.
|
||||
|
||||
On Linux, if +chronyd+ is compiled with support for Linux capabilities
|
||||
(available in the libcap library), or on NetBSD with the +/dev/clockctl+
|
||||
device, you can specify an unprivileged user with the +-u+ option or +user+
|
||||
directive in the 'chrony.conf' file to drop root privileges after start. The
|
||||
configure option +--with-user+ can be used to drop the privileges by default.
|
||||
|
||||
Also, if +chronyd+ is compiled with support for the Linux secure computing
|
||||
(seccomp) facility, you can enable a system call filter with the +-F+ option.
|
||||
It will significantly reduce the kernel attack surface and possibly prevent
|
||||
kernel exploits from the +chronyd+ process if compromised. The filter
|
||||
shouldn't be enabled without testing that it allows all system calls needed
|
||||
with the specific configuration and libraries that +chronyd+ is using (e.g.
|
||||
libc and its NSS configuration). If +chronyd+ is getting killed, some system
|
||||
call is missing and the filter has to be disabled until it's patched to allow
|
||||
that call.
|
||||
|
||||
=== How can I improve the accuracy of the system clock with NTP sources?
|
||||
|
||||
Select NTP servers that are well synchronised, stable and close to your
|
||||
network. It's better to use more than one server, three or four is usually
|
||||
recommended as the minimum, so +chronyd+ can detect falsetickers and combine
|
||||
measurements from multiple sources.
|
||||
|
||||
There are also useful options which can be set in the +server+ directive, they
|
||||
are +minpoll+, +maxpoll+, +polltarget+, +maxdelay+, +maxdelayratio+ and
|
||||
+maxdelaydevratio+.
|
||||
|
||||
The first three options set the minimum and maximum allowed polling interval,
|
||||
and how should be the actual interval adjusted in the specified range. Their
|
||||
default values are 6 (64 seconds) for +minpoll+, 10 (1024 seconds) for
|
||||
+maxpoll+ and 6 (samples) for +polltarget+. The default values should be used
|
||||
for general servers on the internet. With your own NTP servers or if have
|
||||
permission to poll some servers more frequently, setting these options for
|
||||
shorter polling intervals may significantly improve the accuracy of the system
|
||||
clock.
|
||||
|
||||
The optimal polling interval depends on many factors, including the ratio
|
||||
between the wander of the clock and the network jitter (sometimes expressed in
|
||||
NTP documents as the Allan intercept), the temperature sensitivity of the
|
||||
crystal oscillator and the maximum rate of change of the temperature.
|
||||
|
||||
An example of the directive for an NTP server on the internet that you are
|
||||
allowed to poll frequently could be
|
||||
|
||||
----
|
||||
server foo.example.net minpoll 4 maxpoll 6 polltarget 16
|
||||
----
|
||||
|
||||
An example using very short polling intervals for a server located in the same
|
||||
LAN could be
|
||||
|
||||
----
|
||||
server ntp.local minpoll 2 maxpoll 4 polltarget 30
|
||||
----
|
||||
|
||||
The maxdelay options are useful to ignore measurements with larger delay (e.g.
|
||||
due to congestion in the network) and improve the stability of the
|
||||
synchronisation. The +maxdelaydevratio+ option could be added to the example
|
||||
with local NTP server
|
||||
|
||||
----
|
||||
server ntp.local minpoll 2 maxpoll 4 polltarget 30 maxdelaydevratio 2
|
||||
----
|
||||
|
||||
=== What happened to the +commandkey+ and +generatecommandkey+ directives?
|
||||
|
||||
They were removed in version 2.2. Authentication is no longer supported in the
|
||||
command protocol. Commands that required authentication are now allowed only
|
||||
through a Unix domain socket, which is accessible only by the root and chrony
|
||||
users. If you need to configure +chronyd+ remotely or locally without the root
|
||||
password, please consider using ssh and/or sudo to run +chronyc+ under the root
|
||||
or chrony user on the same host as +chronyd+ is running.
|
||||
|
||||
== Computer is not synchronising
|
||||
|
||||
This is the most common problem. There are a number of reasons, see the
|
||||
following questions.
|
||||
|
||||
=== Behind a firewall?
|
||||
|
||||
If there is a firewall between you and the NTP server you're trying to use, the
|
||||
packets may be blocked. Try using a tool like +wireshark+ or +tcpdump+ to see if
|
||||
you're getting responses from the server. If you have an external modem, see
|
||||
if the receive light blinks straight after the transmit light (when the link is
|
||||
quiet apart from the NTP traffic.) Try adding +log measurements+ to the
|
||||
'chrony.conf' file and look in the 'measurements.log' file after +chronyd+ has
|
||||
been running for a short period. See if any measurements appear.
|
||||
|
||||
=== Are NTP servers specified with the +offline+ option?
|
||||
|
||||
Check that you're using +chronyc+\'s +online+ and +offline+ commands
|
||||
appropriately. Again, check in 'measurements.log' to see if you're getting any
|
||||
data back from the server.
|
||||
|
||||
=== Is +chronyd+ allowed to step the system clock?
|
||||
|
||||
By default, +chronyd+ adjusts the clock gradually by slowing it down or
|
||||
speeding it up. If the clock is too far from the correct time, it will take
|
||||
a long time to correct the error. The +System time+ value printed by the
|
||||
+chronyc+'s +tracking+ command is the remaining correction that needs to be
|
||||
applied to the system clock.
|
||||
|
||||
The +makestep+ directive can be used to allow +chronyd+ to step the clock. For
|
||||
example, if 'chrony.conf' had
|
||||
|
||||
----
|
||||
makestep 1 3
|
||||
----
|
||||
|
||||
the clock would be stepped in the first three updates if its offset was larger
|
||||
than one second. Normally, it's recommended to allow the step only in the
|
||||
first few updates, but in some cases (e.g. a computer without RTC or virtual
|
||||
machine which can be suspended and resumed with incorrect time) it may be
|
||||
necessary to allow the step at any clock update. The example above would
|
||||
change to
|
||||
|
||||
----
|
||||
makestep 1 -1
|
||||
----
|
||||
|
||||
== Issues with +chronyc+
|
||||
|
||||
=== I keep getting the error +506 Cannot talk to daemon+
|
||||
|
||||
When accessing +chronyd+ remotely, make sure that the 'chrony.conf' file (on
|
||||
the computer where +chronyd+ is running) has a 'cmdallow' entry for the
|
||||
computer you are running +chronyc+ on and an appropriate 'bindcmdaddress'
|
||||
directive. This isn't necessary for localhost.
|
||||
|
||||
Perhaps +chronyd+ is not running. Try using the +ps+ command (e.g. on Linux,
|
||||
+ps -auxw+) to see if it's running. Or try +netstat -a+ and see if the ports
|
||||
123/udp and 323/udp are listening. If +chronyd+ is not running, you may have a
|
||||
problem with the way you are trying to start it (e.g. at boot time).
|
||||
|
||||
Perhaps you have a firewall set up in a way that blocks packets on port
|
||||
323/udp. You need to amend the firewall configuration in this case.
|
||||
|
||||
=== I keep getting the error +501 Not authorised+
|
||||
|
||||
Since version 2.2, the +password+ command doesn't do anything and +chronyc+
|
||||
needs to run under the root or chrony user, which are allowed to access the
|
||||
Unix domain command socket.
|
||||
|
||||
=== Is the +chronyc+ / +chronyd+ protocol documented anywhere?
|
||||
|
||||
Only by the source code :-) See 'cmdmon.c' (+chronyd+ side) and 'client.c'
|
||||
(+chronyc+ side).
|
||||
|
||||
== Real-time clock issues
|
||||
|
||||
=== What is the real-time clock (RTC)?
|
||||
|
||||
This is the clock which keeps the time even when your computer is turned off.
|
||||
It is used to initialize the system clock on boot. It normally doesn't drift
|
||||
more than few seconds per day.
|
||||
|
||||
There are two approaches how +chronyd+ can work with it. One is to use the
|
||||
+rtcsync+ directive, which tells +chronyd+ to enable a kernel mode which sets
|
||||
the RTC from the system clock every 11 minutes. +chronyd+ itself won't touch
|
||||
the RTC. If the computer is not turned off for a long time, the RTC should
|
||||
still be close to the true time when the system clock will be initialized from
|
||||
it on the next boot.
|
||||
|
||||
The other option is to use the +rtcfile+ directive, which will tell +chronyd+
|
||||
to monitor the rate at which the RTC gains or loses time. When +chronyd+ is
|
||||
started with the +-s+ option on the next boot, it will set the system time from
|
||||
the RTC and also compensate for the drift it has measured previously. The
|
||||
+rtcautotrim+ directive can be used to keep the RTC close to the true time, but
|
||||
it's not strictly necessary if its only purpose is to set the system clock when
|
||||
+chronyd+ is started on boot. See the documentation for details.
|
||||
|
||||
=== I want to use +chronyd+'s RTC support. Must I disable +hwclock+?
|
||||
|
||||
The +hwclock+ program is often set-up by default in the boot and shutdown
|
||||
scripts with many Linux installations. With the kernel RTC synchronisation
|
||||
(+rtcsync+ directive), the RTC will be set also every 11 minutes as long as the
|
||||
system clock is synchronised. If you want to use +chronyd+'s RTC monitoring
|
||||
(+rtcfile+ directive), it's important to disable +hwclock+ in the shutdown
|
||||
procedure. If you don't, it will over-write the RTC with a new value, unknown
|
||||
to +chronyd+. At the next reboot, +chronyd+ started with the +-s+ option will
|
||||
compensate this (wrong) time with its estimate of how far the RTC has drifted
|
||||
whilst the power was off, giving a meaningless initial system time.
|
||||
|
||||
There is no need to remove +hwclock+ from the boot process, as long as +chronyd+
|
||||
is started after it has run.
|
||||
|
||||
=== I just keep getting the +513 RTC driver not running+ message
|
||||
|
||||
For the real time clock support to work, you need the following three
|
||||
things
|
||||
|
||||
* a kernel that is supported (e.g. 2.2 onwards)
|
||||
* enhanced RTC support compiled into the kernel
|
||||
* an +rtcfile+ directive in your 'chrony.conf' file
|
||||
|
||||
== NTP-specific issues
|
||||
|
||||
=== Can +chronyd+ be driven from broadcast NTP servers?
|
||||
|
||||
No, the broadcast client mode is not supported and there is currently no plan
|
||||
to implement it. The broadcast and multicast modes are inherently less
|
||||
accurate and less secure (even with authentication) than the ordinary
|
||||
server/client mode and they are not as useful as they used to be. Even with
|
||||
very modest hardware a single NTP server can serve time to hundreds of
|
||||
thousands of clients using the ordinary mode.
|
||||
|
||||
=== Can +chronyd+ transmit broadcast NTP packets?
|
||||
|
||||
Yes, the +broadcast+ directive can be used to enable the broadcast server mode
|
||||
to serve time to clients in the network which support the broadcast client mode
|
||||
(it's not supported in +chronyd+, see the previous question).
|
||||
|
||||
=== Can +chronyd+ keep the system clock a fixed offset away from real time?
|
||||
|
||||
This is not possible as the program currently stands.
|
||||
|
||||
=== What happens if the network connection is dropped without using +chronyc+'s +offline+ command first?
|
||||
|
||||
+chronyd+ will keep trying to access the server(s) that it thinks are online.
|
||||
When the network is connected again, it will take some time (on average half of
|
||||
the current polling interval) before new measurements are made and the clock is
|
||||
corrected. If the servers were set to offline and the +online+ command was
|
||||
issued when the network was connected, +chronyd+ would make new measurements
|
||||
immediately.
|
||||
|
||||
The +auto_offline+ option to the +server+ entry in the 'chrony.conf' file may
|
||||
be useful to switch the servers to the offline state automatically.
|
||||
|
||||
== Linux-specific issues
|
||||
|
||||
=== I get +Could not open /dev/rtc, Device or resource busy+ in my syslog file
|
||||
|
||||
Some other program running on the system may be using the device.
|
||||
|
||||
== Microsoft Windows
|
||||
|
||||
=== Does +chrony+ support Windows?
|
||||
|
||||
No. The +chronyc+ program (the command-line client used for configuring
|
||||
+chronyd+ while it is running) has been successfully built and run under
|
||||
Cygwin in the past. +chronyd+ is not portable, because part of it is
|
||||
very system-dependent. It needs adapting to work with Windows'
|
||||
equivalent of the adjtimex() call, and it needs to be made to work as a
|
||||
service.
|
||||
|
||||
=== Are there any plans to support Windows?
|
||||
|
||||
We have no plans to do this. Anyone is welcome to pick this work up and
|
||||
contribute it back to the project.
|
||||
17
examples/chrony-wait.service
Normal file
17
examples/chrony-wait.service
Normal file
@@ -0,0 +1,17 @@
|
||||
[Unit]
|
||||
Description=Wait for chrony to synchronize system clock
|
||||
After=chronyd.service
|
||||
Requires=chronyd.service
|
||||
Before=time-sync.target
|
||||
Wants=time-sync.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
# Wait up to ~10 minutes for chronyd to synchronize and the remaining
|
||||
# clock correction to be less than 0.1 seconds
|
||||
ExecStart=/usr/bin/chronyc waitsync 600 0.1 0.0 1
|
||||
RemainAfterExit=yes
|
||||
StandardOutput=null
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
12
examples/chrony.conf.example1
Normal file
12
examples/chrony.conf.example1
Normal file
@@ -0,0 +1,12 @@
|
||||
# Use public NTP servers from the pool.ntp.org project.
|
||||
pool pool.ntp.org iburst
|
||||
|
||||
# Record the rate at which the system clock gains/losses time.
|
||||
driftfile /var/lib/chrony/drift
|
||||
|
||||
# In first three updates step the system clock instead of slew
|
||||
# if the adjustment is larger than 1 second.
|
||||
makestep 1.0 3
|
||||
|
||||
# Enable kernel synchronization of the real-time clock (RTC).
|
||||
rtcsync
|
||||
34
examples/chrony.conf.example2
Normal file
34
examples/chrony.conf.example2
Normal file
@@ -0,0 +1,34 @@
|
||||
# Use public servers from the pool.ntp.org project.
|
||||
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
|
||||
pool pool.ntp.org iburst
|
||||
|
||||
# Record the rate at which the system clock gains/losses time.
|
||||
driftfile /var/lib/chrony/drift
|
||||
|
||||
# In first three updates step the system clock instead of slew
|
||||
# if the adjustment is larger than 1 second.
|
||||
makestep 1.0 3
|
||||
|
||||
# Enable kernel synchronization of the real-time clock (RTC).
|
||||
rtcsync
|
||||
|
||||
# Allow NTP client access from local network.
|
||||
#allow 192.168/16
|
||||
|
||||
# Serve time even if not synchronized to any NTP server.
|
||||
#local stratum 10
|
||||
|
||||
# Specify file containing keys for NTP authentication.
|
||||
#keyfile /etc/chrony.keys
|
||||
|
||||
# Disable logging of client accesses.
|
||||
noclientlog
|
||||
|
||||
# Send message to syslog when clock adjustment is larger than 0.5 seconds.
|
||||
logchange 0.5
|
||||
|
||||
# Specify directory for log files.
|
||||
logdir /var/log/chrony
|
||||
|
||||
# Select which information is logged.
|
||||
#log measurements statistics tracking
|
||||
@@ -40,28 +40,32 @@
|
||||
# more 'NTP servers'. You will probably find that your Internet Service
|
||||
# Provider or company have one or more NTP servers that you can specify.
|
||||
# Failing that, there are a lot of public NTP servers. There is a list
|
||||
# you can access at
|
||||
# http://www.eecis.udel.edu/~mills/ntp/servers.htm.
|
||||
# you can access at http://support.ntp.org/bin/view/Servers/WebHome or
|
||||
# you can use servers from the pool.ntp.org project.
|
||||
|
||||
! server ntp0.your-isp.com
|
||||
! server ntp1.your-isp.com
|
||||
! server ntp.public-server.org
|
||||
! server foo.example.net iburst
|
||||
! server bar.example.net iburst
|
||||
! server baz.example.net iburst
|
||||
|
||||
! pool pool.ntp.org iburst
|
||||
|
||||
# However, for dial-up use you probably want these instead. The word
|
||||
# 'offline' means that the server is not visible at boot time. Use
|
||||
# chronyc's 'online' command to tell chronyd that these servers have
|
||||
# become visible after you go on-line.
|
||||
|
||||
! server ntp0.your-isp.com offline
|
||||
! server ntp1.your-isp.com offline
|
||||
! server ntp.public-server.org offline
|
||||
! server foo.example.net offline
|
||||
! server bar.example.net offline
|
||||
! server baz.example.net offline
|
||||
|
||||
! pool pool.ntp.org offline
|
||||
|
||||
# You may want to specify NTP 'peers' instead. If you run a network
|
||||
# with a lot of computers and want several computers running chrony to
|
||||
# have the 'front-line' interface to the public NTP servers, you can
|
||||
# 'peer' these machines together to increase robustness.
|
||||
|
||||
! peer ntp0.my-company.com
|
||||
! peer foo.example.net
|
||||
|
||||
# There are other options to the 'server' and 'peer' directives that you
|
||||
# might want to use. For example, you can ignore measurements whose
|
||||
@@ -89,22 +93,12 @@
|
||||
# immediately so that it doesn't gain or lose any more time. You
|
||||
# generally want this, so it is uncommented.
|
||||
|
||||
driftfile /etc/chrony.drift
|
||||
driftfile /var/lib/chrony/drift
|
||||
|
||||
# If you want to use the program called chronyc to configure aspects of
|
||||
# chronyd's operation once it is running (e.g. tell it the Internet link
|
||||
# has gone up or down), you need a password. This is stored in the
|
||||
# following keys file. (You also need keys to support authenticated NTP
|
||||
# exchanges between cooperating machines.) Again, this option is
|
||||
# assumed by default.
|
||||
# If you want to enable NTP authentication with symmetric keys, you will need
|
||||
# to uncomment the following line and edit the file to set up the keys.
|
||||
|
||||
keyfile /etc/chrony.keys
|
||||
|
||||
# Tell chronyd which numbered key in the file is used as the password
|
||||
# for chronyc. (You can pick any integer up to 2**32-1. '1' is just a
|
||||
# default. Using another value will _NOT_ increase security.)
|
||||
|
||||
commandkey 1
|
||||
! keyfile /etc/chrony.keys
|
||||
|
||||
# chronyd can save the measurement history for the servers to files when
|
||||
# it it exits. This is useful in 2 situations:
|
||||
@@ -122,7 +116,7 @@ commandkey 1
|
||||
# Enable these two options to use this.
|
||||
|
||||
! dumponexit
|
||||
! dumpdir /var/log/chrony
|
||||
! dumpdir /var/lib/chrony
|
||||
|
||||
# chronyd writes its process ID to a file. If you try to start a second
|
||||
# copy of chronyd, it will detect that the process named in the file is
|
||||
@@ -133,17 +127,16 @@ commandkey 1
|
||||
|
||||
#######################################################################
|
||||
### INITIAL CLOCK CORRECTION
|
||||
# This option is only useful if your NTP servers are visible at boot
|
||||
# time. This probably means you are on a LAN. If so, the following
|
||||
# option will choose the best-looking of the servers and correct the
|
||||
# system time to that. The value '10' means that if the error is less
|
||||
# than 10 seconds, it will be gradually removed by speeding up or
|
||||
# slowing down your computer's clock until it is correct. If the error
|
||||
# is above 10 seconds, an immediate time jump will be applied to correct
|
||||
# it. Some software can get upset if the system clock jumps (especially
|
||||
# backwards), so be careful!
|
||||
# This option is useful to quickly correct the clock on start if it's
|
||||
# off by a large amount. The value '1.0' means that if the error is less
|
||||
# than 1 second, it will be gradually removed by speeding up or slowing
|
||||
# down your computer's clock until it is correct. If the error is above
|
||||
# 1 second, an immediate time jump will be applied to correct it. The
|
||||
# value '3' means the step is allowed only in the first three updates of
|
||||
# the clock. Some software can get upset if the system clock jumps
|
||||
# (especially backwards), so be careful!
|
||||
|
||||
! initstepslew 10 ntp0.your-company.com ntp1.your-company.com ntp2.your-company.com
|
||||
! makestep 1.0 3
|
||||
|
||||
#######################################################################
|
||||
### LOGGING
|
||||
@@ -231,13 +224,18 @@ commandkey 1
|
||||
# several people, you need to set up a mailing list or sendmail alias
|
||||
# for them and use the address of that.)
|
||||
|
||||
! mailonchange wibble@foobar.org 0.5
|
||||
! mailonchange wibble@foo.example.net 0.5
|
||||
|
||||
#######################################################################
|
||||
### COMMAND ACCESS
|
||||
# The program chronyc is used to show the current operation of chronyd
|
||||
# and to change parts of its configuration whilst it is running.
|
||||
|
||||
# By default chronyd binds to the loopback interface. Uncomment the
|
||||
# following lines to allow receiving command packets from remote hosts.
|
||||
! bindcmdaddress 0.0.0.0
|
||||
! bindcmdaddress ::
|
||||
|
||||
# Normally, chronyd will only allow connections from chronyc on the same
|
||||
# machine as itself. This is for security. If you have a subnet
|
||||
# 192.168.*.* and you want to be able to use chronyc from any machine on
|
||||
@@ -250,18 +248,6 @@ commandkey 1
|
||||
# syntax and meaning is the same as for 'allow' and 'deny', except that
|
||||
# 'cmdallow' and 'cmddeny' control access to the chronyd's command port.
|
||||
|
||||
# NOTE, even if the host where you run chronyc is granted access, you
|
||||
# still need a command key set up and you have to know the password to
|
||||
# put into chronyc to allow you to modify chronyd's parameters. By
|
||||
# default all you can do is view information about chronyd's operation.
|
||||
|
||||
# Some people have reported that the need the following line to allow
|
||||
# chronyc to work even on the same machine. This should not be
|
||||
# necessary, and the problem is being investigated. You can leave this
|
||||
# line enabled, as it's benign otherwise.
|
||||
|
||||
cmdallow 127.0.0.1
|
||||
|
||||
#######################################################################
|
||||
### REAL TIME CLOCK
|
||||
# chronyd can characterise the system's real-time clock. This is the
|
||||
@@ -273,7 +259,7 @@ cmdallow 127.0.0.1
|
||||
# You need to have 'enhanced RTC support' compiled into your Linux
|
||||
# kernel. (Note, these options apply only to Linux.)
|
||||
|
||||
! rtcfile /etc/chrony.rtc
|
||||
! rtcfile /var/lib/chrony/rtc
|
||||
|
||||
# Your RTC can be set to keep Universal Coordinated Time (UTC) or local
|
||||
# time. (Local time means UTC +/- the effect of your timezone.) If you
|
||||
@@ -1,27 +1,15 @@
|
||||
#######################################################################
|
||||
# $Header: /cvs/src/chrony/examples/chrony.keys.example,v 1.1 2002/01/31 00:00:08 richard Exp $
|
||||
# This is an example chrony keys file. It is used for NTP authentication with
|
||||
# symmetric keys. It should be readable only by root or the user to which
|
||||
# chronyd is configured to switch to.
|
||||
#
|
||||
# This is an example chrony keys file. You should copy it to /etc/chrony.keys
|
||||
# after editing it to set up the key(s) you want to use. In most situations,
|
||||
# you will require a single key (the 'commandkey') so that you can supply a
|
||||
# password to chronyc to enable you to modify chronyd's operation whilst it is
|
||||
# running.
|
||||
#
|
||||
# Copyright 2002 Richard P. Curnow
|
||||
#
|
||||
#######################################################################
|
||||
# A valid key line looks like this
|
||||
# Don't use the example keys! The keys need to be random for maximum security.
|
||||
# These shell commands can be used to generate random MD5 and SHA1 keys on
|
||||
# systems which have the /dev/urandom device:
|
||||
# echo "1 MD5 HEX:$(tr -d -c '[:xdigit:]' < /dev/urandom | head -c 32)"
|
||||
# echo "1 SHA1 HEX:$(tr -d -c '[:xdigit:]' < /dev/urandom | head -c 40)"
|
||||
|
||||
1 a_key
|
||||
|
||||
# It must consist of an integer, followed by whitespace, followed by a block of
|
||||
# text with no spaces in it. (You cannot put a space in a key). If you wanted
|
||||
# to use the above line as your commandkey (i.e. chronyc password), you would
|
||||
# put the following line into chrony.conf (remove the # from the start):
|
||||
|
||||
# commandkey 1
|
||||
|
||||
# You might want to define more keys if you use the MD5 authentication facility
|
||||
# in the network time protocol to authenticate request/response packets between
|
||||
# trusted clients and servers.
|
||||
# Examples of valid keys:
|
||||
|
||||
#1 ALongAndRandomPassword
|
||||
#2 MD5 HEX:B028F91EA5C38D06C2E140B26C7F41EC
|
||||
#3 SHA1 HEX:1DC764E0791B11FA67EFC7ECBC4B0D73F68A070C
|
||||
|
||||
8
examples/chrony.logrotate
Normal file
8
examples/chrony.logrotate
Normal file
@@ -0,0 +1,8 @@
|
||||
/var/log/chrony/*.log {
|
||||
missingok
|
||||
nocreate
|
||||
sharedscripts
|
||||
postrotate
|
||||
/usr/bin/chronyc cyclelogs > /dev/null 2>&1 || true
|
||||
endscript
|
||||
}
|
||||
17
examples/chrony.nm-dispatcher
Normal file
17
examples/chrony.nm-dispatcher
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
# This is a NetworkManager dispatcher script for chronyd to set its NTP sources
|
||||
# online/offline when a default route is configured/removed on the system.
|
||||
|
||||
export LC_ALL=C
|
||||
|
||||
if [ "$2" = "up" ]; then
|
||||
/sbin/ip route list dev "$1" | grep -q '^default' &&
|
||||
/usr/bin/chronyc online > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
if [ "$2" = "down" ]; then
|
||||
/sbin/ip route list | grep -q '^default' ||
|
||||
/usr/bin/chronyc offline > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
56
examples/chrony.spec
Normal file
56
examples/chrony.spec
Normal file
@@ -0,0 +1,56 @@
|
||||
%global chrony_version @@VERSION@@
|
||||
%if 0%(echo %{chrony_version} | grep -q pre && echo 1)
|
||||
%global prerelease %(echo %{chrony_version} | sed 's/.*-//')
|
||||
%endif
|
||||
Summary: An NTP client/server
|
||||
Name: chrony
|
||||
Version: %(echo %{chrony_version} | sed 's/-.*//')
|
||||
Release: %{!?prerelease:1}%{?prerelease:0.1.%{prerelease}}
|
||||
Source: chrony-%{version}%{?prerelease:-%{prerelease}}.tar.gz
|
||||
License: GPLv2
|
||||
Group: Applications/Utilities
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-root-%(id -u -n)
|
||||
Requires: info
|
||||
|
||||
%description
|
||||
chrony is a client and server for the Network Time Protocol (NTP).
|
||||
This program keeps your computer's clock accurate. It was specially
|
||||
designed to support systems with intermittent Internet connections,
|
||||
but it also works well in permanently connected environments. It can
|
||||
also use hardware reference clocks, the system real-time clock, or
|
||||
manual input as time references.
|
||||
|
||||
%prep
|
||||
%setup -q -n %{name}-%{version}%{?prerelease:-%{prerelease}}
|
||||
|
||||
%build
|
||||
./configure \
|
||||
--prefix=%{_prefix} \
|
||||
--bindir=%{_bindir} \
|
||||
--sbindir=%{_sbindir} \
|
||||
--infodir=%{_infodir} \
|
||||
--mandir=%{_mandir}
|
||||
make
|
||||
make chrony.txt
|
||||
make chrony.info
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
make install DESTDIR=$RPM_BUILD_ROOT
|
||||
rm -rf $RPM_BUILD_ROOT%{_docdir}
|
||||
mkdir -p $RPM_BUILD_ROOT%{_infodir}
|
||||
cp chrony.info* $RPM_BUILD_ROOT%{_infodir}
|
||||
|
||||
%files
|
||||
%{_sbindir}/chronyd
|
||||
%{_bindir}/chronyc
|
||||
%{_infodir}/chrony.info*
|
||||
%{_mandir}/man1/chronyc.1.gz
|
||||
%{_mandir}/man5/chrony.conf.5.gz
|
||||
%{_mandir}/man8/chronyd.8.gz
|
||||
%doc README
|
||||
%doc chrony.txt
|
||||
%doc COPYING
|
||||
%doc examples/chrony.conf.example*
|
||||
%doc examples/chrony.keys.example
|
||||
|
||||
13
examples/chronyd.service
Normal file
13
examples/chronyd.service
Normal file
@@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=NTP client/server
|
||||
After=ntpdate.service sntp.service ntpd.service
|
||||
Conflicts=ntpd.service systemd-timesyncd.service
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
PIDFile=/var/run/chronyd.pid
|
||||
EnvironmentFile=-/etc/sysconfig/chronyd
|
||||
ExecStart=/usr/sbin/chronyd $OPTIONS
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
366
faq.txt
366
faq.txt
@@ -1,366 +0,0 @@
|
||||
@@PROLOGUE
|
||||
<html>
|
||||
<head>
|
||||
<title>Frequently asked questions</title>
|
||||
<meta name="description" content="Chrony FAQ (frequently asked questions)">
|
||||
<meta name="keywords" content="chrony,network time protocol,NTP,RFC 1305,dial-up connection,real time clock,RTC,Linux,FAQ,frequently asked questns">
|
||||
<?php
|
||||
$root = ".";
|
||||
include "$root/styles.php";
|
||||
?>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<?php
|
||||
include 'main_banner.php';
|
||||
include 'header.php';
|
||||
?>
|
||||
<?php pretty_h1("Introduction") ?>
|
||||
<p>
|
||||
This is a set of questions and answers to common problems and issues.
|
||||
<p>
|
||||
As we receive more emails about the software, we will add new questions
|
||||
to this page.
|
||||
<hr>
|
||||
<p>
|
||||
The developers can be reached via the chrony-dev mailing list. See
|
||||
<a href="#question_1.4">question 1.4.</a> for details.
|
||||
<hr>
|
||||
|
||||
<br clear=all>
|
||||
@@ENDPROLOGUE
|
||||
S: Administrative issues
|
||||
|
||||
Q: Where can I get chrony source code?
|
||||
Tarballs are available via the <b>Download</b> link on the Chrony
|
||||
Web site. For the current development from the developers' version control
|
||||
system see the <b>Git</b> link on the Web site.
|
||||
|
||||
Q: Are there any packaged versions of chrony?
|
||||
We are aware of packages for Debian, Fedora, Gentoo, Mandriva, Slackware,
|
||||
and Ubuntu. We are not involved with how these are built or distributed.
|
||||
|
||||
Q: Where is the home page?
|
||||
It is currently at <a href="http://chrony.tuxfamily.org/">http://chrony.tuxfamily.org/</a>.
|
||||
|
||||
Q: Is there a mailing list?
|
||||
Yes, it's currently at chrony-users@chrony.tuxfamily.org. There is a low-volume
|
||||
list called chrony-announce which is just for announcements of new releases or
|
||||
similar matters of high importance. You can join the lists by sending a
|
||||
message with the subject subscribe to <a href="mailto:chrony-users-request@chrony.tuxfamily.org">chrony-users-request@chrony.tuxfamily.org</a> or
|
||||
<a href="mailto:chrony-announce-request@chrony.tuxfamily.org">chrony-announce-request@chrony.tuxfamily.org</a> respectively.
|
||||
|
||||
For those who want to contribute to the development of chrony, there is a
|
||||
developers' mailing list. You can subscribe by sending mail with the
|
||||
subject subscribe to
|
||||
<a href="mailto:chrony-dev-request@chrony.tuxfamily.org">chrony-dev-request@chrony.tuxfamily.org</a>.
|
||||
|
||||
Q: What licence is applied to chrony?
|
||||
Starting from version 1.15, chrony is licensed under the GNU General Public
|
||||
License, Version 2. Versions prior to 1.15 were licensed under a custom BSD-like
|
||||
license.
|
||||
|
||||
S: Chrony compared to other programs
|
||||
Q: How does chrony compare to xntpd?
|
||||
If your computer is permenently connected, or connected for long periods (that
|
||||
is, for the several hours it takes xntpd to settle down), or you need to
|
||||
support hardware reference clocks to your computer, then xntpd will work fine.
|
||||
Apart from not supporting hardware clocks, chrony will work fine too.
|
||||
|
||||
If your computer connects to the 'net for 5 minutes once a day (or something
|
||||
like that), or you turn your (Linux v2.0) computer off when you're not using
|
||||
it, or you want to use NTP on an isolated network with no hardware clocks in
|
||||
sight, chrony will work much better for you.
|
||||
|
||||
The reason I wrote chrony was that I could not get xntpd to do
|
||||
anything sensible on my PC at home, which is connected to the 'net for
|
||||
about 5 minutes once or twice a day, mainly to upload/download email
|
||||
and news. Nowadays it is also turned off for 22-23 hours a day, when
|
||||
not in use. I wanted a program which would :
|
||||
|
||||
- slew the time to correct it when I go online and NTP servers become visible
|
||||
|
||||
- determine the rate at which the computer gains or loses time and use this
|
||||
information to keep it reasonably correct between connects to the 'net. This
|
||||
has to be done using a method that does not care about the intermittent
|
||||
availability of the references or the fact the computer is turned off between
|
||||
groups of measurements..
|
||||
|
||||
- maintain the time across reboots, by working out the error and drift rate of
|
||||
the computer's real-time clock and using this information to set the system
|
||||
clock correctly at boot up. (In the last few months, it became impossible for
|
||||
me to leave my computer powered permanently.)
|
||||
|
||||
Also, when working with isolated networks with no true time references
|
||||
at all, I found xntpd gave me no help with managing the local clock's
|
||||
gain/loss rate on the NTP master node (which I set from my watch). I
|
||||
added some automated support in chrony to deal with this.
|
||||
|
||||
S: Compilation issues
|
||||
Q:How do I apply source patches?
|
||||
Sometimes we release source patches rather than a full version when we need to
|
||||
provide a fix for small problems. Supposing you have chrony-1.X.tar.gz and a
|
||||
source patch chrony-1.X-1.X.1.gz. The steps required are:
|
||||
|
||||
tar xzvf ../chrony-1.X.tar.gz
|
||||
cd chrony-1.X
|
||||
gunzip < ../../chrony-1.X-1.X.1.gz | patch -p1
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
|
||||
Q:Can I compile chrony with an ANSI-C compiler that is not GCC v2.x?
|
||||
I have had reports that chrony can be compiled with GCC v1.42, by using the
|
||||
following trick when running make
|
||||
|
||||
make CC='gcc -D__FUNCTION__=\"function_not_available\"'
|
||||
|
||||
(this gets around the lack of a __FUNCTION__ macro in GCC v1.)
|
||||
|
||||
The same trick may be enough to allow other compilers to be used.
|
||||
|
||||
Q: I get errors like 'client.c:44: readline/readline.h: file not found'
|
||||
Read the section about 'readline' in the INSTALL file or in chrony.txt. You
|
||||
may need to disable readline support (e.g. if you haven't got readline
|
||||
installed at all, or just don't want it), or specify the location of the
|
||||
readline files (e.g. if you've installed them in a non-standard place).
|
||||
|
||||
Q: I have RedHat 7.3 and can't compile rtc_linux.c (error in spinlock.h)
|
||||
The following solution has been found for this. Enter the following 3 commands
|
||||
(as root):
|
||||
|
||||
cd /usr/include/
|
||||
mv linux linux.rh
|
||||
ln -s /usr/src/linux/include/linux ./linux
|
||||
|
||||
The problem seems to be that RedHat provide their own kernel header files in
|
||||
/usr/include/linux. Besides differing from those used by your current kernel,
|
||||
if you compiled it yourself, they also seem to have been changed in a way that
|
||||
causes a problem compiling chrony. Chrony compiles fine with standard kernel
|
||||
header files.
|
||||
|
||||
There have also been reports that just replacing the file
|
||||
/usr/src/linux/spinlock.h by the equivalent file from a vanilla kernel source
|
||||
tree is sufficient to fix the problem.
|
||||
|
||||
Note : from version 1.21 onwards, this problem no longer exists. The kernel
|
||||
header files are no longer included.
|
||||
|
||||
S: Selection of NTP servers
|
||||
Q: I have several computers on a LAN. Should I make one the master, or make them all clients of an external server?
|
||||
I think the best configuration is to make one computer the master, with the
|
||||
others as clients of it. Add a 'local' directive to the master's chrony.conf
|
||||
file. This configuration will be better because
|
||||
|
||||
* the load on the external connection is less
|
||||
* the load on the external NTP server(s) is less
|
||||
* if your external connection goes down, the computers on the LAN will maintain
|
||||
a common time with each other.
|
||||
|
||||
S: Addressing issues
|
||||
Q: I get the following error message : "Could not get IP adress for localhost"
|
||||
Add a line like the following to your /etc/hosts file
|
||||
127.0.0.1 localhost
|
||||
|
||||
Q: I have problems if I put the names of my NTP servers in the chrony.conf file.
|
||||
If you have no connection to the Internet at boot time, chrony won't be able to
|
||||
turn the names into IP addresses when it starts. There seem to be 2 solutions:
|
||||
|
||||
1. Put the numeric IP addresses in the chrony.conf file
|
||||
or
|
||||
2. Put the server->IP address mappings in your /etc/hosts file and ensure that
|
||||
/etc/host.conf reads 'order hosts,bind'.
|
||||
|
||||
The problem is that chronyd (currently) isn't designed in a way that allows
|
||||
hostname->IP address lookups during normal operation. I hope to work on this
|
||||
problem very soon.
|
||||
|
||||
S: My computer is not synchronising.
|
||||
This is the most common problem. There are a number of reasons, see the
|
||||
following questions.
|
||||
|
||||
Q: Behind a firewall?
|
||||
If there is a firewall between you and the NTP server you're trying to use,
|
||||
the packets may be blocked. Try using a tool like etherfind or tcpdump to see
|
||||
if you're getting responses from the server. If you have an external modem,
|
||||
see if the receive light blinks straight after the transmit light (when the
|
||||
link is quiet apart from the NTP traffic.) Try adding 'log measurements' to
|
||||
the chrony.conf file and look in the measurements.log file after chrony has
|
||||
been running for a short period. See if any measurements appear.
|
||||
|
||||
Most people run chronyd on the firewall itself, to avoid all issues of UDP
|
||||
packet forwarding and/or masquerading.
|
||||
|
||||
Q: Do you have a non-permanant (i.e. intermittent) Internet connection?
|
||||
Check that you're using chronyc's 'online' and 'offline' commands
|
||||
appropriately. Again, check in measurements.log to see if you're getting any
|
||||
data back from the server.
|
||||
|
||||
Q: In measurements.log, do the '7' and '8' flag columns always show zero?
|
||||
Do you have a 'local stratum X' directive in the chrony.conf file? If X is
|
||||
lower than the stratum of the server you're trying to use, this situation will
|
||||
arise. You should always make X quite high (e.g. 10) in this directive.
|
||||
|
||||
S: Issues with chronyd
|
||||
|
||||
Q: chronyd crashes after a syslog message "adjtimex failed for set frequency"
|
||||
The usual cause is that the kernel is running with a different value of 'HZ'
|
||||
(the timer interrupt rate) than the value that was found in the kernel header
|
||||
files when chrony was compiled. The chrony.conf file can include options to
|
||||
modify the HZ value (see the discussion of linux_hz and linux_freq_scale in the
|
||||
documentation), however the problem is to find the value of HZ being used.
|
||||
|
||||
S: Issues with chronyc
|
||||
|
||||
Q: I keep getting the error '510 No command access from this host --- Reply not authenticated'.
|
||||
Make sure that the chrony.conf file (on the computer where chronyd is running)
|
||||
has a 'cmdallow' entry for the computer you are running chronyc on. This
|
||||
shouldn't be necessary for localhost, but some people still seem to need an
|
||||
entry like 'cmdallow 127.0.0.1'. (It would be good to understand why problem
|
||||
only affects some people).
|
||||
|
||||
Q: I cannot log in from chronyc to carry out privileged tasks.
|
||||
This is the second most common problem.
|
||||
|
||||
Perhaps your /etc/chrony.keys file is badly formatted. Make sure that the
|
||||
final line has a line feed at the end, otherwise the key on that line will work
|
||||
as though the last character is missing. (Note, this bug was fixed in version
|
||||
1.16.)
|
||||
|
||||
Q: When I enter a command and hit <Return>, chronyc hangs
|
||||
This probably means that chronyc cannot communicate with chronyd.
|
||||
|
||||
Perhaps chronyd is not running. Try using the ps command (e.g. on Linux, 'ps
|
||||
-auxw') to see if it's running. Or try 'netstat -a' and see if the ports
|
||||
123/udp and 323/udp are listening. If chronyd is not running, you may have a
|
||||
problem with the way you are trying to start it (e.g. at boot time).
|
||||
|
||||
Perhaps you have a firewall set up in a way that blocks packets on port
|
||||
323/udp. You need to amend the firewall configuration in this case.
|
||||
|
||||
Q: Is the chronyc<->chronyd protocol documented anywhere?
|
||||
Only by the source code :-) See cmdmon.c (chronyd side) and client.c (chronyc
|
||||
side).
|
||||
|
||||
S: Real-time clock issues.
|
||||
Q: What is the real-time clock (RTC)?
|
||||
This is the clock which keeps the time even when your computer is turned off.
|
||||
It works with 1 second resolution. chronyd can monitor the rate at which the
|
||||
real-time clock gains or loses time, and compensate for it when you set the
|
||||
system time from it at the next reboot. See the documentation for details.
|
||||
|
||||
Q: I want to use chronyd's real-time clock support. Must I disable hwclock?
|
||||
The hwclock program is often set-up by default in the boot and shutdown scripts
|
||||
with many Linux installations. If you want to use chronyd's real-time clock
|
||||
support, the important thing is to disable hwclock in the <b>shutdown</b>
|
||||
procedure. If you don't, it will over-write the RTC with a new value, unknown
|
||||
to chronyd. At the next reboot, chronyd will compensate this (wrong) time with
|
||||
its estimate of how far the RTC has drifted whilst the power was off, giving a
|
||||
meaningless initial system time.
|
||||
|
||||
There is no need to remove hwclock from the boot process, as long as chronyd is
|
||||
started after it has run.
|
||||
|
||||
Q: I just keep getting the '513 RTC driver not running' message
|
||||
For the real time clock support to work, you need the following three things:
|
||||
|
||||
* a kernel that is supported (e.g. 2.2 onwards)
|
||||
* enhanced RTC support compiled into the kernel
|
||||
* an 'rtcfile' directive in your chrony.conf file.
|
||||
|
||||
S: Problems with isolated networks.
|
||||
|
||||
Q: When I use the 'settime' command, chronyd crashes.
|
||||
If you enter times that are too far away from the real time, chronyd will
|
||||
think the system clock runs fast or slow by an excessive amount. The required
|
||||
compensation factor will be outside the bounds for the adjtimex() system call.
|
||||
chronyd will crash when it tries to apply such an excessive adjustment.
|
||||
|
||||
S: Microsoft Windows
|
||||
|
||||
Q: Does chrony support Windows?
|
||||
No. The chronyc program (the command-line client used for configuring
|
||||
chronyd while it is running) has been successfully built and run under Cygwin
|
||||
in the past. chronyd is not portable, because part of it is very
|
||||
system-dependent. It needs adapting to work with Windows' equivalent of the
|
||||
adjtimex() call, and it needs to be made to work as an NT service.
|
||||
|
||||
Q: Are there any plans to support Windows?
|
||||
We have no plans to do this. Anyone is welcome to pick this work up and
|
||||
contribute it back to the project.
|
||||
|
||||
Q: What alternative NTP clients are there for Windows?
|
||||
Some of the names we've seen mentioned are
|
||||
- Automachron
|
||||
- NetTime (nettime.sourceforge.net)
|
||||
|
||||
S: NTP-specific issues
|
||||
Q: Can chrony be driven from broadcast NTP servers?
|
||||
No. I remember looking at how they worked when I was first writing chrony.
|
||||
Since the 'target market' then was dial-up systems, broadcast packets were not
|
||||
relevant so I didn't bother working out how to deal with the complexities of
|
||||
doing the delay estimation.
|
||||
|
||||
I no longer have root access to a LAN environment to develop and test broadcast
|
||||
server support. Neither have I the time to work on this. I would be very
|
||||
happy to accept a patch from anyone who can develop, test and debug the
|
||||
necessary changes!
|
||||
|
||||
Q: Can chronyd transmit broadcast NTP packets (e.g. to synchronise other computers on a private LAN)?
|
||||
Yes. Starting from version 1.17, chrony has this capability.
|
||||
|
||||
Q: Can chrony keep the system clock a fixed offset away from real time?
|
||||
I have not experimented much, but I don't believe this would be possible as
|
||||
the program currently stands.
|
||||
|
||||
Q: What happens if the network connection is dropped without using chronyc's 'offline' command first?
|
||||
In this case chronyd will keep trying to access the server(s) that it thinks
|
||||
are online. Eventually it will decide that they are unreachable and no longer
|
||||
consider itself synchronised to them. If you have other computers on your LAN
|
||||
accessing the computer that is affected this way, they too will become
|
||||
'unsynchronised', unless you have the 'local' directive set up on the master
|
||||
computer.
|
||||
|
||||
The 'auto_offline' option to the 'server' entry in the chrony.conf file may be
|
||||
useful to avoid this situation.
|
||||
|
||||
S: Development
|
||||
|
||||
Q: Can I get the source via git from anywhere?
|
||||
Yes. See the Git link at <a
|
||||
href="http://chrony.tuxfamily.org/">http://chrony.tuxfamily.org</a> for
|
||||
information.
|
||||
|
||||
S: Linux-specific issues
|
||||
|
||||
Q: Why does the source code include kernel header files?
|
||||
The program needs to see the definitions of structures used to interact with
|
||||
the real time clock (via /dev/rtc) and with the adjtimex() system call. Sadly
|
||||
this has led to a number of compilation problems with newer kernels which have
|
||||
been increasingly hard to fix in a way that makes the code compilable on all
|
||||
Linux kernel versions (from 2.0 up anyway, I doubt 1.x still works.) Hopefully
|
||||
the situation will not deteriorate further with future kernel versions.
|
||||
|
||||
Q: I get "Could not open /dev/rtc, Device or resource busy" in my syslog file.
|
||||
Check that you haven't accidentally got two copies of chronyd running (perhaps
|
||||
defined in different start-up scripts.)
|
||||
|
||||
S: Solaris-specific issues
|
||||
Q: On Solaris 2.8, I get an error message about not being able to open kvm to change dosynctodr.
|
||||
(The dosynctodr variable controls whether Solaris couples the equivalent of its
|
||||
BIOS clock into its system clock at regular intervals). The Solaris port of
|
||||
chrony was developed in the Solaris 2.5 era. Some aspect of the Solaris kernel
|
||||
has changed which prevents the same technique working. I no longer have root
|
||||
access to any Solaris machines to work on this, and am reliant on somebody
|
||||
developing the patch and testing it. A good starting point would be to see if
|
||||
xntpd has been modified to work for Solaris 2.8.
|
||||
|
||||
@@EPILOGUE
|
||||
<hr>
|
||||
|
||||
Back to
|
||||
<a href="mailto:rc@rc0.org.uk?subject=chrony">the author</a>'s
|
||||
<a href="http://www.rc0.org.uk/">main page</a>
|
||||
</body>
|
||||
</html>
|
||||
@@ENDEPILOGUE
|
||||
140
faqgen.pl
140
faqgen.pl
@@ -1,140 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
# $Header
|
||||
|
||||
# Copyright 2001 Richard P. Curnow
|
||||
# LICENCE
|
||||
|
||||
# A script to generate an HTML FAQ page from a text input file. The input is assumed to consist of the following:
|
||||
# Lines starting with 'S:'. These introduce sections.
|
||||
# Lines starting with 'Q:'. These are the topics of questions.
|
||||
# Body text (either as an introduction to the sections, or as answers to the questions.
|
||||
# The body text is set as pre-formatted.
|
||||
|
||||
$| = 1;
|
||||
|
||||
@prologue = ();
|
||||
@epilogue = ();
|
||||
|
||||
@sections=(); # section titles
|
||||
@sect_text=(); # introductory text in sections
|
||||
|
||||
@questions=(); # questions in sections
|
||||
@answers=(); # answers to questions
|
||||
|
||||
$sn = -1;
|
||||
$had_q = 0;
|
||||
|
||||
#{{{ Parse input
|
||||
while (<>) {
|
||||
if (m/\@\@PROLOG/o) {
|
||||
while (<>) {
|
||||
last if (m/^\@\@ENDPROLOG/);
|
||||
push (@prologue, $_);
|
||||
}
|
||||
} elsif (m/\@\@EPILOG/o) {
|
||||
while (<>) {
|
||||
last if (m/^\@\@ENDEPILOG/);
|
||||
push (@epilogue, $_);
|
||||
}
|
||||
} elsif (m/^[sS]:[ \t]*(.*)$/) {
|
||||
chomp;
|
||||
$qn = -1;
|
||||
++$sn;
|
||||
$sections[$sn] = &guard($1);
|
||||
$sect_text[$sn] = "";
|
||||
$questions[$sn] = [ ];
|
||||
$answers[$sn] = [ ];
|
||||
$had_q = 0;
|
||||
} elsif (/^[qQ]:[ \t]*(.*)$/) {
|
||||
chomp;
|
||||
die unless ($sn >= 0);
|
||||
++$qn;
|
||||
$questions[$sn]->[$qn] = &guard($1);
|
||||
$had_q = 1;
|
||||
} else {
|
||||
if ($had_q) {
|
||||
if ($qn >= 0) {
|
||||
$answers[$sn]->[$qn] .= $_;
|
||||
}
|
||||
} else {
|
||||
if ($sect_text[$sn] ne "" || $_ !~ /^\s*$/) {
|
||||
$sect_text[$sn] .= $_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#}}}
|
||||
|
||||
# Emit file header
|
||||
if ($#prologue >= 0) {
|
||||
print @prologue;
|
||||
} else {
|
||||
print <<EOF;
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Chrony Frequently Asked Questions
|
||||
</title>
|
||||
</head>
|
||||
<body>
|
||||
<font face=\"arial,helvetica\" size=+4><b>Table of contents</b></font>
|
||||
EOF
|
||||
}
|
||||
|
||||
# Emit table of contents
|
||||
print "<ul>\n";
|
||||
for $sn (0 .. $#sections) {
|
||||
print "<b><li> <a href=\"#section_".($sn+1)."\">".($sn+1).".</a> ".$sections[$sn]."</b>\n";
|
||||
print " <ul>\n";
|
||||
for $qn (0 .. $#{$questions[$sn]}) {
|
||||
$sq = ($sn+1).".".($qn+1);
|
||||
print " <li> <a href=\"#question_".$sq."\">".$sq.".</a> ".$questions[$sn]->[$qn]."\n";
|
||||
#print " <li> ".$sq.". ".$questions[$sn]->[$qn]."\n";
|
||||
}
|
||||
print " </ul>\n";
|
||||
}
|
||||
print "</ul>\n";
|
||||
|
||||
# Emit main sections
|
||||
for $sn (0 .. $#sections) {
|
||||
print "<hr>\n";
|
||||
print "<a name=section_".($sn+1).">\n";
|
||||
#print "<b><font size=+2 face=\"arial,helvetica\">".($sn+1).". ".$sections[$sn]."</font></b>\n";
|
||||
print "<?php pretty_h2(\"".($sn+1).". ".$sections[$sn]."\"); ?>\n";
|
||||
if ($sect_text[$sn] ne "") {
|
||||
print "<pre>\n";
|
||||
print $sect_text[$sn];
|
||||
print "</pre>\n";
|
||||
}
|
||||
for $qn (0 .. $#{$questions[$sn]}) {
|
||||
$sq = ($sn+1).".".($qn+1);
|
||||
print "<p>\n";
|
||||
print "<a name=question_".$sq.">\n";
|
||||
print "<font size=+1 face=\"arial,helvetica\">".$sq.". ".$questions[$sn]->[$qn]."</font>\n";
|
||||
print "<pre>\n";
|
||||
print $answers[$sn]->[$qn];
|
||||
print "</pre>\n";
|
||||
}
|
||||
}
|
||||
|
||||
# Print footer
|
||||
if ($#epilogue >= 0) {
|
||||
print @epilogue;
|
||||
} else {
|
||||
print <<EOF;
|
||||
</body>
|
||||
</html>
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
#{{{ sub guard {
|
||||
sub guard {
|
||||
# Hide wierd tags etc
|
||||
my ($x) = @_;
|
||||
return $x;
|
||||
}
|
||||
#}}}
|
||||
|
||||
|
||||
@@ -8,12 +8,7 @@
|
||||
** This code is in the public domain and has no copyright.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
# ifdef HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
# endif
|
||||
#endif
|
||||
#include "config.h"
|
||||
|
||||
/* Since the code of getdate.y is not included in the Emacs executable
|
||||
itself, there is no need to #define static in this file. Even if
|
||||
@@ -711,7 +706,7 @@ LookupWord (buff)
|
||||
/* Make it lowercase. */
|
||||
for (p = buff; *p; p++)
|
||||
if (ISUPPER ((unsigned char) *p))
|
||||
*p = tolower (*p);
|
||||
*p = tolower ((unsigned char) *p);
|
||||
|
||||
if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0)
|
||||
{
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/strerror.c,v 1.8 2002/02/28 23:27:14 richard Exp $
|
||||
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2002
|
||||
* Copyright (C) Miroslav Lichvar 2012
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -26,16 +21,23 @@
|
||||
|
||||
=======================================================================
|
||||
|
||||
Replacement strerror function for systems that don't have it
|
||||
Header file for crypto hashing.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef SUNOS
|
||||
#ifndef GOT_HASH_H
|
||||
#define GOT_HASH_H
|
||||
|
||||
#include <errno.h>
|
||||
extern char *sys_errlist[];
|
||||
/* length of hash values produced by SHA512 */
|
||||
#define MAX_HASH_LENGTH 64
|
||||
|
||||
char *strerror(int n) {
|
||||
return sys_errlist[n];
|
||||
}
|
||||
extern int HSH_GetHashId(const char *name);
|
||||
|
||||
#endif /* SUNOS */
|
||||
extern unsigned int HSH_Hash(int id,
|
||||
const unsigned char *in1, unsigned int in1_len,
|
||||
const unsigned char *in2, unsigned int in2_len,
|
||||
unsigned char *out, unsigned int out_len);
|
||||
|
||||
extern void HSH_Finalise(void);
|
||||
|
||||
#endif
|
||||
@@ -1,12 +1,8 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/acquire.h,v 1.9 2002/02/28 23:27:07 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2002
|
||||
* Copyright (C) Miroslav Lichvar 2012
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -25,25 +21,49 @@
|
||||
|
||||
=======================================================================
|
||||
|
||||
Header file for acquisition module
|
||||
Routines implementing crypto hashing using internal MD5 implementation.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef GOT_ACQUIRE_H
|
||||
#define GOT_ACQUIRE_H
|
||||
#include "config.h"
|
||||
#include "sysincl.h"
|
||||
#include "hash.h"
|
||||
#include "memory.h"
|
||||
|
||||
#include "addressing.h"
|
||||
#include "md5.c"
|
||||
|
||||
typedef struct ACQ_SourceRecord *ACQ_Source;
|
||||
static MD5_CTX ctx;
|
||||
|
||||
extern void ACQ_Initialise(void);
|
||||
int
|
||||
HSH_GetHashId(const char *name)
|
||||
{
|
||||
/* only MD5 is supported */
|
||||
if (strcmp(name, "MD5"))
|
||||
return -1;
|
||||
|
||||
extern void ACQ_Finalise(void);
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void ACQ_StartAcquisition(int n, IPAddr *ip_addrs, int init_slew_threshold,
|
||||
void (*after_hook)(void *), void *anything);
|
||||
unsigned int
|
||||
HSH_Hash(int id, const unsigned char *in1, unsigned int in1_len,
|
||||
const unsigned char *in2, unsigned int in2_len,
|
||||
unsigned char *out, unsigned int out_len)
|
||||
{
|
||||
if (out_len < 16)
|
||||
return 0;
|
||||
|
||||
extern void ACQ_AccumulateSample(ACQ_Source acq_source, double offset, double root_distance);
|
||||
MD5Init(&ctx);
|
||||
MD5Update(&ctx, in1, in1_len);
|
||||
if (in2)
|
||||
MD5Update(&ctx, in2, in2_len);
|
||||
MD5Final(&ctx);
|
||||
|
||||
extern void ACQ_MissedSample(ACQ_Source acq_source);
|
||||
memcpy(out, ctx.digest, 16);
|
||||
|
||||
#endif /* GOT_ACQUIRE_H */
|
||||
return 16;
|
||||
}
|
||||
|
||||
void
|
||||
HSH_Finalise(void)
|
||||
{
|
||||
}
|
||||
104
hash_nss.c
Normal file
104
hash_nss.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Miroslav Lichvar 2012
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
=======================================================================
|
||||
|
||||
Routines implementing crypto hashing using NSSLOWHASH API of the NSS library.
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <nss.h>
|
||||
#include <hasht.h>
|
||||
#include <nsslowhash.h>
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
static NSSLOWInitContext *ictx;
|
||||
|
||||
struct hash {
|
||||
HASH_HashType type;
|
||||
const char *name;
|
||||
NSSLOWHASHContext *context;
|
||||
};
|
||||
|
||||
static struct hash hashes[] = {
|
||||
{ HASH_AlgMD5, "MD5", NULL },
|
||||
{ HASH_AlgSHA1, "SHA1", NULL },
|
||||
{ HASH_AlgSHA256, "SHA256", NULL },
|
||||
{ HASH_AlgSHA384, "SHA384", NULL },
|
||||
{ HASH_AlgSHA512, "SHA512", NULL },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
int
|
||||
HSH_GetHashId(const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; hashes[i].name; i++) {
|
||||
if (!strcmp(name, hashes[i].name))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!hashes[i].name)
|
||||
return -1; /* not found */
|
||||
|
||||
if (!ictx && !(ictx = NSSLOW_Init()))
|
||||
return -1; /* couldn't init NSS */
|
||||
|
||||
if (!hashes[i].context &&
|
||||
!(hashes[i].context = NSSLOWHASH_NewContext(ictx, hashes[i].type)))
|
||||
return -1; /* couldn't init hash */
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
HSH_Hash(int id, const unsigned char *in1, unsigned int in1_len,
|
||||
const unsigned char *in2, unsigned int in2_len,
|
||||
unsigned char *out, unsigned int out_len)
|
||||
{
|
||||
unsigned int ret;
|
||||
|
||||
NSSLOWHASH_Begin(hashes[id].context);
|
||||
NSSLOWHASH_Update(hashes[id].context, in1, in1_len);
|
||||
if (in2)
|
||||
NSSLOWHASH_Update(hashes[id].context, in2, in2_len);
|
||||
NSSLOWHASH_End(hashes[id].context, out, &ret, out_len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
HSH_Finalise(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; hashes[i].name; i++) {
|
||||
if (hashes[i].context)
|
||||
NSSLOWHASH_Destroy(hashes[i].context);
|
||||
}
|
||||
|
||||
if (ictx)
|
||||
NSSLOW_Shutdown(ictx);
|
||||
}
|
||||
121
hash_tomcrypt.c
Normal file
121
hash_tomcrypt.c
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Miroslav Lichvar 2012
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
=======================================================================
|
||||
|
||||
Routines implementing crypto hashing using tomcrypt library.
|
||||
|
||||
*/
|
||||
|
||||
#include <tomcrypt.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "hash.h"
|
||||
|
||||
struct hash {
|
||||
const char *name;
|
||||
const char *int_name;
|
||||
const struct ltc_hash_descriptor *desc;
|
||||
};
|
||||
|
||||
static const struct hash hashes[] = {
|
||||
{ "MD5", "md5", &md5_desc },
|
||||
#ifdef LTC_RIPEMD128
|
||||
{ "RMD128", "rmd128", &rmd128_desc },
|
||||
#endif
|
||||
#ifdef LTC_RIPEMD160
|
||||
{ "RMD160", "rmd160", &rmd160_desc },
|
||||
#endif
|
||||
#ifdef LTC_RIPEMD256
|
||||
{ "RMD256", "rmd256", &rmd256_desc },
|
||||
#endif
|
||||
#ifdef LTC_RIPEMD320
|
||||
{ "RMD320", "rmd320", &rmd320_desc },
|
||||
#endif
|
||||
#ifdef LTC_SHA1
|
||||
{ "SHA1", "sha1", &sha1_desc },
|
||||
#endif
|
||||
#ifdef LTC_SHA256
|
||||
{ "SHA256", "sha256", &sha256_desc },
|
||||
#endif
|
||||
#ifdef LTC_SHA384
|
||||
{ "SHA384", "sha384", &sha384_desc },
|
||||
#endif
|
||||
#ifdef LTC_SHA512
|
||||
{ "SHA512", "sha512", &sha512_desc },
|
||||
#endif
|
||||
#ifdef LTC_TIGER
|
||||
{ "TIGER", "tiger", &tiger_desc },
|
||||
#endif
|
||||
#ifdef LTC_WHIRLPOOL
|
||||
{ "WHIRLPOOL", "whirlpool", &whirlpool_desc },
|
||||
#endif
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
int
|
||||
HSH_GetHashId(const char *name)
|
||||
{
|
||||
int i, h;
|
||||
|
||||
for (i = 0; hashes[i].name; i++) {
|
||||
if (!strcmp(name, hashes[i].name))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!hashes[i].name)
|
||||
return -1; /* not found */
|
||||
|
||||
h = find_hash(hashes[i].int_name);
|
||||
if (h >= 0)
|
||||
return h; /* already registered */
|
||||
|
||||
/* register and try again */
|
||||
register_hash(hashes[i].desc);
|
||||
|
||||
return find_hash(hashes[i].int_name);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
HSH_Hash(int id, const unsigned char *in1, unsigned int in1_len,
|
||||
const unsigned char *in2, unsigned int in2_len,
|
||||
unsigned char *out, unsigned int out_len)
|
||||
{
|
||||
unsigned long len;
|
||||
int r;
|
||||
|
||||
len = out_len;
|
||||
if (in2)
|
||||
r = hash_memory_multi(id, out, &len,
|
||||
in1, (unsigned long)in1_len, in2, (unsigned long)in2_len, NULL, 0);
|
||||
else
|
||||
r = hash_memory(id, in1, in1_len, out, &len);
|
||||
|
||||
if (r != CRYPT_OK)
|
||||
return 0;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void
|
||||
HSH_Finalise(void)
|
||||
{
|
||||
}
|
||||
75
io_linux.h
75
io_linux.h
@@ -1,75 +0,0 @@
|
||||
/* Taken from <asm-$foo/ioctl.h> in the Linux kernel sources.
|
||||
* The ioctl.h file is pretty similar from one architecture to another.
|
||||
* */
|
||||
#ifndef IO_LINUX_H
|
||||
#define IO_LINUX_H
|
||||
|
||||
/* Hmm. These constants vary a bit between systems. */
|
||||
/* (__sh__ includes both sh and sh64) */
|
||||
/* (__s390__ includes both s390 and s390x) */
|
||||
#if defined(__i386__) || defined(__sh__) || defined(__arm__) || defined(__x86_64__) || defined(__s390__)
|
||||
#define CHRONY_IOC_NRBITS 8
|
||||
#define CHRONY_IOC_TYPEBITS 8
|
||||
#define CHRONY_IOC_SIZEBITS 14
|
||||
#define CHRONY_IOC_DIRBITS 2
|
||||
|
||||
#define CHRONY_IOC_NONE 0U
|
||||
#define CHRONY_IOC_WRITE 1U
|
||||
#define CHRONY_IOC_READ 2U
|
||||
|
||||
#elif defined(__alpha__) || defined(__sparc__) || defined(__ppc__) || defined(__ppc64__) || defined(__sparc64__)
|
||||
#define CHRONY_IOC_NRBITS 8
|
||||
#define CHRONY_IOC_TYPEBITS 8
|
||||
#define CHRONY_IOC_SIZEBITS 13
|
||||
#define CHRONY_IOC_DIRBITS 2
|
||||
|
||||
#define CHRONY_IOC_NONE 1U
|
||||
#define CHRONY_IOC_READ 2U
|
||||
#define CHRONY_IOC_WRITE 4U
|
||||
|
||||
#elif defined(__mips__) || defined(__mips32__) || defined(__powerpc__)
|
||||
#define CHRONY_IOC_NRBITS 8
|
||||
#define CHRONY_IOC_TYPEBITS 8
|
||||
#define CHRONY_IOC_SIZEBITS 13
|
||||
#define CHRONY_IOC_DIRBITS 3
|
||||
#define CHRONY_IOC_NONE 1U
|
||||
#define CHRONY_IOC_READ 2U
|
||||
#define CHRONY_IOC_WRITE 4U
|
||||
|
||||
#else
|
||||
#error "I don't know the values of the _IOC_* constants for your architecture"
|
||||
#endif
|
||||
|
||||
#define CHRONY_IOC_NRMASK ((1 << CHRONY_IOC_NRBITS)-1)
|
||||
#define CHRONY_IOC_TYPEMASK ((1 << CHRONY_IOC_TYPEBITS)-1)
|
||||
#define CHRONY_IOC_SIZEMASK ((1 << CHRONY_IOC_SIZEBITS)-1)
|
||||
#define CHRONY_IOC_DIRMASK ((1 << CHRONY_IOC_DIRBITS)-1)
|
||||
|
||||
#define CHRONY_IOC_NRSHIFT 0
|
||||
#define CHRONY_IOC_TYPESHIFT (CHRONY_IOC_NRSHIFT+CHRONY_IOC_NRBITS)
|
||||
#define CHRONY_IOC_SIZESHIFT (CHRONY_IOC_TYPESHIFT+CHRONY_IOC_TYPEBITS)
|
||||
#define CHRONY_IOC_DIRSHIFT (CHRONY_IOC_SIZESHIFT+CHRONY_IOC_SIZEBITS)
|
||||
|
||||
#define CHRONY_IOC(dir,type,nr,size) \
|
||||
(((dir) << CHRONY_IOC_DIRSHIFT) | \
|
||||
((type) << CHRONY_IOC_TYPESHIFT) | \
|
||||
((nr) << CHRONY_IOC_NRSHIFT) | \
|
||||
((size) << CHRONY_IOC_SIZESHIFT))
|
||||
|
||||
/* used to create numbers */
|
||||
#define CHRONY_IO(type,nr) CHRONY_IOC(CHRONY_IOC_NONE,(type),(nr),0)
|
||||
#define CHRONY_IOR(type,nr,size) CHRONY_IOC(CHRONY_IOC_READ,(type),(nr),sizeof(size))
|
||||
#define CHRONY_IOW(type,nr,size) CHRONY_IOC(CHRONY_IOC_WRITE,(type),(nr),sizeof(size))
|
||||
#define CHRONY_IOWR(type,nr,size) CHRONY_IOC(CHRONY_IOC_READ|CHRONY_IOC_WRITE,(type),(nr),sizeof(size))
|
||||
|
||||
#define RTC_UIE_ON CHRONY_IO('p', 0x03) /* Update int. enable on */
|
||||
#define RTC_UIE_OFF CHRONY_IO('p', 0x04) /* ... off */
|
||||
|
||||
#define RTC_RD_TIME CHRONY_IOR('p', 0x09, struct rtc_time) /* Read RTC time */
|
||||
#define RTC_SET_TIME CHRONY_IOW('p', 0x0a, struct rtc_time) /* Set RTC time */
|
||||
|
||||
/* From mc146818.h */
|
||||
#define RTC_UIE 0x10 /* update-finished interrupt enable */
|
||||
|
||||
#endif
|
||||
|
||||
334
keys.c
334
keys.c
@@ -1,12 +1,9 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/keys.c,v 1.12 2003/09/22 21:22:30 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2012-2014
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -29,41 +26,56 @@
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "config.h"
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "array.h"
|
||||
#include "keys.h"
|
||||
#include "cmdparse.h"
|
||||
#include "conf.h"
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "local.h"
|
||||
#include "logging.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
unsigned long id;
|
||||
uint32_t id;
|
||||
char *val;
|
||||
int len;
|
||||
int hash_id;
|
||||
int auth_delay;
|
||||
} Key;
|
||||
|
||||
#define MAX_KEYS 256
|
||||
static ARR_Instance keys;
|
||||
|
||||
static int n_keys;
|
||||
static Key keys[MAX_KEYS];
|
||||
|
||||
static int command_key_valid;
|
||||
static int command_key_pos;
|
||||
static int cache_valid;
|
||||
static unsigned long cache_key_id;
|
||||
static uint32_t cache_key_id;
|
||||
static int cache_key_pos;
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
free_keys(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARR_GetSize(keys); i++)
|
||||
Free(((Key *)ARR_GetElement(keys, i))->val);
|
||||
|
||||
ARR_SetSize(keys, 0);
|
||||
cache_valid = 0;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
KEY_Initialise(void)
|
||||
{
|
||||
n_keys = 0;
|
||||
command_key_valid = 0;
|
||||
keys = ARR_CreateInstance(sizeof (Key));
|
||||
cache_valid = 0;
|
||||
KEY_Reload();
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -71,8 +83,47 @@ KEY_Initialise(void)
|
||||
void
|
||||
KEY_Finalise(void)
|
||||
{
|
||||
/* Nothing to do */
|
||||
return;
|
||||
free_keys();
|
||||
ARR_DestroyInstance(keys);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static Key *
|
||||
get_key(unsigned int index)
|
||||
{
|
||||
return ((Key *)ARR_GetElements(keys)) + index;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
determine_hash_delay(uint32_t key_id)
|
||||
{
|
||||
NTP_Packet pkt;
|
||||
struct timeval before, after;
|
||||
unsigned long usecs, min_usecs=0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
LCL_ReadRawTime(&before);
|
||||
KEY_GenerateAuth(key_id, (unsigned char *)&pkt, NTP_NORMAL_PACKET_LENGTH,
|
||||
(unsigned char *)&pkt.auth_data, sizeof (pkt.auth_data));
|
||||
LCL_ReadRawTime(&after);
|
||||
|
||||
usecs = (after.tv_sec - before.tv_sec) * 1000000 + (after.tv_usec - before.tv_usec);
|
||||
|
||||
if (i == 0 || usecs < min_usecs) {
|
||||
min_usecs = usecs;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add on a bit extra to allow for copying, conversions etc */
|
||||
min_usecs += min_usecs >> 4;
|
||||
|
||||
DEBUG_LOG(LOGF_Keys, "authentication delay for key %"PRIu32": %ld useconds", key_id, min_usecs);
|
||||
|
||||
return min_usecs;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -97,147 +148,176 @@ compare_keys_by_id(const void *a, const void *b)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
|
||||
#define KEYLEN 2047
|
||||
#define SKEYLEN "2047"
|
||||
|
||||
void
|
||||
KEY_Reload(void)
|
||||
{
|
||||
int i, len1;
|
||||
char *key_file;
|
||||
unsigned int i, line_number;
|
||||
FILE *in;
|
||||
unsigned long key_id;
|
||||
char line[KEYLEN+1], keyval[KEYLEN+1];
|
||||
uint32_t key_id;
|
||||
char line[2048], *keyval, *key_file;
|
||||
const char *hashname;
|
||||
Key key;
|
||||
|
||||
for (i=0; i<n_keys; i++) {
|
||||
Free(keys[i].val);
|
||||
}
|
||||
|
||||
n_keys = 0;
|
||||
free_keys();
|
||||
|
||||
key_file = CNF_GetKeysFile();
|
||||
line_number = 0;
|
||||
|
||||
if (key_file) {
|
||||
in = fopen(key_file, "r");
|
||||
if (in) {
|
||||
while (fgets(line, sizeof(line), in)) {
|
||||
len1 = strlen(line) - 1;
|
||||
if (!key_file)
|
||||
return;
|
||||
|
||||
/* Guard against removing last character of the line
|
||||
* if the last line of the file is missing an end-of-line */
|
||||
if (line[len1] == '\n') {
|
||||
line[len1] = '\0';
|
||||
}
|
||||
|
||||
if (sscanf(line, "%lu%" SKEYLEN "s", &key_id, keyval) == 2) {
|
||||
keys[n_keys].id = key_id;
|
||||
keys[n_keys].len = strlen(keyval);
|
||||
keys[n_keys].val = MallocArray(char, 1 + keys[n_keys].len);
|
||||
strcpy(keys[n_keys].val, keyval);
|
||||
n_keys++;
|
||||
}
|
||||
}
|
||||
fclose(in);
|
||||
|
||||
/* Sort keys into order. Note, if there's a duplicate, it is
|
||||
arbitrary which one we use later - the user should have been
|
||||
more careful! */
|
||||
qsort((void *) keys, n_keys, sizeof(Key), compare_keys_by_id);
|
||||
|
||||
}
|
||||
in = fopen(key_file, "r");
|
||||
if (!in) {
|
||||
LOG(LOGS_WARN, LOGF_Keys, "Could not open keyfile %s", key_file);
|
||||
return;
|
||||
}
|
||||
|
||||
command_key_valid = 0;
|
||||
cache_valid = 0;
|
||||
while (fgets(line, sizeof (line), in)) {
|
||||
line_number++;
|
||||
|
||||
return;
|
||||
CPS_NormalizeLine(line);
|
||||
if (!*line)
|
||||
continue;
|
||||
|
||||
if (!CPS_ParseKey(line, &key_id, &hashname, &keyval)) {
|
||||
LOG(LOGS_WARN, LOGF_Keys, "Could not parse key at line %d in file %s", line_number, key_file);
|
||||
continue;
|
||||
}
|
||||
|
||||
key.hash_id = HSH_GetHashId(hashname);
|
||||
if (key.hash_id < 0) {
|
||||
LOG(LOGS_WARN, LOGF_Keys, "Unknown hash function in key %"PRIu32, key_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
key.len = UTI_DecodePasswordFromText(keyval);
|
||||
if (!key.len) {
|
||||
LOG(LOGS_WARN, LOGF_Keys, "Could not decode password in key %"PRIu32, key_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
key.id = key_id;
|
||||
key.val = MallocArray(char, key.len);
|
||||
memcpy(key.val, keyval, key.len);
|
||||
ARR_AppendElement(keys, &key);
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
|
||||
/* Sort keys into order. Note, if there's a duplicate, it is
|
||||
arbitrary which one we use later - the user should have been
|
||||
more careful! */
|
||||
qsort(ARR_GetElements(keys), ARR_GetSize(keys), sizeof (Key), compare_keys_by_id);
|
||||
|
||||
/* Check for duplicates */
|
||||
for (i = 1; i < ARR_GetSize(keys); i++) {
|
||||
if (get_key(i - 1)->id == get_key(i)->id)
|
||||
LOG(LOGS_WARN, LOGF_Keys, "Detected duplicate key %"PRIu32, get_key(i - 1)->id);
|
||||
}
|
||||
|
||||
/* Erase any passwords from stack */
|
||||
memset(line, 0, sizeof (line));
|
||||
|
||||
for (i = 0; i < ARR_GetSize(keys); i++)
|
||||
get_key(i)->auth_delay = determine_hash_delay(get_key(i)->id);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
lookup_key(unsigned long id)
|
||||
lookup_key(uint32_t id)
|
||||
{
|
||||
Key specimen, *where;
|
||||
Key specimen, *where, *keys_ptr;
|
||||
int pos;
|
||||
|
||||
keys_ptr = ARR_GetElements(keys);
|
||||
specimen.id = id;
|
||||
where = (Key *) bsearch((void *)&specimen, (void *)keys, n_keys, sizeof(Key), compare_keys_by_id);
|
||||
where = (Key *)bsearch((void *)&specimen, keys_ptr, ARR_GetSize(keys),
|
||||
sizeof (Key), compare_keys_by_id);
|
||||
if (!where) {
|
||||
return -1;
|
||||
} else {
|
||||
pos = where - keys;
|
||||
pos = where - keys_ptr;
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
KEY_CommandKey(char **key, int *len)
|
||||
{
|
||||
unsigned long command_key_id;
|
||||
|
||||
if (!command_key_valid) {
|
||||
command_key_id = CNF_GetCommandKey();
|
||||
command_key_pos = lookup_key(command_key_id);
|
||||
command_key_valid = 1;
|
||||
}
|
||||
|
||||
if (command_key_pos >= 0) {
|
||||
*key = keys[command_key_pos].val;
|
||||
*len = keys[command_key_pos].len;
|
||||
} else {
|
||||
*key = "";
|
||||
*len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
KEY_GetKey(unsigned long key_id, char **key, int *len)
|
||||
{
|
||||
if (!cache_valid || key_id != cache_key_id) {
|
||||
cache_valid = 1;
|
||||
cache_key_pos = lookup_key(key_id);
|
||||
cache_key_id = key_id;
|
||||
}
|
||||
|
||||
if (cache_key_pos >= 0) {
|
||||
*key = keys[cache_key_pos].val;
|
||||
*len = keys[cache_key_pos].len;
|
||||
return 1;
|
||||
} else {
|
||||
*key = "";
|
||||
*len = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
KEY_KeyKnown(unsigned long key_id)
|
||||
static Key *
|
||||
get_key_by_id(uint32_t key_id)
|
||||
{
|
||||
int position;
|
||||
|
||||
if (cache_valid && (key_id == cache_key_id)) {
|
||||
return 1;
|
||||
} else {
|
||||
if (cache_valid && key_id == cache_key_id)
|
||||
return get_key(cache_key_pos);
|
||||
|
||||
position = lookup_key(key_id);
|
||||
position = lookup_key(key_id);
|
||||
|
||||
if (position >= 0) {
|
||||
/* Store key in cache, we will probably be using it in a
|
||||
minute... */
|
||||
cache_valid = 1;
|
||||
cache_key_pos = position;
|
||||
cache_key_id = key_id;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if (position >= 0) {
|
||||
cache_valid = 1;
|
||||
cache_key_pos = position;
|
||||
cache_key_id = key_id;
|
||||
|
||||
return get_key(position);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
KEY_KeyKnown(uint32_t key_id)
|
||||
{
|
||||
return get_key_by_id(key_id) != NULL;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
KEY_GetAuthDelay(uint32_t key_id)
|
||||
{
|
||||
Key *key;
|
||||
|
||||
key = get_key_by_id(key_id);
|
||||
|
||||
if (!key)
|
||||
return 0;
|
||||
|
||||
return key->auth_delay;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
KEY_GenerateAuth(uint32_t key_id, const unsigned char *data, int data_len,
|
||||
unsigned char *auth, int auth_len)
|
||||
{
|
||||
Key *key;
|
||||
|
||||
key = get_key_by_id(key_id);
|
||||
|
||||
if (!key)
|
||||
return 0;
|
||||
|
||||
return UTI_GenerateNTPAuth(key->hash_id, (unsigned char *)key->val,
|
||||
key->len, data, data_len, auth, auth_len);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
KEY_CheckAuth(uint32_t key_id, const unsigned char *data, int data_len,
|
||||
const unsigned char *auth, int auth_len)
|
||||
{
|
||||
Key *key;
|
||||
|
||||
key = get_key_by_id(key_id);
|
||||
|
||||
if (!key)
|
||||
return 0;
|
||||
|
||||
return UTI_CheckNTPAuth(key->hash_id, (unsigned char *)key->val,
|
||||
key->len, data, data_len, auth, auth_len);
|
||||
}
|
||||
|
||||
16
keys.h
16
keys.h
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/keys.h,v 1.8 2002/02/28 23:27:10 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
@@ -31,14 +27,20 @@
|
||||
#ifndef GOT_KEYS_H
|
||||
#define GOT_KEYS_H
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
extern void KEY_Initialise(void);
|
||||
extern void KEY_Finalise(void);
|
||||
|
||||
extern void KEY_Reload(void);
|
||||
|
||||
extern void KEY_CommandKey(char **key, int *len);
|
||||
extern int KEY_GetKey(uint32_t key_id, char **key, int *len);
|
||||
extern int KEY_KeyKnown(uint32_t key_id);
|
||||
extern int KEY_GetAuthDelay(uint32_t key_id);
|
||||
|
||||
extern int KEY_GetKey(unsigned long key_id, char **key, int *len);
|
||||
extern int KEY_KeyKnown(unsigned long key_id);
|
||||
extern int KEY_GenerateAuth(uint32_t key_id, const unsigned char *data,
|
||||
int data_len, unsigned char *auth, int auth_len);
|
||||
extern int KEY_CheckAuth(uint32_t key_id, const unsigned char *data,
|
||||
int data_len, const unsigned char *auth, int auth_len);
|
||||
|
||||
#endif /* GOT_KEYS_H */
|
||||
|
||||
518
local.c
518
local.c
@@ -1,12 +1,9 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/local.c,v 1.21 2003/09/22 21:22:30 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2011, 2014-2015
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -31,20 +28,30 @@
|
||||
They interface with the system specific driver files in sys_*.c
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include "config.h"
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "conf.h"
|
||||
#include "local.h"
|
||||
#include "localp.h"
|
||||
#include "memory.h"
|
||||
#include "smooth.h"
|
||||
#include "util.h"
|
||||
#include "logging.h"
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
/* Maximum allowed frequency offset in ppm, the time must not stop
|
||||
or run backwards */
|
||||
#define MAX_FREQ 500000.0
|
||||
|
||||
/* Variable to store the current frequency, in ppm */
|
||||
static double current_freq_ppm;
|
||||
|
||||
/* Temperature compensation, in ppm */
|
||||
static double temp_comp_ppm;
|
||||
|
||||
/* ================================================== */
|
||||
/* Store the system dependent drivers */
|
||||
|
||||
@@ -53,8 +60,8 @@ static lcl_SetFrequencyDriver drv_set_freq;
|
||||
static lcl_AccrueOffsetDriver drv_accrue_offset;
|
||||
static lcl_ApplyStepOffsetDriver drv_apply_step_offset;
|
||||
static lcl_OffsetCorrectionDriver drv_offset_convert;
|
||||
static lcl_ImmediateStepDriver drv_immediate_step;
|
||||
static lcl_SetLeapDriver drv_set_leap;
|
||||
static lcl_SetSyncStatusDriver drv_set_sync_status;
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
@@ -89,6 +96,8 @@ static DispersionNotifyListEntry dispersion_notify_list;
|
||||
static int precision_log;
|
||||
static double precision_quantum;
|
||||
|
||||
static double max_clock_error;
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
/* Define the number of increments of the system clock that we want
|
||||
@@ -101,17 +110,15 @@ static double precision_quantum;
|
||||
static void
|
||||
calculate_sys_precision(void)
|
||||
{
|
||||
struct timeval tv, old_tv, first_tv;
|
||||
struct timezone tz;
|
||||
struct timeval tv, old_tv;
|
||||
int dusec, best_dusec;
|
||||
int iters;
|
||||
|
||||
gettimeofday(&old_tv, &tz);
|
||||
first_tv = old_tv;
|
||||
gettimeofday(&old_tv, NULL);
|
||||
best_dusec = 1000000; /* Assume we must be better than a second */
|
||||
iters = 0;
|
||||
do {
|
||||
gettimeofday(&tv, &tz);
|
||||
gettimeofday(&tv, NULL);
|
||||
dusec = 1000000*(tv.tv_sec - old_tv.tv_sec) + (tv.tv_usec - old_tv.tv_usec);
|
||||
old_tv = tv;
|
||||
if (dusec > 0) {
|
||||
@@ -121,18 +128,19 @@ calculate_sys_precision(void)
|
||||
iters++;
|
||||
}
|
||||
} while (iters < NITERS);
|
||||
if (!(best_dusec > 0)) {
|
||||
CROAK("best_dusec should be positive");
|
||||
}
|
||||
|
||||
assert(best_dusec > 0);
|
||||
|
||||
precision_quantum = best_dusec * 1.0e-6;
|
||||
|
||||
/* Get rounded log2 value of the measured precision */
|
||||
precision_log = 0;
|
||||
while (best_dusec < 500000) {
|
||||
while (best_dusec < 707107) {
|
||||
precision_log--;
|
||||
best_dusec *= 2;
|
||||
}
|
||||
|
||||
precision_quantum = 1.0 / (double)(1<<(-precision_log));
|
||||
|
||||
return;
|
||||
DEBUG_LOG(LOGF_Local, "Clock precision %.9f (%d)", precision_quantum, precision_log);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -154,8 +162,11 @@ LCL_Initialise(void)
|
||||
|
||||
/* This ought to be set from the system driver layer */
|
||||
current_freq_ppm = 0.0;
|
||||
temp_comp_ppm = 0.0;
|
||||
|
||||
calculate_sys_precision();
|
||||
|
||||
max_clock_error = CNF_GetMaxClockError() * 1e-6;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -163,7 +174,13 @@ LCL_Initialise(void)
|
||||
void
|
||||
LCL_Finalise(void)
|
||||
{
|
||||
return;
|
||||
while (change_list.next != &change_list)
|
||||
LCL_RemoveParameterChangeHandler(change_list.next->handler,
|
||||
change_list.next->anything);
|
||||
|
||||
while (dispersion_notify_list.next != &dispersion_notify_list)
|
||||
LCL_RemoveDispersionNotifyHandler(dispersion_notify_list.next->handler,
|
||||
dispersion_notify_list.next->anything);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -186,6 +203,14 @@ LCL_GetSysPrecisionAsQuantum(void)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
double
|
||||
LCL_GetMaxClockError(void)
|
||||
{
|
||||
return max_clock_error;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LCL_AddParameterChangeHandler(LCL_ParameterChangeHandler handler, void *anything)
|
||||
{
|
||||
@@ -194,7 +219,7 @@ LCL_AddParameterChangeHandler(LCL_ParameterChangeHandler handler, void *anything
|
||||
/* Check that the handler is not already registered */
|
||||
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
|
||||
if (!(ptr->handler != handler || ptr->anything != anything)) {
|
||||
CROAK("a handler is already registered");
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,14 +233,11 @@ LCL_AddParameterChangeHandler(LCL_ParameterChangeHandler handler, void *anything
|
||||
new_entry->prev = change_list.prev;
|
||||
change_list.prev->next = new_entry;
|
||||
change_list.prev = new_entry;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
/* Remove a handler */
|
||||
extern
|
||||
void LCL_RemoveParameterChangeHandler(LCL_ParameterChangeHandler handler, void *anything)
|
||||
{
|
||||
|
||||
@@ -232,17 +254,35 @@ void LCL_RemoveParameterChangeHandler(LCL_ParameterChangeHandler handler, void *
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
CROAK("did not find a matching handler");
|
||||
}
|
||||
assert(ok);
|
||||
|
||||
/* Unlink entry from the list */
|
||||
ptr->next->prev = ptr->prev;
|
||||
ptr->prev->next = ptr->next;
|
||||
|
||||
free(ptr);
|
||||
Free(ptr);
|
||||
}
|
||||
|
||||
return;
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
LCL_IsFirstParameterChangeHandler(LCL_ParameterChangeHandler handler)
|
||||
{
|
||||
return change_list.next->handler == handler;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
invoke_parameter_change_handlers(struct timeval *raw, struct timeval *cooked,
|
||||
double dfreq, double doffset,
|
||||
LCL_ChangeType change_type)
|
||||
{
|
||||
ChangeListEntry *ptr;
|
||||
|
||||
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
|
||||
(ptr->handler)(raw, cooked, dfreq, doffset, change_type, ptr->anything);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -255,7 +295,7 @@ LCL_AddDispersionNotifyHandler(LCL_DispersionNotifyHandler handler, void *anythi
|
||||
/* Check that the handler is not already registered */
|
||||
for (ptr = dispersion_notify_list.next; ptr != &dispersion_notify_list; ptr = ptr->next) {
|
||||
if (!(ptr->handler != handler || ptr->anything != anything)) {
|
||||
CROAK("a handler is already registered");
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,8 +309,6 @@ LCL_AddDispersionNotifyHandler(LCL_DispersionNotifyHandler handler, void *anythi
|
||||
new_entry->prev = dispersion_notify_list.prev;
|
||||
dispersion_notify_list.prev->next = new_entry;
|
||||
dispersion_notify_list.prev = new_entry;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -293,17 +331,13 @@ void LCL_RemoveDispersionNotifyHandler(LCL_DispersionNotifyHandler handler, void
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
CROAK("no matching handler found");
|
||||
}
|
||||
assert(ok);
|
||||
|
||||
/* Unlink entry from the list */
|
||||
ptr->next->prev = ptr->prev;
|
||||
ptr->prev->next = ptr->next;
|
||||
|
||||
free(ptr);
|
||||
|
||||
return;
|
||||
Free(ptr);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -313,13 +347,9 @@ void LCL_RemoveDispersionNotifyHandler(LCL_DispersionNotifyHandler handler, void
|
||||
void
|
||||
LCL_ReadRawTime(struct timeval *result)
|
||||
{
|
||||
struct timezone tz;
|
||||
|
||||
if (!(gettimeofday(result, &tz) >= 0)) {
|
||||
CROAK("Could not get time of day");
|
||||
if (gettimeofday(result, NULL) < 0) {
|
||||
LOG_FATAL(LOGF_Local, "gettimeofday() failed");
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -328,67 +358,104 @@ void
|
||||
LCL_ReadCookedTime(struct timeval *result, double *err)
|
||||
{
|
||||
struct timeval raw;
|
||||
double correction;
|
||||
|
||||
LCL_ReadRawTime(&raw);
|
||||
|
||||
/* For now, cheat and set the error to zero in all cases.
|
||||
*/
|
||||
|
||||
*err = 0.0;
|
||||
|
||||
/* Call system specific driver to get correction */
|
||||
(*drv_offset_convert)(&raw, &correction);
|
||||
UTI_AddDoubleToTimeval(&raw, correction, result);
|
||||
|
||||
return;
|
||||
LCL_CookTime(&raw, result, err);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
double
|
||||
LCL_GetOffsetCorrection(struct timeval *raw)
|
||||
void
|
||||
LCL_CookTime(struct timeval *raw, struct timeval *cooked, double *err)
|
||||
{
|
||||
double correction;
|
||||
(*drv_offset_convert)(raw, &correction);
|
||||
return correction;
|
||||
|
||||
LCL_GetOffsetCorrection(raw, &correction, err);
|
||||
UTI_AddDoubleToTimeval(raw, correction, cooked);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
/* This is just a simple passthrough of the system specific routine */
|
||||
|
||||
void
|
||||
LCL_GetOffsetCorrection(struct timeval *raw, double *correction, double *err)
|
||||
{
|
||||
/* Call system specific driver to get correction */
|
||||
(*drv_offset_convert)(raw, correction, err);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
/* Return current frequency */
|
||||
|
||||
double
|
||||
LCL_ReadAbsoluteFrequency(void)
|
||||
{
|
||||
return (*drv_read_freq)();
|
||||
double freq;
|
||||
|
||||
freq = current_freq_ppm;
|
||||
|
||||
/* Undo temperature compensation */
|
||||
if (temp_comp_ppm != 0.0) {
|
||||
freq = (freq + temp_comp_ppm) / (1.0 - 1.0e-6 * temp_comp_ppm);
|
||||
}
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static double
|
||||
clamp_freq(double freq)
|
||||
{
|
||||
if (freq <= MAX_FREQ && freq >= -MAX_FREQ)
|
||||
return freq;
|
||||
|
||||
LOG(LOGS_WARN, LOGF_Local, "Frequency %.1f ppm exceeds allowed maximum", freq);
|
||||
|
||||
return freq >= MAX_FREQ ? MAX_FREQ : -MAX_FREQ;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
check_offset(struct timeval *now, double offset)
|
||||
{
|
||||
/* Check if the time will be still sane with accumulated offset */
|
||||
if (UTI_IsTimeOffsetSane(now, -offset))
|
||||
return 1;
|
||||
|
||||
LOG(LOGS_WARN, LOGF_Local, "Adjustment of %.1f seconds is invalid", -offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
/* This involves both setting the absolute frequency with the
|
||||
system-specific driver, as well as calling all notify handlers */
|
||||
|
||||
void
|
||||
LCL_SetAbsoluteFrequency(double afreq_ppm)
|
||||
{
|
||||
ChangeListEntry *ptr;
|
||||
struct timeval raw, cooked;
|
||||
double correction;
|
||||
double dfreq;
|
||||
|
||||
afreq_ppm = clamp_freq(afreq_ppm);
|
||||
|
||||
/* Apply temperature compensation */
|
||||
if (temp_comp_ppm != 0.0) {
|
||||
afreq_ppm = afreq_ppm * (1.0 - 1.0e-6 * temp_comp_ppm) - temp_comp_ppm;
|
||||
}
|
||||
|
||||
/* Call the system-specific driver for setting the frequency */
|
||||
|
||||
(*drv_set_freq)(afreq_ppm);
|
||||
afreq_ppm = (*drv_set_freq)(afreq_ppm);
|
||||
|
||||
dfreq = 1.0e-6 * (afreq_ppm - current_freq_ppm) / (1.0 - 1.0e-6 * current_freq_ppm);
|
||||
dfreq = (afreq_ppm - current_freq_ppm) / (1.0e6 - current_freq_ppm);
|
||||
|
||||
LCL_ReadRawTime(&raw);
|
||||
(drv_offset_convert)(&raw, &correction);
|
||||
UTI_AddDoubleToTimeval(&raw, correction, &cooked);
|
||||
LCL_CookTime(&raw, &cooked, NULL);
|
||||
|
||||
/* Dispatch to all handlers */
|
||||
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
|
||||
(ptr->handler)(&raw, &cooked, dfreq, afreq_ppm, 0.0, 0, ptr->anything);
|
||||
}
|
||||
invoke_parameter_change_handlers(&raw, &cooked, dfreq, 0.0, LCL_ChangeAdjust);
|
||||
|
||||
current_freq_ppm = afreq_ppm;
|
||||
|
||||
@@ -399,120 +466,147 @@ LCL_SetAbsoluteFrequency(double afreq_ppm)
|
||||
void
|
||||
LCL_AccumulateDeltaFrequency(double dfreq)
|
||||
{
|
||||
ChangeListEntry *ptr;
|
||||
struct timeval raw, cooked;
|
||||
double correction;
|
||||
|
||||
/* Work out new absolute frequency. Note that absolute frequencies
|
||||
are handled in units of ppm, whereas the 'dfreq' argument is in
|
||||
terms of the gradient of the (offset) v (local time) function. */
|
||||
|
||||
current_freq_ppm = (1.0 - dfreq) * current_freq_ppm +
|
||||
(1.0e6 * dfreq);
|
||||
|
||||
/* Call the system-specific driver for setting the frequency */
|
||||
(*drv_set_freq)(current_freq_ppm);
|
||||
|
||||
LCL_ReadRawTime(&raw);
|
||||
(drv_offset_convert)(&raw, &correction);
|
||||
UTI_AddDoubleToTimeval(&raw, correction, &cooked);
|
||||
|
||||
/* Dispatch to all handlers */
|
||||
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
|
||||
(ptr->handler)(&raw, &cooked, dfreq, current_freq_ppm, 0.0, 0, ptr->anything);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LCL_AccumulateOffset(double offset)
|
||||
{
|
||||
ChangeListEntry *ptr;
|
||||
struct timeval raw, cooked;
|
||||
double correction;
|
||||
|
||||
/* In this case, the cooked time to be passed to the notify clients
|
||||
has to be the cooked time BEFORE the change was made */
|
||||
|
||||
LCL_ReadRawTime(&raw);
|
||||
(drv_offset_convert)(&raw, &correction);
|
||||
UTI_AddDoubleToTimeval(&raw, correction, &cooked);
|
||||
|
||||
(*drv_accrue_offset)(offset);
|
||||
|
||||
/* Dispatch to all handlers */
|
||||
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
|
||||
(ptr->handler)(&raw, &cooked, 0.0, current_freq_ppm, offset, 0, ptr->anything);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LCL_ApplyStepOffset(double offset)
|
||||
{
|
||||
ChangeListEntry *ptr;
|
||||
struct timeval raw, cooked;
|
||||
double correction;
|
||||
|
||||
/* In this case, the cooked time to be passed to the notify clients
|
||||
has to be the cooked time BEFORE the change was made */
|
||||
|
||||
LCL_ReadRawTime(&raw);
|
||||
(drv_offset_convert)(&raw, &correction);
|
||||
UTI_AddDoubleToTimeval(&raw, correction, &cooked);
|
||||
|
||||
(*drv_apply_step_offset)(offset);
|
||||
|
||||
/* Dispatch to all handlers */
|
||||
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
|
||||
(ptr->handler)(&raw, &cooked, 0.0, current_freq_ppm, offset, 1, ptr->anything);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset)
|
||||
{
|
||||
ChangeListEntry *ptr;
|
||||
struct timeval raw, cooked;
|
||||
double correction;
|
||||
double old_freq_ppm;
|
||||
|
||||
LCL_ReadRawTime(&raw);
|
||||
(drv_offset_convert)(&raw, &correction);
|
||||
/* Due to modifying the offset, this has to be the cooked time prior
|
||||
to the change we are about to make */
|
||||
UTI_AddDoubleToTimeval(&raw, correction, &cooked);
|
||||
|
||||
old_freq_ppm = current_freq_ppm;
|
||||
|
||||
/* Work out new absolute frequency. Note that absolute frequencies
|
||||
are handled in units of ppm, whereas the 'dfreq' argument is in
|
||||
terms of the gradient of the (offset) v (local time) function. */
|
||||
current_freq_ppm = (1.0 - dfreq) * old_freq_ppm +
|
||||
(1.0e6 * dfreq);
|
||||
|
||||
#ifdef TRACEON
|
||||
LOG(LOGS_INFO, LOGF_Local, "old_freq=%.3fppm new_freq=%.3fppm offset=%.6fsec",
|
||||
old_freq_ppm, current_freq_ppm, doffset);
|
||||
#endif
|
||||
current_freq_ppm += dfreq * (1.0e6 - current_freq_ppm);
|
||||
|
||||
current_freq_ppm = clamp_freq(current_freq_ppm);
|
||||
|
||||
/* Call the system-specific driver for setting the frequency */
|
||||
(*drv_set_freq)(current_freq_ppm);
|
||||
(*drv_accrue_offset)(doffset);
|
||||
current_freq_ppm = (*drv_set_freq)(current_freq_ppm);
|
||||
dfreq = (current_freq_ppm - old_freq_ppm) / (1.0e6 - old_freq_ppm);
|
||||
|
||||
LCL_ReadRawTime(&raw);
|
||||
LCL_CookTime(&raw, &cooked, NULL);
|
||||
|
||||
/* Dispatch to all handlers */
|
||||
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
|
||||
(ptr->handler)(&raw, &cooked, dfreq, current_freq_ppm, doffset, 0, ptr->anything);
|
||||
invoke_parameter_change_handlers(&raw, &cooked, dfreq, 0.0, LCL_ChangeAdjust);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LCL_AccumulateOffset(double offset, double corr_rate)
|
||||
{
|
||||
struct timeval raw, cooked;
|
||||
|
||||
/* In this case, the cooked time to be passed to the notify clients
|
||||
has to be the cooked time BEFORE the change was made */
|
||||
|
||||
LCL_ReadRawTime(&raw);
|
||||
LCL_CookTime(&raw, &cooked, NULL);
|
||||
|
||||
if (!check_offset(&cooked, offset))
|
||||
return;
|
||||
|
||||
(*drv_accrue_offset)(offset, corr_rate);
|
||||
|
||||
/* Dispatch to all handlers */
|
||||
invoke_parameter_change_handlers(&raw, &cooked, 0.0, offset, LCL_ChangeAdjust);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
LCL_ApplyStepOffset(double offset)
|
||||
{
|
||||
struct timeval raw, cooked;
|
||||
|
||||
/* In this case, the cooked time to be passed to the notify clients
|
||||
has to be the cooked time BEFORE the change was made */
|
||||
|
||||
LCL_ReadRawTime(&raw);
|
||||
LCL_CookTime(&raw, &cooked, NULL);
|
||||
|
||||
if (!check_offset(&raw, offset))
|
||||
return 0;
|
||||
|
||||
if (!(*drv_apply_step_offset)(offset)) {
|
||||
LOG(LOGS_ERR, LOGF_Local, "Could not step clock");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Reset smoothing on all clock steps */
|
||||
SMT_Reset(&cooked);
|
||||
|
||||
/* Dispatch to all handlers */
|
||||
invoke_parameter_change_handlers(&raw, &cooked, 0.0, offset, LCL_ChangeStep);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LCL_NotifyExternalTimeStep(struct timeval *raw, struct timeval *cooked,
|
||||
double offset, double dispersion)
|
||||
{
|
||||
/* Dispatch to all handlers */
|
||||
invoke_parameter_change_handlers(raw, cooked, 0.0, offset, LCL_ChangeUnknownStep);
|
||||
|
||||
lcl_InvokeDispersionNotifyHandlers(dispersion);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LCL_NotifyLeap(int leap)
|
||||
{
|
||||
struct timeval raw, cooked;
|
||||
|
||||
LCL_ReadRawTime(&raw);
|
||||
LCL_CookTime(&raw, &cooked, NULL);
|
||||
|
||||
/* Smooth the leap second out */
|
||||
SMT_Leap(&cooked, leap);
|
||||
|
||||
/* Dispatch to all handlers as if the clock was stepped */
|
||||
invoke_parameter_change_handlers(&raw, &cooked, 0.0, -leap, LCL_ChangeStep);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset, double corr_rate)
|
||||
{
|
||||
struct timeval raw, cooked;
|
||||
double old_freq_ppm;
|
||||
|
||||
LCL_ReadRawTime(&raw);
|
||||
/* Due to modifying the offset, this has to be the cooked time prior
|
||||
to the change we are about to make */
|
||||
LCL_CookTime(&raw, &cooked, NULL);
|
||||
|
||||
if (!check_offset(&cooked, doffset))
|
||||
return;
|
||||
|
||||
old_freq_ppm = current_freq_ppm;
|
||||
|
||||
/* Work out new absolute frequency. Note that absolute frequencies
|
||||
are handled in units of ppm, whereas the 'dfreq' argument is in
|
||||
terms of the gradient of the (offset) v (local time) function. */
|
||||
current_freq_ppm += dfreq * (1.0e6 - current_freq_ppm);
|
||||
|
||||
current_freq_ppm = clamp_freq(current_freq_ppm);
|
||||
|
||||
DEBUG_LOG(LOGF_Local, "old_freq=%.3fppm new_freq=%.3fppm offset=%.6fsec",
|
||||
old_freq_ppm, current_freq_ppm, doffset);
|
||||
|
||||
/* Call the system-specific driver for setting the frequency */
|
||||
current_freq_ppm = (*drv_set_freq)(current_freq_ppm);
|
||||
dfreq = (current_freq_ppm - old_freq_ppm) / (1.0e6 - old_freq_ppm);
|
||||
|
||||
(*drv_accrue_offset)(doffset, corr_rate);
|
||||
|
||||
/* Dispatch to all handlers */
|
||||
invoke_parameter_change_handlers(&raw, &cooked, dfreq, doffset, LCL_ChangeAdjust);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -536,24 +630,20 @@ lcl_RegisterSystemDrivers(lcl_ReadFrequencyDriver read_freq,
|
||||
lcl_AccrueOffsetDriver accrue_offset,
|
||||
lcl_ApplyStepOffsetDriver apply_step_offset,
|
||||
lcl_OffsetCorrectionDriver offset_convert,
|
||||
lcl_ImmediateStepDriver immediate_step,
|
||||
lcl_SetLeapDriver set_leap)
|
||||
lcl_SetLeapDriver set_leap,
|
||||
lcl_SetSyncStatusDriver set_sync_status)
|
||||
{
|
||||
drv_read_freq = read_freq;
|
||||
drv_set_freq = set_freq;
|
||||
drv_accrue_offset = accrue_offset;
|
||||
drv_apply_step_offset = apply_step_offset;
|
||||
drv_offset_convert = offset_convert;
|
||||
drv_immediate_step = immediate_step;
|
||||
drv_set_leap = set_leap;
|
||||
drv_set_sync_status = set_sync_status;
|
||||
|
||||
current_freq_ppm = (*drv_read_freq)();
|
||||
|
||||
#ifdef TRACEON
|
||||
LOG(LOGS_INFO, LOGF_Local, "Local freq=%.3fppm", current_freq_ppm);
|
||||
#endif
|
||||
|
||||
return;
|
||||
DEBUG_LOG(LOGF_Local, "Local freq=%.3fppm", current_freq_ppm);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -563,27 +653,79 @@ lcl_RegisterSystemDrivers(lcl_ReadFrequencyDriver read_freq,
|
||||
int
|
||||
LCL_MakeStep(void)
|
||||
{
|
||||
if (drv_immediate_step) {
|
||||
(drv_immediate_step)();
|
||||
#ifdef TRACEON
|
||||
LOG(LOGS_INFO, LOGF_Local, "Made step to system time to apply remaining slew");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
struct timeval raw;
|
||||
double correction;
|
||||
|
||||
return 0;
|
||||
LCL_ReadRawTime(&raw);
|
||||
LCL_GetOffsetCorrection(&raw, &correction, NULL);
|
||||
|
||||
if (!check_offset(&raw, -correction))
|
||||
return 0;
|
||||
|
||||
/* Cancel remaining slew and make the step */
|
||||
LCL_AccumulateOffset(correction, 0.0);
|
||||
if (!LCL_ApplyStepOffset(-correction))
|
||||
return 0;
|
||||
|
||||
LOG(LOGS_WARN, LOGF_Local, "System clock was stepped by %.6f seconds", correction);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
LCL_CanSystemLeap(void)
|
||||
{
|
||||
return drv_set_leap ? 1 : 0;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LCL_SetLeap(int leap)
|
||||
LCL_SetSystemLeap(int leap)
|
||||
{
|
||||
if (drv_set_leap) {
|
||||
(drv_set_leap)(leap);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
double
|
||||
LCL_SetTempComp(double comp)
|
||||
{
|
||||
double uncomp_freq_ppm;
|
||||
|
||||
if (temp_comp_ppm == comp)
|
||||
return comp;
|
||||
|
||||
/* Undo previous compensation */
|
||||
current_freq_ppm = (current_freq_ppm + temp_comp_ppm) /
|
||||
(1.0 - 1.0e-6 * temp_comp_ppm);
|
||||
|
||||
uncomp_freq_ppm = current_freq_ppm;
|
||||
|
||||
/* Apply new compensation */
|
||||
current_freq_ppm = current_freq_ppm * (1.0 - 1.0e-6 * comp) - comp;
|
||||
|
||||
/* Call the system-specific driver for setting the frequency */
|
||||
current_freq_ppm = (*drv_set_freq)(current_freq_ppm);
|
||||
|
||||
temp_comp_ppm = (uncomp_freq_ppm - current_freq_ppm) /
|
||||
(1.0e-6 * uncomp_freq_ppm + 1.0);
|
||||
|
||||
return temp_comp_ppm;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LCL_SetSyncStatus(int synchronised, double est_error, double max_error)
|
||||
{
|
||||
if (drv_set_sync_status) {
|
||||
(drv_set_sync_status)(synchronised, est_error, max_error);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
80
local.h
80
local.h
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/local.h,v 1.16 2002/02/28 23:27:10 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
@@ -50,11 +46,13 @@ extern void LCL_ReadRawTime(struct timeval *);
|
||||
|
||||
extern void LCL_ReadCookedTime(struct timeval *t, double *err);
|
||||
|
||||
/* Read the current offset between the system clock and true time
|
||||
(i.e. 'cooked' - 'raw') (in seconds). Only intended for use in
|
||||
status reporting, really. */
|
||||
/* Convert raw time to cooked. */
|
||||
extern void LCL_CookTime(struct timeval *raw, struct timeval *cooked, double *err);
|
||||
|
||||
extern double LCL_GetOffsetCorrection(struct timeval *raw);
|
||||
/* Read the current offset between the system clock and true time
|
||||
(i.e. 'cooked' - 'raw') (in seconds). */
|
||||
|
||||
extern void LCL_GetOffsetCorrection(struct timeval *raw, double *correction, double *err);
|
||||
|
||||
/* Type of routines that may be invoked as callbacks when there is a
|
||||
change to the frequency or offset.
|
||||
@@ -66,23 +64,25 @@ extern double LCL_GetOffsetCorrection(struct timeval *raw);
|
||||
dfreq : delta frequency relative to previous value (in terms of
|
||||
seconds gained by system clock per unit system clock time)
|
||||
|
||||
afreq : absolute frequency relative to uncompensated system (in
|
||||
terms of ppm seconds gained by system clock per unit of the
|
||||
uncalibrated system clock)
|
||||
|
||||
doffset : delta offset applied (positive => make local system fast
|
||||
by that amount, negative => make it slow by that amount)
|
||||
|
||||
is_step_change : true if change is being applied as a jump (using
|
||||
settimeofday rather than adjtime)
|
||||
change_type : what type of change is being applied
|
||||
|
||||
anything : Passthrough argument from call to registration routine */
|
||||
|
||||
|
||||
typedef enum {
|
||||
LCL_ChangeAdjust,
|
||||
LCL_ChangeStep,
|
||||
LCL_ChangeUnknownStep
|
||||
} LCL_ChangeType;
|
||||
|
||||
typedef void (*LCL_ParameterChangeHandler)
|
||||
(struct timeval *raw, struct timeval *cooked,
|
||||
double dfreq, double afreq_ppm,
|
||||
double doffset, int is_step_change,
|
||||
double dfreq,
|
||||
double doffset,
|
||||
LCL_ChangeType change_type,
|
||||
void *anything
|
||||
);
|
||||
|
||||
@@ -92,6 +92,9 @@ extern void LCL_AddParameterChangeHandler(LCL_ParameterChangeHandler handler, vo
|
||||
/* Remove a handler */
|
||||
extern void LCL_RemoveParameterChangeHandler(LCL_ParameterChangeHandler, void *anything);
|
||||
|
||||
/* Check if a handler is invoked first when dispatching */
|
||||
extern int LCL_IsFirstParameterChangeHandler(LCL_ParameterChangeHandler handler);
|
||||
|
||||
/* Function type for handlers to be called back when an indeterminate
|
||||
offset is introduced into the local time. This situation occurs
|
||||
when the frequency must be adjusted to effect a clock slew and
|
||||
@@ -144,9 +147,10 @@ extern void LCL_AccumulateDeltaFrequency(double dfreq);
|
||||
/* Routine to apply an offset (in seconds) to the local clock. The
|
||||
argument should be positive to move the clock backwards (i.e. the
|
||||
local clock is currently fast of true time), or negative to move it
|
||||
forwards (i.e. it is currently slow of true time). */
|
||||
forwards (i.e. it is currently slow of true time). Provided is also
|
||||
a suggested correction rate (correction time * offset). */
|
||||
|
||||
extern void LCL_AccumulateOffset(double offset);
|
||||
extern void LCL_AccumulateOffset(double offset, double corr_rate);
|
||||
|
||||
/* Routine to apply an immediate offset by doing a sudden step if
|
||||
possible. (Intended for use after an initial estimate of offset has
|
||||
@@ -155,11 +159,20 @@ extern void LCL_AccumulateOffset(double offset);
|
||||
the system clock is fast on true time, i.e. it needs to be stepped
|
||||
backwards. (Same convention as for AccumulateOffset routine). */
|
||||
|
||||
extern void LCL_ApplyStepOffset(double offset);
|
||||
extern int LCL_ApplyStepOffset(double offset);
|
||||
|
||||
/* Routine to invoke notify handlers on an unexpected time jump
|
||||
in system clock */
|
||||
extern void LCL_NotifyExternalTimeStep(struct timeval *raw, struct timeval *cooked,
|
||||
double offset, double dispersion);
|
||||
|
||||
/* Routine to invoke notify handlers on leap second when the system clock
|
||||
doesn't correct itself */
|
||||
extern void LCL_NotifyLeap(int leap);
|
||||
|
||||
/* Perform the combination of modifying the frequency and applying
|
||||
a slew, in one easy step */
|
||||
extern void LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset);
|
||||
extern void LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset, double corr_rate);
|
||||
|
||||
/* Routine to read the system precision as a log to base 2 value. */
|
||||
extern int LCL_GetSysPrecisionAsLog(void);
|
||||
@@ -167,6 +180,10 @@ extern int LCL_GetSysPrecisionAsLog(void);
|
||||
/* Routine to read the system precision in terms of the actual time step */
|
||||
extern double LCL_GetSysPrecisionAsQuantum(void);
|
||||
|
||||
/* Routine to read the maximum frequency error of the local clock. This
|
||||
is a frequency stability, not an absolute error. */
|
||||
extern double LCL_GetMaxClockError(void);
|
||||
|
||||
/* Routine to initialise the module (to be called once at program
|
||||
start-up) */
|
||||
|
||||
@@ -181,9 +198,24 @@ extern void LCL_Finalise(void);
|
||||
to a timezone problem. */
|
||||
extern int LCL_MakeStep(void);
|
||||
|
||||
/* Routine to schedule a leap second. Leap second will be inserted
|
||||
at the end of the day if argument is positive, deleted if negative,
|
||||
and zero cancels scheduled leap second. */
|
||||
extern void LCL_SetLeap(int leap);
|
||||
/* Check if the system driver supports leap seconds, i.e. LCL_SetSystemLeap
|
||||
does something */
|
||||
extern int LCL_CanSystemLeap(void);
|
||||
|
||||
/* Routine to set the system clock to correct itself for a leap second if
|
||||
supported. Leap second will be inserted at the end of the day if the
|
||||
argument is positive, deleted if negative, and zero resets the setting. */
|
||||
extern void LCL_SetSystemLeap(int leap);
|
||||
|
||||
/* Routine to set a frequency correction (in ppm) that should be applied
|
||||
to local clock to compensate for temperature changes. A positive
|
||||
argument means that the clock frequency should be increased. Return the
|
||||
actual compensation (may be different from the requested compensation
|
||||
due to clamping or rounding). */
|
||||
extern double LCL_SetTempComp(double comp);
|
||||
|
||||
/* Routine to update the synchronisation status in the kernel to allow other
|
||||
applications to know if the system clock is synchronised and error bounds */
|
||||
extern void LCL_SetSyncStatus(int synchronised, double est_error, double max_error);
|
||||
|
||||
#endif /* GOT_LOCAL_H */
|
||||
|
||||
29
localp.h
29
localp.h
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/localp.h,v 1.9 2002/02/28 23:27:10 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
@@ -40,29 +36,30 @@ typedef double (*lcl_ReadFrequencyDriver)(void);
|
||||
|
||||
/* System driver to set the current local frequency, in ppm relative
|
||||
to nominal. A positive value indicates that the local clock runs
|
||||
fast when uncompensated. */
|
||||
typedef void (*lcl_SetFrequencyDriver)(double freq_ppm);
|
||||
fast when uncompensated. Return actual frequency (may be different
|
||||
from the requested frequency due to clamping or rounding). */
|
||||
typedef double (*lcl_SetFrequencyDriver)(double freq_ppm);
|
||||
|
||||
/* System driver to accrue an offset. A positive argument means slew
|
||||
the clock forwards. */
|
||||
typedef void (*lcl_AccrueOffsetDriver)(double offset);
|
||||
the clock forwards. The suggested correction rate of time to correct the
|
||||
offset is given in 'corr_rate'. */
|
||||
typedef void (*lcl_AccrueOffsetDriver)(double offset, double corr_rate);
|
||||
|
||||
/* System driver to apply a step offset. A positive argument means step
|
||||
the clock forwards. */
|
||||
typedef void (*lcl_ApplyStepOffsetDriver)(double offset);
|
||||
typedef int (*lcl_ApplyStepOffsetDriver)(double offset);
|
||||
|
||||
/* System driver to convert a raw time to an adjusted (cooked) time.
|
||||
The number of seconds returned in 'corr' have to be added to the
|
||||
raw time to get the corrected time */
|
||||
typedef void (*lcl_OffsetCorrectionDriver)(struct timeval *raw, double *corr);
|
||||
|
||||
/* System driver to stop slewing the current offset and to apply is
|
||||
as an immediate step instead */
|
||||
typedef void (*lcl_ImmediateStepDriver)(void);
|
||||
typedef void (*lcl_OffsetCorrectionDriver)(struct timeval *raw, double *corr, double *err);
|
||||
|
||||
/* System driver to schedule leap second */
|
||||
typedef void (*lcl_SetLeapDriver)(int leap);
|
||||
|
||||
/* System driver to set the synchronisation status */
|
||||
typedef void (*lcl_SetSyncStatusDriver)(int synchronised, double est_error, double max_error);
|
||||
|
||||
extern void lcl_InvokeDispersionNotifyHandlers(double dispersion);
|
||||
|
||||
extern void
|
||||
@@ -71,7 +68,7 @@ lcl_RegisterSystemDrivers(lcl_ReadFrequencyDriver read_freq,
|
||||
lcl_AccrueOffsetDriver accrue_offset,
|
||||
lcl_ApplyStepOffsetDriver apply_step_offset,
|
||||
lcl_OffsetCorrectionDriver offset_convert,
|
||||
lcl_ImmediateStepDriver immediate_step_driver,
|
||||
lcl_SetLeapDriver set_leap);
|
||||
lcl_SetLeapDriver set_leap,
|
||||
lcl_SetSyncStatusDriver set_sync_status);
|
||||
|
||||
#endif /* GOT_LOCALP_H */
|
||||
|
||||
330
logging.c
330
logging.c
@@ -1,12 +1,9 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/logging.c,v 1.15 2003/09/22 21:22:30 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2011-2014
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -28,21 +25,42 @@
|
||||
Module to handle logging of diagnostic information
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "conf.h"
|
||||
#include "logging.h"
|
||||
#include "version.h"
|
||||
#include "util.h"
|
||||
|
||||
/* This is used by DEBUG_LOG macro */
|
||||
int log_debug_enabled = 0;
|
||||
|
||||
/* ================================================== */
|
||||
/* Flag indicating we have initialised */
|
||||
static int initialised = 0;
|
||||
|
||||
static int is_detached = 0;
|
||||
static int system_log = 0;
|
||||
|
||||
#ifdef WINNT
|
||||
static FILE *logfile;
|
||||
#endif
|
||||
static int parent_fd = 0;
|
||||
|
||||
#define DEBUG_LEVEL_PRINT_FUNCTION 2
|
||||
#define DEBUG_LEVEL_PRINT_DEBUG 2
|
||||
static int debug_level = 0;
|
||||
|
||||
struct LogFile {
|
||||
const char *name;
|
||||
const char *banner;
|
||||
FILE *file;
|
||||
unsigned long writes;
|
||||
};
|
||||
|
||||
static int n_filelogs = 0;
|
||||
|
||||
/* Increase this when adding a new logfile */
|
||||
#define MAX_FILELOGS 6
|
||||
|
||||
static struct LogFile logfiles[MAX_FILELOGS];
|
||||
|
||||
/* ================================================== */
|
||||
/* Init function */
|
||||
@@ -51,12 +69,6 @@ void
|
||||
LOG_Initialise(void)
|
||||
{
|
||||
initialised = 1;
|
||||
|
||||
#ifdef WINNT
|
||||
logfile = fopen("./chronyd.err", "a");
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -65,168 +77,218 @@ LOG_Initialise(void)
|
||||
void
|
||||
LOG_Finalise(void)
|
||||
{
|
||||
#ifdef WINNT
|
||||
if (logfile) {
|
||||
fclose(logfile);
|
||||
}
|
||||
#else
|
||||
if (is_detached) {
|
||||
if (system_log) {
|
||||
closelog();
|
||||
}
|
||||
#endif
|
||||
|
||||
LOG_CycleLogFiles();
|
||||
|
||||
initialised = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LOG_Line_Function(LOG_Severity severity, LOG_Facility facility, const char *format, ...)
|
||||
static void log_message(int fatal, LOG_Severity severity, const char *message)
|
||||
{
|
||||
char buf[2048];
|
||||
va_list other_args;
|
||||
va_start(other_args, format);
|
||||
vsnprintf(buf, sizeof(buf), format, other_args);
|
||||
va_end(other_args);
|
||||
#ifdef WINNT
|
||||
if (logfile) {
|
||||
fprintf(logfile, "%s\n", buf);
|
||||
}
|
||||
#else
|
||||
if (is_detached) {
|
||||
if (system_log) {
|
||||
int priority;
|
||||
switch (severity) {
|
||||
case LOGS_DEBUG:
|
||||
priority = LOG_DEBUG;
|
||||
break;
|
||||
case LOGS_INFO:
|
||||
syslog(LOG_INFO, "%s", buf);
|
||||
priority = LOG_INFO;
|
||||
break;
|
||||
case LOGS_WARN:
|
||||
syslog(LOG_WARNING, "%s", buf);
|
||||
priority = LOG_WARNING;
|
||||
break;
|
||||
case LOGS_ERR:
|
||||
default:
|
||||
syslog(LOG_ERR, "%s", buf);
|
||||
priority = LOG_ERR;
|
||||
break;
|
||||
case LOGS_FATAL:
|
||||
priority = LOG_CRIT;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
syslog(priority, fatal ? "Fatal error : %s" : "%s", message);
|
||||
} else {
|
||||
fprintf(stderr, "%s\n", buf);
|
||||
fprintf(stderr, fatal ? "Fatal error : %s\n" : "%s\n", message);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LOG_Fatal_Function(LOG_Facility facility, const char *format, ...)
|
||||
void LOG_Message(LOG_Severity severity,
|
||||
#if DEBUG > 0
|
||||
LOG_Facility facility, int line_number,
|
||||
const char *filename, const char *function_name,
|
||||
#endif
|
||||
const char *format, ...)
|
||||
{
|
||||
char buf[2048];
|
||||
va_list other_args;
|
||||
time_t t;
|
||||
struct tm stm;
|
||||
|
||||
if (!system_log) {
|
||||
/* Don't clutter up syslog with timestamps and internal debugging info */
|
||||
time(&t);
|
||||
stm = *gmtime(&t);
|
||||
strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", &stm);
|
||||
fprintf(stderr, "%s ", buf);
|
||||
#if DEBUG > 0
|
||||
if (debug_level >= DEBUG_LEVEL_PRINT_FUNCTION)
|
||||
fprintf(stderr, "%s:%d:(%s) ", filename, line_number, function_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
va_start(other_args, format);
|
||||
vsnprintf(buf, sizeof(buf), format, other_args);
|
||||
va_end(other_args);
|
||||
|
||||
#ifdef WINNT
|
||||
if (logfile) {
|
||||
fprintf(logfile, "Fatal error : %s\n", buf);
|
||||
}
|
||||
#else
|
||||
if (is_detached) {
|
||||
syslog(LOG_CRIT, "Fatal error : %s", buf);
|
||||
} else {
|
||||
fprintf(stderr, "Fatal error : %s\n", buf);
|
||||
}
|
||||
#endif
|
||||
switch (severity) {
|
||||
case LOGS_DEBUG:
|
||||
case LOGS_INFO:
|
||||
case LOGS_WARN:
|
||||
case LOGS_ERR:
|
||||
log_message(0, severity, buf);
|
||||
break;
|
||||
case LOGS_FATAL:
|
||||
log_message(1, severity, buf);
|
||||
|
||||
MAI_CleanupAndExit();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LOG_Position(const char *filename, int line_number, const char *function_name)
|
||||
{
|
||||
#ifdef WINNT
|
||||
#else
|
||||
time_t t;
|
||||
struct tm stm;
|
||||
char buf[64];
|
||||
if (!is_detached) {
|
||||
/* Don't clutter up syslog with internal debugging info */
|
||||
time(&t);
|
||||
stm = *gmtime(&t);
|
||||
strftime(buf, sizeof(buf), "%d-%H:%M:%S", &stm);
|
||||
fprintf(stderr, "%s:%d:(%s)[%s] ", filename, line_number, function_name, buf);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LOG_GoDaemon(void)
|
||||
{
|
||||
#ifdef WINNT
|
||||
|
||||
|
||||
#else
|
||||
|
||||
int pid, fd;
|
||||
|
||||
/* Does this preserve existing signal handlers? */
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0) {
|
||||
LOG(LOGS_ERR, LOGF_Logging, "Could not detach, fork failed : %s", strerror(errno));
|
||||
} else if (pid > 0) {
|
||||
exit(0); /* In the 'grandparent' */
|
||||
} else {
|
||||
|
||||
setsid();
|
||||
|
||||
/* Do 2nd fork, as-per recommended practice for launching daemons. */
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0) {
|
||||
LOG(LOGS_ERR, LOGF_Logging, "Could not detach, fork failed : %s", strerror(errno));
|
||||
} else if (pid > 0) {
|
||||
exit(0); /* In the 'parent' */
|
||||
} else {
|
||||
/* In the child we want to leave running as the daemon */
|
||||
|
||||
/* Don't keep stdin/out/err from before. */
|
||||
for (fd=0; fd<1024; fd++) {
|
||||
close(fd);
|
||||
/* With syslog, send the message also to the grandparent
|
||||
process or write it to stderr if not detached */
|
||||
if (system_log) {
|
||||
if (parent_fd > 0) {
|
||||
if (write(parent_fd, buf, strlen(buf) + 1) < 0)
|
||||
; /* Not much we can do here */
|
||||
} else if (parent_fd == 0) {
|
||||
system_log = 0;
|
||||
log_message(1, severity, buf);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
is_detached = 1;
|
||||
/* ================================================== */
|
||||
|
||||
openlog("chronyd", LOG_PID, LOG_DAEMON);
|
||||
void
|
||||
LOG_OpenSystemLog(void)
|
||||
{
|
||||
system_log = 1;
|
||||
openlog("chronyd", LOG_PID, LOG_DAEMON);
|
||||
}
|
||||
|
||||
LOG(LOGS_INFO, LOGF_Logging, "chronyd version %s starting", PROGRAM_VERSION_STRING);
|
||||
/* ================================================== */
|
||||
|
||||
void LOG_SetDebugLevel(int level)
|
||||
{
|
||||
debug_level = level;
|
||||
if (level >= DEBUG_LEVEL_PRINT_DEBUG) {
|
||||
log_debug_enabled = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LOG_SetParentFd(int fd)
|
||||
{
|
||||
parent_fd = fd;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LOG_CloseParentFd()
|
||||
{
|
||||
if (parent_fd > 0)
|
||||
close(parent_fd);
|
||||
parent_fd = -1;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
LOG_FileID
|
||||
LOG_FileOpen(const char *name, const char *banner)
|
||||
{
|
||||
assert(n_filelogs < MAX_FILELOGS);
|
||||
|
||||
logfiles[n_filelogs].name = name;
|
||||
logfiles[n_filelogs].banner = banner;
|
||||
logfiles[n_filelogs].file = NULL;
|
||||
logfiles[n_filelogs].writes = 0;
|
||||
|
||||
return n_filelogs++;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LOG_FileWrite(LOG_FileID id, const char *format, ...)
|
||||
{
|
||||
va_list other_args;
|
||||
int banner;
|
||||
|
||||
if (id < 0 || id >= n_filelogs || !logfiles[id].name)
|
||||
return;
|
||||
|
||||
if (!logfiles[id].file) {
|
||||
char filename[512];
|
||||
|
||||
if (snprintf(filename, sizeof(filename), "%s/%s.log",
|
||||
CNF_GetLogDir(), logfiles[id].name) >= sizeof(filename) ||
|
||||
!(logfiles[id].file = fopen(filename, "a"))) {
|
||||
LOG(LOGS_WARN, LOGF_Refclock, "Couldn't open logfile %s for update", filename);
|
||||
logfiles[id].name = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Close on exec */
|
||||
UTI_FdSetCloexec(fileno(logfiles[id].file));
|
||||
}
|
||||
|
||||
#endif
|
||||
banner = CNF_GetLogBanner();
|
||||
if (banner && logfiles[id].writes++ % banner == 0) {
|
||||
char bannerline[256];
|
||||
int i, bannerlen;
|
||||
|
||||
bannerlen = strlen(logfiles[id].banner);
|
||||
|
||||
for (i = 0; i < bannerlen; i++)
|
||||
bannerline[i] = '=';
|
||||
bannerline[i] = '\0';
|
||||
|
||||
fprintf(logfiles[id].file, "%s\n", bannerline);
|
||||
fprintf(logfiles[id].file, "%s\n", logfiles[id].banner);
|
||||
fprintf(logfiles[id].file, "%s\n", bannerline);
|
||||
}
|
||||
|
||||
va_start(other_args, format);
|
||||
vfprintf(logfiles[id].file, format, other_args);
|
||||
va_end(other_args);
|
||||
fprintf(logfiles[id].file, "\n");
|
||||
|
||||
fflush(logfiles[id].file);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
/* Force a core dump and exit without doing abort() or assert(0).
|
||||
These do funny things with the call stack in the core file that is
|
||||
generated, which makes diagnosis difficult. */
|
||||
|
||||
int
|
||||
croak(const char *file, int line, const char *msg)
|
||||
void
|
||||
LOG_CycleLogFiles(void)
|
||||
{
|
||||
int a;
|
||||
LOG(LOGS_ERR, LOGF_Util, "Unexpected condition [%s] at %s:%d, core dumped",
|
||||
msg, file, line);
|
||||
a = * (int *) 0;
|
||||
return a; /* Can't happen - this stops the optimiser optimising the
|
||||
line above */
|
||||
LOG_FileID i;
|
||||
|
||||
for (i = 0; i < n_filelogs; i++) {
|
||||
if (logfiles[i].file)
|
||||
fclose(logfiles[i].file);
|
||||
logfiles[i].file = NULL;
|
||||
logfiles[i].writes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
119
logging.h
119
logging.h
@@ -1,12 +1,9 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/logging.h,v 1.15 2002/02/28 23:27:10 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2002
|
||||
* Copyright (C) Miroslav Lichvar 2013-2015
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -32,11 +29,51 @@
|
||||
#ifndef GOT_LOGGING_H
|
||||
#define GOT_LOGGING_H
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
/* Flag indicating whether debug messages are logged */
|
||||
extern int log_debug_enabled;
|
||||
|
||||
/* Line logging macros. If the compiler is GNU C, we take advantage of
|
||||
being able to get the function name also. */
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define FUNCTION_NAME __FUNCTION__
|
||||
#define FORMAT_ATTRIBUTE_PRINTF(str, first) __attribute__ ((format (printf, str, first)))
|
||||
#else
|
||||
#define FUNCTION_NAME ""
|
||||
#define FORMAT_ATTRIBUTE_PRINTF(str, first)
|
||||
#endif
|
||||
|
||||
#if DEBUG > 0
|
||||
#define LOG_MESSAGE(severity, facility, ...) \
|
||||
LOG_Message(severity, facility, __LINE__, __FILE__, FUNCTION_NAME, __VA_ARGS__);
|
||||
#else
|
||||
#define LOG_MESSAGE(severity, facility, ...) \
|
||||
LOG_Message(severity, __VA_ARGS__);
|
||||
#endif
|
||||
|
||||
#define DEBUG_LOG(facility, ...) \
|
||||
do { \
|
||||
if (DEBUG && log_debug_enabled) \
|
||||
LOG_MESSAGE(LOGS_DEBUG, facility, __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define LOG_FATAL(facility, ...) \
|
||||
do { \
|
||||
LOG_MESSAGE(LOGS_FATAL, facility, __VA_ARGS__); \
|
||||
exit(1); \
|
||||
} while (0)
|
||||
|
||||
#define LOG(severity, facility, ...) LOG_MESSAGE(severity, facility, __VA_ARGS__)
|
||||
|
||||
/* Definition of severity */
|
||||
typedef enum {
|
||||
LOGS_INFO,
|
||||
LOGS_WARN,
|
||||
LOGS_ERR
|
||||
LOGS_ERR,
|
||||
LOGS_FATAL,
|
||||
LOGS_DEBUG
|
||||
} LOG_Severity;
|
||||
|
||||
/* Definition of facility. Each message is tagged with who generated
|
||||
@@ -53,21 +90,31 @@ typedef enum {
|
||||
LOGF_Local,
|
||||
LOGF_Util,
|
||||
LOGF_Main,
|
||||
LOGF_Memory,
|
||||
LOGF_Client,
|
||||
LOGF_ClientLog,
|
||||
LOGF_Configure,
|
||||
LOGF_CmdMon,
|
||||
LOGF_Acquire,
|
||||
LOGF_Manual,
|
||||
LOGF_Keys,
|
||||
LOGF_Logging,
|
||||
LOGF_Nameserv,
|
||||
LOGF_Rtc,
|
||||
LOGF_Regress,
|
||||
LOGF_Sys,
|
||||
LOGF_SysGeneric,
|
||||
LOGF_SysLinux,
|
||||
LOGF_SysMacOSX,
|
||||
LOGF_SysNetBSD,
|
||||
LOGF_SysSolaris,
|
||||
LOGF_SysSunOS,
|
||||
LOGF_SysTimex,
|
||||
LOGF_SysWinnt,
|
||||
LOGF_TempComp,
|
||||
LOGF_RtcLinux,
|
||||
LOGF_Refclock
|
||||
LOGF_Refclock,
|
||||
LOGF_Smooth,
|
||||
} LOG_Facility;
|
||||
|
||||
/* Init function */
|
||||
@@ -77,33 +124,41 @@ extern void LOG_Initialise(void);
|
||||
extern void LOG_Finalise(void);
|
||||
|
||||
/* Line logging function */
|
||||
extern void LOG_Line_Function(LOG_Severity severity, LOG_Facility facility, const char *format, ...);
|
||||
|
||||
/* Logging function for fatal errors */
|
||||
extern void LOG_Fatal_Function(LOG_Facility facility, const char *format, ...);
|
||||
|
||||
/* Position in code reporting function */
|
||||
extern void LOG_Position(const char *filename, int line_number, const char *function_name);
|
||||
|
||||
extern void LOG_GoDaemon(void);
|
||||
|
||||
/* Line logging macro. If the compiler is GNU C, we take advantage of
|
||||
being able to get the function name also. */
|
||||
#if defined(__GNUC__)
|
||||
#define LOG LOG_Position(__FILE__, __LINE__, __FUNCTION__); LOG_Line_Function
|
||||
#define LOG_FATAL LOG_Position(__FILE__, __LINE__, __FUNCTION__); LOG_Fatal_Function
|
||||
#if DEBUG > 0
|
||||
FORMAT_ATTRIBUTE_PRINTF(6, 7)
|
||||
extern void LOG_Message(LOG_Severity severity, LOG_Facility facility,
|
||||
int line_number, const char *filename,
|
||||
const char *function_name, const char *format, ...);
|
||||
#else
|
||||
#define LOG LOG_Position(__FILE__, __LINE__, ""); LOG_Line_Function
|
||||
#define LOG_FATAL LOG_Position(__FILE__, __LINE__, ""); LOG_Fatal_Function
|
||||
#endif /* defined (__GNUC__) */
|
||||
|
||||
/* Like assert(0) */
|
||||
|
||||
#if defined(LINUX) && defined(__alpha__)
|
||||
#define CROAK(message) assert(0) /* Added JGH Feb 24 2001 FIXME */
|
||||
#else
|
||||
extern int croak(const char *file, int line, const char *msg);
|
||||
#define CROAK(message) croak(__FILE__, __LINE__, message);
|
||||
FORMAT_ATTRIBUTE_PRINTF(2, 3)
|
||||
extern void LOG_Message(LOG_Severity severity, const char *format, ...);
|
||||
#endif
|
||||
|
||||
/* Set debug level:
|
||||
0, 1 - only non-debug messages are logged
|
||||
2 - debug messages are logged too, all messages are prefixed with
|
||||
filename, line, and function name
|
||||
*/
|
||||
extern void LOG_SetDebugLevel(int level);
|
||||
|
||||
/* Log messages to syslog instead of stderr */
|
||||
extern void LOG_OpenSystemLog(void);
|
||||
|
||||
/* Send fatal message also to the foreground process */
|
||||
extern void LOG_SetParentFd(int fd);
|
||||
|
||||
/* Close the pipe to the foreground process so it can exit */
|
||||
extern void LOG_CloseParentFd(void);
|
||||
|
||||
/* File logging functions */
|
||||
|
||||
typedef int LOG_FileID;
|
||||
|
||||
extern LOG_FileID LOG_FileOpen(const char *name, const char *banner);
|
||||
|
||||
FORMAT_ATTRIBUTE_PRINTF(2, 3)
|
||||
extern void LOG_FileWrite(LOG_FileID id, const char *format, ...);
|
||||
|
||||
extern void LOG_CycleLogFiles(void);
|
||||
|
||||
#endif /* GOT_LOGGING_H */
|
||||
|
||||
327
main.c
327
main.c
@@ -1,13 +1,10 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/main.c,v 1.31 2003/09/22 21:22:30 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) John G. Hasler 2009
|
||||
* Copyright (C) Miroslav Lichvar 2012-2015
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -29,6 +26,8 @@
|
||||
The main program
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "main.h"
|
||||
@@ -45,14 +44,14 @@
|
||||
#include "conf.h"
|
||||
#include "cmdmon.h"
|
||||
#include "keys.h"
|
||||
#include "acquire.h"
|
||||
#include "manual.h"
|
||||
#include "version.h"
|
||||
#include "rtc.h"
|
||||
#include "refclock.h"
|
||||
#include "clientlog.h"
|
||||
#include "broadcast.h"
|
||||
#include "nameserv.h"
|
||||
#include "smooth.h"
|
||||
#include "tempcomp.h"
|
||||
#include "util.h"
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
@@ -61,10 +60,12 @@
|
||||
|
||||
static int initialised = 0;
|
||||
|
||||
/* ================================================== */
|
||||
static int exit_status = 0;
|
||||
|
||||
static int reload = 0;
|
||||
|
||||
static REF_Mode ref_mode = REF_ModeNormal;
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
@@ -80,35 +81,41 @@ delete_pidfile(void)
|
||||
void
|
||||
MAI_CleanupAndExit(void)
|
||||
{
|
||||
if (!initialised) exit(0);
|
||||
if (!initialised) exit(exit_status);
|
||||
|
||||
if (CNF_GetDumpOnExit()) {
|
||||
SRC_DumpSources();
|
||||
}
|
||||
|
||||
/* Don't update clock when removing sources */
|
||||
REF_SetMode(REF_ModeIgnore);
|
||||
|
||||
SMT_Finalise();
|
||||
TMC_Finalise();
|
||||
MNL_Finalise();
|
||||
ACQ_Finalise();
|
||||
KEY_Finalise();
|
||||
CLG_Finalise();
|
||||
NSR_Finalise();
|
||||
NCR_Finalise();
|
||||
BRD_Finalise();
|
||||
SRC_Finalise();
|
||||
SST_Finalise();
|
||||
REF_Finalise();
|
||||
RCL_Finalise();
|
||||
RTC_Finalise();
|
||||
CAM_Finalise();
|
||||
NCR_Finalise();
|
||||
NIO_Finalise();
|
||||
CAM_Finalise();
|
||||
KEY_Finalise();
|
||||
RCL_Finalise();
|
||||
SRC_Finalise();
|
||||
REF_Finalise();
|
||||
RTC_Finalise();
|
||||
SYS_Finalise();
|
||||
SCH_Finalise();
|
||||
LCL_Finalise();
|
||||
|
||||
delete_pidfile();
|
||||
|
||||
CNF_Finalise();
|
||||
LOG_Finalise();
|
||||
|
||||
exit(0);
|
||||
HSH_Finalise();
|
||||
|
||||
exit(exit_status);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -116,7 +123,6 @@ MAI_CleanupAndExit(void)
|
||||
static void
|
||||
signal_cleanup(int x)
|
||||
{
|
||||
LOG(LOGS_WARN, LOGF_Main, "chronyd exiting on signal");
|
||||
if (!initialised) exit(0);
|
||||
SCH_QuitProgram();
|
||||
}
|
||||
@@ -124,11 +130,10 @@ signal_cleanup(int x)
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
post_acquire_hook(void *anything)
|
||||
ntp_source_resolving_end(void)
|
||||
{
|
||||
NSR_SetSourceResolvingEndHandler(NULL);
|
||||
|
||||
CNF_AddSources();
|
||||
CNF_AddBroadcasts();
|
||||
if (reload) {
|
||||
/* Note, we want reload to come well after the initialisation from
|
||||
the real time clock - this gives us a fighting chance that the
|
||||
@@ -136,10 +141,62 @@ post_acquire_hook(void *anything)
|
||||
semblence of validity about it. */
|
||||
SRC_ReloadSources();
|
||||
}
|
||||
CNF_SetupAccessRestrictions();
|
||||
|
||||
RTC_StartMeasurements();
|
||||
RCL_StartRefclocks();
|
||||
NSR_StartSources();
|
||||
NSR_AutoStartSources();
|
||||
|
||||
/* Special modes can end only when sources update their reachability.
|
||||
Give up immediatelly if there are no active sources. */
|
||||
if (ref_mode != REF_ModeNormal && !SRC_ActiveSources()) {
|
||||
REF_SetUnsynchronised();
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
post_init_ntp_hook(void *anything)
|
||||
{
|
||||
if (ref_mode == REF_ModeInitStepSlew) {
|
||||
/* Remove the initstepslew sources and set normal mode */
|
||||
NSR_RemoveAllSources();
|
||||
ref_mode = REF_ModeNormal;
|
||||
REF_SetMode(ref_mode);
|
||||
}
|
||||
|
||||
/* Close the pipe to the foreground process so it can exit */
|
||||
LOG_CloseParentFd();
|
||||
|
||||
CNF_AddSources();
|
||||
CNF_AddBroadcasts();
|
||||
|
||||
NSR_SetSourceResolvingEndHandler(ntp_source_resolving_end);
|
||||
NSR_ResolveSources();
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
reference_mode_end(int result)
|
||||
{
|
||||
switch (ref_mode) {
|
||||
case REF_ModeNormal:
|
||||
case REF_ModeUpdateOnce:
|
||||
case REF_ModePrintOnce:
|
||||
exit_status = !result;
|
||||
SCH_QuitProgram();
|
||||
break;
|
||||
case REF_ModeInitStepSlew:
|
||||
/* Switch to the normal mode, the delay is used to prevent polling
|
||||
interval shorter than the burst interval if some configured servers
|
||||
were used also for initstepslew */
|
||||
SCH_AddTimeoutByDelay(2.0, post_init_ntp_hook, NULL);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -147,7 +204,14 @@ post_acquire_hook(void *anything)
|
||||
static void
|
||||
post_init_rtc_hook(void *anything)
|
||||
{
|
||||
CNF_ProcessInitStepSlew(post_acquire_hook, NULL);
|
||||
if (CNF_GetInitSources() > 0) {
|
||||
CNF_AddInitSources();
|
||||
NSR_StartSources();
|
||||
assert(REF_GetMode() != REF_ModeNormal);
|
||||
/* Wait for mode end notification */
|
||||
} else {
|
||||
(post_init_ntp_hook)(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -199,24 +263,93 @@ write_lockfile(void)
|
||||
|
||||
out = fopen(pidfile, "w");
|
||||
if (!out) {
|
||||
LOG(LOGS_ERR, LOGF_Main, "could not open lockfile %s for writing", pidfile);
|
||||
LOG_FATAL(LOGF_Main, "could not open lockfile %s for writing", pidfile);
|
||||
} else {
|
||||
fprintf(out, "%d\n", getpid());
|
||||
fprintf(out, "%d\n", (int)getpid());
|
||||
fclose(out);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
go_daemon(void)
|
||||
{
|
||||
int pid, fd, pipefd[2];
|
||||
|
||||
/* Create pipe which will the daemon use to notify the grandparent
|
||||
when it's initialised or send an error message */
|
||||
if (pipe(pipefd)) {
|
||||
LOG_FATAL(LOGF_Logging, "Could not detach, pipe failed : %s", strerror(errno));
|
||||
}
|
||||
|
||||
/* Does this preserve existing signal handlers? */
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0) {
|
||||
LOG_FATAL(LOGF_Logging, "Could not detach, fork failed : %s", strerror(errno));
|
||||
} else if (pid > 0) {
|
||||
/* In the 'grandparent' */
|
||||
char message[1024];
|
||||
int r;
|
||||
|
||||
close(pipefd[1]);
|
||||
r = read(pipefd[0], message, sizeof (message));
|
||||
if (r) {
|
||||
if (r > 0) {
|
||||
/* Print the error message from the child */
|
||||
fprintf(stderr, "%.1024s\n", message);
|
||||
}
|
||||
exit(1);
|
||||
} else
|
||||
exit(0);
|
||||
} else {
|
||||
close(pipefd[0]);
|
||||
|
||||
setsid();
|
||||
|
||||
/* Do 2nd fork, as-per recommended practice for launching daemons. */
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0) {
|
||||
LOG_FATAL(LOGF_Logging, "Could not detach, fork failed : %s", strerror(errno));
|
||||
} else if (pid > 0) {
|
||||
exit(0); /* In the 'parent' */
|
||||
} else {
|
||||
/* In the child we want to leave running as the daemon */
|
||||
|
||||
/* Change current directory to / */
|
||||
if (chdir("/") < 0) {
|
||||
LOG_FATAL(LOGF_Logging, "Could not chdir to / : %s", strerror(errno));
|
||||
}
|
||||
|
||||
/* Don't keep stdin/out/err from before. But don't close
|
||||
the parent pipe yet. */
|
||||
for (fd=0; fd<1024; fd++) {
|
||||
if (fd != pipefd[1])
|
||||
close(fd);
|
||||
}
|
||||
|
||||
LOG_SetParentFd(pipefd[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int main
|
||||
(int argc, char **argv)
|
||||
{
|
||||
char *conf_file = NULL;
|
||||
const char *conf_file = DEFAULT_CONF_FILE;
|
||||
const char *progname = argv[0];
|
||||
char *user = NULL;
|
||||
int debug = 0;
|
||||
int do_init_rtc = 0;
|
||||
struct passwd *pw;
|
||||
int debug = 0, nofork = 0, address_family = IPADDR_UNSPEC;
|
||||
int do_init_rtc = 0, restarted = 0;
|
||||
int other_pid;
|
||||
int lock_memory = 0, sched_priority = 0;
|
||||
int scfilter_level = 0, lock_memory = 0, sched_priority = 0;
|
||||
int system_log = 1;
|
||||
int config_args = 0;
|
||||
|
||||
LOG_Initialise();
|
||||
|
||||
@@ -235,6 +368,8 @@ int main
|
||||
lock_memory = 1;
|
||||
} else if (!strcmp("-r", *argv)) {
|
||||
reload = 1;
|
||||
} else if (!strcmp("-R", *argv)) {
|
||||
restarted = 1;
|
||||
} else if (!strcmp("-u", *argv)) {
|
||||
++argv, --argc;
|
||||
if (argc == 0) {
|
||||
@@ -242,63 +377,105 @@ int main
|
||||
} else {
|
||||
user = *argv;
|
||||
}
|
||||
} else if (!strcmp("-F", *argv)) {
|
||||
++argv, --argc;
|
||||
if (argc == 0 || sscanf(*argv, "%d", &scfilter_level) != 1)
|
||||
LOG_FATAL(LOGF_Main, "Bad syscall filter level");
|
||||
} else if (!strcmp("-s", *argv)) {
|
||||
do_init_rtc = 1;
|
||||
} else if (!strcmp("-v", *argv) || !strcmp("--version",*argv)) {
|
||||
/* This write to the terminal is OK, it comes before we turn into a daemon */
|
||||
printf("chronyd (chrony) version %s\n", PROGRAM_VERSION_STRING);
|
||||
exit(0);
|
||||
printf("chronyd (chrony) version %s (%s)\n", CHRONY_VERSION, CHRONYD_FEATURES);
|
||||
return 0;
|
||||
} else if (!strcmp("-n", *argv)) {
|
||||
nofork = 1;
|
||||
} else if (!strcmp("-d", *argv)) {
|
||||
debug = 1;
|
||||
debug++;
|
||||
nofork = 1;
|
||||
system_log = 0;
|
||||
} else if (!strcmp("-q", *argv)) {
|
||||
ref_mode = REF_ModeUpdateOnce;
|
||||
nofork = 1;
|
||||
system_log = 0;
|
||||
} else if (!strcmp("-Q", *argv)) {
|
||||
ref_mode = REF_ModePrintOnce;
|
||||
nofork = 1;
|
||||
system_log = 0;
|
||||
} else if (!strcmp("-4", *argv)) {
|
||||
DNS_SetAddressFamily(IPADDR_INET4);
|
||||
address_family = IPADDR_INET4;
|
||||
} else if (!strcmp("-6", *argv)) {
|
||||
DNS_SetAddressFamily(IPADDR_INET6);
|
||||
address_family = IPADDR_INET6;
|
||||
} else if (!strcmp("-h", *argv) || !strcmp("--help", *argv)) {
|
||||
printf("Usage: %s [-4|-6] [-n|-d] [-q|-Q] [-r] [-R] [-s] [-f FILE|COMMAND...]\n",
|
||||
progname);
|
||||
return 0;
|
||||
} else if (*argv[0] == '-') {
|
||||
LOG_FATAL(LOGF_Main, "Unrecognized command line option [%s]", *argv);
|
||||
} else {
|
||||
LOG(LOGS_WARN, LOGF_Main, "Unrecognized command line option [%s]", *argv);
|
||||
/* Process remaining arguments and configuration lines */
|
||||
config_args = argc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SYS_WINNT
|
||||
if (getuid() != 0) {
|
||||
/* This write to the terminal is OK, it comes before we turn into a daemon */
|
||||
fprintf(stderr,"Not superuser\n");
|
||||
exit(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Turn into a daemon */
|
||||
if (!debug) {
|
||||
LOG_GoDaemon();
|
||||
if (!nofork) {
|
||||
go_daemon();
|
||||
}
|
||||
|
||||
if (system_log) {
|
||||
LOG_OpenSystemLog();
|
||||
}
|
||||
|
||||
LOG_SetDebugLevel(debug);
|
||||
|
||||
LOG(LOGS_INFO, LOGF_Main, "chronyd version %s starting (%s)",
|
||||
CHRONY_VERSION, CHRONYD_FEATURES);
|
||||
|
||||
DNS_SetAddressFamily(address_family);
|
||||
|
||||
CNF_Initialise(restarted);
|
||||
|
||||
/* Parse the config file or the remaining command line arguments */
|
||||
if (!config_args) {
|
||||
CNF_ReadFile(conf_file);
|
||||
} else {
|
||||
do {
|
||||
CNF_ParseLine(NULL, config_args - argc + 1, *argv);
|
||||
} while (++argv, --argc);
|
||||
}
|
||||
|
||||
/* Check whether another chronyd may already be running. Do this after
|
||||
* forking, so that message logging goes to the right place (i.e. syslog), in
|
||||
* case this chronyd is being run from a boot script. */
|
||||
if (maybe_another_chronyd_running(&other_pid)) {
|
||||
LOG_FATAL(LOGF_Main, "Another chronyd may already be running (pid=%d), check lockfile (%s)",
|
||||
other_pid, CNF_GetPidFile());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Write our lockfile to prevent other chronyds running. This has *GOT* to
|
||||
* be done *AFTER* the daemon-creation fork() */
|
||||
write_lockfile();
|
||||
#endif
|
||||
|
||||
CNF_ReadFile(conf_file);
|
||||
|
||||
if (do_init_rtc) {
|
||||
RTC_TimePreInit();
|
||||
}
|
||||
|
||||
LCL_Initialise();
|
||||
SCH_Initialise();
|
||||
SYS_Initialise();
|
||||
NIO_Initialise();
|
||||
CAM_Initialise();
|
||||
RTC_Initialise();
|
||||
RTC_Initialise(do_init_rtc);
|
||||
SRC_Initialise();
|
||||
RCL_Initialise();
|
||||
KEY_Initialise();
|
||||
|
||||
/* Open privileged ports before dropping root */
|
||||
CAM_Initialise(address_family);
|
||||
NIO_Initialise(address_family);
|
||||
NCR_Initialise();
|
||||
CNF_SetupAccessRestrictions();
|
||||
|
||||
/* Command-line switch must have priority */
|
||||
if (!sched_priority) {
|
||||
@@ -312,41 +489,57 @@ int main
|
||||
SYS_LockMemory();
|
||||
}
|
||||
|
||||
if (user) {
|
||||
SYS_DropRoot(user);
|
||||
if (!user) {
|
||||
user = CNF_GetUser();
|
||||
}
|
||||
|
||||
if ((pw = getpwnam(user)) == NULL)
|
||||
LOG_FATAL(LOGF_Main, "Could not get %s uid/gid", user);
|
||||
|
||||
/* Create all directories before dropping root */
|
||||
CNF_CreateDirs(pw->pw_uid, pw->pw_gid);
|
||||
|
||||
/* Drop root privileges if the user has non-zero uid or gid */
|
||||
if (pw->pw_uid || pw->pw_gid)
|
||||
SYS_DropRoot(pw->pw_uid, pw->pw_gid);
|
||||
|
||||
REF_Initialise();
|
||||
SST_Initialise();
|
||||
SRC_Initialise();
|
||||
BRD_Initialise();
|
||||
NCR_Initialise();
|
||||
NSR_Initialise();
|
||||
CLG_Initialise();
|
||||
KEY_Initialise();
|
||||
ACQ_Initialise();
|
||||
MNL_Initialise();
|
||||
TMC_Initialise();
|
||||
SMT_Initialise();
|
||||
|
||||
/* From now on, it is safe to do finalisation on exit */
|
||||
initialised = 1;
|
||||
|
||||
UTI_SetQuitSignalsHandler(signal_cleanup);
|
||||
|
||||
CAM_OpenUnixSocket();
|
||||
|
||||
if (scfilter_level)
|
||||
SYS_EnableSystemCallFilter(scfilter_level);
|
||||
|
||||
if (ref_mode == REF_ModeNormal && CNF_GetInitSources() > 0) {
|
||||
ref_mode = REF_ModeInitStepSlew;
|
||||
}
|
||||
|
||||
REF_SetModeEndHandler(reference_mode_end);
|
||||
REF_SetMode(ref_mode);
|
||||
|
||||
if (do_init_rtc) {
|
||||
RTC_TimeInit(post_init_rtc_hook, NULL);
|
||||
} else {
|
||||
post_init_rtc_hook(NULL);
|
||||
}
|
||||
|
||||
signal(SIGINT, signal_cleanup);
|
||||
signal(SIGTERM, signal_cleanup);
|
||||
#if !defined(WINNT)
|
||||
signal(SIGQUIT, signal_cleanup);
|
||||
signal(SIGHUP, signal_cleanup);
|
||||
#endif /* WINNT */
|
||||
|
||||
/* The program normally runs under control of the main loop in
|
||||
the scheduler. */
|
||||
SCH_MainLoop();
|
||||
|
||||
LOG(LOGS_INFO, LOGF_Main, "chronyd exiting");
|
||||
|
||||
MAI_CleanupAndExit();
|
||||
|
||||
return 0;
|
||||
|
||||
4
main.h
4
main.h
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/main.h,v 1.8 2002/02/28 23:27:10 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
|
||||
96
make_release
96
make_release
@@ -1,52 +1,70 @@
|
||||
#!/usr/bin/env perl
|
||||
#!/bin/sh
|
||||
|
||||
$tool = "chrony";
|
||||
LANG=C
|
||||
export LANG
|
||||
|
||||
$version = shift || die "Usage : $0 <version>\n";
|
||||
$subdir = "${tool}-${version}";
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "Usage : $0 <version>"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
unless (-d ".git") {
|
||||
die "No .git subdirectory?"
|
||||
}
|
||||
version=$1
|
||||
tag=$version
|
||||
subdir=chrony-${version}
|
||||
mandate=$(date +'%B %Y')
|
||||
|
||||
unless (-d "RELEASES") {
|
||||
mkdir "RELEASES", 0755;
|
||||
}
|
||||
umask 022
|
||||
|
||||
system ("git tag -s $version");
|
||||
die "git-tag failed" if ($? != 0);
|
||||
if (-d "RELEASES/$subdir") {
|
||||
system ("rm -rf RELEASES/$subdir");
|
||||
}
|
||||
if [ ! -d .git ]; then
|
||||
echo "No .git subdirectory?"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
system ("git archive --format=tar --prefix=RELEASES/${subdir}/ $version | tar xf -");
|
||||
die "git-tar-tree failed" if ($? != 0);
|
||||
[ -d RELEASES ] || mkdir RELEASES
|
||||
|
||||
chdir "RELEASES";
|
||||
$here = qx/pwd/;
|
||||
chomp $here;
|
||||
chdir $subdir;
|
||||
rm -rf RELEASES/$subdir
|
||||
|
||||
open (OUT, ">version.txt");
|
||||
print OUT $version."\n";
|
||||
close OUT;
|
||||
if [ $version != test ]; then
|
||||
git tag -s $tag || exit 1
|
||||
else
|
||||
tag=HEAD
|
||||
fi
|
||||
|
||||
open (IN, "<${tool}.spec.sample");
|
||||
open (OUT, ">${tool}.spec");
|
||||
while (<IN>) {
|
||||
s/\@\@VERSION\@\@/$version/;
|
||||
print OUT;
|
||||
}
|
||||
close (IN);
|
||||
close (OUT);
|
||||
git archive --format=tar --prefix=RELEASES/${subdir}/ $tag | \
|
||||
tar xf - || exit 1
|
||||
|
||||
system("makeinfo --no-headers --number-sections -o chrony.txt chrony.texi");
|
||||
unlink "make_release";
|
||||
unlink "${tool}.spec.sample";
|
||||
unlink ".gitignore";
|
||||
cd RELEASES/$subdir || exit 1
|
||||
|
||||
chdir $here;
|
||||
system ("tar cvf - $subdir | gzip -9 > ${subdir}.tar.gz");
|
||||
system ("gpg -b -a -o ${subdir}-tar-gz-asc.txt ${subdir}.tar.gz");
|
||||
echo $version > version.txt
|
||||
|
||||
sed -i -e "s%@@VERSION@@%${version}%" examples/chrony.spec
|
||||
|
||||
for m in chronyc.1.in chrony.conf.5.in chronyd.8.in; do
|
||||
sed -e "s%@VERSION@%${version}%;s%@MAN_DATE@%${mandate}%" \
|
||||
< $m > ${m}_
|
||||
mv -f ${m}_ $m
|
||||
done
|
||||
|
||||
./configure && make chrony.txt getdate.c || exit 1
|
||||
|
||||
awk '/^[1-9] Installation$/{p=1}
|
||||
/^[1-9]\.. Support for line editing/{exit}; p' chrony.txt | \
|
||||
tail -n +4 > INSTALL
|
||||
|
||||
if [ $(wc -l < INSTALL) -gt 100 -o $(wc -l < INSTALL) -lt 85 ]; then
|
||||
echo "INSTALL generated incorrectly?"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
a2x --lynx -f text doc/faq.adoc || exit 1
|
||||
mv doc/faq.text FAQ
|
||||
rm -rf doc
|
||||
|
||||
make distclean
|
||||
rm -f config.h config.log make_release .gitignore
|
||||
|
||||
cd ..
|
||||
tar cv --owner root --group root $subdir | gzip -9 > ${subdir}.tar.gz
|
||||
|
||||
[ $version != test ] && \
|
||||
gpg -b -a -o ${subdir}-tar-gz-asc.txt ${subdir}.tar.gz
|
||||
|
||||
74
manual.c
74
manual.c
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/manual.c,v 1.21 2003/09/22 21:22:30 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
@@ -34,7 +30,9 @@
|
||||
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "config.h"
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "manual.h"
|
||||
#include "logging.h"
|
||||
@@ -56,27 +54,21 @@ typedef struct {
|
||||
(measured-predicted)) */
|
||||
} Sample;
|
||||
|
||||
#define MIN_SAMPLE_SEPARATION 1.0
|
||||
|
||||
#define MAX_SAMPLES 16
|
||||
|
||||
static Sample samples[16];
|
||||
static int n_samples;
|
||||
|
||||
static int replace_margin;
|
||||
static int error;
|
||||
|
||||
/* Eventually these constants need to be user-defined in conf file */
|
||||
#define REPLACE_MARGIN 300
|
||||
#define ERROR_MARGIN 0.2
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
slew_samples(struct timeval *raw,
|
||||
struct timeval *cooked,
|
||||
double dfreq,
|
||||
double afreq,
|
||||
double doffset,
|
||||
int is_step_change,
|
||||
LCL_ChangeType change_type,
|
||||
void *not_used);
|
||||
|
||||
/* ================================================== */
|
||||
@@ -92,12 +84,7 @@ MNL_Initialise(void)
|
||||
|
||||
n_samples = 0;
|
||||
|
||||
replace_margin = REPLACE_MARGIN;
|
||||
error = ERROR_MARGIN;
|
||||
|
||||
LCL_AddParameterChangeHandler(slew_samples, NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -105,7 +92,6 @@ MNL_Initialise(void)
|
||||
void
|
||||
MNL_Finalise(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -148,6 +134,8 @@ estimate_and_set_system(struct timeval *now, int offset_provided, double offset,
|
||||
}
|
||||
b1 = freq = 0.0;
|
||||
found_freq = 0;
|
||||
agos[0] = 0.0;
|
||||
offsets[0] = b0;
|
||||
}
|
||||
|
||||
if (offset_provided) {
|
||||
@@ -158,7 +146,7 @@ estimate_and_set_system(struct timeval *now, int offset_provided, double offset,
|
||||
|
||||
if (found_freq) {
|
||||
LOG(LOGS_INFO, LOGF_Manual,
|
||||
"Making a frequency change of %.3fppm and a slew of %.6f\n",
|
||||
"Making a frequency change of %.3f ppm and a slew of %.6f",
|
||||
1.0e6 * freq, slew_by);
|
||||
|
||||
REF_SetManualReference(now,
|
||||
@@ -188,14 +176,23 @@ int
|
||||
MNL_AcceptTimestamp(struct timeval *ts, long *offset_cs, double *dfreq_ppm, double *new_afreq_ppm)
|
||||
{
|
||||
struct timeval now;
|
||||
double local_clock_err;
|
||||
double offset;
|
||||
double offset, diff;
|
||||
int i;
|
||||
|
||||
if (enabled) {
|
||||
LCL_ReadCookedTime(&now, NULL);
|
||||
|
||||
/* Check whether timestamp is within margin of old one */
|
||||
LCL_ReadCookedTime(&now, &local_clock_err);
|
||||
/* Make sure the provided timestamp is sane and the sample
|
||||
is not too close to the last one */
|
||||
|
||||
if (!UTI_IsTimeOffsetSane(ts, 0.0))
|
||||
return 0;
|
||||
|
||||
if (n_samples) {
|
||||
UTI_DiffTimevalsToDouble(&diff, &now, &samples[n_samples - 1].when);
|
||||
if (diff < MIN_SAMPLE_SEPARATION)
|
||||
return 0;
|
||||
}
|
||||
|
||||
UTI_DiffTimevalsToDouble(&offset, &now, ts);
|
||||
|
||||
@@ -230,20 +227,22 @@ static void
|
||||
slew_samples(struct timeval *raw,
|
||||
struct timeval *cooked,
|
||||
double dfreq,
|
||||
double afreq,
|
||||
double doffset,
|
||||
int is_step_change,
|
||||
LCL_ChangeType change_type,
|
||||
void *not_used)
|
||||
{
|
||||
double elapsed, delta_time;
|
||||
double delta_time;
|
||||
int i;
|
||||
|
||||
if (change_type == LCL_ChangeUnknownStep) {
|
||||
MNL_Reset();
|
||||
}
|
||||
|
||||
for (i=0; i<n_samples; i++) {
|
||||
UTI_DiffTimevalsToDouble(&elapsed, cooked, &samples[i].when);
|
||||
delta_time = elapsed * dfreq - doffset;
|
||||
UTI_AddDoubleToTimeval(&samples[i].when, delta_time, &samples[i].when);
|
||||
UTI_AdjustTimeval(&samples[i].when, cooked, &samples[i].when, &delta_time,
|
||||
dfreq, doffset);
|
||||
samples[i].offset += delta_time;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -271,6 +270,14 @@ MNL_Reset(void)
|
||||
n_samples = 0;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
MNL_IsEnabled(void)
|
||||
{
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
/* Generate report data for the REQ_MANUAL_LIST command/monitoring
|
||||
protocol */
|
||||
@@ -303,7 +310,6 @@ MNL_DeleteSample(int index)
|
||||
{
|
||||
int i;
|
||||
struct timeval now;
|
||||
double local_clock_err;
|
||||
|
||||
if ((index < 0) || (index >= n_samples)) {
|
||||
return 0;
|
||||
@@ -319,7 +325,7 @@ MNL_DeleteSample(int index)
|
||||
|
||||
/* Now re-estimate. NULLs because we don't want the parameters back
|
||||
in this case. */
|
||||
LCL_ReadCookedTime(&now, &local_clock_err);
|
||||
LCL_ReadCookedTime(&now, NULL);
|
||||
estimate_and_set_system(&now, 0, 0.0, NULL, NULL, NULL);
|
||||
|
||||
return 1;
|
||||
|
||||
5
manual.h
5
manual.h
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/manual.h,v 1.12 2002/02/28 23:27:11 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
@@ -42,6 +38,7 @@ extern int MNL_AcceptTimestamp(struct timeval *ts, long *offset_cs, double *dfre
|
||||
extern void MNL_Enable(void);
|
||||
extern void MNL_Disable(void);
|
||||
extern void MNL_Reset(void);
|
||||
extern int MNL_IsEnabled(void);
|
||||
|
||||
extern void MNL_ReportSamples(RPT_ManualSamplesReport *report, int max, int *n);
|
||||
extern int MNL_DeleteSample(int index);
|
||||
|
||||
6
md5.h
6
md5.h
@@ -32,11 +32,7 @@
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
#ifdef HAS_STDINT_H
|
||||
#include <stdint.h>
|
||||
#elif defined(HAS_INTTYPES_H)
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#include "sysincl.h"
|
||||
|
||||
/* typedef a 32-bit type */
|
||||
typedef uint32_t UINT4;
|
||||
|
||||
67
memory.c
Normal file
67
memory.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Miroslav Lichvar 2014
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
=======================================================================
|
||||
|
||||
Utility functions for memory allocation.
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "logging.h"
|
||||
#include "memory.h"
|
||||
|
||||
void *
|
||||
Malloc(size_t size)
|
||||
{
|
||||
void *r;
|
||||
|
||||
r = malloc(size);
|
||||
if (!r && size)
|
||||
LOG_FATAL(LOGF_Memory, "Could not allocate memory");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void *
|
||||
Realloc(void *ptr, size_t size)
|
||||
{
|
||||
void *r;
|
||||
|
||||
r = realloc(ptr, size);
|
||||
if (!r && size)
|
||||
LOG_FATAL(LOGF_Memory, "Could not allocate memory");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
char *
|
||||
Strdup(const char *s)
|
||||
{
|
||||
void *r;
|
||||
|
||||
r = strdup(s);
|
||||
if (!r)
|
||||
LOG_FATAL(LOGF_Memory, "Could not allocate memory");
|
||||
|
||||
return r;
|
||||
}
|
||||
18
memory.h
18
memory.h
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/memory.h,v 1.7 2002/02/28 23:27:11 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
@@ -31,13 +27,15 @@
|
||||
#ifndef GOT_MEMORY_H
|
||||
#define GOT_MEMORY_H
|
||||
|
||||
#include <stdlib.h>
|
||||
/* Wrappers checking for errors */
|
||||
extern void *Malloc(size_t size);
|
||||
extern void *Realloc(void *ptr, size_t size);
|
||||
extern char *Strdup(const char *s);
|
||||
|
||||
#define Malloc(x) malloc(x)
|
||||
#define MallocNew(T) ((T *) malloc(sizeof(T)))
|
||||
#define MallocArray(T, n) ((T *) malloc((n) * sizeof(T)))
|
||||
#define Realloc(x,y) realloc(x,y)
|
||||
#define ReallocArray(T,n,x) ((T *) realloc((void *)(x), (n)*sizeof(T)))
|
||||
/* Convenient macros */
|
||||
#define MallocNew(T) ((T *) Malloc(sizeof(T)))
|
||||
#define MallocArray(T, n) ((T *) Malloc((n) * sizeof(T)))
|
||||
#define ReallocArray(T,n,x) ((T *) Realloc((void *)(x), (n)*sizeof(T)))
|
||||
#define Free(x) free(x)
|
||||
|
||||
#endif /* GOT_MEMORY_H */
|
||||
|
||||
135
mkdirpp.c
135
mkdirpp.c
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/mkdirpp.c,v 1.10 2002/11/03 22:49:17 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2002
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
=======================================================================
|
||||
|
||||
A function for creating a directory and any parent directories that
|
||||
don't exist.
|
||||
|
||||
*/
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "mkdirpp.h"
|
||||
|
||||
static int
|
||||
do_dir(char *p)
|
||||
{
|
||||
int status;
|
||||
struct stat buf;
|
||||
|
||||
#if defined(TEST)
|
||||
fprintf(stderr, "do_dir(%s)\n", p);
|
||||
#endif
|
||||
|
||||
/* See if directory exists */
|
||||
status = stat(p, &buf);
|
||||
|
||||
if (status < 0) {
|
||||
if (errno == ENOENT) {
|
||||
/* Try to create directory */
|
||||
status = mkdir(p, 0755);
|
||||
return status;
|
||||
} else {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (!S_ISDIR(buf.st_mode)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
/* Return 0 if the directory couldn't be created, 1 if it could (or
|
||||
already existed) */
|
||||
|
||||
int
|
||||
mkdir_and_parents(const char *path)
|
||||
{
|
||||
char *p;
|
||||
int len;
|
||||
int i, j, k, last;
|
||||
len = strlen(path);
|
||||
|
||||
p = (char *) malloc(1 + len);
|
||||
|
||||
i = k = 0;
|
||||
while (1) {
|
||||
p[i++] = path[k++];
|
||||
|
||||
if (path[k] == '/' || !path[k]) {
|
||||
p[i] = 0;
|
||||
|
||||
if (do_dir(p) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!path[k]) {
|
||||
/* End of the string */
|
||||
break;
|
||||
}
|
||||
|
||||
/* check whether its a trailing / or group of / */
|
||||
last = 1;
|
||||
j = k+1;
|
||||
while (path[j]) {
|
||||
if (path[j] != '/') {
|
||||
k = j - 1; /* Pick up a / into p[] thru the assignment at the top of the loop */
|
||||
last = 0;
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
|
||||
if (last) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!path[k]) break;
|
||||
|
||||
}
|
||||
|
||||
free(p);
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
#if defined(TEST)
|
||||
int main(int argc, char **argv) {
|
||||
if (argc > 1) {
|
||||
/* Invert sense of result */
|
||||
return mkdir_and_parents(argv[1]) ? 0 : 1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
15
mkversion
15
mkversion
@@ -1,15 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -f version.h
|
||||
echo "#ifndef VERSION_H" > version.h
|
||||
echo "#define VERSION_H 1" >> version.h
|
||||
|
||||
if [ -f version.txt ]; then
|
||||
ver=`cat version.txt`
|
||||
echo "#define PROGRAM_VERSION_STRING \"$ver\"" >> version.h
|
||||
else
|
||||
echo "#define PROGRAM_VERSION_STRING \"DEVELOPMENT\"" >> version.h
|
||||
fi
|
||||
|
||||
echo "#endif /* VERSION_H */" >> version.h
|
||||
|
||||
157
nameserv.c
157
nameserv.c
@@ -1,13 +1,9 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/nameserv.c,v 1.15 2003/09/22 21:22:30 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2009
|
||||
* Copyright (C) Miroslav Lichvar 2009-2011
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -30,17 +26,15 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "nameserv.h"
|
||||
#include "util.h"
|
||||
#include <resolv.h>
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
#define MAXRETRIES 10
|
||||
static unsigned int retries = 0;
|
||||
|
||||
static int address_family = IPADDR_UNSPEC;
|
||||
|
||||
void
|
||||
@@ -49,111 +43,106 @@ DNS_SetAddressFamily(int family)
|
||||
address_family = family;
|
||||
}
|
||||
|
||||
int
|
||||
DNS_Name2IPAddress(const char *name, IPAddr *addr, int retry)
|
||||
DNS_Status
|
||||
DNS_Name2IPAddress(const char *name, IPAddr *ip_addrs, int max_addrs)
|
||||
{
|
||||
#ifdef HAVE_IPV6
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
struct addrinfo hints, *res, *ai;
|
||||
int result;
|
||||
int i, result;
|
||||
|
||||
memset(&hints, 0, sizeof (hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
#ifdef AI_ADDRCONFIG
|
||||
hints.ai_flags = AI_ADDRCONFIG;
|
||||
#endif
|
||||
|
||||
try_again:
|
||||
result = getaddrinfo(name, NULL, &hints, &res);
|
||||
|
||||
if (result) {
|
||||
if (retry && result == EAI_AGAIN && retries < MAXRETRIES) {
|
||||
sleep(2 << retries);
|
||||
retries++;
|
||||
res_init();
|
||||
goto try_again;
|
||||
}
|
||||
return 0;
|
||||
#ifdef FORCE_DNSRETRY
|
||||
return DNS_TryAgain;
|
||||
#else
|
||||
return result == EAI_AGAIN ? DNS_TryAgain : DNS_Failure;
|
||||
#endif
|
||||
}
|
||||
|
||||
for (ai = res; !result && ai != NULL; ai = ai->ai_next) {
|
||||
for (ai = res, i = 0; i < max_addrs && ai != NULL; ai = ai->ai_next) {
|
||||
switch (ai->ai_family) {
|
||||
case AF_INET:
|
||||
addr->family = IPADDR_INET4;
|
||||
addr->addr.in4 = ntohl(((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr);
|
||||
result = 1;
|
||||
if (address_family != IPADDR_UNSPEC && address_family != IPADDR_INET4)
|
||||
continue;
|
||||
ip_addrs[i].family = IPADDR_INET4;
|
||||
ip_addrs[i].addr.in4 = ntohl(((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr);
|
||||
i++;
|
||||
break;
|
||||
#ifdef HAVE_IPV6
|
||||
#ifdef FEAT_IPV6
|
||||
case AF_INET6:
|
||||
addr->family = IPADDR_INET6;
|
||||
memcpy(&addr->addr.in6, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr.s6_addr, sizeof (addr->addr.in6));
|
||||
result = 1;
|
||||
if (address_family != IPADDR_UNSPEC && address_family != IPADDR_INET6)
|
||||
continue;
|
||||
ip_addrs[i].family = IPADDR_INET6;
|
||||
memcpy(&ip_addrs[i].addr.in6, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr.s6_addr,
|
||||
sizeof (ip_addrs->addr.in6));
|
||||
i++;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
if (result && address_family != IPADDR_UNSPEC && address_family != addr->family)
|
||||
result = 0;
|
||||
}
|
||||
|
||||
for (; i < max_addrs; i++)
|
||||
ip_addrs[i].family = IPADDR_UNSPEC;
|
||||
|
||||
freeaddrinfo(res);
|
||||
return result;
|
||||
|
||||
return !max_addrs || ip_addrs[0].family != IPADDR_UNSPEC ? DNS_Success : DNS_Failure;
|
||||
#else
|
||||
struct hostent *host;
|
||||
char *address0;
|
||||
int i;
|
||||
|
||||
try_again:
|
||||
if (address_family != IPADDR_UNSPEC && address_family != IPADDR_INET4)
|
||||
return DNS_Failure;
|
||||
|
||||
host = gethostbyname(name);
|
||||
|
||||
if (host == NULL) {
|
||||
if (retry && h_errno == TRY_AGAIN && retries < MAXRETRIES) {
|
||||
sleep(2 << retries);
|
||||
retries++;
|
||||
res_init();
|
||||
goto try_again;
|
||||
}
|
||||
if (h_errno == TRY_AGAIN)
|
||||
return DNS_TryAgain;
|
||||
} else {
|
||||
addr->family = IPADDR_INET4;
|
||||
address0 = host->h_addr_list[0];
|
||||
addr->addr.in4 = ((((unsigned long)address0[0])<<24) |
|
||||
(((unsigned long)address0[1])<<16) |
|
||||
(((unsigned long)address0[2])<<8) |
|
||||
(((unsigned long)address0[3])));
|
||||
return 1;
|
||||
if (host->h_addrtype != AF_INET || !host->h_addr_list[0])
|
||||
return DNS_Failure;
|
||||
|
||||
for (i = 0; host->h_addr_list[i] && i < max_addrs; i++) {
|
||||
ip_addrs[i].family = IPADDR_INET4;
|
||||
ip_addrs[i].addr.in4 = ntohl(*(uint32_t *)host->h_addr_list[i]);
|
||||
}
|
||||
|
||||
for (; i < max_addrs; i++)
|
||||
ip_addrs[i].family = IPADDR_UNSPEC;
|
||||
|
||||
return DNS_Success;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#ifdef FORCE_DNSRETRY
|
||||
return DNS_TryAgain;
|
||||
#else
|
||||
return DNS_Failure;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
int
|
||||
DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len)
|
||||
{
|
||||
#ifdef HAVE_IPV6
|
||||
int result;
|
||||
struct sockaddr_in in4;
|
||||
char *result = NULL;
|
||||
|
||||
#ifdef FEAT_IPV6
|
||||
struct sockaddr_in6 in6;
|
||||
socklen_t slen;
|
||||
char hbuf[NI_MAXHOST];
|
||||
|
||||
switch (ip_addr->family) {
|
||||
case IPADDR_INET4:
|
||||
memset(&in4, 0, sizeof (in4));
|
||||
in4.sin_family = AF_INET;
|
||||
in4.sin_addr.s_addr = htonl(ip_addr->addr.in4);
|
||||
result = getnameinfo((const struct sockaddr *)&in4, sizeof (in4), name, len, NULL, 0, 0);
|
||||
break;
|
||||
case IPADDR_INET6:
|
||||
memset(&in6, 0, sizeof (in6));
|
||||
in6.sin6_family = AF_INET6;
|
||||
memcpy(&in6.sin6_addr.s6_addr, ip_addr->addr.in6, sizeof (in6.sin6_addr.s6_addr));
|
||||
result = getnameinfo((const struct sockaddr *)&in6, sizeof (in6), name, len, NULL, 0, 0);
|
||||
break;
|
||||
default:
|
||||
result = 1;
|
||||
}
|
||||
|
||||
if (result)
|
||||
snprintf(name, len, "%s", UTI_IPToString(ip_addr));
|
||||
slen = UTI_IPAndPortToSockaddr(ip_addr, 0, (struct sockaddr *)&in6);
|
||||
if (!getnameinfo((struct sockaddr *)&in6, slen, hbuf, sizeof (hbuf), NULL, 0, 0))
|
||||
result = hbuf;
|
||||
#else
|
||||
struct hostent *host;
|
||||
uint32_t addr;
|
||||
@@ -163,7 +152,7 @@ DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len)
|
||||
addr = htonl(ip_addr->addr.in4);
|
||||
host = gethostbyaddr((const char *) &addr, sizeof (ip_addr), AF_INET);
|
||||
break;
|
||||
#ifdef HAVE_IPV6
|
||||
#ifdef FEAT_IPV6
|
||||
case IPADDR_INET6:
|
||||
host = gethostbyaddr((const void *) ip_addr->addr.in6, sizeof (ip_addr->addr.in6), AF_INET6);
|
||||
break;
|
||||
@@ -171,8 +160,24 @@ DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len)
|
||||
default:
|
||||
host = NULL;
|
||||
}
|
||||
snprintf(name, len, "%s", host ? host->h_name : UTI_IPToString(ip_addr));
|
||||
if (host)
|
||||
result = host->h_name;
|
||||
#endif
|
||||
|
||||
if (result == NULL)
|
||||
result = UTI_IPToString(ip_addr);
|
||||
if (snprintf(name, len, "%s", result) >= len)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
DNS_Reload(void)
|
||||
{
|
||||
res_init();
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
16
nameserv.h
16
nameserv.h
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/nameserv.h,v 1.8 2002/02/28 23:27:11 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
@@ -34,12 +30,20 @@
|
||||
|
||||
#include "addressing.h"
|
||||
|
||||
typedef enum {
|
||||
DNS_Success,
|
||||
DNS_TryAgain,
|
||||
DNS_Failure
|
||||
} DNS_Status;
|
||||
|
||||
/* Resolve names only to selected address family */
|
||||
extern void DNS_SetAddressFamily(int family);
|
||||
|
||||
extern int DNS_Name2IPAddress(const char *name, IPAddr *addr, int retry);
|
||||
extern DNS_Status DNS_Name2IPAddress(const char *name, IPAddr *ip_addrs, int max_addrs);
|
||||
|
||||
extern void DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len);
|
||||
extern int DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len);
|
||||
|
||||
extern void DNS_Reload(void);
|
||||
|
||||
#endif /* GOT_NAMESERV_H */
|
||||
|
||||
|
||||
131
nameserv_async.c
Normal file
131
nameserv_async.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Miroslav Lichvar 2014
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
=======================================================================
|
||||
|
||||
Functions to asynchronously convert name to IP address
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "nameserv_async.h"
|
||||
#include "logging.h"
|
||||
#include "memory.h"
|
||||
#include "sched.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifdef USE_PTHREAD_ASYNCDNS
|
||||
#include <pthread.h>
|
||||
|
||||
#define MAX_ADDRESSES 16
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
struct DNS_Async_Instance {
|
||||
const char *name;
|
||||
DNS_Status status;
|
||||
IPAddr addresses[MAX_ADDRESSES];
|
||||
DNS_NameResolveHandler handler;
|
||||
void *arg;
|
||||
|
||||
pthread_t thread;
|
||||
int pipe[2];
|
||||
};
|
||||
|
||||
static int resolving_threads = 0;
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void *
|
||||
start_resolving(void *anything)
|
||||
{
|
||||
struct DNS_Async_Instance *inst = (struct DNS_Async_Instance *)anything;
|
||||
|
||||
inst->status = DNS_Name2IPAddress(inst->name, inst->addresses, MAX_ADDRESSES);
|
||||
|
||||
/* Notify the main thread that the result is ready */
|
||||
if (write(inst->pipe[1], "", 1) < 0)
|
||||
;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
end_resolving(void *anything)
|
||||
{
|
||||
struct DNS_Async_Instance *inst = (struct DNS_Async_Instance *)anything;
|
||||
int i;
|
||||
|
||||
if (pthread_join(inst->thread, NULL)) {
|
||||
LOG_FATAL(LOGF_Nameserv, "pthread_join() failed");
|
||||
}
|
||||
|
||||
resolving_threads--;
|
||||
|
||||
SCH_RemoveInputFileHandler(inst->pipe[0]);
|
||||
close(inst->pipe[0]);
|
||||
close(inst->pipe[1]);
|
||||
|
||||
for (i = 0; inst->status == DNS_Success && i < MAX_ADDRESSES &&
|
||||
inst->addresses[i].family != IPADDR_UNSPEC; i++)
|
||||
;
|
||||
|
||||
(inst->handler)(inst->status, i, inst->addresses, inst->arg);
|
||||
|
||||
Free(inst);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, void *anything)
|
||||
{
|
||||
struct DNS_Async_Instance *inst;
|
||||
|
||||
inst = MallocNew(struct DNS_Async_Instance);
|
||||
inst->name = name;
|
||||
inst->handler = handler;
|
||||
inst->arg = anything;
|
||||
inst->status = DNS_Failure;
|
||||
|
||||
if (pipe(inst->pipe)) {
|
||||
LOG_FATAL(LOGF_Nameserv, "pipe() failed");
|
||||
}
|
||||
|
||||
resolving_threads++;
|
||||
assert(resolving_threads <= 1);
|
||||
|
||||
if (pthread_create(&inst->thread, NULL, start_resolving, inst)) {
|
||||
LOG_FATAL(LOGF_Nameserv, "pthread_create() failed");
|
||||
}
|
||||
|
||||
SCH_AddInputFileHandler(inst->pipe[0], end_resolving, inst);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
40
nameserv_async.h
Normal file
40
nameserv_async.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Miroslav Lichvar 2014
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
=======================================================================
|
||||
|
||||
Header for asynchronous nameserver functions
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GOT_NAMESERV_ASYNC_H
|
||||
#define GOT_NAMESERV_ASYNC_H
|
||||
|
||||
#include "nameserv.h"
|
||||
|
||||
/* Function type for callback to process the result */
|
||||
typedef void (*DNS_NameResolveHandler)(DNS_Status status, int n_addrs, IPAddr *ip_addrs, void *anything);
|
||||
|
||||
/* Request resolving of a name to IP address. The handler will be
|
||||
called when the result is available. */
|
||||
extern void DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, void *anything);
|
||||
|
||||
#endif
|
||||
81
ntp.h
81
ntp.h
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/ntp.h,v 1.12 2003/09/22 21:22:30 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
@@ -31,11 +27,9 @@
|
||||
#ifndef GOT_NTP_H
|
||||
#define GOT_NTP_H
|
||||
|
||||
#ifdef HAS_STDINT_H
|
||||
#include <stdint.h>
|
||||
#elif defined(HAS_INTTYPES_H)
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t hi;
|
||||
@@ -44,7 +38,23 @@ typedef struct {
|
||||
|
||||
typedef uint32_t NTP_int32;
|
||||
|
||||
#define AUTH_DATA_LEN 16
|
||||
/* The NTP protocol version that we support */
|
||||
#define NTP_VERSION 4
|
||||
|
||||
/* Maximum stratum number (infinity) */
|
||||
#define NTP_MAX_STRATUM 16
|
||||
|
||||
/* The minimum valid length of an extension field */
|
||||
#define NTP_MIN_EXTENSION_LENGTH 16
|
||||
|
||||
/* The maximum assumed length of all extension fields in received
|
||||
packets (RFC 5905 doesn't specify a limit on length or number of
|
||||
extension fields in one packet) */
|
||||
#define NTP_MAX_EXTENSIONS_LENGTH 1024
|
||||
|
||||
/* The minimum and maximum supported length of MAC */
|
||||
#define NTP_MIN_MAC_LENGTH 16
|
||||
#define NTP_MAX_MAC_LENGTH MAX_HASH_LENGTH
|
||||
|
||||
/* Type definition for leap bits */
|
||||
typedef enum {
|
||||
@@ -75,42 +85,33 @@ typedef struct {
|
||||
NTP_int64 originate_ts;
|
||||
NTP_int64 receive_ts;
|
||||
NTP_int64 transmit_ts;
|
||||
|
||||
/* Optional extension fields, we don't send packets with them yet */
|
||||
/* uint8_t extensions[] */
|
||||
|
||||
/* Optional message authentication code (MAC) */
|
||||
NTP_int32 auth_keyid;
|
||||
uint8_t auth_data[AUTH_DATA_LEN];
|
||||
uint8_t auth_data[NTP_MAX_MAC_LENGTH];
|
||||
} NTP_Packet;
|
||||
|
||||
/* We have to declare a buffer type to hold a datagram read from the
|
||||
network. Even though we won't be using them (yet?!), this must be
|
||||
large enough to hold NTP control messages. */
|
||||
#define NTP_NORMAL_PACKET_LENGTH (int)offsetof(NTP_Packet, auth_keyid)
|
||||
|
||||
/* Define the maximum number of bytes that can be read in a single
|
||||
message. (This is cribbed from ntp.h in the xntpd source code). */
|
||||
|
||||
#define MAX_NTP_MESSAGE_SIZE (468+12+16+4)
|
||||
|
||||
typedef union {
|
||||
/* The buffer used to hold a datagram read from the network */
|
||||
typedef struct {
|
||||
NTP_Packet ntp_pkt;
|
||||
uint8_t arbitrary[MAX_NTP_MESSAGE_SIZE];
|
||||
} ReceiveBuffer;
|
||||
uint8_t extensions[NTP_MAX_EXTENSIONS_LENGTH];
|
||||
} NTP_Receive_Buffer;
|
||||
|
||||
#define NTP_NORMAL_PACKET_SIZE (sizeof(NTP_Packet) - (sizeof(NTP_int32) + AUTH_DATA_LEN))
|
||||
/* Macros to work with the lvm field */
|
||||
#define NTP_LVM_TO_LEAP(lvm) (((lvm) >> 6) & 0x3)
|
||||
#define NTP_LVM_TO_VERSION(lvm) (((lvm) >> 3) & 0x7)
|
||||
#define NTP_LVM_TO_MODE(lvm) ((lvm) & 0x7)
|
||||
#define NTP_LVM(leap, version, mode) \
|
||||
((((leap) << 6) & 0xc0) | (((version) << 3) & 0x38) | ((mode) & 0x07))
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
inline static double
|
||||
int32_to_double(NTP_int32 x)
|
||||
{
|
||||
return (double) ntohl(x) / 65536.0;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
inline static NTP_int32
|
||||
double_to_int32(double x)
|
||||
{
|
||||
return htonl((NTP_int32)(0.5 + 65536.0 * x));
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
/* Special NTP reference IDs */
|
||||
#define NTP_REFID_UNSYNC 0x0UL
|
||||
#define NTP_REFID_LOCAL 0x7F7F0101UL /* 127.127.1.1 */
|
||||
#define NTP_REFID_SMOOTH 0x7F7F01FFUL /* 127.127.1.255 */
|
||||
|
||||
#endif /* GOT_NTP_H */
|
||||
|
||||
2720
ntp_core.c
2720
ntp_core.c
File diff suppressed because it is too large
Load Diff
49
ntp_core.h
49
ntp_core.h
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/ntp_core.h,v 1.16 2002/02/28 23:27:12 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
@@ -38,6 +34,10 @@
|
||||
#include "ntp.h"
|
||||
#include "reports.h"
|
||||
|
||||
typedef enum {
|
||||
NTP_SERVER, NTP_PEER
|
||||
} NTP_Source_Type;
|
||||
|
||||
/* This is a private data type used for storing the instance record for
|
||||
each source that we are chiming with */
|
||||
typedef struct NCR_Instance_Record *NCR_Instance;
|
||||
@@ -46,31 +46,28 @@ typedef struct NCR_Instance_Record *NCR_Instance;
|
||||
extern void NCR_Initialise(void);
|
||||
extern void NCR_Finalise(void);
|
||||
|
||||
/* Get a new instance for a server */
|
||||
extern NCR_Instance NCR_GetServerInstance(NTP_Remote_Address *remote_addr, SourceParameters *params);
|
||||
|
||||
/* Get a new instance for a peer */
|
||||
extern NCR_Instance NCR_GetPeerInstance(NTP_Remote_Address *remote_addr, SourceParameters *params);
|
||||
/* Get a new instance for a server or peer */
|
||||
extern NCR_Instance NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParameters *params);
|
||||
|
||||
/* Destroy an instance */
|
||||
extern void NCR_DestroyInstance(NCR_Instance instance);
|
||||
|
||||
/* Start an instance */
|
||||
extern void NCR_StartInstance(NCR_Instance instance);
|
||||
|
||||
/* Reset an instance */
|
||||
extern void NCR_ResetInstance(NCR_Instance inst);
|
||||
|
||||
/* Change the remote address of an instance */
|
||||
extern void NCR_ChangeRemoteAddress(NCR_Instance inst, NTP_Remote_Address *remote_addr);
|
||||
|
||||
/* This routine is called when a new packet arrives off the network,
|
||||
and it relates to a source we have an ongoing protocol exchange with */
|
||||
extern void NCR_ProcessNoauthKnown(NTP_Packet *message, struct timeval *now, NCR_Instance data);
|
||||
extern int NCR_ProcessKnown(NTP_Packet *message, struct timeval *now, double now_err, NCR_Instance data, NTP_Local_Address *local_addr, int length);
|
||||
|
||||
/* This routine is called when a new packet arrives off the network,
|
||||
and we do not recognize its source */
|
||||
extern void NCR_ProcessNoauthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Address *remote_addr);
|
||||
|
||||
/* This routine is called when a new authenticated packet arrives off
|
||||
the network, and it relates to a source we have an ongoing protocol
|
||||
exchange with */
|
||||
extern void NCR_ProcessAuthKnown(NTP_Packet *message, struct timeval *now, NCR_Instance data);
|
||||
|
||||
/* This routine is called when a new authenticated packet arrives off
|
||||
the network, and we do not recognize its source */
|
||||
extern void NCR_ProcessAuthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Address *remote_addr);
|
||||
extern void NCR_ProcessUnknown(NTP_Packet *message, struct timeval *now, double now_err, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length);
|
||||
|
||||
/* Slew receive and transmit times in instance records */
|
||||
extern void NCR_SlewTimes(NCR_Instance inst, struct timeval *when, double dfreq, double doffset);
|
||||
@@ -90,6 +87,12 @@ extern void NCR_ModifyMaxdelay(NCR_Instance inst, double new_max_delay);
|
||||
|
||||
extern void NCR_ModifyMaxdelayratio(NCR_Instance inst, double new_max_delay_ratio);
|
||||
|
||||
extern void NCR_ModifyMaxdelaydevratio(NCR_Instance inst, double new_max_delay_dev_ratio);
|
||||
|
||||
extern void NCR_ModifyMinstratum(NCR_Instance inst, int new_min_stratum);
|
||||
|
||||
extern void NCR_ModifyPolltarget(NCR_Instance inst, int new_poll_target);
|
||||
|
||||
extern void NCR_InitiateSampleBurst(NCR_Instance inst, int n_good_samples, int n_total_samples);
|
||||
|
||||
extern void NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timeval *now);
|
||||
@@ -97,11 +100,13 @@ extern void NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct
|
||||
extern int NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
|
||||
extern int NCR_CheckAccessRestriction(IPAddr *ip_addr);
|
||||
|
||||
extern void NCR_CycleLogFile(void);
|
||||
|
||||
extern void NCR_IncrementActivityCounters(NCR_Instance inst, int *online, int *offline,
|
||||
int *burst_online, int *burst_offline);
|
||||
|
||||
extern NTP_Remote_Address *NCR_GetRemoteAddress(NCR_Instance instance);
|
||||
|
||||
extern int NCR_IsSyncPeer(NCR_Instance instance);
|
||||
|
||||
extern void NCR_AddBroadcastDestination(IPAddr *addr, unsigned short port, int interval);
|
||||
|
||||
#endif /* GOT_NTP_CORE_H */
|
||||
|
||||
682
ntp_io.c
682
ntp_io.c
@@ -1,14 +1,10 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/ntp_io.c,v 1.24 2003/09/22 21:22:30 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Timo Teras 2009
|
||||
* Copyright (C) Miroslav Lichvar 2009
|
||||
* Copyright (C) Miroslav Lichvar 2009, 2013-2015
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -30,6 +26,8 @@
|
||||
This file deals with the IO aspects of reading and writing NTP packets
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "ntp_io.h"
|
||||
@@ -41,94 +39,135 @@
|
||||
#include "conf.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#define INVALID_SOCK_FD -1
|
||||
|
||||
union sockaddr_in46 {
|
||||
struct sockaddr_in in4;
|
||||
#ifdef HAVE_IPV6
|
||||
#ifdef FEAT_IPV6
|
||||
struct sockaddr_in6 in6;
|
||||
#endif
|
||||
struct sockaddr u;
|
||||
};
|
||||
|
||||
/* The file descriptors for the IPv4 and IPv6 sockets */
|
||||
static int sock_fd4;
|
||||
#ifdef HAVE_IPV6
|
||||
static int sock_fd6;
|
||||
/* The server/peer and client sockets for IPv4 and IPv6 */
|
||||
static int server_sock_fd4;
|
||||
static int client_sock_fd4;
|
||||
#ifdef FEAT_IPV6
|
||||
static int server_sock_fd6;
|
||||
static int client_sock_fd6;
|
||||
#endif
|
||||
|
||||
/* Reference counters for server sockets to keep them open only when needed */
|
||||
static int server_sock_ref4;
|
||||
#ifdef FEAT_IPV6
|
||||
static int server_sock_ref6;
|
||||
#endif
|
||||
|
||||
/* Flag indicating we create a new connected client socket for each
|
||||
server instead of sharing client_sock_fd4 and client_sock_fd6 */
|
||||
static int separate_client_sockets;
|
||||
|
||||
/* Flag indicating the server sockets are not created dynamically when needed,
|
||||
either to have a socket for client requests when separate client sockets
|
||||
are disabled and client port is equal to server port, or the server port is
|
||||
disabled */
|
||||
static int permanent_server_sockets;
|
||||
|
||||
/* Flag indicating that we have been initialised */
|
||||
static int initialised=0;
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
/* Forward prototypes */
|
||||
static int prepare_socket(int family);
|
||||
static void read_from_socket(void *anything);
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
do_size_checks(void)
|
||||
{
|
||||
/* Assertions to check the sizes of certain data types
|
||||
and the positions of certain record fields */
|
||||
|
||||
/* Check that certain invariants are true */
|
||||
assert(sizeof(NTP_int32) == 4);
|
||||
assert(sizeof(NTP_int64) == 8);
|
||||
|
||||
/* Check offsets of all fields in the NTP packet format */
|
||||
assert(offsetof(NTP_Packet, lvm) == 0);
|
||||
assert(offsetof(NTP_Packet, stratum) == 1);
|
||||
assert(offsetof(NTP_Packet, poll) == 2);
|
||||
assert(offsetof(NTP_Packet, precision) == 3);
|
||||
assert(offsetof(NTP_Packet, root_delay) == 4);
|
||||
assert(offsetof(NTP_Packet, root_dispersion) == 8);
|
||||
assert(offsetof(NTP_Packet, reference_id) == 12);
|
||||
assert(offsetof(NTP_Packet, reference_ts) == 16);
|
||||
assert(offsetof(NTP_Packet, originate_ts) == 24);
|
||||
assert(offsetof(NTP_Packet, receive_ts) == 32);
|
||||
assert(offsetof(NTP_Packet, transmit_ts) == 40);
|
||||
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
prepare_socket(int family)
|
||||
prepare_socket(int family, int port_number, int client_only)
|
||||
{
|
||||
union sockaddr_in46 my_addr;
|
||||
socklen_t my_addr_len;
|
||||
int sock_fd;
|
||||
unsigned short port_number;
|
||||
IPAddr bind_address;
|
||||
int on_off = 1;
|
||||
|
||||
port_number = CNF_GetNTPPort();
|
||||
|
||||
/* Open Internet domain UDP socket for NTP message transmissions */
|
||||
|
||||
#if 0
|
||||
sock_fd = socket(family, SOCK_DGRAM, IPPROTO_UDP);
|
||||
#else
|
||||
sock_fd = socket(family, SOCK_DGRAM, 0);
|
||||
#endif
|
||||
|
||||
if (sock_fd < 0) {
|
||||
LOG(LOGS_ERR, LOGF_NtpIO, "Could not open %s NTP socket : %s",
|
||||
family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
|
||||
return -1;
|
||||
if (!client_only) {
|
||||
LOG(LOGS_ERR, LOGF_NtpIO, "Could not open %s NTP socket : %s",
|
||||
UTI_SockaddrFamilyToString(family), strerror(errno));
|
||||
} else {
|
||||
DEBUG_LOG(LOGF_NtpIO, "Could not open %s NTP socket : %s",
|
||||
UTI_SockaddrFamilyToString(family), strerror(errno));
|
||||
}
|
||||
return INVALID_SOCK_FD;
|
||||
}
|
||||
|
||||
/* Make the socket capable of re-using an old address */
|
||||
if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on_off, sizeof(on_off)) < 0) {
|
||||
/* Close on exec */
|
||||
UTI_FdSetCloexec(sock_fd);
|
||||
|
||||
/* Prepare local address */
|
||||
memset(&my_addr, 0, sizeof (my_addr));
|
||||
my_addr_len = 0;
|
||||
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
if (!client_only)
|
||||
CNF_GetBindAddress(IPADDR_INET4, &bind_address);
|
||||
else
|
||||
CNF_GetBindAcquisitionAddress(IPADDR_INET4, &bind_address);
|
||||
|
||||
if (bind_address.family == IPADDR_INET4)
|
||||
my_addr.in4.sin_addr.s_addr = htonl(bind_address.addr.in4);
|
||||
else if (port_number)
|
||||
my_addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
else
|
||||
break;
|
||||
|
||||
my_addr.in4.sin_family = family;
|
||||
my_addr.in4.sin_port = htons(port_number);
|
||||
my_addr_len = sizeof (my_addr.in4);
|
||||
|
||||
break;
|
||||
#ifdef FEAT_IPV6
|
||||
case AF_INET6:
|
||||
if (!client_only)
|
||||
CNF_GetBindAddress(IPADDR_INET6, &bind_address);
|
||||
else
|
||||
CNF_GetBindAcquisitionAddress(IPADDR_INET6, &bind_address);
|
||||
|
||||
if (bind_address.family == IPADDR_INET6)
|
||||
memcpy(my_addr.in6.sin6_addr.s6_addr, bind_address.addr.in6,
|
||||
sizeof (my_addr.in6.sin6_addr.s6_addr));
|
||||
else if (port_number)
|
||||
my_addr.in6.sin6_addr = in6addr_any;
|
||||
else
|
||||
break;
|
||||
|
||||
my_addr.in6.sin6_family = family;
|
||||
my_addr.in6.sin6_port = htons(port_number);
|
||||
my_addr_len = sizeof (my_addr.in6);
|
||||
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* Make the socket capable of re-using an old address if binding to a specific port */
|
||||
if (port_number &&
|
||||
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on_off, sizeof(on_off)) < 0) {
|
||||
LOG(LOGS_ERR, LOGF_NtpIO, "Could not set reuseaddr socket options");
|
||||
/* Don't quit - we might survive anyway */
|
||||
}
|
||||
|
||||
/* Make the socket capable of sending broadcast pkts - needed for NTP broadcast mode */
|
||||
if (setsockopt(sock_fd, SOL_SOCKET, SO_BROADCAST, (char *)&on_off, sizeof(on_off)) < 0) {
|
||||
if (!client_only &&
|
||||
setsockopt(sock_fd, SOL_SOCKET, SO_BROADCAST, (char *)&on_off, sizeof(on_off)) < 0) {
|
||||
LOG(LOGS_ERR, LOGF_NtpIO, "Could not set broadcast socket options");
|
||||
/* Don't quit - we might survive anyway */
|
||||
}
|
||||
@@ -141,107 +180,175 @@ prepare_socket(int family)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IP_FREEBIND
|
||||
/* Allow binding to address that doesn't exist yet */
|
||||
if (my_addr_len > 0 &&
|
||||
setsockopt(sock_fd, IPPROTO_IP, IP_FREEBIND, (char *)&on_off, sizeof(on_off)) < 0) {
|
||||
LOG(LOGS_ERR, LOGF_NtpIO, "Could not set free bind socket option");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (family == AF_INET) {
|
||||
#ifdef IP_PKTINFO
|
||||
/* We want the local IP info too */
|
||||
#ifdef HAVE_IN_PKTINFO
|
||||
/* We want the local IP info on server sockets */
|
||||
if (setsockopt(sock_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
|
||||
LOG(LOGS_ERR, LOGF_NtpIO, "Could not request packet info using socket option");
|
||||
LOG(LOGS_ERR, LOGF_NtpIO, "Could not set packet info socket option");
|
||||
/* Don't quit - we might survive anyway */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
#ifdef FEAT_IPV6
|
||||
else if (family == AF_INET6) {
|
||||
#ifdef IPV6_V6ONLY
|
||||
/* Receive IPv6 packets only */
|
||||
if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on_off, sizeof(on_off)) < 0) {
|
||||
LOG(LOGS_ERR, LOGF_NtpIO, "Could not request IPV6_V6ONLY socket option");
|
||||
LOG(LOGS_ERR, LOGF_NtpIO, "Could not set IPV6_V6ONLY socket option");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IN6_PKTINFO
|
||||
#ifdef IPV6_RECVPKTINFO
|
||||
if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
|
||||
LOG(LOGS_ERR, LOGF_NtpIO, "Could not set IPv6 packet info socket option");
|
||||
}
|
||||
#else
|
||||
if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
|
||||
LOG(LOGS_ERR, LOGF_NtpIO, "Could not set IPv6 packet info socket option");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Bind the port */
|
||||
memset(&my_addr, 0, sizeof (my_addr));
|
||||
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
my_addr_len = sizeof (my_addr.in4);
|
||||
my_addr.in4.sin_family = family;
|
||||
my_addr.in4.sin_port = htons(port_number);
|
||||
|
||||
CNF_GetBindAddress(IPADDR_INET4, &bind_address);
|
||||
|
||||
if (bind_address.family == IPADDR_INET4)
|
||||
my_addr.in4.sin_addr.s_addr = htonl(bind_address.addr.in4);
|
||||
else
|
||||
my_addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
break;
|
||||
#ifdef HAVE_IPV6
|
||||
case AF_INET6:
|
||||
my_addr_len = sizeof (my_addr.in6);
|
||||
my_addr.in6.sin6_family = family;
|
||||
my_addr.in6.sin6_port = htons(port_number);
|
||||
|
||||
CNF_GetBindAddress(IPADDR_INET6, &bind_address);
|
||||
|
||||
if (bind_address.family == IPADDR_INET6)
|
||||
memcpy(my_addr.in6.sin6_addr.s6_addr, bind_address.addr.in6,
|
||||
sizeof (my_addr.in6.sin6_addr.s6_addr));
|
||||
else
|
||||
my_addr.in6.sin6_addr = in6addr_any;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
LOG(LOGS_INFO, LOGF_NtpIO, "Initialising, socket fd=%d", sock_fd);
|
||||
#endif
|
||||
|
||||
if (bind(sock_fd, &my_addr.u, my_addr_len) < 0) {
|
||||
LOG_FATAL(LOGF_NtpIO, "Could not bind %s NTP socket : %s",
|
||||
family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
|
||||
/* Bind the socket if a port or address was specified */
|
||||
if (my_addr_len > 0 && bind(sock_fd, &my_addr.u, my_addr_len) < 0) {
|
||||
LOG(LOGS_ERR, LOGF_NtpIO, "Could not bind %s NTP socket : %s",
|
||||
UTI_SockaddrFamilyToString(family), strerror(errno));
|
||||
close(sock_fd);
|
||||
return INVALID_SOCK_FD;
|
||||
}
|
||||
|
||||
/* Register handler for read events on the socket */
|
||||
SCH_AddInputFileHandler(sock_fd, read_from_socket, (void *)(long)sock_fd);
|
||||
|
||||
#if 0
|
||||
if (fcntl(sock_fd, F_SETFL, O_NONBLOCK | O_NDELAY) < 0) {
|
||||
LOG(LOGS_ERR, LOGF_NtpIO, "Could not make socket non-blocking");
|
||||
}
|
||||
|
||||
if (ioctl(sock_fd, I_SETSIG, S_INPUT) < 0) {
|
||||
LOG(LOGS_ERR, LOGF_NtpIO, "Could not enable signal");
|
||||
}
|
||||
#endif
|
||||
return sock_fd;
|
||||
}
|
||||
|
||||
void
|
||||
NIO_Initialise(void)
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
prepare_separate_client_socket(int family)
|
||||
{
|
||||
switch (family) {
|
||||
case IPADDR_INET4:
|
||||
return prepare_socket(AF_INET, 0, 1);
|
||||
#ifdef FEAT_IPV6
|
||||
case IPADDR_INET6:
|
||||
return prepare_socket(AF_INET6, 0, 1);
|
||||
#endif
|
||||
default:
|
||||
return INVALID_SOCK_FD;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
connect_socket(int sock_fd, NTP_Remote_Address *remote_addr)
|
||||
{
|
||||
union sockaddr_in46 addr;
|
||||
socklen_t addr_len;
|
||||
|
||||
addr_len = UTI_IPAndPortToSockaddr(&remote_addr->ip_addr, remote_addr->port, &addr.u);
|
||||
|
||||
assert(addr_len);
|
||||
|
||||
if (connect(sock_fd, &addr.u, addr_len) < 0) {
|
||||
DEBUG_LOG(LOGF_NtpIO, "Could not connect NTP socket to %s:%d : %s",
|
||||
UTI_IPToString(&remote_addr->ip_addr), remote_addr->port,
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
close_socket(int sock_fd)
|
||||
{
|
||||
if (sock_fd == INVALID_SOCK_FD)
|
||||
return;
|
||||
|
||||
SCH_RemoveInputFileHandler(sock_fd);
|
||||
close(sock_fd);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
void
|
||||
NIO_Initialise(int family)
|
||||
{
|
||||
int server_port, client_port;
|
||||
|
||||
assert(!initialised);
|
||||
initialised = 1;
|
||||
|
||||
do_size_checks();
|
||||
server_port = CNF_GetNTPPort();
|
||||
client_port = CNF_GetAcquisitionPort();
|
||||
|
||||
sock_fd4 = prepare_socket(AF_INET);
|
||||
#ifdef HAVE_IPV6
|
||||
sock_fd6 = prepare_socket(AF_INET6);
|
||||
/* Use separate connected sockets if client port is negative */
|
||||
separate_client_sockets = client_port < 0;
|
||||
if (client_port < 0)
|
||||
client_port = 0;
|
||||
|
||||
permanent_server_sockets = !server_port || (!separate_client_sockets &&
|
||||
client_port == server_port);
|
||||
|
||||
server_sock_fd4 = INVALID_SOCK_FD;
|
||||
client_sock_fd4 = INVALID_SOCK_FD;
|
||||
server_sock_ref4 = 0;
|
||||
#ifdef FEAT_IPV6
|
||||
server_sock_fd6 = INVALID_SOCK_FD;
|
||||
client_sock_fd6 = INVALID_SOCK_FD;
|
||||
server_sock_ref6 = 0;
|
||||
#endif
|
||||
|
||||
if (sock_fd4 < 0
|
||||
#ifdef HAVE_IPV6
|
||||
&& sock_fd6 < 0
|
||||
#endif
|
||||
) {
|
||||
LOG_FATAL(LOGF_NtpIO, "Could not open any NTP socket");
|
||||
if (family == IPADDR_UNSPEC || family == IPADDR_INET4) {
|
||||
if (permanent_server_sockets && server_port)
|
||||
server_sock_fd4 = prepare_socket(AF_INET, server_port, 0);
|
||||
if (!separate_client_sockets) {
|
||||
if (client_port != server_port || !server_port)
|
||||
client_sock_fd4 = prepare_socket(AF_INET, client_port, 1);
|
||||
else
|
||||
client_sock_fd4 = server_sock_fd4;
|
||||
}
|
||||
}
|
||||
#ifdef FEAT_IPV6
|
||||
if (family == IPADDR_UNSPEC || family == IPADDR_INET6) {
|
||||
if (permanent_server_sockets && server_port)
|
||||
server_sock_fd6 = prepare_socket(AF_INET6, server_port, 0);
|
||||
if (!separate_client_sockets) {
|
||||
if (client_port != server_port || !server_port)
|
||||
client_sock_fd6 = prepare_socket(AF_INET6, client_port, 1);
|
||||
else
|
||||
client_sock_fd6 = server_sock_fd6;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
if ((server_port && server_sock_fd4 == INVALID_SOCK_FD &&
|
||||
permanent_server_sockets
|
||||
#ifdef FEAT_IPV6
|
||||
&& server_sock_fd6 == INVALID_SOCK_FD
|
||||
#endif
|
||||
) || (!separate_client_sockets && client_sock_fd4 == INVALID_SOCK_FD
|
||||
#ifdef FEAT_IPV6
|
||||
&& client_sock_fd6 == INVALID_SOCK_FD
|
||||
#endif
|
||||
)) {
|
||||
LOG_FATAL(LOGF_NtpIO, "Could not open NTP sockets");
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -249,24 +356,127 @@ NIO_Initialise(void)
|
||||
void
|
||||
NIO_Finalise(void)
|
||||
{
|
||||
if (sock_fd4 >= 0) {
|
||||
SCH_RemoveInputFileHandler(sock_fd4);
|
||||
close(sock_fd4);
|
||||
}
|
||||
sock_fd4 = -1;
|
||||
#ifdef HAVE_IPV6
|
||||
if (sock_fd6 >= 0) {
|
||||
SCH_RemoveInputFileHandler(sock_fd6);
|
||||
close(sock_fd6);
|
||||
}
|
||||
sock_fd6 = -1;
|
||||
if (server_sock_fd4 != client_sock_fd4)
|
||||
close_socket(client_sock_fd4);
|
||||
close_socket(server_sock_fd4);
|
||||
server_sock_fd4 = client_sock_fd4 = INVALID_SOCK_FD;
|
||||
#ifdef FEAT_IPV6
|
||||
if (server_sock_fd6 != client_sock_fd6)
|
||||
close_socket(client_sock_fd6);
|
||||
close_socket(server_sock_fd6);
|
||||
server_sock_fd6 = client_sock_fd6 = INVALID_SOCK_FD;
|
||||
#endif
|
||||
initialised = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
NIO_OpenClientSocket(NTP_Remote_Address *remote_addr)
|
||||
{
|
||||
if (separate_client_sockets) {
|
||||
int sock_fd = prepare_separate_client_socket(remote_addr->ip_addr.family);
|
||||
|
||||
if (sock_fd == INVALID_SOCK_FD)
|
||||
return INVALID_SOCK_FD;
|
||||
|
||||
if (!connect_socket(sock_fd, remote_addr)) {
|
||||
close_socket(sock_fd);
|
||||
return INVALID_SOCK_FD;
|
||||
}
|
||||
|
||||
return sock_fd;
|
||||
} else {
|
||||
switch (remote_addr->ip_addr.family) {
|
||||
case IPADDR_INET4:
|
||||
return client_sock_fd4;
|
||||
#ifdef FEAT_IPV6
|
||||
case IPADDR_INET6:
|
||||
return client_sock_fd6;
|
||||
#endif
|
||||
default:
|
||||
return INVALID_SOCK_FD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
NIO_OpenServerSocket(NTP_Remote_Address *remote_addr)
|
||||
{
|
||||
switch (remote_addr->ip_addr.family) {
|
||||
case IPADDR_INET4:
|
||||
if (permanent_server_sockets)
|
||||
return server_sock_fd4;
|
||||
if (server_sock_fd4 == INVALID_SOCK_FD)
|
||||
server_sock_fd4 = prepare_socket(AF_INET, CNF_GetNTPPort(), 0);
|
||||
if (server_sock_fd4 != INVALID_SOCK_FD)
|
||||
server_sock_ref4++;
|
||||
return server_sock_fd4;
|
||||
#ifdef FEAT_IPV6
|
||||
case IPADDR_INET6:
|
||||
if (permanent_server_sockets)
|
||||
return server_sock_fd6;
|
||||
if (server_sock_fd6 == INVALID_SOCK_FD)
|
||||
server_sock_fd6 = prepare_socket(AF_INET6, CNF_GetNTPPort(), 0);
|
||||
if (server_sock_fd6 != INVALID_SOCK_FD)
|
||||
server_sock_ref6++;
|
||||
return server_sock_fd6;
|
||||
#endif
|
||||
default:
|
||||
return INVALID_SOCK_FD;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
NIO_CloseClientSocket(int sock_fd)
|
||||
{
|
||||
if (separate_client_sockets)
|
||||
close_socket(sock_fd);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
NIO_CloseServerSocket(int sock_fd)
|
||||
{
|
||||
if (permanent_server_sockets || sock_fd == INVALID_SOCK_FD)
|
||||
return;
|
||||
|
||||
if (sock_fd == server_sock_fd4) {
|
||||
if (--server_sock_ref4 <= 0) {
|
||||
close_socket(server_sock_fd4);
|
||||
server_sock_fd4 = INVALID_SOCK_FD;
|
||||
}
|
||||
}
|
||||
#ifdef FEAT_IPV6
|
||||
else if (sock_fd == server_sock_fd6) {
|
||||
if (--server_sock_ref6 <= 0) {
|
||||
close_socket(server_sock_fd6);
|
||||
server_sock_fd6 = INVALID_SOCK_FD;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
NIO_IsServerSocket(int sock_fd)
|
||||
{
|
||||
return sock_fd != INVALID_SOCK_FD &&
|
||||
(sock_fd == server_sock_fd4
|
||||
#ifdef FEAT_IPV6
|
||||
|| sock_fd == server_sock_fd6
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
@@ -277,11 +487,13 @@ read_from_socket(void *anything)
|
||||
to read, otherwise it will block. */
|
||||
|
||||
int status, sock_fd;
|
||||
ReceiveBuffer message;
|
||||
NTP_Receive_Buffer message;
|
||||
union sockaddr_in46 where_from;
|
||||
unsigned int flags = 0;
|
||||
struct timeval now;
|
||||
double now_err;
|
||||
NTP_Remote_Address remote_addr;
|
||||
NTP_Local_Address local_addr;
|
||||
char cmsgbuf[256];
|
||||
struct msghdr msg;
|
||||
struct iovec iov;
|
||||
@@ -289,9 +501,9 @@ read_from_socket(void *anything)
|
||||
|
||||
assert(initialised);
|
||||
|
||||
SCH_GetFileReadyTime(&now);
|
||||
SCH_GetLastEventTime(&now, &now_err, NULL);
|
||||
|
||||
iov.iov_base = message.arbitrary;
|
||||
iov.iov_base = &message.ntp_pkt;
|
||||
iov.iov_len = sizeof(message);
|
||||
msg.msg_name = &where_from;
|
||||
msg.msg_namelen = sizeof(where_from);
|
||||
@@ -312,61 +524,54 @@ read_from_socket(void *anything)
|
||||
reponse on a subsequent recvfrom). */
|
||||
|
||||
if (status > 0) {
|
||||
memset(&remote_addr, 0, sizeof (remote_addr));
|
||||
if (msg.msg_namelen > sizeof (where_from))
|
||||
LOG_FATAL(LOGF_NtpIO, "Truncated source address");
|
||||
|
||||
switch (where_from.u.sa_family) {
|
||||
case AF_INET:
|
||||
remote_addr.ip_addr.family = IPADDR_INET4;
|
||||
remote_addr.ip_addr.addr.in4 = ntohl(where_from.in4.sin_addr.s_addr);
|
||||
remote_addr.port = ntohs(where_from.in4.sin_port);
|
||||
break;
|
||||
#ifdef HAVE_IPV6
|
||||
case AF_INET6:
|
||||
remote_addr.ip_addr.family = IPADDR_INET6;
|
||||
memcpy(&remote_addr.ip_addr.addr.in6, where_from.in6.sin6_addr.s6_addr,
|
||||
sizeof (remote_addr.ip_addr.addr.in6));
|
||||
remote_addr.port = ntohs(where_from.in6.sin6_port);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
UTI_SockaddrToIPAndPort(&where_from.u, &remote_addr.ip_addr, &remote_addr.port);
|
||||
|
||||
local_addr.ip_addr.family = IPADDR_UNSPEC;
|
||||
local_addr.sock_fd = sock_fd;
|
||||
|
||||
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
||||
#ifdef IP_PKTINFO
|
||||
#ifdef HAVE_IN_PKTINFO
|
||||
if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
|
||||
struct in_pktinfo ipi;
|
||||
|
||||
memcpy(&ipi, CMSG_DATA(cmsg), sizeof(ipi));
|
||||
remote_addr.local_ip_addr.addr.in4 = ntohl(ipi.ipi_spec_dst.s_addr);
|
||||
remote_addr.local_ip_addr.family = IPADDR_INET4;
|
||||
local_addr.ip_addr.addr.in4 = ntohl(ipi.ipi_spec_dst.s_addr);
|
||||
local_addr.ip_addr.family = IPADDR_INET4;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IN6_PKTINFO
|
||||
if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
|
||||
struct in6_pktinfo ipi;
|
||||
|
||||
memcpy(&ipi, CMSG_DATA(cmsg), sizeof(ipi));
|
||||
memcpy(&local_addr.ip_addr.addr.in6, &ipi.ipi6_addr.s6_addr,
|
||||
sizeof (local_addr.ip_addr.addr.in6));
|
||||
local_addr.ip_addr.family = IPADDR_INET6;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SO_TIMESTAMP
|
||||
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP) {
|
||||
struct timeval tv;
|
||||
double correction;
|
||||
|
||||
memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv));
|
||||
correction = LCL_GetOffsetCorrection(&tv);
|
||||
UTI_AddDoubleToTimeval(&tv, correction, &tv);
|
||||
#if 0
|
||||
UTI_DiffTimevalsToDouble(&correction, &now, &tv);
|
||||
LOG(LOGS_INFO, LOGF_NtpIO, "timestamp diff: %f", correction);
|
||||
#endif
|
||||
now = tv;
|
||||
LCL_CookTime(&tv, &now, &now_err);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (status == NTP_NORMAL_PACKET_SIZE) {
|
||||
DEBUG_LOG(LOGF_NtpIO, "Received %d bytes from %s:%d to %s fd %d",
|
||||
status, UTI_IPToString(&remote_addr.ip_addr), remote_addr.port,
|
||||
UTI_IPToString(&local_addr.ip_addr), local_addr.sock_fd);
|
||||
|
||||
NSR_ProcessReceive((NTP_Packet *) &message.ntp_pkt, &now, &remote_addr);
|
||||
if (status >= NTP_NORMAL_PACKET_LENGTH) {
|
||||
|
||||
} else if (status == sizeof(NTP_Packet)) {
|
||||
|
||||
NSR_ProcessAuthenticatedReceive((NTP_Packet *) &message.ntp_pkt, &now, &remote_addr);
|
||||
NSR_ProcessReceive((NTP_Packet *) &message.ntp_pkt, &now, now_err,
|
||||
&remote_addr, &local_addr, status);
|
||||
|
||||
} else {
|
||||
|
||||
@@ -374,57 +579,51 @@ read_from_socket(void *anything)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
/* Send a packet to given address */
|
||||
/* Send a packet to remote address from local address */
|
||||
|
||||
static void
|
||||
send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
|
||||
static int
|
||||
send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr)
|
||||
{
|
||||
union sockaddr_in46 remote;
|
||||
struct msghdr msg;
|
||||
struct iovec iov;
|
||||
char cmsgbuf[256];
|
||||
int cmsglen;
|
||||
int sock_fd;
|
||||
socklen_t addrlen;
|
||||
socklen_t addrlen = 0;
|
||||
|
||||
assert(initialised);
|
||||
|
||||
switch (remote_addr->ip_addr.family) {
|
||||
case IPADDR_INET4:
|
||||
memset(&remote.in4, 0, sizeof (remote.in4));
|
||||
addrlen = sizeof (remote.in4);
|
||||
remote.in4.sin_family = AF_INET;
|
||||
remote.in4.sin_port = htons(remote_addr->port);
|
||||
remote.in4.sin_addr.s_addr = htonl(remote_addr->ip_addr.addr.in4);
|
||||
sock_fd = sock_fd4;
|
||||
break;
|
||||
#ifdef HAVE_IPV6
|
||||
case IPADDR_INET6:
|
||||
memset(&remote.in6, 0, sizeof (remote.in6));
|
||||
addrlen = sizeof (remote.in6);
|
||||
remote.in6.sin6_family = AF_INET6;
|
||||
remote.in6.sin6_port = htons(remote_addr->port);
|
||||
memcpy(&remote.in6.sin6_addr.s6_addr, &remote_addr->ip_addr.addr.in6,
|
||||
sizeof (remote.in6.sin6_addr.s6_addr));
|
||||
sock_fd = sock_fd6;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return;
|
||||
if (local_addr->sock_fd == INVALID_SOCK_FD) {
|
||||
DEBUG_LOG(LOGF_NtpIO, "No socket to send to %s:%d",
|
||||
UTI_IPToString(&remote_addr->ip_addr), remote_addr->port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sock_fd < 0)
|
||||
return;
|
||||
/* Don't set address with connected socket */
|
||||
if (local_addr->sock_fd == server_sock_fd4 ||
|
||||
#ifdef FEAT_IPV6
|
||||
local_addr->sock_fd == server_sock_fd6 ||
|
||||
#endif
|
||||
!separate_client_sockets) {
|
||||
addrlen = UTI_IPAndPortToSockaddr(&remote_addr->ip_addr, remote_addr->port,
|
||||
&remote.u);
|
||||
if (!addrlen)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (addrlen) {
|
||||
msg.msg_name = &remote.u;
|
||||
msg.msg_namelen = addrlen;
|
||||
} else {
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
}
|
||||
|
||||
iov.iov_base = packet;
|
||||
iov.iov_len = packetlen;
|
||||
msg.msg_name = &remote.u;
|
||||
msg.msg_namelen = addrlen;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = cmsgbuf;
|
||||
@@ -432,8 +631,8 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
|
||||
msg.msg_flags = 0;
|
||||
cmsglen = 0;
|
||||
|
||||
#ifdef IP_PKTINFO
|
||||
if (remote_addr->local_ip_addr.family == IPADDR_INET4) {
|
||||
#ifdef HAVE_IN_PKTINFO
|
||||
if (local_addr->ip_addr.family == IPADDR_INET4) {
|
||||
struct cmsghdr *cmsg;
|
||||
struct in_pktinfo *ipi;
|
||||
|
||||
@@ -446,13 +645,27 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
|
||||
|
||||
ipi = (struct in_pktinfo *) CMSG_DATA(cmsg);
|
||||
ipi->ipi_spec_dst.s_addr = htonl(remote_addr->local_ip_addr.addr.in4);
|
||||
ipi->ipi_spec_dst.s_addr = htonl(local_addr->ip_addr.addr.in4);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
LOG(LOGS_INFO, LOGF_NtpIO, "sending to %s:%d from %s",
|
||||
UTI_IPToString(&remote_addr->ip_addr), remote_addr->port, UTI_IPToString(&remote_addr->local_ip_addr));
|
||||
#ifdef HAVE_IN6_PKTINFO
|
||||
if (local_addr->ip_addr.family == IPADDR_INET6) {
|
||||
struct cmsghdr *cmsg;
|
||||
struct in6_pktinfo *ipi;
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
memset(cmsg, 0, CMSG_SPACE(sizeof(struct in6_pktinfo)));
|
||||
cmsglen += CMSG_SPACE(sizeof(struct in6_pktinfo));
|
||||
|
||||
cmsg->cmsg_level = IPPROTO_IPV6;
|
||||
cmsg->cmsg_type = IPV6_PKTINFO;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
|
||||
|
||||
ipi = (struct in6_pktinfo *) CMSG_DATA(cmsg);
|
||||
memcpy(&ipi->ipi6_addr.s6_addr, &local_addr->ip_addr.addr.in6,
|
||||
sizeof(ipi->ipi6_addr.s6_addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
msg.msg_controllen = cmsglen;
|
||||
@@ -460,45 +673,26 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
|
||||
if (!cmsglen)
|
||||
msg.msg_control = NULL;
|
||||
|
||||
if (sendmsg(sock_fd, &msg, 0) < 0) {
|
||||
LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s",
|
||||
UTI_IPToString(&remote_addr->ip_addr), remote_addr->port, strerror(errno));
|
||||
if (sendmsg(local_addr->sock_fd, &msg, 0) < 0) {
|
||||
DEBUG_LOG(LOGF_NtpIO, "Could not send to %s:%d from %s fd %d : %s",
|
||||
UTI_IPToString(&remote_addr->ip_addr), remote_addr->port,
|
||||
UTI_IPToString(&local_addr->ip_addr), local_addr->sock_fd,
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return;
|
||||
DEBUG_LOG(LOGF_NtpIO, "Sent %d bytes to %s:%d from %s fd %d", packetlen,
|
||||
UTI_IPToString(&remote_addr->ip_addr), remote_addr->port,
|
||||
UTI_IPToString(&local_addr->ip_addr), local_addr->sock_fd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
/* Send an unauthenticated packet to a given address */
|
||||
/* Send a packet to a given address */
|
||||
|
||||
void
|
||||
NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
|
||||
int
|
||||
NIO_SendPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length)
|
||||
{
|
||||
send_packet((void *) packet, NTP_NORMAL_PACKET_SIZE, remote_addr);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
/* Send an authenticated packet to a given address */
|
||||
|
||||
void
|
||||
NIO_SendAuthenticatedPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
|
||||
{
|
||||
send_packet((void *) packet, sizeof(NTP_Packet), remote_addr);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
/* We ought to use getservbyname, but I can't really see this changing */
|
||||
#define ECHO_PORT 7
|
||||
|
||||
void
|
||||
NIO_SendEcho(NTP_Remote_Address *remote_addr)
|
||||
{
|
||||
unsigned long magic_message = 0xbe7ab1e7UL;
|
||||
NTP_Remote_Address addr;
|
||||
|
||||
addr = *remote_addr;
|
||||
addr.port = ECHO_PORT;
|
||||
|
||||
send_packet((void *) &magic_message, sizeof(unsigned long), &addr);
|
||||
return send_packet((void *) packet, length, remote_addr, local_addr);
|
||||
}
|
||||
|
||||
30
ntp_io.h
30
ntp_io.h
@@ -1,12 +1,9 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/ntp_io.h,v 1.9 2002/02/28 23:27:12 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2002
|
||||
* Copyright (C) Miroslav Lichvar 2014
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -36,18 +33,27 @@
|
||||
#include "addressing.h"
|
||||
|
||||
/* Function to initialise the module. */
|
||||
extern void NIO_Initialise(void);
|
||||
extern void NIO_Initialise(int family);
|
||||
|
||||
/* Function to finalise the module */
|
||||
extern void NIO_Finalise(void);
|
||||
|
||||
/* Function to obtain a socket for sending client packets */
|
||||
extern int NIO_OpenClientSocket(NTP_Remote_Address *remote_addr);
|
||||
|
||||
/* Function to obtain a socket for sending server/peer packets */
|
||||
extern int NIO_OpenServerSocket(NTP_Remote_Address *remote_addr);
|
||||
|
||||
/* Function to close a socket returned by NIO_OpenClientSocket() */
|
||||
extern void NIO_CloseClientSocket(int sock_fd);
|
||||
|
||||
/* Function to close a socket returned by NIO_OpenServerSocket() */
|
||||
extern void NIO_CloseServerSocket(int sock_fd);
|
||||
|
||||
/* Function to check if socket is a server socket */
|
||||
extern int NIO_IsServerSocket(int sock_fd);
|
||||
|
||||
/* Function to transmit a packet */
|
||||
extern void NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr);
|
||||
|
||||
/* Function to transmit an authenticated packet */
|
||||
extern void NIO_SendAuthenticatedPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr);
|
||||
|
||||
/* Function to send a datagram to a remote machine's UDP echo port. */
|
||||
extern void NIO_SendEcho(NTP_Remote_Address *remote_addr);
|
||||
extern int NIO_SendPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length);
|
||||
|
||||
#endif /* GOT_NTP_IO_H */
|
||||
|
||||
886
ntp_sources.c
886
ntp_sources.c
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,9 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/ntp_sources.h,v 1.12 2002/02/28 23:27:12 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2002
|
||||
* Copyright (C) Miroslav Lichvar 2014
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -45,27 +42,49 @@
|
||||
typedef enum {
|
||||
NSR_Success, /* Operation successful */
|
||||
NSR_NoSuchSource, /* Remove - attempt to remove a source that is not known */
|
||||
NSR_AlreadyInUse, /* AddServer, AddPeer - attempt to add a source that is already known */
|
||||
NSR_TooManySources, /* AddServer, AddPeer - too many sources already present */
|
||||
NSR_InvalidAF /* AddServer, AddPeer - attempt to add a source with invalid address family */
|
||||
NSR_AlreadyInUse, /* AddSource - attempt to add a source that is already known */
|
||||
NSR_TooManySources, /* AddSource - too many sources already present */
|
||||
NSR_InvalidAF /* AddSource - attempt to add a source with invalid address family */
|
||||
} NSR_Status;
|
||||
|
||||
/* Procedure to add a new server source (to which this machine will be
|
||||
a client) */
|
||||
extern NSR_Status NSR_AddServer(NTP_Remote_Address *remote_addr, SourceParameters *params);
|
||||
/* Procedure to add a new server or peer source. */
|
||||
extern NSR_Status NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParameters *params);
|
||||
|
||||
/* Procedure to add a new peer source. We will use symmetric active
|
||||
mode packets when communicating with this source */
|
||||
extern NSR_Status NSR_AddPeer(NTP_Remote_Address *remote_addr, SourceParameters *params);
|
||||
/* Procedure to add a new server, peer source, or pool of servers specified by
|
||||
name instead of address. The name is resolved in exponentially increasing
|
||||
intervals until it succeeds or fails with a non-temporary error. */
|
||||
extern void NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type, SourceParameters *params);
|
||||
|
||||
/* Function type for handlers to be called back when an attempt
|
||||
* (possibly unsuccessful) to resolve unresolved sources ends */
|
||||
typedef void (*NSR_SourceResolvingEndHandler)(void);
|
||||
|
||||
/* Set the handler, or NULL to disable the notification */
|
||||
extern void NSR_SetSourceResolvingEndHandler(NSR_SourceResolvingEndHandler handler);
|
||||
|
||||
/* Procedure to start resolving unresolved sources */
|
||||
extern void NSR_ResolveSources(void);
|
||||
|
||||
/* Procedure to start all sources */
|
||||
extern void NSR_StartSources(void);
|
||||
|
||||
/* Start new sources automatically */
|
||||
extern void NSR_AutoStartSources(void);
|
||||
|
||||
/* Procedure to remove a source */
|
||||
extern NSR_Status NSR_RemoveSource(NTP_Remote_Address *remote_addr);
|
||||
|
||||
/* This routine is called by ntp_io when a new packet arrives off the network */
|
||||
extern void NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, NTP_Remote_Address *remote_addr);
|
||||
/* Procedure to remove all sources */
|
||||
extern void NSR_RemoveAllSources(void);
|
||||
|
||||
/* This routine is called by ntp_io when a new packet with an authentication tail arrives off the network */
|
||||
extern void NSR_ProcessAuthenticatedReceive(NTP_Packet *message, struct timeval *now, NTP_Remote_Address *remote_addr);
|
||||
/* Procedure to try to find a replacement for a bad source */
|
||||
extern void NSR_HandleBadSource(IPAddr *address);
|
||||
|
||||
/* Procedure to resolve all names again */
|
||||
extern void NSR_RefreshAddresses(void);
|
||||
|
||||
/* This routine is called by ntp_io when a new packet arrives off the network */
|
||||
extern void NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, double now_err, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length);
|
||||
|
||||
/* Initialisation function */
|
||||
extern void NSR_Initialise(void);
|
||||
@@ -91,6 +110,12 @@ extern int NSR_ModifyMaxdelay(IPAddr *address, double new_max_delay);
|
||||
|
||||
extern int NSR_ModifyMaxdelayratio(IPAddr *address, double new_max_delay_ratio);
|
||||
|
||||
extern int NSR_ModifyMaxdelaydevratio(IPAddr *address, double new_max_delay_ratio);
|
||||
|
||||
extern int NSR_ModifyMinstratum(IPAddr *address, int new_min_stratum);
|
||||
|
||||
extern int NSR_ModifyPolltarget(IPAddr *address, int new_poll_target);
|
||||
|
||||
extern int NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples, IPAddr *mask, IPAddr *address);
|
||||
|
||||
extern void NSR_ReportSource(RPT_SourceReport *report, struct timeval *now);
|
||||
|
||||
243
pktlength.c
243
pktlength.c
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/pktlength.c,v 1.12 2002/02/28 23:27:12 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
@@ -30,6 +26,8 @@
|
||||
integer endianness within the structures.
|
||||
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "util.h"
|
||||
@@ -37,8 +35,8 @@
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
PKL_CommandLength(CMD_Request *r)
|
||||
static int
|
||||
command_unpadded_length(CMD_Request *r)
|
||||
{
|
||||
int type;
|
||||
type = ntohs(r->command);
|
||||
@@ -46,9 +44,8 @@ PKL_CommandLength(CMD_Request *r)
|
||||
return 0;
|
||||
} else {
|
||||
switch (type) {
|
||||
|
||||
case REQ_NULL:
|
||||
return offsetof(CMD_Request, data);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_ONLINE:
|
||||
return offsetof(CMD_Request, data.online.EOR);
|
||||
case REQ_OFFLINE:
|
||||
@@ -65,8 +62,12 @@ PKL_CommandLength(CMD_Request *r)
|
||||
return offsetof(CMD_Request, data.modify_maxdelay.EOR);
|
||||
case REQ_MODIFY_MAXDELAYRATIO:
|
||||
return offsetof(CMD_Request, data.modify_maxdelayratio.EOR);
|
||||
case REQ_MODIFY_MAXDELAYDEVRATIO:
|
||||
return offsetof(CMD_Request, data.modify_maxdelaydevratio.EOR);
|
||||
case REQ_MODIFY_MAXUPDATESKEW:
|
||||
return offsetof(CMD_Request, data.modify_maxupdateskew.EOR);
|
||||
case REQ_MODIFY_MAKESTEP:
|
||||
return offsetof(CMD_Request, data.modify_makestep.EOR);
|
||||
case REQ_LOGON :
|
||||
return offsetof(CMD_Request, data.logon.EOR);
|
||||
case REQ_SETTIME :
|
||||
@@ -76,11 +77,11 @@ PKL_CommandLength(CMD_Request *r)
|
||||
case REQ_MANUAL :
|
||||
return offsetof(CMD_Request, data.manual.EOR);
|
||||
case REQ_N_SOURCES :
|
||||
return offsetof(CMD_Request, data.n_sources.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_SOURCE_DATA :
|
||||
return offsetof(CMD_Request, data.source_data.EOR);
|
||||
case REQ_REKEY :
|
||||
return offsetof(CMD_Request, data.rekey.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_ALLOW :
|
||||
return offsetof(CMD_Request, data.allow_deny.EOR);
|
||||
case REQ_ALLOWALL :
|
||||
@@ -108,45 +109,49 @@ PKL_CommandLength(CMD_Request *r)
|
||||
case REQ_DEL_SOURCE :
|
||||
return offsetof(CMD_Request, data.del_source.EOR);
|
||||
case REQ_WRITERTC :
|
||||
return offsetof(CMD_Request, data.writertc.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_DFREQ :
|
||||
return offsetof(CMD_Request, data.dfreq.EOR);
|
||||
case REQ_DOFFSET :
|
||||
return offsetof(CMD_Request, data.doffset.EOR);
|
||||
case REQ_TRACKING :
|
||||
return offsetof(CMD_Request, data.tracking.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_SOURCESTATS :
|
||||
return offsetof(CMD_Request, data.sourcestats.EOR);
|
||||
case REQ_RTCREPORT :
|
||||
return offsetof(CMD_Request, data.rtcreport.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_TRIMRTC :
|
||||
return offsetof(CMD_Request, data.trimrtc.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_CYCLELOGS :
|
||||
return offsetof(CMD_Request, data.cyclelogs.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_SUBNETS_ACCESSED :
|
||||
{
|
||||
unsigned long ns;
|
||||
ns = ntohl(r->data.subnets_accessed.n_subnets);
|
||||
return (offsetof(CMD_Request, data.subnets_accessed.subnets) +
|
||||
ns * sizeof(REQ_SubnetsAccessed_Subnet));
|
||||
}
|
||||
case REQ_CLIENT_ACCESSES:
|
||||
{
|
||||
unsigned long nc;
|
||||
nc = ntohl(r->data.client_accesses.n_clients);
|
||||
return (offsetof(CMD_Request, data.client_accesses.client_ips) +
|
||||
nc * sizeof(unsigned long));
|
||||
}
|
||||
/* No longer supported */
|
||||
return 0;
|
||||
case REQ_CLIENT_ACCESSES_BY_INDEX:
|
||||
return offsetof(CMD_Request, data.client_accesses_by_index.EOR);
|
||||
case REQ_MANUAL_LIST:
|
||||
return offsetof(CMD_Request, data.manual_list.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_MANUAL_DELETE:
|
||||
return offsetof(CMD_Request, data.manual_delete.EOR);
|
||||
case REQ_MAKESTEP:
|
||||
return offsetof(CMD_Request, data.make_step.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_ACTIVITY:
|
||||
return offsetof(CMD_Request, data.activity.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_RESELECT:
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_RESELECTDISTANCE:
|
||||
return offsetof(CMD_Request, data.reselect_distance.EOR);
|
||||
case REQ_MODIFY_MINSTRATUM:
|
||||
return offsetof(CMD_Request, data.modify_minstratum.EOR);
|
||||
case REQ_MODIFY_POLLTARGET:
|
||||
return offsetof(CMD_Request, data.modify_polltarget.EOR);
|
||||
case REQ_SMOOTHING:
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_SMOOTHTIME:
|
||||
return offsetof(CMD_Request, data.smoothtime.EOR);
|
||||
case REQ_REFRESH:
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
default:
|
||||
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */
|
||||
assert(0);
|
||||
@@ -159,6 +164,157 @@ PKL_CommandLength(CMD_Request *r)
|
||||
}
|
||||
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
PKL_CommandLength(CMD_Request *r)
|
||||
{
|
||||
int command_length;
|
||||
|
||||
command_length = command_unpadded_length(r);
|
||||
if (!command_length)
|
||||
return 0;
|
||||
|
||||
return command_length + PKL_CommandPaddingLength(r);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
#define PADDING_LENGTH_(request_length, reply_length) \
|
||||
((request_length) < (reply_length) ? (reply_length) - (request_length) : 0)
|
||||
|
||||
#define PADDING_LENGTH(request_data, reply_data) \
|
||||
PADDING_LENGTH_(offsetof(CMD_Request, request_data), offsetof(CMD_Reply, reply_data))
|
||||
|
||||
int
|
||||
PKL_CommandPaddingLength(CMD_Request *r)
|
||||
{
|
||||
int type;
|
||||
|
||||
if (r->version < PROTO_VERSION_PADDING)
|
||||
return 0;
|
||||
|
||||
type = ntohs(r->command);
|
||||
|
||||
if (type < 0 || type >= N_REQUEST_TYPES)
|
||||
return 0;
|
||||
|
||||
switch (type) {
|
||||
case REQ_NULL:
|
||||
return PADDING_LENGTH(data, data.null.EOR);
|
||||
case REQ_ONLINE:
|
||||
return PADDING_LENGTH(data.online.EOR, data.null.EOR);
|
||||
case REQ_OFFLINE:
|
||||
return PADDING_LENGTH(data.offline.EOR, data.null.EOR);
|
||||
case REQ_BURST:
|
||||
return PADDING_LENGTH(data.burst.EOR, data.null.EOR);
|
||||
case REQ_MODIFY_MINPOLL:
|
||||
return PADDING_LENGTH(data.modify_minpoll.EOR, data.null.EOR);
|
||||
case REQ_MODIFY_MAXPOLL:
|
||||
return PADDING_LENGTH(data.modify_maxpoll.EOR, data.null.EOR);
|
||||
case REQ_DUMP:
|
||||
return PADDING_LENGTH(data.dump.EOR, data.null.EOR);
|
||||
case REQ_MODIFY_MAXDELAY:
|
||||
return PADDING_LENGTH(data.modify_maxdelay.EOR, data.null.EOR);
|
||||
case REQ_MODIFY_MAXDELAYRATIO:
|
||||
return PADDING_LENGTH(data.modify_maxdelayratio.EOR, data.null.EOR);
|
||||
case REQ_MODIFY_MAXDELAYDEVRATIO:
|
||||
return PADDING_LENGTH(data.modify_maxdelaydevratio.EOR, data.null.EOR);
|
||||
case REQ_MODIFY_MAXUPDATESKEW:
|
||||
return PADDING_LENGTH(data.modify_maxupdateskew.EOR, data.null.EOR);
|
||||
case REQ_MODIFY_MAKESTEP:
|
||||
return PADDING_LENGTH(data.modify_makestep.EOR, data.null.EOR);
|
||||
case REQ_LOGON:
|
||||
return PADDING_LENGTH(data.logon.EOR, data.null.EOR);
|
||||
case REQ_SETTIME:
|
||||
return PADDING_LENGTH(data.settime.EOR, data.manual_timestamp.EOR);
|
||||
case REQ_LOCAL:
|
||||
return PADDING_LENGTH(data.local.EOR, data.null.EOR);
|
||||
case REQ_MANUAL:
|
||||
return PADDING_LENGTH(data.manual.EOR, data.null.EOR);
|
||||
case REQ_N_SOURCES:
|
||||
return PADDING_LENGTH(data.null.EOR, data.n_sources.EOR);
|
||||
case REQ_SOURCE_DATA:
|
||||
return PADDING_LENGTH(data.source_data.EOR, data.source_data.EOR);
|
||||
case REQ_REKEY:
|
||||
return PADDING_LENGTH(data.null.EOR, data.null.EOR);
|
||||
case REQ_ALLOW:
|
||||
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
||||
case REQ_ALLOWALL:
|
||||
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
||||
case REQ_DENY:
|
||||
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
||||
case REQ_DENYALL:
|
||||
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
||||
case REQ_CMDALLOW:
|
||||
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
||||
case REQ_CMDALLOWALL:
|
||||
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
||||
case REQ_CMDDENY:
|
||||
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
||||
case REQ_CMDDENYALL:
|
||||
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
||||
case REQ_ACCHECK:
|
||||
return PADDING_LENGTH(data.ac_check.EOR, data.null.EOR);
|
||||
case REQ_CMDACCHECK:
|
||||
return PADDING_LENGTH(data.ac_check.EOR, data.null.EOR);
|
||||
case REQ_ADD_SERVER:
|
||||
return PADDING_LENGTH(data.ntp_source.EOR, data.null.EOR);
|
||||
case REQ_ADD_PEER:
|
||||
return PADDING_LENGTH(data.ntp_source.EOR, data.null.EOR);
|
||||
case REQ_DEL_SOURCE:
|
||||
return PADDING_LENGTH(data.del_source.EOR, data.null.EOR);
|
||||
case REQ_WRITERTC:
|
||||
return PADDING_LENGTH(data.null.EOR, data.null.EOR);
|
||||
case REQ_DFREQ:
|
||||
return PADDING_LENGTH(data.dfreq.EOR, data.null.EOR);
|
||||
case REQ_DOFFSET:
|
||||
return PADDING_LENGTH(data.doffset.EOR, data.null.EOR);
|
||||
case REQ_TRACKING:
|
||||
return PADDING_LENGTH(data.null.EOR, data.tracking.EOR);
|
||||
case REQ_SOURCESTATS:
|
||||
return PADDING_LENGTH(data.sourcestats.EOR, data.sourcestats.EOR);
|
||||
case REQ_RTCREPORT:
|
||||
return PADDING_LENGTH(data.null.EOR, data.rtc.EOR);
|
||||
case REQ_TRIMRTC:
|
||||
return PADDING_LENGTH(data.null.EOR, data.null.EOR);
|
||||
case REQ_CYCLELOGS:
|
||||
return PADDING_LENGTH(data.null.EOR, data.null.EOR);
|
||||
case REQ_SUBNETS_ACCESSED:
|
||||
case REQ_CLIENT_ACCESSES:
|
||||
/* No longer supported */
|
||||
return 0;
|
||||
case REQ_CLIENT_ACCESSES_BY_INDEX:
|
||||
return PADDING_LENGTH(data.client_accesses_by_index.EOR, data.client_accesses_by_index.EOR);
|
||||
case REQ_MANUAL_LIST:
|
||||
return PADDING_LENGTH(data.null.EOR, data.manual_list.EOR);
|
||||
case REQ_MANUAL_DELETE:
|
||||
return PADDING_LENGTH(data.manual_delete.EOR, data.null.EOR);
|
||||
case REQ_MAKESTEP:
|
||||
return PADDING_LENGTH(data.null.EOR, data.null.EOR);
|
||||
case REQ_ACTIVITY:
|
||||
return PADDING_LENGTH(data.null.EOR, data.activity.EOR);
|
||||
case REQ_RESELECT:
|
||||
return PADDING_LENGTH(data.null.EOR, data.null.EOR);
|
||||
case REQ_RESELECTDISTANCE:
|
||||
return PADDING_LENGTH(data.reselect_distance.EOR, data.null.EOR);
|
||||
case REQ_MODIFY_MINSTRATUM:
|
||||
return PADDING_LENGTH(data.modify_minstratum.EOR, data.null.EOR);
|
||||
case REQ_MODIFY_POLLTARGET:
|
||||
return PADDING_LENGTH(data.modify_polltarget.EOR, data.null.EOR);
|
||||
case REQ_SMOOTHING:
|
||||
return PADDING_LENGTH(data.null.EOR, data.smoothing.EOR);
|
||||
case REQ_SMOOTHTIME:
|
||||
return PADDING_LENGTH(data.smoothtime.EOR, data.null.EOR);
|
||||
case REQ_REFRESH:
|
||||
return PADDING_LENGTH(data.null.EOR, data.null.EOR);
|
||||
default:
|
||||
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
@@ -186,29 +342,15 @@ PKL_ReplyLength(CMD_Reply *r)
|
||||
case RPY_RTC:
|
||||
return offsetof(CMD_Reply, data.rtc.EOR);
|
||||
case RPY_SUBNETS_ACCESSED :
|
||||
{
|
||||
unsigned long ns = ntohl(r->data.subnets_accessed.n_subnets);
|
||||
if (r->status == htons(STT_SUCCESS)) {
|
||||
return (offsetof(CMD_Reply, data.subnets_accessed.subnets) +
|
||||
ns * sizeof(RPY_SubnetsAccessed_Subnet));
|
||||
} else {
|
||||
return offsetof(CMD_Reply, data);
|
||||
}
|
||||
}
|
||||
case RPY_CLIENT_ACCESSES:
|
||||
{
|
||||
unsigned long nc = ntohl(r->data.client_accesses.n_clients);
|
||||
if (r->status == htons(STT_SUCCESS)) {
|
||||
return (offsetof(CMD_Reply, data.client_accesses.clients) +
|
||||
nc * sizeof(RPY_ClientAccesses_Client));
|
||||
} else {
|
||||
return offsetof(CMD_Reply, data);
|
||||
}
|
||||
}
|
||||
/* No longer supported */
|
||||
return 0;
|
||||
case RPY_CLIENT_ACCESSES_BY_INDEX:
|
||||
{
|
||||
unsigned long nc = ntohl(r->data.client_accesses_by_index.n_clients);
|
||||
if (r->status == htons(STT_SUCCESS)) {
|
||||
if (nc > MAX_CLIENT_ACCESSES)
|
||||
return 0;
|
||||
return (offsetof(CMD_Reply, data.client_accesses_by_index.clients) +
|
||||
nc * sizeof(RPY_ClientAccesses_Client));
|
||||
} else {
|
||||
@@ -218,6 +360,8 @@ PKL_ReplyLength(CMD_Reply *r)
|
||||
case RPY_MANUAL_LIST:
|
||||
{
|
||||
unsigned long ns = ntohl(r->data.manual_list.n_samples);
|
||||
if (ns > MAX_MANUAL_LIST_SAMPLES)
|
||||
return 0;
|
||||
if (r->status == htons(STT_SUCCESS)) {
|
||||
return (offsetof(CMD_Reply, data.manual_list.samples) +
|
||||
ns * sizeof(RPY_ManualListSample));
|
||||
@@ -227,7 +371,8 @@ PKL_ReplyLength(CMD_Reply *r)
|
||||
}
|
||||
case RPY_ACTIVITY:
|
||||
return offsetof(CMD_Reply, data.activity.EOR);
|
||||
|
||||
case RPY_SMOOTHING:
|
||||
return offsetof(CMD_Reply, data.smoothing.EOR);
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
$Header: /cvs/src/chrony/pktlength.h,v 1.4 2002/02/28 23:27:12 richard Exp $
|
||||
|
||||
=======================================================================
|
||||
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
@@ -37,6 +33,8 @@
|
||||
|
||||
extern int PKL_CommandLength(CMD_Request *r);
|
||||
|
||||
extern int PKL_CommandPaddingLength(CMD_Request *r);
|
||||
|
||||
extern int PKL_ReplyLength(CMD_Reply *r);
|
||||
|
||||
#endif /* GOT_PKTLENGTH_H */
|
||||
|
||||
758
refclock.c
758
refclock.c
File diff suppressed because it is too large
Load Diff
15
refclock.h
15
refclock.h
@@ -32,15 +32,21 @@
|
||||
#include "sources.h"
|
||||
|
||||
typedef struct {
|
||||
char driver_name[4];
|
||||
char *driver_name;
|
||||
char *driver_parameter;
|
||||
int driver_poll;
|
||||
int poll;
|
||||
int filter_length;
|
||||
int pps_rate;
|
||||
unsigned long ref_id;
|
||||
int min_samples;
|
||||
int max_samples;
|
||||
uint32_t ref_id;
|
||||
uint32_t lock_ref_id;
|
||||
double offset;
|
||||
double delay;
|
||||
double precision;
|
||||
double max_dispersion;
|
||||
SRC_SelectOption sel_option;
|
||||
} RefclockParameters;
|
||||
|
||||
typedef struct RCL_Instance_Record *RCL_Instance;
|
||||
@@ -55,15 +61,14 @@ extern void RCL_Initialise(void);
|
||||
extern void RCL_Finalise(void);
|
||||
extern int RCL_AddRefclock(RefclockParameters *params);
|
||||
extern void RCL_StartRefclocks(void);
|
||||
extern void RCL_StartRefclocks(void);
|
||||
extern void RCL_ReportSource(RPT_SourceReport *report, struct timeval *now);
|
||||
extern void RCL_CycleLogFile(void);
|
||||
|
||||
/* functions used by drivers */
|
||||
extern void RCL_SetDriverData(RCL_Instance instance, void *data);
|
||||
extern void *RCL_GetDriverData(RCL_Instance instance);
|
||||
extern char *RCL_GetDriverParameter(RCL_Instance instance);
|
||||
extern int RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, NTP_Leap leap_status);
|
||||
extern char *RCL_GetDriverOption(RCL_Instance instance, char *name);
|
||||
extern int RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, int leap);
|
||||
extern int RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second);
|
||||
|
||||
#endif
|
||||
|
||||
193
refclock_phc.c
Normal file
193
refclock_phc.c
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Miroslav Lichvar 2013
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
=======================================================================
|
||||
|
||||
PTP hardware clock (PHC) refclock driver.
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "refclock.h"
|
||||
|
||||
#ifdef FEAT_PHC
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
#include <linux/ptp_clock.h>
|
||||
|
||||
#include "refclock.h"
|
||||
#include "logging.h"
|
||||
#include "util.h"
|
||||
|
||||
/* From linux/include/linux/posix-timers.h */
|
||||
#define CPUCLOCK_MAX 3
|
||||
#define CLOCKFD CPUCLOCK_MAX
|
||||
#define CLOCKFD_MASK (CPUCLOCK_PERTHREAD_MASK|CPUCLOCK_CLOCK_MASK)
|
||||
|
||||
#define FD_TO_CLOCKID(fd) ((~(clockid_t) (fd) << 3) | CLOCKFD)
|
||||
|
||||
#define NUM_READINGS 10
|
||||
|
||||
static int no_sys_offset_ioctl = 0;
|
||||
|
||||
struct phc_reading {
|
||||
struct timespec sys_ts1;
|
||||
struct timespec phc_ts;;
|
||||
struct timespec sys_ts2;
|
||||
};
|
||||
|
||||
static double diff_ts(struct timespec *ts1, struct timespec *ts2)
|
||||
{
|
||||
return (ts1->tv_sec - ts2->tv_sec) + (ts1->tv_nsec - ts2->tv_nsec) / 1e9;
|
||||
}
|
||||
|
||||
static int read_phc_ioctl(struct phc_reading *readings, int phc_fd, int n)
|
||||
{
|
||||
#if defined(PTP_SYS_OFFSET) && NUM_READINGS <= PTP_MAX_SAMPLES
|
||||
struct ptp_sys_offset sys_off;
|
||||
int i;
|
||||
|
||||
/* Silence valgrind */
|
||||
memset(&sys_off, 0, sizeof (sys_off));
|
||||
|
||||
sys_off.n_samples = n;
|
||||
if (ioctl(phc_fd, PTP_SYS_OFFSET, &sys_off)) {
|
||||
LOG(LOGS_ERR, LOGF_Refclock, "ioctl(PTP_SYS_OFFSET) failed : %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
readings[i].sys_ts1.tv_sec = sys_off.ts[i * 2].sec;
|
||||
readings[i].sys_ts1.tv_nsec = sys_off.ts[i * 2].nsec;
|
||||
readings[i].phc_ts.tv_sec = sys_off.ts[i * 2 + 1].sec;
|
||||
readings[i].phc_ts.tv_nsec = sys_off.ts[i * 2 + 1].nsec;
|
||||
readings[i].sys_ts2.tv_sec = sys_off.ts[i * 2 + 2].sec;
|
||||
readings[i].sys_ts2.tv_nsec = sys_off.ts[i * 2 + 2].nsec;
|
||||
}
|
||||
|
||||
return 1;
|
||||
#else
|
||||
/* Not available */
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int read_phc_user(struct phc_reading *readings, int phc_fd, int n)
|
||||
{
|
||||
clockid_t phc_id;
|
||||
int i;
|
||||
|
||||
phc_id = FD_TO_CLOCKID(phc_fd);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (clock_gettime(CLOCK_REALTIME, &readings[i].sys_ts1) ||
|
||||
clock_gettime(phc_id, &readings[i].phc_ts) ||
|
||||
clock_gettime(CLOCK_REALTIME, &readings[i].sys_ts2)) {
|
||||
LOG(LOGS_ERR, LOGF_Refclock, "clock_gettime() failed : %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int phc_initialise(RCL_Instance instance)
|
||||
{
|
||||
struct ptp_clock_caps caps;
|
||||
int phc_fd;
|
||||
char *path;
|
||||
|
||||
path = RCL_GetDriverParameter(instance);
|
||||
|
||||
phc_fd = open(path, O_RDONLY);
|
||||
if (phc_fd < 0) {
|
||||
LOG_FATAL(LOGF_Refclock, "open() failed on %s", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make sure it is a PHC */
|
||||
if (ioctl(phc_fd, PTP_CLOCK_GETCAPS, &caps)) {
|
||||
LOG_FATAL(LOGF_Refclock, "ioctl(PTP_CLOCK_GETCAPS) failed : %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
UTI_FdSetCloexec(phc_fd);
|
||||
|
||||
RCL_SetDriverData(instance, (void *)(long)phc_fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void phc_finalise(RCL_Instance instance)
|
||||
{
|
||||
close((long)RCL_GetDriverData(instance));
|
||||
}
|
||||
|
||||
static int phc_poll(RCL_Instance instance)
|
||||
{
|
||||
struct phc_reading readings[NUM_READINGS];
|
||||
struct timeval tv;
|
||||
double offset = 0.0, delay, best_delay = 0.0;
|
||||
int i, phc_fd, best;
|
||||
|
||||
phc_fd = (long)RCL_GetDriverData(instance);
|
||||
|
||||
if (!no_sys_offset_ioctl) {
|
||||
if (!read_phc_ioctl(readings, phc_fd, NUM_READINGS)) {
|
||||
no_sys_offset_ioctl = 1;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!read_phc_user(readings, phc_fd, NUM_READINGS))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find the fastest reading */
|
||||
for (i = 0; i < NUM_READINGS; i++) {
|
||||
delay = diff_ts(&readings[i].sys_ts2, &readings[i].sys_ts1);
|
||||
|
||||
if (!i || best_delay > delay) {
|
||||
best = i;
|
||||
best_delay = delay;
|
||||
}
|
||||
}
|
||||
|
||||
offset = diff_ts(&readings[best].phc_ts, &readings[best].sys_ts2) + best_delay / 2.0;
|
||||
tv.tv_sec = readings[best].sys_ts2.tv_sec;
|
||||
tv.tv_usec = readings[best].sys_ts2.tv_nsec / 1000;
|
||||
|
||||
DEBUG_LOG(LOGF_Refclock, "PHC offset: %+.9f delay: %.9f", offset, best_delay);
|
||||
|
||||
return RCL_AddSample(instance, &tv, offset, LEAP_Normal);
|
||||
}
|
||||
|
||||
RefclockDriver RCL_PHC_driver = {
|
||||
phc_initialise,
|
||||
phc_finalise,
|
||||
phc_poll
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
RefclockDriver RCL_PHC_driver = { NULL, NULL, NULL };
|
||||
|
||||
#endif
|
||||
@@ -25,11 +25,17 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "refclock.h"
|
||||
|
||||
#if HAVE_PPSAPI
|
||||
#if FEAT_PPS
|
||||
|
||||
#if defined(HAVE_SYS_TIMEPPS_H)
|
||||
#include <sys/timepps.h>
|
||||
#elif defined(HAVE_TIMEPPS_H)
|
||||
#include <timepps.h>
|
||||
#endif
|
||||
|
||||
#include "logging.h"
|
||||
#include "memory.h"
|
||||
@@ -46,15 +52,10 @@ static int pps_initialise(RCL_Instance instance) {
|
||||
pps_params_t params;
|
||||
struct pps_instance *pps;
|
||||
int fd, edge_clear, mode;
|
||||
char *path, *s;
|
||||
char *path;
|
||||
|
||||
path = RCL_GetDriverParameter(instance);
|
||||
|
||||
edge_clear = 0;
|
||||
if ((s = strrchr(path, ':')) != NULL) {
|
||||
*s = '\0';
|
||||
edge_clear = atoi(s + 1);
|
||||
}
|
||||
edge_clear = RCL_GetDriverOption(instance, "clear") ? 1 : 0;
|
||||
|
||||
fd = open(path, O_RDWR);
|
||||
if (fd < 0) {
|
||||
@@ -62,6 +63,8 @@ static int pps_initialise(RCL_Instance instance) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
UTI_FdSetCloexec(fd);
|
||||
|
||||
if (time_pps_create(fd, &handle) < 0) {
|
||||
LOG_FATAL(LOGF_Refclock, "time_pps_create() failed on %s", path);
|
||||
return 0;
|
||||
@@ -98,6 +101,7 @@ static int pps_initialise(RCL_Instance instance) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
pps = MallocNew(struct pps_instance);
|
||||
pps->handle = handle;
|
||||
pps->last_seq = 0;
|
||||
@@ -130,9 +134,7 @@ static int pps_poll(RCL_Instance instance)
|
||||
ts.tv_nsec = 0;
|
||||
|
||||
if (time_pps_fetch(pps->handle, PPS_TSFMT_TSPEC, &pps_info, &ts) < 0) {
|
||||
#if 0
|
||||
LOG(LOGS_INFO, LOGF_Refclock, "time_pps_fetch error");
|
||||
#endif
|
||||
LOG(LOGS_ERR, LOGF_Refclock, "time_pps_fetch() failed : %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -145,6 +147,8 @@ static int pps_poll(RCL_Instance instance)
|
||||
}
|
||||
|
||||
if (seq == pps->last_seq || (ts.tv_sec == 0 && ts.tv_nsec == 0)) {
|
||||
DEBUG_LOG(LOGF_Refclock, "PPS sample ignored seq=%lu ts=%lu.%09lu",
|
||||
seq, ts.tv_sec, ts.tv_nsec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,13 +25,14 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "refclock.h"
|
||||
#include "logging.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/shm.h>
|
||||
|
||||
#define SHMKEY 0x4e545030
|
||||
|
||||
struct shmTime {
|
||||
@@ -43,7 +44,7 @@ struct shmTime {
|
||||
* use values
|
||||
* clear valid
|
||||
*/
|
||||
int count;
|
||||
volatile int count;
|
||||
time_t clockTimeStampSec;
|
||||
int clockTimeStampUSec;
|
||||
time_t receiveTimeStampSec;
|
||||
@@ -51,17 +52,22 @@ struct shmTime {
|
||||
int leap;
|
||||
int precision;
|
||||
int nsamples;
|
||||
int valid;
|
||||
int dummy[10];
|
||||
volatile int valid;
|
||||
int clockTimeStampNSec;
|
||||
int receiveTimeStampNSec;
|
||||
int dummy[8];
|
||||
};
|
||||
|
||||
static int shm_initialise(RCL_Instance instance) {
|
||||
int id, param;
|
||||
int id, param, perm;
|
||||
char *s;
|
||||
struct shmTime *shm;
|
||||
|
||||
param = atoi(RCL_GetDriverParameter(instance));
|
||||
s = RCL_GetDriverOption(instance, "perm");
|
||||
perm = s ? strtol(s, NULL, 8) & 0777 : 0600;
|
||||
|
||||
id = shmget(SHMKEY + param, sizeof (struct shmTime), IPC_CREAT | 0700);
|
||||
id = shmget(SHMKEY + param, sizeof (struct shmTime), IPC_CREAT | perm);
|
||||
if (id == -1) {
|
||||
LOG_FATAL(LOGF_Refclock, "shmget() failed");
|
||||
return 0;
|
||||
@@ -84,7 +90,7 @@ static void shm_finalise(RCL_Instance instance)
|
||||
|
||||
static int shm_poll(RCL_Instance instance)
|
||||
{
|
||||
struct timeval tv1, tv2;
|
||||
struct timeval tv;
|
||||
struct shmTime t, *shm;
|
||||
double offset;
|
||||
|
||||
@@ -94,21 +100,24 @@ static int shm_poll(RCL_Instance instance)
|
||||
|
||||
if ((t.mode == 1 && t.count != shm->count) ||
|
||||
!(t.mode == 0 || t.mode == 1) || !t.valid) {
|
||||
#if 0
|
||||
LOG(LOGS_INFO, LOGF_Refclock, "sample ignored mode: %d count: %d valid: %d", t.mode, t.count, t.valid);
|
||||
#endif
|
||||
DEBUG_LOG(LOGF_Refclock, "SHM sample ignored mode=%d count=%d valid=%d",
|
||||
t.mode, t.count, t.valid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
shm->valid = 0;
|
||||
|
||||
tv1.tv_sec = t.receiveTimeStampSec;
|
||||
tv1.tv_usec = t.receiveTimeStampUSec;
|
||||
tv2.tv_sec = t.clockTimeStampSec;
|
||||
tv2.tv_usec = t.clockTimeStampUSec;
|
||||
tv.tv_sec = t.receiveTimeStampSec;
|
||||
tv.tv_usec = t.receiveTimeStampUSec;
|
||||
|
||||
UTI_DiffTimevalsToDouble(&offset, &tv2, &tv1);
|
||||
return RCL_AddSample(instance, &tv1, offset, t.leap);
|
||||
offset = t.clockTimeStampSec - t.receiveTimeStampSec;
|
||||
if (t.clockTimeStampNSec / 1000 == t.clockTimeStampUSec &&
|
||||
t.receiveTimeStampNSec / 1000 == t.receiveTimeStampUSec)
|
||||
offset += (t.clockTimeStampNSec - t.receiveTimeStampNSec) * 1e-9;
|
||||
else
|
||||
offset += (t.clockTimeStampUSec - t.receiveTimeStampUSec) * 1e-6;
|
||||
|
||||
return RCL_AddSample(instance, &tv, offset, t.leap);
|
||||
}
|
||||
|
||||
RefclockDriver RCL_SHM_driver = {
|
||||
|
||||
@@ -25,16 +25,15 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "refclock.h"
|
||||
#include "logging.h"
|
||||
#include "util.h"
|
||||
#include "sched.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define SOCK_MAGIC 0x534f434b
|
||||
|
||||
struct sock_sample {
|
||||
@@ -58,23 +57,20 @@ static void read_sample(void *anything)
|
||||
s = recv(sockfd, &sample, sizeof (sample), 0);
|
||||
|
||||
if (s < 0) {
|
||||
#if 0
|
||||
LOG(LOGS_INFO, LOGF_Refclock, "Error reading from SOCK socket : %s", strerror(errno));
|
||||
#endif
|
||||
LOG(LOGS_ERR, LOGF_Refclock, "Could not read SOCK sample : %s",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (s != sizeof (sample)) {
|
||||
#if 0
|
||||
LOG(LOGS_INFO, LOGF_Refclock, "Unexpected length of SOCK sample : %d != %d", s, sizeof (sample));
|
||||
#endif
|
||||
LOG(LOGS_WARN, LOGF_Refclock, "Unexpected length of SOCK sample : %d != %ld",
|
||||
s, (long)sizeof (sample));
|
||||
return;
|
||||
}
|
||||
|
||||
if (sample.magic != SOCK_MAGIC) {
|
||||
#if 0
|
||||
LOG(LOGS_INFO, LOGF_Refclock, "Unexpected magic number in SOCK sample : %x != %x", sample.magic, SOCK_MAGIC);
|
||||
#endif
|
||||
LOG(LOGS_WARN, LOGF_Refclock, "Unexpected magic number in SOCK sample : %x != %x",
|
||||
sample.magic, SOCK_MAGIC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -105,6 +101,8 @@ static int sock_initialise(RCL_Instance instance)
|
||||
return 0;
|
||||
}
|
||||
|
||||
UTI_FdSetCloexec(sockfd);
|
||||
|
||||
unlink(path);
|
||||
if (bind(sockfd, (struct sockaddr *)&s, sizeof (s)) < 0) {
|
||||
LOG_FATAL(LOGF_Refclock, "bind() failed");
|
||||
|
||||
1043
reference.c
1043
reference.c
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user