1use bitflags::bitflags;
9use bytes::{Buf, BufMut};
10use std::convert::From;
11use std::error::Error;
12use std::fmt::{Debug, Display};
13use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
14use std::time::{Duration, SystemTime, UNIX_EPOCH};
15
16use chrony_candm_derive::ChronySerialize;
17
18#[derive(Debug, thiserror::Error)]
19pub enum QueryError {
20 #[error("Unable to send request")]
21 Send(#[source] std::io::Error),
22 #[error("Unable to receive reply")]
23 Recv(#[source] std::io::Error),
24 #[error("Failed deserialization")]
25 Deserialization(#[from] DeserializationError),
26 #[error("Sequence number mismatch. Expected {expected}, got {received}")]
27 SequenceMismatch { expected: u32, received: u32 },
28 #[error("Timeout")]
29 Timeout,
30}
31
32impl QueryError {
33 pub(crate) fn into_io(self) -> std::io::Error {
35 match self {
36 QueryError::Send(e) => e,
37 QueryError::Recv(e) => e,
38 QueryError::Deserialization(e) => std::io::Error::new(std::io::ErrorKind::InvalidData, e),
39 QueryError::SequenceMismatch { .. } => std::io::Error::new(
40 std::io::ErrorKind::InvalidData,
41 String::from("Sequence number mismatch"),
42 ),
43 QueryError::Timeout => std::io::Error::new(std::io::ErrorKind::TimedOut, "Timed out"),
44 }
45 }
46}
47
48#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
50pub struct DeserializationError(Option<&'static str>);
51
52impl DeserializationError {
53 pub(crate) fn new(detail: &'static str) -> DeserializationError {
54 DeserializationError(Some(detail))
55 }
56
57 #[allow(dead_code)]
58 pub(crate) fn generic() -> DeserializationError {
59 DeserializationError(None)
60 }
61}
62
63impl Display for DeserializationError {
64 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 match self.0 {
66 None => write!(f, "Deserialization error"),
67 Some(detail) => write!(f, "Deserialization error: {}", detail),
68 }
69 }
70}
71impl Error for DeserializationError {}
72
73pub(crate) trait ChronySerialize: Sized {
74 fn length() -> usize;
75 fn serialize<B: BufMut>(&self, buf: &mut B);
76 fn deserialize_unchecked<B: Buf>(buf: &mut B) -> Result<Self, DeserializationError>;
77
78 fn deserialize<B: Buf>(buf: &mut B) -> Result<Self, DeserializationError> {
79 if buf.remaining() < Self::length() {
80 Err(DeserializationError::new("message too short"))
81 } else {
82 Self::deserialize_unchecked(buf)
83 }
84 }
85}
86
87impl<T: ChronySerialize + Copy, const N: usize> ChronySerialize for [T; N] {
88 fn length() -> usize {
89 T::length() * N
90 }
91
92 fn serialize<B: BufMut>(&self, buf: &mut B) {
93 for i in 0..N {
94 self[i].serialize(buf)
95 }
96 }
97
98 fn deserialize_unchecked<B: Buf>(buf: &mut B) -> Result<Self, DeserializationError> {
99 let mut arr = arrayvec::ArrayVec::<T, N>::new_const();
100 unsafe {
101 for _ in 0..N {
102 arr.push_unchecked(T::deserialize_unchecked(buf)?);
104 }
105 Ok(arr.into_inner_unchecked())
107 }
108 }
109}
110
111macro_rules! serialize_primitive {
112 ($ty:ty, $get:ident, $put:ident) => {
113 impl ChronySerialize for $ty {
114 fn length() -> usize {
115 std::mem::size_of::<$ty>()
116 }
117
118 fn serialize<B: BufMut>(&self, buf: &mut B) {
119 buf.$put(*self)
120 }
121
122 fn deserialize_unchecked<B: Buf>(buf: &mut B) -> Result<Self, DeserializationError> {
123 Ok(buf.$get())
124 }
125 }
126 };
127}
128
129serialize_primitive!(u8, get_u8, put_u8);
130serialize_primitive!(i8, get_i8, put_i8);
131serialize_primitive!(u16, get_u16, put_u16);
132serialize_primitive!(i16, get_i16, put_i16);
133serialize_primitive!(u32, get_u32, put_u32);
134serialize_primitive!(i32, get_i32, put_i32);
135serialize_primitive!(u64, get_u64, put_u64);
136serialize_primitive!(i64, get_i64, put_i64);
137
138impl ChronySerialize for SystemTime {
139 fn length() -> usize {
140 12
141 }
142
143 fn serialize<B: BufMut>(&self, buf: &mut B) {
144 let (secs, nsecs) = match self.duration_since(UNIX_EPOCH) {
145 Ok(d) => (d.as_secs() as i64, d.subsec_nanos()),
146 Err(e) => {
147 let d = e.duration();
148 let secs = d.as_secs() as i64;
149 let nsecs = d.subsec_nanos();
150 if nsecs == 0 {
151 (-secs, 0)
152 } else {
153 (-secs - 1, 1_000_000_000 - nsecs)
154 }
155 }
156 };
157
158 let secs_high = (secs >> 32) as i32;
159 let secs_low = (secs & 0xffffffff) as u32;
160
161 buf.put_i32(secs_high);
162 buf.put_u32(secs_low);
163 buf.put_u32(nsecs);
164 }
165
166 fn deserialize_unchecked<B: Buf>(buf: &mut B) -> Result<Self, DeserializationError> {
167 let secs_high_orig = buf.get_i32();
168 let secs_low = buf.get_u32();
169 let nsecs = buf.get_u32();
170
171 let secs_high = if secs_high_orig == i32::MAX {
172 0
173 } else {
174 secs_high_orig
175 };
176
177 if secs_high >= 0 {
178 let d = Duration::from_secs((secs_high as u64) << 32)
179 + Duration::from_secs(secs_low as u64)
180 + Duration::from_nanos(nsecs as u64);
181 Ok(UNIX_EPOCH + d)
182 } else {
183 let d = Duration::from_secs(((-secs_high) as u64) << 32)
184 - Duration::from_secs(secs_low as u64)
185 - Duration::from_nanos(nsecs as u64);
186 Ok(UNIX_EPOCH - d)
187 }
188 }
189}
190pub(crate) trait ChronyMessage: Sized {
191 fn body_length(&self) -> usize;
192 fn cmd(&self) -> u16;
193 fn serialize_body<B: BufMut>(&self, buf: &mut B);
194 fn deserialize_body<B: Buf>(cmd: u16, body: &mut B) -> Result<Self, DeserializationError>;
195}
196
197#[derive(Copy, Clone, Eq, PartialEq, Hash, Default)]
204pub struct ChronyFloat(u32);
205
206impl Debug for ChronyFloat {
207 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
208 f.debug_tuple("ChronyFloat")
209 .field(&f64::from(*self))
210 .finish()
211 }
212}
213
214impl Display for ChronyFloat {
215 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
216 Display::fmt(&f64::from(*self), f)
217 }
218}
219
220impl PartialOrd for ChronyFloat {
221 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
222 f64::from(*self).partial_cmp(&f64::from(*other))
223 }
224}
225
226impl Ord for ChronyFloat {
227 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
228 self.partial_cmp(other)
229 .expect("Conversion from ChronyFloat yielded incomparable f64")
230 }
231}
232
233const FLOAT_EXP_BITS: u32 = 7;
234const FLOAT_EXP_MIN: i32 = -((1 << (FLOAT_EXP_BITS - 1)) as i32);
235const FLOAT_EXP_MAX: i32 = -FLOAT_EXP_MIN - 1;
236const FLOAT_COEF_BITS: u32 = 32 - FLOAT_EXP_BITS;
237const FLOAT_COEF_MIN: i32 = -((1 << (FLOAT_COEF_BITS - 1)) as i32);
238const FLOAT_COEF_MAX: i32 = -FLOAT_COEF_MIN - 1;
239
240impl From<ChronyFloat> for f64 {
241 fn from(f: ChronyFloat) -> Self {
242 let ChronyFloat(x) = f;
243
244 let mut exp = (x >> FLOAT_COEF_BITS) as i32;
245 if exp >= 1 << (FLOAT_EXP_BITS - 1) {
246 exp -= 1 << FLOAT_EXP_BITS;
247 }
248 exp -= FLOAT_COEF_BITS as i32;
249
250 let mut coef = (x % (1 << FLOAT_COEF_BITS)) as i32;
251
252 if coef >= 1 << (FLOAT_COEF_BITS - 1) {
253 coef -= 1 << FLOAT_COEF_BITS
254 }
255
256 (coef as f64) * 2.0f64.powi(exp)
257 }
258}
259
260impl From<f64> for ChronyFloat {
261 fn from(f: f64) -> Self {
262 let (neg, x) = if f < 0. {
263 (1, -f)
264 } else if f >= 0. {
265 (0, f)
266 } else {
267 (0, 0.) };
269
270 let mut exp: i32;
271 let mut coef: i32;
272
273 if x < 1e-100 {
274 coef = 0;
275 exp = 0;
276 } else if x > 1e100 {
277 coef = FLOAT_COEF_MAX + neg;
278 exp = FLOAT_EXP_MAX;
279 } else {
280 exp = x.log2() as i32 + 1;
281 coef = (x * 2.0f64.powi(-exp + FLOAT_COEF_BITS as i32) + 0.5) as i32;
282 debug_assert!(coef > 0);
283
284 while coef > FLOAT_COEF_MAX + neg {
285 coef >>= 1;
286 exp += 1;
287 }
288
289 if exp > FLOAT_EXP_MAX {
290 exp = FLOAT_EXP_MAX;
291 coef = FLOAT_COEF_MAX + neg;
292 } else if exp < FLOAT_EXP_MIN {
293 if exp + FLOAT_COEF_BITS as i32 >= FLOAT_EXP_MIN {
294 coef >>= FLOAT_EXP_MIN - exp;
295 exp = FLOAT_EXP_MIN;
296 } else {
297 exp = 0;
298 coef = 0;
299 }
300 }
301 };
302
303 if neg != 0 {
304 coef = ((-coef as u32) << FLOAT_EXP_BITS >> FLOAT_EXP_BITS) as i32;
305 }
306
307 ChronyFloat((exp as u32) << FLOAT_COEF_BITS | coef as u32)
308 }
309}
310
311impl ChronySerialize for ChronyFloat {
312 fn length() -> usize {
313 4
314 }
315
316 fn serialize<B: BufMut>(&self, buf: &mut B) {
317 self.0.serialize(buf)
318 }
319
320 fn deserialize_unchecked<B: Buf>(buf: &mut B) -> Result<Self, DeserializationError> {
321 Ok(ChronyFloat(u32::deserialize_unchecked(buf)?))
322 }
323}
324
325#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
327pub enum ChronyAddr {
328 Unspec,
330 V4(Ipv4Addr),
332 V6(Ipv6Addr),
334 Id(u32),
336}
337
338impl Default for ChronyAddr {
339 fn default() -> Self {
340 Self::Unspec
341 }
342}
343
344impl From<Ipv4Addr> for ChronyAddr {
345 fn from(addr: Ipv4Addr) -> Self {
346 Self::V4(addr)
347 }
348}
349
350impl From<Ipv6Addr> for ChronyAddr {
351 fn from(addr: Ipv6Addr) -> Self {
352 Self::V6(addr)
353 }
354}
355
356impl From<IpAddr> for ChronyAddr {
357 fn from(addr: IpAddr) -> Self {
358 match addr {
359 IpAddr::V4(addr4) => Self::V4(addr4),
360 IpAddr::V6(addr6) => Self::V6(addr6),
361 }
362 }
363}
364
365impl Display for ChronyAddr {
366 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
367 match self {
368 ChronyAddr::Unspec => write!(f, "[UNSPEC]"),
369 ChronyAddr::V4(v4) => Display::fmt(v4, f),
370 ChronyAddr::V6(v6) => Display::fmt(v6, f),
371 ChronyAddr::Id(id) => write!(f, "ID#{}", id),
372 }
373 }
374}
375
376const IPADDR_UNSPEC: u16 = 0;
377const IPADDR_INET4: u16 = 1;
378const IPADDR_INET6: u16 = 2;
379const IPADDR_ID: u16 = 3;
380
381impl ChronySerialize for ChronyAddr {
382 fn length() -> usize {
383 20
384 }
385
386 fn serialize<B: BufMut>(&self, buf: &mut B) {
387 match self {
388 ChronyAddr::Unspec => {
389 buf.put(&[0u8; 16] as &[u8]);
390 buf.put_u16(IPADDR_UNSPEC);
391 buf.put_u16(0);
392 }
393 ChronyAddr::V4(addr) => {
394 buf.put_u32((*addr).into());
395 buf.put(&[0u8; 12] as &[u8]);
396 buf.put_u16(IPADDR_INET4);
397 buf.put_u16(0);
398 }
399 ChronyAddr::V6(addr) => {
400 buf.put_u128((*addr).into());
401 buf.put_u16(IPADDR_INET6);
402 buf.put_u16(0);
403 }
404 ChronyAddr::Id(id) => {
405 buf.put_u32(*id);
406 buf.put(&[0u8; 12] as &[u8]);
407 buf.put_u16(IPADDR_ID);
408 buf.put_u16(0);
409 }
410 }
411 }
412
413 fn deserialize_unchecked<B: Buf>(buf: &mut B) -> Result<Self, DeserializationError> {
414 let mut addr = buf.copy_to_bytes(16);
415 let family = buf.get_u16();
416 buf.get_u16();
417
418 match family {
419 IPADDR_INET4 => Ok(Self::V4(Ipv4Addr::from(addr.get_u32()))),
420 IPADDR_INET6 => Ok(Self::V6(Ipv6Addr::from(addr.get_u128()))),
421 IPADDR_ID => Ok(Self::Id(addr.get_u32())),
422 _ => Ok(Self::Unspec),
423 }
424 }
425}
426
427bitflags! {
428 #[derive(ChronySerialize)]
430 pub struct SourceFlags : u16 {
431 const ONLINE = 0x1;
432 const AUTOOFFLINE = 0x2;
433 const IBURST = 0x4;
434 const PREFER = 0x8;
435 const NOSELECT = 0x10;
436 const TRUST = 0x20;
437 const REQUIRE = 0x40;
438 const INTERLEAVED = 0x80;
439 const BURST = 0x100;
440 const NTS = 0x200;
441 const COPY = 0x400;
442 }
443}
444
445pub(crate) const REQUEST_HEADER_LENGTH: usize = 20;
446pub(crate) const REPLY_HEADER_LENGTH: usize = 28;