http://qs321.pair.com?node_id=345396

sunadmn has asked for the wisdom of the Perl Monks concerning the following question:

Good morning all first I would like to thank all the monks who have put up with me this week in my quest for knowldge I know I have some silly questions at times, but I promise it is just in the quest to better understand the wonders of perl. Anyway on to my battle I have been working with various DNS mods to parse over 30,000 zone files i have on my DNS system to get the data into a mySQL DB for managment and I thought I had this one whipped, but I have come across an issue that for the life of me I can't figure out and come to you all for help.
After some playing and hacking of the mods I have decided that my best fit will be Net::DNS::ZoneFile for this task, now the issue I have is that I want to only parse certain zone files for certain data ( A CNAME MX NS PTR ) now for the most part I have my other scripts working the only two I have trouble with are the scripts for forward records ( A ) and reverse ( PTR ). The mod understands the standards in Bind for RR types and has added functionality for the special $GENERATE and $INCLUDE. The issue I run into with the code below is that when I parse for forward and reverse data with my test to m/^A/ or m/PTR/ is that once the file is loaded and the parse begins once the read finds a line with the $GENERATE on it the script hangs and doesn't know what to do. I have done testing to see what the mod is doing and calls to to build the record {type} and that produces A NS CNAME MX PTR but doesn't match the $GENERATE, so the issue I have is how do I test for that and then build that data so I may insert into my DB. In the Net::DNS::ZoneFile ZoneFile.pm the sub _parse seems to build the data on the fly ( please see the sub for this ) so I know that the test for {type} wont work here and I am at my wits end as how to make this work for both standard records and the special $GENERATE if anyone could please help me out as I am loosing much hair over this one.

Below is my code so far.
#!/usr/bin/perl use strict; use warnings; use File::Find; use FileHandle; use Data::Dumper; use Net::DNS::ZoneFile; use DBI; my $dbh = DBI->connect( "DBI:mysql:database=dns;host=localhost", "root", "test", {'RaiseError' => 1} ); my $sth = $dbh->prepare( "INSERT INTO a (hname,zone,host) VALUES (?,?,?)" ); my $base = "/chroot/named/master/net"; find(\&wanted, $base); $dbh->disconnect(); exit; sub wanted { return unless ( -f "$File::Find::name" and $File::Find::name !~ m! + /in-addr/! ); my $index = 1; my $root = shift; my $zone = new FileHandle "$File::Find::name", "r"; my @name = split('/',$File::Find::name); my $out = join('.', reverse(@name[4..$#name])); my $rrset = Net::DNS::ZoneFile->readfh($zone, $root); for(@$rrset) { print "This is our file to be parsed $out\n"; print "Working on line: ", $index++, ".\n"; print "$_->{type}\n"; print "$_->rdatastr\n" if $_->{type} =~ m/^A/; print "$_->{name},",$_->rdatastr, "\n" if $_->{type} =~ m/^A/; print STDOUT Data::Dumper->Dump([$_->rrset]) . "\n"; if($_->{type} =~ m/^A/) { print "Working on line: ", $index++, ".\n"; $sth->execute( $_->{name}, $out, $_->rdatastr) or die $dbh-> +errstr; } } }
And here is the section from the ZoneFile.pm for the $GENERATE handling.
elsif ($text =~ # $GENERATE s/ \A\$GENERATE \s+ (\d+) \s* - \s* (\d+) \s+ (|\*|\@|\.|([-\w\$\d]+(\.[-\w\$\d]+)*\.?)) \s+ ((IN|HESIOD|CHAOS) \s+)? (\w+) \s+ ([-\w\$\d]+((\.[-\w\$\d]+)*)?\.) \s*$ //mxi) { return undef if $2 < $1; my $rr_template = join(' ', $3, $7 || 'IN', $8, $9); for my $i (reverse $1 .. $2) { my $rr = $rr_template . "\n"; $rr =~ s/\$/$i/g; substr($text, 0, 0) = $rr; } }
SUNADMN
USE PERL