package org.vafer.jmx2snmp.snmp; import java.net.InetAddress; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.management.JMException; import org.snmp4j.CommandResponder; import org.snmp4j.CommandResponderEvent; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.mp.StatusInformation; import org.snmp4j.smi.Counter64; import org.snmp4j.smi.Integer32; import org.snmp4j.smi.Null; import org.snmp4j.smi.OID; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.UdpAddress; import org.snmp4j.smi.Variable; import org.snmp4j.smi.VariableBinding; import org.snmp4j.transport.DefaultUdpTransportMapping; import org.vafer.jmx2snmp.jmx.JmxAttribute; import org.vafer.jmx2snmp.jmx.JmxIndex; import org.vafer.jmx2snmp.jmx.JmxMib; import org.vafer.jmx2snmp.jmx.JmxMib.Bean; /** * The SnmpBridge starts a SNMP agent and provides access to the MBean objects. * It looks up the JMX attribute path from the JmxMib mapping and looks up the * JmxAttribute from the JmxIndex. * * Calling report() on startup will log mapping incosistencies to System.err */ public final class SnmpBridge implements CommandResponder { private final InetAddress address; private final int port; private final JmxIndex jmxIndex; private final JmxMib jmxMib; private Snmp snmp; public SnmpBridge(InetAddress pAddress, int pPort, JmxIndex pJmxIndex, JmxMib pJmxMib) { address = pAddress; port = pPort; jmxIndex = pJmxIndex; jmxMib = pJmxMib; } public void report() { final Map<String,Bean> mibMapping = jmxMib.getMapping(); final Set<String> attributesInMib = new HashSet<String>(); final Set<String> attributesInIndex = new HashSet<String>(jmxIndex.getAttributePaths()); for(Map.Entry<String, Bean> entry : mibMapping.entrySet()) { String oid = entry.getKey(); Bean bean = entry.getValue(); if (attributesInIndex.contains(bean.absolutePath)) { if (attributesInMib.contains(bean.absolutePath)) { System.err.println("jmx2snmp: attribute mapping for [" + bean.absolutePath + "] found more than once"); } attributesInMib.add(bean.absolutePath); } else { if (bean.leaf) { System.err.println("jmx2snmp: attribute [" + bean.absolutePath + "] no longer exists at OID [" + oid + "]"); } } } attributesInIndex.removeAll(attributesInMib); for(String attribute : attributesInIndex) { System.err.println("jmx2snmp: attribute not mapped yet: " + attribute); } } public void processPdu(CommandResponderEvent pRequest) { final PDU requestPdu = pRequest.getPDU(); if (requestPdu == null) { return; } try { final PDU responsePdu = new PDU(requestPdu); responsePdu.setType(PDU.RESPONSE); if (requestPdu.getType() == PDU.GET) { for(VariableBinding binding : responsePdu.toArray()) { final OID oid = binding.getOid(); final String path = jmxMib.getPathFromOid(oid.toString()); if (path == null) { binding.setVariable(Null.noSuchObject); continue; } final JmxAttribute attribute = jmxIndex.getAttributeAtPath(path); if (attribute == null) { binding.setVariable(Null.noSuchObject); continue; } final Variable variable = getVariableFromJmxAttribute(attribute); if (variable != null) { binding.setVariable(variable); } } } else if (requestPdu.getType() == PDU.GETNEXT) { for(VariableBinding binding : responsePdu.toArray()) { final OID oid = binding.getOid(); final String next = jmxMib.getNextOidFromOid(oid.toString()); if (next == null) { binding.setVariable(Null.noSuchObject); continue; } final OID nextOid = new OID(next); binding.setOid(nextOid); final String path = jmxMib.getPathFromOid(nextOid.toString()); if (path == null) { binding.setVariable(Null.noSuchObject); continue; } final JmxAttribute attribute = jmxIndex.getAttributeAtPath(path); if (attribute == null) { binding.setVariable(Null.noSuchObject); continue; } final Variable variable = getVariableFromJmxAttribute(attribute); if (variable != null) { binding.setVariable(variable); } } } else { } pRequest.getStateReference().setTransportMapping(pRequest.getTransportMapping()); pRequest.getMessageDispatcher().returnResponsePdu( pRequest.getMessageProcessingModel(), pRequest.getSecurityModel(), pRequest.getSecurityName(), pRequest.getSecurityLevel(), responsePdu, pRequest.getMaxSizeResponsePDU(), pRequest.getStateReference(), new StatusInformation() ); } catch (Exception e) { e.printStackTrace(); } } public void start() throws Exception { snmp = new Snmp(new DefaultUdpTransportMapping(new UdpAddress(address, port))); snmp.addCommandResponder(this); snmp.listen(); } public void stop() throws Exception { snmp.close(); snmp = null; } private Variable getVariableFromJmxAttribute(JmxAttribute pAttribute) throws JMException { final Object value = pAttribute.getValue(); if (value == null) { return new Null(); } final String type = pAttribute.getType(); if ("int".equals(type)) { final Number n = (Number) value; return new Integer32(n.intValue()); } else if ("long".equals(type)) { final Number n = (Number) value; return new Counter64(n.longValue()); } else if ("boolean".equals(type)) { final Boolean b = (Boolean) value; return new Integer32(b?1:0); } else if ("java.lang.String".equals(type)) { return new OctetString(String.valueOf(value)); } else { return new OctetString("Unsupported Type: " + pAttribute.getType()); } } // public static void main(String[] args) throws Exception { // // System.out.println("starting..."); // // final MBeanExporter exporter = new MBeanExporter(ManagementFactory.getPlatformMBeanServer()); // exporter.export("bean:name=test1", new TestBeanImpl()); // // final JmxServer jmxServer = new JmxServer(InetAddress.getByName("localhost")); // jmxServer.start(); // // final URL url = JmxutilsTestCase.class.getResource("/org/vafer/jmx2snmp/mapping.properties"); // // final JmxMib jmxMib = new JmxMib(); // jmxMib.load(new FileReader(url.getFile())); // // final JmxIndex jmxIndex = new JmxIndex(); // // final SnmpBridge snmpBridge = new SnmpBridge(InetAddress.getByName("192.168.214.1"), 1161, jmxIndex, jmxMib); // snmpBridge.start(); // // System.out.println("enter 'quit' to stop..."); // final Scanner sc = new Scanner(System.in); // while(!sc.nextLine().equals("quit")); // // snmpBridge.stop(); // jmxServer.stop(); // } }