SNMP4Jを使ってsnmpv3のGET PDUをシミュレートすると、存在しないOIDを変数バインディングリストに追加しても、有効な応答が得られることがわかりました。
しかし、プロトコルのバージョンがv1,の場合は、エラーコード2が表示されますが、「そのような名前はありません」という意味です。
プロトコルバージョンがV2C、あるとき、私はERRORを取得し、VBリストのサイズを返されませんでしたが1であり、リスト(0)変数の結合構文は、 『そのようなオブジェクト』を意味しない例外です。
だから私はv1またはv2cのを使用している場合、それが存在するかどうかを把握することができますが、それはV3だとき、私は次の応答を得た:snmpv3が存在しないOIDで正常にPDUを返すのはなぜですか?
SNMP-USER-BASED-SM-MIB::usmStatsUnknownEngineIDs.0 = Counter32: xx
** XX番号です。
コードは次のとおりです。
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;
}
}
だから私の質問は次のとおりです。
(1)正しく実装V3のこの振る舞いですか?なぜ私は何らかのエラーを起こさなかったのですか?
(2)SNMP4Jを使用してOIDが存在するかどうかをテストするにはどうすればよいですか?