#!/usr/local/bin/perl 
##
## THIS IS A SAMPLE PERL MONITOR TAKEN FROM "snmp-modemmon"
#
#        SNMPmodemmon - perl monitor for modem line's usage on Terminal Servers
#
#  -Vikas Aggarwal, vikas@navya.com
#
#
#####################
# To Install:
#
#	Compile the CMU-SNMP programs and install snmpwalk and the
#	mib.txt file in desired locations. Then set the variables
#	as described in the 'Customize' section.
#
# Modemmon  reads a list of cisco terminal servers to monitor (from
# a config file) and thresholds. It then logs into the cisco's and
# counts the number of lines in use. When the used lines exceeds the
# thresholds, the lines are displayed in NOCOL data format.
#
# Files used:
#   snmpwalk -		From CMU-SNMP distribution
#   mib.txt  -		MIB file in ASN syntax with merged Cisco MIB.
#
# Nocol event elements used:
#   sender                     "modemmon"
#   severity                   as read from the config file
#   site
#    name                      the cisco name
#    addr                      cisco IP address
#   var                       
#    name                      "ModemLines"
#    value                     1 means at Info level
#    threshold                 as read from the config file
#    units                     always "Usage"
#
## 
##
#
############################
## Variables customization #  overrides values in the nocollib.pl library
############################
$SNMP = "../cmu-snmp" ;			# To find binary and MIBFILW
$prog =  "$SNMP/bin/snmpwalk" ;		# location of 'snmpwalk'
$mibfile = "$SNMP/mib.txt" ;	# Location of MIB file

# Cisco MIB ASN
# cisco.local...tsLineActive = 9.2.9.2.1.1
$mibcisco  = ".iso.org.dod.internet.private.enterprises.cisco.local" ;
$miblineactive = $mibcisco.".lts.ltsLineTable.ltsLineEntry.tsLineActive" ;
$miblinetype = $mibcisco.".lts.ltsLineTable.ltsLineEntry.tsLineType" ;

$community=  "public";

$varname="ModemLines";
$varunits="Usage" ;			# the var.units field in EVENT struct
$sleepint=60*5;       			# Seconds to sleep between tries.
############################
$debug = 0;				# set to 1 for debugging output
$libdebug = 0;				# set to 1 for debugging output
$prognm = $0;				# save program name

require  "nocollib.pl" ;

-x $prog || die("Could not find executable $prog, exiting");
-f $mibfile || die("Could not find MIB file $rprog, exiting");
$ENV{"MIBFILE"}= $mibfile ;

##
# Read the config file. Use '\t' as a separator for 'item'
sub readconf {
    local ($nets, $interface, $zone) ;

    open(CONFIG,"<$cfile")||die("Couldn't find $cfile, exiting");
    while(<CONFIG>)
    {
	chop;
	if(/^\s*#/) {next;}   # skip comments
	if(/^\s*$/) {next;}   # skip blank lines
	if (/\s*(\S+)\s+(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s*$/)
	{
	    $item="$1\t$2" ;	 # the name and address
	    $wlevel{$item} = $3; # Warning level
	    $elevel{$item} = $4; # Error level
	    $clevel{$item} = $5; # Critical level
	    push(@items,$item);
	}
	else {print "Ignoring illegal line: $_\n";}

    }	# end while(CONFIG)

    close(CONFIG);
    if(0>$#items){die("Nothing to monitor in $cfile, exiting")};
    if ($debug) {
	print "Items are:\n"; foreach (@items) { print "\t$_\n" } ;
    }
}				# end: readconf


# 
## Check state of each router
##
#
# Walks the TServer ltsLineActive/ltsLineType  mib trees (cisco specific) 
# and collects TERMINAL type lines that are ACTIVE.
# Prints number of active lines and total number of TTY lines.
# Prints '-1' on error.
#
# CAVEATS:
#   - Walking entire mib tree over UDP can be iffy. This is tested by seeing
#     if any responses are missing in the TYPE list and the ACTIVE list.
#
###	
#
sub dotest {
    local ($host, $router) = @_ ;
    local ($acount, $tcount, $isok) = (0, 0, 0);
    local ($walkactive, $walktype, @active, @type) ;

    if ($debug) { print "Checking $router\n"; }

    -x $prog || die("Could not find executable $prog, exiting");

    $walkactive = "$prog $router $community $miblineactive";
    $walktype =   "$prog $router $community $miblinetype";
    if ($debug) { 
#	print "Active cmd= $walkactive\nType cmd= $walktype\n\n" ;
    }
#
# Output of Check-active SNMP command is:
#    Name: .iso.org.dod........lts.ltsLineTable.lts.LineEntry.tsLineActive.0
#    INTEGER: 1

    open (ACTIVE, "$walkactive |") || die "Can't check active lines.";
    while(<ACTIVE>){
	chop;
	if (/^\s*INTEGER:\s*(\d+)\s*$/)
	{
	    push(@active,$1);
#	    if ($debug) { print "$1, "; }
	}
    }
    close(ACTIVE);
#    if ($debug) { print "\n"; }

## Output of Check-Type SNMP command is:
#    Name: .iso.org.dod........lts.ltsLineTable.lts.LineEntry.tsLineType.0
#    INTEGER: console(2) OR terminal(3) OR virtual-terminal(5)

    open (TYPE, "$walktype |") || die "Can't check line types.";
    while(<TYPE>){
	chop;
	if (/^\s*INTEGER:\s*(\S(.*\S)?)\s*$/)
	{
	    push(@type,$1);
#	    if ($debug == 2) { print "$1, "; }
	}
    }
    close(TYPE);
#    if ($debug) { print "\n"; }

    if ($debug) { 
	print "(debug): active list= $#active, type list= $#type\n" ;
    }

    if ($#active != $#type) 
    { 
	print "WARNING: active list len= $#active != type list len= $#type\n" ;
	return (-1, 0);
    }

    foreach $i (0..$#active)
    {
	$isterm = ($type[$i] =~ /terminal\(3\)/); # Search for TTY terminals
	if($isterm) {
	    $tcount++;
	    $acount+=$active[$i]; # Since '$active' is either 0 or 1 anyway
	    if ($debug) { 
		print "(debug): Index=$i Type=$type[$i] Active=$active[$i]\n";
	    }
	}
    }

    if ($debug) {print "(debug)Active/Total terminals: $acount/$tcount\n"; }

    if ($acount < 0) { return (-1, 0); } # negative status to be ignored

    ($isok, $varthres{$item}, $maxseverity) = 
	&calc_status ($acount, $wlevel{$item}, $elevel{item}, $clevel{$item});

    if ($debug) {print "(debug): Status $isok, MaxSev= $maxseverity\n";}
    return ($isok, $acount);

}	# end &dotest()


###
### main
###

## Since our dotest() and readconf() is pretty standard, we can call
## the nocollib.pl routine nocol_main() to do all the work for us...

&nocol_main;

#

