Section 11.9. Simple SNMP Agent


11.9. Simple SNMP Agent

Traditional SNMP agents typically give you all the monitoring and management features you could want. Sometimes you may wish you could write your own SNMP agent. Anyone who has looked at the Net-SNMP agent code knows how complex it is. Well, have no fear! The Net-SNMP package now comes with Perl bindings that allow you to create a Perl SNMP agent in a number of ways:

  • Standalone SNMP agent

  • AgentX subagent

  • Embedded agent within the normal Net-SNMP agent

For this section, we thought it would be interesting to present a fully working Perl agent. This isn't so much to write yet another SNMP agent but rather to show how an SNMP agent operates.

The basic flow through the agent is as follows:

  1. Create a new agent object

  2. Register the top of the agent's OID tree

  3. Register a callback subroutine

  4. Sit and wait for requests

It's pretty straightforward, and so is the code itself. First things first, though. You need to get a copy of the Net-SNMP package from http://www.net-snmp.org. Follow the instructions for building and installing the package and Perl modules.

The complete agent source follows:

 205    #!/usr/bin/perl 206 207    # 208    # File: agent.pl 209    # 210 211    use NetSNMP::agent (':all'); 212    use NetSNMP::default_store (':all'); 213    use NetSNMP::ASN (':all'); 214    use NetSNMP::OID; 215    use SNMP; 216 217    my $port = "9161"; 218    my $host = ".1.3.6.1.4.1.8072.25"; 219    my $hrMemorySize = $host.".2.2"; 220 221    sub myHandler{ 222       my ($handler, $registration_info, $request_info, $requests) = @_; 223       my $request; 224       for($request = $requests; $request; $request = $request->next( )) { 225          my $oid = $request->getOID( ); 226          if ($request_info->getMode( ) == MODE_GET) { 227             if ($oid == new NetSNMP::OID($hrMemorySize)) { 228                 my $value = getMemorySize( ); 229                 $request->setValue(ASN_INTEGER, $value); 230             } 231          } elsif ($request_info->getMode( ) == MODE_GETNEXT) { 232             if ($oid <= new NetSNMP::OID($host)) { 233                 $request->setOID($hrMemorySize); 234                 my $value = getMemorySize( ); 235                 $request->setValue(ASN_INTEGER, $value); 236             } 237          } 238       } 239    } 240 241    sub getMemorySize{ 242       my $file = "/proc/meminfo"; 243       my $total = 0; 244       open(FILE,$file) || die("Unable to open file: $!\n"); 245       while(<FILE>){ 246          chomp; 247          if($_ =~ /^MemTotal/){ 248             # One Linux (Kernel 2.6.8-2-686), the entry looks like: 249             # MemTotal:      1026960 kB 250             ($total) = $_ =~ m/^MemTotal:.*?(\d+).*?kB$/; 251             last; 252          } 253       } 254       close(FILE); 255       return $total; 256    } 257 258    my $agent = new NetSNMP::agent( 259             'Name' => 'snmpd', 260             'Ports' => $port); 261 262    my $regoid = new NetSNMP::OID($host); #Beginning of Host Resources Tree 263    print "regoid: $regoid\n"; 264    $regitem = $agent->register("mytest", $regoid, \&myHandler); 265    if($regitem == 0){ 266       print "Error registering: $!\n"; 267       exit -1; 268    } 269 270    my $running = 1; 271    $SIG{'TERM'} = sub {$running = 0;}; 272    $SIG{'INT'} = sub {$running = 0;}; 273    while($running) { 274        $agent->agent_check_and_process(1); # 1 blocks, and 0 does not 275    } 276    print "Good-bye!\n"; 

The agent mimics tracking a small portion of the Host Resources MIB (RFC 1514). While Net-SNMP has support for this MIB, it does serve as a good example of how a real agent works under the covers.

Here are some key points about the agent:


Line 217

This is the port the agent will listen on. You can optionally specify the protocol; e.g., tcp:9161 would have the agent listen on TCP port 9161.


Line 218

$host is the top of the OID tree that this agent implements. .1.3.6.1.4.1.8072 is the Net-SNMP enterprise OID. We added .25 to it since this corresponds to the Host Resources top-level OID.


Line 219

$hrMemorySize is the one and only managed variable we will implement. It represents the total memory on the system.


Lines 258 and 259

Line 258 begins the creation of a new agent. Line 259 gives a name to this agent. Note that the underlying Net-SNMP library is going to tack on a .conf to this attribute. We used snmpd so that the library would find the default snmpd.conf and use whatever access permissions are in it. If you don't have a configuration file for the library to use, your agent is effectively uselessit won't respond to any requests.


Line 262

Here we create a new OID object which represents the top of the agent's OID tree. The agent will respond to requests for any objects under this tree.


Line 264

The register method is used to define the subroutine that handles incoming requests. The first argument is a name, the second argument is the OID we created on Line 262, and the third argument is the subroutine name.


Line 274

Here we just sit and wait for requests to come in. The underlying library will call the subroutine we registered on Line 264 for us when a request comes in.


Line 221

This begins the subroutine for handling requests. In this agent, we respond to get and getnext requests, but there is no reason why we couldn't handle set requests as well.


Lines 228 and 234

These lines call a routine to parse the /proc/meminfo on Linux to get the total memory on the system. Note that this is not portable. Some operating systems, like Solaris, may support actual kernel calls that can return such information.


Lines 229 and 235

Here we encode the value obtained from Line 228 or 234 and encode it as an integer. Why an integer? If we look in the Host Resources MIB for hrMemorySize, we see the following:

        hrMemorySize OBJECT-TYPE            SYNTAX KBytes            ACCESS read-only            STATUS mandatory            DESCRIPTION                   "The amount of physical main memory contained by                   the host."            ::= { hrStorage 2 } 

The SYNTAX is Kbytes. Kbytes is defined earlier in the MIB as:

       -- memory size, expressed in units of 1024bytes       KBytes ::=    INTEGER (0..2147483647) 

It's an integer under the covers, so that's how we chose to encode the total memory.

That's it. The various modules installed by Net-SNMP have corresponding manpages. They provide good details for general usage.




Essential SNMP
Essential SNMP, Second Edition
ISBN: 0596008406
EAN: 2147483647
Year: 2003
Pages: 165

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net