pub mod source;
pub mod selection;
pub mod clock;
pub mod log;
pub mod rtc;
pub mod ntp;
pub mod cmd;
pub mod hw;
pub mod nts;
pub mod misc;
pub mod source_file;
pub use source::*;
pub use selection::*;
pub use clock::*;
pub use log::*;
pub use rtc::*;
pub use ntp::*;
pub use cmd::*;
pub use hw::*;
pub use nts::*;
pub use misc::*;
pub use source_file::*;
use crate::span::Span;
#[derive(Debug, Clone, PartialEq)]
pub enum DirectiveKind {
Server(ServerConfig),
Pool(PoolConfig),
Peer(PeerConfig),
InitStepSlew(InitStepSlewConfig),
RefClock(RefClockConfig),
Manual,
AcquisitionPort(AcquisitionPortConfig),
BindAcqAddress(BindAddressConfig),
BindAcqDevice(BindDeviceConfig),
Dscp(DscpConfig),
DumpDir(DumpDirConfig),
MaxSamples(MaxSamplesConfig),
MinSamples(MinSamplesConfig),
NtsDumpDir(NtsDumpDirConfig),
NtsRefresh(NtsRefreshConfig),
NtsTrustedCerts(NtsTrustedCertsConfig),
NoSystemCert,
NoCertTimeCheck(NoCertTimeCheckConfig),
Refresh(RefreshConfig),
AuthSelectMode(AuthSelectMode),
CombineLimit(CombineLimitConfig),
MaxDistance(MaxDistanceConfig),
MaxJitter(MaxJitterConfig),
MinSources(MinSourcesConfig),
ReselectDist(ReselectDistConfig),
StratumWeight(StratumWeightConfig),
ClockPrecision(ClockPrecisionConfig),
CorrTimeRatio(CorrTimeRatioConfig),
DriftFile(DriftFileConfig),
FallbackDrift(FallbackDriftConfig),
LeapSecMode(LeapSecMode),
LeapSecTz(LeapSecTzConfig),
LeapSecList(LeapSecListConfig),
MakeStep(MakeStepConfig),
MaxChange(MaxChangeConfig),
MaxClockError(MaxClockErrorConfig),
MaxDrift(MaxDriftConfig),
MaxUpdateSkew(MaxUpdateSkewConfig),
MaxSlewRate(MaxSlewRateConfig),
TempComp(TempCompConfig),
Allow(AllowDenyConfig),
Deny(AllowDenyConfig),
BindAddress(BindAddressConfig),
BindDevice(BindDeviceConfig),
Broadcast(BroadcastConfig),
ClientLogLimit(ClientLogLimitConfig),
NoClientLog,
Local(LocalConfig),
NtpSignDSocket(NtpSignDSocketConfig),
NtsPort(NtsPortConfig),
NtsServerCert(NtsServerCertConfig),
NtsServerKey(NtsServerKeyConfig),
NtsProcesses(NtsProcessesConfig),
MaxNtsConnections(MaxNtsConnectionsConfig),
NtsNtpServer(NtsNtpServerConfig),
NtsRotate(NtsRotateConfig),
Port(PortConfig),
RateLimit(RateLimitConfig),
NtsRateLimit(NtsRateLimitConfig),
SmoothTime(SmoothTimeConfig),
BindCmdAddress(BindCmdAddressConfig),
BindCmdDevice(BindCmdDeviceConfig),
CmdAllow(AllowDenyConfig),
CmdDeny(AllowDenyConfig),
CmdPort(CmdPortConfig),
CmdRateLimit(CmdRateLimitConfig),
OpenCommands(OpenCommandsConfig),
HwClockFile(HwClockFileConfig),
RtcAutoTrim(RtcAutoTrimConfig),
RtcDevice(RtcDeviceConfig),
RtcFile(RtcFileConfig),
RtcOnUtc,
RtcSync,
Log(LogConfig),
LogBanner(LogBannerConfig),
LogChange(LogChangeConfig),
LogDir(LogDirConfig),
HwTimestamp(HwTimestampConfig),
HwTsTimeout(HwTsTimeoutConfig),
MaxTxBuffers(MaxTxBuffersConfig),
PtpPort(PtpPortConfig),
PtpDomain(PtpDomainConfig),
NtsAeads(NtsAeadsConfig),
ConfDir(ConfDirConfig),
Include(IncludeConfig),
SourceDir(SourceDirConfig),
LockAll,
MailOnChange(MailOnChangeConfig),
PidFile(PidFileConfig),
SchedPriority(SchedPriorityConfig),
User(UserConfig),
KeyFile(KeyFileConfig),
DumpOnExit,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Directive {
pub span: Span,
pub leading_comments: Vec<String>,
pub trailing_comment: Option<String>,
pub kind: DirectiveKind,
}
impl Directive {
pub fn new(kind: DirectiveKind, span: Span) -> Self {
Self { span, leading_comments: Vec::new(), trailing_comment: None, kind }
}
#[must_use]
pub fn with_leading_comment(mut self, comment: impl Into<String>) -> Self {
self.leading_comments.push(comment.into());
self
}
#[must_use]
pub fn with_trailing_comment(mut self, comment: impl Into<String>) -> Self {
self.trailing_comment = Some(comment.into());
self
}
}
impl From<DirectiveKind> for Directive {
fn from(kind: DirectiveKind) -> Self {
Self::new(kind, Span::new(None, 0, 0, 0))
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum ConfigNode {
Directive(Box<Directive>),
Comment(String),
BlankLine,
}
impl From<Directive> for ConfigNode {
fn from(d: Directive) -> Self {
Self::Directive(Box::new(d))
}
}
impl From<DirectiveKind> for ConfigNode {
fn from(kind: DirectiveKind) -> Self {
Self::Directive(Box::new(Directive::from(kind)))
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct ChronyConfig {
pub nodes: Vec<ConfigNode>,
}
impl ChronyConfig {
pub fn new() -> Self {
Self { nodes: Vec::new() }
}
pub fn push(&mut self, kind: DirectiveKind) {
self.nodes.push(ConfigNode::Directive(Box::new(Directive::from(kind))));
}
pub fn push_directive(&mut self, directive: Directive) {
self.nodes.push(ConfigNode::Directive(Box::new(directive)));
}
pub fn add_comment(&mut self, comment: impl Into<String>) {
self.nodes.push(ConfigNode::Comment(comment.into()));
}
pub fn add_blank(&mut self) {
self.nodes.push(ConfigNode::BlankLine);
}
pub fn directives(&self) -> impl Iterator<Item = &Directive> {
self.nodes.iter().filter_map(|n| match n {
ConfigNode::Directive(d) => Some(d.as_ref()),
_ => None,
})
}
pub fn directives_mut(&mut self) -> impl Iterator<Item = &mut Directive> {
self.nodes.iter_mut().filter_map(|n| match n {
ConfigNode::Directive(d) => Some(d.as_mut()),
_ => None,
})
}
pub fn find(&self, name: &str) -> impl Iterator<Item = &Directive> {
self.directives().filter(move |d| d.kind.name() == name)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DirectiveCategory {
Source,
Selection,
SystemClock,
NtpServer,
CommandAccess,
Rtc,
Log,
HardwareTimestamping,
Nts,
Miscellaneous,
Deprecated,
}
impl DirectiveKind {
pub fn name(&self) -> &'static str {
match self {
Self::Server(_) => "server",
Self::Pool(_) => "pool",
Self::Peer(_) => "peer",
Self::InitStepSlew(_) => "initstepslew",
Self::RefClock(_) => "refclock",
Self::Manual => "manual",
Self::AcquisitionPort(_) => "acquisitionport",
Self::BindAcqAddress(_) => "bindacqaddress",
Self::BindAcqDevice(_) => "bindacqdevice",
Self::Dscp(_) => "dscp",
Self::DumpDir(_) => "dumpdir",
Self::MaxSamples(_) => "maxsamples",
Self::MinSamples(_) => "minsamples",
Self::NtsDumpDir(_) => "ntsdumpdir",
Self::NtsRefresh(_) => "ntsrefresh",
Self::NtsTrustedCerts(_) => "ntstrustedcerts",
Self::NoSystemCert => "nosystemcert",
Self::NoCertTimeCheck(_) => "nocerttimecheck",
Self::Refresh(_) => "refresh",
Self::AuthSelectMode(_) => "authselectmode",
Self::CombineLimit(_) => "combinelimit",
Self::MaxDistance(_) => "maxdistance",
Self::MaxJitter(_) => "maxjitter",
Self::MinSources(_) => "minsources",
Self::ReselectDist(_) => "reselectdist",
Self::StratumWeight(_) => "stratumweight",
Self::ClockPrecision(_) => "clockprecision",
Self::CorrTimeRatio(_) => "corrtimeratio",
Self::DriftFile(_) => "driftfile",
Self::FallbackDrift(_) => "fallbackdrift",
Self::LeapSecMode(_) => "leapsecmode",
Self::LeapSecTz(_) => "leapsectz",
Self::LeapSecList(_) => "leapseclist",
Self::MakeStep(_) => "makestep",
Self::MaxChange(_) => "maxchange",
Self::MaxClockError(_) => "maxclockerror",
Self::MaxDrift(_) => "maxdrift",
Self::MaxUpdateSkew(_) => "maxupdateskew",
Self::MaxSlewRate(_) => "maxslewrate",
Self::TempComp(_) => "tempcomp",
Self::Allow(_) => "allow",
Self::Deny(_) => "deny",
Self::BindAddress(_) => "bindaddress",
Self::BindDevice(_) => "binddevice",
Self::Broadcast(_) => "broadcast",
Self::ClientLogLimit(_) => "clientloglimit",
Self::NoClientLog => "noclientlog",
Self::Local(_) => "local",
Self::NtpSignDSocket(_) => "ntpsigndsocket",
Self::NtsPort(_) => "ntsport",
Self::NtsServerCert(_) => "ntsservercert",
Self::NtsServerKey(_) => "ntsserverkey",
Self::NtsProcesses(_) => "ntsprocesses",
Self::MaxNtsConnections(_) => "maxntsconnections",
Self::NtsNtpServer(_) => "ntsntpserver",
Self::NtsRotate(_) => "ntsrotate",
Self::Port(_) => "port",
Self::RateLimit(_) => "ratelimit",
Self::NtsRateLimit(_) => "ntsratelimit",
Self::SmoothTime(_) => "smoothtime",
Self::BindCmdAddress(_) => "bindcmdaddress",
Self::BindCmdDevice(_) => "bindcmddevice",
Self::CmdAllow(_) => "cmdallow",
Self::CmdDeny(_) => "cmddeny",
Self::CmdPort(_) => "cmdport",
Self::CmdRateLimit(_) => "cmdratelimit",
Self::OpenCommands(_) => "opencommands",
Self::HwClockFile(_) => "hwclockfile",
Self::RtcAutoTrim(_) => "rtcautotrim",
Self::RtcDevice(_) => "rtcdevice",
Self::RtcFile(_) => "rtcfile",
Self::RtcOnUtc => "rtconutc",
Self::RtcSync => "rtcsync",
Self::Log(_) => "log",
Self::LogBanner(_) => "logbanner",
Self::LogChange(_) => "logchange",
Self::LogDir(_) => "logdir",
Self::HwTimestamp(_) => "hwtimestamp",
Self::HwTsTimeout(_) => "hwtstimeout",
Self::MaxTxBuffers(_) => "maxtxbuffers",
Self::PtpPort(_) => "ptpport",
Self::PtpDomain(_) => "ptpdomain",
Self::NtsAeads(_) => "ntsaeads",
Self::ConfDir(_) => "confdir",
Self::Include(_) => "include",
Self::SourceDir(_) => "sourcedir",
Self::LockAll => "lock_all",
Self::MailOnChange(_) => "mailonchange",
Self::PidFile(_) => "pidfile",
Self::SchedPriority(_) => "sched_priority",
Self::User(_) => "user",
Self::KeyFile(_) => "keyfile",
Self::DumpOnExit => "dumponexit",
}
}
pub fn category(&self) -> DirectiveCategory {
match self {
Self::Server(_) | Self::Pool(_) | Self::Peer(_)
| Self::InitStepSlew(_) | Self::RefClock(_) | Self::Manual
| Self::AcquisitionPort(_) | Self::BindAcqAddress(_)
| Self::BindAcqDevice(_) | Self::Dscp(_) | Self::DumpDir(_)
| Self::MaxSamples(_) | Self::MinSamples(_) | Self::NtsDumpDir(_)
| Self::NtsRefresh(_) | Self::NtsTrustedCerts(_)
| Self::NoSystemCert | Self::NoCertTimeCheck(_)
| Self::Refresh(_) => DirectiveCategory::Source,
Self::AuthSelectMode(_) | Self::CombineLimit(_)
| Self::MaxDistance(_) | Self::MaxJitter(_)
| Self::MinSources(_) | Self::ReselectDist(_)
| Self::StratumWeight(_) => DirectiveCategory::Selection,
Self::ClockPrecision(_) | Self::CorrTimeRatio(_)
| Self::DriftFile(_) | Self::FallbackDrift(_)
| Self::LeapSecMode(_) | Self::LeapSecTz(_)
| Self::LeapSecList(_) | Self::MakeStep(_)
| Self::MaxChange(_) | Self::MaxClockError(_)
| Self::MaxDrift(_) | Self::MaxUpdateSkew(_)
| Self::MaxSlewRate(_) | Self::TempComp(_) => DirectiveCategory::SystemClock,
Self::Allow(_) | Self::Deny(_) | Self::BindAddress(_)
| Self::BindDevice(_) | Self::Broadcast(_)
| Self::ClientLogLimit(_) | Self::NoClientLog
| Self::Local(_) | Self::NtpSignDSocket(_)
| Self::NtsPort(_) | Self::NtsServerCert(_)
| Self::NtsServerKey(_) | Self::NtsProcesses(_)
| Self::MaxNtsConnections(_) | Self::NtsNtpServer(_)
| Self::NtsRotate(_) | Self::Port(_) | Self::RateLimit(_)
| Self::NtsRateLimit(_) | Self::SmoothTime(_) => DirectiveCategory::NtpServer,
Self::BindCmdAddress(_) | Self::BindCmdDevice(_)
| Self::CmdAllow(_) | Self::CmdDeny(_)
| Self::CmdPort(_) | Self::CmdRateLimit(_)
| Self::OpenCommands(_) => DirectiveCategory::CommandAccess,
Self::HwClockFile(_) | Self::RtcAutoTrim(_)
| Self::RtcDevice(_) | Self::RtcFile(_)
| Self::RtcOnUtc | Self::RtcSync => DirectiveCategory::Rtc,
Self::Log(_) | Self::LogBanner(_) | Self::LogChange(_)
| Self::LogDir(_) => DirectiveCategory::Log,
Self::HwTimestamp(_) | Self::HwTsTimeout(_)
| Self::MaxTxBuffers(_) | Self::PtpPort(_)
| Self::PtpDomain(_) => DirectiveCategory::HardwareTimestamping,
Self::NtsAeads(_) => DirectiveCategory::Nts,
Self::ConfDir(_) | Self::Include(_) | Self::SourceDir(_)
| Self::LockAll | Self::MailOnChange(_) | Self::PidFile(_)
| Self::SchedPriority(_) | Self::User(_) | Self::KeyFile(_)
| Self::DumpOnExit => DirectiveCategory::Miscellaneous,
}
}
pub fn is_deprecated(&self) -> bool {
matches!(self, Self::DumpOnExit)
}
}