App-DNS-Zonewalk

 view release on metacpan or  search on metacpan

bin/zonewalk  view on Meta::CPAN

use App::DNS::Zonewalk qw();
use Getopt::Long qw(GetOptions);
use Pod::Usage qw(pod2usage);

our $VERSION = '0.05';

our $debug;
our $v4;
our $v6;
our $long_listing;
our $server;
our $start_zone;

handle_options();
my $rec_zone_listing = run_raxfr($start_zone);
print_rec_zone($rec_zone_listing);
exit;

###############################################################
#                         end of main
###############################################################

#
# check cmdline flags and args
#
sub handle_options {

    GetOptions(
        'debug|d'    => \$debug,
        '4'          => \$v4,
        '6'          => \$v6,
        'long|l'     => \$long_listing,
        'server|s=s' => \$server,
      )
      or pod2usage(
        -exitval => 2,
        -verbose => 1,
      );

    # get the start zone from cmdline
    $start_zone = lc shift @ARGV
      or pod2usage(
        -exitval => 2,
        -verbose => 1,
        -message => 'missing zone',
      );

    # #####################
    # convenience function
    # #####################
    #
    # check for IPv4 address as start zone, build reverse zone
    if ( Net::DNS::Resolver::Base::_ip_is_ipv4($start_zone) ) {
        my @octets = split( /\./, $start_zone );
        $start_zone = join( '.', reverse @octets );
        $start_zone .= '.in-addr.arpa';
    }
    # check for IPv6 address as start zone, build reverse zone
    elsif ( Net::DNS::Resolver::Base::_ip_is_ipv6($start_zone) ) {

        # this simple algo works only for fully expanded IPv6 addresses
        $start_zone =~ s/://g;
        my @octets = split( //, $start_zone );
        $start_zone = join( '.', reverse @octets );
        $start_zone .= '.ip6.arpa';
    }

    return 1;
}

#
# create a Net::DNS::Resolver object and do a raxfr() fro start zone
# return an array-ref of Net::DNS::RR objects from zone walk
#
sub run_raxfr {
    my $zone = shift;

    my $resolver = App::DNS::Zonewalk->new(
        retrans     => 1,
        retry       => 1,
        tcp_timeout => 3,
        debug       => $debug,
        $server ? ( nameservers => [$server] ) : (),
    );

    my $rec_zone_listing = $resolver->raxfr($zone);
    unless (@$rec_zone_listing) {
        warn "Cannot fetch '$zone': ", $resolver->errorstring, "\n";
        exit 1;
    }

    return $rec_zone_listing;
}

#
# print A, AAAA or PTR records as default
# only when requested (-l) do a full RR listing
#
sub print_rec_zone {
    my ($zone) = @_;

    foreach my $rr (@$zone) {

        if ($long_listing) {
            $rr->print;
            next;
        }

        # was this a reverse_zone walk, just print the PTR records
        if ( $start_zone =~ m/ .* \.in-addr\.arpa $ | .* \.ip6\.arpa $/ix )
        {
            printf "%-30s %s\n", $rr->name, $rr->ptrdname
              if $rr->type eq 'PTR';
            next;
        }

        given ( $rr->type ) {

            when ('A') {
                printf "%-15s %s\n", $rr->address, $rr->name unless $v6;
            }



( run in 1.819 second using v1.01-cache-2.11-cpan-a9496e3eb41 )