Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

scandns.pl

by BlueLines (Hermit)
on Jun 20, 2000 at 04:04 UTC ( [id://18912]=sourcecode: print w/replies, xml ) Need Help??
Category: Networking Code
Author/Contact Info jon@divisionbyzero.com
Description:
This script should be pretty straightforward. Feed it a network (ip
address/CIDR or ip address/netmask ) and it scans the dns records of said 
network, reporting theresults to STDOUT. Neat. 

Note: This script views the following notations as equivalent:
	
	10.0.0.0/24
	10.0.0.0/255.255.255.0
	10.0.0.0:255.255.255.0

Rather than reinvent the wheel, I cheated and used Net::Netmask. Eventually
I'll write a sub to handle slash/netmask notation, but until then this program
requires the forementioned module, which is available from cpan.

Here's some example output (and no, none of these machines are publicly
routable, so don't even think about it):


nooky:~$ ./scandns.pl 10.0.0.0/24
<----snip---->
10.0.0.202 => beauty.zacknetwork.com => 10.0.3.101 
10.0.0.203 => tman.zacknetwork.com => 10.0.3.15 
10.0.0.204 => afterglow.zacknetwork.com 
10.0.0.205 => serenity.zacknetwork.com => 10.0.7.10 
10.0.0.206 => girth.zacknetwork.com => girth.zacknetwork.com has no A record
10.0.0.207 => no PTR record
<----snip---->


Note that afterglow's A and PTR records matched. Ideally there shouldn't be
anthing in the third column. If there is, then your forward/inverse records
aren't getting along very well.
#!/usr/bin/perl -w
#
# File:           scandns.pl
# Summary:        dns cleanup tool
#
# Author:         Jon Schatz
# E-Mail:         jon@divisionbyzero.com
# Org:            
#
# Orig-Date:      22-Mar-00 at 13:30:53
# Last-Mod:       19-Jun-00 at 16:24:42 by 
#
#    This program is free software; you can redistribute it and/or mod
+ify it
#    under the terms of the GNU General Public License as published
#    by the Free Software Foundation; either version 1, or (at your op
+tion)
#    any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See either
#    the GNU General Public License or the Artistic License for more d
+etails.
#
# 
# $Source: /home/jschatz/.cvs/el/file-hdr/hdr.perl,v $
# $Date: 1999/12/23 00:06:23 $
# $Revision: 1.1.1.1 $
# $Author: tkunze $
# $State: Exp $
# $Locker:  $
#
# -*- EOF -*-


use IO::Socket;
use Net::Netmask;
use strict;

my ($network)=@ARGV;

#separate the netmask from the network

my ($ip_address,$netmask) = split /[\/||:]/ , $network;
my $address;

&usage unless ($ip_address); #complain if @ARGV was incorrect
&badip unless (&validip($ip_address)); #copmlain if $ip_address is inv
+alid

#complain if $netmask is bad. unfortunately Net::Netmask only warns if
+ it's
#given an invalid netmask. I'm working on a patch so that the module w
+ill
#be smart enough to return something useful when it cant parse the net
+mask.

&badnet unless (&validnet($netmask));

#if the netmask is given as a netmask (ie, 255.255.255.0 as opposed to
+ CIDR
# notation (/24)), then ditch the "/" since Net::Netmask isn't smart e
+nough
# to do that either.

$network=~s/\//:/ if (validip($netmask));

#create the netmask object

(my $obj=Net::Netmask->new ($network)) or die "Invalid address / netma
+sk\n";

#return an array of all addresses in the given network

my (@addresses)=$obj->enumerate();


foreach $address (@addresses) {
  &checkdns($address);
}

#the good stuff

sub checkdns {
  my ($ip_address)=@_;
  my ($packed_ip_address)=&get_packed_ip($ip_address);
  my ($hostname)=gethostbyaddr($packed_ip_address, AF_INET);
  
  if (! $hostname) { 
    &no_ptr("$ip_address"); 
    return; 
  }
  
  my $reverse_packed_ip_address;
  $reverse_packed_ip_address=gethostbyname($hostname);
  
  if (length($reverse_packed_ip_address)!=4) { 
    &no_a("$ip_address","$hostname"); 
    return;
  }
  
  my ($reverse_ip_address)=inet_ntoa($reverse_packed_ip_address);
  
  if ($reverse_ip_address ne $ip_address) {
    print("$ip_address => $hostname => $reverse_ip_address \n");
  }
  
  else {
    print("$ip_address => $hostname \n");
  }
}

sub no_ptr {
  my ($ip_address)=@_;
  print "$ip_address => no PTR record\n";
  
  return;
}

sub no_a {
  my ($ip_address, $hostname)=@_;
  print "$ip_address => $hostname => $hostname has no A record\n";
  return;
}

sub badip {
  print "$ip_address is an invalid address.\n";
  exit 1;
}

sub badnet {
  print "/$netmask is an invalid netmask.\n";
  exit 1;
}

sub usage {
  print "Usage: scandns.pl <address>[/netmask]\n";
  exit 1;
}

sub validnet {
  my ($netmask)=@_;
  return(1) if (validip($netmask)) ;
  return(1) if (($netmask>=0)&&($netmask<=32));
}

#this is an ip checker that seems simpler to me than the enormous rege
+x in
#the cookbook. since it's only executed twice, it's probably not gener
+ating
#that much overhead.

sub validip {
  my ($ip)=@_;
  my $x;
  foreach ($ip=~/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/){ 
    $x++ if(($_>=0)&&($_<=255)); 
  }
  return($x==4);
}

sub get_packed_ip {
 
  my ($ip)=@_;
  chomp $ip;
  my $a;
  my $b;
  my $c;
  my $d;
  ($a, $b, $c, $d)=split(/\./,$ip);
  my $packed_ip=pack "C4","$a","$b","$c","$d";
  return $packed_ip;
}

sub bin2dec {
  my $str= unpack("B8", pack("N", shift));
  $str=~s/^0+(?=\d)//;
  return $str;
}

sub dec2bin {
  return unpack("N",pack("B8", substr("0"x 8, -8)));
}
Replies are listed 'Best First'.
Re: scandns.pl
by taint (Chaplain) on Nov 12, 2013 at 22:01 UTC
    Greetings, BlueLines.

    Great little ditty -- especially in light of the fact it still works, nearly 12yrs. later!

    One little nit;
    Line 146 (my copy) reads:

    return($x==4);
    Which issues:
    Use of uninitialized value $x in numeric eq (==) at ./scandns.pl line +146. Use of uninitialized value $x in numeric eq (==) at ./scandns.pl line +146.
    Changing the offending line to:
    return($x);
    Seems to squelch the complaint(s), and seemingly without ill.

    Just thought I'd mention it, for you, or anyone else pondering it's use. :)

    --Chris

    #!/usr/bin/perl -Tw
    use Perl::Always or die;
    my $perl_version = (5.12.5);
    print $perl_version;

      That's stupid. A better, simpler, less logic-assaulting change would be to address the warning message itself, by changing

      my $x;
      to
      my $x=0;
      More to the point, your "fix" completely blows the logic of the code, which attempts to implement the requirement that all four of the octets must be in the range 0..255. Your "fix" would say that an argument of 1.99999.99999.99999 is a valid IP address.

      I reckon we are the only monastery ever to have a dungeon stuffed with 16,000 zombies.
        Right you are jdporter.

        Boy, was I stupid! It would have killed me to take the time to evaluate it. Rather than simply stripping off the offender.

        I'll take more time, before pressing the "create" button, in the future.

        Sorry for the bother, and thanks for calling me on it, jdporter.

        --Chris

        #!/usr/bin/perl -Tw
        use Perl::Always or die;
        my $perl_version = (5.12.5);
        print $perl_version;
        The eval:
        $x++ if(($_>=0)&&($_<=255));
        as I read it, is:
        if the input ($x), is at least 0, and no greater than 255
        $x is legitimate, so return $x

        So as I see it. There is nothing afoul with my proposed solution.

        :)

        --Chris

        #!/usr/bin/perl -Tw
        use Perl::Always or die;
        my $perl_version = (5.12.5);
        print $perl_version;
        Greetings jdporter.

        So is you're assignment.

        I take back most of my 1st reply to you.

        If choosing you're assignment. CDIR masks will be rejected:

        % ./scandns.pl 209.197.123.153/29 209.197.123.153 is an invalid address. %
        Using my assignment (correct, or incorrect):
        % ./scandns.pl 209.197.123.153/29 209.197.123.152 => renku.org => 4.79.43.173 209.197.123.153 => perlmonks.pair.com 209.197.123.154 => taidsaccount.com 209.197.123.155 => murphyworld.com => 208.91.197.132 209.197.123.156 => beetz.at 209.197.123.157 => best-kids-bedding-prices-online.com => best-kids-be +dding-prices-online.com has no A record 209.197.123.158 => lowest-prices-for-kids-bedding.com => lowest-prices +-for-kids-bedding.com has no A record 209.197.123.159 => no PTR record %
        Not to sound too much the smart a$$. But before ridiculing someone for trying to help. Perhaps it best to test your own solution first?

        Best wishes.

        --Chris

        #!/usr/bin/perl -Tw
        use Perl::Always or die;
        my $perl_version = (5.12.5);
        print $perl_version;

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://18912]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (5)
As of 2024-04-24 01:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found