Andrew Tomaka
e0e789b58f
By default, pinger will not lookup hostnames for IPs that are unreachable. This prevents extended times if dead IPs do not have host entries. However, there are also cases where DNS resolution is important even when the IP is unreachable. pinger now supports this using the -f flag.
137 lines
3.4 KiB
Perl
Executable file
137 lines
3.4 KiB
Perl
Executable file
#!/usr/bin/env perl
|
|
use strict;
|
|
use Getopt::Std;
|
|
use Net::Ping;
|
|
use POSIX;
|
|
use Socket;
|
|
use Switch;
|
|
use Time::HiRes qw/time/;
|
|
|
|
# force print before buffer is full
|
|
$| = 1;
|
|
|
|
# imcp requires root access
|
|
die("pinger must be run as root\n") if($> != 0);
|
|
|
|
my $alive = 1;
|
|
my(%switches, $time, $name, $force, $startTime, $finishTime);
|
|
|
|
# handle command line options
|
|
my $status = getopts('dfrnth', \%switches);
|
|
help() if(!$status || $switches{'h'});
|
|
for (keys %switches) {
|
|
switch($_) {
|
|
case 'd' { $alive = 0; }
|
|
case 'f' { $force = 1; }
|
|
case 'r' { $alive = 1; }
|
|
case 'n' { $name = 1; }
|
|
case 't' { $time = 1; }
|
|
else {}
|
|
}
|
|
}
|
|
|
|
|
|
die("Usage: pinger START_IP [END_IP]\n")if(scalar(@ARGV) < 1 || scalar(@ARGV) > 2);
|
|
|
|
$startTime = time if($time);
|
|
my $p = Net::Ping->new('icmp');
|
|
my @ips;
|
|
|
|
# must be IP addresses
|
|
if($ARGV[0] !~ /((?:\d{1,3}\.){3}\d{1,3})/ || (defined($ARGV[1]) && $ARGV[1] !~ /((?:\d{1,3}\.){3}\d{1,3})/)) {
|
|
die("Both arguments must be IP addresses if two are specified.\n");
|
|
}
|
|
|
|
my @ip1 = split(/\./, $ARGV[0]);
|
|
# Set the second IP address to the first if no second argument
|
|
my @ip2 = (scalar(@ARGV) == 2) ? split(/\./, $ARGV[1]) : @ip1;
|
|
|
|
# and only the final octet should differ
|
|
if($ip1[0] != $ip2[0] || $ip1[1] != $ip2[1] || $ip1[2] != $ip2[2]) {
|
|
die("The first three octets of the IP addresses must match.\n")
|
|
}
|
|
|
|
# reverse IPs if 1 is larger than 2
|
|
if($ip1[3] > $ip2[3]) {
|
|
my $temp = $ip2[3];
|
|
$ip2[3] = $ip1[3];
|
|
$ip1[3] = $temp;
|
|
}
|
|
|
|
my $baseIp = $ip1[0] . '.' . $ip1[1] . '.' . $ip1[2];
|
|
my $start = $ip1[3];
|
|
my $end = $ip2[3];
|
|
my $count = $ip2[3] - $ip1[3] + 1;
|
|
|
|
for(my $i = $start, my $k = 1; $i <= $end; $i++, $k++) {
|
|
progressBar($k, $count);
|
|
|
|
my $ip = $baseIp . '.' . $i;
|
|
|
|
my $reachable = $p->ping($ip, 1);
|
|
if($reachable == $alive) {
|
|
if($name && ($reachable || $force)) {
|
|
my $hostaddr = gethostbyaddr(inet_aton($ip), AF_INET);
|
|
$ip = $hostaddr if($hostaddr ne "");
|
|
}
|
|
|
|
push(@ips, $ip);
|
|
}
|
|
}
|
|
$p->close();
|
|
$finishTime = time if($time);
|
|
|
|
print "\n\n";
|
|
($alive) ? print "Reachable:\n" : print "Dead:\n";
|
|
print join(", ", @ips);
|
|
print "\n\n";
|
|
|
|
if($time) {
|
|
my $completed = $finishTime - $startTime;
|
|
printf("Completed in %.2f seconds.\n", $completed);
|
|
}
|
|
|
|
# details from http://stackoverflow.com/questions/1782107/how-do-i-retrieve-the-terminal-width-in-perl
|
|
sub findTerminalWidth {
|
|
my($winsize, $row, $col, $xpixel, $ypixel);
|
|
my $available = 1;
|
|
require 'sys/ioctl.ph';
|
|
$available = 0 unless defined &TIOCGWINSZ;
|
|
open(TTY, "+</dev/tty") or $available = 0;
|
|
$available = 0 unless (ioctl(TTY, &TIOCGWINSZ, $winsize = ''));
|
|
if($available == 1) {
|
|
($row, $col, $xpixel, $ypixel) = unpack('S4', $winsize);
|
|
} else {
|
|
return -1;
|
|
}
|
|
close(TTY);
|
|
|
|
return $col;
|
|
}
|
|
|
|
sub progressBar {
|
|
my($current, $total) = @_;
|
|
my $width = findTerminalWidth();
|
|
|
|
my $barWidth = $width - 11;
|
|
my $percent = ($current / $total) * 100;
|
|
my $barPercent = int($percent / 100 * $barWidth);
|
|
printf(" [%3d\%",$percent);
|
|
if($width > 0) {
|
|
print "] [";
|
|
for(my $i = 1; $i < $barWidth; $i++) {
|
|
($i <= $barPercent) ? print '=' : print ' ';
|
|
}
|
|
}
|
|
print "]\r";
|
|
}
|
|
|
|
sub help {
|
|
print "usage:\t pinger [-d] start [finish]\n\n";
|
|
print "\t-d\t\tList dead addresses\n";
|
|
print "\t-f\t\tForce hostname lookup even if unreachable\n";
|
|
print "\t-n\t\tReturn list as hostnames when possible\n";
|
|
print "\t-r\t\tList reachable addresses (default)\n";
|
|
print "\t-t\t\tTime ping execution\n";
|
|
exit(1);
|
|
}
|