天天看點

SNMP4J學習總結(SNMPv3)一、SNMP4J實作v3程式設計與v1/v2的差別

一、SNMP4J實作v3程式設計與v1/v2的差別

使用SNMP4J可以很友善的實作一個SNMP NMS的功能。 SNMPv3與SNMPv1/v2相比不同點有:

  1. 需要建立USM對象并添加User。
  2. 需要建立UserTarget對象,而不是建立CommunityTarget對象。
  3. 需要建立ScopedPDU對象,而不是PDU對象。

二、使用SNMP4J進行SNMPv3程式設計的步驟

  1. 建立Snmp對象snmp。
  2. 建立USM對象,并建立User,添加到USM對象中。 建立User是需要指定securityName,認證協定MD5/SHA1,認證密鑰,加密算法DES/AES,加密密鑰。 添加User到USM對象中時候,可以指定engineID也可以不指定。
  3. 建立UserTarget對象target,并指定version, address, timeout, retry等參數,這些和SNMPv1/v2相同。 另外還必須指定SNMPv3特有的兩個參數SecurityLevel和SecurityName。 SNMP4J會根據這個SecurityName到USM的UserTable中查找比對的User,用這個User的資訊進行認證加密處理。 查找的時候必須同時比對SecurityName和engineID,但是如果添加User到USM對象中時候,沒有指定engineID,那麼SecurityName相同即比對成功。
  4. 建立ScopedPDU對象pdu,并指定操作類型(GET/GETNEXT/GETBULK/SET), 添加VariableBinding(也就是待操作的OID), 如果是GETBULK操作,還可以指定MaxRepetitions和NonRepeaters。 注意一定要指定MaxRepetitions,預設值是0,那樣不會傳回任何結果。 如果agent上設定的contextEngineId和snmpEngineId不一緻,那麼需要調用ScopedPDU.setContextEngineID()方法設定contextEngineId。 如果agent上設定了contextName,那麼需要調用ScopedPDU.setContextName()方法設定contextName。
  5. 調用snmp.send(pdu, target)方法,發送請求請傳回結果。

對于SNMPv3,仍然可以調用TableUtils類實作一個SNMP Walk的功能。 但是如果需要指定contextEngineId和contextName, 那麼不能使用DefaultPDUFactory,可以從它繼承并覆寫它的createPDU方法。 異步的send方法支援和SNMPv1/v2類似。

三、實作

下面的代碼執行個體實作了GET, Walk操作, 其他GETNEXT, GETBULK, SET操作類似。

 import java.io.IOException;
 import java.util.List;
 import java.util.Vector;
 ​
 import org.snmp4j.PDU;
 import org.snmp4j.ScopedPDU;
 import org.snmp4j.Snmp;
 import org.snmp4j.Target;
 import org.snmp4j.UserTarget;
 import org.snmp4j.event.ResponseEvent;
 import org.snmp4j.mp.MPv3;
 import org.snmp4j.mp.SnmpConstants;
 import org.snmp4j.security.AuthMD5;
 import org.snmp4j.security.PrivDES;
 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;
 ​
 public class SNMPv3Test {
     public static void main(String[] args) throws IOException, InterruptedException {
     Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
     USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
     SecurityModels.getInstance().addSecurityModel(usm);
     snmp.listen();
     
     // Add User
     UsmUser user = new UsmUser(
             new OctetString("nmsAdmin"),
             AuthMD5.ID, new OctetString("nmsAuthKey"),
             PrivDES.ID, new OctetString("nmsPrivKey"));
     //If the specified SNMP engine id is specified, this user can only be used with the specified engine ID
     //So if it's not correct, will get an error that can't find a user from the user table.
     //snmp.getUSM().addUser(new OctetString("nmsAdmin"), new OctetString("0002651100"), user);
     snmp.getUSM().addUser(new OctetString("nmsAdmin"), user);
     
     UserTarget target = new UserTarget();
     target.setVersion(SnmpConstants.version3);
     target.setAddress(new UdpAddress("192.168.0.100/161"));
     target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
     target.setSecurityName(new OctetString("nmsAdmin"));
     target.setTimeout(3000);    //3s
     target.setRetries(0);
             
     OctetString contextEngineId = new OctetString("0002651100[02]");
     sendRequest(snmp, createGetPdu(contextEngineId), target);
     snmpWalk(snmp, target, contextEngineId);
 }
 ​
 private static PDU createGetPdu(OctetString contextEngineId) {
     ScopedPDU pdu = new ScopedPDU();
     pdu.setType(PDU.GET);
     pdu.setContextEngineID(contextEngineId);    //if not set, will be SNMP engine id
     //pdu.setContextName(contextName);  //must be same as SNMP agent
     
     pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.3.0"))); //sysUpTime
     pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.5.0"))); //sysName
     pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.5")));   //expect an no_such_instance error
     return pdu;
 }
 ​
 private static void sendRequest(Snmp snmp, PDU pdu, UserTarget target)
 throws IOException {
     ResponseEvent responseEvent = snmp.send(pdu, target);
     PDU response = responseEvent.getResponse();
     
     if (response == null) {
         System.out.println("TimeOut...");
     } else {
         if (response.getErrorStatus() == PDU.noError) {
             Vector<? extends VariableBinding> vbs = response.getVariableBindings();
             for (VariableBinding vb : vbs) {
                 System.out.println(vb + " ," + vb.getVariable().getSyntaxString());
             }
         } else {
             System.out.println("Error:" + response.getErrorStatusText());
         }
     }
 }
 ​
 private static void snmpWalk(Snmp snmp, UserTarget target, OctetString contextEngineId) {
     TableUtils utils = new TableUtils(snmp,
             new MyDefaultPDUFactory(PDU.GETNEXT, //GETNEXT or GETBULK)
                                     contextEngineId));
     utils.setMaxNumRowsPerPDU(5);   //only for GETBULK, set max-repetitions, default is 10
     OID[] columnOids = new OID[] {
             new OID("1.3.6.1.2.1.1.9.1.2"), //sysORID
             new OID("1.3.6.1.2.1.1.9.1.3")  //sysORDescr
     };
     // If not null, all returned rows have an index in a range (lowerBoundIndex, upperBoundIndex]
     List<TableEvent> l = utils.getTable(target, columnOids, new OID("3"), new OID("10"));
     for (TableEvent e : l) {
         System.out.println(e);
     }
 }
 ​
 private static class MyDefaultPDUFactory extends DefaultPDUFactory {
     private OctetString contextEngineId = null;
     
     public MyDefaultPDUFactory(int pduType, OctetString contextEngineId) {
         super(pduType);
         this.contextEngineId = contextEngineId;
     }
  
     @Override
     public PDU createPDU(Target target) {
         PDU pdu = super.createPDU(target);
         if (target.getVersion() == SnmpConstants.version3) {
             ((ScopedPDU)pdu).setContextEngineID(contextEngineId);
         }
         return pdu;
     }       
 }
 }           

四、參考網址

原文連結

繼續閱讀