home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!tcsi.com!iat.holonet.net!news.cerf.net!usc!zaphod.mps.ohio-state.edu!saimiri.primate.wisc.edu!usenet.coe.montana.edu!news.u.washington.edu!news.uoregon.edu!pith.uoregon.edu!meyer
- From: meyer@darkwing.uoregon.edu (David M. Meyer 503/346-1747)
- Newsgroups: comp.protocols.tcp-ip.domains
- Subject: how to you do consistency checking?
- Date: 26 Jan 93 16:47:57
- Organization: University Network Services, University of Oregon, Eugene, OR
- 97403
- Lines: 364
- Distribution: world
- Message-ID: <MEYER.93Jan26164757@darkwing.uoregon.edu>
- NNTP-Posting-Host: darkwing.uoregon.edu
-
-
-
- I have the need to check consistency checking between my
- zone and reverse zone files. I wrote the following perl
- code, but I'm not too happy with it. Anyone have anything
- better, or suggestions on how to make this better?
-
- Thanks,
-
-
- Dave
-
- David M. Meyer Voice: 503/346-1747
- Senior Network Engineer Pager: 503/342-9458
- Office of University Computing FAX: 503/346-4397
- Computing Center Internet: meyer@ns.uoregon.edu
- University of Oregon
- 1225 Kincaid
- Eugene, OR 97403
-
-
-
- -------
-
-
- #!/usr/local/bin/perl -- # -*- perl -*-
-
- #
- # checkdns --
- #
- # Be mindful of the multitiude of errors I make here...
- #
- # David M. Meyer
- # meyer@phloem.uoregon.edu
- # 15-Jan-93
- #
- # $Header: /usr/local/etc/named/RCS/checkdns,v 1.0 1993/01/27 00:36:55 meyer Exp $
- #
- #
- require('getopts.pl');
-
- ($program = $0) =~ s%.*/%%;
- $Usage = " [args] \
- -d for debugging \
- -i <initial domain name> \
- -n <network number> \
- -r <path to reverse zone file> \
- -s <subnet mask> (subnet octet only) \
- -u for this message \
- -z <path to zone file> \
- ";
-
- do Getopts("di:n:r:s:uz:");
-
- if ($opt_d eq "") {
- $DEBUG = 0;
- } else {
- $DEBUG = 1;
- }
-
- if ($opt_i eq "") {
- $domain = "uoregon.edu";
- } else {
- $domain = $opt_i;
- }
-
- if ($opt_n eq "") {
- $network = "128.223";
- } else {
- $network = $opt_n;
- }
-
- if ($opt_r eq "") {
- $revzonefile = "/usr/local/etc/named/uoregon.rev";
- } else {
- $revzonefile = $opt_r;
- }
-
- if ($opt_s eq "") {
- $subnetmask = 0xfe; # subnet only
- } else {
- $subnetmask = $opt_s;
- }
- if ($opt_u ne "") {
- printf("Usage: $program $Usage");
- exit 1;
- }
-
- if ($opt_z eq "") {
- $zonefile = "/usr/local/etc/named/uoregon.zone";
- } else {
- $zonefile = $opt_z;
- }
-
-
- #
- # Do some inititalizing...
- #
-
- $GOOD = 0;
- $BAD = 1;
- $exitval = $GOOD;
- $HaveRevNotZone = 0;
- $HaveInconsistent = 0;
- $HaveBadIP = 0;
- $NoNameServer = 0;
-
-
- select(STDERR); $| = 1;
- &CheckZone($zonefile);
- &CheckRevZone($revzonefile);
- printf("\nAnalyzing...\n");
-
-
- #
- # First, check for inconsistency
- #
-
- if ($HaveInconsistent) {
- foreach $ipaddr (sort keys(%Inconsistent)) {
- printf(STDERR "%s inconsistent\n", $ipaddr);
- }
- $exitval = $BAD;
- }
-
- #
- # Now, just see if every address in the zone file is
- # actually in the reverse zone file. If not, check that the
- # file actually had a good IP address (not a typo -> inconsistent).
- #
-
- foreach $ipaddr (sort keys(%ZoneHaveSeen)) {
- next if &NotOurSubnet($ipaddr);
- if ($RevHaveSeen{$ipaddr} ne $ipaddr) {
- if (!&CouldBeIPAddr($ipaddr)) {
- printf(STDERR "Bad IP address for %s (%s) in %s\n",
- $IPAddrs{$ipaddr}, $ipaddr, $zonefile);
- }
- printf(STDERR "Missing %s (%s) from %s\n",
- $IPAddrs{$ipaddr}, $ipaddr, $revzonefile);
- $exitval = $BAD;
- }
- }
-
- #
- # Check for addresses in the reverse zone file which are not
- # in the zone file
- #
-
- if ($HaveRevNotZone) {
- foreach $ipaddr (sort keys(%RevNotZone)) {
- $fqdn = $RevNotZone{$ipaddr};
- printf(STDERR "Missing %s (%s) from %s\n",
- $fqdn, $ipaddr, $zonefile);
- if (!&CouldBeIPAddr($ipaddr)) {
- printf(STDERR "Bad IP address for %s (%s) in %s\n",
- $fqdn,$ipaddr, $revzonefile);
- }
- }
- $exitval = $BAD;
- }
-
- if ($HaveBadIP) {
- foreach $ipaddr (sort keys(%BadIP)) {
- $fqdn = $BadIP{$ipaddr};
- printf(STDERR "%s (%s) bad IP address\n", $fqdn, $ipaddr);
- }
- $exitval = $BAD;
- }
-
- if ($NoNameServer) {
- foreach $ns (sort keys(%NoNameServer)) {
- printf(STDERR "Inconsistent NS records for %s\n", $ns);
- }
- $exitval = $BAD;
- }
-
- exit $exitval;
-
- #
- # Just check A records in a zone file. "Try" to handle include
- # files...
- #
-
- sub CheckZone {
- local($zonefile) = @_;
- open(ZONE, $zonefile) || die "Can't open ZONE FILE: $!\n";
- printf("Reading zone file (%s)\n", $zonefile);
- while (<ZONE>) {
- next if /^$/; # throw blank lines
- next if /^[\s]*;/; # throw comments
- if (/[^\s]*\$[include|INCLUDE]/) {
- ($include_file) = /[include|INCLUDE]\W+([^'"\s]+)/;
- &CheckZone($include_file);
- }
- chop; # and \n on last field
- @tmp = split; # now get fields
-
- if ($tmp[0] eq '$origin') {
- chop($tmp[1]); # remove trailing .
- $domain = $tmp[1];
- } elsif ($tmp[2] eq 'NS') { # $tmp[0] = domain
- $NameServer{$tmp[3]} = $tmp[0]; # $tmp[3] = NS
- } elsif ($tmp[3] eq 'NS') { # ttl
- $NameServer{$tmp[4]} = $tmp[0];
- } elsif ($tmp[2] eq 'A') { # no ttl
- if (!&SpecialCase($tmp[0])) { # $tmp[0] = name
- &HandleARecord($tmp[0],$domain,$tmp[3]);# $tmp[3] = IP addr
- }
- } elsif ($tmp[3] eq 'A') { # have ttl
- if (!&SpecialCase($tmp[0])) { # $tmp[0] = name
- &HandleARecord($tmp[0],$domain,$tmp[4]);# $tmp[4 = IP addr
- }
- }
-
- }
- close(ZONE);
- printf("Done with $zonefile\n");
- }
-
- #
- # Just check PTR records in a reverse zone file. "Try" to handle
- # include files...
- #
-
- sub CheckRevZone {
- local($revzonefile) = @_;
-
- open(REVZONE, $revzonefile) || die "Can't open REVERSE ZONE FILE: $!\n";
- printf("Reading reverse zone file (%s)\n", $revzonefile);
-
- while (<REVZONE>) {
- next if /^$/; # throw blank lines
- next if /^[\s]*[;@]/; # throw comments
- if (/[^\s]*\$[include|INCLUDE]/) {
- ($include_file) = /[include|INCLUDE]\W+([^'"\s]+)/;
- &CheckRevZone($include_file);
- }
- chop; # and \n on last field
- @tmp = split; # get fields
-
- @addr = split(/[. ]/,$tmp[0]); # get addr octets
-
- if (($tmp[2] eq 'A') || ($tmp[3] eq 'A')) { # Ignore NSs
- next if ($NameServer{$tmp[0]} ne "");
- $NoNameServer{$tmp[0]} = $tmp[0];
- $NoNameServer = 1;
- next;
- }
- #
- # Ignore inverse address 0.0 and and NS glue records
- #
- next if (($addr[0] eq "") ||
- ($addr[1] eq "") ||
- ($addr[0] eq "0") ||
- ($addr[1] eq "0")); # Ignore this
-
- $fqdn = $tmp[$#tmp]; # last in rev file
- chop($fqdn); # trailing .
- $ipaddr = sprintf("%s.%s.%s", $network,$addr[1],$addr[0]);
- $RevHaveSeen{$ipaddr} = $ipaddr;
-
- if ($DEBUG) {
- printf("revzone:\t$fqdn,$ipaddr\n");
- }
-
- if ($IPAddrs{$ipaddr} eq "") {
- $HaveRevNotZone = 1;
- $RevNotZone{$ipaddr} = $fqdn;
- }
- if ($IPAddrs{$ipaddr} ne $fqdn) {
- $HaveInconsistent = 1;
- $Inconsistent{$ipaddr} = $fqdn;
- }
- if (!&CouldBeIPAddr($ipaddr)) {
- $HaveBadIP = 1;
- $BadIP{$ipaddr} = $fqdn;
- }
- }
- close(REVZONE);
- printf("Done with $revzonefile\n");
- }
-
-
- #
- # Find out if it could be an IP address...
- #
- # NB. Doesn't catch problems trailing digits on the
- # last octet, e.g., 128.223.32.115e won't be
- # detected.
- #
- #
- #
-
- sub CouldBeIPAddr {
- local($ipaddr) = @_;
- @octets = split(/[. ]/,$ipaddr);
- if ($#octets != 3) { # count from 0
- return(0);
- }
- if ($ipaddr =~ /(\d+\.\d+\.\d+\.\d+)/) {
- return(1);
- } else {
- return(0);
- }
- }
-
- #
- # Handle Glue and other A records for which we don't have
- # in-addr.arpa authority.
- #
-
- sub NotOurSubnet {
- local($ipaddr) = @_;
- @addr = split(/[. ]/,$ipaddr);
- $subnet = $subnetmask & $addr[2];
- if (($addr[0] == 128) &&
- ($addr[1] == 223) &&
- ($subnet != 4) &&
- ($subnet != 6) &&
- ($subnet != 8) &&
- ($subnet != 90)) {
- return(0);
- } else {
- return(1);
- }
- }
-
-
- #
- # These names are special cases...
- #
-
- sub SpecialCase {
- local($name) = @_;
- $name =~ y/A-Z/a-z/; # canonicalize to lower...
- if ($name eq "localhost") {
- return(1);
- } else {
- return(0);
- }
- }
-
- #
- # Do this if A Record
- #
- #
-
- sub HandleARecord {
- local($name,$domain,$ipaddr) = @_;
- if ($name eq "") {
- $name = $lastname;
- } else {
- $lastname = $name;
- }
- $fqdn = sprintf("%s.%s.",$name,$domain);
- chop($fqdn);
- $IPAddrs{$ipaddr} = $fqdn;
- $ZoneHaveSeen{$ipaddr} = $ipaddr;
- if ($DEBUG) {
- printf("zone:\t%s,%s\n",$fqdn,$ipaddr);
- }
- }
-
-