Snmpd

From RARFORGE
Jump to: navigation, search

Ubuntu/Debian

sudo apt-get install snmpd snmp libsnmp15 libsnmp-perl libsnmp-info-perl libsnmp-base libnet-snmp-perl snmp-mibs-downloader libparse-debian-packages-perl
/etc/snmp/snmpd.conf
 agentAddress  udp:161
 rocommunity <secret>
 rouser   authOnlyUser
 sysLocation    ChangeME - Sitting on the Dock of the Bay
 sysContact     You <me@example.org>
 
 sysServices    72
 proc  mountd
 proc  ntalkd    4
 proc  sendmail 10 1
 disk       /     10000
 disk       /var  5%
 includeAllDisks  10%
 load   12 10 5
 trapsink     localhost public
 iquerySecName   internalUser       
 rouser          internalUser
 defaultMonitors          yes
 linkUpDownNotifications  yes
 extend    test1   /bin/echo  Hello, world!
 extend-sh test2   echo Hello, world! ; echo Hi there ; exit 35
 ## this will allow you list the sw installed. Script required below
 perl do   "/etc/snmp/hrswinstalled.pl";
 master          agentx
  • list software installed script required
/etc/snmp/hrswinstalled.pl
#!/usr/bin/perl
 
#This is a rather quick (?) and dirty (!) script to implement the hrSWInstalled
#MIB on Debian and other dpkg based Linux distributions.
#
#If you have improvements, please send to rmk@bistromath.org
 
 
#Configuration
 
#maximum allowed cache age (in seconds)
#the agent will check the mtime on $statusfile if it hasn't checked in this long
$maxCacheAge = 10;
 
#location of dpkg files
my $statusfile = "/var/lib/dpkg/status";
my $infodir    = "/var/lib/dpkg/info";
 
# 0 - quiet, 1 - basic debugging, 2 - trace debugging
$debug = 0;
 
my $regat                       = '1.3.6.1.2.1.25.6';
my $hrSWInstalledLastChange     = $regat . ".1";
my $hrSWInstalledLastUpdateTime = $regat . ".2";
my $hrSWInstalledEntry          = $regat . ".3.1";
my $hrSWInstalledIndex          = $hrSWInstalledEntry . ".1";
my $hrSWInstalledName           = $hrSWInstalledEntry . ".2";
my $hrSWInstalledID             = $hrSWInstalledEntry . ".3";
my $hrSWInstalledType           = $hrSWInstalledEntry . ".4";
my $hrSWInstalledDate           = $hrSWInstalledEntry . ".5";
 
use Net::SNMP qw(oid_lex_sort);
use YAML;
use IO::File;
use Parse::Debian::Packages;
use Data::Dumper;
use NetSNMP::OID   (':all');
use NetSNMP::agent (':all');
use NetSNMP::ASN   (':all');
use SNMP;
 
my $inittime = time();
my $lastCacheCheck;
my $cacheAge = 0;
my %oidtable;
my @oidkeys;
my %nextOIDMap;
 
BEGIN {
   print STDERR "loading Debian hrSWInstalled MIB extension \n";
}
 
populateCaches();
 
# if we're not embedded, this will get auto-set below to 1
$subagent = 0;
 
# where we are going to hook onto
my $regoid = new NetSNMP::OID($regat);
print STDERR "registering at ", $regoid, "\n" if ($debug);
 
# If we're not running embedded within the agent, then try to start
# our own subagent instead.
if ( !$agent ) {
   $agent = new NetSNMP::agent(
       'Name'   => 'hrswinstalled',
       'AgentX' => 1
   );    # make us a subagent
   $subagent = 1;
   print STDERR "started us as a subagent ($agent)\n";
}
 
# we register ourselves with the master agent we're embedded in.  The
# global $agent variable is how we do this:
$agent->register( 'myname', $regoid, \&hrSWInstalledHandler );
 
if ($subagent) {
 
   # We need to perform a loop here waiting for snmp requests.  We
   # aren't doing anything else here, but we could.
   $SIG{'INT'}  = \&shutDown;
   $SIG{'QUIT'} = \&shutDown;
   $running     = 1;
   while ($running) {
       $agent->agent_check_and_process(1);    # 1 = block
       print STDERR "main loop\n" if ( $debug > 2 );
   }
   $agent->shutdown();
}
 
#the actual SNMP handler
sub hrSWInstalledHandler {
   my ( $handler, $registration_info, $request_info, $requests ) = @_;
   my $request;
 
   #check package cache time
   populateCaches() if statusCacheUpdated($statusfile);
 
   print STDERR "processing a request of type "
     . $request_info->getMode() . "\n"
     if $debug > 1;
 
   for ( $request = $requests ; $request ; $request = $request->next() ) {
       my $oid = $request->getOID();
       print STDERR "  processing request of $oid\n" if $debug > 1;
 
       if ( $request_info->getMode() == MODE_GET ) {
           my $numericOid = SNMP::translateObj($oid);
           $numericOid =~ s/^\.//;
           $request->setOID($numericOid);
           $request->setValue( $oidtable{$numericOid}{type},
               $oidtable{$numericOid}{val} );
       }
       elsif ( $request_info->getMode() == MODE_GETNEXT ) {
           print STDERR "requested oid $oid\n" if $debug > 1;
           for my $oidentry (
               $nextOIDMap{$oid} ? ( $nextOIDMap{$oid}, @oidkeys ) : @oidkeys )
           {
               if ( $oid < $oidtable{$oidentry}{oid} ) {
                   print STDERR "returned $oidentry" if $debug > 1;
                   $request->setOID($oidentry);
                   $request->setValue( $oidtable{$oidentry}{type},
                       $oidtable{$oidentry}{val} );
                   last;
               }
           }
 
       }
   }
 
   print STDERR "  finished processing\n" if $debug > 1;
}
 
#optimised oid map
sub nextOIDMap {
   my ( $oidtable, $oidkeys ) = @_;
 
   my %nextmap;
   my %oididx;
   my $idx = 0;
 
   print STDERR "Generating OID cache...\n" if $debug;
 
   #generate hash mapping OIDs in @{$oidkeys} array to the index of that key
   #within the array, for performance reasons
   for my $oidkey ( @{$oidkeys} ) {
       $oididx{$oidkey} = $idx;
   }
 
   for my $oid ( keys %{$oidtable} ) {
       my $index = $oididx{$oid};
       $nextmap{ $oidtable{$oid}{oid} } = $oidkeys->[ $index + 1 ];
   }
   print STDERR "\t...done.\n" if $debug;
 
   return %nextmap;
}
 
#check if package status has changed
sub statusCacheUpdated {
 
   my ($statusfile) = @_;
 
   #allow for max cache age
   return 0 if time() <= $lastCacheCheck + $maxCacheAge;
   $lastCacheCheck = time();
   print STDERR "dpkg cache expired\n"
     if $debug && ( stat($statusfile) )[9] > $cacheAge;
   return ( stat($statusfile) )[9] > $cacheAge ? 1 : 0;
 
}
 
#enumerate package status
sub enumPkgs {
 
   my ( $statusfile, $infodir ) = @_;
   my $index = 1;
   my %packages;
   my %oidtable;
 
   print STDERR "Enumerating installed packages...\n" if $debug;
 
   #remember our cache age
   $cacheAge = time();
 
   my $fh = IO::File->new($statusfile);
 
   my $parser = Parse::Debian::Packages->new($fh);
   while ( my %package = $parser->next ) {
       next unless $package{Status} =~ /(?<!not-)installed/;
       $packages{ $package{Package} } = \%package;
   }
 
   close $fh;
 
   for my $name ( sort keys %packages ) {
 
       my $oid;
 
       #hrSWInstalledIndex
       $oid = $hrSWInstalledIndex . "." . $index;
       $oidtable{$oid}{oid} =
         new NetSNMP::OID( $hrSWInstalledIndex . "." . "$index" );
       $oidtable{$oid}{type} = ASN_INTEGER;
 
       $oidtable{$oid}{val} = $index;
 
       #hrSWInstalledName
       $oid = $hrSWInstalledName . "." . $index;
       $oidtable{$oid}{oid} =
         new NetSNMP::OID( $hrSWInstalledName . "." . "$index" );
       $oidtable{$oid}{type} = ASN_OCTET_STR;
 
       $oidtable{$oid}{val} =
         "$name $packages{$name}{Version}/$packages{$name}{Architecture} ("
         . ( $packages{$name}{Description} || "No description" ) . ")";
 
       #hrSWInstalledDate
       $oid = $hrSWInstalledDate . "." . $index;
       $oidtable{$oid}{oid} =
         new NetSNMP::OID( $hrSWInstalledDate . "." . "$index" );
       $oidtable{$oid}{type} = ASN_OCTET_STR;
 
       my $mtime = ( stat( "$infodir" . "/" . $name . ".list" ) )[9];
       $oidtable{$oid}{val} = snmpDateStamp($mtime);
 
       #hrSWInstalledID
       $oid = $hrSWInstalledID . "." . $index;
       $oidtable{$oid}{oid} =
         new NetSNMP::OID( $hrSWInstalledID . "." . "$index" );
       $oidtable{$oid}{type} = ASN_OBJECT_ID;
 
       $oidtable{$oid}{val} = "0.0";
 
       #hrSWInstalledType
       $oid = $hrSWInstalledType . "." . $index;
       $oidtable{$oid}{oid} =
         new NetSNMP::OID( $hrSWInstalledType . "." . "$index" );
       $oidtable{$oid}{type} = ASN_INTEGER;
 
       if (   $packages{$name}{Priority} eq "required"
           || $packages{$name}{Section} eq "base" )
       {
 
           #OS package
           $oidtable{$oid}{val} = 2;
       }
       else {
 
           #application
           $oidtable{$oid}{val} = 4;
       }
 
       #increment index
       $index++;
   }
 
   #hrSWInstalledLastChange
   $oid = $hrSWInstalledLastChange . "." . $index;
   $oidtable{$oid}{oid} =
     new NetSNMP::OID( $hrSWInstalledLastChange . "." . "$index" );
   $oidtable{$oid}{type} = ASN_TIMETICKS;
 
   my $mtime = ( stat($statusfile) )[9];
   $oidtable{$oid}{val} = ( time() - $inittime ) * 100;
 
   #hrSWInstalledLastUpdateTime
   $oid = $hrSWInstalledLastUpdateTime . "." . $index;
   $oidtable{$oid}{oid} =
     new NetSNMP::OID( $hrSWInstalledLastUpdateTime . "." . "$index" );
   $oidtable{$oid}{type} = ASN_TIMETICKS;
 
   $oidtable{$oid}{val} = ( time() - $inittime ) * 100;
 
   print "\tdone. (" . scalar( keys %packages ) . " packages)\n" if $debug;
   return %oidtable;
}
 
#convert unix timestamp to snmp TimeAndDate
sub snmpDateStamp {
 
   my ($ts) = @_;
 
   my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
     gmtime($ts);
   return pack 'n C6 a C2', $year + 1900, $mon + 1, $mday, $hour, $min, $sec,
     0, '-', 0, 0;
 
}
 
sub populateCaches {
   %oidtable   = enumPkgs( $statusfile, $infodir );
   @oidkeys    = oid_lex_sort( keys %oidtable );
   %nextOIDMap = nextOIDMap( \%oidtable, \@oidkeys );
}
 
sub shutDown {
   $running = 0;
   print STDERR "shutting down\n" if ($debug);
}
chmod +x /etc/snmp/hrswinstalled.pl
  • verify it can run
root@servrr:/etc/snmp# /etc/snmp/hrswinstalled.pl
 loading Debian hrSWInstalled MIB extension 
 started us as a subagent (NetSNMP::agent=HASH(0x42575f0))
 ## looks good - type ctrl-c to quit
service  snmpd restart
 * Restarting network management services:
snmpwalk -v2c -c <secret> localhost
iso.3.6.1.2.1.1.1.0 = STRING: "Linux onion 3.2.0-40-generic #64-Ubuntu SMP Mon Mar 25 21:22:10 UTC 2013 x86_64"
iso.3.6.1.2.1.1.2.0 = OID: iso.3.6.1.4.1.8072.3.2.10
iso.3.6.1.2.1.1.3.0 = Timeticks: (3536) 0:00:35.36
iso.3.6.1.2.1.1.4.0 = STRING: "Me <me@example.org>"
iso.3.6.1.2.1.1.5.0 = STRING: "server"
iso.3.6.1.2.1.1.6.0 = STRING: "Sitting on the Dock of the Bay"
iso.3.6.1.2.1.1.7.0 = INTEGER: 72
.....
Personal tools
Namespaces

Variants
Views
Actions
Navigation
Toolbox