diff --git a/.bind9version b/.bind9version new file mode 100644 index 0000000..d5c45db --- /dev/null +++ b/.bind9version @@ -0,0 +1,43 @@ +# BIND9 9.18 LTS Support Branch + +Branch: 9.18 +Purpose: Long-term support for BIND9 9.18.x (ISC LTS release) +Status: Active +Support Level: Full + +## Version Information + +- **BIND9 Version**: 9.18.x (LTS) +- **Supported Until**: Aligned with ISC BIND9 9.18 LTS support timeline +- **Branch Base**: BIND9 9.18.44 (as of February 2026) + +## Supported Platforms + +- Debian 11 (Bullseye) +- Debian 12 (Bookworm) +- Debian 13 (Trixie) +- Ubuntu 20.04 LTS +- Ubuntu 22.04 LTS +- Ubuntu 24.04 LTS + +## Policies + +### Backporting +- ✅ Security fixes: Always backported +- ✅ Bug fixes: Backported if compatible +- ❌ New features: Case-by-case (no breaking changes) +- ❌ Breaking changes: Never + +### Release Numbering +Uses MAJOR.MINOR.PATCH (e.g., v1.2.3) + +## Key Documentation + +- [Version Support Policy](docs/VERSION_SUPPORT.md) +- [Configuration Grammar](CONFIGURATION_GRAMMAR.md) +- [Changelog](CHANGELOG.md) +- [README](README.md) + +## Next Major Version + +For BIND9 9.20+ support, see the `main` branch which will eventually have version-specific releases. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..3c6a784 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,114 @@ +# Changelog + +All notable changes to the ansible-bind9-role will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added +- Version support policy documentation in `docs/VERSION_SUPPORT.md` +- Branching strategy for supporting multiple BIND9 versions +- Grammar comparison tooling (`scripts/compare_bind_versions.py`) +- Grammar fetcher for upstream BIND9 sources (`scripts/fetch_bind_grammar.py`) +- Automated version difference tracking +- Operating system support matrix + +### Changed +- Established formal release management process +- Defined backporting policy for security, bugs, and features + +### Planned +- BIND9 9.20+ support in separate `9.20` branch +- Multi-platform molecule test matrix +- Automated BIND9 version detection in tasks +- Version-specific template conditional logic +- Enhanced CI/CD pipeline with version matrix testing + +## [1.0.0] - TBD + +### Initial Release +- Full support for BIND9 9.18.x (LTS) +- Configuration grammar based on BIND9 9.18.44 +- Comprehensive template system for all BIND9 statement types: + - `acl` + - `controls` + - `dlz` + - `dnssec-policy` + - `dyndb` + - `http` + - `key` + - `logging` + - `options` + - `parental-agents` + - `primaries` (masters) + - `server` + - `statistics-channels` + - `tls` + - `trust-anchors` + - `view` + - `zone` (all types: primary, secondary, forward, hint, stub, static-stub, mirror, redirect, in-view, delegation-only) +- Support for Debian 11, 12, 13 +- Support for Ubuntu 20.04, 22.04, 24.04 +- Molecule testing framework +- Configuration validation with `named-checkconf` +- Automatic configuration backup and rollback on errors +- Detailed configuration grammar documentation +- GPL-3.0-or-later license + +--- + +## Version History (Pre-Changelog) + +Prior to this changelog, the role was developed without formal version tracking. +This changelog starts with the establishment of the version support policy. + +--- + +## Versioning Schema + +- **MAJOR**: Incompatible changes to role variables or behavior +- **MINOR**: New features in a backwards compatible manner +- **PATCH**: Backwards compatible bug fixes + +### Branch-Specific Versioning + +- `main` branch: `vX.Y.Z` (BIND9 9.18 LTS) +- `9.20` branch: `v9.20.X[-suffix]` (BIND9 9.20+) + - Suffixes: `-alpha`, `-beta`, `-rc` for pre-releases + +## Release Types + +### Security Releases +Critical security fixes are released as patch versions and backported to all supported branches. + +### Feature Releases +New features are added in minor version increments. Breaking changes require major version increments. + +### Bug Fix Releases +Bug fixes are released as patch versions when they accumulate or for critical issues. + +## Upgrade Notes + +### From Pre-Versioned to v1.0.0 +The first official release establishes baseline compatibility. Users of pre-release versions should: +1. Review all role variables for any changes +2. Test in non-production environment +3. Review generated configuration with `named-checkconf` +4. Check `docs/VERSION_SUPPORT.md` for supported platforms + +### Future Upgrades +Check individual version sections above for specific upgrade notes and breaking changes. + +## Contributing + +See `docs/VERSION_SUPPORT.md` for contribution guidelines and release processes. + +## Links + +- [Version Support Policy](docs/VERSION_SUPPORT.md) +- [Configuration Grammar](CONFIGURATION_GRAMMAR.md) +- [Issue Tracker](https://git.valid.dk/daniel/ansible-bind9-role/issues) +- [Repository](https://git.valid.dk/daniel/ansible-bind9-role) + diff --git a/README.md b/README.md index 9491dee..6f5aa78 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,20 @@ bind9 ===== -A feature-complete ansible role for installing and configuring bind9. The purpose of this role is to fully template out the entire official bind9 configuration file format. +A feature-complete ansible role for installing and configuring bind9. The purpose of this role is to fully template out the entire official bind9 configuration file format. + +## Version Compatibility + +| BIND9 Version | Role Branch | Status | Supported Platforms | +|---------------|-------------|--------|---------------------| +| 9.18.x (LTS) | `main` | ✅ Supported | Debian 11-13, Ubuntu 20.04-24.04 | +| 9.20.x+ | `9.20` | 🚧 Planned | Debian 12-13, Ubuntu 22.04-24.04 | + +For detailed version support policy, branching strategy, and migration guidance, see [docs/VERSION_SUPPORT.md](docs/VERSION_SUPPORT.md). + +**Minimum Requirements:** +- Ansible: 2.13+ +- Python: 3.8+ What the role does: - Fully configures named.conf @@ -195,10 +208,30 @@ Simple sample config of a recursive BIND server that allows your localnetwork to allow-recursion: - mylan +## Documentation + +- **[Configuration Grammar Reference](CONFIGURATION_GRAMMAR.md)**: Comprehensive guide to all BIND9 configuration options +- **[Version Support Policy](docs/VERSION_SUPPORT.md)**: Supported versions, branching strategy, and release management +- **[Changelog](CHANGELOG.md)**: Version history and upgrade notes + +## Contributing + +Contributions are welcome! Please see [docs/VERSION_SUPPORT.md](docs/VERSION_SUPPORT.md) for: +- Branching strategy +- Testing requirements +- Backporting policies +- Release procedures + +## Links + +- **Repository**: https://git.valid.dk/daniel/ansible-bind9-role +- **Issues**: https://git.valid.dk/daniel/ansible-bind9-role/issues +- **BIND9 Documentation**: https://bind9.readthedocs.io/ + License ------- -BSD +GPL-3.0-or-later Author Information ------------------ diff --git a/bind9-grammar/upstream/README.md b/bind9-grammar/upstream/README.md new file mode 100644 index 0000000..14ae913 --- /dev/null +++ b/bind9-grammar/upstream/README.md @@ -0,0 +1,54 @@ +# BIND9 Grammar Files - Upstream Source + +This directory contains upstream BIND9 grammar files from the official BIND9 mirror for version comparison and validation. + +## Files to Fetch + +When grammar files are needed, fetch from: +- **Repository**: https://git.valid.dk/Mirrors/bind9 +- **9.18 Tag**: v9.18.44 +- **9.20 Tag**: v9.20.18 + +### Required Grammar Files (from doc/misc/) + +- options +- forward.zoneopt +- hint.zoneopt +- in-view.zoneopt +- mirror.zoneopt +- primary.zoneopt +- redirect.zoneopt +- secondary.zoneopt +- static-stub.zoneopt +- stub.zoneopt +- delegation-only.zoneopt +- rndc.grammar +- parsegrammar.py +- checkgrammar.py + +## Directory Structure + +``` +upstream/ +├── v9.18.44/ +│ ├── grammar/ (Grammar files) +│ └── metadata.json (Fetch metadata) +└── v9.20.18/ + ├── grammar/ (Grammar files) + └── metadata.json (Fetch metadata) +``` + +## Fetching + +Option 1: Using git fetch +```bash +git clone --depth 1 --branch v9.18.44 https://git.valid.dk/Mirrors/bind9.git /tmp/bind9-9.18 +cp /tmp/bind9-9.18/doc/misc/* bind9-grammar/upstream/v9.18.44/grammar/ +``` + +Option 2: Using Gitea MCP tools (see scripts/fetch_bind_grammar.py) + +## Scripts + +- `scripts/fetch_bind_grammar.py` - MCP-based fetcher template +- `scripts/compare_bind_versions.py` - Grammar comparison tool diff --git a/bind9-grammar/upstream/v9.18.44/grammar/delegation-only.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/delegation-only.zoneopt new file mode 100644 index 0000000..ab86327 --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/delegation-only.zoneopt @@ -0,0 +1,3 @@ +zone [ ] { + type delegation-only; +}; diff --git a/bind9-grammar/upstream/v9.18.44/grammar/forward.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/forward.zoneopt new file mode 100644 index 0000000..069f2ce --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/forward.zoneopt @@ -0,0 +1,6 @@ +zone [ ] { + type forward; + delegation-only ; // deprecated + forward ( first | only ); + forwarders [ port ] { ( | ) [ port ]; ... }; +}; diff --git a/bind9-grammar/upstream/v9.18.44/grammar/hint.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/hint.zoneopt new file mode 100644 index 0000000..d14c3ef --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/hint.zoneopt @@ -0,0 +1,6 @@ +zone [ ] { + type hint; + check-names ( fail | warn | ignore ); + delegation-only ; // deprecated + file ; +}; diff --git a/bind9-grammar/upstream/v9.18.44/grammar/in-view.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/in-view.zoneopt new file mode 100644 index 0000000..c63c427 --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/in-view.zoneopt @@ -0,0 +1,3 @@ +zone [ ] { + in-view ; +}; diff --git a/bind9-grammar/upstream/v9.18.44/grammar/mirror.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/mirror.zoneopt new file mode 100644 index 0000000..5f688ca --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/mirror.zoneopt @@ -0,0 +1,45 @@ +zone [ ] { + type mirror; + allow-notify { ; ... }; + allow-query { ; ... }; + allow-query-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update-forwarding { ; ... }; + also-notify [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + alt-transfer-source ( | * ) ; // deprecated + alt-transfer-source-v6 ( | * ) ; // deprecated + check-names ( fail | warn | ignore ); + database ; + file ; + ixfr-from-differences ; + journal ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-records ; + max-records-per-type ; + max-refresh-time ; + max-retry-time ; + max-transfer-idle-in ; + max-transfer-idle-out ; + max-transfer-time-in ; + max-transfer-time-out ; + max-types-per-name ; + min-refresh-time ; + min-retry-time ; + multi-master ; + notify ( explicit | master-only | primary-only | ); + notify-delay ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + primaries [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + request-expire ; + request-ixfr ; + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + try-tcp-refresh ; + use-alt-transfer-source ; // deprecated + zero-no-soa-ttl ; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.18.44/grammar/options b/bind9-grammar/upstream/v9.18.44/grammar/options new file mode 100644 index 0000000..871d6ad --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/options @@ -0,0 +1,604 @@ +acl { ; ... }; // may occur multiple times + +controls { + inet ( | | * ) [ port ( | * ) ] allow { ; ... } [ keys { ; ... } ] [ read-only ]; // may occur multiple times + unix perm owner group [ keys { ; ... } ] [ read-only ]; // may occur multiple times +}; // may occur multiple times + +dlz { + database ; + search ; +}; // may occur multiple times + +dnssec-policy { + dnskey-ttl ; + keys { ( csk | ksk | zsk ) [ ( key-directory ) ] lifetime algorithm [ ]; ... }; + max-zone-ttl ; + nsec3param [ iterations ] [ optout ] [ salt-length ]; + parent-ds-ttl ; + parent-propagation-delay ; + parent-registration-delay ; // obsolete + publish-safety ; + purge-keys ; + retire-safety ; + signatures-jitter ; + signatures-refresh ; + signatures-validity ; + signatures-validity-dnskey ; + zone-propagation-delay ; +}; // may occur multiple times + +dyndb { }; // may occur multiple times + +http { + endpoints { ; ... }; + listener-clients ; + streams-per-connection ; +}; // may occur multiple times + +key { + algorithm ; + secret ; +}; // may occur multiple times + +logging { + category { ; ... }; // may occur multiple times + channel { + buffered ; + file [ versions ( unlimited | ) ] [ size ] [ suffix ( increment | timestamp ) ]; + null; + print-category ; + print-severity ; + print-time ( iso8601 | iso8601-utc | local | ); + severity ; + stderr; + syslog [ ]; + }; // may occur multiple times +}; + +managed-keys { ( static-key | initial-key | static-ds | initial-ds ) ; ... }; // may occur multiple times, deprecated + +options { + allow-new-zones ; + allow-notify { ; ... }; + allow-query { ; ... }; + allow-query-cache { ; ... }; + allow-query-cache-on { ; ... }; + allow-query-on { ; ... }; + allow-recursion { ; ... }; + allow-recursion-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update { ; ... }; + allow-update-forwarding { ; ... }; + also-notify [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + alt-transfer-source ( | * ) ; // deprecated + alt-transfer-source-v6 ( | * ) ; // deprecated + answer-cookie ; + attach-cache ; + auth-nxdomain ; + auto-dnssec ( allow | maintain | off ) ; // deprecated + automatic-interface-scan ; + avoid-v4-udp-ports { ; ... }; // deprecated + avoid-v6-udp-ports { ; ... }; // deprecated + bindkeys-file ; + blackhole { ; ... }; + catalog-zones { zone [ default-primaries [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... } ] [ zone-directory ] [ in-memory ] [ min-update-interval ]; ... }; + check-dup-records ( fail | warn | ignore ); + check-integrity ; + check-mx ( fail | warn | ignore ); + check-mx-cname ( fail | warn | ignore ); + check-names ( primary | master | secondary | slave | response ) ( fail | warn | ignore ); // may occur multiple times + check-sibling ; + check-spf ( warn | ignore ); + check-srv-cname ( fail | warn | ignore ); + check-wildcard ; + clients-per-query ; + cookie-algorithm ( aes | siphash24 ); + cookie-secret ; // may occur multiple times + coresize ( default | unlimited | ); // deprecated + datasize ( default | unlimited | ); // deprecated + deny-answer-addresses { ; ... } [ except-from { ; ... } ]; + deny-answer-aliases { ; ... } [ except-from { ; ... } ]; + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + directory ; + disable-algorithms { ; ... }; // may occur multiple times + disable-ds-digests { ; ... }; // may occur multiple times + disable-empty-zone ; // may occur multiple times + dns64 { + break-dnssec ; + clients { ; ... }; + exclude { ; ... }; + mapped { ; ... }; + recursive-only ; + suffix ; + }; // may occur multiple times + dns64-contact ; + dns64-server ; + dnskey-sig-validity ; + dnsrps-enable ; // not configured + dnsrps-options { }; // not configured + dnssec-accept-expired ; + dnssec-dnskey-kskonly ; + dnssec-loadkeys-interval ; + dnssec-must-be-secure ; // may occur multiple times, deprecated + dnssec-policy ; + dnssec-secure-to-insecure ; + dnssec-update-mode ( maintain | no-resign ); + dnssec-validation ( yes | no | auto ); + dnstap { ( all | auth | client | forwarder | resolver | update ) [ ( query | response ) ]; ... }; // not configured + dnstap-identity ( | none | hostname ); // not configured + dnstap-output ( file | unix ) [ size ( unlimited | ) ] [ versions ( unlimited | ) ] [ suffix ( increment | timestamp ) ]; // not configured + dnstap-version ( | none ); // not configured + dscp ; // obsolete + dual-stack-servers [ port ] { ( [ port ] | [ port ] | [ port ] ); ... }; + dump-file ; + edns-udp-size ; + empty-contact ; + empty-server ; + empty-zones-enable ; + fetch-quota-params ; + fetches-per-server [ ( drop | fail ) ]; + fetches-per-zone [ ( drop | fail ) ]; + files ( default | unlimited | ); // deprecated + flush-zones-on-shutdown ; + forward ( first | only ); + forwarders [ port ] { ( | ) [ port ]; ... }; + fstrm-set-buffer-hint ; // not configured + fstrm-set-flush-timeout ; // not configured + fstrm-set-input-queue-size ; // not configured + fstrm-set-output-notify-threshold ; // not configured + fstrm-set-output-queue-model ( mpscs | spscs ); // not configured + fstrm-set-output-queue-size ; // not configured + fstrm-set-reopen-interval ; // not configured + geoip-directory ( | none ); + glue-cache ; // deprecated + heartbeat-interval ; // deprecated + hostname ( | none ); + http-listener-clients ; + http-port ; + http-streams-per-connection ; + https-port ; + interface-interval ; + ipv4only-contact ; + ipv4only-enable ; + ipv4only-server ; + ixfr-from-differences ( primary | master | secondary | slave | ); + keep-response-order { ; ... }; + key-directory ; + lame-ttl ; + listen-on [ port ] [ tls ] [ http ] { ; ... }; // may occur multiple times + listen-on-v6 [ port ] [ tls ] [ http ] { ; ... }; // may occur multiple times + lmdb-mapsize ; + lock-file ( | none ); + managed-keys-directory ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + match-mapped-addresses ; + max-cache-size ( default | unlimited | | ); + max-cache-ttl ; + max-clients-per-query ; + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-ncache-ttl ; + max-query-count ; + max-query-restarts ; + max-records ; + max-records-per-type ; + max-recursion-depth ; + max-recursion-queries ; + max-refresh-time ; + max-retry-time ; + max-rsa-exponent-size ; + max-stale-ttl ; + max-transfer-idle-in ; + max-transfer-idle-out ; + max-transfer-time-in ; + max-transfer-time-out ; + max-types-per-name ; + max-udp-size ; + maxz-zone-ttl ( unlimited | ); + memstatistics ; + memstatistics-file ; + message-compression ; + min-cache-ttl ; + min-ncache-ttl ; + min-refresh-time ; + min-retry-time ; + minimal-any ; + minimal-responses ( no-auth | no-auth-recursive | ); + multi-master ; + new-zones-directory ; + no-case-compress { ; ... }; + nocookie-udp-size ; + notify ( explicit | master-only | primary-only | ); + notify-delay ; + notify-rate ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + notify-to-soa ; + nsec3-test-zone ; // test only + nta-lifetime ; + nta-recheck ; + nxdomain-redirect ; + parental-source ( | * ) ; + parental-source-v6 ( | * ) ; + pid-file ( | none ); + port ; + preferred-glue ; + prefetch [ ]; + provide-ixfr ; + qname-minimization ( strict | relaxed | disabled | off ); + query-source [ address ] ( | * ); + query-source-v6 [ address ] ( | * ); + querylog ; + random-device ( | none ); // obsolete + rate-limit { + all-per-second ; + errors-per-second ; + exempt-clients { ; ... }; + ipv4-prefix-length ; + ipv6-prefix-length ; + log-only ; + max-table-size ; + min-table-size ; + nodata-per-second ; + nxdomains-per-second ; + qps-scale ; + referrals-per-second ; + responses-per-second ; + slip ; + window ; + }; + recurse-ing-file ; + recursion ; + recursive-clients ; + request-expire ; + request-ixfr ; + request-nsid ; + require-server-cookie ; + reserved-sockets ; // deprecated + resolver-nonbackoff-tries ; // deprecated + resolver-query-timeout ; + resolver-retry-interval ; // deprecated + response-padding { ; ... } block-size ; + response-policy { zone [ add-soa ] [ log ] [ max-policy-ttl ] [ min-update-interval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only ) ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ]; ... } [ add-soa ] [ break-dnssec ] [ max-policy-ttl ] [ min-update-interval ] [ min-ns-dots ] [ nsip-wait-recurse ] [ nsdname-wait-recurse ] [ qname-wait-recurse ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ] [ dnsrps-enable ] [ dnsrps-options { } ]; + reuse port ; + root-delegation-only [ exclude { ; ... } ]; // deprecated + root-key-sentinel ; + rrset-order { [ class ] [ type ] [ name ] ; ... }; + secroots-file ; + send-cookie ; + serial-query-rate ; + serial-update-method ( date | increment | unixtime ); + server-id ( | none | hostname ); + servfail-ttl ; + session-keyalg ; + session-keyfile ( | none ); + session-keyname ; + sig-signing-nodes ; + sig-signing-signatures ; + sig-signing-type ; + sig-validity-interval [ ]; + sortlist { ; ... }; + stacksize ( default | unlimited | ); // deprecated + stale-answer-client-timeout ( disabled | off | ); + stale-answer-enable ; + stale-answer-ttl ; + stale-cache-enable ; + stale-refresh-time ; + startup-notify-rate ; + statistics-file ; + suppress-initial-notify ; // obsolete + synth-from-dnssec ; + tcp-advertised-timeout ; + tcp-clients ; + tcp-idle-timeout ; + tcp-initial-timeout ; + tcp-keepalive-timeout ; + tcp-listen-queue ; + tcp-receive-buffer ; + tcp-send-buffer ; + tkey-dhkey ; // deprecated + tkey-domain ; // deprecated + tkey-gssapi-credential ; // deprecated + tkey-gssapi-keytab ; + tls-port ; + transfer-format ( many-answers | one-answer ); + transfer-message-size ; + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + transfers-in ; + transfers-out ; + transfers-per-ns ; + trust-anchor-telemetry ; + try-tcp-refresh ; + udp-receive-buffer ; + udp-send-buffer ; + update-check-ksk ; + update-quota ; + use-alt-transfer-source ; // deprecated + use-v4-udp-ports { ; ... }; // deprecated + use-v6-udp-ports { ; ... }; // deprecated + v6-bias ; + validate-except { ; ... }; + version ( | none ); + zero-no-soa-ttl ; + zero-no-soa-ttl-cache ; + zone-statistics ( full | terse | none | ); +}; + +parental-agents [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; // may occur multiple times + +plugin ( query ) [ { } ]; // may occur multiple times + +primaries [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; // may occur multiple times + +server { + bogus ; + edns ; + edns-udp-size ; + edns-version ; + keys ; + max-udp-size ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + padding ; + provide-ixfr ; + query-source [ address ] ( | * ); + query-source-v6 [ address ] ( | * ); + request-expire ; + request-ixfr ; + request-nsid ; + send-cookie ; + tcp-keepalive ; + tcp-only ; + transfer-format ( many-answers | one-answer ); + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + transfers ; +}; // may occur multiple times + +statistics-channels { + inet ( | | * ) [ port ( | * ) ] [ allow { ; ... } ]; // may occur multiple times +}; // may occur multiple times + +tls { + ca-file ; + cert-file ; + ciphers ; + dhparam-file ; + key-file ; + prefer-server-ciphers ; + protocols { ; ... }; + remote-hostname ; + session-tickets ; +}; // may occur multiple times + +trust-anchors { ( static-key | initial-key | static-ds | initial-ds ) ; ... }; // may occur multiple times + +trusted-keys { ; ... }; // may occur multiple times, deprecated + +view [ ] { + allow-new-zones ; + allow-notify { ; ... }; + allow-query { ; ... }; + allow-query-cache { ; ... }; + allow-query-cache-on { ; ... }; + allow-query-on { ; ... }; + allow-recursion { ; ... }; + allow-recursion-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update { ; ... }; + allow-update-forwarding { ; ... }; + also-notify [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + alt-transfer-source ( | * ) ; // deprecated + alt-transfer-source-v6 ( | * ) ; // deprecated + attach-cache ; + auth-nxdomain ; + auto-dnssec ( allow | maintain | off ) ; // deprecated + catalog-zones { zone [ default-primaries [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... } ] [ zone-directory ] [ in-memory ] [ min-update-interval ]; ... }; + check-dup-records ( fail | warn | ignore ); + check-integrity ; + check-mx ( fail | warn | ignore ); + check-mx-cname ( fail | warn | ignore ); + check-names ( primary | master | secondary | slave | response ) ( fail | warn | ignore ); // may occur multiple times + check-sibling ; + check-spf ( warn | ignore ); + check-srv-cname ( fail | warn | ignore ); + check-wildcard ; + clients-per-query ; + deny-answer-addresses { ; ... } [ except-from { ; ... } ]; + deny-answer-aliases { ; ... } [ except-from { ; ... } ]; + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + disable-algorithms { ; ... }; // may occur multiple times + disable-ds-digests { ; ... }; // may occur multiple times + disable-empty-zone ; // may occur multiple times + dlz { + database ; + search ; + }; // may occur multiple times + dns64 { + break-dnssec ; + clients { ; ... }; + exclude { ; ... }; + mapped { ; ... }; + recursive-only ; + suffix ; + }; // may occur multiple times + dns64-contact ; + dns64-server ; + dnskey-sig-validity ; + dnsrps-enable ; // not configured + dnsrps-options { }; // not configured + dnssec-accept-expired ; + dnssec-dnskey-kskonly ; + dnssec-loadkeys-interval ; + dnssec-must-be-secure ; // may occur multiple times, deprecated + dnssec-policy ; + dnssec-secure-to-insecure ; + dnssec-update-mode ( maintain | no-resign ); + dnssec-validation ( yes | no | auto ); + dnstap { ( all | auth | client | forwarder | resolver | update ) [ ( query | response ) ]; ... }; // not configured + dual-stack-servers [ port ] { ( [ port ] | [ port ] | [ port ] ); ... }; + dyndb { }; // may occur multiple times + edns-udp-size ; + empty-contact ; + empty-server ; + empty-zones-enable ; + fetch-quota-params ; + fetches-per-server [ ( drop | fail ) ]; + fetches-per-zone [ ( drop | fail ) ]; + forward ( first | only ); + forwarders [ port ] { ( | ) [ port ]; ... }; + glue-cache ; // deprecated + ipv4only-contact ; + ipv4only-enable ; + ipv4only-server ; + ixfr-from-differences ( primary | master | secondary | slave | ); + key { + algorithm ; + secret ; + }; // may occur multiple times + key-directory ; + lame-ttl ; + lmdb-mapsize ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + match-clients { ; ... }; + match-destinations { ; ... }; + match-recursive-only ; + max-cache-size ( default | unlimited | | ); + max-cache-ttl ; + max-clients-per-query ; + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-ncache-ttl ; + max-query-count ; + max-query-restarts ; + max-records ; + max-records-per-type ; + max-recursion-depth ; + max-recursion-queries ; + max-refresh-time ; + max-retry-time ; + max-stale-ttl ; + max-transfer-idle-in ; + max-transfer-idle-out ; + max-transfer-time-in ; + max-transfer-time-out ; + max-types-per-name ; + max-udp-size ; + maxz-zone-ttl ( unlimited | ); + message-compression ; + min-cache-ttl ; + min-ncache-ttl ; + min-refresh-time ; + min-retry-time ; + minimal-any ; + minimal-responses ( no-auth | no-auth-recursive | ); + multi-master ; + new-zones-directory ; + no-case-compress { ; ... }; + nocookie-udp-size ; + notify ( explicit | master-only | primary-only | ); + notify-delay ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + notify-to-soa ; + nsec3-test-zone ; // test only + nta-lifetime ; + nta-recheck ; + nxdomain-redirect ; + parental-source ( | * ) ; + parental-source-v6 ( | * ) ; + plugin ( query ) [ { } ]; // may occur multiple times + preferred-glue ; + prefetch [ ]; + provide-ixfr ; + qname-minimization ( strict | relaxed | disabled | off ); + query-source [ address ] ( | * ); + query-source-v6 [ address ] ( | * ); + rate-limit { + all-per-second ; + errors-per-second ; + exempt-clients { ; ... }; + ipv4-prefix-length ; + ipv6-prefix-length ; + log-only ; + max-table-size ; + min-table-size ; + nodata-per-second ; + nxdomains-per-second ; + qps-scale ; + referrals-per-second ; + responses-per-second ; + slip ; + window ; + }; + recursion ; + request-expire ; + request-ixfr ; + request-nsid ; + require-server-cookie ; + resolver-nonbackoff-tries ; // deprecated + resolver-query-timeout ; + resolver-retry-interval ; // deprecated + response-padding { ; ... } block-size ; + response-policy { zone [ add-soa ] [ log ] [ max-policy-ttl ] [ min-update-interval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only ) ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ]; ... } [ add-soa ] [ break-dnssec ] [ max-policy-ttl ] [ min-update-interval ] [ min-ns-dots ] [ nsip-wait-recurse ] [ nsdname-wait-recurse ] [ qname-wait-recurse ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ] [ dnsrps-enable ] [ dnsrps-options { } ]; + root-delegation-only [ exclude { ; ... } ]; // deprecated + root-key-sentinel ; + rrset-order { [ class ] [ type ] [ name ] ; ... }; + send-cookie ; + serial-update-method ( date | increment | unixtime ); + server { + bogus ; + edns ; + edns-udp-size ; + edns-version ; + keys ; + max-udp-size ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + padding ; + provide-ixfr ; + query-source [ address ] ( | * ); + query-source-v6 [ address ] ( | * ); + request-expire ; + request-ixfr ; + request-nsid ; + send-cookie ; + tcp-keepalive ; + tcp-only ; + transfer-format ( many-answers | one-answer ); + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + transfers ; + }; // may occur multiple times + servfail-ttl ; + sig-signing-nodes ; + sig-signing-signatures ; + sig-signing-type ; + sig-validity-interval [ ]; + sortlist { ; ... }; + stale-answer-client-timeout ( disabled | off | ); + stale-answer-enable ; + stale-answer-ttl ; + stale-cache-enable ; + stale-refresh-time ; + suppress-initial-notify ; // obsolete + synth-from-dnssec ; + transfer-format ( many-answers | one-answer ); + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + trust-anchor-telemetry ; + trust-anchors { ( static-key | initial-key | static-ds | initial-ds ) ; ... }; // may occur multiple times + trusted-keys { ; ... }; // may occur multiple times, deprecated + try-tcp-refresh ; + update-check-ksk ; + use-alt-transfer-source ; // deprecated + v6-bias ; + validate-except { ; ... }; + zero-no-soa-ttl ; + zero-no-soa-ttl-cache ; + zone-statistics ( full | terse | none | ); +}; // may occur multiple times diff --git a/bind9-grammar/upstream/v9.18.44/grammar/primary.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/primary.zoneopt new file mode 100644 index 0000000..6b54f0c --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/primary.zoneopt @@ -0,0 +1,64 @@ +zone [ ] { + type primary; + allow-query { ; ... }; + allow-query-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update { ; ... }; + also-notify [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + alt-transfer-source ( | * ) ; // deprecated + alt-transfer-source-v6 ( | * ) ; // deprecated + auto-dnssec ( allow | maintain | off ) ; // deprecated + check-dup-records ( fail | warn | ignore ); + check-integrity ; + check-mx ( fail | warn | ignore ); + check-mx-cname ( fail | warn | ignore ); + check-names ( fail | warn | ignore ); + check-sibling ; + check-spf ( warn | ignore ); + check-srv-cname ( fail | warn | ignore ); + check-wildcard ; + database ; + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + dlz ; + dnskey-sig-validity ; + dnssec-dnskey-kskonly ; + dnssec-loadkeys-interval ; + dnssec-policy ; + dnssec-secure-to-insecure ; + dnssec-update-mode ( maintain | no-resign ); + file ; + forward ( first | only ); + forwarders [ port ] { ( | ) [ port ]; ... }; + inline-signing ; + ixfr-from-differences ; + journal ; + key-directory ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-records ; + max-records-per-type ; + max-transfer-idle-out ; + max-transfer-time-out ; + max-types-per-name ; + max-zone-ttl ( unlimited | ); + notify ( explicit | master-only | primary-only | ); + notify-delay ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + notify-to-soa ; + nsec3-test-zone ; // test only + parental-agents [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + parental-source ( | * ) ; + parental-source-v6 ( | * ) ; + serial-update-method ( date | increment | unixtime ); + sig-signing-nodes ; + sig-signing-signatures ; + sig-signing-type ; + sig-validity-interval [ ]; + update-check-ksk ; + update-policy ( local | { ( deny | grant ) ( 6to4-self | external | krb5-self | krb5-selfsub | krb5-subdomain | krb5-subdomain-self-rhs | ms-self | ms-selfsub | ms-subdomain | ms-subdomain-self-rhs | name | self | selfsub | selfwild | subdomain | tcp-self | wildcard | zonesubject ) [ ] ; ... } ); + zero-no-soa-ttl ; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.18.44/grammar/redirect.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/redirect.zoneopt new file mode 100644 index 0000000..9d238c1 --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/redirect.zoneopt @@ -0,0 +1,15 @@ +zone [ ] { + type redirect; + allow-query { ; ... }; + allow-query-on { ; ... }; + dlz ; + file ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-records ; + max-records-per-type ; + max-types-per-name ; + max-zone-ttl ( unlimited | ); + primaries [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.18.44/grammar/rndc.grammar b/bind9-grammar/upstream/v9.18.44/grammar/rndc.grammar new file mode 100644 index 0000000..f28ec73 --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/rndc.grammar @@ -0,0 +1,20 @@ +key { + algorithm ; + secret ; +}; // may occur multiple times + +options { + default-key ; + default-port ; + default-server ; + default-source-address ( | * ); + default-source-address-v6 ( | * ); +}; + +server { + addresses { ( [ port ] | [ port ] | [ port ] ); ... }; + key ; + port ; + source-address ( | * ); + source-address-v6 ( | * ); +}; // may occur multiple times diff --git a/bind9-grammar/upstream/v9.18.44/grammar/secondary.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/secondary.zoneopt new file mode 100644 index 0000000..19fae5a --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/secondary.zoneopt @@ -0,0 +1,67 @@ +zone [ ] { + type secondary; + allow-notify { ; ... }; + allow-query { ; ... }; + allow-query-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update-forwarding { ; ... }; + also-notify [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + alt-transfer-source ( | * ) ; // deprecated + alt-transfer-source-v6 ( | * ) ; // deprecated + auto-dnssec ( allow | maintain | off ) ; // deprecated + check-names ( fail | warn | ignore ); + database ; + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + dlz ; + dnskey-sig-validity ; + dnssec-dnskey-kskonly ; + dnssec-loadkeys-interval ; + dnssec-policy ; + dnssec-update-mode ( maintain | no-resign ); + file ; + forward ( first | only ); + forwarders [ port ] { ( | ) [ port ]; ... }; + inline-signing ; + ixfr-from-differences ; + journal ; + key-directory ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-records ; + max-records-per-type ; + max-refresh-time ; + max-retry-time ; + max-transfer-idle-in ; + max-transfer-idle-out ; + max-transfer-time-in ; + max-transfer-time-out ; + max-types-per-name ; + min-refresh-time ; + min-retry-time ; + multi-master ; + notify ( explicit | master-only | primary-only | ); + notify-delay ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + notify-to-soa ; + nsec3-test-zone ; // test only + parental-agents [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + parental-source ( | * ) ; + parental-source-v6 ( | * ) ; + primaries [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + request-expire ; + request-ixfr ; + sig-signing-nodes ; + sig-signing-signatures ; + sig-signing-type ; + sig-validity-interval [ ]; + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + try-tcp-refresh ; + update-check-ksk ; + use-alt-transfer-source ; // deprecated + zero-no-soa-ttl ; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.18.44/grammar/static-stub.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/static-stub.zoneopt new file mode 100644 index 0000000..93a3220 --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/static-stub.zoneopt @@ -0,0 +1,13 @@ +zone [ ] { + type static-stub; + allow-query { ; ... }; + allow-query-on { ; ... }; + forward ( first | only ); + forwarders [ port ] { ( | ) [ port ]; ... }; + max-records ; + max-records-per-type ; + max-types-per-name ; + server-addresses { ( | ); ... }; + server-names { ; ... }; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.18.44/grammar/stub.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/stub.zoneopt new file mode 100644 index 0000000..2834682 --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/stub.zoneopt @@ -0,0 +1,29 @@ +zone [ ] { + type stub; + allow-query { ; ... }; + allow-query-on { ; ... }; + check-names ( fail | warn | ignore ); + database ; + delegation-only ; // deprecated + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + file ; + forward ( first | only ); + forwarders [ port ] { ( | ) [ port ]; ... }; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-records ; + max-records-per-type ; + max-refresh-time ; + max-retry-time ; + max-transfer-idle-in ; + max-transfer-time-in ; + max-types-per-name ; + min-refresh-time ; + min-retry-time ; + multi-master ; + primaries [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + use-alt-transfer-source ; // deprecated + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.20.18/grammar/forward.zoneopt b/bind9-grammar/upstream/v9.20.18/grammar/forward.zoneopt new file mode 100644 index 0000000..a0d26b1 --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/forward.zoneopt @@ -0,0 +1,5 @@ +zone [ ] { + type forward; + forward ( first | only ); + forwarders [ port ] [ tls ] { ( | ) [ port ] [ tls ]; ... }; +}; diff --git a/bind9-grammar/upstream/v9.20.18/grammar/hint.zoneopt b/bind9-grammar/upstream/v9.20.18/grammar/hint.zoneopt new file mode 100644 index 0000000..2d2c98d --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/hint.zoneopt @@ -0,0 +1,5 @@ +zone [ ] { + type hint; + check-names ( fail | warn | ignore ); + file ; +}; diff --git a/bind9-grammar/upstream/v9.20.18/grammar/in-view.zoneopt b/bind9-grammar/upstream/v9.20.18/grammar/in-view.zoneopt new file mode 100644 index 0000000..c63c427 --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/in-view.zoneopt @@ -0,0 +1,3 @@ +zone [ ] { + in-view ; +}; diff --git a/bind9-grammar/upstream/v9.20.18/grammar/mirror.zoneopt b/bind9-grammar/upstream/v9.20.18/grammar/mirror.zoneopt new file mode 100644 index 0000000..2e491cc --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/mirror.zoneopt @@ -0,0 +1,44 @@ +zone [ ] { + type mirror; + allow-notify { ; ... }; + allow-query { ; ... }; + allow-query-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update-forwarding { ; ... }; + also-notify [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + check-names ( fail | warn | ignore ); + database ; + file ; + ixfr-from-differences ; + journal ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-records ; + max-records-per-type ; + max-refresh-time ; + max-retry-time ; + max-transfer-idle-in ; + max-transfer-idle-out ; + max-transfer-time-in ; + max-transfer-time-out ; + max-types-per-name ; + min-refresh-time ; + min-retry-time ; + min-transfer-rate-in ; + multi-master ; + notify ( explicit | master-only | primary-only | ); + notify-defer ; + notify-delay ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + primaries [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + request-expire ; + request-ixfr ; + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + try-tcp-refresh ; + zero-no-soa-ttl ; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.20.18/grammar/options b/bind9-grammar/upstream/v9.20.18/grammar/options new file mode 100644 index 0000000..44ae262 --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/options @@ -0,0 +1,605 @@ +acl { ; ... }; // may occur multiple times + +controls { + inet ( | | * ) [ port ( | * ) ] allow { ; ... } [ keys { ; ... } ] [ read-only ]; // may occur multiple times + unix perm owner group [ keys { ; ... } ] [ read-only ]; // may occur multiple times +}; // may occur multiple times + +dlz { + database ; + search ; +}; // may occur multiple times + +dnssec-policy { + cdnskey ; + cds-digest-types { ; ... }; + dnskey-ttl ; + inline-signing ; + keys { ( csk | ksk | zsk ) [ key-directory | key-store ] lifetime algorithm [ tag-range ] [ ]; ... }; + manual-mode ; + max-zone-ttl ; + nsec3param [ iterations ] [ optout ] [ salt-length ]; + offline-ksk ; + parent-ds-ttl ; + parent-propagation-delay ; + publish-safety ; + purge-keys ; + retire-safety ; + signatures-jitter ; + signatures-refresh ; + signatures-validity ; + signatures-validity-dnskey ; + zone-propagation-delay ; +}; // may occur multiple times + +dyndb { }; // may occur multiple times + +http { + endpoints { ; ... }; + listener-clients ; + streams-per-connection ; +}; // may occur multiple times + +key { + algorithm ; + secret ; +}; // may occur multiple times + +key-store { + directory ; + pkcs11-uri ; +}; // may occur multiple times + +logging { + category { ; ... }; // may occur multiple times + channel { + buffered ; + file [ versions ( unlimited | ) ] [ size ] [ suffix ( increment | timestamp ) ]; + null; + print-category ; + print-severity ; + print-time ( iso8601 | iso8601-utc | local | ); + severity ; + stderr; + syslog [ ]; + }; // may occur multiple times +}; + +managed-keys { ( static-key | initial-key | static-ds | initial-ds ) ; ... }; // may occur multiple times, deprecated + +options { + allow-new-zones ; + allow-notify { ; ... }; + allow-proxy { ; ... }; // experimental + allow-proxy-on { ; ... }; // experimental + allow-query { ; ... }; + allow-query-cache { ; ... }; + allow-query-cache-on { ; ... }; + allow-query-on { ; ... }; + allow-recursion { ; ... }; + allow-recursion-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update { ; ... }; + allow-update-forwarding { ; ... }; + also-notify [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + answer-cookie ; + attach-cache ; + auth-nxdomain ; + automatic-interface-scan ; + avoid-v4-udp-ports { ; ... }; // deprecated + avoid-v6-udp-ports { ; ... }; // deprecated + bindkeys-file ; // test only + blackhole { ; ... }; + catalog-zones { zone [ default-primaries [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... } ] [ zone-directory ] [ in-memory ] [ min-update-interval ]; ... }; + check-dup-records ( fail | warn | ignore ); + check-integrity ; + check-mx ( fail | warn | ignore ); + check-mx-cname ( fail | warn | ignore ); + check-names ( primary | master | secondary | slave | response ) ( fail | warn | ignore ); // may occur multiple times + check-sibling ; + check-spf ( warn | ignore ); + check-srv-cname ( fail | warn | ignore ); + check-svcb ; + check-wildcard ; + clients-per-query ; + cookie-algorithm ( siphash24 ); + cookie-secret ; // may occur multiple times + deny-answer-addresses { ; ... } [ except-from { ; ... } ]; + deny-answer-aliases { ; ... } [ except-from { ; ... } ]; + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + directory ; + disable-algorithms { ; ... }; // may occur multiple times + disable-ds-digests { ; ... }; // may occur multiple times + disable-empty-zone ; // may occur multiple times + dns64 { + break-dnssec ; + clients { ; ... }; + exclude { ; ... }; + mapped { ; ... }; + recursive-only ; + suffix ; + }; // may occur multiple times + dns64-contact ; + dns64-server ; + dnskey-sig-validity ; // obsolete + dnsrps-enable ; // not configured + dnsrps-library ; // not configured + dnsrps-options { }; // not configured + dnssec-accept-expired ; + dnssec-dnskey-kskonly ; // obsolete + dnssec-loadkeys-interval ; + dnssec-must-be-secure ; // may occur multiple times, deprecated + dnssec-policy ; + dnssec-secure-to-insecure ; // obsolete + dnssec-update-mode ( maintain | no-resign ) ; // obsolete + dnssec-validation ( yes | no | auto ); + dnstap { ( all | auth | client | forwarder | resolver | update ) [ ( query | response ) ]; ... }; // not configured + dnstap-identity ( | none | hostname ); // not configured + dnstap-output ( file | unix ) [ size ( unlimited | ) ] [ versions ( unlimited | ) ] [ suffix ( increment | timestamp ) ]; // not configured + dnstap-version ( | none ); // not configured + dual-stack-servers [ port ] { ( [ port ] | [ port ] | [ port ] ); ... }; + dump-file ; + edns-udp-size ; + empty-contact ; + empty-server ; + empty-zones-enable ; + fetch-quota-params ; + fetches-per-server [ ( drop | fail ) ]; + fetches-per-zone [ ( drop | fail ) ]; + flush-zones-on-shutdown ; + forward ( first | only ); + forwarders [ port ] [ tls ] { ( | ) [ port ] [ tls ]; ... }; + fstrm-set-buffer-hint ; // not configured + fstrm-set-flush-timeout ; // not configured + fstrm-set-input-queue-size ; // not configured + fstrm-set-output-notify-threshold ; // not configured + fstrm-set-output-queue-model ( mpscs | spscs ); // not configured + fstrm-set-output-queue-size ; // not configured + fstrm-set-reopen-interval ; // not configured + geoip-directory ( | none ); + hostname ( | none ); + http-listener-clients ; + http-port ; + http-streams-per-connection ; + https-port ; + interface-interval ; + ipv4only-contact ; + ipv4only-enable ; + ipv4only-server ; + ixfr-from-differences ( primary | master | secondary | slave | ); + key-directory ; + lame-ttl ; + listen-on [ port ] [ proxy ] [ tls ] [ http ] { ; ... }; // may occur multiple times + listen-on-v6 [ port ] [ proxy ] [ tls ] [ http ] { ; ... }; // may occur multiple times + lmdb-mapsize ; + managed-keys-directory ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + match-mapped-addresses ; + max-cache-size ( default | unlimited | | ); + max-cache-ttl ; + max-clients-per-query ; + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-ncache-ttl ; + max-query-count ; + max-query-restarts ; + max-records ; + max-records-per-type ; + max-recursion-depth ; + max-recursion-queries ; + max-refresh-time ; + max-retry-time ; + max-rsa-exponent-size ; + max-stale-ttl ; + max-transfer-idle-in ; + max-transfer-idle-out ; + max-transfer-time-in ; + max-transfer-time-out ; + max-types-per-name ; + max-udp-size ; + max-validation-failures-per-fetch ; // experimental + max-validations-per-fetch ; // experimental + memstatistics ; + memstatistics-file ; + message-compression ; + min-cache-ttl ; + min-ncache-ttl ; + min-refresh-time ; + min-retry-time ; + min-transfer-rate-in ; + minimal-any ; + minimal-responses ( no-auth | no-auth-recursive | ); + multi-master ; + new-zones-directory ; + no-case-compress { ; ... }; + nocookie-udp-size ; + notify ( explicit | master-only | primary-only | ); + notify-defer ; + notify-delay ; + notify-rate ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + notify-to-soa ; + nsec3-test-zone ; // test only + nta-lifetime ; + nta-recheck ; + nxdomain-redirect ; + parental-source ( | * ) ; + parental-source-v6 ( | * ) ; + pid-file ( | none ); + port ; + preferred-glue ; + prefetch [ ]; + provide-ixfr ; + qname-minimization ( strict | relaxed | disabled | off ); + query-source [ address ] ( | * | none ); + query-source-v6 [ address ] ( | * | none ); + querylog ; + rate-limit { + all-per-second ; + errors-per-second ; + exempt-clients { ; ... }; + ipv4-prefix-length ; + ipv6-prefix-length ; + log-only ; + max-table-size ; + min-table-size ; + nodata-per-second ; + nxdomains-per-second ; + qps-scale ; + referrals-per-second ; + responses-per-second ; + slip ; + window ; + }; + recursing-file ; + recursion ; + recursive-clients ; + request-expire ; + request-ixfr ; + request-nsid ; + require-server-cookie ; + resolver-query-timeout ; + resolver-use-dns64 ; + response-padding { ; ... } block-size ; + response-policy { zone [ add-soa ] [ log ] [ max-policy-ttl ] [ min-update-interval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only ) ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ] [ ede ]; ... } [ add-soa ] [ break-dnssec ] [ max-policy-ttl ] [ min-update-interval ] [ min-ns-dots ] [ nsip-wait-recurse ] [ nsdname-wait-recurse ] [ qname-wait-recurse ] [ recursive-only ] [ servfail-until-ready ] [ nsip-enable ] [ nsdname-enable ] [ dnsrps-enable ] [ dnsrps-options { } ]; + responselog ; + reuseport ; + root-key-sentinel ; + rrset-order { [ class ] [ type ] [ name ] ; ... }; + secroots-file ; + send-cookie ; + serial-query-rate ; + serial-update-method ( date | increment | unixtime ); + server-id ( | none | hostname ); + servfail-ttl ; + session-keyalg ; + session-keyfile ( | none ); + session-keyname ; + sig-signing-nodes ; + sig-signing-signatures ; + sig-signing-type ; + sig-validity-interval [ ]; // obsolete + sig0-checks-quota ; // experimental + sig0-checks-quota-exempt { ; ... }; // experimental + sig0-key-checks-limit ; + sig0-message-checks-limit ; + sortlist { ; ... }; // deprecated + stale-answer-client-timeout ( disabled | off | ); + stale-answer-enable ; + stale-answer-ttl ; + stale-cache-enable ; + stale-refresh-time ; + startup-notify-rate ; + statistics-file ; + synth-from-dnssec ; + tcp-advertised-timeout ; + tcp-clients ; + tcp-idle-timeout ; + tcp-initial-timeout ; + tcp-keepalive-timeout ; + tcp-listen-queue ; + tcp-receive-buffer ; + tcp-send-buffer ; + tkey-domain ; // obsolete + tkey-gssapi-keytab ; + tls-port ; + transfer-format ( many-answers | one-answer ); + transfer-message-size ; + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + transfers-in ; + transfers-out ; + transfers-per-ns ; + trust-anchor-telemetry ; + try-tcp-refresh ; + udp-receive-buffer ; + udp-send-buffer ; + update-check-ksk ; // obsolete + update-quota ; + use-v4-udp-ports { ; ... }; // deprecated + use-v6-udp-ports { ; ... }; // deprecated + v6-bias ; + validate-except { ; ... }; + version ( | none ); + zero-no-soa-ttl ; + zero-no-soa-ttl-cache ; + zone-statistics ( full | terse | none | ); +}; + +plugin ( query ) [ { } ]; // may occur multiple times + +remote-servers [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; // may occur multiple times + +server { + bogus ; + edns ; + edns-udp-size ; + edns-version ; + keys ; + max-udp-size ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + padding ; + provide-ixfr ; + query-source [ address ] ( | * ); + query-source-v6 [ address ] ( | * ); + request-expire ; + request-ixfr ; + request-nsid ; + require-cookie ; + send-cookie ; + tcp-keepalive ; + tcp-only ; + transfer-format ( many-answers | one-answer ); + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + transfers ; +}; // may occur multiple times + +statistics-channels { + inet ( | | * ) [ port ( | * ) ] [ allow { ; ... } ]; // may occur multiple times +}; // may occur multiple times + +tls { + ca-file ; + cert-file ; + cipher-suites ; + ciphers ; + dhparam-file ; + key-file ; + prefer-server-ciphers ; + protocols { ; ... }; + remote-hostname ; + session-tickets ; +}; // may occur multiple times + +trust-anchors { ( static-key | initial-key | static-ds | initial-ds ) ; ... }; // may occur multiple times + +trusted-keys { ; ... }; // may occur multiple times, deprecated + +view [ ] { + allow-new-zones ; + allow-notify { ; ... }; + allow-proxy { ; ... }; // experimental + allow-proxy-on { ; ... }; // experimental + allow-query { ; ... }; + allow-query-cache { ; ... }; + allow-query-cache-on { ; ... }; + allow-query-on { ; ... }; + allow-recursion { ; ... }; + allow-recursion-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update { ; ... }; + allow-update-forwarding { ; ... }; + also-notify [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + attach-cache ; + auth-nxdomain ; + catalog-zones { zone [ default-primaries [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... } ] [ zone-directory ] [ in-memory ] [ min-update-interval ]; ... }; + check-dup-records ( fail | warn | ignore ); + check-integrity ; + check-mx ( fail | warn | ignore ); + check-mx-cname ( fail | warn | ignore ); + check-names ( primary | master | secondary | slave | response ) ( fail | warn | ignore ); // may occur multiple times + check-sibling ; + check-spf ( warn | ignore ); + check-srv-cname ( fail | warn | ignore ); + check-svcb ; + check-wildcard ; + clients-per-query ; + deny-answer-addresses { ; ... } [ except-from { ; ... } ]; + deny-answer-aliases { ; ... } [ except-from { ; ... } ]; + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + disable-algorithms { ; ... }; // may occur multiple times + disable-ds-digests { ; ... }; // may occur multiple times + disable-empty-zone ; // may occur multiple times + dlz { + database ; + search ; + }; // may occur multiple times + dns64 { + break-dnssec ; + clients { ; ... }; + exclude { ; ... }; + mapped { ; ... }; + recursive-only ; + suffix ; + }; // may occur multiple times + dns64-contact ; + dns64-server ; + dnskey-sig-validity ; // obsolete + dnsrps-enable ; // not configured + dnsrps-options { }; // not configured + dnssec-accept-expired ; + dnssec-dnskey-kskonly ; // obsolete + dnssec-loadkeys-interval ; + dnssec-must-be-secure ; // may occur multiple times, deprecated + dnssec-policy ; + dnssec-secure-to-insecure ; // obsolete + dnssec-update-mode ( maintain | no-resign ) ; // obsolete + dnssec-validation ( yes | no | auto ); + dnstap { ( all | auth | client | forwarder | resolver | update ) [ ( query | response ) ]; ... }; // not configured + dual-stack-servers [ port ] { ( [ port ] | [ port ] | [ port ] ); ... }; + dyndb { }; // may occur multiple times + edns-udp-size ; + empty-contact ; + empty-server ; + empty-zones-enable ; + fetch-quota-params ; + fetches-per-server [ ( drop | fail ) ]; + fetches-per-zone [ ( drop | fail ) ]; + forward ( first | only ); + forwarders [ port ] [ tls ] { ( | ) [ port ] [ tls ]; ... }; + ipv4only-contact ; + ipv4only-enable ; + ipv4only-server ; + ixfr-from-differences ( primary | master | secondary | slave | ); + key { + algorithm ; + secret ; + }; // may occur multiple times + key-directory ; + lame-ttl ; + lmdb-mapsize ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + match-clients { ; ... }; + match-destinations { ; ... }; + match-recursive-only ; + max-cache-size ( default | unlimited | | ); + max-cache-ttl ; + max-clients-per-query ; + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-ncache-ttl ; + max-query-count ; + max-query-restarts ; + max-records ; + max-records-per-type ; + max-recursion-depth ; + max-recursion-queries ; + max-refresh-time ; + max-retry-time ; + max-stale-ttl ; + max-transfer-idle-in ; + max-transfer-idle-out ; + max-transfer-time-in ; + max-transfer-time-out ; + max-types-per-name ; + max-udp-size ; + max-validation-failures-per-fetch ; // experimental + max-validations-per-fetch ; // experimental + message-compression ; + min-cache-ttl ; + min-ncache-ttl ; + min-refresh-time ; + min-retry-time ; + min-transfer-rate-in ; + minimal-any ; + minimal-responses ( no-auth | no-auth-recursive | ); + multi-master ; + new-zones-directory ; + no-case-compress { ; ... }; + nocookie-udp-size ; + notify ( explicit | master-only | primary-only | ); + notify-defer ; + notify-delay ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + notify-to-soa ; + nsec3-test-zone ; // test only + nta-lifetime ; + nta-recheck ; + nxdomain-redirect ; + parental-source ( | * ) ; + parental-source-v6 ( | * ) ; + plugin ( query ) [ { } ]; // may occur multiple times + preferred-glue ; + prefetch [ ]; + provide-ixfr ; + qname-minimization ( strict | relaxed | disabled | off ); + query-source [ address ] ( | * | none ); + query-source-v6 [ address ] ( | * | none ); + rate-limit { + all-per-second ; + errors-per-second ; + exempt-clients { ; ... }; + ipv4-prefix-length ; + ipv6-prefix-length ; + log-only ; + max-table-size ; + min-table-size ; + nodata-per-second ; + nxdomains-per-second ; + qps-scale ; + referrals-per-second ; + responses-per-second ; + slip ; + window ; + }; + recursion ; + request-expire ; + request-ixfr ; + request-nsid ; + require-server-cookie ; + resolver-query-timeout ; + resolver-use-dns64 ; + response-padding { ; ... } block-size ; + response-policy { zone [ add-soa ] [ log ] [ max-policy-ttl ] [ min-update-interval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only ) ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ] [ ede ]; ... } [ add-soa ] [ break-dnssec ] [ max-policy-ttl ] [ min-update-interval ] [ min-ns-dots ] [ nsip-wait-recurse ] [ nsdname-wait-recurse ] [ qname-wait-recurse ] [ recursive-only ] [ servfail-until-ready ] [ nsip-enable ] [ nsdname-enable ] [ dnsrps-enable ] [ dnsrps-options { } ]; + root-key-sentinel ; + rrset-order { [ class ] [ type ] [ name ] ; ... }; + send-cookie ; + serial-update-method ( date | increment | unixtime ); + server { + bogus ; + edns ; + edns-udp-size ; + edns-version ; + keys ; + max-udp-size ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + padding ; + provide-ixfr ; + query-source [ address ] ( | * ); + query-source-v6 [ address ] ( | * ); + request-expire ; + request-ixfr ; + request-nsid ; + require-cookie ; + send-cookie ; + tcp-keepalive ; + tcp-only ; + transfer-format ( many-answers | one-answer ); + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + transfers ; + }; // may occur multiple times + servfail-ttl ; + sig-signing-nodes ; + sig-signing-signatures ; + sig-signing-type ; + sig-validity-interval [ ]; // obsolete + sig0-key-checks-limit ; + sig0-message-checks-limit ; + sortlist { ; ... }; // deprecated + stale-answer-client-timeout ( disabled | off | ); + stale-answer-enable ; + stale-answer-ttl ; + stale-cache-enable ; + stale-refresh-time ; + synth-from-dnssec ; + transfer-format ( many-answers | one-answer ); + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + trust-anchor-telemetry ; + trust-anchors { ( static-key | initial-key | static-ds | initial-ds ) ; ... }; // may occur multiple times + trusted-keys { ; ... }; // may occur multiple times, deprecated + try-tcp-refresh ; + v6-bias ; + validate-except { ; ... }; + zero-no-soa-ttl ; + zero-no-soa-ttl-cache ; + zone-statistics ( full | terse | none | ); +}; // may occur multiple times diff --git a/bind9-grammar/upstream/v9.20.18/grammar/primary.zoneopt b/bind9-grammar/upstream/v9.20.18/grammar/primary.zoneopt new file mode 100644 index 0000000..d4b1667 --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/primary.zoneopt @@ -0,0 +1,63 @@ +zone [ ] { + type primary; + allow-query { ; ... }; + allow-query-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update { ; ... }; + also-notify [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + check-dup-records ( fail | warn | ignore ); + check-integrity ; + check-mx ( fail | warn | ignore ); + check-mx-cname ( fail | warn | ignore ); + check-names ( fail | warn | ignore ); + check-sibling ; + check-spf ( warn | ignore ); + check-srv-cname ( fail | warn | ignore ); + check-svcb ; + check-wildcard ; + checkds ( explicit | ); + database ; + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + dlz ; + dnskey-sig-validity ; // obsolete + dnssec-dnskey-kskonly ; // obsolete + dnssec-loadkeys-interval ; + dnssec-policy ; + dnssec-secure-to-insecure ; // obsolete + dnssec-update-mode ( maintain | no-resign ) ; // obsolete + file ; + forward ( first | only ); + forwarders [ port ] [ tls ] { ( | ) [ port ] [ tls ]; ... }; + inline-signing ; + ixfr-from-differences ; + journal ; + key-directory ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-records ; + max-records-per-type ; + max-transfer-idle-out ; + max-transfer-time-out ; + max-types-per-name ; + max-zone-ttl ( unlimited | ); // deprecated + notify ( explicit | master-only | primary-only | ); + notify-defer ; + notify-delay ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + notify-to-soa ; + nsec3-test-zone ; // test only + parental-agents [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + parental-source ( | * ) ; + parental-source-v6 ( | * ) ; + serial-update-method ( date | increment | unixtime ); + sig-signing-nodes ; + sig-signing-signatures ; + sig-signing-type ; + sig-validity-interval [ ]; // obsolete + update-policy ( local | { ( deny | grant ) ( 6to4-self | external | krb5-self | krb5-selfsub | krb5-subdomain | krb5-subdomain-self-rhs | ms-self | ms-selfsub | ms-subdomain | ms-subdomain-self-rhs | name | self | selfsub | selfwild | subdomain | tcp-self | wildcard | zonesub ) [ ] ; ... } ); + zero-no-soa-ttl ; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.20.18/grammar/redirect.zoneopt b/bind9-grammar/upstream/v9.20.18/grammar/redirect.zoneopt new file mode 100644 index 0000000..f457c80 --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/redirect.zoneopt @@ -0,0 +1,15 @@ +zone [ ] { + type redirect; + allow-query { ; ... }; + allow-query-on { ; ... }; + dlz ; + file ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-records ; + max-records-per-type ; + max-types-per-name ; + max-zone-ttl ( unlimited | ); // deprecated + primaries [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.20.18/grammar/rndc.grammar b/bind9-grammar/upstream/v9.20.18/grammar/rndc.grammar new file mode 100644 index 0000000..f28ec73 --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/rndc.grammar @@ -0,0 +1,20 @@ +key { + algorithm ; + secret ; +}; // may occur multiple times + +options { + default-key ; + default-port ; + default-server ; + default-source-address ( | * ); + default-source-address-v6 ( | * ); +}; + +server { + addresses { ( [ port ] | [ port ] | [ port ] ); ... }; + key ; + port ; + source-address ( | * ); + source-address-v6 ( | * ); +}; // may occur multiple times diff --git a/bind9-grammar/upstream/v9.20.18/grammar/secondary.zoneopt b/bind9-grammar/upstream/v9.20.18/grammar/secondary.zoneopt new file mode 100644 index 0000000..2c07b9c --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/secondary.zoneopt @@ -0,0 +1,66 @@ +zone [ ] { + type secondary; + allow-notify { ; ... }; + allow-query { ; ... }; + allow-query-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update-forwarding { ; ... }; + also-notify [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + check-names ( fail | warn | ignore ); + checkds ( explicit | ); + database ; + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + dlz ; + dnskey-sig-validity ; // obsolete + dnssec-dnskey-kskonly ; // obsolete + dnssec-loadkeys-interval ; + dnssec-policy ; + dnssec-update-mode ( maintain | no-resign ) ; // obsolete + file ; + forward ( first | only ); + forwarders [ port ] [ tls ] { ( | ) [ port ] [ tls ]; ... }; + inline-signing ; + ixfr-from-differences ; + journal ; + key-directory ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-records ; + max-records-per-type ; + max-refresh-time ; + max-retry-time ; + max-transfer-idle-in ; + max-transfer-idle-out ; + max-transfer-time-in ; + max-transfer-time-out ; + max-types-per-name ; + min-refresh-time ; + min-retry-time ; + min-transfer-rate-in ; + multi-master ; + notify ( explicit | master-only | primary-only | ); + notify-defer ; + notify-delay ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + notify-to-soa ; + nsec3-test-zone ; // test only + parental-agents [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + parental-source ( | * ) ; + parental-source-v6 ( | * ) ; + primaries [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + request-expire ; + request-ixfr ; + sig-signing-nodes ; + sig-signing-signatures ; + sig-signing-type ; + sig-validity-interval [ ]; // obsolete + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + try-tcp-refresh ; + update-check-ksk ; // obsolete + zero-no-soa-ttl ; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.20.18/grammar/static-stub.zoneopt b/bind9-grammar/upstream/v9.20.18/grammar/static-stub.zoneopt new file mode 100644 index 0000000..40a340f --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/static-stub.zoneopt @@ -0,0 +1,13 @@ +zone [ ] { + type static-stub; + allow-query { ; ... }; + allow-query-on { ; ... }; + forward ( first | only ); + forwarders [ port ] [ tls ] { ( | ) [ port ] [ tls ]; ... }; + max-records ; + max-records-per-type ; + max-types-per-name ; + server-addresses { ( | ); ... }; + server-names { ; ... }; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.20.18/grammar/stub.zoneopt b/bind9-grammar/upstream/v9.20.18/grammar/stub.zoneopt new file mode 100644 index 0000000..abbc89d --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/stub.zoneopt @@ -0,0 +1,28 @@ +zone [ ] { + type stub; + allow-query { ; ... }; + allow-query-on { ; ... }; + check-names ( fail | warn | ignore ); + database ; + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + file ; + forward ( first | only ); + forwarders [ port ] [ tls ] { ( | ) [ port ] [ tls ]; ... }; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-records ; + max-records-per-type ; + max-refresh-time ; + max-retry-time ; + max-transfer-idle-in ; + max-transfer-time-in ; + max-types-per-name ; + min-refresh-time ; + min-retry-time ; + min-transfer-rate-in ; + multi-master ; + primaries [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + zone-statistics ( full | terse | none | ); +}; diff --git a/docs/VERSION_SUPPORT.md b/docs/VERSION_SUPPORT.md new file mode 100644 index 0000000..6009f61 --- /dev/null +++ b/docs/VERSION_SUPPORT.md @@ -0,0 +1,370 @@ +# BIND9 Version Support Policy + +**Document Version**: 1.0 +**Last Updated**: 2026-02-07 +**Role Version**: Current development + +## Overview + +This document defines the version maintenance strategy for the ansible-bind9-role, including supported BIND9 versions, OS platforms, branching strategy, and release management policies. + +## Supported Versions + +### BIND9 Versions + +| BIND9 Version | Branch | Status | Support Level | EOL Date | +|---------------|--------|--------|---------------|----------| +| 9.18.x (LTS) | `main` | ✅ Active | Full support | TBD (following ISC LTS timeline) | +| 9.20.x+ | `9.20` | 🚧 In Development | Planned | N/A | + +#### Version Selection Rationale + +- **BIND9 9.18**: Long Term Support (LTS) release from ISC + - Maintained by ISC with extended support timeline + - Stable feature set suitable for production environments + - Current focus of this role + +- **BIND9 9.20+**: Feature release series + - Introduces significant configuration changes + - New features and modernization + - May have shorter support windows per release + - Will be supported in separate branch to prevent breaking changes + +### Operating System Support Matrix + +| OS Distribution | Versions | BIND9 9.18 | BIND9 9.20+ | Notes | +|----------------|----------|------------|-------------|-------| +| Debian | 11 (Bullseye) | ✅ Supported | 🔍 Testing | Current stable | +| Debian | 12 (Bookworm) | ✅ Supported | ✅ Supported | Current testing focus | +| Debian | 13 (Trixie) | ✅ Supported | ✅ Supported | Future stable | +| Ubuntu | 20.04 LTS | ✅ Supported | 🔍 Testing | LTS until 2025 | +| Ubuntu | 22.04 LTS | ✅ Supported | ✅ Supported | LTS until 2027 | +| Ubuntu | 24.04 LTS | ✅ Supported | ✅ Supported | LTS until 2029 | + +**Legend**: +- ✅ Supported: Fully tested and supported +- 🔍 Testing: In testing, use with caution +- ⚠️ Limited: Basic support only +- ❌ Unsupported: Not supported + +### Minimum Requirements + +- **Ansible**: 2.13 or later +- **Python**: 3.8 or later (on controller and managed nodes) +- **BIND9 Packages**: Must be available in distribution repositories or custom sources + +## Branching Strategy + +### Branch Structure + +``` +main # BIND9 9.18 LTS (stable) +├── 9.20 # BIND9 9.20+ development +├── docs # Documentation updates (merged to both) +└── feature/* # Feature branches (target appropriate base) +``` + +### Branch Policies + +#### `main` Branch +- **Purpose**: Production-ready code for BIND9 9.18 LTS +- **Stability**: Stable, tested releases only +- **Breaking Changes**: Not allowed +- **Version Tagging**: `v1.x.x`, `v2.x.x`, etc. + +#### `9.20` Branch +- **Purpose**: Development for BIND9 9.20+ support +- **Stability**: Development/testing phase +- **Breaking Changes**: Allowed (vs 9.18 configurations) +- **Version Tagging**: `v9.20.x-betaX`, `v9.20.x-rcX`, `v9.20.x` + +#### Feature Branches +- **Naming**: `feature/description` or `fix/issue-number` +- **Target**: Merge to appropriate base (`main` for 9.18, `9.20` for 9.20+) +- **Lifecycle**: Delete after merge + +### Backporting Policy + +#### Security Fixes +- **Policy**: MUST be backported to all supported branches +- **Timeline**: Within 48 hours of fix +- **Priority**: Critical + +#### Bug Fixes +- **Policy**: SHOULD be backported if: + - Affects both versions + - Low risk of introducing regressions + - Reasonable effort required +- **Timeline**: Within 1 week +- **Priority**: High + +#### New Features +- **Policy**: Case-by-case evaluation +- **Criteria**: + - Feature is compatible with both BIND9 versions + - Does not introduce breaking changes + - Provides significant value + - Low implementation complexity +- **Timeline**: Best effort +- **Priority**: Medium + +#### Breaking Changes +- **Policy**: NEVER backported +- **Implementation**: Only in version-specific branches + +## Release Management + +### Version Numbering + +Following [Semantic Versioning 2.0.0](https://semver.org/): + +``` +MAJOR.MINOR.PATCH + +MAJOR: Incompatible API changes (role variable structure changes) +MINOR: New functionality in a backwards compatible manner +PATCH: Backwards compatible bug fixes +``` + +#### Examples + +- `v1.2.3`: Patch release for BIND9 9.18 +- `v2.0.0`: Major release with breaking role variable changes +- `v9.20.0-beta1`: Beta release for BIND9 9.20 support +- `v9.20.0`: First stable release for BIND9 9.20 + +### Release Cadence + +- **Patch Releases**: As needed for bug fixes and security updates +- **Minor Releases**: Quarterly (or when significant features accumulate) +- **Major Releases**: Annually (or when breaking changes are necessary) + +### Pre-release Testing + +All releases must pass: +1. **Molecule tests** across all supported platforms +2. **named-checkconf** validation for all example configurations +3. **Manual testing** on at least 2 different distributions +4. **Documentation review** and update + +### Release Checklist + +- [ ] Update `CHANGELOG.md` with all changes +- [ ] Update version in `meta/main.yml` +- [ ] Run full molecule test suite +- [ ] Update `README.md` if needed +- [ ] Create annotated git tag +- [ ] Push tag to trigger CI/CD +- [ ] Create GitHub/Gitea release with notes +- [ ] Announce on project channels + +## Testing Strategy + +### Test Matrix + +#### Molecule Scenarios + +| Scenario | Distribution | BIND9 Version | Purpose | +|----------|--------------|---------------|---------| +| default | Debian 13 | 9.18 | Primary development testing | +| ubuntu2204 | Ubuntu 22.04 | 9.18 | LTS testing | +| ubuntu2404 | Ubuntu 24.04 | 9.18/9.20 | Future-proofing | +| debian12 | Debian 12 | 9.18 | Stable release testing | + +#### Test Coverage + +- **Syntax validation**: All templates pass `named-checkconf` +- **Service management**: Start, stop, reload, restart operations +- **Configuration types**: All zone types and statement blocks +- **Edge cases**: Empty configurations, complex nested structures +- **Upgrade scenarios**: Migration from previous role versions + +### Continuous Integration + +```yaml +# .github/workflows/test.yml (example structure) +on: [push, pull_request] +jobs: + molecule: + strategy: + matrix: + distro: [debian12, debian13, ubuntu2204, ubuntu2404] + bind_version: ['9.18', '9.20'] + exclude: + # Don't test 9.20 on older distributions + - distro: ubuntu2004 + bind_version: '9.20' +``` + +## Grammar Tracking and Validation + +### Automated Grammar Comparison + +The role maintains upstream BIND9 grammar files to: +1. Detect configuration syntax changes between versions +2. Identify deprecated and removed options +3. Document breaking changes for users + +#### Grammar Repository Structure + +``` +bind9-grammar/ +├── upstream/ +│ ├── v9.18.44/ # Latest 9.18 LTS grammar +│ │ ├── grammar/ +│ │ │ ├── options +│ │ │ ├── *.zoneopt +│ │ │ └── parsegrammar.py +│ │ └── metadata.json +│ └── v9.20.18/ # Latest 9.20 grammar +│ ├── grammar/ +│ └── metadata.json +├── 9.18/ # Current 9.18 JSON schemas +│ └── *.json +└── 9.20/ # Future 9.20 JSON schemas + └── *.json +``` + +### Validation Tools + +#### `scripts/fetch_bind_grammar.py` +- Fetches grammar files from Gitea mirror (`Mirrors/bind9`) +- Supports version tags (e.g., `v9.18.44`, `v9.20.18`) +- Stores upstream grammar for comparison + +#### `scripts/compare_bind_versions.py` +- Compares grammar files between versions +- Generates `docs/BIND_VERSION_DIFFERENCES.md` +- Identifies: + - Breaking changes (removed options) + - New features (added options) + - Modified syntax + - Deprecation notices + +### Grammar Update Workflow + +1. **Monitor**: Watch Gitea mirror for new BIND9 releases +2. **Fetch**: Run `fetch_bind_grammar.py` for new version +3. **Compare**: Run `compare_bind_versions.py` to identify changes +4. **Review**: Analyze breaking changes and impact +5. **Update**: Modify templates and variables as needed +6. **Test**: Run molecule tests with new version +7. **Document**: Update `BIND_VERSION_DIFFERENCES.md` and `CHANGELOG.md` + +## Deprecation Policy + +### Deprecation Process + +1. **Announcement**: Document deprecation in `CHANGELOG.md` and `README.md` +2. **Warning Period**: Minimum 2 minor releases before removal +3. **Alternative**: Provide migration path or alternative approach +4. **Removal**: Only in major version releases + +### Current Deprecations + +*None at this time* + +### Planned Deprecations + +*To be determined based on BIND9 9.20 analysis* + +## Version-Specific Features + +### Version Detection + +The role will detect BIND9 version at runtime: + +```yaml +# tasks/main.yml (planned implementation) +- name: Detect BIND9 version + ansible.builtin.command: named -V + register: _bind9_version_output + changed_when: false + +- name: Set BIND9 version facts + ansible.builtin.set_fact: + bind9_version_full: "{{ _bind9_version_output.stdout | regex_search('BIND (\\S+)', '\\1') | first }}" + bind9_version_major: "{{ _bind9_version_output.stdout | regex_search('BIND (\\d+)\\.(\\d+)', '\\1') | first }}" + bind9_version_minor: "{{ _bind9_version_output.stdout | regex_search('BIND (\\d+)\\.(\\d+)', '\\2') | first }}" +``` + +### Conditional Configuration + +Templates will use version-aware conditionals: + +```jinja2 +{# templates/named.conf.options.j2 (planned) #} +{% if bind9_version_major | int >= 20 %} + {# BIND9 9.20+ specific options #} +{% else %} + {# BIND9 9.18 options #} +{% endif %} +``` + +## Migration Guidance + +### Migrating from BIND9 9.18 to 9.20 + +When BIND9 9.20 support is released: + +1. **Review**: Read `docs/BIND_VERSION_DIFFERENCES.md` +2. **Test**: Use `9.20` branch in test environment +3. **Update**: Modify playbook variables for deprecated/removed options +4. **Validate**: Run `named-checkconf` against generated configuration +5. **Deploy**: Upgrade BIND9 package and deploy new configuration +6. **Monitor**: Check logs for warnings or errors + +### Migrating Between Role Versions + +See `CHANGELOG.md` for version-specific migration notes. + +## Support and Contribution + +### Getting Help + +- **Issues**: Report bugs and request features on Gitea +- **Documentation**: Refer to `README.md` and `CONFIGURATION_GRAMMAR.md` +- **Examples**: Check `tests/` directory for working configurations + +### Contributing + +- **Bug Fixes**: Target `main` branch (or `9.20` if version-specific) +- **Features**: Discuss in issue before implementation +- **Testing**: Ensure molecule tests pass +- **Documentation**: Update relevant documentation files + +### Governance + +- **Maintainer**: Primary maintainer approves all merges +- **Review**: All changes require review before merge +- **Testing**: CI/CD must pass before merge + +## Future Considerations + +### BIND9 9.21+ and Beyond + +- Monitor ISC release announcements +- Evaluate need for additional branches +- Consider dropping support for EOL'd distributions +- Reassess branching strategy if maintenance burden increases + +### Automation Improvements + +- Automated grammar fetching in CI +- Automated breaking change detection +- Version compatibility testing matrix +- Documentation generation from grammar files + +## References + +- [ISC BIND9 Documentation](https://bind9.readthedocs.io/) +- [ISC BIND9 Release Schedule](https://www.isc.org/bind/) +- [Semantic Versioning](https://semver.org/) +- [Ansible Best Practices](https://docs.ansible.com/ansible/latest/tips_tricks/ansible_tips_tricks.html) + +## Changelog + +| Date | Version | Changes | +|------|---------|---------| +| 2026-02-07 | 1.0 | Initial version support policy | + diff --git a/scripts/compare_bind_versions.py b/scripts/compare_bind_versions.py new file mode 100644 index 0000000..5f214b4 --- /dev/null +++ b/scripts/compare_bind_versions.py @@ -0,0 +1,390 @@ +#!/usr/bin/env python3 +""" +Compare BIND9 grammar files between versions to identify breaking changes. + +This script compares grammar files from two BIND9 versions and generates +a comprehensive report of: +- Removed options (breaking changes) +- Added options (new features) +- Modified option syntax +- Deprecated options + +Usage: + python scripts/compare_bind_versions.py \\ + --version1-dir bind9-grammar/upstream/v9.18.44 \\ + --version2-dir bind9-grammar/upstream/v9.20.18 \\ + --output docs/BIND_VERSION_DIFFERENCES.md +""" + +import argparse +import json +import sys +from pathlib import Path +from typing import Dict, List, Set, Tuple +import re + + +class GrammarComparator: + """Compare BIND9 grammar files between versions.""" + + def __init__(self, version1_dir: Path, version2_dir: Path): + """ + Initialize comparator with two version directories. + + Args: + version1_dir: Path to first version's grammar files + version2_dir: Path to second version's grammar files + """ + self.version1_dir = version1_dir + self.version2_dir = version2_dir + self.version1_name = version1_dir.name + self.version2_name = version2_dir.name + + def load_grammar_file(self, file_path: Path) -> Dict: + """Load and parse a grammar file.""" + try: + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + + # Parse grammar file into structured data + options = self._parse_grammar(content) + return options + except FileNotFoundError: + return {} + + def _parse_grammar(self, content: str) -> Dict[str, str]: + """ + Parse grammar content into a dictionary of options. + + This is a simplified parser that extracts top-level keywords + and their definitions. + """ + options = {} + lines = content.split('\n') + + for line in lines: + line = line.strip() + if not line or line.startswith('#') or line.startswith('//'): + continue + + # Extract keyword and its definition + # Pattern: keyword ; or keyword { ... }; + match = re.match(r'^([a-z0-9-]+)\s+(.+?)(?:;|$)', line) + if match: + keyword = match.group(1) + definition = match.group(2).strip() + + # Extract flags from comments + flags = [] + if '// may occur multiple times' in line: + flags.append('may occur multiple times') + if '// deprecated' in line: + flags.append('deprecated') + if '// obsolete' in line: + flags.append('obsolete') + if '// not configured' in line: + flags.append('not configured') + if '// test only' in line: + flags.append('test only') + if '// experimental' in line: + flags.append('experimental') + + options[keyword] = { + 'definition': definition, + 'flags': flags, + 'raw_line': line + } + + return options + + def compare_files(self, filename: str) -> Dict: + """ + Compare a specific grammar file between two versions. + + Returns: + Dict with added, removed, modified, and deprecated options + """ + file1 = self.version1_dir / 'grammar' / filename + file2 = self.version2_dir / 'grammar' / filename + + options1 = self.load_grammar_file(file1) + options2 = self.load_grammar_file(file2) + + keys1 = set(options1.keys()) + keys2 = set(options2.keys()) + + # Identify changes + added = keys2 - keys1 + removed = keys1 - keys2 + common = keys1 & keys2 + + modified = [] + deprecated_new = [] + + for key in common: + opt1 = options1[key] + opt2 = options2[key] + + # Check if definition changed + if opt1['definition'] != opt2['definition']: + modified.append({ + 'option': key, + 'old_definition': opt1['definition'], + 'new_definition': opt2['definition'] + }) + + # Check if newly deprecated + if 'deprecated' not in opt1['flags'] and 'deprecated' in opt2['flags']: + deprecated_new.append(key) + + return { + 'file': filename, + 'added': sorted(added), + 'removed': sorted(removed), + 'modified': modified, + 'deprecated_new': deprecated_new, + 'options1_count': len(options1), + 'options2_count': len(options2) + } + + def compare_all(self) -> Dict: + """Compare all grammar files between versions.""" + # List of grammar files to compare + grammar_files = [ + 'options', + 'forward.zoneopt', + 'hint.zoneopt', + 'in-view.zoneopt', + 'mirror.zoneopt', + 'primary.zoneopt', + 'redirect.zoneopt', + 'secondary.zoneopt', + 'static-stub.zoneopt', + 'stub.zoneopt', + 'delegation-only.zoneopt', + 'rndc.grammar', + ] + + results = {} + for filename in grammar_files: + result = self.compare_files(filename) + results[filename] = result + + return results + + def generate_markdown_report(self, results: Dict) -> str: + """Generate a Markdown report from comparison results.""" + lines = [] + lines.append(f"# BIND9 Version Differences: {self.version1_name} vs {self.version2_name}") + lines.append("") + lines.append(f"This document compares BIND9 configuration grammar between {self.version1_name} and {self.version2_name}.") + lines.append("") + lines.append("Generated automatically by `scripts/compare_bind_versions.py`.") + lines.append("") + + # Summary + lines.append("## Summary") + lines.append("") + + total_added = sum(len(r['added']) for r in results.values()) + total_removed = sum(len(r['removed']) for r in results.values()) + total_modified = sum(len(r['modified']) for r in results.values()) + total_deprecated = sum(len(r['deprecated_new']) for r in results.values()) + + lines.append(f"- **New Options**: {total_added}") + lines.append(f"- **Removed Options**: {total_removed} ⚠️") + lines.append(f"- **Modified Options**: {total_modified}") + lines.append(f"- **Newly Deprecated**: {total_deprecated}") + lines.append("") + + # Breaking Changes + if total_removed > 0: + lines.append("## ⚠️ Breaking Changes") + lines.append("") + lines.append(f"The following options were removed in {self.version2_name} and will cause configuration errors:") + lines.append("") + + for filename, result in results.items(): + if result['removed']: + lines.append(f"### {filename}") + lines.append("") + for option in result['removed']: + lines.append(f"- `{option}`") + lines.append("") + + # New Features + if total_added > 0: + lines.append("## ✨ New Features") + lines.append("") + lines.append(f"The following options were added in {self.version2_name}:") + lines.append("") + + for filename, result in results.items(): + if result['added']: + lines.append(f"### {filename}") + lines.append("") + for option in result['added']: + lines.append(f"- `{option}`") + lines.append("") + + # Modified Options + if total_modified > 0: + lines.append("## 🔧 Modified Options") + lines.append("") + lines.append(f"The following options have syntax changes in {self.version2_name}:") + lines.append("") + + for filename, result in results.items(): + if result['modified']: + lines.append(f"### {filename}") + lines.append("") + for mod in result['modified']: + lines.append(f"#### `{mod['option']}`") + lines.append("") + lines.append(f"**{self.version1_name}**:") + lines.append(f"```") + lines.append(f"{mod['old_definition']}") + lines.append(f"```") + lines.append("") + lines.append(f"**{self.version2_name}**:") + lines.append(f"```") + lines.append(f"{mod['new_definition']}") + lines.append(f"```") + lines.append("") + + # Deprecated Options + if total_deprecated > 0: + lines.append("## 📋 Newly Deprecated Options") + lines.append("") + lines.append(f"The following options were marked as deprecated in {self.version2_name}:") + lines.append("") + + for filename, result in results.items(): + if result['deprecated_new']: + lines.append(f"### {filename}") + lines.append("") + for option in result['deprecated_new']: + lines.append(f"- `{option}`") + lines.append("") + + # File-by-File Comparison + lines.append("## Detailed File-by-File Comparison") + lines.append("") + + for filename, result in results.items(): + lines.append(f"### {filename}") + lines.append("") + lines.append(f"- {self.version1_name}: {result['options1_count']} options") + lines.append(f"- {self.version2_name}: {result['options2_count']} options") + lines.append(f"- Added: {len(result['added'])}") + lines.append(f"- Removed: {len(result['removed'])}") + lines.append(f"- Modified: {len(result['modified'])}") + lines.append("") + + # Migration Guide + if total_removed > 0 or total_deprecated > 0: + lines.append("## Migration Guide") + lines.append("") + lines.append(f"### Migrating from {self.version1_name} to {self.version2_name}") + lines.append("") + + if total_removed > 0: + lines.append("1. **Remove unsupported options** from your configuration") + lines.append(" - Review the Breaking Changes section above") + lines.append(" - Check if there are replacement options") + lines.append("") + + if total_deprecated > 0: + lines.append("2. **Plan for deprecated options**") + lines.append(" - These options still work but may be removed in future versions") + lines.append(" - Start planning migration to recommended alternatives") + lines.append("") + + lines.append("3. **Test your configuration**") + lines.append(" - Use `named-checkconf` to validate syntax") + lines.append(" - Test in a development environment before production") + lines.append("") + + return '\n'.join(lines) + + +def main(): + """Main entry point.""" + parser = argparse.ArgumentParser( + description="Compare BIND9 grammar files between versions" + ) + parser.add_argument( + "--version1-dir", + type=Path, + required=True, + help="Directory containing first version's grammar files" + ) + parser.add_argument( + "--version2-dir", + type=Path, + required=True, + help="Directory containing second version's grammar files" + ) + parser.add_argument( + "--output", + type=Path, + default=Path("docs/BIND_VERSION_DIFFERENCES.md"), + help="Output file for Markdown report" + ) + parser.add_argument( + "--json", + type=Path, + help="Also output raw comparison as JSON" + ) + + args = parser.parse_args() + + # Validate directories + if not args.version1_dir.exists(): + print(f"Error: {args.version1_dir} does not exist", file=sys.stderr) + sys.exit(1) + + if not args.version2_dir.exists(): + print(f"Error: {args.version2_dir} does not exist", file=sys.stderr) + sys.exit(1) + + # Perform comparison + print(f"Comparing BIND9 versions:") + print(f" Version 1: {args.version1_dir.name}") + print(f" Version 2: {args.version2_dir.name}") + + comparator = GrammarComparator(args.version1_dir, args.version2_dir) + results = comparator.compare_all() + + # Generate and save Markdown report + report = comparator.generate_markdown_report(results) + + args.output.parent.mkdir(parents=True, exist_ok=True) + with open(args.output, 'w', encoding='utf-8') as f: + f.write(report) + + print(f"✓ Markdown report saved to: {args.output}") + + # Save JSON if requested + if args.json: + args.json.parent.mkdir(parents=True, exist_ok=True) + with open(args.json, 'w', encoding='utf-8') as f: + json.dump(results, f, indent=2) + print(f"✓ JSON comparison saved to: {args.json}") + + # Print summary + total_added = sum(len(r['added']) for r in results.values()) + total_removed = sum(len(r['removed']) for r in results.values()) + total_modified = sum(len(r['modified']) for r in results.values()) + + print(f"\nComparison Summary:") + print(f" Added options: {total_added}") + print(f" Removed options: {total_removed}") + print(f" Modified options: {total_modified}") + + if total_removed > 0: + print(f"\n⚠️ Warning: {total_removed} breaking changes detected!") + + +if __name__ == "__main__": + main() diff --git a/scripts/fetch_bind_grammar.py b/scripts/fetch_bind_grammar.py new file mode 100644 index 0000000..fcbbe87 --- /dev/null +++ b/scripts/fetch_bind_grammar.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python3 +""" +Fetch BIND9 grammar files from Gitea mirror repository for version comparison. + +This script uses the Gitea MCP tools to fetch grammar files from the official +BIND9 mirror at git.valid.dk/Mirrors/bind9 for specified version tags. +""" + +import argparse +import json +import os +import sys +from pathlib import Path +from typing import Dict, List + + +# Grammar files to fetch from doc/misc/ +GRAMMAR_FILES = [ + "options", + "forward.zoneopt", + "hint.zoneopt", + "in-view.zoneopt", + "mirror.zoneopt", + "primary.zoneopt", + "redirect.zoneopt", + "secondary.zoneopt", + "static-stub.zoneopt", + "stub.zoneopt", + "delegation-only.zoneopt", + "rndc.grammar", +] + +# Support files +SUPPORT_FILES = [ + "parsegrammar.py", + "checkgrammar.py", +] + + +def fetch_file_content(owner: str, repo: str, ref: str, file_path: str) -> str: + """ + Fetch file content from Gitea repository. + + This would use mcp_gitea-mcp_get_file_content in the actual MCP environment. + For standalone usage, returns placeholder. + """ + # In MCP environment, this would call: + # mcp_gitea-mcp_get_file_content(owner=owner, repo=repo, ref=ref, filePath=file_path) + print(f"Would fetch: {owner}/{repo}@{ref}:{file_path}") + return "" + + +def save_grammar_file(content: str, version: str, filename: str, output_dir: Path): + """Save fetched grammar file to local directory.""" + version_dir = output_dir / version / "grammar" + version_dir.mkdir(parents=True, exist_ok=True) + + file_path = version_dir / filename + with open(file_path, 'w', encoding='utf-8') as f: + f.write(content) + + print(f"Saved: {file_path}") + + +def fetch_version_grammars(owner: str, repo: str, tag: str, output_dir: Path): + """Fetch all grammar files for a specific version tag.""" + print(f"\n=== Fetching grammar files for {tag} ===") + + # Create metadata + metadata = { + "version": tag, + "repository": f"{owner}/{repo}", + "files": [], + } + + # Fetch grammar files + for grammar_file in GRAMMAR_FILES: + try: + file_path = f"doc/misc/{grammar_file}" + content = fetch_file_content(owner, repo, tag, file_path) + + if content: + save_grammar_file(content, tag, grammar_file, output_dir) + metadata["files"].append({ + "name": grammar_file, + "path": file_path, + "type": "grammar" + }) + except Exception as e: + print(f"Warning: Could not fetch {grammar_file}: {e}") + + # Fetch support files + for support_file in SUPPORT_FILES: + try: + file_path = f"doc/misc/{support_file}" + content = fetch_file_content(owner, repo, tag, file_path) + + if content: + save_grammar_file(content, tag, support_file, output_dir) + metadata["files"].append({ + "name": support_file, + "path": file_path, + "type": "support" + }) + except Exception as e: + print(f"Warning: Could not fetch {support_file}: {e}") + + # Save metadata + metadata_file = output_dir / tag / "metadata.json" + with open(metadata_file, 'w', encoding='utf-8') as f: + json.dump(metadata, f, indent=2) + + print(f"Metadata saved: {metadata_file}") + return metadata + + +def main(): + """Main entry point.""" + parser = argparse.ArgumentParser( + description="Fetch BIND9 grammar files from Gitea mirror" + ) + parser.add_argument( + "--owner", + default="Mirrors", + help="Repository owner (default: Mirrors)" + ) + parser.add_argument( + "--repo", + default="bind9", + help="Repository name (default: bind9)" + ) + parser.add_argument( + "--tags", + nargs="+", + default=["v9.18.44", "v9.20.18"], + help="Version tags to fetch (default: v9.18.44 v9.20.18)" + ) + parser.add_argument( + "--output-dir", + type=Path, + default=Path("bind9-grammar/upstream"), + help="Output directory for grammar files" + ) + + args = parser.parse_args() + + print("BIND9 Grammar Fetcher") + print("=" * 60) + print(f"Repository: {args.owner}/{args.repo}") + print(f"Tags: {', '.join(args.tags)}") + print(f"Output: {args.output_dir}") + + # Fetch grammars for each version + results = {} + for tag in args.tags: + try: + metadata = fetch_version_grammars( + args.owner, + args.repo, + tag, + args.output_dir + ) + results[tag] = metadata + except Exception as e: + print(f"Error fetching {tag}: {e}") + sys.exit(1) + + # Save overall summary + summary_file = args.output_dir / "fetch_summary.json" + with open(summary_file, 'w', encoding='utf-8') as f: + json.dump(results, f, indent=2) + + print(f"\n=== Fetch complete ===") + print(f"Summary: {summary_file}") + print(f"Fetched {len(results)} versions") + + +if __name__ == "__main__": + main() diff --git a/scripts/fetch_bind_grammar_mcp.py b/scripts/fetch_bind_grammar_mcp.py new file mode 100644 index 0000000..d68a517 --- /dev/null +++ b/scripts/fetch_bind_grammar_mcp.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 +""" +Fetch BIND9 grammar files using Gitea MCP integration. + +This script demonstrates how to use mcp_gitea-mcp tools to fetch grammar files. +Since we can't directly call MCP tools from Python, this serves as documentation +for the manual fetching process that should be done through the MCP interface. + +Usage: + The actual fetching should be done through MCP tool calls: + + 1. List available tags: + mcp_gitea-mcp_list_tags(owner="Mirrors", repo="bind9") + + 2. Get directory listing: + mcp_gitea-mcp_get_dir_content(owner="Mirrors", repo="bind9", + ref="v9.18.44", filePath="doc/misc") + + 3. Fetch each grammar file: + mcp_gitea-mcp_get_file_content(owner="Mirrors", repo="bind9", + ref="v9.18.44", + filePath="doc/misc/options") +""" + +import json +from pathlib import Path +from typing import Dict, List + +# Target versions +VERSIONS = { + "9.18": "v9.18.44", + "9.20": "v9.20.18", +} + +# Grammar files to fetch +GRAMMAR_FILES = [ + "options", + "forward.zoneopt", + "hint.zoneopt", + "in-view.zoneopt", + "mirror.zoneopt", + "primary.zoneopt", + "redirect.zoneopt", + "secondary.zoneopt", + "static-stub.zoneopt", + "stub.zoneopt", + "delegation-only.zoneopt", + "rndc.grammar", +] + +SUPPORT_FILES = [ + "parsegrammar.py", + "checkgrammar.py", +] + + +def generate_fetch_commands() -> List[Dict]: + """Generate MCP tool call commands for fetching grammar files.""" + commands = [] + + for version_name, tag in VERSIONS.items(): + # List directory command + commands.append({ + "tool": "mcp_gitea-mcp_get_dir_content", + "params": { + "owner": "Mirrors", + "repo": "bind9", + "ref": tag, + "filePath": "doc/misc" + }, + "description": f"List grammar files for {version_name} ({tag})" + }) + + # File fetch commands + for grammar_file in GRAMMAR_FILES + SUPPORT_FILES: + commands.append({ + "tool": "mcp_gitea-mcp_get_file_content", + "params": { + "owner": "Mirrors", + "repo": "bind9", + "ref": tag, + "filePath": f"doc/misc/{grammar_file}" + }, + "save_to": f"bind9-grammar/upstream/{tag}/grammar/{grammar_file}", + "description": f"Fetch {grammar_file} for {version_name}" + }) + + return commands + + +def save_file_structure() -> Dict: + """Generate expected file structure after fetching.""" + structure = { + "bind9-grammar": { + "upstream": {} + } + } + + for version_name, tag in VERSIONS.items(): + structure["bind9-grammar"]["upstream"][tag] = { + "grammar": { + "files": GRAMMAR_FILES + SUPPORT_FILES + }, + "metadata.json": { + "version": tag, + "version_name": version_name, + "repository": "Mirrors/bind9", + "fetched_files": len(GRAMMAR_FILES) + len(SUPPORT_FILES) + } + } + + return structure + + +def main(): + """Generate instructions and commands for grammar fetching.""" + print("=" * 70) + print("BIND9 Grammar Fetcher - MCP Integration Guide") + print("=" * 70) + + print("\nTarget Versions:") + for version_name, tag in VERSIONS.items(): + print(f" - BIND {version_name}: {tag}") + + print(f"\nFiles to fetch per version: {len(GRAMMAR_FILES)} grammar files + {len(SUPPORT_FILES)} support files") + + print("\n" + "=" * 70) + print("MCP TOOL CALL SEQUENCE") + print("=" * 70) + + commands = generate_fetch_commands() + + for i, cmd in enumerate(commands, 1): + print(f"\n[{i}/{len(commands)}] {cmd['description']}") + print(f"Tool: {cmd['tool']}") + print(f"Parameters:") + for key, value in cmd['params'].items(): + print(f" - {key}: {value}") + if 'save_to' in cmd: + print(f"Save to: {cmd['save_to']}") + + print("\n" + "=" * 70) + print("EXPECTED FILE STRUCTURE") + print("=" * 70) + + structure = save_file_structure() + print(json.dumps(structure, indent=2)) + + # Save command list + output_dir = Path("bind9-grammar/upstream") + output_dir.mkdir(parents=True, exist_ok=True) + + commands_file = output_dir / "fetch_commands.json" + with open(commands_file, 'w') as f: + json.dump(commands, f, indent=2) + + print(f"\nCommand list saved to: {commands_file}") + print("\nNote: These commands should be executed through the MCP interface,") + print(" not directly from this Python script.") + + +if __name__ == "__main__": + main() diff --git a/scripts/process_mcp_result.py b/scripts/process_mcp_result.py new file mode 100644 index 0000000..9f31f40 --- /dev/null +++ b/scripts/process_mcp_result.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +""" +Fetch BIND9 grammar files using Gitea MCP tools. +This script must be run from an environment where MCP tools are available. +""" + +import base64 +import json +import sys +from pathlib import Path + +# Files to fetch +GRAMMAR_FILES = [ + "options", + "forward.zoneopt", + "hint.zoneopt", + "in-view.zoneopt", + "mirror.zoneopt", + "primary.zoneopt", + "redirect.zoneopt", + "secondary.zoneopt", + "static-stub.zoneopt", + "stub.zoneopt", + "delegation-only.zoneopt", + "rndc.grammar", + "parsegrammar.py", + "checkgrammar.py", +] + +def save_file_from_mcp_result(result_json: dict, output_path: Path) -> bool: + """Save a file from MCP tool result JSON.""" + try: + if 'Result' in result_json and 'content' in result_json['Result']: + content_b64 = result_json['Result']['content'] + content = base64.b64decode(content_b64).decode('utf-8') + + output_path.parent.mkdir(parents=True, exist_ok=True) + with open(output_path, 'w', encoding='utf-8') as f: + f.write(content) + + return True + return False + except Exception as e: + print(f"Error saving {output_path}: {e}", file=sys.stderr) + return False + +def main(): + """Process stdin JSON from MCP tool calls.""" + print("Reading MCP tool results from stdin...") + + # Read all input + input_data = sys.stdin.read() + + try: + result = json.loads(input_data) + + # Determine output path from result metadata + if 'Result' in result and 'name' in result['Result']: + filename = result['Result']['name'] + # Output path will be provided as command line argument + if len(sys.argv) > 1: + output_path = Path(sys.argv[1]) + if save_file_from_mcp_result(result, output_path): + print(f"✓ Saved: {output_path}") + sys.exit(0) + else: + print(f"✗ Failed to save: {output_path}", file=sys.stderr) + sys.exit(1) + + print("✗ Could not determine output path", file=sys.stderr) + sys.exit(1) + + except json.JSONDecodeError as e: + print(f"✗ Invalid JSON input: {e}", file=sys.stderr) + sys.exit(1) + +if __name__ == "__main__": + main() diff --git a/scripts/save_grammar_file.py b/scripts/save_grammar_file.py new file mode 100644 index 0000000..9b94305 --- /dev/null +++ b/scripts/save_grammar_file.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +"""Helper script to save base64-encoded grammar file from MCP tool output.""" + +import base64 +import json +import sys +from pathlib import Path + +def main(): + if len(sys.argv) != 3: + print("Usage: save_grammar_file.py ") + sys.exit(1) + + json_file = Path(sys.argv[1]) + output_path = Path(sys.argv[2]) + + # Read JSON from MCP tool output + with open(json_file, 'r') as f: + data = json.load(f) + + # Extract and decode base64 content + if 'Result' in data and 'content' in data['Result']: + content_b64 = data['Result']['content'] + content = base64.b64decode(content_b64).decode('utf-8') + + # Save to output path + output_path.parent.mkdir(parents=True, exist_ok=True) + with open(output_path, 'w', encoding='utf-8') as f: + f.write(content) + + print(f"✓ Saved: {output_path}") + else: + print(f"✗ Error: No content found in JSON", file=sys.stderr) + sys.exit(1) + +if __name__ == "__main__": + main()