[SNMP4J] TCP Socket in SYN_RECV when sending V3 traps

Neeraj Vaidya neeraj.vaidya at yahoo.co.in
Tue May 23 20:33:30 CEST 2017


Hi,
I have written the following code to send v3 traps to a trap collector daemon (specifically snmptrapd from net-snmp library), which is running on a TCP port.
The snmptrapd is running on a RHEL server. And my code is also running on that same host.
All I am trying at the moment is to include the linkup trapOID and the sysUpTime in the PDU (ScopedPDU to be precise).

In an Eclipse IDE or even by invoking my application via a command line, when I "Run" the application, traps do not get sent out, however, when I "Debug" the application in Eclipse IDE, the traps DO get sent successfully.

Upon analyzing further, I noticed that when I "Run" the application, the application completes (but without sending TRAPS) without any error, however, the socket that got created as a result of the Snmp.send() invocation, is in a SYN_RECV state. 

This lead me to think that it is possible that the ServerThread in the DefaultTcpTransportMapping class is not allowed to complete the 3-way handshake and thus the sending of the message, before the flow moves on to the next statement in the code.

So, I then added a Thread.Sleep of even 10ms, immediately after the Snmp.send() method invocation, and Now the trap gets sent out (both when I "Run" the application via command-line/Eclipse OR even when I debug it in Eclipse).

The code shown below is the one which contains the Thread.Sleep statement and is a working version of the code.

Is this a bug in the SNMP4J library or am I doing something wrong in my code ? Why does the trap not get sent out without adding the Sleep.
Shouldn't the TCP connection (& send) be allowed to complete before the code moves on to the next statement in the program ?

------------------------------------------------ Code Start ------------------------------------------------ 

                Address address = GenericAddress.parse("tcp:rhelhost1/1163");

		try {
			TransportMapping transportMapping = new DefaultTcpTransportMapping();
			transportMapping.listen();			
					
			Snmp snmp = new Snmp(transportMapping);

			USM usm = new USM(SecurityProtocols.getInstance(),
                                                       new OctetString(MPv3.createLocalEngineID()), 0);
			
			SecurityModels.getInstance().addSecurityModel(usm);

			//snmp.listen(); ----> Do I need to use this invocation ??

			byte[] b = (new BigInteger("0102030405",16)).toByteArray();

			snmp.getUSM().addUser(new OctetString("snmp4j"),
					new UsmUser(new OctetString("snmp4j"), AuthMD5.ID, new OctetString("snmp4j"), PrivDES.ID, new OctetString("snmp4j")));
			
			UserTarget target = new UserTarget();
				
			target.setAddress(address);
			target.setRetries(1);
			target.setTimeout(5000);
			target.setVersion(SnmpConstants.version3);
			target.setSecurityLevel(SecurityLevel.AUTH_NOPRIV);
			target.setSecurityName(new OctetString("snmp4j"));
			
			// create the PDU
			ScopedPDU pdu = new ScopedPDU();
			long sysUpTime = Instant.now().getEpochSecond();
			//pdu.add(new VariableBinding(SnmpConstants.sysUpTime),new OctetString(new Date().toString()));
			pdu.setType(ScopedPDU.TRAP);			
			pdu.add(new VariableBinding(SnmpConstants.sysUpTime, new TimeTicks(sysUpTime)));
			pdu.add(new VariableBinding(SnmpConstants.snmpTrapOID, SnmpConstants.linkUp));
			pdu.setContextEngineID(new OctetString().fromByteArray(b));
			snmp.setLocalEngine(b, 0, 0);
			// send the PDU			
			
			ResponseEvent response = null;

			response = snmp.send(pdu, target);

			Thread.sleep(10); // This Sleep somehow allows the entire TCP 3-way handshake to occur without terminating the program 

			snmp.close();			

		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} 	
------------------------------------------------ Code End  ------------------------------------------------ 

Regards,
Neeraj


More information about the SNMP4J mailing list