Skip to content

Validating

Hornet's validator performs semantic checks on a parsed AST and returns a list of ValidationError diagnostics. Validation never modifies the AST.


Basic usage

Validate a named.conf

use hornet_bind9::{parse_named_conf, validate_named_conf, Severity};

let conf = parse_named_conf(input)?;
let diags = validate_named_conf(&conf);

if diags.is_empty() {
    println!("No issues found.");
}

for d in &diags {
    let prefix = match d.severity {
        Severity::Error   => "error",
        Severity::Warning => "warning",
        Severity::Info    => "info",
    };
    eprintln!("{prefix}: {}", d.message);
}

Validate a zone file

use hornet_bind9::{parse_zone_file, validate_zone_file};

let zone = parse_zone_file(zone_text)?;
let diags = validate_zone_file(&zone);

for d in &diags {
    eprintln!("[{:?}] {}", d.severity, d.message);
}

Severity levels

Level Meaning
Severity::Error Definite misconfiguration; BIND9 will likely refuse to load
Severity::Warning Suspicious configuration; BIND9 will load but behaviour may be unintended
Severity::Info Informational note; best practice reminder

Severity implements PartialOrdError > Warning > Info.


Filtering by severity

use hornet_bind9::Severity;

let errors: Vec<_> = diags.iter()
    .filter(|d| d.severity == Severity::Error)
    .collect();

let warnings_and_above: Vec<_> = diags.iter()
    .filter(|d| d.severity >= Severity::Warning)
    .collect();

Exit code integration

A common pattern for CI pipelines is to fail on errors but pass on warnings:

use hornet_bind9::Severity;

let has_error   = diags.iter().any(|d| d.severity == Severity::Error);
let has_warning = diags.iter().any(|d| d.severity == Severity::Warning);

if has_error {
    std::process::exit(1);
}
if has_warning && !allow_warnings {
    std::process::exit(1);
}

Tip

The hornet check CLI command handles exit codes automatically. See check.


What named.conf validation checks

Check Severity
ACL reference to undefined name Error
CIDR prefix length out of range Error
Key with empty secret Error
Duplicate zone declaration Error
Logging category references undefined channel Error
Primary zone without file directive Warning
Secondary zone without primaries directive Warning
Forward zone without forwarders Warning
forwarders set without forward policy Warning
DNSSEC validation enabled with recursion disabled Warning
Unrecognised key algorithm Warning
View without match-clients or match-destinations Warning
Logging file channel without severity Info
Zone name > 253 characters Error
Zone label > 63 characters Error
Zone label starts or ends with - Warning

Built-in ACLs

The validator recognises the following built-in ACL names and never reports them as undefined:

  • any
  • none
  • localhost
  • localnets

What zone file validation checks

Check Severity
Missing SOA record Error
Multiple SOA records Error
Missing NS records Error
TXT string chunk exceeds 255 bytes Warning
TXT record total exceeds 65535 bytes Error
MX exchange is . (null MX) Warning
Non-standard CAA tag Warning

Next Steps

  • Parsing — Parse configs before validating
  • check CLI — Validate from the command line
  • Error TypesValidationError and Severity types