- Repository
- Munin (2.0)
- Last change
- 2020-03-15
- Graph Categories
- Family
- manual
- Capabilities
- Keywords
- Language
- Perl
- License
- GPL-2.0-only
port_
Name
port_ - Munin wildcard plugin to monitor network port usage.
Configuration
To monitor a port link port_<service> to this file. E.g.
ln -s /usr/share/munin/plugins/port_ /etc/munin/plugins/port_ssh
will monitor ssh connections. Services are those from /etc/services or a numeric port number.
Magic Markers
#%# family=manual
#%# capabilities=autoconf suggest
Bugs
The plugin doesnt count the tcp6 connections if tcp and tcp6 is used.
Author
Unknown
License
GPLv2
#!@@PERL@@
# -*- perl -*-
=head1 NAME
port_ - Munin wildcard plugin to monitor network port usage.
=head1 CONFIGURATION
To monitor a port link port_<service> to this file. E.g.
ln -s /usr/share/munin/plugins/port_ /etc/munin/plugins/port_ssh
will monitor ssh connections. Services are those from /etc/services or
a numeric port number.
=head1 MAGIC MARKERS
#%# family=manual
#%# capabilities=autoconf suggest
=head1 BUGS
The plugin doesnt count the tcp6 connections if tcp and tcp6 is used.
=head1 AUTHOR
Unknown
=head1 LICENSE
GPLv2
=cut
use Munin::Plugin;
use constant {
ST_ESTABLISHED => 1,
ST_LISTEN => 10,
};
sub cache_open
{
my ($fd, $file) = @_;
my $cache_dir = "$ENV{MUNIN_PLUGSTATE}";
my $cache = $file;
$cache =~ s:/:_:g;
$cache = "$cache_dir/$cache";
my $ttl = $ENV{'cache_ttl'};
$ttl = 60 unless (defined $ttl);
# The user can disable caching by setting cache_ttl to something
# other than a positive integer.
if ($ttl !~ /^\d+$/ || $ttl == 0)
{
return open($fd, $file);
}
if (-e $cache && -M _ < $ttl / 86400)
{
return open($fd, $cache);
}
unless (-d $cache_dir)
{
mkdir($cache_dir) || die "$cache_dir: mkdir: $!\n";
}
my $retval;
$retval = open(CACHE_INPUT, $file);
return $retval unless ($retval);
my $tmpfile = "$cache.$$";
open(CACHE_OUTPUT, ">$tmpfile") || die "$tmpfile: open: $!\n";
while (<CACHE_INPUT>)
{
print CACHE_OUTPUT;
}
close(CACHE_OUTPUT) || die "$tmpfile: close: $!\n";
close(CACHE_INPUT);
rename($tmpfile, $cache) || die "$cache: rename: $!\n";
# Okay, we have a fresh copy in our cache.
return open($fd, $cache);
}
if ($ARGV[0] and $ARGV[0] =~ /^\s*autoconf\s*$/i)
{
if (-r "/proc/net/tcp" or -r "/proc/net/tcp6")
{
print "yes\n";
exit 0;
}
else
{
print "no\n";
exit 0;
}
}
sub count_tcp_ports
{
my ($state, $ports) = @_;
cache_open("NETSTAT", "/proc/net/tcp") or exit 1;
# Skip header line, else hex($curstate) will complain
my $header = <NETSTAT>;
# 32/4 + 1 corresponds to the IP address in hex + ":"
my $local_port_offset = 32/4 + 1;
while (<NETSTAT>)
{
my ($linenr, $local, $remote, $curstate) = split;
next unless (hex($curstate) == $state);
++$ports->{hex(substr($local, $local_port_offset, 4))};
}
close NETSTAT;
}
sub count_tcp6_ports
{
my ($state, $ports) = @_;
cache_open("NETSTAT", "/proc/net/tcp6") or exit 1;
# Skip header line, else hex($curstate) will complain
my $header = <NETSTAT>;
# 128/4 + 1 corresponds to the IP address in hex + ":"
my $local_port_offset = 128/4 + 1;
while (<NETSTAT>)
{
my ($linenr, $local, $remote, $curstate) = split;
next unless (hex($curstate) == $state);
++$ports->{hex(substr($local, $local_port_offset, 4))};
}
close(NETSTAT);
}
if ($ARGV[0] and $ARGV[0] =~ /^\s*suggest\s*$/i)
{
if (-r "/proc/net/tcp" or -r "/proc/net/tcp6")
{
my %ports = ();
count_tcp_ports(ST_LISTEN, \%ports) if (-r "/proc/net/tcp");
count_tcp6_ports(ST_LISTEN, \%ports) if (-r "/proc/net/tcp6");
foreach my $port (keys %ports)
{
my $p = (getservbyport($port, "tcp"))[0];
print $p || $port, "\n";
}
exit 0;
}
exit 1;
}
my ($name, $port);
if ($0 =~ /port_(.+)*$/) {
$name = $port = $1;
if ($port =~ /\D/) {
$port = (getservbyname ($name, "tcp"))[2];
}
} else {
exit 2;
}
if ($ARGV[0] and $ARGV[0] =~ /^\s*config\s*$/i)
{
if (int($name)) {
print "graph_title TCP port $name connection count\n";
} else {
print "graph_title $name connection count\n";
}
print "graph_args --base 1000 -l 0\n";
print "graph_vlabel concurrent connections\n";
print "graph_category network\n";
print "count.label $name\n";
print_thresholds("count");
exit 0;
}
my %ports = ();
count_tcp_ports(ST_ESTABLISHED, \%ports) if (-r "/proc/net/tcp");
count_tcp6_ports(ST_ESTABLISHED, \%ports) if (-r "/proc/net/tcp6");
# If there aint any the right answer is 0, not blank or U.
$ports{$port} = 0 if (!exists $ports{$port}) or ($ports{$port} eq '');
print "count.value ", $ports{$port}, "\n";
# vim:syntax=perl