14.5. Receiving Traps and InformsWe've split up the SNMPv2c and SNMPv3 trap receivers into two separate classes, V2TRapReceiver and V3TRapReceiver. These classes implement CommandResponder. This means that we must implement a method that has the following signature: public synchronized void processPdu(CommandResponderEvent e) { ... } The processPdu method is responsible for handling incoming requests. Since SnmpWalk supports SNMPv3, we have to be able to respond to discovery requests from an authoritative SNMP engine.
Consider the following code sequence: _threadPool = ThreadPool.create("DispatcherPool", _numThreads); MessageDispatcher mtDispatcher = new MultiThreadedMessageDispatcher(_threadPool, new MessageDispatcherImpl( )); // add message processing models mtDispatcher.addMessageProcessingModel(new MPv2c( )); // add all security protocols SecurityProtocols.getInstance().addDefaultProtocols( ); CommunityTarget target = new CommunityTarget( ); if(target != null) { target.setCommunity(_comm); _target = target; } else { System.out.println("Unable to create Target object"); System.exit(-1); } _snmp = new Snmp(mtDispatcher, _transport); if(_snmp != null){ _snmp.addCommandResponder(this); } else { System.out.println("Unable to create Snmp object"); System.exit(-1); } This example does the following:
Now let's look at the same sequence for SNMPv3: _threadPool = ThreadPool.create("DispatcherPool", _numThreads); MessageDispatcher mtDispatcher = new MultiThreadedMessageDispatcher(_threadPool, new MessageDispatcherImpl( )); // add message processing models mtDispatcher.addMessageProcessingModel(new MPv1( )); mtDispatcher.addMessageProcessingModel(new MPv2c( )); mtDispatcher.addMessageProcessingModel(new MPv3( )); // add all security protocols SecurityProtocols.getInstance().addDefaultProtocols( ); _snmp = new Snmp(mtDispatcher, _transport); if(_snmp != null){ _snmp.addCommandResponder(this); } else { System.out.println("Unable to create Target object"); System.exit(-1); } MPv3 mpv3 = (MPv3)_snmp.getMessageProcessingModel(MessageProcessingModel.MPv3); USM usm = new USM(SecurityProtocols.getInstance( ), new OctetString(mpv3.createLocalEngineID( )), 0); SecurityModels.getInstance( ).addSecurityModel(usm); No surprises here. We do basically the same operations for SNMPv3, except that we also create a USM entry and a local engine ID in case we receive a discovery request. The client of this class calls listen( ) to begin the session: public synchronized void listen( ) { try { _transport.listen( ); } catch(IOException ioex) { System.out.println("Unable to listen: " + ioex); System.exit(-1); } System.out.println("Waiting for traps.."); try { this.wait( );//Wait for traps to come in } catch (InterruptedException ex) { System.out.println("Interrupted while waiting for traps: " + ex); System.exit(-1); } } We place the transport into listen mode by calling _TRansport.listen( ). If this succeeds, this.wait( ) is called and we block until a trap or inform comes in. When one does, processPdu( ) is invoked and we handle the request since we created our own implementation of this method. Since listen( ) is blocked when called, here are two similar Main classes, one for an SNMPv2c receiver and one for an SNMPv3 receiver: public class Main{ public Main( ){ } public static void main(String[] args){ V2TrapReceiver v2 = new V2TrapReceiver( ); v2.listen( ); } } public class Main{ public Main( ){ } public static void main(String[] args){ V3TrapReceiver v3 = new V3TrapReceiver( ); v3.listen( ); } } When sending an SNMPv3 trap (we're using the Net-SNMP command-line tools to send traps and informs), use a command like this: $ snmptrap -v3 -u kjs -a MD5 -A "this is private" -x DES -X "this is me" \ 127.0.0.1 '' .1.3.6.1.6.3.1.1.5.3 ifIndex i 2 ifAdminStatus i 1 ifOperStatus i 1 Waiting for traps.. TRAP[reqestID=769359741, errorStatus=0, errorIndex=0, VBS[1.3.6.1.2.1.1.3.0 = 64 days, 22:53:05.51; 1.3.6.1.6.3.1.1.4.1.0 = 1.3.6.1.6.3.1.1.5.3; 1.3.6.1.2.1.2.2.1.1 = 2; 1.3.6.1.2.1.2.2.1.7 = 1; 1.3.6.1.2.1.2.2.1.8 = 1]] We see basically the same output when sending an SNMPv2c trap: $ snmptrap -v2c -c public 127.0.0.1 '' .1.3.6.1.6.3.1.1.5.3 \ ifIndex i 2 ifAdminStatus i 1 ifOperStatus i 1 Waiting for traps.. TRAP[reqestID=1476119517, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.1.2.1.1.3.0 = 64 days, 22:56:04.20; 1.3.6.1.6.3.1.1.4.1.0 = 1.3.6.1.6.3.1.1.5.3; 1.3.6.1.2.1.2.2. 1.1 = 2; 1.3.6.1.2.1.2.2.1.7 = 1; 1.3.6.1.2.1.2.2.1.8 = 1]] Receiving informs produces, as you might imagine, similar output to traps: $ snmpinform -v2c -c public 127.0.0.1 '' .1.3.6.1.6.3.1.1.5.3 \ ifIndex i 2 ifAdminStatus i 1 ifOperStatus i 1 Waiting for traps.. INFORM[reqestID=2056364955, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.1.2.1.1. 3.0 = 65 days, 23:41:40.60; 1.3.6.1.6.3.1.1.4.1.0 = 1.3.6.1.6.3.1.1.5.3; 1.3.6.1.2.1. 2.2.1.1 = 2; 1.3.6.1.2.1.2.2.1.7 = 1; 1.3.6.1.2.1.2.2.1.8 = 1]] And finally an SNMPv3 inform: $ snmpinform -v3 -u kjs -a MD5 -A "this is private" -x DES \ -X "this is me" 127.0.0.1 '' .1.3.6.1.6.3.1.1.5.3 ifIndex i 2 \ ifAdminStatus i 1 ifOperStatus i 1 Waiting for traps.. INFORM[reqestID=648331621, errorStatus=0, errorIndex=0, VBS[1.3.6.1.2.1.1.3.0 = 65 days, 23:44:40.18; 1.3.6.1.6.3.1.1.4.1.0 = 1.3.6.1.6.3.1.1.5.3; 1.3.6.1.2.1.2.2.1.1 = 2; 1.3.6.1.2.1.2.2.1.7 = 1; 1.3.6.1.2.1.2.2.1.8 = 1]] One final note: recall that our SnmpTrap class had to encode sysUpTime and snmpTrapOID as the first two variable bindings in the trap we created. Notice how all the output includes this information, as encoded from the Net-SNMP command-line tools: ...VBS[1.3.6.1.2.1.1.3.0 = 65 days, 23:44:40.18; 1.3.6.1.6.3.1.1.4.1.0 = 1.3.6.1.6.3.1.1.5.3; ...]] |