#!/usr/bin/perl -w

# $Id: jail-snmp 21 2004-02-11 03:06:06Z kirk $

use strict;
use Jail;

open STDERR, '>/dev/null' or die "Couldn't redirect STDERR: $_";

$| = 1;

my $max;
my @id;
my @jail;

# open LOGFILE, '>>/tmp/snmplog' or die "Unable to write to the log file: $!";

MAINLOOP:
while (1)
{
    # Wait for a knock then answer it.
    while ($_ = <>)
    {
	# print LOGFILE $_;
	if ($_ eq "PING\n")
	{
	    print "PONG\n";
	    last;
	}
    }

    # Get the command, either 'get' or 'getnext'.
    $_ = <>;
    exit unless defined $_;
    chomp;
    my $command = $_;

    # Get the requested OID.
    $_ = <>;
    chomp;
    my $oid = $_;

    $_ = $oid;
    s/^\.//;

    @id = (split /\./);
    $max = (scalar @id) - 1;

    @jail = Jail::getJailList();
    my $retval;

    # I love get requests.  Seriously.  I love them.
    if ($command eq 'get')
    {
	$retval = topLevel(8);
	if (defined $$retval{'error'})
	{
	    print "NONE\n";
	}
	else
	{
	    print <<__EORESPONSE__;
$oid
$$retval{'type'}
$$retval{'value'}
__EORESPONSE__
	}
	next MAINLOOP;
    }

    # I hate getnext requests.  Really.  I hate them.
    my $count = 0;

    $retval = topLevel(8);
    unless (defined $$retval{'error'})
    {
	$id[-1]++;
    }

    while (1 and ++$count < 20)
    {
	# $id[-1]++;
	$retval = topLevel(8);

	if (defined ($$retval{'error'}))
	{
	    if ($$retval{'error'} eq 'short')
	    {
		push @id, 1;
		$max++;
	    }
	    elsif ($$retval{'error'} eq 'long')
	    {
		pop @id;
		$max--;
	    }
	    elsif ($$retval{'error'} eq 'max')
	    {
		my $levels = $$retval{'levels'} || 1;
		for (my $i = 0; $i < $levels; $i++)
		{
		    pop @id;
		    $max--;
		}
		$id[-1]++;
		if (scalar @id < 8)
		{
		    print "NONE\n";
		    next MAINLOOP;
		}
	    }
	    elsif ($$retval{'error'} eq 'quit')
	    {
		print "NONE\n";
		next MAINLOOP;
	    }
	}
	else
	{
	    $oid = '.' . (join '.', @id);
	    print <<__EORESPONSE__;
$oid
$$retval{'type'}
$$retval{'value'}
__EORESPONSE__
	    next MAINLOOP;
	}
    }
}


sub topLevel
  {
    my $level = shift;

    return {'error'=>'short'} if $level > $max;

    if ($id[$level] == 1)
      {
	return general($level + 1);
      }

    if ($id[$level] == 2)
      {
	return jailTable($level + 1);
      }

    return {'error'=>'quit'};
}

sub general
  {
    my $level = shift;
    my $key = $id[$level];

    return {'error'=>'short'} if $level > $max;

    # Number of jails
    if ($key == 1)
      {
	return {'type' => 'integer', 'value' => scalar @jail};
      }

    return {'error'=>'max'};
  }

sub jailTable
  {
    my $level = shift;

    return {'error'=>'short'} if ($level + 1) > $max;
    return {'error'=>'long'} if ($level + 1) < $max;

    my $key = $id[$level];
    my $index = $id[$level + 1];

    # Jail too high?
    return {'error'=>'max'} if $index > scalar @jail;

    my $servername = $jail[$index - 1];

    # Index
    if ($key == 1)
      {
	return {'type'=>'integer', 'value'=>$index};
      }
    # Servername
    elsif ($key == 2)
      {
	return {'type'=>'string', 'value'=>$servername};
      }
    # Hostname
    elsif ($key == 3)
      {
	my $temp = Jail::getJailInfo($servername);
	return {'type'=>'string','value'=>$$temp{'hostname'}};
      }
    # IP address
    elsif ($key == 4)
      {
	my $temp = Jail::getJailInfo($servername);
	return {'type'=>'ipaddress','value'=>$$temp{'ip'}};
      }
    # Processes
    elsif ($key == 5)
      {
	my %temp = Jail::getProcList($servername);
	return {'type'=>'string','value'=>scalar (keys %temp) . ".0"};
      }

    # Back out at least two levels to get out of this table
    return {'error'=>'max', 'levels'=>2};
  }
