#!/usr/bin/perl -w

# pscan: perl scan, lightweight port scanner.  Simply tries to
# open a socket to each of the ports in the range specified on
# the command line.  You do not need to be root to execute this
# script.
#
# TODO:  
#	- use alarms to avoid hanging on closed ports

use Socket;
use Getopt::Long;

usage_and_exit(1) unless (GetOptions (
        'help'          => \$help,
        'ipaddress=s'        => \$ipaddress,
        'startport=s'        => \$start_port,
        'endport=s'        => \$end_port
));
usage_and_exit(0) if ($help);

if ($ipaddress && $start_port && $end_port) {
	my @closed_ports;
	my @open_ports;

	my $ipaddr = inet_aton $ipaddress or die "Could not get ip address for host: $ipaddress\n";
	my $protocol = getprotobyname 'tcp';
	my $timeout = 5;
	print "Scanning: $ipaddress\n";
	my $i = $start_port;
	while ($i <= $end_port) { 
		socket SCAN, PF_INET, SOCK_STREAM, $protocol or die "Could not open socket: $!\n";
		my $test = connect SCAN, sockaddr_in($i, $ipaddr);
		if (! $test) {
			push @closed_ports, $i;
		} else {
			push @open_ports, $i;
		}
		close SCAN;
		$i++;
	}
	print "Port:	Status:\n";
	foreach my $o_port (@open_ports) {
		print "$o_port	open\n";
	}
	if ($#closed_ports == ($end_port - $start_port)) {
		print "All $#closed_ports ports are closed\n";
	} else {
		print "The remaining $#closed_ports ports are closed\n" if ($#closed_ports > 0); 
	}
	exit 0;
} else {
	usage_and_exit(1);
}
 
sub usage_and_exit() {
        my $exitcode = shift;
        print <<_HELP_;

Usage: bscan [-i <ip address>] [-s <start port>] [-e <end port>] [-h]

	-i		- ip address
	-s		- starting port
	-e		- ending port	
        -h              - prints this help message.

_HELP_
        exit $exitcode;
}

