In Previous article, we have seen that how to create SNMP client in JAVA using SNMP4j.
To create the Agent for SNMP which listens for the request should extend the abstract class BaseAgent.
The BaseAgent abstract class defines a framework for writing SNMP agents using the SNMP4J-Agent API. To implement your own SNMP agent, extend this class and implement the abstract methods defined by BaseAgent. The hook methods do not need any specific implementation. They only provide a defined mechanism to customize your agent.
Below Class is used to create the SNMP Agent:
package com.G2.SNMP.Server; import java.io.File; import java.io.IOException; import org.snmp4j.TransportMapping; import org.snmp4j.agent.BaseAgent; import org.snmp4j.agent.CommandProcessor; import org.snmp4j.agent.DuplicateRegistrationException; import org.snmp4j.agent.MOGroup; import org.snmp4j.agent.ManagedObject; import org.snmp4j.agent.mo.MOTableRow; import org.snmp4j.agent.mo.snmp.RowStatus; import org.snmp4j.agent.mo.snmp.SnmpCommunityMIB; import org.snmp4j.agent.mo.snmp.SnmpNotificationMIB; import org.snmp4j.agent.mo.snmp.SnmpTargetMIB; import org.snmp4j.agent.mo.snmp.StorageType; import org.snmp4j.agent.mo.snmp.VacmMIB; import org.snmp4j.agent.security.MutableVACM; import org.snmp4j.mp.MPv3; import org.snmp4j.security.SecurityLevel; import org.snmp4j.security.SecurityModel; import org.snmp4j.security.USM; import org.snmp4j.smi.Address; import org.snmp4j.smi.GenericAddress; import org.snmp4j.smi.Integer32; import org.snmp4j.smi.OID; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.Variable; import org.snmp4j.transport.TransportMappings; public class SNMPAgent extends BaseAgent { private String address; /** * * @param address * @throws IOException */ public SNMPAgent(String address) throws IOException { /** * Creates a base agent with boot-counter, config file, and a * CommandProcessor for processing SNMP requests. Parameters: * "bootCounterFile" - a file with serialized boot-counter information * (read/write). If the file does not exist it is created on shutdown of * the agent. "configFile" - a file with serialized configuration * information (read/write). If the file does not exist it is created on * shutdown of the agent. "commandProcessor" - the CommandProcessor * instance that handles the SNMP requests. */ super(new File("conf.agent"), new File("bootCounter.agent"), new CommandProcessor( new OctetString(MPv3.createLocalEngineID()))); this.address = address; } /** * Adds community to security name mappings needed for SNMPv1 and SNMPv2c. */ @Override protected void addCommunities(SnmpCommunityMIB communityMIB) { Variable[] com2sec = new Variable[] { new OctetString("public"), new OctetString("cpublic"), // security name getAgent().getContextEngineID(), // local engine ID new OctetString("public"), // default context name new OctetString(), // transport tag new Integer32(StorageType.nonVolatile), // storage type new Integer32(RowStatus.active) // row status }; MOTableRow row = communityMIB.getSnmpCommunityEntry().createRow( new OctetString("public2public").toSubIndex(true), com2sec); communityMIB.getSnmpCommunityEntry().addRow(row); } /** * Adds initial notification targets and filters. */ @Override protected void addNotificationTargets(SnmpTargetMIB arg0, SnmpNotificationMIB arg1) { // TODO Auto-generated method stub } /** * Adds all the necessary initial users to the USM. */ @Override protected void addUsmUser(USM arg0) { // TODO Auto-generated method stub } /** * Adds initial VACM configuration. */ @Override protected void addViews(VacmMIB vacm) { vacm.addGroup(SecurityModel.SECURITY_MODEL_SNMPv2c, new OctetString( "cpublic"), new OctetString("v1v2group"), StorageType.nonVolatile); vacm.addAccess(new OctetString("v1v2group"), new OctetString("public"), SecurityModel.SECURITY_MODEL_ANY, SecurityLevel.NOAUTH_NOPRIV, MutableVACM.VACM_MATCH_EXACT, new OctetString("fullReadView"), new OctetString("fullWriteView"), new OctetString( "fullNotifyView"), StorageType.nonVolatile); vacm.addViewTreeFamily(new OctetString("fullReadView"), new OID("1.3"), new OctetString(), VacmMIB.vacmViewIncluded, StorageType.nonVolatile); } /** * Unregister the basic MIB modules from the agent's MOServer. */ @Override protected void unregisterManagedObjects() { // TODO Auto-generated method stub } /** * Register additional managed objects at the agent's server. */ @Override protected void registerManagedObjects() { // TODO Auto-generated method stub } protected void initTransportMappings() throws IOException { transportMappings = new TransportMapping[1]; Address addr = GenericAddress.parse(address); TransportMapping tm = TransportMappings.getInstance() .createTransportMapping(addr); transportMappings[0] = tm; } /** * Start method invokes some initialization methods needed to start the * agent * * @throws IOException */ public void start() throws IOException { init(); // This method reads some old config from a file and causes // unexpected behavior. // loadConfig(ImportModes.REPLACE_CREATE); addShutdownHook(); getServer().addContext(new OctetString("public")); finishInit(); run(); sendColdStartNotification(); } /** * Clients can register the MO they need */ public void registerManagedObject(ManagedObject mo) { try { server.register(mo, null); } catch (DuplicateRegistrationException ex) { throw new RuntimeException(ex); } } public void unregisterManagedObject(MOGroup moGroup) { moGroup.unregisterMOs(server, getContext(moGroup)); } }
This class is used to create ManagedObject which is used by the SNMP agent Class created above:
package com.G2.SNMP.Server; import org.snmp4j.agent.mo.MOAccessImpl; import org.snmp4j.agent.mo.MOScalar; import org.snmp4j.smi.OID; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.Variable; /** * This class creates and returns ManagedObjects * @author Shiva * */ public class MOCreator { public static MOScalar createReadOnly(OID oid,Object value ){ return new MOScalar(oid, MOAccessImpl.ACCESS_READ_ONLY, getVariable(value)); } private static Variable getVariable(Object value) { if(value instanceof String) { return new OctetString((String)value); } throw new IllegalArgumentException("Unmanaged Type: " + value.getClass()); } }
Below class tests that agent is working properly or not :
package com.G2.SNMP.Server; import java.io.IOException; import org.snmp4j.smi.OID; import com.G2.SNMP.client.SNMPManager; public class TestSNMPAgent { static final OID sysDescr = new OID(".1.3.6.1.2.1.1.1.0"); public static void main(String[] args) throws IOException { TestSNMPAgent client = new TestSNMPAgent("udp:127.0.0.1/161"); client.init(); } SNMPAgent agent = null; /** * This is the client which we have created earlier */ SNMPManager client = null; String address = null; /** * Constructor * * @param add */ public TestSNMPAgent(String add) { address = add; } private void init() throws IOException { agent = new SNMPAgent("0.0.0.0/2001"); agent.start(); // Since BaseAgent registers some MIBs by default we need to unregister // one before we register our own sysDescr. Normally you would // override that method and register the MIBs that you need agent.unregisterManagedObject(agent.getSnmpv2MIB()); // Register a system description, use one from you product environment // to test with agent.registerManagedObject(MOCreator.createReadOnly(sysDescr, "This Description is set By ShivaSoft")); // Setup the client to use our newly started agent client = new SNMPManager("udp:127.0.0.1/2001"); client.start(); // Get back Value which is set System.out.println(client.getAsString(sysDescr)); } }
Output :
This Description is set By ShivaSoft
Possible run time errors :
Few of you may receive error like
“Exception in thread “main” java.lang.RuntimeException: java.net.BindException: Address already in use: Cannot bind”.
Solution: You are trying to listen on a local IP and port which is already in use by some other process (for example the operating system – if you use port 161 this is rather likely).
Try to use a different port (or IP address – but most services listen on all local IP addresses) or stop the process that is using it.
Leave a Reply