资源描述
使用SNMP4J可以很方便的实现一个SNMP NMS的功能。
对于SNMPv1/SNMPv2,简单的说,只需要以下几个步骤
1) 创建Snmp对象snmp
2) 创建CommunityTarget对象target,并指定community, version, address, timeout, retry等参数。
3) 创建PDU对象pdu,并指定操作类型(GET/GETNEXT/GETBULK/SET), 添加VariableBinding(也就是待操作的OID),
如果是GETBULK操作,还可以指定MaxRepetitions和NonRepeaters。
注意一定要指定MaxRepetitions,默认值是0,那样不会返回任何结果。
4) 调用snmp.send(pdu, target)方法,发送请求请返回结果。
此外,SNMP4J提供了TableUtils类,可以很轻松的实现一个SNMP Walk的功能,比如一次返回一个表格下面的所有MIB值。
TableUtils类还支持指定ower bound index 和 upper bound index, 得到更小范围的结果以提高性能。这一点对于从一个很多行的表中取一部分行的数据来说很重要。
Snmp还支持异步的send方法。
下面的代码实例实现了GET, GETNEXT, GETBULK, Walk, SET操作,
以及一个利用异步send方法实现的agent discovery: 对一个广播地址发送请求,等待agent返回的应答。
如果需要对一个范围内的IP进行扫描,可以稍加改进,反复调用异步send多次发送给不同IP。
[java] view plaincopyprint?
1. import java.io.IOException;
2. import java.util.List;
3. import java.util.Vector;
4.
5. import org.snmp4j.CommunityTarget;
6. import org.snmp4j.PDU;
7. import org.snmp4j.Snmp;
8. import org.snmp4j.event.ResponseEvent;
9. import org.snmp4j.event.ResponseListener;
10. import org.snmp4j.mp.SnmpConstants;
11. import org.snmp4j.smi.OID;
12. import org.snmp4j.smi.OctetString;
13. import org.snmp4j.smi.UdpAddress;
14. import org.snmp4j.smi.VariableBinding;
15. import org.snmp4j.transport.DefaultUdpTransportMapping;
16. import org.snmp4j.util.DefaultPDUFactory;
17. import org.snmp4j.util.TableEvent;
18. import org.snmp4j.util.TableUtils;
19.
20. public class SNMPv2Test {
21. public static void main(String[] args) throws IOException, InterruptedException {
22. Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
23. snmp.listen();
24.
25. CommunityTarget target = new CommunityTarget();
26. target.setCommunity(new OctetString("public"));
27. target.setVersion(SnmpConstants.version2c);
28. target.setAddress(new UdpAddress("192.168.0.100/161"));
29. target.setTimeout(3000); //3s
30. target.setRetries(1);
31.
32. sendRequest(snmp, createGetPdu(), target);
33. sendRequest(snmp, createGetNextPdu(), target);
34. sendRequest(snmp, createGetBulkPdu(), target);
35. snmpWalk(snmp, target);
36.
37. target.setCommunity(new OctetString("private"));
38. sendRequest(snmp, createSetPdu(), target);
39.
40. CommunityTarget broadcastTarget = new CommunityTarget();
41. broadcastTarget.setCommunity(new OctetString("public"));
42. broadcastTarget.setVersion(SnmpConstants.version2c);
43. broadcastTarget.setAddress(new UdpAddress("192.168.0.255/161"));
44. broadcastTarget.setTimeout(5000); //5s
45. sendAsyncRequest(snmp, createGetNextPdu(), broadcastTarget);
46. Thread.sleep(6000); //main thread wait 6s for the completion of asynchronous request
47. }
48.
49. private static PDU createGetPdu() {
50. PDU pdu = new PDU();
51. pdu.setType(PDU.GET);
52. pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.3.0"))); //sysUpTime
53. pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.5.0"))); //sysName
54. pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.5"))); //expect an no_such_instance error
55. return pdu;
56. }
57.
58. private static PDU createGetNextPdu() {
59. PDU pdu = new PDU();
60. pdu.setType(PDU.GETNEXT);
61. pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.3"))); //sysUpTime
62. pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.5"))); //sysName
63.
64. return pdu;
65. }
66.
67. private static PDU createGetBulkPdu() {
68. PDU pdu = new PDU();
69. pdu.setType(PDU.GETBULK);
70. pdu.setMaxRepetitions(10); //must set it, default is 0
71. pdu.setNonRepeaters(0);
72. pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1"))); //system
73. return pdu;
74. }
75.
76. private static PDU createSetPdu() {
77. PDU pdu = new PDU();
78. pdu.setType(PDU.SET);
79. pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.5.0"), new OctetString("sysname"))); //sysName
80. return pdu;
81. }
82.
83. private static void sendRequest(Snmp snmp, PDU pdu, CommunityTarget target)
84. throws IOException {
85. ResponseEvent responseEvent = snmp.send(pdu, target);
86. PDU response = responseEvent.getResponse();
87.
88. if (response == null) {
89. System.out.println("TimeOut...");
90. } else {
91. if (response.getErrorStatus() == PDU.noError) {
92. Vector<? extends VariableBinding> vbs = response.getVariableBindings();
93. for (VariableBinding vb : vbs) {
94. System.out.println(vb + " ," + vb.getVariable().getSyntaxString());
95. }
96. } else {
97. System.out.println("Error:" + response.getErrorStatusText());
98. }
99. }
100. }
101.
102. private static void sendAsyncRequest(Snmp snmp, PDU pdu, CommunityTarget target)
103. throws IOException {
104. snmp.send(pdu, target, null, new ResponseListener(){
105.
106. @Override
107. public void onResponse(ResponseEvent event) {
108. PDU response = event.getResponse();
109. System.out.println("Got response from " + event.getPeerAddress());
110. if (response == null) {
111. System.out.println("TimeOut...");
112. } else {
113. if (response.getErrorStatus() == PDU.noError) {
114. Vector<? extends VariableBinding> vbs = response.getVariableBindings();
115. for (VariableBinding vb : vbs) {
116. System.out.println(vb + " ," + vb.getVariable().getSyntaxString());
117. }
118. } else {
119. System.out.println("Error:" + response.getErrorStatusText());
120. }
121. }
122. }});
123. }
124.
125. private static void snmpWalk(Snmp snmp, CommunityTarget target) {
126. TableUtils utils = new TableUtils(snmp, new DefaultPDUFactory(PDU.GETBULK));//GETNEXT or GETBULK
127. utils.setMaxNumRowsPerPDU(5); //only for GETBULK, set max-repetitions, default is 10
128. OID[] columnOids = new OID[] {
129. new OID("1.3.6.1.2.1.1.9.1.2"), //sysORID
130. new OID("1.3.6.1.2.1.1.9.1.3"), //sysORDescr
131. new OID("1.3.6.1.2.1.1.9.1.5") //wrong OID, expect an null in in VariableBinding array
132. };
133. // If not null, all returned rows have an index in a range (lowerBoundIndex, upperBoundIndex]
134. List<TableEvent> l = utils.getTable(target, columnOids, new OID("3"), new OID("10"));
135. for (TableEvent e : l) {
136. System.out.println(e);
137. }
138. }
139. }
对于SNMPv3,不同点有
1) 需要创建USM对象并添加User,
关于USM->
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操作类似。
[java] view plaincopyprint?
1. import java.io.IOException;
2. import java.util.List;
3. import java.util.Vector;
4.
5. import org.snmp4j.PDU;
6. import org.snmp4j.ScopedPDU;
7. import org.snmp4j.Snmp;
8. import org.snmp4j.Target;
9. import org.snmp4j.UserTarget;
10. import org.snmp4j.event.ResponseEvent;
11. import org.snmp4j.mp.MPv3;
12. import org.snmp4j.mp.SnmpConstants;
13. import org.snmp4j.security.AuthMD5;
14. import org.snmp4j.security.PrivDES;
15. import org.snmp4j.security.SecurityLevel;
16. import org.snmp4j.security.SecurityModels;
17. import org.snmp4j.security.SecurityProtocols;
18. import org.snmp4j.security.USM;
19. import org.snmp4j.security.UsmUser;
20. import org.snmp4j.smi.OID;
21. import org.snmp4j.smi.OctetString;
22. import org.snmp4j.smi.UdpAddress;
23. import org.snmp4j.smi.VariableBinding;
24. import org.snmp4j.transport.DefaultUdpTransportMapping;
25. import org.snmp4j.util.DefaultPDUFactory;
26. import org.snmp4j.util.TableEvent;
27. import org.snmp4j.util.TableUtils;
28.
29. public class SNMPv3Test {
30. public static void main(String[] args) throws IOException, InterruptedException {
31.
32. Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
33. USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
34. SecurityModels.getInstance().addSecurityModel(usm);
35. snmp.listen();
36.
37. // Add User
38. UsmUser user = new UsmUser(
39. new OctetString("nmsAdmin"),
40. AuthMD5.ID, new OctetString("nmsAuthKey"),
41. PrivDES.ID, new OctetString("nmsPrivKey"));
42. //If the specified SNMP engine id is specified, this user can only be used with the specified engine ID
43. //So if it's not correct, will get an error that can't find a user from the user table.
44. //snmp.getUSM().addUser(new OctetString("nmsAdmin"), new OctetString("0002651100"), user);
45. snmp.getUSM().addUser(new OctetString("nmsAdmin"), user);
46.
47. UserTarget target = new UserTarget();
48. target.setVersion(SnmpConstants.version3);
49. target.setAddress(new UdpAddress("192.168.0.100/161"));
50. target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
51. target.setSecurityName(new OctetString("nmsAdmin"));
52. target.setTimeout(3000); //3s
53. target.setRetries(0);
54.
55. OctetString contextEngineId = new OctetString("0002651100[02]");
56. sendRequest(snmp, createGetPdu(contextEngineId), target);
57. snmpWalk(snmp, target, contextEngineId);
58. }
59.
60. private static PDU createGetPdu(OctetString contextEngineId) {
61. ScopedPDU pdu = new ScopedPDU();
62. pdu.setType(PDU.GET);
63. pdu.setContextEngineID(contextEngineId); //if not set, will be SNMP engine id
64. //pdu.setContextName(contextName); //must be same as SNMP agent
65.
66. pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.3.0"))); //sysUpTime
67. pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.5.0"))); //sysName
68. pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.5"))); //expect an no_such_instance error
69. return pdu;
70. }
71.
72. private static void sendRequest(Snmp snmp, PDU pdu, UserTarget target)
73. throws IOException {
74. ResponseEvent responseEvent = snmp.send(pdu, target);
75. PDU response = responseEvent.getResponse();
76.
77. if (response == null) {
78. System.out.println("TimeOut...");
79. } else {
80. if (response.getErrorStatus() == PDU.noError) {
81. Vector<? extends VariableBinding> vbs = response.getVariableBindings();
82. for (VariableBinding vb : vbs) {
83. System.out.println(vb + " ," + vb.getVariable().getSyntaxString());
84. }
85. } else {
86. System.out.println("Error:" + response.getErrorStatusText());
87. }
88. }
89. }
90.
91. private static void snmpWalk(Snmp snmp, UserTarget target, OctetString contextEngineId) {
92. TableUtils utils = new TableUtils(snmp,
93. new MyDefaultPDUFactory(PDU.GETNEXT, //GETNEXT or GETBULK)
94. contextEngineId));
95. utils.setMaxNumRowsPerPDU(5); //only for GETBULK, set max-repetitions, default is 10
96. OID[] columnOids = new OID[] {
97. new OID("1.3.6.1.2.1.1.9.1.2"), //sysORID
98. new OID("1.3.6.1.2.1.1.9.1.3") //sysORDescr
99. };
100. // If not null, all returned rows have an index in a range (lowerBoundIndex, upperBoundIndex]
101. List<TableEvent> l = utils.getTable(target, columnOids, new OID("3"), new OID("10"));
102. for (TableEvent e : l) {
103. System.out.println(e);
104. }
105. }
106.
107. private static class MyDefaultPDUFactory extends DefaultPDUFactory {
108. private OctetString contextEngineId = null;
109.
110. public MyDefaultPDUFactory(int pduType, OctetString contextEngineId) {
111. super(pduType);
112. this.contextEngineId = contextEngineId;
113. }
114.
115. @Override
116. public PDU createPDU(Target target) {
117. PDU pdu = super.createPDU(target);
118. if (target.getVersion() == SnmpConstants.version3) {
119. ((ScopedPDU)pdu).setContextEngineID(contextEngineId);
120. }
121. return pdu;
122. }
123. }
124. }
import java.io.IOException;
import java.util.
展开阅读全文