Allow the user to specify port ranges against which to match inet sockets.

Suggested by:	roam
This commit is contained in:
Dag-Erling Smørgrav 2001-08-07 19:59:52 +00:00
parent 3fa96e6678
commit 03f28475f8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=81259
2 changed files with 76 additions and 3 deletions

View File

@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd April 13, 1999
.Dd August 7, 2001
.Dt SOCKSTAT 1
.Os
.Sh NAME
@ -36,6 +36,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl 46clu
.Op Fl p Ar ports
.Sh DESCRIPTION
The
.Nm
@ -51,6 +52,13 @@ Show AF_INET6 (IPv6) sockets.
Show connected sockets.
.It Fl l
Show listening sockets.
.It Fl p Ar ports
Only show Internet sockets if either the local or foreign port number
is on the specified list.
The
.Ar ports
argument is a comma-separated list of port numbers and ranges
specified as first and last port separated by a dash.
.It Fl u
Show AF_LOCAL (Unix) sockets.
.El

View File

@ -39,6 +39,67 @@ my $unknown = [ "?", "?", "?", "?", "?", "?", "?", "?", "?" ];
my $inet_fmt = "%-8.8s %-8.8s %5.5s %4.4s %-6.6s %-21.21s %-21.21s\n";
my $unix_fmt = "%-8.8s %-8.8s %5.5s %4.4s %-6.6s %-43.43s\n";
my @ranges;
#
# Parse a port range specification
#
sub parse_port_ranges($) {
my $spec = shift; # Range spec
my $range; # Range
my ($low, $high); # Low/high ends of range
foreach $range (split(/\s*,\s*/, $spec)) {
if ($range =~ m/^(\d+)-(\d+)$/) {
($low, $high) = ($1, $2);
} elsif ($range =~ m/^-(\d+)$/) {
($low, $high) = (1, $1);
} elsif ($range =~ m/^(\d+)-$/) {
($low, $high) = ($1, 65535);
} elsif ($range =~ m/^(\d+)$/) {
$low = $high = $1;
} else {
die("invalid range specification: $range\n");
}
if ($low < 0 || $low > 65535 || $high < 0 || $high > 65535) {
die("valid ports numbers are 1-65535 inclusive\n");
}
if ($low > $high) {
$low ^= $high;
$high ^= $low;
$low ^= $high;
}
push(@ranges, [ $low, $high ]);
}
}
#
# Check if a port is in an allowed range
#
sub check_range($) {
my $addr = shift; # Address to check
my $port; # Port number
my $range; # Range
if (@ranges == 0) {
return 1;
}
if ($addr !~ m/\.(\d+)$/) {
return undef;
}
$port = $1;
foreach $range (@ranges) {
if ($port >= $range->[0] && $port <= $range->[1]) {
return 1;
}
}
return undef;
}
#
# Gather information about sockets
#
@ -108,6 +169,7 @@ sub print_inet($$$) {
foreach $fsd (@{$fstat{$af}}) {
next unless defined($fsd->[7]);
$nsd = $netstat{$fsd->[7]} || $unknown;
next unless (check_range($nsd->[4]) || check_range($nsd->[5]));
next if (!$conn && $nsd->[5] ne '*.*');
next if (!$listen && $nsd->[5] eq '*.*');
printf($inet_fmt, $fsd->[0], $fsd->[1], $fsd->[2],
@ -149,14 +211,14 @@ sub print_unix($$) {
# Print usage message and exit
#
sub usage() {
print(STDERR "Usage: sockstat [-46clu]\n");
print(STDERR "Usage: sockstat [-46clu] [-p ports]\n");
exit(1);
}
MAIN:{
my %opts; # Command-line options
getopts("46clu", \%opts)
getopts("46clp:u", \%opts)
or usage();
gather();
@ -167,6 +229,9 @@ MAIN:{
if (!$opts{'c'} && !$opts{'l'}) {
$opts{'c'} = $opts{'l'} = 1;
}
if ($opts{'p'}) {
parse_port_ranges($opts{'p'});
}
if ($opts{'4'}) {
print_inet("internet", $opts{'c'}, $opts{'l'});
}