2016-08-09 25 views
1

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?

Antwort

1

Sie erhalten so genannte SNMP REPORT PDU. Was passiert, ist, dass der Agent die Anfrage-PDU vom Manager empfängt und feststellt, dass einige wichtige Sicherheitsattribute wie engine_id, engine_boots und engine_time fehlen, und sendet einen REPORT zurück, um den Manager darüber zu informieren. Der Manager sollte die REPORT-PDU in Übereinstimmung mit dem so genannten SNMP-Engine-Discovery-Verfahren verarbeiten, das detailliert in https://tools.ietf.org/html/rfc5343 beschrieben ist.

0

Für Frage 1, wenn ich den securityName & securityLevel des userTarget, funktionierte es richtig.

 userTarget.setSecurityName(new OctetString(_V3_USERNAME)); 
     userTarget.setSecurityLevel(SecurityLevel.AUTH_PRIV); 

Und so für Frage 2, es ist das gleiche mit der Version 1 & 2c jetzt.

Referenz: rfc3414:

3) Wenn der Wert des msgAuthoritativeEngineID Feld in den securityParameters unbekannt ist dann: a) eine nicht autorisierende SNMP-Engine, die Entdeckung führt möglicherweise optional einen neuen Eintrag in der lokalen Konfiguration Datastore (LCD) und die Verarbeitung fortsetzen; oder b) die usmStatsUnknownEngineIDs Zähler inkrementierten und eine Fehleranzeige (unknownEngineID) zusammen mit dem OID und Wert des inkrementierten Zählers wird an die rufenden Modul zurückgegeben.