home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC-Online 1996 May
/
PCOnline_05_1996.bin
/
linux
/
source
/
n
/
bind
/
bind-4.001
/
bind-4~
/
bind-4.9.3-BETA9
/
contrib
/
dnsparse
/
dnsparse.pl
< prev
next >
Wrap
Perl Script
|
1990-09-11
|
7KB
|
255 lines
#!/usr/bin/perl
#
# $Id: dnsparse.pl,v 2.0 90/09/11 11:07:36 hakanson Rel $
#
# Subroutines to parse DNS master (RFC-1035) format files.
# Marion Hakanson (hakanson@cse.ogi.edu)
# Oregon Graduate Institute of Science and Technology
#
# Copyright (c) 1990, Marion Hakanson.
#
# You may distribute under the terms of the GNU General Public License
# as specified in the README file that comes with the dnsparse kit.
#
# Note that this file is not standalone. It requires the dnslex C program,
# and it provides subroutines for a calling Perl program.
#
# One calls dns_init() with a list of input master file names, each
# optionally with an origin domain following it after a comma. The
# typical calling program might pass those from its @ARGV, something
# like "dnstest zone.x,x.edu zone.y.x,y.x.edu".
#
# Then the calling program repeatedly calls dns_getrr() until it returns
# the null array, at which point all the input files are exhausted. Some
# type checking is done, and some minor canonicalization is done (e.g. the
# RR types are capitalized and domain names lower-cased), but more of both
# should be added to catch errors.
#
# Apologies for the ugly code. It was originally designed to take only
# a single input file per invocation, and should really be reworked to
# deal with multiple files more gracefully.
package dns;
$FALSE = 0;
$TRUE = 1;
$prog = $main'0;
$prog =~ s?^.*/??;
# Defaults
$dnslex = 'dnslex';
$delim = ':';
# Package globals
$initialized = $FALSE;
$fileopen = $FALSE;
$alldone = $FALSE;
$pid = 0;
sub main'dns_init {
if ( $#_ < $[ ) {
@dns_argv = (',');
} else {
@dns_argv = @_;
}
$initialized = $TRUE;
}
sub main'dns_getrr {
local (@data);
local ($tmp,$data);
local ($ttl,$class,$type);
die "$prog: dns_init() not called, aborted" unless ($initialized);
#print STDERR "inside dns_getrr()\n";
while (1) {
#print STDERR "inside outer-while\n";
tryopen: until ( $fileopen || $alldone ) {
#print STDERR "inside tryopen\n";
if ( $#dns_argv < $[ ) {
$alldone = $TRUE;
next tryopen;
}
($ifile,$origin1) = do main'dns_commasplit(shift(@dns_argv));
if ( $ifile eq '' || $ifile eq '-' ) {
$ifile = '';
@dns_argv = (); # STDIN must be last
} else {
unless ( -r $ifile ) {
print STDERR "$prog: $ifile: $!, trying another\n";
next tryopen;
}
$ifile = "< $ifile";
}
$pid = open(DNS_IN, "$dnslex -d$delim $ifile |");
unless ( defined($pid) ) {
print STDERR "$prog: Can't start '$dnslex $ifile', trying another\n";
next tryopen;
}
$origin = do main'dns_makefqdn($origin1, ''); # '' is root
$domain = $origin;
$fileopen = $TRUE;
}
#print STDERR "tryopen() done\n";
return () unless ( $fileopen );
#print STDERR "fileopen test passed\n";
dline: while ( <DNS_IN> ) {
#print STDERR $_;
chop;
@data = split(/$delim/o); # split on $delim
#print STDERR "$data[0] $data[1] $data[2]\n";
s/$delim/ /go; # for error msgs
if ( $data[0] =~ /^\$/ ) { # special "$" directives
if ( $data[0] =~ /^\$ORIGIN$/i
&& $data[1] ) {
$origin = do main'dns_makefqdn($data[1], $origin);
} else {
print STDERR "$prog: unknown directive ignored: $_\n";
}
next dline;
}
# Set $domain for the current record. After doing so,
# $data[0] should contain the next field to parse.
dom: {
if ( $data[0] eq "." ) { # root domain
$domain = "";
last dom;
}
if ( $data[0] eq "@" ) { # use $origin
$domain = $origin;
last dom;
}
if ( $data[0] ne "" ) {
$domain = do main'dns_makefqdn($data[0], $origin);
last dom;
}
# otherwise use current domain
}
shift(@data);
if ( $data[0] =~ /^[0-9]+/ ) { # numeric ttl
$ttl = shift(@data);
} else {
$ttl = 0; # default
}
# This defaulting looks strange, but it's what named does
if ( $data[0] =~ /IN/i ||
$data[0] =~ /CHAOS/i ) {
$class = shift(@data);
$class =~ tr/a-z/A-Z/;
} else {
$class = "IN";
}
$type = shift(@data);
$type =~ tr/a-z/A-Z/;
typ: {
if ( $type eq "A" ||
$type eq "WKS" ||
$type eq "HINFO" ||
$type eq "UID" ||
$type eq "GID" ) {
last typ; # no further processing
}
if ( $type eq "SOA" ||
$type eq "MINFO" ) {
$data[0] = do main'dns_makefqdn($data[0], $origin);
$data[1] = do main'dns_makefqdn($data[1], $origin);
last typ;
}
if ( $type eq "NS" ||
$type eq "CNAME" ||
$type eq "MB" ||
$type eq "MG" ||
$type eq "MR" ||
$type eq "PTR" ) {
$data[0] = do main'dns_makefqdn($data[0], $origin);
last typ;
}
if ( $type eq "MX" ) {
if ( $data[0] !~ /^[0-9]/ || $data[0] > 64535 ) {
print STDERR "$prog: bad MX ignored: $_\n";
next dline;
}
$data[1] = do main'dns_makefqdn($data[1], $origin);
last typ;
}
if ( $type eq "UINFO" ) {
# need to check for escaped dot here !!!
($tmp) = split(/./,$domain,1);
$data[0] =~ s/&/$tmp/e;
last typ;
}
# otherwise
print STDERR "$prog: unrecognized type '$type' ignored: $_\n";
next dline;
}
return ($domain,$ttl,$class,$type,@data);
}
close(DNS_IN);
$fileopen = $FALSE;
# now we've hit eof & must open the next file
# to satisfy the getrr() request.
}
}
sub main'dns_makefqdn {
local ($name, $origin) = @_;
return ("") if ( $name eq "." || # root domain
$name eq "" ); # should not happen
# check for non-escaped trailing dot
if ( $name =~ /(.*)(\\*)\.$/
&& (length($2) % 2 == 0) ) {
return ($1.$2); # strip trailing dot
}
$origin =~ s/^\.//; # strip leading dot
return ($name) if ( $origin eq "" );
return ($origin) if ( $name eq "@" );
return ("$name.$origin");
}
# The file args may be of the form 'file,domain', where ',' is
# the first un-doubled comma (later commas are not processed).
sub main'dns_commasplit {
local ($_) = @_;
local ($first,$secnd);
$first = '';
$secnd = '';
commasplit: while ( /,/ ) {
$first .= $`; # before the comma
$_ = $'; # and after it
if ( s/^,// ) { # turn double into a single & continue
$first .= ',';
} else { # make the split
$secnd = $_;
$_ = ''; # remainder goes above
last commasplit;
}
}
$first .= $_; # in case no single comma was found
($first,$secnd);
}