如何利用snmp4j-agent在PC端模拟snmp服务

唐宋源码清 2013-06-17

    想在PC端起一个snmp模拟器,在网上搜了一段时间,例子也不算少,但一般都有些问题,可能是自己某个地方出错了。

    索性直接从源码的example开始,看了几天snmp4j-agent源码后,虽然啥也没看懂,但还是被我找到了一些突破口。

    直接将org.snmp4j.agent.example下的例子复制出来,然后修改即可。这几天刚写好的例子,也懒得作修饰了。

1. 将源码中的SampleAgentConfig.properties(org.snmp4j.agent.example下)复制出来。

2. 建立如图的包层次结构

如何利用snmp4j-agent在PC端模拟snmp服务
          如何利用snmp4j-agent在PC端模拟snmp服务

3. 代码明细

SysDate.java

package celul.snmpSeverTest.scalar;

import org.snmp4j.agent.mo.MOAccessImpl;
import org.snmp4j.agent.mo.MOScalar;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;

public class SysDate extends MOScalar<OctetString> {

	public SysDate() {
		super(new OID("1.3.6.1.4.1.12321.1.1.1.2.0"), MOAccessImpl.ACCESS_READ_ONLY,
	            new OctetString("com"));
	}

	@Override
	public OctetString getValue() {
		return new OctetString("com");
	}

}

 SysInitDevice.java

package celul.snmpSeverTest.scalar;

import org.snmp4j.agent.mo.MOAccessImpl;
import org.snmp4j.agent.mo.MOScalar;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.OID;

public class SysInitDevice extends MOScalar<Integer32> {

	public SysInitDevice() {
		super(new OID("1.3.6.1.4.1.12321.1.1.1.3.0"), MOAccessImpl.ACCESS_READ_WRITE,
	            new Integer32(3));
	}

	@Override
	public Integer32 getValue() {
		return super.getValue();
	}

	@Override
	public int setValue(Integer32 value) {
		return super.setValue(value);
	}

}

 SysInitParams.java与SysTimeUp.java不再赘述。

MoTableUtil.java

package celul.snmpSeverTest.table;

import org.snmp4j.agent.MOAccess;
import org.snmp4j.agent.mo.DefaultMOMutableTableModel;
import org.snmp4j.agent.mo.DefaultMOTable;
import org.snmp4j.agent.mo.DefaultMOTableRow;
import org.snmp4j.agent.mo.MOAccessImpl;
import org.snmp4j.agent.mo.MOColumn;
import org.snmp4j.agent.mo.MOMutableColumn;
import org.snmp4j.agent.mo.MOTableIndex;
import org.snmp4j.agent.mo.MOTableSubIndex;
import org.snmp4j.agent.mo.snmp.RowStatus;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.SMIConstants;
import org.snmp4j.smi.Variable;

import celul.snmpSeverTest.Constant;



public class MoTableUtil{
	
	@SuppressWarnings("rawtypes")
	private static DefaultMOTable emuTable;
	private static final String emuTableEntryOid = "1.3.6.1.4.1.19547.1.6.1.1.1";
	private static final Object[][] columnEmuDefined = {
		{ 1, "1", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 2, "2", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 3, "3", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 4, "4", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 5, "5", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 6, "6", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 7, "7", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 8, "8", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 9, "9", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 10, Constant.ROWSTATUS, MOAccessImpl.ACCESS_READ_CREATE, SMIConstants.SYNTAX_INTEGER32 } };
	
	
	@SuppressWarnings("rawtypes")
	private static DefaultMOTable edfaTable;
	private static final String edfaTableEntryOid = "1.3.6.1.4.1.19547.1.6.1.2.1";
	private static final Object[][] columnEdfaDefined = {
		{ 1, "1", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 2, "2", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 3, "3", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 4, "4", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 5, "5", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 6, "6", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 7, "7", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 8, "8", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 9, "9", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 10, "10", MOAccessImpl.ACCESS_READ_ONLY, SMIConstants.SYNTAX_OCTET_STRING },
		{ 11, Constant.ROWSTATUS, MOAccessImpl.ACCESS_READ_CREATE, SMIConstants.SYNTAX_INTEGER32 } };
	
	//private static DefaultMOTable defaTable;
	
	@SuppressWarnings("rawtypes")
	public static DefaultMOTable getEmuTable(){
		if(emuTable == null){
			initEmuTable();
		}
		return emuTable;
	}
	
	@SuppressWarnings("rawtypes")
	public static DefaultMOTable getEdfaTable(){
		if(edfaTable == null){
			initEdfaTable();
		}
		return edfaTable;
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static void initEmuTable(){
		int columnLength = columnEmuDefined.length;
		MOColumn[] edfaColumns = new MOColumn[columnLength];
		for( int i=0; i<columnLength; i++){
			Object[] acol = columnEmuDefined[i];
			int index = (Integer) acol[0];
			String name = (String) acol[1];
			MOAccess access = (MOAccess) acol[2];
			int operType = (Integer) acol[3];
			
			Variable valueDefault = new Integer32(1);
			
			if(name.startsWith(Constant.ROWSTATUS)){
				edfaColumns[i] = new RowStatus(index);
			}else{
				edfaColumns[i] = new MOMutableColumn<Variable>(index, operType, access, valueDefault, true);
			}
		}
		
		emuTable = new DefaultMOTable(
				new OID(emuTableEntryOid),

				new MOTableIndex(
						new MOTableSubIndex[] { 
						new MOTableSubIndex(
						new OID(emuTableEntryOid + ".1001"),
						SMIConstants.SYNTAX_OCTET_STRING, 1, 16) }, 
						true),

						edfaColumns,
				new DefaultMOMutableTableModel<DefaultMOTableRow>()
		);
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static void initEdfaTable(){
		int columnLength = columnEdfaDefined.length;
		MOColumn[] edfaColumns = new MOColumn[columnLength];
		for( int i=0; i<columnLength; i++){
			Object[] acol = columnEdfaDefined[i];
			int index = (Integer) acol[0];
			String name = (String) acol[1];
			MOAccess access = (MOAccess) acol[2];
			int operType = (Integer) acol[3];
			
			Variable valueDefault = new Integer32(1);
			
			if(name.startsWith(Constant.ROWSTATUS)){
				edfaColumns[i] = new RowStatus(index);
			}else{
				edfaColumns[i] = new MOMutableColumn<Variable>(index, operType, access, valueDefault, true);
			}
		}
		
		edfaTable = new DefaultMOTable(
				new OID(edfaTableEntryOid),

				new MOTableIndex(
						new MOTableSubIndex[] { 
						new MOTableSubIndex(
						new OID(edfaTableEntryOid + ".1001"),
						SMIConstants.SYNTAX_OCTET_STRING, 1, 16) }, 
						true),

						edfaColumns,
				new DefaultMOMutableTableModel<DefaultMOTableRow>()
		);
	}
	
	@SuppressWarnings("unchecked")
	public static void fillDefaultDataIntoEmuTable(){
		for (int rowId = 1; rowId < 2; rowId++) {
			Variable[] values = new Variable[10];
			values[0] = new OctetString("a.0." + rowId);
			values[1] = new OctetString("b.0." + rowId);
			values[2] = new OctetString("c.0." + rowId);
			values[3] = new OctetString("d.0." + rowId);
			values[4] = new OctetString("e.0." + rowId);
			values[5] = new OctetString("f.0." + rowId);
			values[6] = new OctetString("g.0." + rowId);
			values[7] = new OctetString("h.0." + rowId);
			values[8] = new OctetString("i.0." + rowId);
			values[9] = new Integer32(rowId);
			emuTable.addRow(new DefaultMOTableRow(new OID("1.0." + rowId),
					values));
		}
	}
	
	@SuppressWarnings("unchecked")
	public static void fillDefaultDataIntoEdfaTable(){
		for (int rowId = 1; rowId < 5; rowId++) {
			Variable[] values = new Variable[11];
			values[0] = new OctetString("edfa.a.0." + rowId);
			values[1] = new OctetString("edfa.b.0." + rowId);
			values[2] = new OctetString("edfa.c.0." + rowId);
			values[3] = new OctetString("edfa.d.0." + rowId);
			values[4] = new OctetString("edfa.e.0." + rowId);
			values[5] = new OctetString("edfa.f.0." + rowId);
			values[6] = new OctetString("edfa.g.0." + rowId);
			values[7] = new OctetString("edfa.h.0." + rowId);
			values[8] = new OctetString("edfa.i.0." + rowId);
			values[9] = new OctetString("edfa.j.0." + rowId);
			values[10] = new Integer32(rowId);
			edfaTable.addRow(new DefaultMOTableRow(new OID("1.0." + rowId),
					values));
		}
	}
}

Constant.java

public class Constant {

	public static final String ROWSTATUS="rowStatus";
	
}

 主要入口snmp4jAgent.java

package celul.snmpSeverTest;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.apache.log4j.BasicConfigurator;
import org.snmp4j.MessageDispatcher;
import org.snmp4j.MessageDispatcherImpl;
import org.snmp4j.TransportMapping;
import org.snmp4j.agent.AgentConfigManager;
import org.snmp4j.agent.DefaultMOContextScope;
import org.snmp4j.agent.DefaultMOServer;
import org.snmp4j.agent.DuplicateRegistrationException;
import org.snmp4j.agent.MOQuery;
import org.snmp4j.agent.MOQueryWithSource;
import org.snmp4j.agent.MOScope;
import org.snmp4j.agent.MOServer;
import org.snmp4j.agent.ManagedObject;
import org.snmp4j.agent.cfg.EngineBootsCounterFile;
import org.snmp4j.agent.io.DefaultMOPersistenceProvider;
import org.snmp4j.agent.io.MOInput;
import org.snmp4j.agent.io.MOInputFactory;
import org.snmp4j.agent.io.prop.PropertyMOInput;
import org.snmp4j.agent.mo.util.VariableProvider;
import org.snmp4j.agent.request.Request;
import org.snmp4j.agent.request.RequestStatus;
import org.snmp4j.agent.request.SubRequest;
import org.snmp4j.agent.request.SubRequestIterator;
import org.snmp4j.log.Log4jLogFactory;
import org.snmp4j.log.LogAdapter;
import org.snmp4j.log.LogFactory;
import org.snmp4j.log.LogLevel;
import org.snmp4j.mp.MPv3;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.Variable;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.TransportMappings;
import org.snmp4j.util.ThreadPool;

import celul.snmpSeverTest.scalar.SysDate;
import celul.snmpSeverTest.scalar.SysInitDevice;
import celul.snmpSeverTest.scalar.SysInitParams;
import celul.snmpSeverTest.scalar.SysTimeUp;
import celul.snmpSeverTest.table.MoTableUtil;

public class SNMP4JAgent implements VariableProvider {

	static{
		LogFactory.setLogFactory(new Log4jLogFactory());
		BasicConfigurator.configure();
		LogFactory.getLogFactory().getRootLogger().setLogLevel(LogLevel.ALL);
	}
	
	private LogAdapter logger = LogFactory.getLogger(SNMP4JAgent.class);
	
	protected AgentConfigManager agent;
	protected MOServer server;
	private String configFile;
	private File bootCounterFile;
	
	public SNMP4JAgent(){
		configFile = "configFile.cfg";
		bootCounterFile = new File("bootCounterFile.bc");
		
		server = new DefaultMOServer();
		MOServer[] moServers = new MOServer[] { server };
		
		final Properties props = new Properties();
		try {
			props.load(SNMP4JAgent.class.getResourceAsStream("SampleAgentConfig.properties"));
		} catch (IOException ex) {
			ex.printStackTrace();
		}
		MOInputFactory configurationFactory = new MOInputFactory(){
			@Override
			public MOInput createMOInput() {
				return new PropertyMOInput(props, SNMP4JAgent.this);
			}
		};
		
		MessageDispatcher messageDispatcher = new MessageDispatcherImpl();
		List<String> list = new ArrayList<String>();
		list.add("udp:0.0.0.0/161");
		addListenAddresses(messageDispatcher,list);
		
		agent = new AgentConfigManager(
					new OctetString(MPv3.createLocalEngineID()), 
					messageDispatcher, 
					null, 
					moServers, 
					ThreadPool.create("snmp4JAgent", 3), 
					configurationFactory, 
					new DefaultMOPersistenceProvider(moServers, configFile), 
					new EngineBootsCounterFile(bootCounterFile)
				);
	}
	
	
	@Override
	public Variable getVariable(String name) {
		OID oid;
		OctetString context = null;
		int pos = name.indexOf(':');
		if (pos >= 0) {
			context = new OctetString(name.substring(0, pos));
			oid = new OID(name.substring(pos + 1, name.length()));
		} else {
			oid = new OID(name);
		}
		final DefaultMOContextScope scope = new DefaultMOContextScope(context,
				oid, true, oid, true);
		MOQuery query = new MOQueryWithSource(scope, false, this);
		ManagedObject mo = server.lookup(query);
		if (mo != null) {
			final VariableBinding vb = new VariableBinding(oid);
			final RequestStatus status = new RequestStatus();
			SubRequest req = new SubRequest() {
				private boolean completed;
				private MOQuery query;

				public boolean hasError() {
					return false;
				}

				public void setErrorStatus(int errorStatus) {
					status.setErrorStatus(errorStatus);
				}

				public int getErrorStatus() {
					return status.getErrorStatus();
				}

				public RequestStatus getStatus() {
					return status;
				}

				public MOScope getScope() {
					return scope;
				}

				public VariableBinding getVariableBinding() {
					return vb;
				}

				public Request getRequest() {
					return null;
				}

				public Object getUndoValue() {
					return null;
				}

				public void setUndoValue(Object undoInformation) {
				}

				public void completed() {
					completed = true;
				}

				public boolean isComplete() {
					return completed;
				}

				public void setTargetMO(ManagedObject managedObject) {
				}

				public ManagedObject getTargetMO() {
					return null;
				}

				public int getIndex() {
					return 0;
				}

				public void setQuery(MOQuery query) {
					this.query = query;
				}

				public MOQuery getQuery() {
					return query;
				}

				public SubRequestIterator repetitions() {
					return null;
				}

				public void updateNextRepetition() {
				}

				public Object getUserObject() {
					return null;
				}

				public void setUserObject(Object userObject) {
				}

			};
			mo.get(req);
			return vb.getVariable();
		}
		return null;
	}
	
	protected void addListenAddresses(MessageDispatcher md,
			List<String> addresses) {
		for (String addressString : addresses) {
			Address address = GenericAddress.parse(addressString);
			if (address == null) {
				logger.fatal("Could not parse address string '" + addressString
						+ "'");
				return;
			}
			@SuppressWarnings("rawtypes")
			TransportMapping tm = TransportMappings.getInstance().createTransportMapping(address);
			if (tm != null) {
				md.addTransportMapping(tm);
			} else {
				logger.warn("No transport mapping available for address '"
						+ address + "'.");
			}
		}
	}
	
	public void registerMIBs(){
		try {
			server.register(new SysTimeUp(), null);
			server.register(new SysDate(), null); 
			server.register(new SysInitDevice(), null);
			server.register(new SysInitParams(), null);
			
			server.register(MoTableUtil.getEmuTable(), null);
			server.register(MoTableUtil.getEdfaTable(), null);
			
			MoTableUtil.fillDefaultDataIntoEmuTable();
			MoTableUtil.fillDefaultDataIntoEdfaTable();
		} catch (DuplicateRegistrationException e) {
			e.printStackTrace();
		} 
		
	}
	
	public void run() {
		agent.initialize();
		registerMIBs();
		agent.setupProxyForwarder();
		agent.setTableSizeLimits(new Properties());
		agent.run();
	}
	
	public static void main(String[] args){
		SNMP4JAgent sa = new SNMP4JAgent();
		SecurityProtocols.getInstance().addDefaultProtocols();
		sa.run();
	}
}

运行snmp4jAgent.java,这样,我们的服务端就已经起来了。通过mibBrowser可以访问。

.1.3.6.1.4.1.19547.1.6.1.1.1.1.1.0.1	a.0.1
.1.3.6.1.4.1.19547.1.6.1.1.1.2.1.0.1	b.0.1
.1.3.6.1.4.1.19547.1.6.1.1.1.3.1.0.1	c.0.1
.1.3.6.1.4.1.19547.1.6.1.1.1.4.1.0.1	d.0.1
.1.3.6.1.4.1.19547.1.6.1.1.1.5.1.0.1	e.0.1
.1.3.6.1.4.1.19547.1.6.1.1.1.6.1.0.1	f.0.1
.1.3.6.1.4.1.19547.1.6.1.1.1.7.1.0.1	g.0.1
.1.3.6.1.4.1.19547.1.6.1.1.1.8.1.0.1	h.0.1
.1.3.6.1.4.1.19547.1.6.1.1.1.9.1.0.1	i.0.1
.1.3.6.1.4.1.19547.1.6.1.1.1.10.1.0.1	1

.1.3.6.1.4.1.19547.1.6.1.2.1.1.1.0.1	edfa.a.0.1
.1.3.6.1.4.1.19547.1.6.1.2.1.1.1.0.2	edfa.a.0.2
.1.3.6.1.4.1.19547.1.6.1.2.1.1.1.0.3	edfa.a.0.3
.1.3.6.1.4.1.19547.1.6.1.2.1.1.1.0.4	edfa.a.0.4
.1.3.6.1.4.1.19547.1.6.1.2.1.2.1.0.1	edfa.b.0.1
.1.3.6.1.4.1.19547.1.6.1.2.1.2.1.0.2	edfa.b.0.2
.1.3.6.1.4.1.19547.1.6.1.2.1.2.1.0.3	edfa.b.0.3
.1.3.6.1.4.1.19547.1.6.1.2.1.2.1.0.4	edfa.b.0.4
.1.3.6.1.4.1.19547.1.6.1.2.1.3.1.0.1	edfa.c.0.1
.1.3.6.1.4.1.19547.1.6.1.2.1.3.1.0.2	edfa.c.0.2
.1.3.6.1.4.1.19547.1.6.1.2.1.3.1.0.3	edfa.c.0.3
.1.3.6.1.4.1.19547.1.6.1.2.1.3.1.0.4	edfa.c.0.4
.1.3.6.1.4.1.19547.1.6.1.2.1.4.1.0.1	edfa.d.0.1
.1.3.6.1.4.1.19547.1.6.1.2.1.4.1.0.2	edfa.d.0.2
.1.3.6.1.4.1.19547.1.6.1.2.1.4.1.0.3	edfa.d.0.3
.1.3.6.1.4.1.19547.1.6.1.2.1.4.1.0.4	edfa.d.0.4
.1.3.6.1.4.1.19547.1.6.1.2.1.5.1.0.1	edfa.e.0.1
.1.3.6.1.4.1.19547.1.6.1.2.1.5.1.0.2	edfa.e.0.2
.1.3.6.1.4.1.19547.1.6.1.2.1.5.1.0.3	edfa.e.0.3
.1.3.6.1.4.1.19547.1.6.1.2.1.5.1.0.4	edfa.e.0.4
.1.3.6.1.4.1.19547.1.6.1.2.1.6.1.0.1	edfa.f.0.1
.1.3.6.1.4.1.19547.1.6.1.2.1.6.1.0.2	edfa.f.0.2
.1.3.6.1.4.1.19547.1.6.1.2.1.6.1.0.3	edfa.f.0.3
.1.3.6.1.4.1.19547.1.6.1.2.1.6.1.0.4	edfa.f.0.4
.1.3.6.1.4.1.19547.1.6.1.2.1.7.1.0.1	edfa.g.0.1
.1.3.6.1.4.1.19547.1.6.1.2.1.7.1.0.2	edfa.g.0.2
.1.3.6.1.4.1.19547.1.6.1.2.1.7.1.0.3	edfa.g.0.3
.1.3.6.1.4.1.19547.1.6.1.2.1.7.1.0.4	edfa.g.0.4
.1.3.6.1.4.1.19547.1.6.1.2.1.8.1.0.1	edfa.h.0.1
.1.3.6.1.4.1.19547.1.6.1.2.1.8.1.0.2	edfa.h.0.2
.1.3.6.1.4.1.19547.1.6.1.2.1.8.1.0.3	edfa.h.0.3
.1.3.6.1.4.1.19547.1.6.1.2.1.8.1.0.4	edfa.h.0.4
.1.3.6.1.4.1.12321.1.1.1.3.0	3

也可以通过snmp4j客户端程序访问该服务器资源。后续再跟踪。

相关推荐