/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2006-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * OpenNMS(R) 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 OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.netmgt.trapd; import static org.opennms.core.utils.InetAddressUtils.addr; import java.net.InetAddress; import java.util.concurrent.Callable; import org.opennms.core.concurrent.WaterfallCallable; import org.opennms.core.utils.InetAddressUtils; import org.opennms.core.utils.ThreadCategory; import org.opennms.netmgt.config.EventConfDao; import org.opennms.netmgt.eventd.EventIpcManager; import org.opennms.netmgt.model.events.EventBuilder; import org.opennms.netmgt.snmp.TrapNotification; import org.opennms.netmgt.xml.event.Event; import org.opennms.netmgt.xml.eventconf.Logmsg; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * The TrapQueueProcessor handles the conversion of V1 and V2 traps to events * and sending them out the JSDT channel that eventd is listening on * * @author <A HREF="mailto:weave@oculan.com">Brian Weaver </A> * @author <A HREF="mailto:sowmya@opennms.org">Sowmya Nataraj </A> * @author <A HREF="mailto:larry@opennms.org">Lawrence Karnowski </A> * @author <A HREF="mailto:mike@opennms.org">Mike Davidson </A> * @author <A HREF="mailto:tarus@opennms.org">Tarus Balog </A> * @author <A HREF="http://www.opennms.org">OpenNMS.org </A> * */ class TrapQueueProcessor implements WaterfallCallable, InitializingBean { /** * The name of the local host. */ private static final String LOCALHOST_ADDRESS = InetAddressUtils.getLocalHostName(); /** * Whether or not a newSuspect event should be generated with a trap from an * unknown IP address */ private Boolean m_newSuspect; /** * The event IPC manager to which we send events created from traps. */ private EventIpcManager m_eventMgr; /** * The event configuration DAO that we use to convert from traps to events. */ private EventConfDao m_eventConfDao; private TrapNotification m_trapNotification; /** * Process a V2 trap and convert it to an event for transmission. * * <p> * From RFC2089 ('Mapping SNMPv2 onto SNMPv1'), section 3.3 ('Processing an * outgoing SNMPv2 TRAP') * </p> * * <p> * <strong>2b </strong> * <p> * If the snmpTrapOID.0 value is one of the standard traps the specific-trap * field is set to zero and the generic trap field is set according to this * mapping: * <p> * * <pre> * * * * * * * value of snmpTrapOID.0 generic-trap * =============================== ============ * 1.3.6.1.6.3.1.1.5.1 (coldStart) 0 * 1.3.6.1.6.3.1.1.5.2 (warmStart) 1 * 1.3.6.1.6.3.1.1.5.3 (linkDown) 2 * 1.3.6.1.6.3.1.1.5.4 (linkUp) 3 * 1.3.6.1.6.3.1.1.5.5 (authenticationFailure) 4 * 1.3.6.1.6.3.1.1.5.6 (egpNeighborLoss) 5 * * * * * * * </pre> * * <p> * The enterprise field is set to the value of snmpTrapEnterprise.0 if this * varBind is present, otherwise it is set to the value snmpTraps as defined * in RFC1907 [4]. * </p> * * <p> * <strong>2c. </strong> * </p> * <p> * If the snmpTrapOID.0 value is not one of the standard traps, then the * generic-trap field is set to 6 and the specific-trap field is set to the * last subid of the snmpTrapOID.0 value. * </p> * * <p> * If the next to last subid of snmpTrapOID.0 is zero, then the enterprise * field is set to snmpTrapOID.0 value and the last 2 subids are truncated * from that value. If the next to last subid of snmpTrapOID.0 is not zero, * then the enterprise field is set to snmpTrapOID.0 value and the last 1 * subid is truncated from that value. * </p> * * <p> * In any event, the snmpTrapEnterprise.0 varBind (if present) is ignored in * this case. * </p> */ @Override public Callable<Void> call() { try { processTrapEvent(((EventCreator)m_trapNotification.getTrapProcessor()).getEvent()); } catch (IllegalArgumentException e) { log().info(e.getMessage()); } catch (Throwable e) { log().error("Unexpected error processing trap: " + e, e); } return null; } /** * <p>processTrapEvent</p> * * @param event a {@link org.opennms.netmgt.xml.event.Event} object. */ private void processTrapEvent(final Event event) { final InetAddress trapInterface = event.getInterfaceAddress(); final org.opennms.netmgt.xml.eventconf.Event econf = m_eventConfDao.findByEvent(event); if (econf == null || econf.getUei() == null) { event.setUei("uei.opennms.org/default/trap"); } else { event.setUei(econf.getUei()); } if (econf != null) { final Logmsg logmsg = econf.getLogmsg(); if (logmsg != null) { final String dest = logmsg.getDest(); if ("discardtraps".equals(dest)) { log().debug("Trap discarded due to matching event having logmsg dest == discardtraps"); return; } } } // send the event to eventd m_eventMgr.sendNow(event); log().debug("Trap successfully converted and sent to eventd with UEI " + event.getUei()); if (!event.hasNodeid() && m_newSuspect) { sendNewSuspectEvent(InetAddressUtils.str(trapInterface)); if (log().isDebugEnabled()) { log().debug("Sent newSuspectEvent for interface: " + trapInterface); } } } /** * Send a newSuspect event for the interface * * @param trapInterface * The interface for which the newSuspect event is to be * generated */ private void sendNewSuspectEvent(String trapInterface) { // construct event with 'trapd' as source EventBuilder bldr = new EventBuilder(org.opennms.netmgt.EventConstants.NEW_SUSPECT_INTERFACE_EVENT_UEI, "trapd"); bldr.setInterface(addr(trapInterface)); bldr.setHost(LOCALHOST_ADDRESS); // send the event to eventd m_eventMgr.sendNow(bldr.getEvent()); } /** * The constructor */ public TrapQueueProcessor() { } private ThreadCategory log() { return ThreadCategory.getInstance(getClass()); } /** * <p>getEventConfDao</p> * * @return a {@link org.opennms.netmgt.config.EventConfDao} object. */ public EventConfDao getEventConfDao() { return m_eventConfDao; } /** * <p>setEventConfDao</p> * * @param eventConfDao a {@link org.opennms.netmgt.config.EventConfDao} object. */ public void setEventConfDao(EventConfDao eventConfDao) { m_eventConfDao = eventConfDao; } /** * <p>getEventMgr</p> * * @return a {@link org.opennms.netmgt.eventd.EventIpcManager} object. */ public EventIpcManager getEventManager() { return m_eventMgr; } /** * <p>setEventMgr</p> * * @param eventMgr a {@link org.opennms.netmgt.eventd.EventIpcManager} object. */ public void setEventManager(EventIpcManager eventMgr) { m_eventMgr = eventMgr; } /** * <p>isNewSuspect</p> * * @return a {@link java.lang.Boolean} object. */ public Boolean isNewSuspect() { return m_newSuspect; } /** * <p>setNewSuspect</p> * * @param newSuspect a {@link java.lang.Boolean} object. */ public void setNewSuspect(Boolean newSuspect) { m_newSuspect = newSuspect; } public TrapNotification getTrapNotification() { return m_trapNotification; } public void setTrapNotification(TrapNotification info) { m_trapNotification = info; } @Override public void afterPropertiesSet() throws IllegalStateException { Assert.state(m_eventConfDao != null, "property eventConfDao must be set"); Assert.state(m_eventMgr != null, "property eventMgr must be set"); Assert.state(m_newSuspect != null, "property newSuspect must be set"); Assert.state(m_trapNotification != null, "property trapNotification must be set"); } }