Re: Parsing Zonefiles
by greenFox (Vicar) on Aug 05, 2004 at 06:35 UTC
|
Unless you have a good reason not to I would be considering generating the zone file directly from your database. It is a technique described in Perl for System Administration and saves parsing the zone file at all.
-- Do not seek to follow in the footsteps of the wise. Seek what they sought. -Basho
| [reply] |
|
| [reply] |
|
Hmmm... now that you mention it... it kinda makes me wonder why I did that in the first place O_o. Anyway, got an online version of that book or the part about zone files?
| [reply] |
|
| [reply] |
|
Re: Parsing Zonefiles
by bgreenlee (Friar) on Aug 05, 2004 at 06:44 UTC
|
I don't have a lot of DNS experience, but any time you're trying to remove duplicates, a little voice should whisper "hash" in your ear. If you can parse the file so that each unique entry becomes the key of a hash, the hash will remove the duplicates for you.
Brad
| [reply] |
|
I think I remember now how those hash thingies work, kinda like a dictionary... but how can that remove the duplicates?? sorry I didn't get that part, I'm still new to perl...
| [reply] |
|
Hashes remove duplicates because hashes have keys - you can't have 2 keys that are the same. If you try to add another key=value pair to the hash where the key already exists, the new key=value will just overwrite the old one.
| [reply] |
Re: Parsing Zonefiles
by fokat (Deacon) on Aug 05, 2004 at 17:36 UTC
|
Hi there:
I don't know if you did look at it, but Net::DNS::ZoneFile will parse most BIND zone files, returning a list of Net::DNS::RR objects as the result.
You can then act on the objects themselves, remove them from the list or add new ones. Finally, you can simply print them to a new file. The pseudo-code would look like:
use Net::DNS;
use Net::DNS::ZoneFile;
my $rrs = Net::DNS::ZoneFile->read("/var/named/named.local",
{
# You might need to set the
# $ORIGIN explicitly here if
# your zone file does not make
# this explicit. See perldoc
}
);
# Print the RRs that were fetched
print $_->string, "\n" for @$rrs;
# Add a sample RR
push @$rrs, new Net::DNS::RR "3 7200 IN PTR always-listed.your.domain.
+";
# Update the serial :)
# You can also "replace" the current serial, with the current date,
# as commonly recommended. However, if you're looking into this, you
# probably have better change control on your zones already.
foreach (@$rrs)
{
next unless $_->type eq 'SOA' and $_->class eq 'IN';
$_->serial($_->serial + 1);
}
# Print the resulting RR set (this could be your new zone by printing
+to
# a file)
print $_->string, "\n" for @$rrs;
Feel free to ask if you need further help with this code...
Best regards
-lem, but some call me fokat
| [reply] [d/l] |
|
Ah!! now I remember why I used a temporary file for the main zone file, It's for the DNS::Zone::File; ... didn't work out though.
Hmmm... Net::DNS::ZoneFile might just be what I'm looking for... I tried executing it till the print part, but didn't get any results.
| [reply] |
Re: Parsing Zonefiles
by tomhukins (Curate) on Aug 05, 2004 at 17:00 UTC
|
If you're generating the zone files automatically, and you know they'll render in a certain format, you could use Template::Extract. This would work especially well if you used Template Toolkit to generate the files. | [reply] |
Re: Parsing Zonefiles
by Elijah_A (Novice) on Aug 06, 2004 at 06:24 UTC
|
I got only one result out of this one:
"3. 7200 IN PTR gov.ph."
#!/usr/bin/perl
use strict;
use warnings;
use Net::DNS;
use lib "/home/postgres/elijah/govph/tests/Net";
use Net::DNS::ZoneFile;
my $rrset = Net::DNS::ZoneFile->read("/home/postgres/elijah/govph/etc/
+namedb/tem
p.gov.ph");
print $_->string, "\n" for @$rrset;
push @$rrset, new Net::DNS::RR "3 7200 IN PTR gov.ph.";
foreach (@$rrset)
{
next unless $_->type eq 'SOA' and $_->class eq 'IN';
$_->serial($_->serial + 1);
}
print $_->string, "\n" for @$rrset;
What am I doing wrong?? I should be getting something like this right?:
; Sta. Magdalena, Sorsogon
; Created by GovPh: Fri Aug 6 13:02:54 2004
stamagdalena IN NS ncc.xx.gov.ph
IN NS ncc.xx.gov.ph
| [reply] [d/l] [select] |
|
Hi Elijah_A:
I believe the problem might be your source file. Are you sure it is a real BIND zone? Your example does not have a SOA record, which might be ok for your scenario.
On my side, the code below (slight modification of yours)...
#!/usr/bin/perl
use strict;
use warnings;
use Net::DNS;
use Net::DNS::ZoneFile;
my $rrset = Net::DNS::ZoneFile->readfh(*DATA);
print "Just read:\n";
print $_->string, "\n" for @$rrset;
push @$rrset, new Net::DNS::RR "3 7200 IN PTR gov.ph.";
foreach (@$rrset)
{
next unless $_->type eq 'SOA' and $_->class eq 'IN';
$_->serial($_->serial + 1);
}
print "After adding one to the SOA's serial:\n";
print $_->string, "\n" for @$rrset;
__DATA__
; Sta. Magdalena, Sorsogon
; Created by GovPh: Fri Aug 6 13:02:54 2004
stamagdalena IN NS ncc.xx.gov.ph
IN NS ncc.xx.gov.ph
Produces the following output...
Just read:
stamagdalena. 0 IN NS ncc.xx.gov.ph.
stamagdalena. 0 IN NS ncc.xx.gov.ph.
After adding one to the SOA's serial:
stamagdalena. 0 IN NS ncc.xx.gov.ph.
stamagdalena. 0 IN NS ncc.xx.gov.ph.
3. 7200 IN PTR gov.ph.
I would check the source file for extraneous characters. For the record, this is what I'm running on my side:
$ perl -MNet::DNS::ZoneFile -e 'print $Net::DNS::ZoneFile::VERSION, "\n"'
1.10
$ perl -v | egrep darwin
This is perl, v5.8.1 built for darwin
Best regards
-lem, but some call me fokat
| [reply] [d/l] |