Wenn ich SNMP4J verwenden, um die GET PDU des SNMPv3 zu simulieren, stellte ich fest, dass obwohl ich eine nicht existierende OID zu der Variablenbindungsliste hinzufüge, ich eine gültige Antwort weiterhin erhalte.
Aber wenn die Protokollversion ist v1, Ich habe den Fehlercode 2, bedeutet 'kein solcher Name'.
Wenn die Protokollversion ist v2c, Ich habe nicht FEHLER, und zurückgegeben Vb Liste Größe ist 1, und die Liste (0) Variable Binding 's Syntax ist Ausnahme, was bedeutet "keine solche Objekt".
So kann ich herausfinden, ob es existiert oder nicht, wenn die v1 oder v2c verwenden, aber wenn es v3 ist, bekam ich folgende Antwort:Warum snmpv3 erhalten PDU erfolgreich mit einer nicht vorhandenen OID zurückgegeben?
SNMP-USER-BASED-SM-MIB::usmStatsUnknownEngineIDs.0 = Counter32: xx
** xx ist eine Zahl.
Der Code ist:
import org.snmp4j.*;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.*;
import org.snmp4j.smi.*;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import static org.snmp4j.mp.MPv3.createLocalEngineID;
/**
*
* Following syntax may helpfull: SMIConstants
* public static final int EXCEPTION_NO_SUCH_OBJECT = BER.NOSUCHOBJECT;
* public static final int EXCEPTION_NO_SUCH_INSTANCE = BER.NOSUCHINSTANCE;
* public static final int EXCEPTION_END_OF_MIB_VIEW = BER.ENDOFMIBVIEW;
*
* give a string and test whether it exists or not
*
* Conclusions:
* (1)When the op is GET,
* V1:
* errorcode at pdu, AND IS 2, MEANS "no such name"
* V2C:
* NOT GET ERROR, and returned vb list size is 1, and the list(0) Null.isExceptionSyntax(vb.getSyntax()) == true // means "no such object"
* V3:
* NOT GET ERROR, like this : SNMP-USER-BASED-SM-MIB::usmStatsUnknownEngineIDs.0 = Counter32: 23
* returned varbingds : 1.3.6.1.6.3.15.1.1.3.0 = xxx
* (2)When the op is GETNEXT:
* V1:
* errorcode at pdu, AND IS 2, MEANS "no such name"
* V2C:
* NOT GET ERROR, and returned vb list size is 1, and the list(0) Null.isExceptionSyntax(vb.getSyntax()) == true // means "endOfMibView"
* V3:
* NOT GET ERROR, like this : SNMP-USER-BASED-SM-MIB::usmStatsUnknownEngineIDs.0 = Counter32: 23
* (3)When the op is GETBULK:
*
* Created by edward.gao on 8/9/16.
*/
public class TestOidExists {
private static final String _V1_OR_V2_COMMUNITYNAME= "public";
private static final String _V3_USERNAME = "edward";
/**
* authentication protocol MD5 or SHA
*/
private static final String _V3_AUTHENTICATION_PASSPHRASE = "auth12345678";
/**
* privacy protocol DES OR AES
*/
private static final String _V3_PRIVACY_PASSPHRASE = "encry12345678";
public static void main(String[] args) throws Exception{
final String addrString= "udp:192.168.170.150/161";
byte [] localEngineID = createLocalEngineID();
//version3 need usm
USM usm = new USM(SecurityProtocols.getInstance(),new OctetString(localEngineID), 0);
SecurityModels.getInstance().addSecurityModel(usm);
Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
snmp.listen();
String [] oids = new String[] {/*".1.3.6.1.2.1.1.5.0", ".1.3.6.1.2.1.25.6.3.1.2", ".1.3.6.1.2.1.1.5",*/ ".1.3.999"};
String [] types = new String[]{ "get","getnext", "getbulk"};
for (String oid : oids)
{
for (String type : types) {
System.out.println(String.format("VERSION IS 3, oid:%s result: %d", oid, typeOfOID(oid, snmp, SnmpConstants.version3, type)));
System.out.println(String.format("VERSION IS 2, oid:%s result: %d", oid, typeOfOID(oid, snmp, SnmpConstants.version2c, type)));
System.out.println(String.format("VERSION IS 1, oid:%s result: %d", oid, typeOfOID(oid, snmp, SnmpConstants.version1, type)));
}
}
}
/**
* get the type of matched oid string
* @param oid
* @param snmp
* @return -1 : not exist , 0, leaf, 1, tree
*/
public static int typeOfOID(String oid , Snmp snmp, int version, String typeString) throws Exception
{
boolean isv3 = version == SnmpConstants.version3;
//build a client
Address addr = GenericAddress.parse("192.168.170.150/161");
Target target = null;
if (isv3) {
UsmUser usmUser = new UsmUser(new OctetString(_V3_USERNAME),
AuthMD5.ID,
new OctetString(_V3_AUTHENTICATION_PASSPHRASE),
PrivDES.ID,
new OctetString(_V3_PRIVACY_PASSPHRASE)
);
snmp.getUSM().addUser(usmUser);
target = new UserTarget();
}
else
{
target = new CommunityTarget();
//the default version is 3
if (version == SnmpConstants.version2c)
{
target.setVersion(SnmpConstants.version2c);
}
else
{
target.setVersion(SnmpConstants.version1);
}
((CommunityTarget)target).setCommunity(new OctetString("public"));
}
target.setAddress(addr);
target.setRetries(2);
target.setTimeout(30000);
int type = typeString.equalsIgnoreCase("get") ? PDU.GET : (typeString.equalsIgnoreCase("getnext") ? PDU.GETNEXT : PDU.GETBULK);
System.out.println("Using version " + (version == SnmpConstants.version1 ? "v1" :(version == SnmpConstants.version2c ? "v2c " : "v3 ")) + " type:" + typeString);
PDU pdu = version == SnmpConstants.version3 ? new ScopedPDU() : new PDU();
pdu.setType(type);
pdu.add(new VariableBinding(new OID(oid)));
pdu.setRequestID(new Integer32(0));
ResponseEvent responseEvent = snmp.send(pdu, target);
if (responseEvent.getError() == null)
{
PDU responsePdu = responseEvent.getResponse();
if (responsePdu.getErrorStatus() == 0)
{
responsePdu.getVariableBindings().forEach(vb ->System.out.print(vb + " " + Null.isExceptionSyntax(vb.getSyntax())));
System.out.println();
//leaf get only one, other get more than one
return responsePdu.getVariableBindings().size() == 1 ? 0 : 1;
}
else
{
System.out.println("error code at pdu," + responsePdu.getErrorStatus() + " text:" + responsePdu.getErrorStatusText() + " index:" + responsePdu.getErrorIndex());
}
}
else
{
System.out.println("error happend,");
responseEvent.getError().printStackTrace();
}
return -1;
}
}
Also meine Frage ist:
(1) Ist das Verhalten von v3 richtig umgesetzt? Warum habe ich keinen Fehler bekommen?
(2) Wie kann ich mit SNMP4J testen, ob die OID existiert oder nicht?