Monday, July 28, 2008

A Simple SNMP4J usage

For some network administrator, querying an SNMP agent is as simple as executing:
snmpwalk -v2c -c public localhost system
Similarly, Java application developer could do that as well using SNMP4J quite easily. Oh, BTW, don't complain about the length of the code because I don't know how to attach the code to this post..:( Here is the import code snippet
 org.jbs.snmputils.*
 import java.util.List;
 import org.snmp4j.mp.SnmpConstants;
 importorg.snmp4j.smi.*;
and here is how to use it somewhere in your code
    
 Address targetAddress = GenericAddress.parse("udp:localhost/161");
 String comm = "public";
 OID oid = new OID(".1.3.6.1.2.1.1");
 List result = SnmpUtils.walk(SnmpConstants.version2c,targetAddress,comm,oid);
 for (VariableBinding vb: result)
 {
          out.println(vb.getOid()+" : "+vb.getVariable().toString()+"
"); }
Hopefully this might be useful. By the way, the code for SnmpUtils is:
package org.jbs.snmputils;

import java.util.List;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.VariableBinding;

/**
 *
 * @author masjoko
 */
public class SnmpUtils {
    public static String get(int version, Address targetaddress, String comm, OID oid)
    {
        if (version==SnmpConstants.version1)
        {
            return SnmpV1Utils.get(targetaddress, comm, oid);
        } else if (version==SnmpConstants.version2c) {
            return SnmpV2cUtils.get(targetaddress, comm, oid);
        } else {
            return null;
        }
    }
    
    public static VariableBinding getNext(int version, Address targetaddress, String comm, OID oid)
    {
        if (version==SnmpConstants.version1)
        {
            return SnmpV1Utils.getNext(targetaddress, comm, oid);
        } else if (version==SnmpConstants.version2c) {
            return SnmpV2cUtils.getNext(targetaddress, comm, oid);
        } else {
            return null;
        }
        
    }
    
    public static List walk(int version, Address address, String comm, OID rootOID)      
    {
        if (version==SnmpConstants.version1)
        {
            return SnmpV1Utils.walk(address, comm, rootOID);
        } else if (version==SnmpConstants.version2c) {
            return SnmpV2cUtils.walk(address, comm, rootOID);
        } else {
            return null;
        }        
    }
}
Which is just a wrapper that calls Snmpv2Utils.
package org.jbs.snmputils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
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.Integer32;
import org.snmp4j.smi.Null;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;

public class SnmpV2cUtils {
    public static String get(Address targetaddress, String comm, OID oid)
    {
        String ret = null;        
        TransportMapping transport;
        try {
            //create transport
            transport = new DefaultUdpTransportMapping();
            CommunityTarget target = new CommunityTarget(); 
            target.setCommunity(new OctetString("public")); 
            target.setAddress(targetaddress); 
            target.setRetries(3); 
            target.setTimeout(2000); 
            target.setVersion(SnmpConstants.version2c); 

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

            //pdu string
            System.out.println("pdu " + pdu.toString()); 			 
            Snmp snmp = new Snmp(transport);
            snmp.listen();

            // send the PDU 
            ResponseEvent responseEvent = snmp.send(pdu, target); 
            Logger.getLogger(SnmpV2cUtils.class.getName()).log(Level.INFO,responseEvent.toString());            
            // extract the response PDU (could be null if timed out) 
            PDU responsePDU = responseEvent.getResponse(); 
            Logger.getLogger(SnmpV2cUtils.class.getName()).log(Level.INFO,responsePDU.toString());
            Vector vbs = responsePDU.getVariableBindings();
            if (vbs.size()>0)
            {
                VariableBinding vb = (VariableBinding) vbs.get(0);
                ret = vb.getVariable().toString();
            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return ret;
    }
    
    public static VariableBinding getNext(Address targetaddress, String comm, OID oid)
    {        
        VariableBinding ret = null;
        TransportMapping transport;
        try {
            //create transport
            transport = new DefaultUdpTransportMapping();
            CommunityTarget target = new CommunityTarget(); 
            target.setCommunity(new OctetString("public")); 
            target.setAddress(targetaddress); 
            target.setRetries(3); 
            target.setTimeout(2000); 
            target.setVersion(SnmpConstants.version2c); 

            // 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);

            //pdu string
            System.out.println("pdu " + pdu.toString()); 			 
            Snmp snmp = new Snmp(transport);
            snmp.listen();

            // send the PDU 
            ResponseEvent responseEvent = snmp.send(pdu, target); 
            Logger.getLogger(SnmpV2cUtils.class.getName()).log(Level.INFO,responseEvent.toString());            
            // extract the response PDU (could be null if timed out) 
            PDU responsePDU = responseEvent.getResponse(); 
            Logger.getLogger(SnmpV2cUtils.class.getName()).log(Level.INFO,responsePDU.toString());
            Vector vbs = responsePDU.getVariableBindings();
            if (vbs.size()>0)
            {
                ret = (VariableBinding) vbs.get(0);                
            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return ret;
    }

    public static List walk(Address address, String comm, OID rootOID)      
    {
        List ret = new ArrayList();            

        PDU requestPDU = new PDU();
        requestPDU.add(new VariableBinding(rootOID));
        requestPDU.setType(PDU.GETBULK);
        // maximum oid per pdu request
        requestPDU.setMaxRepetitions(5);

        CommunityTarget target = new CommunityTarget();
        target.setCommunity(new OctetString(comm));
        target.setAddress(address);
        target.setVersion(SnmpConstants.version2c);        

        try
        {
            TransportMapping transport = new DefaultUdpTransportMapping();
            Snmp snmp = new Snmp(transport);
            transport.listen();

            boolean finished = false;
            int iter = 0;

            while (!finished)
            {
                VariableBinding vb = null;

                ResponseEvent respEvt = snmp.send(requestPDU, target);
                Logger.getLogger(SnmpV2cUtils.class.getName()).log(Level.INFO,"GETBULK iteration number "+iter++);
                PDU responsePDU = respEvt.getResponse();
                
                if (responsePDU != null)
                {                    
                    Vector vbs = responsePDU.getVariableBindings();
                    if (vbs!=null && vbs.size()>0)
                    {
                        for (int i=0; i

16 comments:

Ramakrishnan said...

thanks. this piece of code bailed me out in a flash

ganges said...

Hi,

I am going to use SNMP4J for one of our requirement. I held up with an issue while using GetNext operation where it always returning 1 record. Actually my requirement is i want all the rows from the table for single OID. I know there is something called TableUtils class which will work for my requirement but i can't use it because i am using Apache Camel (which internally uses SNMP4J). So, i would request if you have any sample snippet to get all the values from the table using GETNEXT, Please share it.

ganges said...

Hi,

I would like to know how to use GETBULK without max repetitions to get all the values from a mib table.
I had a requirement to fetch all the values from a MIB table using GETBULK operations. But GETBULK always demands for max repetitions. We can't always set some value due to its dynamic nature.

Thanks in advance.

William Bathurst said...

How would pass credentials to to the utility class if the target device uses SNMPv3?

sastriawan said...

@Ganges: to get the rows of a table, you just use walk at the table OID. It will compare if the next OID is still below the requested table OID.

@William Bathurst: I have not considered Snmp V3 when writing this code.

rajshekar said...

hey this code is incomplete isn't it?

tanlccc said...

Hi,

New to SNMP4J programming and need an example of snmpwalk for specific OID. Your example helps me alot. Looks like SnmpV2cUtils portion is incomplete. Also, missing SnmpV1Utils portion. Can fill up the missing portions?

Anonymous said...

Thanks for this code!
Great contribution to the community!

sastriawan said...

Hi all, I am not sure why the code I posted is incomplete. I will fix it when I have time.

Apoorv Kumar Jhadi said...

hiiiiiiiii i have tried ur code but their is error in
for(VariableBinding vb:result)
{
System.out.println(vb.getOid()+" : "+vb.getVariable().toString()+"");
}

error- incompatable type

Anonymous said...

The last lines of method walk in class SnmpV2cUtils are missing. Maybe lost by c&p-ing. (: Anyway great peace of code!

Anonymous said...

Funny, in source view of this blog the code is complete. :)

sastriawan said...

Corrected here:

http://sastriawan.blogspot.com/2009/11/simplified-snmputility-class-based-upon.html

Joel said...

Seems like it would be easier to use the utility class that Snmp4j already provides, TableUtils, to walk a table:
http://www.snmp4j.org/doc/org/snmp4j/util/TableUtils.html#getTable(org.snmp4j.Target,%20org.snmp4j.smi.OID[],%20org.snmp4j.smi.OID,%20org.snmp4j.smi.OID)

sastriawan said...

Yeah, for table types. This is intended for general bulk query.

Brad Hein said...

The code seems to be chopped off - the for-loop is incomplete. The rest of the code has been pretty useful in building a snmp walk class in Java so thank you!