sourcecode
ybiC
<code>#!/usr/bin/perl -w
# portck.pl
# pod at tail
use strict; # avoid d'oh! bugs
require 5; # for following modules
use IO::Socket; # support port connections
use Getopt::Long; # support commandline arguments, options
use Pod::Usage; # avoid duplicating Usage() in Pod
my $start = time;
my (
$opt_remote,
$opt_firstport,
$opt_lastport,
$opt_proto,
$opt_timeout,
$opt_help,
$opt_man,
);
GetOptions(
'remote=s' => \$opt_remote,
'firstport=i' => \$opt_firstport,
'lastport=i' => \$opt_lastport,
'proto=s' => \$opt_proto,
'timeout=i' => \$opt_timeout,
'help!' => \$opt_help,
'man!' => \$opt_man,
);
my $remote = defined $opt_remote ? $opt_remote : 'localhost';
my $firstport = defined $opt_firstport ? $opt_firstport : 1;
my $lastport = defined $opt_lastport ? $opt_lastport : 1024;
my $proto = defined $opt_proto ? $opt_proto : 'tcp';
my $timeout = defined $opt_timeout ? $opt_timeout : 1;
pod2usage(-verbose => 2) if (defined $opt_man);
pod2usage(-verbose => 1) if (defined $opt_help);
pod2usage(-verbose => 1) unless(
$remote =~ /localhost/ and
$remote =~ /(^\w+$)/ and
$firstport > 0 and
$lastport > 0 and
$firstport < 65536 and
$lastport < 65536 and
$lastport >= $firstport and
$timeout > 0
);
print "\nChecking $remote for $proto ports $firstport through $lastport\n";
for (my $port=$firstport; $port<$lastport+1; $port++){
my $connect = IO::Socket::INET->new(
PeerAddr => $remote,
PeerPort => $port,
Proto => $proto,
);
if ($connect) {
if ($proto eq 'udp') {
open (ERROR, ">/dev/null") or die $!;
STDERR->fdopen(\*ERROR, "w") or die $!;
$connect->send('Yo!') or next;
$SIG{ALRM} = \&timed_out;
eval {
alarm ($timeout);
$connect->recv($_,1) or next;
alarm (0);
print " connected to $remote at $proto port $port\n";
close $connect;
};
} else {
print " connected to $remote at $proto port $port\n";
close $connect;
}
}
}
my $done = time;
my $runSecs = int($done-$start);
print "\nRuntime ", $runSecs, " second";
print 's' if $runSecs != 1;
print "\n\n";
print <<EOF;
IO::Socket $IO::Socket::VERSION
Getopt::Long $Getopt::Long::VERSION
Pod::Usage $Pod::Usage::VERSION
Perl $]
OS $^O
EOF
;
sub timed_out {
die "How long can this go on?!";
}
=head1 NAME
portck.pl
=head1 DESCRIPTION
A TCP and UDP port sccaner written in Perl.
Requires no additional modules beyond those in the base Perl install.
=head1 SYNOPSIS
C<portck.pl> to run with default values for arguments
=head1 OPTIONS
--help
display Usage, Arguments, and Options
--man
display complete man page
=head1 ARGUMENTS
--remote
Name or IPaddr of remote host
default of 'localhost'
--firstport
Integer between 1 and 65535, indicating starting port number
default of 1
--lastport
Integer between 1 and 65535, indicating ending port number
default of 1024
--proto
tcp or udp
default of tcp
--timeout
Integer greater than 0, indicating seconds to wait for response
default of 1
=head1 EXAMPLES
portck.pl
check localhost for TCP ports 1 through 1024
portck.pl --remote tux --firstport 80
check named host for TCP ports 80 through 1024
portck.pl -t sparky -f 69 -l 69 -p udp
check named host for TFTP port
portck.pl -t 172.16.1.1 -l 65535
check numbered host for all TCP ports
portck.pl -t enterprise -f 13 -l 13 -p udp -w 10
check named host for daytime, with 10 second response timeout
portck.pl -t 192.168.1.1 -w 1
check numbered host with connection timeout of 1 second
=head1 BUGS
None that I know of.
=head1 UPDATE
2002-01-22 08:40 CST
Fix numerous tyops
Post to PerlMonks
More effective regex for $remote sanity-check
Pod::Usage
Discern betwixt (s)tring and (i)nteger for arguments and options
Require Perl 5
Eliminate TCP connection timeout, as appears to do nothing
Combine UDP response and TCP connection timeouts to one argument
Cleaner syntax for default values
Non-repetitive syntax for passel o' &Usage() calls
Intelligently print second or seconds runtime
&Usage()
Input sanity-checks
UDP timeout
No eval exit errs on UDP by STDERR redirect to /dev/null.
No false UDP positives by sending and checking response.
POD
2002-01-17
Initial working code.
=head1 TODO
More clean support for specifying ports
=head1 TESTED
IO::Socket 1.25, 1.26
Getopt::Long 2.2602, 2.25
Pod::Usage 1.14
Perl 5.00503, 5.006001
OS Debian 2.2r5, Win2k, Cygwin/Win2k
=head1 AUTHOR
ybiC
=head1 CREDITS
Props to Screamer for reminder of proper Getopt types for input,
jcwren+Russ for ternery to simplify provision for default values,
jeffa for pointing to $connect->recv for UDP,
c for inspiration of problem with tftp-detect-before-copy-config.
Oh yeah, and to some guy named vroom.
=head1 DISCLAIMER
This software was written to aid in configuring the author's computers
in a reasonably secure manner. Anyone using this software is encouraged
to do so in a responsible and constructive fashion. Remember kids to
always use your powers for good, not evil.
=cut
</code>
A localhost TCP+UDP port sccaner, intended to supplement <tt>netstat -vat</tt>, which doesn't seem to report listening UDP services. Requires no additional modules beyond those in the base Perl.
<p>
<b>portck.pl was written to aid in configuring the author's computers in a reasonably secure manner. Anyone using this software is encouraged to do so in a responsible and constructive fashion. Remember, kids, always use your powers for *good*, not evil.</b>
<p>
From a perlish perspective, this ditty has been an introduction to [cpan://IO::Socket], as well as finally getting around to applying the most excellent [cpan://Pod::Usage] in conjunction with [cpan://Getopt::Long].
<p>
As always, comments and critique are respectfully requested (and appreciated).
<br> cheers,
<br> [ybiC|Don]
<p>
<sub><b>Update: </b> added a bit o'clarification to description<br />
Just found <tt>netstat -vatu</tt> for localhost TCP *and* UDP services. D'oh!</sub>
</p>
Networking Code
[ybiC]