#Date: Mon, 26 Apr 1993 09:28:17 -0700 #From: Don Lewis <gdonl@ssi1.com> #Message-Id: <199304261628.AA09295@sunrise.ssi1.com> #To: vixie #Subject: Re: send me your tools #!/bin/sh # shar: Shell Archiver (v1.22) # # Run the following text with /bin/sh to create: # dnsrpt # sed 's/^X//' << 'SHAR_EOF' > dnsrpt && X#!/usr/local/bin/perl X# X# Copyright (c) 1993 by Silicon Systems Inc. X# X# Permission to use, copy, modify, and distribute this software for any X# purpose with or without fee is hereby granted, provided that this X# copyright notice appear in all copies, and that the name of Silicon X# Systems Inc. not be used in advertising or publicity pertaining to X# distribution of the document or software without specific, X# written prior permission. X# X# THE SOFTWARE IS PROVIDED "AS IS" AND SILICON SYSTEMS INC. DISCLAIMS ALL X# WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES X# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL SILICON SYTEMS X# INC. BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL X# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR X# PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS X# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS X# SOFTWARE. X# X# Author: Don Lewis <gdonl@ssi1.com> X# X# This perl script reads the /etc/named.boot file to find all the zone X# files. It reads the zone files and produces a report listing the X# hosts sorted by both name and address in a format similar to that of X# /etc/hosts (the difference being that this report contains multiple X# address fields for multi-homed hosts). This script checks that the X# A RRs and PTR RRs match up, and also knows about CNAME RRs. X# X# This script is fairly dependent on having a complete set of the zone X# files for a domain (both forward and reverse) accessable. X# X Xsub getnonblank { X local ($line, $instring, $inparens, $saweof); X local ($handle) = @_; X X $instring = 0; X $inparens = 0; X $saweof = 0; X X do { X $line = ''; X do { X $c = getc($handle); X if ($c eq ';') { X do { X $c = getc($handle); X if ($c eq '') { X last; X } X } while ($c ne "\n"); X } X if ($c eq '') { X $saweof = 1; X last; X } elsif ($c eq ';') { X $line .= $c; X } else { X $line .= $c; X } X if ($instring) { X if ($c eq '"') { X $instring = 0; X } X } else { X if ($c eq '"') { X $instring = 1; X } elsif ($c eq '(') { X $inparens = 1; X } elsif ($c eq ')') { X $inparens = 0; X } X } X } while ( $inparens || $c ne "\n" ); X } while ((! $saweof) && (split(/[ \t\n]/, $line) == 0)); X return($line); X} X Xsub parsezone { X local ($origin) = $_[0]; X local ($zonefile) = $_[1]; X local ($zonedata); X local ($owner); X X if ($origin ne '.') { X $origin .= '.'; X } X X if ($directory ne '') { X $zonefile = $directory . '/' . $zonefile; X } X X if (! -f $zonefile) { X die "zone file '" . $zonefile . "' for zone '" . $origin . "' is not a file\n"; X } X if (open(zone, $zonefile) != 1) { X die "can't open zone file '" . $zonefile . "' for zone '" . $origin . "'\n"; X } X X while ($zonedata = &getnonblank(zone)) { X split(/[ \t\n]+/, $zonedata); X if ($_[0] eq '$ORIGIN') { X $origin = $_[1]; X } else { X if ($_[0] ne '') { X if ($_[0] eq '@') { X $owner = $origin; X } elsif ($_[0] =~ /.*\.$/) { X $owner = $_[0]; X } elsif ($origin eq '.') { X $owner = $_[0] . '.'; X } else { X $owner = $_[0] . '.' . $origin; X } X } X shift; # skip owner X if ($_[0] =~ /^[0-9]+$/) { X shift; # skip ttl X } X if ($_[0] ne 'IN') { X print "skipping non-IN class RR " . $zonedata; X next; X } X shift; # skip class X if ($_[0] eq 'A') { X if ($addrtohost{$_[1]}) { X local (@tmpvar); X foreach $var (split(/ /, $addrtohost{$_[1]})) { X $tmpvar{$var} = 'junk'; X } X if (! $tmpvar{$owner} ) { X $addrtohost{$_[1]} .= " " . $owner; X } X } else { X $addrtohost{$_[1]} = $owner; X } X if ($hosttoaddr{$owner}) { X local (@tmpvar); X foreach $var (split(/ /, $hosttoaddr{$owner})) { X $tmpvar{$var} = 'junk'; X } X if (! $tmpvar{$_[1]} ) { X $hosttoaddr{$owner} .= " " . $_[1]; X } X } else { X $hosttoaddr{$owner} = $_[1]; X } X } elsif ($_[0] eq 'CNAME') { X local ($hostname); X X if ($_[1] =~ /.*\.$/) { X $hostname = $_[1]; X } elsif ($origin eq '.') { X $hostname = $_[1] . '.'; X } else { X $hostname = $_[1] . '.' . $origin; X } X X if ($hosttocname{$hostname}) { X $hosttocname{$hostname} .= " " . $owner; X } else { X $hosttocname{$hostname} = $owner; X } X } elsif ($_[0] eq 'PTR') { X if ($ptrtohost{$owner}) { X $ptrtohost{$owner} .= " " . $_[1]; X } else { X $ptrtohost{$owner} = $_[1]; X } X } X } X } X X close(zone); X} X Xsub cmpaddr { X local (@addr1) = split(/\./, $a); X local (@addr2) = split(/\./, $b); X X for ($i = 0; $i < 4; $i++) { X if ($addr1[$i] != $addr2[$i]) { X return($addr1[$i] - $addr2[$i]); X } X } X return(0); X} X Xif (open(bootfile, "</etc/named.boot") != 1) { X die "can't open /etc/named.boot\n"; X} X Xwhile ($cmd = &getnonblank(bootfile)) { X split(/[ \t\n]+/, $cmd); X if ($_[0] eq 'directory') { X $directory = $_[1]; X } elsif ($_[0] eq 'primary') { X &parsezone( $_[1], $_[2]); X } elsif ($_[0] eq 'secondary') { X &parsezone( $_[1], $_[$#_]); X } X} X Xforeach $addr (keys(%addrtohost)) { X local ($revaddr) = join('.', reverse(split(/\./, $addr))); X local ($ptr) = $ptrtohost{$revaddr . '.in-addr.arpa.'}; X local ($hostname) = $addrtohost{$addr}; X X if (! $ptr ) { X print "address " . $addr . " (" . $hostname . ") has no matching PTR record\n"; X } elsif ( $ptr ne $hostname ) { X print "address " . $addr . " has name " . $hostname . " and PTR " . $ptr . "\n"; X } X} X Xforeach $ptr (keys(%ptrtohost)) { X local ($hostname) = $ptrtohost{$ptr}; X local (@parts) = split(/\./, $ptr); X X if ($parts[$#parts] eq 'arpa' && $parts[$#parts - 1] eq 'in-addr') { X X if ( ! $hosttoaddr{$hostname} ) { X if ( $ptrtohost{$hostname} ) { X if ( $ptrtohost{$hostname} ne $ptr ) { X print "mismatched PTRs for " . $ptr . " and " . $hostname . "\n"; X } X } else { X print "PTR " . $ptr . " to " . $hostname . " is dangling\n"; X } X } else { X local ($addr) = $parts[3] . '.' . $parts[2] . '.' . $parts[1] . '.' . $parts[0]; X X if ( ! $addrtohost{$addr} ) { X print "PTR " . $ptr . " to " . $hostname . " refers to an invalid address\n"; X } elsif ( $hostname ne $addrtohost{$addr} ) { X print "PTR " . $ptr . " to " . $hostname . " has address of host " . $addrtohost{$addr} . "\n"; X } X } X } elsif ( ! $ptrtohost{$hostname} ) { X print "network PTR " . $ptr . " to " . $hostname . " is dangling\n"; X } X} X Xprint " Hosts Sorted by Name\n\n\n"; X Xforeach $host (sort(keys(%hosttoaddr))) { X local ($count) = 0; X foreach $addr (split(/ /, $hosttoaddr{$host})) { X $count++; X printf("%-16s", $addr); X } X for (; $count < 2; $count++) { X printf("%-16s", ""); X } X printf " %s", $host; X if ($hosttocname{$host}) { X print ' ' . $hosttocname{$host}; X } X print "\n"; X} X Xprint "\f Hosts Sorted by Address\n\n\n"; X Xforeach $addr (sort(cmpaddr keys(%addrtohost))) { X printf "%-32s %s\n", $addr, $addrtohost{$addr}; X} SHAR_EOF chmod 0755 dnsrpt || echo "restore of dnsrpt fails" exit 0 Don "Truck" Lewis Phone: +1 916 478-8284 Silicon Systems Internet: gdonl@ssi1.com FAX: +1 916 478-8251 138 New Mohawk Road UUCP: {uunet,tektronix!gvgpsa.gvg.tek.com}!ssigv!gdonl Nevada City, CA 95959