#!/usr/bin/perl
#
# Wildcard-script to monitor network port usage. To monitor a
# port, link port_<service> to this file. E.g.
#
#    ln -s /usr/share/munin/node/plugins-auto/port_ /etc/munin/node.d/port_www
#
# ...will monitor www connections. Services are those listed in
# /etc/services.
#
# Parameters:
#
# 	config   (required)
# 	autoconf (optional - used by munin-config)
# 	suggest  (optional - used by munin-config)
#
# $Log$
# Revision 1.2  2004/05/20 13:57:12  jimmyo
# Set categories to some of the plugins.
#
# Revision 1.1  2004/01/02 18:50:01  jimmyo
# Renamed occurrances of lrrd -> munin
#
# Revision 1.1.1.1  2004/01/02 15:18:07  jimmyo
# Import of LRRD CVS tree after renaming to Munin
#
# Revision 1.4  2003/12/16 16:22:36  jimmyo
# Typo fix.
#
# Revision 1.3  2003/11/07 17:43:16  jimmyo
# Cleanups and log entries
#
#
#
# Magic markers (optional - used by munin-config and some installation
# scripts):
#%# family=manual
#%# capabilities=autoconf suggest


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 1;
    }
}

if ($ARGV[0] and $ARGV[0] =~ /^\s*suggest\s*$/i)
{
    if (-r "/proc/net/tcp" or -r "/proc/net/tcp6")
    {
	my %ports = ();
	if (-r "/proc/net/tcp")
	{
	    open (NETSTAT, "/proc/net/tcp") or exit 1;

	    while (<NETSTAT>)
	    {
		    chomp;
		    next unless (hex (substr($_,35,2)) == 10);
		    my $p = substr( $_,15,4);
		    if (defined $ports{hex($p)})
		    {
			$ports{hex($p)}++;
		    }
		    else
		    {
			$ports{hex($p)} = 1;
		    }
	    }
	    close NETSTAT;
	}

	if (-r "/proc/net/tcp6")
	{
		open (NETSTAT, "/proc/net/tcp6") or exit 1;

		while (<NETSTAT>)
		{
			chomp;
			next unless (hex (substr($_,83,2)) == 10);
			my $p = substr( $_,39,4);
			if (defined $ports{hex($p)})
			{
			    $ports{hex($p)}++;
			}
			else
			{
			    $ports{hex($p)} = 1;
			}
		}

		close NETSTAT;

	}

	foreach my $port (keys %ports)
	{
	    my $p = (getservbyport ($port, "tcp"))[0];
	    if ($p)
	    {
		print "$p\n";
	    }
	    else
	    {
		print "$port\n";
	    }
	}
	exit 0;
    }
    else
    {
	exit 1;
    }
}

$0 =~ /port_(.+)*$/;
unless ($name = $1)
{
	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";
	exit 0;
}

if ($name =~ /\D/)
{
  $port = (getservbyname ($name, "tcp"))[2];
}
else
{
  $port = $name;
}


$count = 0;

if (-r "/proc/net/tcp")
{
    open (NETSTAT, "/proc/net/tcp") or exit 1;

    while (<NETSTAT>)
    {
	    chomp;
	    next unless (hex (substr($_,35,2)) == 1);
	    my $p = substr( $_,15,4);
	    $count++ if hex($p) == $port;
    }

    close NETSTAT;
}

if (-r "/proc/net/tcp6")
{
        open (NETSTAT, "/proc/net/tcp6") or exit 1;

        while (<NETSTAT>)
        {
                chomp;
                next unless (hex (substr($_,83,2)) == 1);
                my $p = substr( $_,40,4);
                $count++ if hex($p) == $port;
        }

        close NETSTAT;
}

print "count.value $count\n";
# vim:syntax=perl
