Use context name with snmp4j

Hi
Sorry i’m a very noob with snmp specs and with snmp4f but i’m trying to create a little main program to get all key/value for table for one OID and i have problem when using context name.
If i use it without context for other parameters, it works but with context, always time out.
I have added a way to call snmpwalk command with Process class and I have not problem with context : i get all key/values.

Is-it possible to check my main program if i give you my little main?

here is my little prg : thanks

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.CopyOnWriteArrayList;

import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.UserTarget;
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.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.DefaultPDUFactory;
import org.snmp4j.util.TableEvent;
import org.snmp4j.util.TableUtils;

//        java -cp snmp4j-3.8.2.jar GetTableTest.java <host> <port> <securityName> <serverAuthPassphrase> <serverPrivatePassphrase> <oid> <context>

public class GetTableTest {

    public static void main(String[] args) throws Exception {
        String host = args[0];
        String port = args[1];
        String securityName = args[2];
        String serverAuthPassphrase = args[3];
        String serverPrivatePassphrase = args[4];
        String oid = args[5];
        String context = args[6];

        // with snmp4j
		Map<String, Object> table = getTable(host, port, securityName, serverAuthPassphrase, serverPrivatePassphrase, oid, context);
        table.forEach((key, value) -> System.out.println(key+"="+value));

		// with snmpwalk
        table =getTableWithShellCmd(host, port, securityName, serverAuthPassphrase, serverPrivatePassphrase, oid, context);
        table.forEach((key, value) -> System.out.println(key+"="+value));
    }

    public static Map<String, Object> getTableWithShellCmd(String host, String port, String securityName,
            String serverAuthPassphrase,
            String serverPrivatePassphrase,
            String oid,
            String context) throws Exception
    {
        Map<String, Object> result = new TreeMap<>();


        ProcessBuilder processBuilder = new ProcessBuilder("snmpwalk", "-On", "-v3", "-l", "authPriv", "-u", securityName, "-a", "SHA", "-A", serverPrivatePassphrase,
                "-x", "AES", "-X", serverPrivatePassphrase, "-n", context, host+":"+port, oid);

        Process process = processBuilder.start();

        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line;

        while ((line = reader.readLine()) != null) {
//            System.out.println(line);
            int index = line.indexOf("=");
            if (index != -1) {
                String key = line.substring(0, index-1).trim();
                index = line.indexOf(":");
                if (index != -1) {
                    String value = line.substring(index+1).trim();
                    if (key.startsWith(".")) {
                        key = key.substring(1);
                    }
                    result.put(key, value);
                }
            }
        }

        reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
        while ((line = reader.readLine()) != null) {
            System.err.println("ERROR "+line);
        }

        int exitVal = process.waitFor();
        System.out.println("exitVal "+exitVal);

        return result;
    }

    public static Map<String, Object> getTable(String host, String port, String securityName,
            String serverAuthPassphrase,
            String serverPrivatePassphrase,
            String oid,
            String context) throws IOException {

        DefaultUdpTransportMapping transportMapping = new DefaultUdpTransportMapping();

        // create an SNMP core with a unique engine ID and with User Based SecurityModel
        Snmp snmp = new Snmp(transportMapping);
        OctetString engineID = new OctetString(MPv3.createLocalEngineID());
        USM usm = new USM(SecurityProtocols.getInstance(), engineID, 0);
        usm.setEngineDiscoveryEnabled(true);

        SecurityModels.getInstance().addSecurityModel(usm);

        SecurityProtocols.getInstance().addAuthenticationProtocol(new AuthSHA());

        transportMapping.listen();

        Map<String, Object> result = new TreeMap<>();

        final UserTarget<UdpAddress> target = new UserTarget<>();
        target.setVersion(SnmpConstants.version3);

        target.setAddress(new UdpAddress(String.format("%s/%s", host, port)));
        target.setSecurityLevel(SecurityLevel.AUTH_PRIV);

        target.setSecurityName(new OctetString(securityName));
        target.setTimeout(1500);
        target.setRetries(2);

        final UsmUser usmUser = new UsmUser(new OctetString(securityName), AuthSHA.ID,
                new OctetString(serverAuthPassphrase), PrivAES128.ID, new OctetString(serverPrivatePassphrase));

        // add user in the model only if not exists
        if (!snmp.getUSM().hasUser(engineID, usmUser.getSecurityName())) {
            snmp.getUSM().addUser(usmUser);
        }

        final OctetString contextName = context.isEmpty()? new OctetString() : new OctetString(context);
        System.out.println("contextName "+contextName);

        TableUtils tUtils = new TableUtils(snmp, new DefaultPDUFactory(PDU.GET, engineID, contextName));

        OID[] oids = { new OID(oid) };

        // Manage concurrent access for iteration
        long time = System.currentTimeMillis();
        List<TableEvent> tableEventList = tUtils.getTable(target, oids, null, null);
        System.out.println("TIME="+(System.currentTimeMillis()-time));
        CopyOnWriteArrayList<TableEvent> cptbEventLst;
        synchronized (tableEventList) {
            cptbEventLst = new CopyOnWriteArrayList<>(new ArrayList<>(tableEventList));
        }
        for (TableEvent tableEvent : cptbEventLst) {

            // Treat one by one SNMP data without stopping treatment for others if error
            if (tableEvent.isError()) {
                System.err.println("tableEvent.isError() " + tableEvent.getErrorMessage() + " "
                        + tableEvent.getException() + " " + tableEvent.getStatus());
                continue;
            }

            VariableBinding[] vbArrays = tableEvent.getColumns();
            for (VariableBinding vb : vbArrays) {
                result.put(vb.getOid().toString(), vb.getVariable());
            }
        }

        snmp.close();

        return result;
    }

}

What SNNP4J version are you using?
In versions >2.5.0 TableUtils (DefaultPDUFactory) with non-default context name should work.

Hi

I use 3.8.2 version

Ok, then the problem is most likely not related to SNMP4J functionality.

thanks so i’m not misusing the snmp4j library?

You are not obviously using it in a wrong way :wink: