Provided by: dnssec-tools_2.0-1_all bug


         Net::DNS::SEC::Tools::Donuts::Rule - Define donuts DNS record-checking rules


       This class wraps around a rule definition which is used by the donuts DNS zone file
       checker.  It stores the data that implements a given rule.

       Rules are defined in donuts rule configuration files using the following syntax.  See the
       donuts manual page for details on where to place those files and how to load them.


       Each rule file can contain multiple rules.  Each rule is composed of a number of parts.
       Minimally, it must contain a name and a test portion.  Everything else is optional and/or
       has defaults associated with it.  The rule file format follows this example:

         name: rulename
         class: Warning
           my ($record) = @_;
           return "problem found"
             if ($record{xxx} != yyy);

       Further details about each section can be found below.  Besides the tokens 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.  These special tokens include test and init.  See below for

       Each rule definition within a file should be separated using a blank line.

       Lines beginning with the '#' character will be discarded as a comment.

           The name of the rule.  This is mandatory, as 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.

           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.



           The rule's execution level, as recognized by donuts.  donuts will run only those rules
           at or above donuts' current execution level.  The execution level is specified by the
           -l option to donuts; if 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.


             level: 2

           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.

             class: Warning

           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.


             ruletype: record

           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.

           For example, if a rule is testing a particular aspect of an MX record, it should
           specify "MX" in this field.


             type: MX

           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

           init sections are wrapped in an XML-like syntax which specifies the start and end of
           the init section of code.


               use My::Module;
               $value = calculate();

           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.

           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

           EG, the resulting code for a record test will look like this:

             package main;
             no strict;
               my ($record, $rule) = @_;

           And for name test will be:

             package main;
             no strict;
               my ($records, $rule, $recordname) = @_;

           (Again, this structure is only created if the test definition does notb begin with
           "sub {" already)

           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

           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:

                 1) $record: The record which is to be tested

                 2) $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:

                 1) $records: A hash reference to all the record types associated
                    with that record name (e.g., '' 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 '' entry).

                 2) $rule: The Net::DNS::SEC::Tools::Donuts::Rule object reference
                    and rule definition information.

                 3) $recordname: The record name being checked (the name associated
                    with the data from 1) above which might be "" for
                    instance, or "">).

               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
               return "TTL for $record->{name} is too small" if ($record->ttl < 60);

             # 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
               return "$recordname has an A record but does not have an HINFO record"
                 if (exists($records->{'A'}) && !exists($records->{'HINFO'}));

       feature: NAME
           The feature tag prevents this rule from running unless the NAME keyword was specified
           using the --features flag.

       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.

       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).


             1) In the rule file (this is an incomplete rule definition):

                name:           SOME_TEST
                myconfig:       40
                help: myconfig: A special number to configure this test
                 # ... use $rule->{'myconfig'}

             2) This allows the user to change the value of myconfig via their
                .donuts.conf file:

                # change SOME_TEST config...
                name:     SOME_TEST
                myconfig: 40

             3) and running donuts -H will show the help line for myconfig.

       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.


       Copyright 2004-2013 SPARTA, Inc.  All rights reserved.  See the COPYING file included with
       the DNSSEC-Tools package for details.


       Wes Hardaker <>



       Net::DNS, Net::DNS::RR