Java Dynamic Management Kit 5.0 Tutorial

Inform Requests

The inform request is specified in SNMPv2 and SNMPv3 as a mechanism for sending a report and receiving a response.

Because SNMP managers both send and receive inform requests, the SNMP manager API includes the mechanisms for doing both. Roughly, inform requests are sent in the same way as other requests, and they are received in the same way as traps. Both of these mechanisms are explained in the following sections.

There are simple examples, one for SMNPv2 and one for SNMPv3. Each example has two manager applications, one of which sends an inform request, and the other which listens for and replies to this request. No SNMP agents are involved in these exchanges.

Sending an Inform Request (SNMPv2)

Like the other types of requests, the manager sends an inform request through a session. The only difference is that the peer object associated with the request should be an SNMP manager able to receive and reply to InformRequest PDUs.

You can associate a peer with a session by making it the default peer object. This is how we do it in this example. This means that if we do not specify a peer when sending requests, they are automatically addressed to our manager peer. Because sessions often have agent peers as a default, you can specify the manager peer as a parameter to the snmpInform method of the session object.


Example 19–9 Sending an SNMPv2 Inform Request in SimpleManager1

// When calling the program, you must specify the hostname
// of the SNMP manager you want to send the inform to.
//
String host = argv[0];
        
// Initialize the port number to send inform PDUs on port 8085.
//
int port = 8085;
   
try {
    // Create an SnmpPeer object that represents the entity to
    // communicate with. 
    //
    SnmpPeer peer = new SnmpPeer(host, port);
     
    // Create parameters to associate to the peer.
    // When creating the parameter object, you can specify the
    // read and write community to be used when sending an
    // inform request.
    // 
    SnmpParameters params = new SnmpParameters(
        "public", "private", "public");
       
    // The newly created parameter must be associated to the peer.
    //
    peer.setSnmpParam(params);
     
    // Build the session. A session creates, controls and manages
    // one or more requests.
    //
    SnmpSession session = new SnmpSession("SimpleManager1 session");
    session.setDefaultPeer(peer);
     
    // Make the SNMP inform request and wait for the result.
    //
    SnmpRequest request = session.snmpInform(
        null, new SnmpOid("1.2.3.4"), null);
    java.lang.System.out.println(
        "NOTE: Inform request sent to SNMP manager on " +
        host + " at port " + port);
    boolean completed = request.waitForCompletion(10000);
       
    // Check for a timeout of the request.
    //
    if (completed == false) {
        java.lang.System.out.println(
            "\nSimpleManager1::main: Request timed out. " +
            "Check if agent can be reached");
         
        // Print request.
        //
        java.lang.System.out.println("Request: " + request.toString());
        java.lang.System.exit(0);
    }
     
    // Now we have a response. Check if the response contains an error.
    //
    int errorStatus = request.getErrorStatus();
    if (errorStatus != SnmpDefinitions.snmpRspNoError) {
        java.lang.System.out.println("Error status = " +
            SnmpRequest.snmpErrorToString(errorStatus));
        java.lang.System.out.println("Error index = " +
            request.getErrorIndex());
        java.lang.System.exit(0);
    }
       
    // Now we shall display the content of the result.
    //
    SnmpVarbindList result = request.getResponseVbList();
    java.lang.System.out.println("\nNOTE: Response received:\n" + result);
       
    // Stop the session properly before exiting
    session.destroySession();
    java.lang.System.exit(0);
     
} catch(Exception e) {
    java.lang.System.err.println(
        "SimpleManager1::main: Exception occurred:" + e );
    e.printStackTrace();
}

Before sending the request, the snmpInform method automatically adds two variables to the head of the varbind list that is passed in as the last parameter. These are sysUpTime.0 and snmpTrapOid.0, in the order they appear in the list. These variables are mandated by RFC 1905 and added systematically so that the calling process does not need to add them.

Like all other requests in a session, inform requests can be handled either synchronously or asynchronously in the sender. In our example, we process the inform request synchronously: the manager blocks the session while waiting for the completion of the request. In an asynchronous manager, you would need to implement a response handler as explained in Response Handler, and then use it to process responses, as shown in Example 19–7.

Sending an Inform Request (SNMPv3)

This example shows how to build an SNMPv3 manager that sends and/or receives SNMPv3 requests. It initializes an SNMPv3 USM peer and an SNMP session, and then sends an inform request to a second SNMP manager.


Example 19–10 Sending an SNMPv3 Inform Request in SimpleManager1V3

			//	When calling the program, specify the hostname of the  
			// SNMP manager to send the inform to
			//
			final String host = argv[0];
        
        // Initialize the port number to send inform PDUs on port 8085.
        //
        final int port = 8085;
   
        	[...]

	    	// Create an SnmpUSMPeer object for representing the entity 
	    	// to communicate with. 
        //
        final SnmpUsmPeer peer = new SnmpUsmPeer(session.getEngine(),
						    host, 
						    port);
     
        // Create parameters to associate to the entity to 
	      // communicate with.
       // When creating the parameter object, you specify the necessary 
	      // security related parameters.
        // 
        final SnmpUsmParameters params = 
			new SnmpUsmParameters(session.getEngine());

	    	// Set the parameters
		   //
	    
	   		// First a principal
	    	//
		   params.setPrincipal("defaultUser");
	    
	      // A security level. Authentication is applied.
	      // 
	      params.setSecurityLevel(SnmpDefinitions.authNoPriv);
	    
	      // Add a contextEngineId. The context engine Id is the 
	      // manager's engine ID and not the adaptor's.
	      //
	      params.setContextEngineId(peer.getEngineId().getBytes());

	      // Add a context name.
	      //
	      params.setContextName("TEST-CONTEXT".getBytes());
	    
       // The newly created parameter must be associated to the peer.
       //
       peer.setParams(params);
     

	      // The inform is authenticated, so the timeliness 
	      // discovery must be processed.
	      //
	      peer.processUsmTimelinessDiscovery();
	    


       // A default peer (listener manager) can be associated to an 
	      // SnmpSession. When invoking a service provided by the 
	      // SnmpSession, if the peer is not specified, the session 
	      // will perform the service using the default one as the 
	      // target of the service
       //
       session.setDefaultPeer(peer);
	    
       println("\nNOTE: SNMP V3 simple manager 1 initialized");
            
       // Make the SNMP inform request and wait for the result.
       //
       println("\n>> Press Enter to send the inform request on " + 
		  host + " at port " + port + "...");
        try {
                System.in.read();
            } catch (IOException e) {
                e.printStackTrace();
            }

            final SnmpRequest request = 
		 session.snmpInformRequest(null, new SnmpOid("1.2.3.4"), 
					  null);

            println("NOTE: Inform request sent to SNMP manager on " + 
		    host + " at port " + port);

            final boolean completed = request.waitForCompletion(10000);
       
         // Check for a timeout of the request.
         //
         if (completed == false) {
                println("\nSimpleManager1::main: Request timed out." +
			" Check reachability of agent");
	 
                // Print request.
                //
                println("Request: " + request.toString());
                java.lang.System.exit(0);
            }
     
         // Check if the response contains an error
         //
         final int errorStatus = request.getErrorStatus();
         if (errorStatus != SnmpDefinitions.snmpRspNoError) {
                println("Error status = " +
 			SnmpRequest.snmpErrorToString(errorStatus));
                println("Error index = " + request.getErrorIndex());
                java.lang.System.exit(0);
            }
       
            // Display the content of the result.
            //
            final SnmpVarBindList result = request.getResponseVarBindList();
            println("\nNOTE: Response received:\n" + result);
       
            // End the session
            //
            println("\nNOTE: SNMP V3 simple manager 1 stopped...");
            session.destroySession();
       

}

As you can see, once the SNMPv3 session has been instantiated and the SNMPv3 USM peer has been created and configured, the inform request is sent in exactly the same way as under SNMPv2. The only difference is the additional SNMPv3 security.


Receiving Inform Requests

Managers receive inform requests as they do traps: they are unsolicited events that must be received by a dispatcher object. Unlike traps, an inform request requires a response PDU that, according to the SNMP specification, must contain the same variable bindings. Therefore, immediately after an inform request is successfully received and decoded, the SnmpEventReportDispatcher class automatically constructs and sends the inform response back to the originating host.

The manager application then retrieves the data in the inform request through a listener on the dispatcher. Inform request listeners are registered with the dispatcher object in the same way as trap listeners. The receiving manager in our example is very simple, because its only function is to create the dispatcher and the listener for inform requests. The receiving manager SimpleManager2 is the same for both the SimpleManager1 and SimpleManager1V3 examples.


Example 19–11 Receiving Inform Requests in SimpleManager2

// Initialize the port number to listen for incoming inform PDUs on 
// port 8085.
int port = 8085;

try {
    
    // Create a dispatcher for SNMP event reports 
	   // (SnmpEventReportDispatcher).
    // SnmpEventReportDispatcher is run as a thread and listens for informs
    // on the specified port.
    // Add our InformListenerImpl class as an SnmpInformListener.
    // InformListenerImpl will receive a callback when a valid trap
    // PDU is received.
    //
    SnmpEventReportDispatcher informDispatcher =
        new SnmpEventReportDispatcher(port,taskServer,null,null);
    informDispatcher.addInformListener(new InformListenerImpl());
	   final Thread informThread = new Thread(informDispatcher);
	   informThread.setPriority(Thread.MAX_PRIORITY);    
     informDispatcher.start();
		println("\nNOTE: SNMP simple manager 2 initialized");

    // Note that you can use the same SnmpEventReportDispatcher object
    // for both incoming traps and informs.
    // Just add your trap listener to the same dispatcher, for example:
    //    informDispatcher.addTrapListener(new TrapListenerImpl());

    // Here we are just going to wait for inform PDUs.
    //
    java.lang.System.out.println("\nNOTE: Event report listener 
	   initialized");
    java.lang.System.out.println(
      "      and listening for incoming inform PDUs on port " + port 
		+ "...");

} catch(Exception e) {
    java.lang.System.err.println(
        "SimpleManager2::main: Exception occurred:" + e );
    e.printStackTrace();
}

The remaining step is to program the behavior we want upon receiving an inform request. To do this, we must write the InformListenerImpl class that we registered as an inform request listener in the previous code sample. This class implements the SnmpInformListener interface and its processSnmpInform and processSnmpInformV3 methods handle the incoming inform requests.

Because the dispatcher automatically sends the inform response back to the originating host, the SnmpInformListener implementation does not need to do this. Usually this method extracts the variable bindings and takes whatever action is necessary upon receiving an inform request. In our example, we simply print out the source and the contents of the inform request.


Example 19–12 The InformListenerImpl Class

import java.io.IOException;
import javax.management.snmp.SnmpPduRequest;
import javax.management.snmp.manager.SnmpInformListener;

/**
 * This class implements the SnmpInformListener interface.
 * The callback method processSnmpInform is called when a
 * valid inform PDU is received.
 */

public class InformListenerImpl implements SnmpInformListener {

    public void processSnmpInform(SnmpPduRequest inform) {
        
        // Display the received PDU.
        //
        java.lang.System.out.println("\nNOTE: Inform request received:\n");
        java.lang.System.out.println("\tType
			 = " + inform.pduTypeToString(inform.type));
        java.lang.System.out.println("\tVersion   = " + inform.version);
        java.lang.System.out.println("\tRequestId = " + inform.requestId);
        java.lang.System.out.println("\tAddress   = " + inform.address);
        java.lang.System.out.println("\tPort      = " + inform.port);
        java.lang.System.out.println("\tCommunity = " +
            new String(inform.community));
        java.lang.System.out.println("\tVB list   = ");

        for (int i = 0; i < inform.varBindList.length; i++) {
            java.lang.System.out.println("\t\t" + inform.varBindList[i]);
        }


			public void processSnmpInformV3(SnmpScopedPduRequest inform) {
				println("\nNOTE: Inform request V3 received:\n");
       	 	println("\tType      = 
				" + inform.pduTypeToString(inform.type));
       		println("\tVersion   = " + inform.version);
		      	println("\tRequestId = " + inform.requestId);
     	  	println("\tAddress   = " + inform.address);
        		println("\tPort      = " + inform.port);
        		println("\tContext = " + new String(inform.contextName));
        		println("\tVB list   = ");
        		for (int i = 0; i < inform.varBindList.length; i++) {
           		 println("\t\t" + inform.varBindList[i]);
        }
    }
    
        // Our listener stops the manager after receiving its first
        // inform request
        java.lang.System.out.println(
            "\nNOTE: SNMP simple manager 2 stopped...");
        java.lang.System.exit(0);
    }
}

To Run the SNMPv2 Inform Request Example

The examplesDir/Snmp/Inform directory contains all of the files for the two manager applications, along with the InformListenerImpl class.

  1. Compile all files in this directory with the javac command.

    For example, on the Solaris platform with the Korn shell, you would type:


    $ cd examplesDir/Snmp/Inform/
    $ javac -classpath classpath *.java
    
  2. To run the example, start the inform request receiver with the following command.


    $ java -classpath classpath SimpleManager2
    

    You can start the application in another terminal window or on another host.

  3. Wait for this manager to be initialized, then start the other manager with the following command.

    The hostname is the name of the host where you started the receiving manager, or localhost.


    $ java -classpath classpath SimpleManager1 hostname
    
  4. When the sender is ready, press Enter to send the inform request.

    You should see the contents of the request displayed by the receiving manager. Immediately afterwards, the sender receives the inform response containing the same variable bindings and displays them. Both manager applications then exit automatically.

To Run the SNMPv3 Inform Request Example
  1. Before running the example, you must compile the Java classes in the examplesDir/Snmp/Inform directory.

    Type the following commands in your working directory:


    $ javac -d . SimpleManager1V3.java SimpleManager2.java 
    InformListenerImpl.java
    
  2. Start the receiving manager, SimpleManager2:


    $ java -classpath classpath -Djdmk.security.file=./jdmk.security 
    SimpleManager2
    

    This manager binds to port 8085.

  3. Wait for this manager to be initialized, then start the other manager with the following command, specifying the hostname and port number of the receiving manager.

    In this case, the host name is the localhost


    $ java -classpath classpath -Djdmk.security.file=./sender.security 
    SimpleManager1V3 localhost
    
  4. When the sender is ready, press Enter to send the inform request.

    You should see the contents of the request displayed by the receiving manager. Immediately afterwards, the sender receives the inform response containing the same variable bindings and displays them. Both manager applications then exit automatically.