use crate::ast::*;
use crate::error::DirectiveError;
pub fn validate_config(config: &ChronyConfig) -> Vec<DirectiveError> {
let mut errors = Vec::new();
for node in &config.nodes {
if let ConfigNode::Directive(d) = node {
validate_poll_limits(d, &mut errors);
validate_refclock_dpoll(d, &mut errors);
validate_pool_maxsources(d, &mut errors);
}
}
errors
}
fn validate_poll_limits(d: &Directive, errors: &mut Vec<DirectiveError>) {
let (name, minpoll, maxpoll) = match &d.kind {
DirectiveKind::Server(c) => ("server", c.minpoll.get(), c.maxpoll.get()),
DirectiveKind::Pool(c) => ("pool", c.source.minpoll.get(), c.source.maxpoll.get()),
DirectiveKind::Peer(c) => ("peer", c.minpoll.get(), c.maxpoll.get()),
DirectiveKind::RefClock(c) => ("refclock", c.poll.get(), c.poll.get()), _ => return,
};
if minpoll > maxpoll {
errors.push(DirectiveError::InvalidValue {
directive: name.into(),
expected: "minpoll <= maxpoll",
got: format!("minpoll {minpoll}, maxpoll {maxpoll}"),
span: d.span.clone(),
});
}
}
fn validate_refclock_dpoll(d: &Directive, errors: &mut Vec<DirectiveError>) {
if let DirectiveKind::RefClock(c) = &d.kind
&& matches!(c.driver, RefClockDriverKind::Pps)
&& c.pps_rate.get() > 1
&& c.dpoll.get() >= 0
{
errors.push(DirectiveError::InvalidOption {
directive: "refclock".into(),
option: "dpoll must be negative when rate > 1".into(),
span: d.span.clone(),
});
}
}
fn validate_pool_maxsources(d: &Directive, errors: &mut Vec<DirectiveError>) {
if let DirectiveKind::Pool(c) = &d.kind
&& (c.max_sources < 1 || c.max_sources > 16)
{
errors.push(DirectiveError::ValueOutOfRange {
directive: "pool".into(),
value: c.max_sources.to_string(),
min: "1".into(),
max: "16".into(),
span: d.span.clone(),
});
}
}