Section 14.2. SNMP getnext


14.2. SNMP getnext

The SNMP getnext operation is commonly referred to as "walking a MIB." The example source implements a command-line snmpwalk tool similar to that of Net-SNMP's snmpwalk:

     public class SnmpWalk implements PDUFactory {     ...     } 

Our SnmpWalk class implements PDUFactory. This means we must implement a method with the following signature:

     public PDU createPDU(Target target) {     ...     } 

The createPDU method is responsible for creating the proper PDU, either an SNMPv2c or SNMPv3 PDU. The type of PDU (the particular SNMP operation) is also configured as part of the version-specific PDU. This is accomplished by setting a member variable that is used when createPDU( ) is called:

       private int _pduType = PDU.GETNEXT; 

The class has two different constructors:

     public SnmpWalk(String host, String oid){     ...     }     public SnmpWalk(String host, String oid, String user, String authProtocol,       String authPassphrase, String privProtocol, String privPassphrase) {     ...     } 

The first constructor creates an SNMPv2c walk command. The arguments are the host on which an agent is running and the prefix of the OIDs we want to walk. The community string is hardcoded in the application, but ordinarily you will want to pass this as a constructor or expose a setter. The second constructor creates an SNMPv3 walk command. The first two arguments are the same as the first constructor, but the other arguments deal with setting up SNMPv3 security.

Each constructor sets the particular version of SNMP by using one of the following predefined constants:

  • SnmpConstants.version1

  • SnmpConstants.version2c

  • SnmpConstants.version3

The following sequence of code sets up the security name (user), authentication protocol, authentication passphrase, privacy protocol, and privacy passphrase:

          _privPassphrase = new OctetString(privPassphrase);      _authPassphrase = new OctetString(authPassphrase);      _securityName = new OctetString(user);         if (authProtocol.equals("MD5")) {           _authProtocol = AuthMD5.ID;         } else if (authProtocol.equals("SHA")) {           _authProtocol = AuthSHA.ID;         }      if (privProtocol.equals("DES")) {           _privProtocol = PrivDES.ID;         } else if ((privProtocol.equals("AES128")) || (privProtocol.equals("AES"))) {           _privProtocol = PrivAES128.ID;         } else if (privProtocol.equals("AES192")) {           _privProtocol = PrivAES192.ID;         } else if (privProtocol.equals("AES256")) {           _privProtocol = PrivAES256.ID;         } 

The privacy passphrase, authentication passphrase, and user are all stored internally as an OctetString, which, in contrast with a String, implements a character-set-independent 8-bit byte string. The authentication and privacy protocols are stored internally as OIDs. SNMP4J includes constants for all the various protocols and their respective OID value. They are:

  • AuthMD5.ID

  • AuthSHA.ID

  • PrivDES.ID

  • PrivAES128.ID

  • PrivAES192.ID

  • PrivAES256.ID

The next step is to add the OID for walking a Vector of VariableBindings:

      _vbs.add(new VariableBinding(new OID(oid))); 

Next we create an instance of UdpAddress, which represents the host and port we plan to communicate with:

      _address = new UdpAddress(host+"/161"); 

The format that is passed to the constructor is host/port.

Now that we have the preliminaries set up, the user of the SnmpWalk class calls doWalk( ) to initiate the process. The call to send( ) sets up all the internals of SNMP:

     PDU response = send( ); 

Here is the sequence of calls that occurs before a response PDU is returned:

  1. createSnmpSession( )

  2. createTarget( )

  3. createPDU( )

  4. walk(...)

  5. processWalk( )

Let's look at each of these method calls. The call to createSnmpSession( ) creates the underlying SNMP session. If SNMPv3 is used, we add a user to this session with a call to addUsmUser(snmp). This method looks like the following:

     private void addUsmUser(Snmp snmp) {         snmp.getUSM( ).addUser(_securityName,            new UsmUser(_securityName,            _authProtocol,            _authPassphrase,            _privProtocol,            _privPassphrase));       } 

Here we call the getUSM( ) method for the SNMP session that was created. This in turn allows us to call addUser, where we create a new user entry, with _securityName, followed by a new instance of UsmUser and all the SNMPv3 security-specific parameters passed to the constructor. If you want to create multiple users for this SNMP session, you would repeat these steps until you have added all the users for your session.

Next we create a target by calling createTarget( ). This creates either a UserTarget (SNMPv3) or a CommunityTarget (SNMPv1 and SNMPv2c). Depending on the version used, either the _securityName or the _community variables are set for the respective target. If SNMPv3 is used, the security level is also specified and is set to one of the following constants:

  • SecurityLevel.NOAUTH_NOPRIV

  • SecurityLevel.AUTH_NOPRIV

  • SecurityLevel.AUTH_PRIV

Once we return from createTarget( ), the send( ) method sets the version, address, timeout, and retries for the target. It also places all transport mappings into listen mode:

     snmp.listen( ); 

This ensures that we respond to SNMP engine discovery requests.

createPDU( ) creates either a ScopedPDU for SNMPv3 or a PDU for SNMPv1 and SNMPv2c. The context name and context engine ID are set for the ScopedPDU. The resulting PDU is returned as the variable request and is used later on by other methods.

Now the walk( ) method is invoked. One of the first things it does is to get the root OID:

         OID rootOID = request.get(0).getOid( ); 

Since request is a PDU instance, calling get(0) returns a VariableBinding. Calling getOid( ) on a VariableBinding gets its OID for the VariableBinding.

     ResponseEvent responseEvent = snmp.send(request, target);     response = responseEvent.getResponse( ); 

This code fragment retrieves the lexicographically next object in the MIB tree we wish to walk and gets the response from the target. If the response is null, we never received a response. The pseudocode for walking a MIB tree follows:

     do {         Send request to target for top-level OID of where you want to start         Check for response from target     } while(!processWalk( ));     function processWalk( ){         if we have reached the end of the MIB, received an error, or received a         response which isn't lexicographically in the MIB we are walking, then         return true         else print the result from the target. Now encode the         received OID in the request object, so when we send the next request, the         target will send us the next OID (lexicographically) in the tree, if         there is one.     } 

Once we've processed the target's MIB tree, we print some statistics on how many requests were sent, how many objects were received, and the total walk time.

That's it in a nutshell. Let's look at a run of the SnmpWalk application. Here's our main program for exercising the class:

     public class Main{     public Main( ){     }     public static void main(String[] args){     System.out.println("Doing SNMPv2 walk..");     SnmpWalk walk = new SnmpWalk("127.0.0.1","1.3.6.1.2.1.1");     walk.doWalk( );     System.out.println("Doing SNMPv3 walk..");     walk = new SnmpWalk("127.0.0.1","1.3.6.1.2.1.1",                  "kschmidt","MD5","mysecretpass","DES","mypassphrase");     walk.doWalk( );     }     } 

The first constructor creates an SNMPv2c PDU, which starts at the system (1.3.6.1.2.1.1) OID and walks from there. The second constructor creates an SNMPv3 PDU with kschmidt as the security name, MD5 as the authentication protocol, mysecretpass as the authentication passphrase, DES as the privacy protocol, and mypassphrase as the privacy passphrase. Here is the command for running this program, along with its output:

     $ java -cp SNMP4J.jar:.Main     Doing SNMPv2 walk..     1.3.6.1.2.1.1.1.0 = Linux dhcp48 2.6.8-2-686 #1 Mon Jan 24 03:58:38 EST 2005 i686     1.3.6.1.2.1.1.2.0 = 1.3.6.1.4.1.8072.3.2.10     1.3.6.1.2.1.1.3.0 = 4 days, 4:47:17.53     1.3.6.1.2.1.1.4.0 = myself     1.3.6.1.2.1.1.5.0 = dhcp48     1.3.6.1.2.1.1.6.0 = A bld JM-10119 floor 7     1.3.6.1.2.1.1.8.0 = 0:00:00.08     1.3.6.1.2.1.1.9.1.2.1 = 1.3.6.1.2.1.31     1.3.6.1.2.1.1.9.1.2.2 = 1.3.6.1.6.3.1     1.3.6.1.2.1.1.9.1.2.3 = 1.3.6.1.2.1.49     1.3.6.1.2.1.1.9.1.2.4 = 1.3.6.1.2.1.4     1.3.6.1.2.1.1.9.1.2.5 = 1.3.6.1.2.1.50     1.3.6.1.2.1.1.9.1.2.6 = 1.3.6.1.6.3.16.2.2.1     1.3.6.1.2.1.1.9.1.2.7 = 1.3.6.1.6.3.10.3.1.1     1.3.6.1.2.1.1.9.1.2.8 = 1.3.6.1.6.3.11.3.1.1     1.3.6.1.2.1.1.9.1.2.9 = 1.3.6.1.6.3.15.2.1.1     1.3.6.1.2.1.1.9.1.3.1 = The MIB module to describe generic objects for network     interface sub-layers     1.3.6.1.2.1.1.9.1.3.2 = The MIB module for SNMPv2 entities     1.3.6.1.2.1.1.9.1.3.3 = The MIB module for managing TCP implementations     1.3.6.1.2.1.1.9.1.3.4 = The MIB module for managing IP and ICMP implementations     1.3.6.1.2.1.1.9.1.3.5 = The MIB module for managing UDP implementations     1.3.6.1.2.1.1.9.1.3.6 = View-based Access Control Model for SNMP.     1.3.6.1.2.1.1.9.1.3.7 = The SNMP Management Architecture MIB.     1.3.6.1.2.1.1.9.1.3.8 = The MIB for Message Processing and Dispatching.     1.3.6.1.2.1.1.9.1.3.9 = The management information definitions for the SNMP User-     based Security Model.     1.3.6.1.2.1.1.9.1.4.1 = 0:00:00.00     1.3.6.1.2.1.1.9.1.4.2 = 0:00:00.00     1.3.6.1.2.1.1.9.1.4.3 = 0:00:00.00     1.3.6.1.2.1.1.9.1.4.4 = 0:00:00.00     1.3.6.1.2.1.1.9.1.4.5 = 0:00:00.00     1.3.6.1.2.1.1.9.1.4.6 = 0:00:00.00     1.3.6.1.2.1.1.9.1.4.7 = 0:00:00.08     1.3.6.1.2.1.1.9.1.4.8 = 0:00:00.08     1.3.6.1.2.1.1.9.1.4.9 = 0:00:00.08     Total requests sent:    35     Total objects received: 35     Total walk time:        55 milliseconds     End of walked subtree '1.3.6.1.2.1.1' reached at:     1.3.6.1.2.1.2.1.0 = 3     Doing SNMPv3 walk..     1.3.6.1.2.1.1.1.0 = Linux dhcp48 2.6.8-2-686 #1 Mon Jan 24 03:58:38 EST 2005 i686     1.3.6.1.2.1.1.2.0 = 1.3.6.1.4.1.8072.3.2.10     1.3.6.1.2.1.1.3.0 = 4 days, 4:47:18.21     1.3.6.1.2.1.1.4.0 = myself     1.3.6.1.2.1.1.5.0 = dhcp48     1.3.6.1.2.1.1.6.0 = A bld JM-10119 floor 7     1.3.6.1.2.1.1.8.0 = 0:00:00.08     1.3.6.1.2.1.1.9.1.2.1 = 1.3.6.1.2.1.31     1.3.6.1.2.1.1.9.1.2.2 = 1.3.6.1.6.3.1     1.3.6.1.2.1.1.9.1.2.3 = 1.3.6.1.2.1.49     1.3.6.1.2.1.1.9.1.2.4 = 1.3.6.1.2.1.4     1.3.6.1.2.1.1.9.1.2.5 = 1.3.6.1.2.1.50     1.3.6.1.2.1.1.9.1.2.6 = 1.3.6.1.6.3.16.2.2.1     1.3.6.1.2.1.1.9.1.2.7 = 1.3.6.1.6.3.10.3.1.1     1.3.6.1.2.1.1.9.1.2.8 = 1.3.6.1.6.3.11.3.1.1     1.3.6.1.2.1.1.9.1.2.9 = 1.3.6.1.6.3.15.2.1.1     1.3.6.1.2.1.1.9.1.3.1 = The MIB module to describe generic objects for network     interface sub-layers     1.3.6.1.2.1.1.9.1.3.2 = The MIB module for SNMPv2 entities     1.3.6.1.2.1.1.9.1.3.3 = The MIB module for managing TCP implementations     1.3.6.1.2.1.1.9.1.3.4 = The MIB module for managing IP and ICMP implementations     1.3.6.1.2.1.1.9.1.3.5 = The MIB module for managing UDP implementations     1.3.6.1.2.1.1.9.1.3.6 = View-based Access Control Model for SNMP.     1.3.6.1.2.1.1.9.1.3.7 = The SNMP Management Architecture MIB.     1.3.6.1.2.1.1.9.1.3.8 = The MIB for Message Processing and Dispatching.     1.3.6.1.2.1.1.9.1.3.9 = The management information definitions for the SNMP User-     based Security Model.     1.3.6.1.2.1.1.9.1.4.1 = 0:00:00.00     1.3.6.1.2.1.1.9.1.4.2 = 0:00:00.00     1.3.6.1.2.1.1.9.1.4.3 = 0:00:00.00     1.3.6.1.2.1.1.9.1.4.4 = 0:00:00.00     1.3.6.1.2.1.1.9.1.4.5 = 0:00:00.00     1.3.6.1.2.1.1.9.1.4.6 = 0:00:00.00     1.3.6.1.2.1.1.9.1.4.7 = 0:00:00.08     1.3.6.1.2.1.1.9.1.4.8 = 0:00:00.08     1.3.6.1.2.1.1.9.1.4.9 = 0:00:00.08     Total requests sent:    35     Total objects received: 35     Total walk time:        741 milliseconds     End of walked subtree '1.3.6.1.2.1.1' reached at:     1.3.6.1.2.1.2.1.0 = 3 

That's it. We've covered a lot of ground in a small space, so let's summarize the pertinent parts of what we've accomplished:

  • Our SNMP application class implements PDUFactory by implementing a createPDU( ) method.

  • The version of SNMP is set, and based on the version, we either use a community string or create a USM entry with a security name and no authentication and privacy, authentication and no privacy, or authentication and privacy.

  • The address and port of the target we communicate with is used to create a UdpAddress.

  • The SNMP request is sent.

  • We create the SNMP session and add the USM user to the session if SNMPv3 is used.

  • A target is created. If SNMPv2c is used, a CommunityTarget is created with the community string. Otherwise, a UserTarget is created with the value of _securityName and the proper security level is ascertained and set.

  • The createPDU( ) method creates either a ScopedPDU for SNMPv3 or a PDU otherwise.

  • From here on out, we walk the MIB tree using the pseudocode algorithm presented earlier.

Each of the remaining examples uses the same basic code for configuring SNMPv2c or SNMPv3. We will point out where the application differs with respect to the actual SNMP operation it implements.




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