1pub mod source;
21pub mod selection;
22pub mod clock;
23pub mod log;
24pub mod rtc;
25pub mod ntp;
26pub mod cmd;
27pub mod hw;
28pub mod nts;
29pub mod misc;
30pub mod source_file;
31
32pub use source::*;
33pub use selection::*;
34pub use clock::*;
35pub use log::*;
36pub use rtc::*;
37pub use ntp::*;
38pub use cmd::*;
39pub use hw::*;
40pub use nts::*;
41pub use misc::*;
42pub use source_file::*;
43
44use crate::span::Span;
45
46#[derive(Debug, Clone, PartialEq)]
48pub enum DirectiveKind {
49 Server(ServerConfig),
51 Pool(PoolConfig),
52 Peer(PeerConfig),
53 InitStepSlew(InitStepSlewConfig),
54 RefClock(RefClockConfig),
55 Manual,
56 AcquisitionPort(AcquisitionPortConfig),
57 BindAcqAddress(BindAddressConfig),
58 BindAcqDevice(BindDeviceConfig),
59 Dscp(DscpConfig),
60 DumpDir(DumpDirConfig),
61 MaxSamples(MaxSamplesConfig),
62 MinSamples(MinSamplesConfig),
63 NtsDumpDir(NtsDumpDirConfig),
64 NtsRefresh(NtsRefreshConfig),
65 NtsTrustedCerts(NtsTrustedCertsConfig),
66 NoSystemCert,
67 NoCertTimeCheck(NoCertTimeCheckConfig),
68 Refresh(RefreshConfig),
69
70 AuthSelectMode(AuthSelectMode),
72 CombineLimit(CombineLimitConfig),
73 MaxDistance(MaxDistanceConfig),
74 MaxJitter(MaxJitterConfig),
75 MinSources(MinSourcesConfig),
76 ReselectDist(ReselectDistConfig),
77 StratumWeight(StratumWeightConfig),
78
79 ClockPrecision(ClockPrecisionConfig),
81 CorrTimeRatio(CorrTimeRatioConfig),
82 DriftFile(DriftFileConfig),
83 FallbackDrift(FallbackDriftConfig),
84 LeapSecMode(LeapSecMode),
85 LeapSecTz(LeapSecTzConfig),
86 LeapSecList(LeapSecListConfig),
87 MakeStep(MakeStepConfig),
88 MaxChange(MaxChangeConfig),
89 MaxClockError(MaxClockErrorConfig),
90 MaxDrift(MaxDriftConfig),
91 MaxUpdateSkew(MaxUpdateSkewConfig),
92 MaxSlewRate(MaxSlewRateConfig),
93 TempComp(TempCompConfig),
94
95 Allow(AllowDenyConfig),
97 Deny(AllowDenyConfig),
98 BindAddress(BindAddressConfig),
99 BindDevice(BindDeviceConfig),
100 Broadcast(BroadcastConfig),
101 ClientLogLimit(ClientLogLimitConfig),
102 NoClientLog,
103 Local(LocalConfig),
104 NtpSignDSocket(NtpSignDSocketConfig),
105 NtsPort(NtsPortConfig),
106 NtsServerCert(NtsServerCertConfig),
107 NtsServerKey(NtsServerKeyConfig),
108 NtsProcesses(NtsProcessesConfig),
109 MaxNtsConnections(MaxNtsConnectionsConfig),
110 NtsNtpServer(NtsNtpServerConfig),
111 NtsRotate(NtsRotateConfig),
112 Port(PortConfig),
113 RateLimit(RateLimitConfig),
114 NtsRateLimit(NtsRateLimitConfig),
115 SmoothTime(SmoothTimeConfig),
116
117 BindCmdAddress(BindCmdAddressConfig),
119 BindCmdDevice(BindCmdDeviceConfig),
120 CmdAllow(AllowDenyConfig),
121 CmdDeny(AllowDenyConfig),
122 CmdPort(CmdPortConfig),
123 CmdRateLimit(CmdRateLimitConfig),
124 OpenCommands(OpenCommandsConfig),
125
126 HwClockFile(HwClockFileConfig),
128 RtcAutoTrim(RtcAutoTrimConfig),
129 RtcDevice(RtcDeviceConfig),
130 RtcFile(RtcFileConfig),
131 RtcOnUtc,
132 RtcSync,
133
134 Log(LogConfig),
136 LogBanner(LogBannerConfig),
137 LogChange(LogChangeConfig),
138 LogDir(LogDirConfig),
139
140 HwTimestamp(HwTimestampConfig),
142 HwTsTimeout(HwTsTimeoutConfig),
143 MaxTxBuffers(MaxTxBuffersConfig),
144 PtpPort(PtpPortConfig),
145 PtpDomain(PtpDomainConfig),
146
147 NtsAeads(NtsAeadsConfig),
149
150 ConfDir(ConfDirConfig),
152 Include(IncludeConfig),
153 SourceDir(SourceDirConfig),
154 LockAll,
155 MailOnChange(MailOnChangeConfig),
156 PidFile(PidFileConfig),
157 SchedPriority(SchedPriorityConfig),
158 User(UserConfig),
159 KeyFile(KeyFileConfig),
160 DumpOnExit,
161}
162
163#[derive(Debug, Clone, PartialEq)]
184pub struct Directive {
185 pub span: Span,
187 pub leading_comments: Vec<String>,
189 pub trailing_comment: Option<String>,
191 pub kind: DirectiveKind,
193}
194
195impl Directive {
196 pub fn new(kind: DirectiveKind, span: Span) -> Self {
198 Self { span, leading_comments: Vec::new(), trailing_comment: None, kind }
199 }
200
201 #[must_use]
203 pub fn with_leading_comment(mut self, comment: impl Into<String>) -> Self {
204 self.leading_comments.push(comment.into());
205 self
206 }
207
208 #[must_use]
210 pub fn with_trailing_comment(mut self, comment: impl Into<String>) -> Self {
211 self.trailing_comment = Some(comment.into());
212 self
213 }
214}
215
216impl From<DirectiveKind> for Directive {
217 fn from(kind: DirectiveKind) -> Self {
218 Self::new(kind, Span::new(None, 0, 0, 0))
219 }
220}
221
222#[derive(Debug, Clone, PartialEq)]
242pub enum ConfigNode {
243 Directive(Box<Directive>),
245 Comment(String),
247 BlankLine,
249}
250
251impl From<Directive> for ConfigNode {
252 fn from(d: Directive) -> Self {
253 Self::Directive(Box::new(d))
254 }
255}
256
257impl From<DirectiveKind> for ConfigNode {
258 fn from(kind: DirectiveKind) -> Self {
259 Self::Directive(Box::new(Directive::from(kind)))
260 }
261}
262
263#[derive(Debug, Clone, Default, PartialEq)]
304pub struct ChronyConfig {
305 pub nodes: Vec<ConfigNode>,
307}
308
309impl ChronyConfig {
310 pub fn new() -> Self {
312 Self { nodes: Vec::new() }
313 }
314
315 pub fn push(&mut self, kind: DirectiveKind) {
331 self.nodes.push(ConfigNode::Directive(Box::new(Directive::from(kind))));
332 }
333
334 pub fn push_directive(&mut self, directive: Directive) {
336 self.nodes.push(ConfigNode::Directive(Box::new(directive)));
337 }
338
339 pub fn add_comment(&mut self, comment: impl Into<String>) {
341 self.nodes.push(ConfigNode::Comment(comment.into()));
342 }
343
344 pub fn add_blank(&mut self) {
346 self.nodes.push(ConfigNode::BlankLine);
347 }
348
349 pub fn directives(&self) -> impl Iterator<Item = &Directive> {
353 self.nodes.iter().filter_map(|n| match n {
354 ConfigNode::Directive(d) => Some(d.as_ref()),
355 _ => None,
356 })
357 }
358
359 pub fn directives_mut(&mut self) -> impl Iterator<Item = &mut Directive> {
364 self.nodes.iter_mut().filter_map(|n| match n {
365 ConfigNode::Directive(d) => Some(d.as_mut()),
366 _ => None,
367 })
368 }
369
370 pub fn find(&self, name: &str) -> impl Iterator<Item = &Directive> {
392 self.directives().filter(move |d| d.kind.name() == name)
393 }
394}
395
396#[derive(Debug, Clone, Copy, PartialEq, Eq)]
411pub enum DirectiveCategory {
412 Source,
414 Selection,
416 SystemClock,
418 NtpServer,
420 CommandAccess,
422 Rtc,
424 Log,
426 HardwareTimestamping,
428 Nts,
430 Miscellaneous,
432 Deprecated,
434}
435
436impl DirectiveKind {
437 pub fn name(&self) -> &'static str {
441 match self {
442 Self::Server(_) => "server",
443 Self::Pool(_) => "pool",
444 Self::Peer(_) => "peer",
445 Self::InitStepSlew(_) => "initstepslew",
446 Self::RefClock(_) => "refclock",
447 Self::Manual => "manual",
448 Self::AcquisitionPort(_) => "acquisitionport",
449 Self::BindAcqAddress(_) => "bindacqaddress",
450 Self::BindAcqDevice(_) => "bindacqdevice",
451 Self::Dscp(_) => "dscp",
452 Self::DumpDir(_) => "dumpdir",
453 Self::MaxSamples(_) => "maxsamples",
454 Self::MinSamples(_) => "minsamples",
455 Self::NtsDumpDir(_) => "ntsdumpdir",
456 Self::NtsRefresh(_) => "ntsrefresh",
457 Self::NtsTrustedCerts(_) => "ntstrustedcerts",
458 Self::NoSystemCert => "nosystemcert",
459 Self::NoCertTimeCheck(_) => "nocerttimecheck",
460 Self::Refresh(_) => "refresh",
461 Self::AuthSelectMode(_) => "authselectmode",
462 Self::CombineLimit(_) => "combinelimit",
463 Self::MaxDistance(_) => "maxdistance",
464 Self::MaxJitter(_) => "maxjitter",
465 Self::MinSources(_) => "minsources",
466 Self::ReselectDist(_) => "reselectdist",
467 Self::StratumWeight(_) => "stratumweight",
468 Self::ClockPrecision(_) => "clockprecision",
469 Self::CorrTimeRatio(_) => "corrtimeratio",
470 Self::DriftFile(_) => "driftfile",
471 Self::FallbackDrift(_) => "fallbackdrift",
472 Self::LeapSecMode(_) => "leapsecmode",
473 Self::LeapSecTz(_) => "leapsectz",
474 Self::LeapSecList(_) => "leapseclist",
475 Self::MakeStep(_) => "makestep",
476 Self::MaxChange(_) => "maxchange",
477 Self::MaxClockError(_) => "maxclockerror",
478 Self::MaxDrift(_) => "maxdrift",
479 Self::MaxUpdateSkew(_) => "maxupdateskew",
480 Self::MaxSlewRate(_) => "maxslewrate",
481 Self::TempComp(_) => "tempcomp",
482 Self::Allow(_) => "allow",
483 Self::Deny(_) => "deny",
484 Self::BindAddress(_) => "bindaddress",
485 Self::BindDevice(_) => "binddevice",
486 Self::Broadcast(_) => "broadcast",
487 Self::ClientLogLimit(_) => "clientloglimit",
488 Self::NoClientLog => "noclientlog",
489 Self::Local(_) => "local",
490 Self::NtpSignDSocket(_) => "ntpsigndsocket",
491 Self::NtsPort(_) => "ntsport",
492 Self::NtsServerCert(_) => "ntsservercert",
493 Self::NtsServerKey(_) => "ntsserverkey",
494 Self::NtsProcesses(_) => "ntsprocesses",
495 Self::MaxNtsConnections(_) => "maxntsconnections",
496 Self::NtsNtpServer(_) => "ntsntpserver",
497 Self::NtsRotate(_) => "ntsrotate",
498 Self::Port(_) => "port",
499 Self::RateLimit(_) => "ratelimit",
500 Self::NtsRateLimit(_) => "ntsratelimit",
501 Self::SmoothTime(_) => "smoothtime",
502 Self::BindCmdAddress(_) => "bindcmdaddress",
503 Self::BindCmdDevice(_) => "bindcmddevice",
504 Self::CmdAllow(_) => "cmdallow",
505 Self::CmdDeny(_) => "cmddeny",
506 Self::CmdPort(_) => "cmdport",
507 Self::CmdRateLimit(_) => "cmdratelimit",
508 Self::OpenCommands(_) => "opencommands",
509 Self::HwClockFile(_) => "hwclockfile",
510 Self::RtcAutoTrim(_) => "rtcautotrim",
511 Self::RtcDevice(_) => "rtcdevice",
512 Self::RtcFile(_) => "rtcfile",
513 Self::RtcOnUtc => "rtconutc",
514 Self::RtcSync => "rtcsync",
515 Self::Log(_) => "log",
516 Self::LogBanner(_) => "logbanner",
517 Self::LogChange(_) => "logchange",
518 Self::LogDir(_) => "logdir",
519 Self::HwTimestamp(_) => "hwtimestamp",
520 Self::HwTsTimeout(_) => "hwtstimeout",
521 Self::MaxTxBuffers(_) => "maxtxbuffers",
522 Self::PtpPort(_) => "ptpport",
523 Self::PtpDomain(_) => "ptpdomain",
524 Self::NtsAeads(_) => "ntsaeads",
525 Self::ConfDir(_) => "confdir",
526 Self::Include(_) => "include",
527 Self::SourceDir(_) => "sourcedir",
528 Self::LockAll => "lock_all",
529 Self::MailOnChange(_) => "mailonchange",
530 Self::PidFile(_) => "pidfile",
531 Self::SchedPriority(_) => "sched_priority",
532 Self::User(_) => "user",
533 Self::KeyFile(_) => "keyfile",
534 Self::DumpOnExit => "dumponexit",
535 }
536 }
537
538 pub fn category(&self) -> DirectiveCategory {
544 match self {
545 Self::Server(_) | Self::Pool(_) | Self::Peer(_)
546 | Self::InitStepSlew(_) | Self::RefClock(_) | Self::Manual
547 | Self::AcquisitionPort(_) | Self::BindAcqAddress(_)
548 | Self::BindAcqDevice(_) | Self::Dscp(_) | Self::DumpDir(_)
549 | Self::MaxSamples(_) | Self::MinSamples(_) | Self::NtsDumpDir(_)
550 | Self::NtsRefresh(_) | Self::NtsTrustedCerts(_)
551 | Self::NoSystemCert | Self::NoCertTimeCheck(_)
552 | Self::Refresh(_) => DirectiveCategory::Source,
553 Self::AuthSelectMode(_) | Self::CombineLimit(_)
554 | Self::MaxDistance(_) | Self::MaxJitter(_)
555 | Self::MinSources(_) | Self::ReselectDist(_)
556 | Self::StratumWeight(_) => DirectiveCategory::Selection,
557 Self::ClockPrecision(_) | Self::CorrTimeRatio(_)
558 | Self::DriftFile(_) | Self::FallbackDrift(_)
559 | Self::LeapSecMode(_) | Self::LeapSecTz(_)
560 | Self::LeapSecList(_) | Self::MakeStep(_)
561 | Self::MaxChange(_) | Self::MaxClockError(_)
562 | Self::MaxDrift(_) | Self::MaxUpdateSkew(_)
563 | Self::MaxSlewRate(_) | Self::TempComp(_) => DirectiveCategory::SystemClock,
564 Self::Allow(_) | Self::Deny(_) | Self::BindAddress(_)
565 | Self::BindDevice(_) | Self::Broadcast(_)
566 | Self::ClientLogLimit(_) | Self::NoClientLog
567 | Self::Local(_) | Self::NtpSignDSocket(_)
568 | Self::NtsPort(_) | Self::NtsServerCert(_)
569 | Self::NtsServerKey(_) | Self::NtsProcesses(_)
570 | Self::MaxNtsConnections(_) | Self::NtsNtpServer(_)
571 | Self::NtsRotate(_) | Self::Port(_) | Self::RateLimit(_)
572 | Self::NtsRateLimit(_) | Self::SmoothTime(_) => DirectiveCategory::NtpServer,
573 Self::BindCmdAddress(_) | Self::BindCmdDevice(_)
574 | Self::CmdAllow(_) | Self::CmdDeny(_)
575 | Self::CmdPort(_) | Self::CmdRateLimit(_)
576 | Self::OpenCommands(_) => DirectiveCategory::CommandAccess,
577 Self::HwClockFile(_) | Self::RtcAutoTrim(_)
578 | Self::RtcDevice(_) | Self::RtcFile(_)
579 | Self::RtcOnUtc | Self::RtcSync => DirectiveCategory::Rtc,
580 Self::Log(_) | Self::LogBanner(_) | Self::LogChange(_)
581 | Self::LogDir(_) => DirectiveCategory::Log,
582 Self::HwTimestamp(_) | Self::HwTsTimeout(_)
583 | Self::MaxTxBuffers(_) | Self::PtpPort(_)
584 | Self::PtpDomain(_) => DirectiveCategory::HardwareTimestamping,
585 Self::NtsAeads(_) => DirectiveCategory::Nts,
586 Self::ConfDir(_) | Self::Include(_) | Self::SourceDir(_)
587 | Self::LockAll | Self::MailOnChange(_) | Self::PidFile(_)
588 | Self::SchedPriority(_) | Self::User(_) | Self::KeyFile(_)
589 | Self::DumpOnExit => DirectiveCategory::Miscellaneous,
590 }
591 }
592
593 pub fn is_deprecated(&self) -> bool {
596 matches!(self, Self::DumpOnExit)
597 }
598}