/* * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.jmx.snmp.daemon; // java import//import java.util.Vector;import java.util.Enumeration;import java.util.Hashtable;import java.util.logging.Level;import java.io.InterruptedIOException;import java.net.DatagramSocket;import java.net.DatagramPacket;import java.net.SocketException; // jmx imports//import javax.management.MBeanServer;import javax.management.ObjectName;import com.sun.jmx.snmp.SnmpMessage;import com.sun.jmx.snmp.SnmpPduFactory;import com.sun.jmx.snmp.SnmpPduBulk;import com.sun.jmx.snmp.SnmpPduPacket;import com.sun.jmx.snmp.SnmpPduRequest;import com.sun.jmx.snmp.SnmpPduTrap;import com.sun.jmx.snmp.SnmpValue;import com.sun.jmx.snmp.SnmpVarBind;import com.sun.jmx.snmp.SnmpVarBindList;import com.sun.jmx.snmp.SnmpDefinitions;import com.sun.jmx.snmp.SnmpStatusException;import com.sun.jmx.snmp.SnmpTooBigException;import com.sun.jmx.snmp.SnmpDataTypeEnums; // RI imports//import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER; // SNMP runtime import//import com.sun.jmx.snmp.agent.SnmpMibAgent;import com.sun.jmx.snmp.agent.SnmpUserDataFactory;//import com.sun.jmx.snmp.IPAcl.IPAcl;import com.sun.jmx.snmp.InetAddressAcl; class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { private transient DatagramSocket socket = null ; private transient DatagramPacket packet = null ; private transient Vector mibs = null ; /** * Contains the list of sub-requests associated to the current request. */ private transient Hashtable<SnmpMibAgent, SnmpSubRequestHandler> subs = null; /** * Reference on the MIBS */ private transient SnmpMibTree root; private transient Object ipacl = null ; private transient SnmpPduFactory pduFactory = null ; private transient SnmpUserDataFactory userDataFactory = null ; private transient SnmpAdaptorServer adaptor = null; /** * Full constructor */ public SnmpRequestHandler(SnmpAdaptorServer server, int id, DatagramSocket s, DatagramPacket p, SnmpMibTree tree, Vector m, Object a, SnmpPduFactory factory, SnmpUserDataFactory dataFactory, MBeanServer f, ObjectName n) { super(server, id, f, n); // Need a reference on SnmpAdaptorServer for getNext & getBulk, // in case of oid equality (mib overlapping). // adaptor = server; socket = s; packet = p; root= tree; mibs = (Vector) m.clone(); subs= new Hashtable<SnmpMibAgent, SnmpSubRequestHandler>(mibs.size()); ipacl = a; pduFactory = factory ; userDataFactory = dataFactory ; //thread.start(); } /** * Treat the request available in 'packet' and send the result * back to the client. * Note: we overwrite 'packet' with the response bytes. */ public void doRun() { // Trace the input packet // if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "doRun","Packet received:\n" + SnmpMessage.dumpHexBuffer(packet.getData(), 0, packet.getLength())); } // Let's build the response packet // DatagramPacket respPacket = makeResponsePacket(packet) ; // Trace the output packet // if ((SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) && (respPacket != null)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "doRun","Packet to be sent:\n" + SnmpMessage.dumpHexBuffer(respPacket.getData(), 0, respPacket.getLength())); } // Send the response packet if any // if (respPacket != null) { try { socket.send(respPacket) ; } catch (SocketException e) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { if (e.getMessage().equals(InterruptSysCallMsg)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "doRun", "interrupted"); } else { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "doRun", "I/O exception", e); } } } catch(InterruptedIOException e) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "doRun", "interrupted"); } } catch(Exception e) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "doRun", "failure when sending response", e); } } } } /** * Here we make a response packet from a request packet. * We return null if there no response packet to sent. */ private DatagramPacket makeResponsePacket(DatagramPacket reqPacket) { DatagramPacket respPacket = null ; // Transform the request packet into a request SnmpMessage // SnmpMessage reqMsg = new SnmpMessage() ; try { reqMsg.decodeMessage(reqPacket.getData(), reqPacket.getLength()) ; reqMsg.address = reqPacket.getAddress() ; reqMsg.port = reqPacket.getPort() ; } catch(SnmpStatusException x) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponsePacket", "packet decoding failed", x); } reqMsg = null ; ((SnmpAdaptorServer)adaptorServer).incSnmpInASNParseErrs(1) ; } // Make the response SnmpMessage if any // SnmpMessage respMsg = null ; if (reqMsg != null) { respMsg = makeResponseMessage(reqMsg) ; } // Try to transform the response SnmpMessage into response packet. // NOTE: we overwrite the request packet. // if (respMsg != null) { try { reqPacket.setLength(respMsg.encodeMessage(reqPacket.getData())) ; respPacket = reqPacket ; } catch(SnmpTooBigException x) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponsePacket", "response message is too big"); } try { respMsg = newTooBigMessage(reqMsg) ; reqPacket.setLength(respMsg.encodeMessage(reqPacket.getData())) ; respPacket = reqPacket ; } catch(SnmpTooBigException xx) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponsePacket", "'too big' is 'too big' !!!"); } adaptor.incSnmpSilentDrops(1); } } } return respPacket ; } /** * Here we make a response message from a request message. * We return null if there is no message to reply. */ private SnmpMessage makeResponseMessage(SnmpMessage reqMsg) { SnmpMessage respMsg = null ; // Transform the request message into a request pdu // SnmpPduPacket reqPdu = null ; Object userData = null; try { reqPdu = (SnmpPduPacket)pduFactory.decodeSnmpPdu(reqMsg) ; if (reqPdu != null && userDataFactory != null) userData = userDataFactory.allocateUserData(reqPdu); } catch(SnmpStatusException x) { reqPdu = null ; SnmpAdaptorServer snmpServer = (SnmpAdaptorServer)adaptorServer ; snmpServer.incSnmpInASNParseErrs(1) ; if (x.getStatus()== SnmpDefinitions.snmpWrongSnmpVersion) snmpServer.incSnmpInBadVersions(1) ; if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "message decoding failed", x); } } // Make the response pdu if any // SnmpPduPacket respPdu = null ; if (reqPdu != null) { respPdu = makeResponsePdu(reqPdu,userData) ; try { if (userDataFactory != null) userDataFactory.releaseUserData(userData,respPdu); } catch (SnmpStatusException x) { respPdu = null; } } // Try to transform the response pdu into a response message if any // if (respPdu != null) { try { respMsg = (SnmpMessage)pduFactory. encodeSnmpPdu(respPdu, packet.getData().length) ; } catch(SnmpStatusException x) { respMsg = null ; if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "failure when encoding the response message", x); } } catch(SnmpTooBigException x) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "response message is too big"); } try { // if the PDU is too small, why should we try to do // recovery ? // if (packet.getData().length <=32) throw x; int pos= x.getVarBindCount(); if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "fail on element" + pos); } int old= 0; while (true) { try { respPdu = reduceResponsePdu(reqPdu, respPdu, pos) ; respMsg = (SnmpMessage)pduFactory. encodeSnmpPdu(respPdu, packet.getData().length -32) ; break; } catch (SnmpTooBigException xx) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "response message is still too big"); } old= pos; pos= xx.getVarBindCount(); if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage","fail on element" + pos); } if (pos == old) { // we can not go any further in trying to // reduce the message ! // throw xx; } } }// end of loop } catch(SnmpStatusException xx) { respMsg = null ; if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "failure when encoding the response message", xx); } } catch(SnmpTooBigException xx) { try { respPdu = newTooBigPdu(reqPdu) ; respMsg = (SnmpMessage)pduFactory. encodeSnmpPdu(respPdu, packet.getData().length) ; } catch(SnmpTooBigException xxx) { respMsg = null ; if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "'too big' is 'too big' !!!"); } adaptor.incSnmpSilentDrops(1); } catch(Exception xxx) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "Got unexpected exception", xxx); } respMsg = null ; } } catch(Exception xx) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "Got unexpected exception", xx); } respMsg = null ; } } } return respMsg ; } /** * Here we make a response pdu from a request pdu. * We return null if there is no pdu to reply. */ private SnmpPduPacket makeResponsePdu(SnmpPduPacket reqPdu, Object userData) { SnmpAdaptorServer snmpServer = (SnmpAdaptorServer)adaptorServer ; SnmpPduPacket respPdu = null ; snmpServer.updateRequestCounters(reqPdu.type) ; if (reqPdu.varBindList != null) snmpServer.updateVarCounters(reqPdu.type, reqPdu.varBindList.length) ; if (checkPduType(reqPdu)) { respPdu = checkAcl(reqPdu) ; if (respPdu == null) { // reqPdu is accepted by ACLs if (mibs.size() < 1) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "makeResponsePdu", "Request " + reqPdu.requestId + " received but no MIB registered."); } return makeNoMibErrorPdu((SnmpPduRequest)reqPdu, userData); } switch(reqPdu.type) { case SnmpPduPacket.pduGetRequestPdu: case SnmpPduPacket.pduGetNextRequestPdu: case SnmpPduPacket.pduSetRequestPdu: respPdu = makeGetSetResponsePdu((SnmpPduRequest)reqPdu, userData) ; break ; case SnmpPduPacket.pduGetBulkRequestPdu: respPdu = makeGetBulkResponsePdu((SnmpPduBulk)reqPdu, userData) ; break ; } } else { // reqPdu is rejected by ACLs // respPdu contains the error response to be sent. // We send this response only if authResEnabled is true. if (!snmpServer.getAuthRespEnabled()) { // No response should be sent respPdu = null ; } if (snmpServer.getAuthTrapEnabled()) { // A trap must be sent try { snmpServer.snmpV1Trap(SnmpPduTrap. trapAuthenticationFailure, 0, new SnmpVarBindList()) ; } catch(Exception x) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponsePdu", "Failure when sending authentication trap", x); } } } } } return respPdu ; } // // Generates a response packet, filling the values in the // varbindlist with one of endOfMibView, noSuchObject, noSuchInstance // according to the value of <code>status</code> // // @param statusTag should be one of: // <li>SnmpDataTypeEnums.errEndOfMibViewTag</li> // <li>SnmpDataTypeEnums.errNoSuchObjectTag</li> // <li>SnmpDataTypeEnums.errNoSuchInstanceTag</li> // SnmpPduPacket makeErrorVarbindPdu(SnmpPduPacket req, int statusTag) { final SnmpVarBind[] vblist = req.varBindList; final int length = vblist.length; switch (statusTag) { case SnmpDataTypeEnums.errEndOfMibViewTag: for (int i=0 ; i<length ; i++) vblist[i].value = SnmpVarBind.endOfMibView; break; case SnmpDataTypeEnums.errNoSuchObjectTag: for (int i=0 ; i<length ; i++) vblist[i].value = SnmpVarBind.noSuchObject; break; case SnmpDataTypeEnums.errNoSuchInstanceTag: for (int i=0 ; i<length ; i++) vblist[i].value = SnmpVarBind.noSuchInstance; break; default: return newErrorResponsePdu(req,snmpRspGenErr,1); } return newValidResponsePdu(req,vblist); } // Generates an appropriate response when no mib is registered in // the adaptor. // // <li>If the version is V1:</li> // <ul><li>Generates a NoSuchName error V1 response PDU</li></ul> // <li>If the version is V2:</li> // <ul><li>If the request is a GET, fills the varbind list with // NoSuchObject's</li> // <li>If the request is a GET-NEXT/GET-BULK, fills the varbind // list with EndOfMibView's</li> // <li>If the request is a SET, generates a NoAccess error V2 // response PDU</li> // </ul> // // SnmpPduPacket makeNoMibErrorPdu(SnmpPduRequest req, Object userData) { // There is no agent registered // if (req.version == SnmpDefinitions.snmpVersionOne) { // Version 1: => NoSuchName return newErrorResponsePdu(req,snmpRspNoSuchName,1); } else if (req.version == SnmpDefinitions.snmpVersionTwo) { // Version 2: => depends on PDU type switch (req.type) { case pduSetRequestPdu :Lines 1–500 of 1152. Load more
/* * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.jmx.snmp.daemon; // java import // import java.util.Vector; import java.util.Enumeration; import java.util.Hashtable; import java.util.logging.Level; import java.io.InterruptedIOException; import java.net.DatagramSocket; import java.net.DatagramPacket; import java.net.SocketException; // jmx imports // import javax.management.MBeanServer; import javax.management.ObjectName; import com.sun.jmx.snmp.SnmpMessage; import com.sun.jmx.snmp.SnmpPduFactory; import com.sun.jmx.snmp.SnmpPduBulk; import com.sun.jmx.snmp.SnmpPduPacket; import com.sun.jmx.snmp.SnmpPduRequest; import com.sun.jmx.snmp.SnmpPduTrap; import com.sun.jmx.snmp.SnmpValue; import com.sun.jmx.snmp.SnmpVarBind; import com.sun.jmx.snmp.SnmpVarBindList; import com.sun.jmx.snmp.SnmpDefinitions; import com.sun.jmx.snmp.SnmpStatusException; import com.sun.jmx.snmp.SnmpTooBigException; import com.sun.jmx.snmp.SnmpDataTypeEnums; // RI imports // import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER; // SNMP runtime import // import com.sun.jmx.snmp.agent.SnmpMibAgent; import com.sun.jmx.snmp.agent.SnmpUserDataFactory; //import com.sun.jmx.snmp.IPAcl.IPAcl; import com.sun.jmx.snmp.InetAddressAcl; class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { private transient DatagramSocket socket = null ; private transient DatagramPacket packet = null ; private transient Vector mibs = null ; /** * Contains the list of sub-requests associated to the current request. */ private transient Hashtable<SnmpMibAgent, SnmpSubRequestHandler> subs = null; /** * Reference on the MIBS */ private transient SnmpMibTree root; private transient Object ipacl = null ; private transient SnmpPduFactory pduFactory = null ; private transient SnmpUserDataFactory userDataFactory = null ; private transient SnmpAdaptorServer adaptor = null; /** * Full constructor */ public SnmpRequestHandler(SnmpAdaptorServer server, int id, DatagramSocket s, DatagramPacket p, SnmpMibTree tree, Vector m, Object a, SnmpPduFactory factory, SnmpUserDataFactory dataFactory, MBeanServer f, ObjectName n) { super(server, id, f, n); // Need a reference on SnmpAdaptorServer for getNext & getBulk, // in case of oid equality (mib overlapping). // adaptor = server; socket = s; packet = p; root= tree; mibs = (Vector) m.clone(); subs= new Hashtable<SnmpMibAgent, SnmpSubRequestHandler>(mibs.size()); ipacl = a; pduFactory = factory ; userDataFactory = dataFactory ; //thread.start(); } /** * Treat the request available in 'packet' and send the result * back to the client. * Note: we overwrite 'packet' with the response bytes. */ public void doRun() { // Trace the input packet // if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "doRun","Packet received:\n" + SnmpMessage.dumpHexBuffer(packet.getData(), 0, packet.getLength())); } // Let's build the response packet // DatagramPacket respPacket = makeResponsePacket(packet) ; // Trace the output packet // if ((SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) && (respPacket != null)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "doRun","Packet to be sent:\n" + SnmpMessage.dumpHexBuffer(respPacket.getData(), 0, respPacket.getLength())); } // Send the response packet if any // if (respPacket != null) { try { socket.send(respPacket) ; } catch (SocketException e) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { if (e.getMessage().equals(InterruptSysCallMsg)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "doRun", "interrupted"); } else { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "doRun", "I/O exception", e); } } } catch(InterruptedIOException e) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "doRun", "interrupted"); } } catch(Exception e) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "doRun", "failure when sending response", e); } } } } /** * Here we make a response packet from a request packet. * We return null if there no response packet to sent. */ private DatagramPacket makeResponsePacket(DatagramPacket reqPacket) { DatagramPacket respPacket = null ; // Transform the request packet into a request SnmpMessage // SnmpMessage reqMsg = new SnmpMessage() ; try { reqMsg.decodeMessage(reqPacket.getData(), reqPacket.getLength()) ; reqMsg.address = reqPacket.getAddress() ; reqMsg.port = reqPacket.getPort() ; } catch(SnmpStatusException x) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponsePacket", "packet decoding failed", x); } reqMsg = null ; ((SnmpAdaptorServer)adaptorServer).incSnmpInASNParseErrs(1) ; } // Make the response SnmpMessage if any // SnmpMessage respMsg = null ; if (reqMsg != null) { respMsg = makeResponseMessage(reqMsg) ; } // Try to transform the response SnmpMessage into response packet. // NOTE: we overwrite the request packet. // if (respMsg != null) { try { reqPacket.setLength(respMsg.encodeMessage(reqPacket.getData())) ; respPacket = reqPacket ; } catch(SnmpTooBigException x) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponsePacket", "response message is too big"); } try { respMsg = newTooBigMessage(reqMsg) ; reqPacket.setLength(respMsg.encodeMessage(reqPacket.getData())) ; respPacket = reqPacket ; } catch(SnmpTooBigException xx) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponsePacket", "'too big' is 'too big' !!!"); } adaptor.incSnmpSilentDrops(1); } } } return respPacket ; } /** * Here we make a response message from a request message. * We return null if there is no message to reply. */ private SnmpMessage makeResponseMessage(SnmpMessage reqMsg) { SnmpMessage respMsg = null ; // Transform the request message into a request pdu // SnmpPduPacket reqPdu = null ; Object userData = null; try { reqPdu = (SnmpPduPacket)pduFactory.decodeSnmpPdu(reqMsg) ; if (reqPdu != null && userDataFactory != null) userData = userDataFactory.allocateUserData(reqPdu); } catch(SnmpStatusException x) { reqPdu = null ; SnmpAdaptorServer snmpServer = (SnmpAdaptorServer)adaptorServer ; snmpServer.incSnmpInASNParseErrs(1) ; if (x.getStatus()== SnmpDefinitions.snmpWrongSnmpVersion) snmpServer.incSnmpInBadVersions(1) ; if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "message decoding failed", x); } } // Make the response pdu if any // SnmpPduPacket respPdu = null ; if (reqPdu != null) { respPdu = makeResponsePdu(reqPdu,userData) ; try { if (userDataFactory != null) userDataFactory.releaseUserData(userData,respPdu); } catch (SnmpStatusException x) { respPdu = null; } } // Try to transform the response pdu into a response message if any // if (respPdu != null) { try { respMsg = (SnmpMessage)pduFactory. encodeSnmpPdu(respPdu, packet.getData().length) ; } catch(SnmpStatusException x) { respMsg = null ; if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "failure when encoding the response message", x); } } catch(SnmpTooBigException x) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "response message is too big"); } try { // if the PDU is too small, why should we try to do // recovery ? // if (packet.getData().length <=32) throw x; int pos= x.getVarBindCount(); if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "fail on element" + pos); } int old= 0; while (true) { try { respPdu = reduceResponsePdu(reqPdu, respPdu, pos) ; respMsg = (SnmpMessage)pduFactory. encodeSnmpPdu(respPdu, packet.getData().length -32) ; break; } catch (SnmpTooBigException xx) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "response message is still too big"); } old= pos; pos= xx.getVarBindCount(); if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage","fail on element" + pos); } if (pos == old) { // we can not go any further in trying to // reduce the message ! // throw xx; } } }// end of loop } catch(SnmpStatusException xx) { respMsg = null ; if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "failure when encoding the response message", xx); } } catch(SnmpTooBigException xx) { try { respPdu = newTooBigPdu(reqPdu) ; respMsg = (SnmpMessage)pduFactory. encodeSnmpPdu(respPdu, packet.getData().length) ; } catch(SnmpTooBigException xxx) { respMsg = null ; if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "'too big' is 'too big' !!!"); } adaptor.incSnmpSilentDrops(1); } catch(Exception xxx) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "Got unexpected exception", xxx); } respMsg = null ; } } catch(Exception xx) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "Got unexpected exception", xx); } respMsg = null ; } } } return respMsg ; } /** * Here we make a response pdu from a request pdu. * We return null if there is no pdu to reply. */ private SnmpPduPacket makeResponsePdu(SnmpPduPacket reqPdu, Object userData) { SnmpAdaptorServer snmpServer = (SnmpAdaptorServer)adaptorServer ; SnmpPduPacket respPdu = null ; snmpServer.updateRequestCounters(reqPdu.type) ; if (reqPdu.varBindList != null) snmpServer.updateVarCounters(reqPdu.type, reqPdu.varBindList.length) ; if (checkPduType(reqPdu)) { respPdu = checkAcl(reqPdu) ; if (respPdu == null) { // reqPdu is accepted by ACLs if (mibs.size() < 1) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "makeResponsePdu", "Request " + reqPdu.requestId + " received but no MIB registered."); } return makeNoMibErrorPdu((SnmpPduRequest)reqPdu, userData); } switch(reqPdu.type) { case SnmpPduPacket.pduGetRequestPdu: case SnmpPduPacket.pduGetNextRequestPdu: case SnmpPduPacket.pduSetRequestPdu: respPdu = makeGetSetResponsePdu((SnmpPduRequest)reqPdu, userData) ; break ; case SnmpPduPacket.pduGetBulkRequestPdu: respPdu = makeGetBulkResponsePdu((SnmpPduBulk)reqPdu, userData) ; break ; } } else { // reqPdu is rejected by ACLs // respPdu contains the error response to be sent. // We send this response only if authResEnabled is true. if (!snmpServer.getAuthRespEnabled()) { // No response should be sent respPdu = null ; } if (snmpServer.getAuthTrapEnabled()) { // A trap must be sent try { snmpServer.snmpV1Trap(SnmpPduTrap. trapAuthenticationFailure, 0, new SnmpVarBindList()) ; } catch(Exception x) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponsePdu", "Failure when sending authentication trap", x); } } } } } return respPdu ; } // // Generates a response packet, filling the values in the // varbindlist with one of endOfMibView, noSuchObject, noSuchInstance // according to the value of <code>status</code> // // @param statusTag should be one of: // <li>SnmpDataTypeEnums.errEndOfMibViewTag</li> // <li>SnmpDataTypeEnums.errNoSuchObjectTag</li> // <li>SnmpDataTypeEnums.errNoSuchInstanceTag</li> // SnmpPduPacket makeErrorVarbindPdu(SnmpPduPacket req, int statusTag) { final SnmpVarBind[] vblist = req.varBindList; final int length = vblist.length; switch (statusTag) { case SnmpDataTypeEnums.errEndOfMibViewTag: for (int i=0 ; i<length ; i++) vblist[i].value = SnmpVarBind.endOfMibView; break; case SnmpDataTypeEnums.errNoSuchObjectTag: for (int i=0 ; i<length ; i++) vblist[i].value = SnmpVarBind.noSuchObject; break; case SnmpDataTypeEnums.errNoSuchInstanceTag: for (int i=0 ; i<length ; i++) vblist[i].value = SnmpVarBind.noSuchInstance; break; default: return newErrorResponsePdu(req,snmpRspGenErr,1); } return newValidResponsePdu(req,vblist); } // Generates an appropriate response when no mib is registered in // the adaptor. // // <li>If the version is V1:</li> // <ul><li>Generates a NoSuchName error V1 response PDU</li></ul> // <li>If the version is V2:</li> // <ul><li>If the request is a GET, fills the varbind list with // NoSuchObject's</li> // <li>If the request is a GET-NEXT/GET-BULK, fills the varbind // list with EndOfMibView's</li> // <li>If the request is a SET, generates a NoAccess error V2 // response PDU</li> // </ul> // // SnmpPduPacket makeNoMibErrorPdu(SnmpPduRequest req, Object userData) { // There is no agent registered // if (req.version == SnmpDefinitions.snmpVersionOne) { // Version 1: => NoSuchName return newErrorResponsePdu(req,snmpRspNoSuchName,1); } else if (req.version == SnmpDefinitions.snmpVersionTwo) { // Version 2: => depends on PDU type switch (req.type) { case pduSetRequestPdu :