Net::DN...s::Rule(3)
π© Net::DN...s::Rule(3) β User Contributed Perl Documentation
okay so bestie, this is the manual page for Net::DNS::SEC::Tools::Donuts::Rule, straight out of the User Contributed Perl Documentation section, and it is literally the blueprint for how you write donuts rules. no cap. pull up a chair π
β¨ NAME
Net::DNS::SEC::Tools::Donuts::Rule β Define donuts DNS record-checking rules π
π DESCRIPTION
This class is a little wrapper around a rule definition, and that rule definition is the thing the donuts DNS zone file checker actually uses. It stores all the data that implements a given rule. that's it, that's the whole job π«Ά
Rules are defined in donuts rule configuration files using the syntax below. For details on where to put those files and how to load them, go read the donuts manual page β that's its whole moment, let it have it β
π RULE FILE FORMAT
Each rule file can contain multiple rules β it's giving β¨communal livingβ¨. Each rule is composed of a number of parts. Minimally, it has to have a name and a test portion. Everything else is optional and/or has defaults associated with it. here's the shape of it:
name: rulename
class: Warning
<test>
my ($record) = @_;
return "problem found"
if ($record{xxx} != yyy);
</test>
Further details about each section can be found below π. Besides the tokens listed below, other rule-specific data can be stored in tokens, and each rule is a hash of the above tokens as keys and their associated data. however, there are a few exceptions where special tokens imply special meanings β those special tokens include test and init. see below for the tea β
Each rule definition within a file should be separated using a blank line. and lines beginning with the # character will be discarded as a comment. gone. deleted. not invited to the party π
πΈ name
The name of the rule. This one is mandatory β the user may need to refer to names in the future for use with the -i flag, specifying behavior in configuration files, and for other uses. so like, don't skip it.
By convention, all names should be specified using capital letters and _ characters between the words. The leftmost word should give an indication of a global test category, such as "DNSSEC". The better-named the rules, the more power the user will have for selecting certain types of rules via donuts -i and other flags. naming is self-care, periodt π
Example:
name: DNSSEC_TEST_SOME_SECURE_FEATURE
πΈ level
The rule's execution level, as recognized by donuts. donuts will run only those rules at or above donuts' current execution level. That execution level is specified by the -l option to donuts; if it's not given, then the default execution level is 5.
The default level of every rule is 5.
Generally, more serious problems should receive lower numbers, and less serious problems should be placed at a higher number. The maximum value is 9, which is reserved for debugging rules only. 8 is the maximum rule level that user-defined rules should use. so 9 is the VIP section, you're not on the list bestie π
Example:
name: DNSSEC_TEST_SOME_SECURE_FEATURE
level: 2
πΈ class
The class code indicates the type of problem associated with the rule. It defaults to "Error", and the only other value that should be used is "Warning".
This value is displayed to the user. Technically, any value could be specified, but using anything other than the Error/Warning convention could break portability in future versions. so like... you can color outside the lines, but future you will be mad at present you π
Example:
name: DNSSEC_TEST_SOME_SECURE_FEATURE
class: Warning
πΈ ruletype
Rules fall into one of two types (currently): record or name. record rules have their test section evaluated for each record in a zone file. name rules, on the other hand, get called once per record name stored in the database. See the test description below for further details on the arguments passed to each rule type.
The default value for this clause is record.
Example:
name: DNSSEC_TEST_SOME_SECURE_FEATURE
ruletype: record
πΈ type
Rules that test a particular type of record should specify the type field with the type of record it will test. The rule will only be executed for records of that type. slay, filtered π₯
For example, if a rule is testing a particular aspect of an MX record, it should specify "MX" in this field.
Example:
name: DNSSEC_TEST_SOME_SECURE_FEATURE
type: MX
πΈ init
A block of code to be executed immediately as the rule is being parsed from the rule definition file. This is useful for boot-strap code to be performed only at start-up. For example, perl use MODULE::NAME; or similar statements should be used in init sections.
init sections are wrapped in an XML-like syntax which specifies the start and end of the init section of code.
Example:
<init>
use My::Module;
$value = calculate();
</init>
πΈ test
A block of code defining the test to be executed for each record or record name. The test statement follows the same multi-line code specification described in the init clause above. Specifically, all the lines between the <test> and </test> braces are considered part of the test code. no crumbs left behind π
The test contents must be a block of perl code. If it is not in the form of an anonymous subroutine (surrounded by sub { and } markers), then the code will be automatically put inside a basic subroutine block to turn it into an anonymous subroutine. it literally dresses your code up for the occasion π
EG, the resulting code for a record test will look like this:
package main;
no strict;
sub
{
my ($record, $rule) = @_;
TESTCODE
}
And for a name test it will be:
package main;
no strict;
sub
{
my ($records, $rule, $recordname) = @_;
TESTCODE
}
(Again, this structure is only created if the test definition does not already begin with sub {.)
When the testcode is run and the test fails, it should return an error string which will be displayed for the user. The text will be line-wrapped before display (and thus should be unformatted text). If the test is checking for multiple problems, a reference to an array of error strings may be returned. A test block that has no errors to report should return either an empty string or a reference to an empty array. so like, return nothing, or return a lil array of nothing. don't make it weird π§
There are two types of tests (currently), and the test code is called with arguments that depend on the ruletype clause of the rule. These arguments and calling conventions are as follows:
π record tests
These code snippets are expected to test a single Net::DNS::RR record.
It is called with two arguments:
$record: The record which is to be tested$recordname: The Net::DNS::SEC::Tools::Donuts::Rule object reference and rule definition information.
These are bound to $record and $rule automatically for the test code to use.
π name tests
These code snippets are expected to test all the records associated with a given name record.
It is called with three arguments:
$records: A hash reference to all the record types associated with that record name (e.g.,'example.com'might have a hash reference containing an entry for'A','MX', ...). Each value of the hash will contain an array of all the records for that type (for example, the hash entry for the'A'key may contain an array with 2 Net::DNS::RR records, one for each A record attached to the'example.com'entry).$rule: The Net::DNS::SEC::Tools::Donuts::Rule object reference and rule definition information.$recordname: The record name being checked (the name associated with the data from 1) above which might be"exmaple.com"for instance, or"www.example.com">).
These are bound to $records, $rule and $recordname automatically for the test code to use.
Example rules:
# local rule to mandate that each record must have a
# TTL > 60 seconds
name: DNS_TTL_AT_LEAST_60
level: 8
type: record
<test>
return "TTL for $record->{name} is too small" if ($record->ttl < 60);
</test>
# local policy rule to mandate that anything with an A record
# must have an HINFO record too
name: DNS_MX_MUST_HAVE_A
level: 8
type: name
<test>
return "$recordname has an A record but does not have an HINFO record"
if (exists($records->{'A'}) && !exists($records->{'HINFO'}));
</test>
πΈ feature: NAME
The feature tag prevents this rule from running unless the NAME keyword was specified using the --features flag. it's giving exclusive guest list ποΈ
πΈ desc: DESCRIPTION
A short description of what the rule tests that will be printed to the user in help output or in the error summary when donuts outputs the results.
πΈ requires: PERLMODULE1 PERLMODULE2 ...
This allows rules to depend on installed perl modules. They'll be required and imported as the rule starts executing. If they don't exist, an error will be logged using donuts_error() stating that the module is required for that rule to work. no module, no rule, that's the rule π€
πΈ help: TOKEN: TOKEN-HELP
If the rule is configurable via the user's .donuts.conf file, this describes the configuration tokens for the user when they request configuration help via the -H or --help-config flags. Tokens may be used within rules by accessing them using the $rule reference passed to the code (the second argument).
Examples:
- In the rule file (this is an incomplete rule definition):
name: SOME_TEST
myconfig: 40
help: myconfig: A special number to configure this test
<test>
# ... use $rule->{'myconfig'}
</test>
- This allows the user to change the value of
myconfigvia their.donuts.conffile:
# change SOME_TEST config...
name: SOME_TEST
myconfig: 40
- and running
donuts -Hwill show the help line formyconfig.
πΈ noindent: 1 / nowrap: 1
Normally donuts will line-wrap the error summary produced by a rule to enable automatic pretty-printing of error results. Sometimes, however, rules may wish to self-format their outputs. The nowrap option indicates to donuts that the output is pre-formatted but should still be indented to align with the output of the rest of the error text (currently about 15 spaces). The noindent tag, however, indicates that neither wrapping nor indenting should be performed, but that the error should be printed as is. raw. unfiltered. the error said what it said π
π COPYRIGHT π
okay so legally we gotta say this and honestly it's giving "read the fine print bestie" energy, but here it is:
Copyright 2004-2013 SPARTA, Inc. All rights reserved.
and like, that's All rights reserved with a capital A, no cap. π«Ά
if you wanna know the actual deets, go peek at the COPYING file that ships inside the DNSSEC-Tools package β that's where the whole story lives β¨
π AUTHOR π
this absolute icon right here made it happen:
- Wes Hardaker β
<hardaker@users.sourceforge.net>
like, thank you for your service, fr fr ππ
π SEE ALSO π
okay so if you're done here and you're like "what else" β bestie, I gotchu, there's a whole friend group:
donuts(8)π© (yes really, that's the name, and no I will not be elaborating, go read it)Net::DNSβ the main character of DNS Perl modules tbhNet::DNS::RRβ the resource record one, you'll be seeing a lot of each otherNet::DNS::SEC::Tools::Donutsβ donuts again but in module form, obsessedhttp://www.dnssec-tools.org/β the website, go touch grass... digitally πβ¨
π¦ and that's the vibe π¦
that's the whole page bestie!! you made it to the very end, I'm so proud of you ππ go forth and rule-file responsibly, okay? iykyk π
so this version came from perl v5.44.0, dated 2026-10-17, and it's the Net::DN...s::Rule(3) page β like the truncated lil title it's always been, iconic honestly πβ¨ bye bestie!! π«ΆπΈ
π¦ where this page comes from
- arch rolling: dnssec-tools 2.2.3-16 Β· BSD
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms