SNMP4J学习总结(SNMPv3)

一、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;
     }       
 }
 }

四、参考网址

原文链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值