Tuesday, November 3, 2009

Simplified SnmpUtility class based upon SNMP4J

Due to popular request, I am posting my wrapper code or SnmpUtility based upon SNMP4J. I copy some part of this code somewhere that I could remember. So, I do apologise if I could not give the original author a proper credit.
Updated: < and > were unable to display properly so the generic is not seen properly. I wish it is fixed now.
Here is how to use it:
SnmpUtility util = new SnmpUtility(SnmpUtility.VERSION_2C, "127.0.0.1");
List<VariableBinding> vbs = util.walk("1.3.6.1.2.1.1","public");
for (VariableBinding vb : vbs) {
            System.out.println(vb.getOid() + ":=" + vb.getVariable().toString());
}
SnmpUtility.java
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.Null;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.Variable;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultTcpTransportMapping;
import org.snmp4j.transport.DefaultUdpTransportMapping;

public class SnmpUtility {

    public static int VERSION_1 = SnmpConstants.version1;
    public static int VERSION_2C = SnmpConstants.version2c;
    public static int VERSION_3 = SnmpConstants.version3;
    private int snmpVersion = SnmpUtility.VERSION_2C;
    private String host;
    private String transportProtocol = "UDP";
    private int snmpPort = 161;
    private int timeout = 3000;
    private int retry = 2;
    private Log log = LogFactory.getLog(SnmpUtility.class);

    public SnmpUtility() {
    }

    public SnmpUtility(int version) {
        this.setSnmpVersion(version);
    }

    public SnmpUtility(int version, String host) {
        this.setSnmpVersion(version);
        this.setHost(host);
    }

    /**
     * @return the snmpVersion
     */
    public int getSnmpVersion() {
        return snmpVersion;
    }

    /**
     * @param snmpVersion the snmpVersion to set
     */
    public void setSnmpVersion(int snmpVersion) {
        this.snmpVersion = snmpVersion;
    }

    /**
     * @return the host
     */
    public String getHost() {
        return host;
    }

    /**
     * @param host the host to set
     */
    public void setHost(String host) {
        this.host = host;
    }

    public Object get(OID oid, String community) {
        Object ret = null;
        TransportMapping transport;
        try {
            if (this.getTransportProtocol().equalsIgnoreCase("UDP")) {
                transport = new DefaultUdpTransportMapping();
            } else {
                transport = new DefaultTcpTransportMapping();
            }
            CommunityTarget target = new CommunityTarget();
            target.setCommunity(new OctetString(community));
            Address address = GenericAddress.parse(this.getTransportProtocol() + ":" + this.getHost() + "/" + this.getSnmpPort());
            target.setAddress(address);
            target.setVersion(this.getSnmpVersion());
            target.setTimeout(this.getTimeout());

            // create PDU
            PDU pdu = new PDU();
            pdu.setType(PDU.GET);
            pdu.addOID(new VariableBinding(oid));
            pdu.setNonRepeaters(0);

            Snmp snmp = new Snmp(transport);
            snmp.listen();

            ResponseEvent resp = snmp.send(pdu, target);
            PDU respPDU = resp.getResponse();
            Vector vbs = respPDU.getVariableBindings();
            if (vbs.size() > 0) {
                VariableBinding vb = (VariableBinding) vbs.get(0);
                ret = vb.getVariable();
            } else {
                ret = null;
            }
            snmp.close();
        } catch (Exception ex) {
            log.warn(ex.getMessage());
        }
        return ret;
    }

    public List<VariableBinding> getList(List<OID> oid_list, String community) {
        List<VariableBinding> ret = new ArrayList<VariableBinding>();
        TransportMapping transport;
        try {
            if (this.getTransportProtocol().equalsIgnoreCase("UDP")) {
                transport = new DefaultUdpTransportMapping();
            } else {
                transport = new DefaultTcpTransportMapping();
            }
            CommunityTarget target = new CommunityTarget();
            target.setCommunity(new OctetString(community));
            Address address = GenericAddress.parse(this.getTransportProtocol() + ":" + this.getHost() + "/" + this.getSnmpPort());
            target.setAddress(address);
            target.setVersion(this.getSnmpVersion());
            target.setTimeout(this.getTimeout());

            // create the PDU
            PDU pdu = new PDU();
            pdu.setType(PDU.GET);
            //put the oids you want to get
            List<VariableBinding> ivbs = new ArrayList<VariableBinding>();
            for (OID o : oid_list) {
                ivbs.add(new VariableBinding(o));
            }
            pdu.addAll(ivbs.toArray(new VariableBinding[]{}));
            pdu.setMaxRepetitions(10);
            pdu.setNonRepeaters(0);

            Snmp snmp = new Snmp(transport);
            snmp.listen();

            // send the PDU
            ResponseEvent responseEvent = snmp.send(pdu, target);
            // extract the response PDU (could be null if timed out)
            PDU responsePDU = responseEvent.getResponse();
            Vector vbs = responsePDU.getVariableBindings();
            if (vbs.size() > 0) {
                List<OID> rec_oid = new ArrayList<OID>();
                for (int i = 0; i < vbs.size(); i++) {
                    VariableBinding v = (VariableBinding) vbs.get(i);
                    if (!rec_oid.contains(v.getOid())) {
                        rec_oid.add(v.getOid());
                        ret.add((VariableBinding) vbs.get(i));
                    }
                }
            }
            snmp.close();
        } catch (Exception ex) {
            log.warn(ex.getMessage());
        }
        return ret;
    }

    public boolean set(OID oid, Variable value, String community) {
        boolean ret = false;
        TransportMapping transport;
        try {
            if (this.getTransportProtocol().equalsIgnoreCase("UDP")) {
                transport = new DefaultUdpTransportMapping();
            } else {
                transport = new DefaultTcpTransportMapping();
            }
            CommunityTarget target = new CommunityTarget();
            target.setCommunity(new OctetString(community));
            Address address = GenericAddress.parse(this.getTransportProtocol() + ":" + this.getHost() + "/" + this.getSnmpPort());
            target.setAddress(address);
            target.setVersion(this.getSnmpVersion());
            target.setTimeout(this.getTimeout());

            // create PDU
            PDU pdu = new PDU();
            pdu.setType(PDU.SET);
            pdu.add(new VariableBinding(oid, value));
            pdu.setNonRepeaters(0);

            Snmp snmp = new Snmp(transport);
            snmp.listen();

            ResponseEvent resp = snmp.set(pdu, target);
            PDU respPDU = resp.getResponse();
            if (respPDU == null) {
                log.warn("SNMP Timeout occured.");
            } else {
                Vector vbs = respPDU.getVariableBindings();
                if (vbs.size() > 0) {
                    VariableBinding vb = (VariableBinding) vbs.get(0);
                    ret = vb.isException() ? false : true;
                } else {
                    ret = false;
                }
            }
            snmp.close();
        } catch (Exception ex) {
            ex.printStackTrace();
            log.warn(ex.getMessage());
        }
        return ret;
    }

    public List<VariableBinding> walk(OID oid, String community) {
        List<VariableBinding> ret = new ArrayList<VariableBinding>();

        PDU requestPDU = new PDU();
        requestPDU.add(new VariableBinding(oid));
        requestPDU.setType(PDU.GETNEXT);

        CommunityTarget target = new CommunityTarget();
        target.setCommunity(new OctetString(community));
        Address address = GenericAddress.parse(this.getTransportProtocol() + ":" + this.getHost() + "/" + this.getSnmpPort());
        target.setAddress(address);
        target.setVersion(this.getSnmpVersion());
        target.setTimeout(this.getTimeout());

        try {
            TransportMapping transport;
            if (this.getTransportProtocol().equalsIgnoreCase("UDP")) {
                transport = new DefaultUdpTransportMapping();
            } else {
                transport = new DefaultTcpTransportMapping();
            }
            Snmp snmp = new Snmp(transport);
            transport.listen();

            boolean finished = false;

            while (!finished) {
                VariableBinding vb = null;

                ResponseEvent respEvt = snmp.send(requestPDU, target);
                PDU responsePDU = respEvt.getResponse();
                if (responsePDU != null) {
                    vb = responsePDU.get(0);
                }

                if (responsePDU == null) {
                    finished = true;
                } else if (responsePDU.getErrorStatus() != 0) {
                    finished = true;
                } else if (vb.getOid() == null) {
                    finished = true;
                } else if (vb.getOid().size() < oid.size()) {
                    finished = true;
                } else if (oid.leftMostCompare(oid.size(), vb.getOid()) != 0) {
                    finished = true;
                } else if (Null.isExceptionSyntax(vb.getVariable().getSyntax())) {
                    finished = true;
                } else if (vb.getOid().compareTo(oid) <= 0) {
                    finished = true;
                } else {
                    ret.add(vb);

                    // Set up the variable binding for the next entry.
                    requestPDU.setRequestID(new Integer32(0));
                    requestPDU.set(0, vb);
                }
            }
            snmp.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ret;
    }

    public VariableBinding getNext(OID oid, String community) {
        VariableBinding ret = null;
        TransportMapping transport;
        try {
            //create transport
            if (this.getTransportProtocol().equalsIgnoreCase("UDP")) {
                transport = new DefaultUdpTransportMapping();
            } else {
                transport = new DefaultTcpTransportMapping();
            }
            CommunityTarget target = new CommunityTarget();
            target.setCommunity(new OctetString(community));
            Address address = GenericAddress.parse(this.getTransportProtocol() + ":" + this.getHost() + "/" + this.getSnmpPort());
            target.setAddress(address);
            target.setRetries(3);
            target.setTimeout(this.getTimeout());
            target.setVersion(this.getSnmpVersion());

            // create the PDU
            PDU pdu = new PDU();
            pdu.setType(PDU.GETNEXT);
            //put the oid you want to get
            pdu.add(new VariableBinding(oid));
            pdu.setNonRepeaters(0);

            Snmp snmp = new Snmp(transport);
            snmp.listen();

            // send the PDU
            ResponseEvent responseEvent = snmp.send(pdu, target);
            // extract the response PDU (could be null if timed out)
            PDU responsePDU = responseEvent.getResponse();
            Vector vbs = responsePDU.getVariableBindings();
            if (vbs.size() > 0) {
                ret = (VariableBinding) vbs.get(0);
            }
            snmp.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ret;
    }

    /**
     * @return the transportProtocol
     */
    public String getTransportProtocol() {
        return transportProtocol;
    }

    /**
     * @param transportProtocol the transportProtocol to set
     */
    public void setTransportProtocol(String transportProtocol) {
        this.transportProtocol = transportProtocol;
    }

    /**
     * @return the snmpPort
     */
    public int getSnmpPort() {
        return snmpPort;
    }

    /**
     * @param snmpPort the snmpPort to set
     */
    public void setSnmpPort(int snmpPort) {
        this.snmpPort = snmpPort;
    }

    /**
     * @return the timeout
     */
    public int getTimeout() {
        return timeout;
    }

    /**
     * @param timeout the timeout to set
     */
    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    /**
     * @return the retry
     */
    public int getRetry() {
        return retry;
    }

    /**
     * @param retry the retry to set
     */
    public void setRetry(int retry) {
        this.retry = retry;
    }
}

19 comments:

Anonymous said...

thank you very very much!!!

Anonymous said...

sorry but this go first or after the code you post on july?

sastriawan said...

This code is the updated version of the previous wrapper code I wrote last July. I have tested it against NetSNMP agent as well as several real hardware (in fact they were a DSLAM -- the other end of your DSL modem and an SNMP based monitoring node).

I have also put an example on how to use it before the source of the SnmpUtility. The code I wrote only support synchronous requests. If you are interested on creating asynchronous version, you can see SNMP4J website.

Anonymous said...

thanks...but i try to use it and give me this error:
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.ve.internal.java.vce.launcher.remotevm.JavaBeansLauncher.main(JavaBeansLauncher.java:79)
Caused by: java.lang.Error: Unresolved compilation problem:
The method walk(OID, String) in the type SnmpUtility is not applicable for the arguments (String, String)

Anonymous said...

sorry if i wrote again to you but i have another question, you wrote in your post how to do a WALK, And Give Me the errore i wrote in the precedent comment, i wanna know why and i also want know if you can write me how to use a GET...
Thank you for your time

sastriawan said...

I have edited my post. Because < and > were processed as HTML tag, generic notation was not displayed properly. I wish it is now fixed.

Anonymous said...

thanks...it's possibile do a bind in snmp? in the exam project i'm writing for university ,I have to do a bind between the source IP and the IP of the remote device,it's possibile?...how?

Anonymous said...

Have a look at SNMP4J sources. The low level socket communication setting such as binding and the rest are performed over there.

awksedgreep said...

Hi,
Thanks for posting this very rare example of SNMP4J code on the web. :)

I'm working on a similar wrapper for JRuby called SNMP4JR.

Do you use Ruby at all? So far I've just been working on it at home, but if you think you might want to contribute I'll open a project on GitHub or something.

My Java skills are lacking and I could sure use the help.

Thanks again for posting this. Let me know if you're interested.

Taila said...

thanks, very useful. I test v1 and v2c and works fine.

Do you have an example using a thread poll?

LianCheng said...

Hi, is there a method call for SNMP trap receiving in this snmpUtility library?

Dwi M. Wibowo said...

Dear Pak Joko,

adakah sample untuk menjalankan SNMP4J di android ?

trims pak :)

sastriawan said...

EN: For running on Android, I believe you need to try to compile SNMP4J using Android development environment first. I have not checked if the Java API used in SNMP4J are all available in Android.

ID: Untuk menjalankan di Android, anda harus coba compile di Android development environment dulu. Saya belum memeriksa apakah JAVA API yg dipakai di SNMP4J semuanya ada di Android.

Android is not JVM but it is a Dalvik VM. Not all Java Standard Edition API are available on Android.

Anonymous said...

Thank You!!!

These two lines of code were crucial for me, because i didn't know how to go to the next step. I really appreciate it!

requestPDU.setRequestID(new Integer32(0));
requestPDU.set(0, vb);

"

sastriawan said...

requestPDU.setRequestID(new Integer32(0));

See http://www.snmp4j.org/doc/org/snmp4j/PDU.html#setRequestID%28org.snmp4j.smi.Integer32%29
It basically lets SNMP4J to set unique ID for SNMP request to send.

requestPDU.set(0, vb)

Set the VariableBinding (i.e. the list of OIDs to request) from index 0.

Please consult the Javadocs @ www.snmp4j.org. The docs are very helpful.

Mahfuzul Islam said...

Facing Error during Call the main


SnmpUtility util = new SnmpUtility(SnmpUtility.VERSION_2C, "127.0.0.1");
List vbs = util.walk("1.3.6.1.2.1.1","public");
for (VariableBinding vb : vbs) {
System.out.println(vb.getOid() + ":=" + vb.getVariable().toString());

For Assigning value "1.3.6.1.2.1.1" its saying

Required org.snmp4j.smi.OID,java.lang.String
found java.lang.String

Please guide how to fix it.
Thanks!


sastriawan said...

Try replacing "1.3.6.1.2.1.1" with new OID("1.3.6.1.2.1.1"). Hope this works.

sancéro Votti said...

hi i have made an application in my education that get list of equipement from servers i want to surveille this list with snmp i had problem to do it can you help me ??

sancéro Votti said...

my skype is monta007
facebook : montacer007@hotmail.com