#!/usr/bin/perl -wT
############################################################
##
##  addrchk -- look up names for range of IP addresses
##
##  Usage: addrchk low-addr hi-addr
##
##  By: Rich Lafferty
##     29 Mar, 1998
##
## To-Do: * --noping, --nolookup, --version, --help (getopt)
##        * work with any address range 
##        * pagination
## 

## Here's what we use...
use Net::Ping;
use Net::hostent;
use Socket;

## Set up output formatting.
format TABLE =
@<<<<<<<<<<<<<<  @<<<<<<<<<<<<<<<<<<<<<<<<<<<  @<<<<<
$t_addr, $t_name, $t_alive_p
.

$t_header ="\ 
Address          Hostname                      State\
===============  ============================  ======\n";

## Timeout for ping. 5 seems good; 1 is too short.
$timeout = 1;

###############################################
## Main
##

# set up the display 
print $t_header;

# get our options ready
$net = net_part($ARGV[0]);
if ($net ne net_part($ARGV[1])) { 
    die "Currently, addrchk can only be used within a Class-C.\n";
}
$start = host_part($ARGV[0]);
$end = host_part($ARGV[1]);

# now we'll do the dirty work for each address in the range
for($i = $start; $i <= $end; $i++) {
    $addr = $net . $i;
    do_chk($addr);
    sleep(1); 
}

###############################################
## Subroutines 
##

## Check if a host is alive:
sub ping_host {
    my ($p, $status);
    $p = Net::Ping->new("icmp",$timeout,10);
    if ($p->ping($_[0])) {
	$status = 1;
    } 
    $p->close();
    return $status;
}

## Get the hostname for an address:
sub get_name {
    my ($h, $name);
    $h = gethost($_[0]);
    if ($h) {
	if ($h = gethostbyaddr($h->addr)) {
	    $name = $h->name;
	} else {
	    die "Unspecified error";
	}
    }
    return $name;
}

## Do the whole process for one host:
sub do_chk {
    my ($status, $name);
    $~ = "TABLE";
    $t_addr = $_[0];
    $t_name = get_name($_[0]) ? get_name($_[0]) : "---";
    $t_alive_p = ping_host($_[0]) ? "ALIVE" : "";
    write(STDOUT);
    return 0;
}

## Isolate the (class-C) network part of a dotted quad:
sub net_part {
    my (@octet);
    @octet = split(/\./,$_[0]);
    return "$octet[0].$octet[1].$octet[2].";
}

## Isolate the (class-C) host part of a dotted quad:
sub host_part {
    my (@octet);
    @octet = split(/\./,$_[0]);
    return $octet[3];
}

##
## fin
####################################################
