Regarding snmp v3 request in multithreaded environment via snmp4j java library

398 Views Asked by At

I am sending an SNMP v3 request via snmp4j java library to the first snmpv3 server and it works fine. Sending SNMP v3 requests via the snmp4j library to the second snmpv3 server also works fine. However, if I am sending to both servers from two different threads in the same program as below, one of them gives a null response as below:-

203> responsePDU == null :

Error : null Address : null Source : com.x.x.x.SnmpV2@755ca288).

My bet is that somehow below two lines might creating a mess since SecurityModels is a Singleton class.

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

Below is the code:-

Any experience with the snmp4j with v3 in a multithreaded environment...

import org.snmp4j.PDU;
import org.snmp4j.ScopedPDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.UserTarget;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.AuthSHA;
import org.snmp4j.security.PrivAES128;
import org.snmp4j.security.SecurityLevel;
import org.snmp4j.security.SecurityModels;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.security.USM;
import org.snmp4j.security.UsmUser;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;

public class MultiThreadedSnmpV3Request {
    public static void main(String[] args) throws Exception {
        MultiThreadedSnmpV3Request requests = new MultiThreadedSnmpV3Request();
        new Thread(() -> {
            try {
                requests.firstServerRequest();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();

        new Thread(() -> {
            try {
                requests.secondServerRequest();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }

    private void firstServerRequest() throws Exception {
        String targetAddress = "udp:10.99.220.203/161";
        String userName = "xxxx";
        OID authProtocol = AuthSHA.ID;
        String authPassphrase = "f8T7wWXeJ6brNeNF";
        OID privProtocol = PrivAES128.ID; // PrivAES256.ID;
        String privPassphrase = "KpbnkSJrP5Kgbhqb";

        // build a PDU with all the OIDs
        UserTarget target = new UserTarget();
        target.setTimeout(5000);
        target.setVersion(SnmpConstants.version3);
        target.setAddress(GenericAddress.parse(targetAddress));
        target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
        target.setSecurityName(new OctetString(userName));

        TransportMapping<UdpAddress> transport = new DefaultUdpTransportMapping();
        SnmpV2 snmp = new SnmpV2(transport);
        USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
        SecurityModels.getInstance().addSecurityModel(usm);
        // add user to the USM
        snmp.getUSM().addUser(new OctetString(userName), new UsmUser(new OctetString(userName), authProtocol,
                new OctetString(authPassphrase), privProtocol, new OctetString(privPassphrase)));

        transport.listen();
        ScopedPDU requestPDU = new ScopedPDU();
        requestPDU.add(new VariableBinding(new OID("1.3.6.1.4.1.2021.2.1.2.1")));
        requestPDU.setType(PDU.GET);

        for (int i = 0; i < 20; i++) {
            Thread.sleep(3000);
            ResponseEvent re = snmp.send(requestPDU, target);
            PDU responsePDU = re.getResponse();
            if (responsePDU == null) {
                System.out.println("1st Server > responsePDU == null :");
                System.out.println("> Error     : " + re.getError());
                System.out.println("> Address     : " + re.getPeerAddress());
                System.out.println("> Source      : " + re.getSource());
                System.out.println("> User object : " + re.getUserObject());
            } else if (responsePDU.getVariableBindings() != null) {
                for (VariableBinding vb : responsePDU.getVariableBindings()) {
                    System.out.println("1st Server >> " + vb.getOid() + " --> " + vb.getVariable());
                }
            }
        }
    }

    private void secondServerRequest() throws Exception {
        String targetAddress = "udp:10.99.220.204/161";
        String userName = "xxxx";
        OID authProtocol = AuthSHA.ID;
        String authPassphrase = "f8T7wWXeJ6brNeNF";
        OID privProtocol = PrivAES128.ID; // PrivAES256.ID;
        String privPassphrase = "KpbnkSJrP5Kgbhqb";

        UserTarget target = new UserTarget();
        target.setTimeout(5000);
        target.setVersion(SnmpConstants.version3);
        target.setAddress(GenericAddress.parse(targetAddress));
        target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
        target.setSecurityName(new OctetString(userName));

        TransportMapping<UdpAddress> transport = new DefaultUdpTransportMapping();
        Snmp snmp = new Snmp(transport);
        USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
        SecurityModels.getInstance().addSecurityModel(usm);
        // add user to the USM
        snmp.getUSM().addUser(new OctetString(userName), new UsmUser(new OctetString(userName), authProtocol,
                new OctetString(authPassphrase), privProtocol, new OctetString(privPassphrase)));

        transport.listen();

        ScopedPDU requestPDU = new ScopedPDU();
        requestPDU.add(new VariableBinding(new OID("1.3.6.1.4.1.2021.2.1.2.1")));
        requestPDU.setType(PDU.GET);
        for (int i = 0; i < 20; i++) {
            Thread.sleep(3000);
            ResponseEvent re = snmp.send(requestPDU, target);
            PDU responsePDU = re.getResponse();
            if (responsePDU == null) {
                System.out.println("2nd Server> responsePDU == null :");
                System.out.println("> Error     : " + re.getError());
                System.out.println("> Address     : " + re.getPeerAddress());
                System.out.println("> Source      : " + re.getSource());
                System.out.println("> User object : " + re.getUserObject());
            } else if (responsePDU.getVariableBindings() != null) {
                for (VariableBinding vb : responsePDU.getVariableBindings()) {
                    System.out.println("2nd Server >> " + vb.getOid() + " --> " + vb.getVariable());
                }
            }
        }

    }
}
1

There are 1 best solutions below

0
On
    TransportMapping<UdpAddress> transport = new DefaultUdpTransportMapping();
    Snmp snmp = new Snmp(transport);
    USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
    SecurityModels.getInstance().addSecurityModel(usm);
    // add user to the USM
    snmp.getUSM().addUser(new OctetString(userName), new UsmUser(new OctetString(userName), authProtocol,
            new OctetString(authPassphrase), privProtocol, new OctetString(privPassphrase)));

these codes should be modified:

TransportMapping<UdpAddress> transport = new DefaultUdpTransportMapping();
Snmp snmp = new Snmp(new MessageDispatcherImpl(), transport);
SecurityProtocols.getInstance().addDefaultProtocols();
USM usm = new USM(SecurityProtocols.getInstance(), new 
OctetString(MPv3.createLocalEngineID()), 0);
SecurityModels.getInstance().addSecurityModel(usm);
usm.addUser(new OctetString(userName), new UsmUser(new OctetString(userName),authProtocol,new OctetString(authPassphrase), privProtocol,new OctetString(privPassphrase)));
MPv3 mPv3 = new MPv3(usm);
snmp.getMessageDispatcher().addMessageProcessingModel(mPv3);