#!/usr/bin/perl -w
# tristan+dns@ethereal.net 7mar2003
# 
# goes through a list of domains to slave, verifies their legitimacy, outputs
# bind8/9 config
#
# whipped this up in about an hour, don't blame me for bugs :)

@::iam = qw(ns1.ethereal.net ns.yikes.net spicy.datasoup.com);
$::root = 'a.root-servers.net.';

use Net::DNS;
use strict;

sub runquery {
  my($res, $domain, $domains, $ns) = @_;

  $$res->nameservers($ns);

  my $packet = Net::DNS::Packet->new($domain, 'NS', 'IN');
  my $query = $$res->send($packet);

  if ($query) {
    if ($query->answer) {
      my $good;
      my @nameservers;
      foreach my $rr ($query->answer) {
        next unless $rr->type eq 'NS';
        my $name = lc $rr->nsdname;
        if ($::iam{$name}) {
          $good = 1;
        } else {
          push(@nameservers, $name);
        }
      }
      if ($good) {
        @{$$domains{$domain}{ns}} = @nameservers;
      } else {
        $$domains{$domain}{bad} = "exists, but I'm not a nameserver for it";
      }
      return 1;
    } elsif ($query->authority) {
      my $results = 0;
      foreach my $rr ($query->authority) {
        next unless $rr->type eq 'NS';
        $results++;
        last if runquery($res, $domain, $domains, $rr->nsdname);
      }
      $$domains{$domain}{bad} = "domain doesn't exist" unless $results;
    }
  } else {
    warn "query against $ns failed: ", $$res->errorstring, "\n";
  }
}

sub main {
  my $res = Net::DNS::Resolver->new;
  my $res2 = Net::DNS::Resolver->new;
  $res->recurse(0);
  $res->udp_timeout(3);
  $res->tcp_timeout(3);

  my %domains;

  for (@::iam) {
    $::iam{$_} = 1;
  }

  while (<>) {
    chomp;
    if ($_ && !/^#/) {
      warn "doing $_\n";
      runquery(\$res, $_, \%domains, $::root) if ($_ && !/^#/);
    }
  }

  foreach my $domain (sort keys %domains) {

    next if $domains{$domain}{bad};

    my $lame = 1;
    for my $ns (@{$domains{$domain}{ns}}) {
      if ($lame) {
        $res->nameservers($ns);
        my $query = $res->query($domain, 'SOA');
        if ($query && $query->answer) {
          foreach my $rr ($query->answer) {
            next unless $rr->type eq 'SOA';
            my $mname = $rr->mname;
            if ($::iam{$mname}) {
              $domains{$domain}{bad} = "SOA MNAME is me";
              last;
            }
            $res->nameserver($mname);
            my @zone = $res->axfr($domain);
  
            if ($#zone > 0) {
              my $query = $res2->search($mname);
              if ($query && $query->answer) {
                foreach my $rr ($query->answer) {
                  next unless $rr->type eq 'A';
                  my $addr = $rr->address;
                  print <<EOF;
zone "$domain" {
  type slave;
  masters {
    $addr;
  };
};

EOF
                }
              } else {
                # this shouldn't happen...
                $domains{$domain}{bad} = "can't look up $mname";
              }
            } else {
              $domains{$domain}{bad} = "$mname refused AXFR";
            }
            $lame = 0;
          }
        } else {
          $domains{$domain}{bad} = "couldn't get SOA - lame delegation to $ns";
        }
      }
    }
  }
  
  foreach my $domain (sort keys %domains) {
    next unless $domains{$domain}{bad};
    print "// $domain: $domains{$domain}{bad}\n";
  }
}

main;
