#!/usr/bin/perl # # # Creation Date: 21st July 2003 # # Author: # Peter P. McGarvey # # Additional Code: # Evren Yurtesen # # VERSION HISTORY # # format x.y.z # - x = Major version number # - y = Minior version number # - z = Burst number # I work in bursts. Weekend here, couple of hours a night # there, then a night (a week etc.) off to think. The # `burst number' helps me keep track of different versions # methinks CVS would be a good idea one day. # # 0.0.1 2003-07-21 - Peter P. McGarvey # * A NASTY hack of a perl script. # 0.1.1 2003-07-22 - Evren Yurtesen # * Added named.conf file parsing # * Added automatical nameserver checking # use vars qw($VERSION); $VERSION = '0.1.1'; # # ============================================================================= #location of named.conf file $named_conf="named.conf"; #the name servers you expect to see @nameservers=('ns1.ispro.net','ns2.ispro.net','dns1.ispro.net.tr','dns2.ispro.net.tr'); #debugging level (the higher, the more text!) $debug=20; # ============================================================================= # Starting the Code use Net::DNS; my $timeout=0; my @domainlist = &get_domain_list; foreach my $zone (&get_domain_list) { #while(my $zone = ) { print "# zone: $zone\n"; my ($parent_zone) = $zone =~ /^[^\.]*\.(.*)/; print "# parent of $zone is $parent_zone\n"; my $parent_auth_primary = &get_auth_primary($parent_zone, $timeout); if ($parent_auth_primary == -1) { print "# DEAD ZONE!\n# ABORT\n\n"; print DEAD "# $zone\n"; next; } print "# parent auth primary is: $parent_auth_primary\n"; my @auth_servers = &get_ns_list($zone, $parent_auth_primary, $timeout); if (scalar(@auth_servers) == 0) { print "# No auth servers, DEAD ZONE!\n"; print DEAD "$zone\n"; next; } foreach my $ns (@auth_servers) { $ns = lc($ns); print $ns, "\n"; } } # ============================================================================= # End of the Code - Start of the Sub-Functions # &get_domain_list - Returns the list of domains from named.conf.file # &get_auth_primary - Takes the name of a zone # Return the MNAME field from the SOA # &get_ns_list - Returns the list of NS records reported by that server # ============================================================================= # Returns the list of domains from named.conf file sub get_domain_list { open(NAMED_CONF,"< $named_conf") or die "Can not open $named_conf"; #set some variables to 0 $comment_block_starting=0; $comment_block_started=0; #make a list of domains while($line=) { #find if there is double backslash and use only left of it #we must put newline if($line =~ /\/\//) { $line=(split /\/\//,$line)[0]."\n"; } #find if there is both /* my text */ in $line and use only outside if ($line =~ /\/\*/ && $line =~ /\*\//) { @values1=split(/\/\*/,$line); @values2=split(/\*\//,$line); $line=$values1[0].$values2[1]; } else { #find if there is only one of them? #if there is only /* take left side and wait until finding */ if($line =~ /\/\*/) { $line=(split /\/\*/,$line)[0]; #count the occurances in case if they are nested $comment_block_starting+=1; } #if there is only */ then stop waiting and take right side if($line =~ /\*\//) { $line=(split /\*\//,$line)[1]; if(($comment_block_starting-=1) eq 0) { $comment_block_started=0; } } } if (($comment_block_started=$comment_block_starting) eq 0) { if($line =~ /zone.+\".+\"/ && ! ($line =~ /zone.+\"."/ || $line =~ /zone.+\".*ARPA\"/i)) { $line=(split /\"/,$line)[1]; #cut out left and right spaces just to be sure $line =~ s/^\s+|\s+$//g; push(@domainlist,$line); } } } close(NAMED_CONF); return sort @domainlist; } # ============================================================================= # Takes the name of a zone # Return the MNAME field from the SOA sub get_auth_primary { my $zone = shift; my $tcp_timeout = shift; my $res = new Net::DNS::Resolver; my $packet = new Net::DNS::Packet($zone, "SOA", "IN"); $res->tcp_timeout($tcp_timeout) if $tcp_timeout; my $req = $res->send($packet); return -1 unless defined($req); return -1 unless ( ($req->header->ancount >= 1) && (($req->answer)[0]->type eq "SOA") ); return ($req->answer)[0]->mname . "."; # Return the FQDN } # ============================================================================= # Returns the list of NS records reported by that server sub get_ns_list { my $zone = shift; my $server = shift; my $tcp_timeout = shift; my @ns_list; my $res = new Net::DNS::Resolver; $res->tcp_timeout($tcp_timeout) if $tcp_timeout; #die "FAIL: NS has no address (" . $res->errorstring . ")" return @ns_list unless $res->nameservers($server); my $req = $res->query($zone, "NS"); #die "WARN: NS query results were bad (" . $res->errorstring . ")" return @ns_list unless ( defined($req) && ($req->header->ancount > 0) ); foreach my $rr_ns ($req->answer) { push @ns_list, $rr_ns->nsdname . "."; #FQDN! } return sort @ns_list; }