name:  	  DNS_SOA_STATUS
level: 	  2
ruletype: name
class: 	  Status
desc:  	  Outputs information from the SOA to the status report
<test>
  if ($recordname eq $current_domain && $#{$records->{'SOA'}} == 0) {
     domain_status("Zone Serial Number", $records->{'SOA'}[0]->serial); 

     my $rname = $records->{'SOA'}[0]->rname;
     if ($rname !~ /\@/) {
         $rname =~ s/\./\@/;
     }
     domain_status("SOA Contact Address", $rname); 
  }

  return;
</test>

name:  	  DNS_NS_STATUS
level: 	  2
ruletype: name
class: 	  Status
desc:  	  Outputs information about the name servers to the status report
<test>
  if ($recordname eq $current_domain && $#{$records->{'NS'}} > -1) {
     my @ns;
     foreach my $ns (@{$records->{'NS'}}) {
       push @ns, $ns->nsdname;
     }
     domain_status("Nameservers", join(", ", @ns));
  }

  return;
</test>

# memorize and report the 
name:  	   DNSSEC_RRSIG_STATUS
level: 	   2
type:  	   RRSIG
warntime:  604800
class:     Status
desc: Reports the signature lifetimes
<init>
  use Date::Parse;
  $donuts::time = time();

  $donuts::sigexpiration = undef;
  $donuts::siginception = undef;
  $donuts::parentexpiration = undef;
  $donuts::parentinception = undef;

  $donuts::foundAlignmentProblem = undef;

  package main;
  sub rrsig_date_to_epoch {
    my ($incoming) = @_;
    $incoming =~ s/(....)(..)(..)(..)(..)(..)/$2-$3-$1 $4:$5:$6/;
    return str2time($incoming);
  }

</init>
<test>

  # check for out-of-zone data (such as a parents)
  if ($record->name !~ /$current_domain$/) {
    # completely out of zone
    return 
  } elsif ($record->typecovered eq 'DS' &&
           $record->name        eq $current_domain) {
        
    # record the parent's notion of the DS validity range
    $donuts::parentexpiration = rrsig_date_to_epoch($record->sigexpiration);
    $donuts::parentinception = rrsig_date_to_epoch($record->siginception);
    return;
  }

  # process the expiration time
  my $newtime = rrsig_date_to_epoch($record->sigexpiration);
  
  if (!defined($donuts::sigexpiration)) {
    $donuts::sigexpiration = $newtime
  } elsif ($donuts::sigexpiration != $newtime) {
    $donuts::foundAlignmentProblem = 1;
    
    # remember the soonest time that the zone might expire
    $donuts::sigexpiration = $donuts::sigexpiration < $newtime
                              ? $donuts::sigexpiration : $newtime;
  } 

  # process the inception time
  my $newtime = rrsig_date_to_epoch($record->siginception);

  if (!defined($donuts::siginception)) {
    $donuts::siginception = $newtime;
  } elsif ($donuts::siginception != $newtime) {
    $donuts::foundAlignmentProblem = 1;
    
    # remember the latest time that the zone might be valid from
    $donuts::siginception = $donuts::siginception > $newtime
                              ? $donuts::siginception : $newtime;
  } 

  return;
</test>
<end>

  if (defined($donuts::siginception)) {
    domain_status("Zone valid from", scalar localtime($donuts::siginception));
  }

  if (defined($donuts::sigexpiration)) {
    domain_status("Zone valid until", scalar localtime($donuts::sigexpiration));
  } else {
    domain_status("DNSSEC Signed", "No!");
  }

  if (defined($donuts::parentinception)) {
    domain_status("Parent zone validity from", scalar localtime($donuts::parentinception));
  }

  if (defined($donuts::parentexpiration)) {
    domain_status("Parent zone validity until", scalar localtime($donuts::parentexpiration));
  }

  if (defined($donuts::foundAlignmentProblem)) {
    donuts_error("warning: signatures in this zone are not time aligned");
  }

  # clean up for the next run
  $donuts::sigexpiration = undef;
  $donuts::siginception = undef;
  $donuts::parentinception = undef;
  $donuts::parentexpiration = undef;
</end>
