#!/usr/bin/perl

# rpscan - Reverse Port Scanner...  Attempts to bind to all possible ports on
#          the local system, in an attempt to find the ones in use...  Why?
#          Just in case you can't rely on "netstat" reporting them all (eg:
#          due to an installed rootkit)...
#
# Consider this public domain...  Do with it as you please...
#
# V1.00 - Baseline...  Inspired by an idea from comments by "fergal" at
#         lwn.net...
#	[Rob Seace <ras@magrathea.com>, 18-Mar-2004]
# V1.01 - Changed the bind() test to be a bit more correct, and only indicate
#         the port is in use if the errno is EADDRINUSE...  (Based on further
#         suggestions from fergal...)
#	[Rob Seace <ras@magrathea.com>, 18-Mar-2004]
#

use Socket;
use POSIX qw( :errno_h );

my $protoname = uc shift || 'TCP';
my $socktype = SOCK_STREAM;
my $startport = 1024;
my $stopport = 65535;
my $uid = $<;

if ($protoname eq 'UDP') {
	$socktype = SOCK_DGRAM;
} elsif ($protoname eq 'TCP') {
	$socktype = SOCK_STREAM;
} else {
	print "Bogus protocol: $protoname\n\nUsage: rpscan [{TCP,UDP}]\n";
	exit -1;
}

if ($uid eq 0) {
	$startport = 1;
} else {
	print "NOTE: You must run as root to scan for ports below 1024!\n\n";
}

print "Scanning $protoname ports ($startport - $stopport)...\n";
foreach $port ($startport .. $stopport) {
	socket (fd, AF_INET, $socktype, 0) || die "socket($socktype): $!";
	if (not bind (fd, sockaddr_in($port,INADDR_ANY))) {
		if ($! == EADDRINUSE) {
			print "$port is in use!\n";
		} else {
			die "bind($port): $!";
		}
	}
	close (fd);
}
print "Done.\n";
exit 0;