#!/usr/athena/bin/perl
# $Header: /afs/.net/tools/arch/common/RCS/hostcheck.pl,v 1.3 1999/02/24 07:40:15 foley Exp $
#$DEBUG = 1;
# To reduce the simon dependancy for ops, I wrote this
# as a test application for the SNMP module.  Next stop, "port"!
#
#   Joe Foley <foley@mit.edu>
#   2/23/1999
#   MIT Network Operations

use Getopt::Long;
use lib '/afs/.net.mit.edu/tools/lib/perl/Net-SNMP-1.10/lib';
use Net::SNMP();
use Socket qw(PF_INET SOCK_DGRAM inet_aton inet_ntoa sockaddr_in);

$vardefs = "/afs/net.mit.edu/tools/src/simon/vardefs";

# I'm not sure what the hell cluster is for
%ARG_DEFAULTS = (
	   'cluster' => "",
	   'class' => "stuff",
	   'community' => "public",
	   'variable' => "",
	   );

$usagemsg .= '$Id: hostcheck.pl,v 1.3 1999/02/24 07:40:15 foley Exp $ '."
hostcheck.pl [options] [<hostname>]
Options:
\t-cluster <cluster>\tTo access a particular cluster of machines
\t-class <class>    \tAccess a <class> of variable from vardefs
\t-community <com>  \tUse <community> when making request
\t-variable <var>   \tQuery a particular OID

Defaults:
";
foreach $default (sort keys %ARG_DEFAULTS) {
    $usagemsg .= "If no $default is given, \"$ARG_DEFAULTS{$default}\" is defaulted\n";
}
$usagemsg .= "
Comments:
This program mimics the most common uses of Tom Coppeto<tom\@mit.edu>'s
\"hostcheck\" script (an interface to \"simon\", his SNMP query agent)
using the Net-SNMP module from CPAN by David M. Town<town+\@pitt.edu>
Bother Joe Foley<foley\@mit.edu> with problems/comments.\n";

&GetOptions("cluster=s" => \$cluster, "class=s" => \$class,
	    "community=s" => \$community, "variable=s" => \$variable)
    || die $usagemsg;

$hostname  = shift || "127.0.0.1";
$cluster ||= $ARG_DEFAULTS{'cluster'};
$class ||= $ARG_DEFAULTS{'class'};
$community ||= $ARG_DEFAULTS{'community'};
$variable ||= $ARG_DEFAULTS{'variable'};

$port      = 161;


($session, $error) = Net::SNMP->session(
					Hostname  => $hostname,
					Community => $community,
                                      Port      => $port
					);

if (!defined($session)) {
    printf("ERROR: %s\n", $error);
    exit 1;
   }
#$sysUpTime = '1.3.6.1.2.1.1.3.0';
#$sysUpTime = '1.3.6.1.4.1.20.1.3.4.0';

#print "Host: $hostname, Cluster: $cluster, Class: $class\n";
#print "Community: $community\n----------------------------\n";
open(VARDEFS, "$vardefs") || die "Unable to open simon variable file $vardefs for reading: $!\n";
print "sending";
if($variable) {
    print "obj: $variable\n";
    do{
	($instance,$response)=&get_snmp_stuff($variable);
	print ".";
	$resp{$desc}{'response'}=$response;
# this must be snmptrap
	$resp{$desc}{'instance'}=$instance;
	$order[$i++]=$desc; #preserve order
    }
    while($inst!=0);    
    $desc = $variable;
#    print "[".join(':', values %$response)."]\n";
    print ".";
} else {
    while(<VARDEFS>) {
	s/#.*//g;    
	/^$/ and next;
	($queryfamily, $variable, $stuff, $desc) = split(/\|/);
	$queryfamily eq $class or next;
	$DEBUG && print "snmpobj: $snmpobj, stuff: $stuff, desc: $variable\n";
	do{
	    ($instance,$response)=&get_snmp_stuff($variable);
	    print ".";	    
	    $resp{$desc}{'response'}=$response;
# this must be snmptrap
	    $resp{$desc}{'instance'}=$instance;
	    $order[$i++]=$desc; #preserve order
	}
	while($inst!=0);
    }
}
$session->close;
print "query session complete.\n\n";
print "[$hostname ".join(".",unpack("C4",inet_aton($hostname)))."]\n";
foreach $desc (@order) {
    print "  $desc\t($resp{$desc}{'instance'})\t$resp{$desc}{'response'}\n";
}
print "\n";
exit 0;

sub get_snmp_stuff {
    local $variable = shift;
    $DEBUG and print "get_snmp_stuff($variable)...";
    local($retinst, $retval) = (0,"");
    # do we have a thing to snmpwalk?
    if($variable =~ /\*/) {
	chop($variable);
$DEBUG and print "{snmpwalk!}";
	if (!defined($response = $session->get_next_request($variable))) {
#	    printf("ERROR: %s\n", $session->error);
#	    $session->close;
#	    exit 1;
	}
	else {
	    foreach $branch (keys %$response) {
		# to emulate hostcheck, we only want the part up to originating OID
		if($branch =~ /^$variable\.(.*)/) {
		    $retinst = $1;		    
		    # yes I know this is broken, but just in case
		    $DEBUG and print "\n\tchecking $variable.$branch";
		    $retval .= $response->{$branch};
		}
		else {
		    next;
		}
	    }
	}
    }
    else {
	if (!defined($response = $session->get_request($variable))) {
	    $DEBUG and print "{single obj}"
## hostcheck dies invisibly on nonsupported queries
#	printf("ERROR: %s\n", $session->error);
#	$session->close;
#	exit 1;	
	}
	else {
	    $retval=$response->{$variable};
	}
    }
#    print "[".join(':', values %$response)."]\n";
    $DEBUG and print "($retinst,$retval)\n";
    return($retinst,$retval)
}
