--- old/src/jdk.snmp/share/classes/com/sun/jmx/snmp/daemon/SnmpRequestHandler.java 2014-10-15 14:06:13.000000000 +0200 +++ /dev/null 2014-10-15 14:06:13.000000000 +0200 @@ -1,1149 +0,0 @@ -/* - * Copyright (c) 1998, 2013, 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 subs = null; - - /** - * Reference on the MIBS - */ - private transient SnmpMibTree root; - - private transient InetAddressAcl 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, - InetAddressAcl 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 = new Vector<>(m); - subs= new Hashtable<>(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. - */ - @Override - 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; - 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; - 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 status - // - // @param statusTag should be one of: - //
  • SnmpDataTypeEnums.errEndOfMibViewTag
  • - //
  • SnmpDataTypeEnums.errNoSuchObjectTag
  • - //
  • SnmpDataTypeEnums.errNoSuchInstanceTag
  • - // - 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 ; iIf the version is V1: - //
    • Generates a NoSuchName error V1 response PDU
    - //
  • If the version is V2:
  • - //
    • If the request is a GET, fills the varbind list with - // NoSuchObject's
    • - //
    • If the request is a GET-NEXT/GET-BULK, fills the varbind - // list with EndOfMibView's
    • - //
    • If the request is a SET, generates a NoAccess error V2 - // response PDU
    • - //
    - // - // - 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 : - case pduWalkRequest : - // SET request => NoAccess - return - newErrorResponsePdu(req,snmpRspNoAccess,1); - case pduGetRequestPdu : - // GET request => NoSuchObject - return - makeErrorVarbindPdu(req,SnmpDataTypeEnums. - errNoSuchObjectTag); - case pduGetNextRequestPdu : - case pduGetBulkRequestPdu : - // GET-NEXT or GET-BULK => EndOfMibView - return - makeErrorVarbindPdu(req,SnmpDataTypeEnums. - errEndOfMibViewTag); - default: - } - } - // Something wrong here: => snmpRspGenErr - return newErrorResponsePdu(req,snmpRspGenErr,1); - } - - /** - * Here we make the response pdu from a get/set request pdu. - * At this level, the result is never null. - */ - private SnmpPduPacket makeGetSetResponsePdu(SnmpPduRequest req, - Object userData) { - - // Create the trhead group specific for handling sub-requests - // associated to the current request. Use the invoke id - // - // Nice idea to use a thread group on a request basis. - // However the impact on performance is terrible ! - // theGroup= new ThreadGroup(thread.getThreadGroup(), - // "request " + String.valueOf(req.requestId)); - - // Let's build the varBindList for the response pdu - // - - if (req.varBindList == null) { - // Good ! Let's make a full response pdu. - // - return newValidResponsePdu(req, null) ; - } - - // First we need to split the request into subrequests - // - splitRequest(req); - int nbSubRequest= subs.size(); - if (nbSubRequest == 1) - return turboProcessingGetSet(req,userData); - - - // Execute all the subrequests resulting from the split of the - // varbind list. - // - SnmpPduPacket result= executeSubRequest(req,userData); - if (result != null) - // It means that an error occurred. The error is already - // formatted by the executeSubRequest - // method. - return result; - - // So far so good. So we need to concatenate all the answers. - // - if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { - SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, - "makeGetSetResponsePdu", - "Build the unified response for request " + req.requestId); - } - return mergeResponses(req); - } - - /** - * The method runs all the sub-requests associated to the current - * instance of SnmpRequestHandler. - */ - private SnmpPduPacket executeSubRequest(SnmpPduPacket req, - Object userData) { - - int errorStatus = SnmpDefinitions.snmpRspNoError ; - - int i; - // If it's a set request, we must first check any varBind - // - if (req.type == pduSetRequestPdu) { - - i=0; - for(Enumeration e= subs.elements(); e.hasMoreElements() ; i++) { - // Indicate to the sub request that a check must be invoked ... - // OK we should have defined out own tag for that ! - // - SnmpSubRequestHandler sub= e.nextElement(); - sub.setUserData(userData); - sub.type= pduWalkRequest; - - sub.run(); - - sub.type= pduSetRequestPdu; - - if (sub.getErrorStatus() != SnmpDefinitions.snmpRspNoError) { - // No point to go any further. - // - if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { - SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, - "executeSubRequest", "an error occurs"); - } - - return newErrorResponsePdu(req, errorStatus, - sub.getErrorIndex() + 1) ; - } - } - }// end processing check operation for a set PDU. - - // Let's start the sub-requests. - // - i=0; - for(Enumeration e= subs.elements(); e.hasMoreElements() ;i++) { - SnmpSubRequestHandler sub= e.nextElement(); - /* NPCTE fix for bugId 4492741, esc 0, 16-August 2001 */ - sub.setUserData(userData); - /* end of NPCTE fix for bugId 4492741 */ - - sub.run(); - - if (sub.getErrorStatus() != SnmpDefinitions.snmpRspNoError) { - // No point to go any further. - // - if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { - SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, - "executeSubRequest", "an error occurs"); - } - - return newErrorResponsePdu(req, errorStatus, - sub.getErrorIndex() + 1) ; - } - } - - // everything is ok - // - return null; - } - - /** - * Optimize when there is only one sub request - */ - private SnmpPduPacket turboProcessingGetSet(SnmpPduRequest req, - Object userData) { - - int errorStatus; - SnmpSubRequestHandler sub = subs.elements().nextElement(); - sub.setUserData(userData); - - // Indicate to the sub request that a check must be invoked ... - // OK we should have defined out own tag for that ! - // - if (req.type == SnmpDefinitions.pduSetRequestPdu) { - sub.type= pduWalkRequest; - sub.run(); - sub.type= pduSetRequestPdu; - - // Check the error status. - // - errorStatus= sub.getErrorStatus(); - if (errorStatus != SnmpDefinitions.snmpRspNoError) { - // No point to go any further. - // - return newErrorResponsePdu(req, errorStatus, - sub.getErrorIndex() + 1) ; - } - } - - // process the operation - // - - sub.run(); - errorStatus= sub.getErrorStatus(); - if (errorStatus != SnmpDefinitions.snmpRspNoError) { - // No point to go any further. - // - if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { - SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, - "turboProcessingGetSet", "an error occurs"); - } - int realIndex= sub.getErrorIndex() + 1; - return newErrorResponsePdu(req, errorStatus, realIndex) ; - } - - // So far so good. So we need to concatenate all the answers. - // - - if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { - SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, - "turboProcessingGetSet", "build the unified response for request " - + req.requestId); - } - return mergeResponses(req); - } - - /** - * Here we make the response pdu for a bulk request. - * At this level, the result is never null. - */ - private SnmpPduPacket makeGetBulkResponsePdu(SnmpPduBulk req, - Object userData) { - - SnmpVarBind[] respVarBindList; - - // RFC 1905, Section 4.2.3, p14 - int L = req.varBindList.length ; - int N = Math.max(Math.min(req.nonRepeaters, L), 0) ; - int M = Math.max(req.maxRepetitions, 0) ; - int R = L - N ; - - if (req.varBindList == null) { - // Good ! Let's make a full response pdu. - // - return newValidResponsePdu(req, null) ; - } - - // Split the request into subrequests. - // - splitBulkRequest(req, N, M, R); - SnmpPduPacket result= executeSubRequest(req,userData); - if (result != null) - return result; - - respVarBindList= mergeBulkResponses(N + (M * R)); - - // Now we remove useless trailing endOfMibView. - // - int m2 ; // respVarBindList[m2] item and next are going to be removed - int t = respVarBindList.length ; - while ((t > N) && (respVarBindList[t-1]. - value.equals(SnmpVarBind.endOfMibView))) { - t-- ; - } - if (t == N) - m2 = N + R ; - else - m2 = N + ((t -1 -N) / R + 2) * R ; // Trivial, of course... - if (m2 < respVarBindList.length) { - SnmpVarBind[] truncatedList = new SnmpVarBind[m2] ; - for (int i = 0 ; i < m2 ; i++) { - truncatedList[i] = respVarBindList[i] ; - } - respVarBindList = truncatedList ; - } - - // Good ! Let's make a full response pdu. - // - return newValidResponsePdu(req, respVarBindList) ; - } - - /** - * Check the type of the pdu: only the get/set/bulk request - * are accepted. - */ - private boolean checkPduType(SnmpPduPacket pdu) { - - boolean result; - - switch(pdu.type) { - - case SnmpDefinitions.pduGetRequestPdu: - case SnmpDefinitions.pduGetNextRequestPdu: - case SnmpDefinitions.pduSetRequestPdu: - case SnmpDefinitions.pduGetBulkRequestPdu: - result = true ; - break; - - default: - if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { - SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, - "checkPduType", "cannot respond to this kind of PDU"); - } - result = false ; - break; - } - - return result ; - } - - /** - * Check if the specified pdu is conform to the ACL. - * This method returns null if the pdu is ok. If not, it returns - * the response pdu to be replied. - */ - private SnmpPduPacket checkAcl(SnmpPduPacket pdu) { - SnmpPduPacket response = null ; - String community = new String(pdu.community) ; - - // We check the pdu type and create an error response if - // the check failed. - // - if (ipacl != null) { - if (pdu.type == SnmpDefinitions.pduSetRequestPdu) { - if (!ipacl.checkWritePermission(pdu.address, community)) { - if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { - SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, - "checkAcl", "sender is " + pdu.address + - " with " + community +". Sender has no write permission"); - } - int err = SnmpSubRequestHandler. - mapErrorStatus(SnmpDefinitions. - snmpRspAuthorizationError, - pdu.version, pdu.type); - response = newErrorResponsePdu(pdu, err, 0) ; - } - else { - if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { - SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, - "checkAcl", "sender is " + pdu.address + - " with " + community +". Sender has write permission"); - } - } - } - else { - if (!ipacl.checkReadPermission(pdu.address, community)) { - if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { - SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, - "checkAcl", "sender is " + pdu.address + - " with " + community +". Sender has no read permission"); - } - int err = SnmpSubRequestHandler. - mapErrorStatus(SnmpDefinitions. - snmpRspAuthorizationError, - pdu.version, pdu.type); - response = newErrorResponsePdu(pdu, - err, - 0); - SnmpAdaptorServer snmpServer = - (SnmpAdaptorServer)adaptorServer; - snmpServer.updateErrorCounters(SnmpDefinitions. - snmpRspNoSuchName); - } - else { - if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { - SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, - "checkAcl", "sender is " + pdu.address + - " with " + community +". Sender has read permission"); - } - } - } - } - - // If the response is not null, this means the pdu is rejected. - // So let's update the statistics. - // - if (response != null) { - SnmpAdaptorServer snmpServer = (SnmpAdaptorServer)adaptorServer ; - snmpServer.incSnmpInBadCommunityUses(1) ; - if (ipacl.checkCommunity(community) == false) - snmpServer.incSnmpInBadCommunityNames(1) ; - } - - return response ; - } - - /** - * Make a response pdu with the specified error status and index. - * NOTE: the response pdu share its varBindList with the request pdu. - */ - private SnmpPduRequest newValidResponsePdu(SnmpPduPacket reqPdu, - SnmpVarBind[] varBindList) { - SnmpPduRequest result = new SnmpPduRequest() ; - - result.address = reqPdu.address ; - result.port = reqPdu.port ; - result.version = reqPdu.version ; - result.community = reqPdu.community ; - result.type = SnmpPduRequest.pduGetResponsePdu ; - result.requestId = reqPdu.requestId ; - result.errorStatus = SnmpDefinitions.snmpRspNoError ; - result.errorIndex = 0 ; - result.varBindList = varBindList ; - - ((SnmpAdaptorServer)adaptorServer). - updateErrorCounters(result.errorStatus) ; - - return result ; - } - - /** - * Make a response pdu with the specified error status and index. - * NOTE: the response pdu share its varBindList with the request pdu. - */ - private SnmpPduRequest newErrorResponsePdu(SnmpPduPacket req,int s,int i) { - SnmpPduRequest result = newValidResponsePdu(req, null) ; - result.errorStatus = s ; - result.errorIndex = i ; - result.varBindList = req.varBindList ; - - ((SnmpAdaptorServer)adaptorServer). - updateErrorCounters(result.errorStatus) ; - - return result ; - } - - private SnmpMessage newTooBigMessage(SnmpMessage reqMsg) - throws SnmpTooBigException { - SnmpMessage result = null ; - SnmpPduPacket reqPdu; - - try { - reqPdu = (SnmpPduPacket)pduFactory.decodeSnmpPdu(reqMsg) ; - if (reqPdu != null) { - SnmpPduPacket respPdu = newTooBigPdu(reqPdu) ; - result = (SnmpMessage)pduFactory. - encodeSnmpPdu(respPdu, packet.getData().length) ; - } - } - catch(SnmpStatusException x) { - // This should not occur because decodeIncomingRequest has normally - // been successfully called before. - if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { - SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, - "newTooBigMessage", "Internal error", x); - } - throw new InternalError(x) ; - } - - return result ; - } - - private SnmpPduPacket newTooBigPdu(SnmpPduPacket req) { - SnmpPduRequest result = - newErrorResponsePdu(req, SnmpDefinitions.snmpRspTooBig, 0) ; - result.varBindList = null ; - return result ; - } - - private SnmpPduPacket reduceResponsePdu(SnmpPduPacket req, - SnmpPduPacket resp, - int acceptedVbCount) - throws SnmpTooBigException { - - // Reduction can be attempted only on bulk response - // - if (req.type != SnmpPduPacket.pduGetBulkRequestPdu) { - if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { - SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, - "reduceResponsePdu", "cannot remove anything"); - } - throw new SnmpTooBigException(acceptedVbCount) ; - } - - // We're going to reduce the varbind list. - // First determine which items should be removed. - // Next duplicate and replace the existing list by the reduced one. - // - // acceptedVbCount is the number of varbind which have been - // successfully encoded before reaching bufferSize: - // * when it is >= 2, we split the varbindlist at this - // position (-1 to be safe), - // * when it is 1, we only put one (big?) item in the varbindlist - // * when it is 0 (in fact, acceptedVbCount is not available), - // we split the varbindlist by 2. - // - int vbCount; - if (acceptedVbCount >= 3) - vbCount = Math.min(acceptedVbCount - 1, resp.varBindList.length) ; - else if (acceptedVbCount == 1) - vbCount = 1 ; - else // acceptedCount == 0 ie it is unknown - vbCount = resp.varBindList.length / 2 ; - - if (vbCount < 1) { - if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { - SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, - "reduceResponsePdu", "cannot remove anything"); - } - throw new SnmpTooBigException(acceptedVbCount) ; - } - else { - SnmpVarBind[] newVbList = new SnmpVarBind[vbCount] ; - for (int i = 0 ; i < vbCount ; i++) { - newVbList[i] = resp.varBindList[i] ; - } - if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { - SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, - "reduceResponsePdu", (resp.varBindList.length - newVbList.length) + - " items have been removed"); - } - resp.varBindList = newVbList ; - } - - return resp ; - } - - /** - * The method takes the incoming requests and split it into subrequests. - */ - private void splitRequest(SnmpPduRequest req) { - - int nbAgents= mibs.size(); - SnmpMibAgent agent = mibs.firstElement(); - if (nbAgents == 1) { - // Take all the oids contained in the request and - // - subs.put(agent, new SnmpSubRequestHandler(agent, req, true)); - return; - } - - // For the get next operation we are going to send the varbind list - // to all agents - // - if (req.type == pduGetNextRequestPdu) { - for(Enumeration e= mibs.elements(); e.hasMoreElements(); ) { - final SnmpMibAgent ag= e.nextElement(); - subs.put(ag, new SnmpSubNextRequestHandler(adaptor, ag, req)); - } - return; - } - - int nbReqs= req.varBindList.length; - SnmpVarBind[] vars= req.varBindList; - SnmpSubRequestHandler sub; - for(int i=0; i < nbReqs; i++) { - agent= root.getAgentMib(vars[i].oid); - sub= subs.get(agent); - if (sub == null) { - // We need to create the sub request handler and update - // the hashtable - // - sub= new SnmpSubRequestHandler(agent, req); - subs.put(agent, sub); - } - - // Update the translation table within the subrequest - // - sub.updateRequest(vars[i], i); - } - } - - /** - * The method takes the incoming get bulk requests and split it into - * subrequests. - */ - private void splitBulkRequest(SnmpPduBulk req, - int nonRepeaters, - int maxRepetitions, - int R) { - // Send the getBulk to all agents - // - for(Enumeration e= mibs.elements(); e.hasMoreElements(); ) { - final SnmpMibAgent agent = e.nextElement(); - - if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { - SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, - "splitBulkRequest", "Create a sub with : " + agent + " " + nonRepeaters - + " " + maxRepetitions + " " + R); - } - - subs.put(agent, - new SnmpSubBulkRequestHandler(adaptor, - agent, - req, - nonRepeaters, - maxRepetitions, - R)); - } - } - - private SnmpPduPacket mergeResponses(SnmpPduRequest req) { - - if (req.type == pduGetNextRequestPdu) { - return mergeNextResponses(req); - } - - SnmpVarBind[] result= req.varBindList; - - // Go through the list of subrequests and concatenate. - // Hopefully, by now all the sub-requests should be finished - // - for(Enumeration e= subs.elements(); e.hasMoreElements();) { - SnmpSubRequestHandler sub= e.nextElement(); - sub.updateResult(result); - } - return newValidResponsePdu(req,result); - } - - private SnmpPduPacket mergeNextResponses(SnmpPduRequest req) { - int max= req.varBindList.length; - SnmpVarBind[] result= new SnmpVarBind[max]; - - // Go through the list of subrequests and concatenate. - // Hopefully, by now all the sub-requests should be finished - // - for(Enumeration e= subs.elements(); e.hasMoreElements();) { - SnmpSubRequestHandler sub= e.nextElement(); - sub.updateResult(result); - } - - if (req.version == snmpVersionTwo) { - return newValidResponsePdu(req,result); - } - - // In v1 make sure there is no endOfMibView ... - // - for(int i=0; i < max; i++) { - SnmpValue val= result[i].value; - if (val == SnmpVarBind.endOfMibView) - return newErrorResponsePdu(req, - SnmpDefinitions.snmpRspNoSuchName, i+1); - } - - // So far so good ... - // - return newValidResponsePdu(req,result); - } - - private SnmpVarBind[] mergeBulkResponses(int size) { - // Let's allocate the array for storing the result - // - SnmpVarBind[] result= new SnmpVarBind[size]; - for(int i= size-1; i >=0; --i) { - result[i]= new SnmpVarBind(); - result[i].value= SnmpVarBind.endOfMibView; - } - - // Go through the list of subrequests and concatenate. - // Hopefully, by now all the sub-requests should be finished - // - for(Enumeration e= subs.elements(); e.hasMoreElements();) { - SnmpSubRequestHandler sub= e.nextElement(); - sub.updateResult(result); - } - - return result; - } - - @Override - protected String makeDebugTag() { - return "SnmpRequestHandler[" + adaptorServer.getProtocol() + ":" + - adaptorServer.getPort() + "]"; - } - - @Override - Thread createThread(Runnable r) { - return null; - } - - static final private String InterruptSysCallMsg = - "Interrupted system call"; -}