11.9. Simple SNMP AgentTraditional 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:
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:
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:
That's it. The various modules installed by Net-SNMP have corresponding manpages. They provide good details for general usage. |