Article directory
- code
- Verification results on actual machines
Code
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.snmp4j.CommunityTarget; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.event.ResponseEvent; import org.snmp4j.event.ResponseListener; import org.snmp4j.mp.SnmpConstants; import org.snmp4j.smi.*; import org.snmp4j.transport.DefaultUdpTransportMapping; import java.io.IOException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * qipengshang <2023-5-16> */ @Slf4j public class SnmpUtil {<!-- --> /*Default parameters */ public static final int DEFAULT_VERSION = SnmpConstants.version2c; //Default SNMP version public static final String DEFAULT_PROTOCOL = "udp"; //Default transport protocol public static final int DEFAULT_PORT = 161; //Default port number public static final long DEFAULT_TIMEOUT = 3 * 1000L; //Default timeout (milliseconds) public static final int DEFAULT_RETRY = 3; //Default number of retries /** * Create CommunityTarget object * * @return CommunityTarget */ public static CommunityTarget createDefault(String ip, String community) {<!-- --> // Create a CommunityTarget object based on IP and community string Address address = GenericAddress.parse(DEFAULT_PROTOCOL + ":" + ip + "/" + DEFAULT_PORT); // Parse the Address object based on the default transmission protocol, IP address and port number CommunityTarget target = new CommunityTarget(); // Create CommunityTarget object target.setCommunity(new OctetString(community)); // Set community target.setAddress(address); //Set Address target.setVersion(DEFAULT_VERSION); // Set SNMP version target.setTimeout(DEFAULT_TIMEOUT); // Set timeout target.setRetries(DEFAULT_RETRY); //Set the number of retries return target; } /* getting information */ public static JSONArray snmpGet(String ip, String community, String oid) {<!-- --> // Implement SNMP GET operation and obtain the corresponding variable value according to OID CommunityTarget target = createDefault(ip, community); // Create CommunityTarget object JSONArray jsonArray = new JSONArray(); // Create JSONArray object Snmp snmp = null; // Create Snmp object try {<!-- --> PDU pdu = new PDU(); // Create PDU object pdu.add(new VariableBinding(new OID(oid))); // Add VariableBinding DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping(); // Create a DefaultUdpTransportMapping object snmp = new Snmp(transport); // Create Snmp object snmp.listen(); // Start SNMP service log.info("-------> Send PDU <-------"); // Output log information pdu.setType(PDU.GET); //Set the PDU type to GET ResponseEvent respEvent = snmp.send(pdu, target); //Send PDU and return response event log.info("PeerAddress:" + respEvent.getPeerAddress()); // Output log information PDU response = respEvent.getResponse(); // Get the response PDU if (response == null) {<!-- --> // If the response is empty log.info("response is null, request time out"); // Output log information } else {<!-- --> log.info("response pdu size is " + response.size()); // Output log information for (int i = 0; i < response.size(); i + + ) {<!-- --> // Traverse the VariableBinding in the response VariableBinding vb = response.get(i); JSONObject jsonObject = new JSONObject(); // Create JSONObject object jsonObject.put("oid", vb.getOid().toString()); // Add OID string to JSONObject jsonObject.put("value", vb.getVariable().toString()); // Add variable value to JSONObject jsonArray.add(jsonObject); // Add JSONObject to JSONArray // log.info(vb.getOid() + " = " + vb.getVariable()); } } log.info("SNMP GET one OID value finished!"); // Output log information return jsonArray; } catch (Exception e) {<!-- --> // Catch exceptions e.printStackTrace(); // Output exception stack information log.info("SNMP Get Exception:" + e); // Output log information } finally {<!-- --> if (snmp != null) {<!-- --> // If the Snmp object is not empty try {<!-- --> snmp.close(); // Close Snmp service } catch (IOException ex1) {<!-- --> snmp = null; } } } return jsonArray; // Return JSONArray object } // Check whether the Walk has been completed and the target OID is the incoming targetOID private static boolean checkWalkFinished(OID targetOID, PDU pdu, VariableBinding vb) {<!-- --> // Mark whether the Walk has been completed, the default is not completed boolean finished = false; // If there is an error status in the PDU, it means that the Walk has been completed. if (pdu.getErrorStatus() != 0) {<!-- --> log.info("[true] responsePDU.getErrorStatus() != 0 "); log.info(pdu.getErrorStatusText()); finished = true; } // If the OID in VariableBinding is empty, it means that the Walk has been completed else if (vb.getOid() == null) {<!-- --> log.info("[true] vb.getOid() == null"); finished = true; } // If the length of the OID in VariableBinding is less than the length of the target OID, it means that the Walk has been completed. else if (vb.getOid().size() < targetOID.size()) {<!-- --> log.info("[true] vb.getOid().size() < targetOID.size()"); finished = true; } // If the OID in VariableBinding is different from the left part of the target OID, it means that the Walk has been completed. else if (targetOID.leftMostCompare(targetOID.size(), vb.getOid()) != 0) {<!-- --> log.info("[true] targetOID.leftMostCompare() != 0"); finished = true; } // If the value in VariableBinding is a Null exception, it means that the Walk has been completed. else if (Null.isExceptionSyntax(vb.getVariable().getSyntax())) {<!-- --> System.out .println("[true] Null.isExceptionSyntax(vb.getVariable().getSyntax())"); finished = true; } // If the OID in VariableBinding is less than or equal to the target OID, it means that the Walk has been completed else if (vb.getOid().compareTo(targetOID) <= 0) {<!-- --> log.info("[true] Variable received is not " + "lexicographic successor of requested " + "one:"); log.info(vb.toString() + " <= " + targetOID); finished = true; } //Return the mark value of Walk completion return finished; } /*Get the table asynchronously*/ public static JSONArray snmpAsynWalk(String ip, String community, String oid) {<!-- --> // Generate CommunityTarget using the given IP and Community final CommunityTarget target = createDefault(ip, community); //Create an empty JSONArray object JSONArray jsonArray = new JSONArray(); //Define an SNMP instance object, the initial value is null Snmp snmp = null; try {<!-- --> //Print log - "----> snmp start <----" log.info("----> snmp start <----"); //Create a default UDP transport mapping object DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping(); //Initialize an Snmp instance object and pass in the transport object created above snmp = new Snmp(transport); // Turn on listening snmp.listen(); //Construct PDU object final PDU pdu = new PDU(); // Construct OID object final OID targetOID = new OID(oid); //Create a countdown deadbolt with an initial value of 1 final CountDownLatch latch = new CountDownLatch(1); //Add the VariableBinding corresponding to the OID to the PDU pdu.add(new VariableBinding(targetOID)); // Create a ResponseListener anonymous inner class object and implement the onResponse method ResponseListener listener = new ResponseListener() {<!-- --> public void onResponse(ResponseEvent event) {<!-- --> ((Snmp) event.getSource()).cancel(event.getRequest(), this); try {<!-- --> // Get response PDU PDU response = event.getResponse(); // If response is null, print log - "[ERROR]: response is null" if (response == null) {<!-- --> log.info("[ERROR]: response is null"); // If the error status of the response is not 0, print the log - "[ERROR]: response status" + response.getErrorStatus() + " Text:" + response.getErrorStatusText() } else if (response.getErrorStatus() != 0) {<!-- --> log.info("[ERROR]: response status" + response.getErrorStatus() + " Text:" + response.getErrorStatusText()); } else {<!-- --> // Get the VariableBinding object VariableBinding vb = response.get(0); // Check if the entire SNMP Walk is completed boolean finished = checkWalkFinished(targetOID, pdu, vb); // If the entire SNMP Walk has not been completed yet if (!finished) {<!-- --> //Create a JSONObject object JSONObject jsonObject = new JSONObject(); //Add OID and corresponding value to JSONObject jsonObject.put("oid", vb.getOid().toString()); jsonObject.put("value", vb.getVariable().toString()); // Add JSONObject to jsonArray jsonArray.add(jsonObject); // Update PDU request ID and VariableBinding pdu.setRequestID(new Integer32(0)); pdu.set(0, vb); // Continue to execute the getNext method for the next step of asynchronous processing ((Snmp) event.getSource()).getNext(pdu, target, null, this); } else {<!-- --> // Print log - "SNMP Asyn walk OID value success !" log.info("SNMP Asyn walk OID value success!"); // Count down the door latch minus one latch.countDown(); } } } catch (Exception e) {<!-- --> e.printStackTrace(); // Count down the door latch minus one latch.countDown(); } } }; //Send an asynchronous request, execute the getNext method, and perform the first step of asynchronous processing snmp.getNext(pdu, target, null, listener); // Print log - "pdu has been sent, waiting for asynchronous processing results..." log.info("pdu has been sent, waiting for asynchronous processing results..."); // Wait for 3 seconds until the countdown latch is completely reduced to zero. If it has not been reduced to zero at this time, continue to execute the following code boolean wait = latch.await(3, TimeUnit.SECONDS); //Print log - "latch.await =:" + wait log.info("latch.await =:" + wait); snmp.close(); log.info("----> snmp end <----"); return jsonArray; } catch (Exception e) {<!-- --> e.printStackTrace(); log.info("SNMP Asyn Walk Exception:" + e); return jsonArray; } } public static void main(String[] args) {<!-- --> String ip = "127.0.0.1"; String community = "public"; String oidval = "1.3.6.1.2.1.1"; String oid = "1.3.6.1.2.1.1.1.0"; ip = args[0]; community = args[1]; String flag = args[2]; if (flag.equals("1")) {<!-- --> oidval = args[3]; // This method can obtain the information of all oids subordinate to the specified oid. JSONArray jsonArray2 = SnmpUtil.snmpAsynWalk(ip, community, oidval); System.out.println("The ip for snmp communication is: " + ip); System.out.println("oid is:'" + oidval + "'All the information obtained by the snmpAsynWalk method is: " + jsonArray2); // Currently only the oid 1.3.6.1.2.1.1 can do all the analysis if (oidval.equals("1.3.6.1.2.1.1")) {<!-- --> for (Object o : jsonArray2) {<!-- --> JSONObject jsonObject = (JSONObject) o; if (jsonObject.getString("oid").equals(oidval + ".1.0")) {<!-- --> System.out.println("The system description information of the machine obtained is: " + jsonObject.getString("value")); } if (jsonObject.getString("oid").equals(oidval + ".2.0")) {<!-- --> System.out.println("The device identifier of the machine obtained is: " + jsonObject.getString("value")); } if (jsonObject.getString("oid").equals(oidval + ".3.0")) {<!-- --> System.out.println("The system startup time of the machine obtained is: " + jsonObject.getString("value")); } if (jsonObject.getString("oid").equals(oidval + ".4.0")) {<!-- --> System.out.println("The device contact of the machine obtained is: " + jsonObject.getString("value")); } if (jsonObject.getString("oid").equals(oidval + ".5.0")) {<!-- --> System.out.println("The device name of the machine obtained is: " + jsonObject.getString("value")); } if (jsonObject.getString("oid").equals(oidval + ".6.0")) {<!-- --> System.out.println("The device location information of the machine obtained is: " + jsonObject.getString("value")); } if (jsonObject.getString("oid").equals(oidval + ".7.0")) {<!-- --> System.out.println("The device service status of the machine obtained is: " + jsonObject.getString("value")); } } } } else if (flag.equals("2")) {<!-- --> oid = args[3]; // This method can only obtain specific oid information JSONArray jsonArray = snmpGet(ip, community, oid); System.out.println("oid is:'" + oid + "'All the information obtained by the snmpGet method is: " + jsonArray); } } }
Verification results on the actual machine
The following is the information obtained from the local machine through snmp4j: The information obtained is
[{"oid":"1.3.6.1.2.1.1.1.0", "value":"Hardware: Intel64 Family 6 Model 158 Stepping 10 AT/AT COMPATIBLE - Software: Windows Version 6.3 (Build 19044 Multiprocessor Free)"},{"oid":"1.3.6.1.2.1.1.2.0", "value":"1.3.6.1.4.1.311.1.1.3.1.1"}, {"oid":"1.3.6.1.2.1.1.3.0","value":"17:58:02.02"},{"oid":"1.3.6.1.2.1.1.4.0","value" :""}, {"oid":"1.3.6.1.2.1.1.5.0","value":"acer"}, {"oid":"1.3.6.1.2.1.1.6.0","value":""}, {"oid":"1.3.6.1.2.1.1.7.0","value":"76"}]
The first of these:
{"oid":"1.3.6.1.2.1.1.1.0", "value":"Hardware: Intel64 Family 6 Model 158 Stepping 10 AT/AT COMPATIBLE - Software: Windows Version 6.3 (Build 19044 Multiprocessor Free)"}
This oid is the identifier used to obtain system description information
The first half of the content of value
“Hardware: Intel64 Family 6 Model 158 Stepping 10 AT/AT COMPATIBLE” describes the computer’s hardware information.
Among them, “Intel64” means that the CPU architecture is x86-64 (that is, the 64-bit Intel processor architecture),
“Family 6” and “Model 158” represent the CPU model.
And “Stepping 10” represents the version number of the CPU.
The “AT/AT COMPATIBLE” at the back means that the computer is compatible with the IBM PC/AT standard.
The second half, “Software: Windows Version 6.3 (Build 19044 Multiprocessor Free)” describes the operating system running on the computer and its version information.
“Windows” means the operating system is Windows series,
“Version 6.3” means the operating system version is Windows 8.1 or Windows Server 2012 R2.
“Build 19044” indicates the installed operating system patch version number.
The last “Multiprocessor Free” indicates that this operating system supports multiple processors.
In addition: the information returned by the Linux system is:
{"oid":"1.3.6.1.2.1.1.1.0", "value":"Linux localhost.localdomain 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64"}
The meaning of each parameter is:
Linux: the name of the operating system
localhost.localdomain: hostname
3.10.0-1160.el7.x86_64: Kernel version number
#1 SMP Mon Oct 19 16:18:59 UTC 2020: Kernel compilation time and date
x86_64: Processor architecture
second section:
{"oid":"1.3.6.1.2.1.1.2.0","value":"1.3.6.1.4.1.311.1.1.3.1.1"}
This OID represents the unique identifier of the device, and the returned value is “1.3.6.1.4.1.311.1.1.3.1.1”
Represents a private OID value for a specific vendor or department.
the third item:
{"oid":"1.3.6.1.2.1.1.3.0","value":"17:58:02.02"}
Indicates the system startup time of the device
The “17” in the return value “17:52:35.62” represents the hour, “52” represents the minute, “35” represents the second, and “.62” represents the millisecond. Therefore, the device’s system boot time was 5:52:35 and 620 milliseconds that day.
Item 4:
{"oid":"1.3.6.1.2.1.1.4.0","value":""}
Indicates the contact information of the device, and the returned value is an empty string.
Item 5:
{"oid":"1.3.6.1.2.1.1.5.0","value":"acer"}
Indicates the name of the device. The returned value is “acer”, which indicates that the name of the device is Acer.
Item 6:
{"oid":"1.3.6.1.2.1.1.6.0","value":""}
Indicates the location information of the device, and the returned value is an empty string.
Item 7:
{"oid":"1.3.6.1.2.1.1.7.0","value":"76"}
Indicates the service status of the device. The returned value is “76”, indicating that the device is currently running.
Convert the return value to binary and get: 01001100.
The first bit from left to right is the highest bit (MSB). Its value is 0, which means the device is running.
The second bit from left to right is the next bit, which has a value of 1, indicating that the device has been restarted at least once.
The 6-bit integer (010110) consisting of the third to eighth bits is converted into a decimal number of 44, indicating that the device has been running for 44 timing cycles after startup. The length and units of each timing cycle are device and implementation dependent.
Therefore, a return value of “76” indicates that the device is currently running, has been restarted at least once, and has been running for 44 ticks since the last restart. This information can help administrators understand the status of the device and perform diagnostics and debugging as needed.