/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 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.snmp.snmp4j; import java.io.IOException; import org.opennms.netmgt.snmp.CollectionTracker; import org.opennms.netmgt.snmp.SnmpObjId; import org.opennms.netmgt.snmp.SnmpValue; import org.opennms.netmgt.snmp.SnmpWalker; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.Target; import org.snmp4j.event.ResponseEvent; import org.snmp4j.event.ResponseListener; import org.snmp4j.mp.SnmpConstants; import org.snmp4j.smi.OID; import org.snmp4j.smi.VariableBinding; public class Snmp4JWalker extends SnmpWalker { public static abstract class Snmp4JPduBuilder extends WalkerPduBuilder { public Snmp4JPduBuilder(int maxVarsPerPdu) { super(maxVarsPerPdu); } public abstract PDU getPdu(); } public class GetNextBuilder extends Snmp4JPduBuilder { private PDU m_nextPdu = null; private GetNextBuilder(int maxVarsPerPdu) { super(maxVarsPerPdu); reset(); } public void reset() { m_nextPdu = m_agentConfig.createPdu(PDU.GETNEXT); } public PDU getPdu() { return m_nextPdu; } public void addOid(SnmpObjId snmpObjId) { VariableBinding varBind = new VariableBinding(new OID(snmpObjId.getIds())); m_nextPdu.add(varBind); } public void setNonRepeaters(int numNonRepeaters) { } public void setMaxRepetitions(int maxRepititions) { } } public class GetBulkBuilder extends Snmp4JPduBuilder { private PDU m_bulkPdu; public GetBulkBuilder(int maxVarsPerPdu) { super(maxVarsPerPdu); reset(); } public void reset() { m_bulkPdu = m_agentConfig.createPdu(PDU.GETBULK); } public PDU getPdu() { return m_bulkPdu; } public void addOid(SnmpObjId snmpObjId) { VariableBinding varBind = new VariableBinding(new OID(snmpObjId.getIds())); m_bulkPdu.add(varBind); } public void setNonRepeaters(int numNonRepeaters) { m_bulkPdu.setNonRepeaters(numNonRepeaters); } public void setMaxRepetitions(int maxRepetitions) { m_bulkPdu.setMaxRepetitions(maxRepetitions); } } /** * TODO: Merge this logic with {@link Snmp4JStrategy#processResponse()} */ public class Snmp4JResponseListener implements ResponseListener { private void processResponse(PDU response) { try { if (log().isDebugEnabled()) { log().debug("Received a tracker PDU of type "+PDU.getTypeString(response.getType())+" from "+getAddress()+" of size "+response.size()+", errorStatus = "+response.getErrorStatus()+", errorStatusText = "+response.getErrorStatusText()+", errorIndex = "+response.getErrorIndex()); } if (response.getType() == PDU.REPORT) { handleAuthError("A REPORT PDU was returned from the agent. This is most likely an authentication problem. Please check the config"); } else { if (!processErrors(response.getErrorStatus(), response.getErrorIndex())) { for (int i = 0; i < response.size(); i++) { VariableBinding vb = response.get(i); SnmpObjId receivedOid = SnmpObjId.get(vb.getOid().getValue()); SnmpValue val = new Snmp4JValue(vb.getVariable()); Snmp4JWalker.this.processResponse(receivedOid, val); } } buildAndSendNextPdu(); } } catch (Throwable e) { handleFatalError(e); } } public void onResponse(ResponseEvent responseEvent) { // need to cancel the request here otherwise SNMP4J Keeps it around forever... go figure m_session.cancel(responseEvent.getRequest(), this); // Check to see if we got an interrupted exception if (responseEvent.getError() instanceof InterruptedException) { if (log().isDebugEnabled()) { log().debug("Interruption event. We have probably tried to close the session due to an error: " + responseEvent.getError(), responseEvent.getError()); } // Check to see if the response is null, indicating a timeout } else if (responseEvent.getResponse() == null) { handleTimeout(getName()+": snmpTimeoutError for: " + getAddress()); // Check to see if we got any kind of error } else if (responseEvent.getError() != null){ handleError(getName()+": snmpInternalError: " + responseEvent.getError() + " for: " + getAddress(), responseEvent.getError()); // If we have a PDU in the response, process it } else { processResponse(responseEvent.getResponse()); } } } private Snmp m_session; private final Target m_tgt; private final ResponseListener m_listener; private final Snmp4JAgentConfig m_agentConfig; public Snmp4JWalker(Snmp4JAgentConfig agentConfig, String name, CollectionTracker tracker) { super(agentConfig.getInetAddress(), name, agentConfig.getMaxVarsPerPdu(), agentConfig.getMaxRepetitions(), tracker); m_agentConfig = agentConfig; m_tgt = agentConfig.getTarget(); m_listener = new Snmp4JResponseListener(); } public void start() { if (log().isDebugEnabled()) { log().info("Walking "+getName()+" for "+getAddress()+" using version "+m_agentConfig.getVersionString()+" with config: "+m_agentConfig); } super.start(); } protected WalkerPduBuilder createPduBuilder(int maxVarsPerPdu) { return (getVersion() == SnmpConstants.version1 ? (WalkerPduBuilder)new GetNextBuilder(maxVarsPerPdu) : (WalkerPduBuilder)new GetBulkBuilder(maxVarsPerPdu)); } protected void sendNextPdu(WalkerPduBuilder pduBuilder) throws IOException { Snmp4JPduBuilder snmp4JPduBuilder = (Snmp4JPduBuilder)pduBuilder; if (m_session == null) { m_session = m_agentConfig.createSnmpSession(); m_session.listen(); } if (log().isDebugEnabled()) { log().debug("Sending tracker pdu of size "+snmp4JPduBuilder.getPdu().size()); } m_session.send(snmp4JPduBuilder.getPdu(), m_tgt, null, m_listener); } protected int getVersion() { return m_tgt.getVersion(); } protected void close() throws IOException { if (m_session != null) { m_session.close(); m_session = null; } } }