/* * 'SNMPTrapReceiver.java' NOTE: This copyright does *not* cover user programs * that use HQ program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development Kit or * the Hyperic Client Development Kit - this is merely considered normal use of * the program, and does *not* fall under the heading of "derived work". * Copyright (C) [2004, 2005, 2006, 2007, 2008, 2009], Hyperic, Inc. This file * is part of HQ. HQ is free software; you can redistribute it and/or modify it * under the terms version 2 of the GNU General Public License as published by * the Free Software Foundation. This program is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. You should have received a copy of the GNU * General Public License along with this program; if not, write to the Free * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ package org.hyperic.hq.plugin.netdevice; import java.io.IOException; import java.net.InetAddress; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.Vector; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hyperic.hq.product.LogTrackPlugin; import org.hyperic.hq.product.LogTrackPluginManager; import org.hyperic.snmp.SNMPClient; import org.snmp4j.CommandResponder; import org.snmp4j.CommandResponderEvent; import org.snmp4j.MessageDispatcherImpl; import org.snmp4j.Snmp; import org.snmp4j.TransportMapping; import org.snmp4j.mp.MPv1; import org.snmp4j.mp.MPv2c; import org.snmp4j.mp.MPv3; import org.snmp4j.security.SecurityModels; import org.snmp4j.security.SecurityProtocols; import org.snmp4j.security.USM; import org.snmp4j.smi.Address; import org.snmp4j.smi.GenericAddress; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.TcpAddress; import org.snmp4j.smi.UdpAddress; import org.snmp4j.smi.VariableBinding; import org.snmp4j.transport.DefaultTcpTransportMapping; import org.snmp4j.transport.DefaultUdpTransportMapping; import org.snmp4j.util.MultiThreadedMessageDispatcher; import org.snmp4j.util.ThreadPool; public class SNMPTrapReceiver implements CommandResponder { static final String PROP_LISTEN_ADDRESS = "snmpTrapReceiver.listenAddress"; static final String DEFAULT_LISTEN_ADDRESS = "udp:0.0.0.0/162"; private static SNMPTrapReceiver instance = null; private static final Log log = LogFactory.getLog(SNMPTrapReceiver.class.getName()); private MultiThreadedMessageDispatcher _dispatcher; private Snmp _snmp; private Address _listenAddress; private ThreadPool _threadPool; private Map _plugins = new HashMap(); LogTrackPluginManager _manager; private int _received = 0; static boolean hasInstance() { return instance != null; } public static SNMPTrapReceiver getInstance(Properties props) throws IOException { if (!hasInstance()) { instance = new SNMPTrapReceiver(); instance.init(props); } return instance; } public static void start(Properties props) throws IOException { getInstance(props); } public static void shutdown() throws IOException { if (hasInstance()) { log.debug("Shutdown instance"); instance._threadPool.cancel(); instance._snmp.close(); instance = null; } } private static String getPluginKey(String address, String community) { return address + "-" + community; } private static String getConfig(LogTrackPlugin plugin, String key, String def) { String value = plugin.getConfig(key); if (value == null) { // Commandline-testing... return plugin.getManager().getProperty(key, def); } else { return value; } } private static String getPluginKey(LogTrackPlugin plugin) { String address = getConfig(plugin, SNMPClient.PROP_IP, SNMPClient.DEFAULT_IP); String community = getConfig(plugin, SNMPClient.PROP_COMMUNITY, SNMPClient.DEFAULT_COMMUNITY); return getPluginKey(address, community); } private LogTrackPlugin getPlugin(String address, String community) { String key = getPluginKey(address, community); return (LogTrackPlugin) _plugins.get(key); } public void add(LogTrackPlugin plugin) throws IOException { String key = getPluginKey(plugin); log.debug("Add " + plugin.getName() + " for " + key); _plugins.put(key, plugin); } public static void remove(LogTrackPlugin plugin) { if (!hasInstance()) { return; } String key = getPluginKey(plugin); log.debug("Remove " + plugin.getName() + " for " + key); instance._plugins.remove(key); } private SNMPTrapReceiver() { } private void init(Properties props) throws IOException { String address = props.getProperty(PROP_LISTEN_ADDRESS, DEFAULT_LISTEN_ADDRESS).trim(); String numThreads = props.getProperty("snmpTrapReceiver.numThreads", "1"); _threadPool = ThreadPool.create("SNMPTrapReceiver", Integer.parseInt(numThreads)); _dispatcher = new MultiThreadedMessageDispatcher(_threadPool, new MessageDispatcherImpl()); try { _listenAddress = GenericAddress.parse(address); if (!_listenAddress.isValid()) { throw new IllegalArgumentException(); } } catch (Exception e) { throw new IOException("Invalid " + PROP_LISTEN_ADDRESS + "=" + address); } log.debug(PROP_LISTEN_ADDRESS + "=" + address); TransportMapping transport; if (_listenAddress instanceof UdpAddress) { transport = new DefaultUdpTransportMapping((UdpAddress) _listenAddress); } else { transport = new DefaultTcpTransportMapping((TcpAddress) _listenAddress); } _snmp = new Snmp(_dispatcher, transport); _snmp.getMessageDispatcher().addMessageProcessingModel(new MPv1()); _snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c()); _snmp.getMessageDispatcher().addMessageProcessingModel(new MPv3()); USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0); SecurityModels.getInstance().addSecurityModel(usm); _snmp.addCommandResponder(this); _snmp.listen(); } public int getTrapsReceived() { return _received; } private String getMessage(CommandResponderEvent event) { StringBuffer msg = new StringBuffer(); Vector vars = event.getPDU().getVariableBindings(); int size = vars.size(); for (int i = 0; i < size; i++) { VariableBinding var = (VariableBinding) vars.get(i); msg.append(var.getVariable().toString().trim()); if (i < size - 1) { msg.append(", "); } } return msg.toString(); } private LogTrackPlugin getPlatformPlugin() { // return _manager.getDefaultPlatformPlugin ( ) final String prop = LogTrackPluginManager.DEFAULT_PLATFORM_PLUGIN; String name = _manager.getProperty(prop); return _manager.getLogTrackPlugin(name); } void setPluginManager(LogTrackPluginManager manager) { _manager = manager; } public void processPdu(CommandResponderEvent event) { _received++; Address peer = event.getPeerAddress(); InetAddress peerAddress; if (peer instanceof UdpAddress) { peerAddress = ((UdpAddress) peer).getInetAddress(); } else if (peer instanceof TcpAddress) { peerAddress = ((TcpAddress) peer).getInetAddress(); } else { log.debug("Unsupported transport: " + peer.getClass().getName()); return; } String address = peerAddress.getHostAddress(); String community = new OctetString(event.getSecurityName()).toString(); LogTrackPlugin plugin = getPlugin(address, community); if (plugin == null) { plugin = getPlatformPlugin(); if (plugin != null) { if (log.isDebugEnabled()) { log.debug("No plugin for '" + address + "', '" + community + "', routing to default platform: " + plugin.getName()); } } } if (plugin == null) { if (log.isDebugEnabled()) { log.debug("No plugin for " + address + ", msg=" + getMessage(event)); } } else { String msg = getMessage(event); if (log.isDebugEnabled()) { log.debug("plugin=" + plugin.getName() + ", trapsReceived=" + getTrapsReceived() + ", pduType=" + event.getPDU().getType() + ", address=" + address + ", community=" + community + ", msg=" + msg); } plugin.reportEvent(System.currentTimeMillis(), LogTrackPlugin.LOGLEVEL_ERROR, address, msg); } } public static void main(String[] args) throws Exception { SNMPTrapReceiver.start(System.getProperties()); System.out.println("Ready"); System.in.read(); System.out.print("Shutting down..."); SNMPTrapReceiver.shutdown(); System.out.println("done"); } }