FileDocCategorySizeDatePackage
SnmpRequestHandler.javaAPI DocJava SE 5 API39670Fri Aug 26 14:55:06 BST 2005com.sun.jmx.snmp.daemon

SnmpRequestHandler

public class SnmpRequestHandler extends ClientHandler implements com.sun.jmx.snmp.SnmpDefinitions

Fields Summary
private transient DatagramSocket
socket
private transient DatagramPacket
packet
private transient Vector
mibs
private transient Hashtable
subs
Contains the list of sub-requests associated to the current request.
private transient SnmpMibTree
root
Reference on the MIBS
private transient Object
ipacl
private transient com.sun.jmx.snmp.SnmpPduFactory
pduFactory
private transient com.sun.jmx.snmp.agent.SnmpUserDataFactory
userDataFactory
private transient SnmpAdaptorServer
adaptor
private static final String
InterruptSysCallMsg
private static final com.sun.jmx.snmp.SnmpStatusException
noSuchNameException
Constructors Summary
public SnmpRequestHandler(SnmpAdaptorServer server, int id, DatagramSocket s, DatagramPacket p, SnmpMibTree tree, Vector m, Object a, com.sun.jmx.snmp.SnmpPduFactory factory, com.sun.jmx.snmp.agent.SnmpUserDataFactory dataFactory, MBeanServer f, ObjectName n)
Full constructor

           
         
                                 
                                    
                                
                               
                                  
    
        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(mibs.size());
        ipacl = a;
        pduFactory = factory ;
        userDataFactory = dataFactory ;
        //thread.start();
    
Methods Summary
private com.sun.jmx.snmp.SnmpPduPacketcheckAcl(com.sun.jmx.snmp.SnmpPduPacket pdu)
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.

        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 (!((InetAddressAcl)ipacl).
		    checkWritePermission(pdu.address, community)) {
                    if (isTraceOn()) {
                        trace("checkAcl", "sender is " + pdu.address + 
			      " with " + community);
                        trace("checkAcl", "sender has no write permission");
                    }
		    int err = SnmpSubRequestHandler.
			mapErrorStatus(SnmpDefinitions.
				       snmpRspAuthorizationError, 
				       pdu.version, pdu.type);
                    response = newErrorResponsePdu(pdu, err, 0) ;
                }
                else {
                    if (isTraceOn()) {
                        trace("checkAcl", "sender is " + pdu.address + 
			      " with " + community);
                        trace("checkAcl", "sender has write permission");
                    }
                }
            }
            else {
                if (!((InetAddressAcl)ipacl).checkReadPermission(pdu.address, community)) {
                    if (isTraceOn()) {
                        trace("checkAcl", "sender is " + pdu.address +
			      " with " + community);
                        trace("checkAcl", "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 (isTraceOn()) {
                        trace("checkAcl", "sender is " + pdu.address +
			      " with " + community);
                        trace("checkAcl", "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 (((InetAddressAcl)ipacl).checkCommunity(community) == false)
                snmpServer.incSnmpInBadCommunityNames(1) ;
        }
    
        return response ;
    
private booleancheckPduType(com.sun.jmx.snmp.SnmpPduPacket pdu)
Check the type of the pdu: only the get/set/bulk request are accepted.


        boolean result = true ;

        switch(pdu.type) {
    
        case SnmpDefinitions.pduGetRequestPdu:
        case SnmpDefinitions.pduGetNextRequestPdu:
        case SnmpDefinitions.pduSetRequestPdu:
        case SnmpDefinitions.pduGetBulkRequestPdu:
            result = true ;
            break;

        default:
            if (isDebugOn()) {
                debug("checkPduType", "cannot respond to this kind of PDU");
            }
            result = false ;
            break;
        }
    
        return result ;
    
java.lang.ThreadcreateThread(java.lang.Runnable r)

	return null;
    
protected voiddebug(java.lang.String clz, java.lang.String func, java.lang.String info)

        Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP, clz,func,info);
    
protected voiddebug(java.lang.String clz, java.lang.String func, java.lang.Throwable exception)

        Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP, clz, func,
		   exception);
    
protected voiddebug(java.lang.String func, java.lang.String info)

        debug(dbgTag, func, info);
    
protected voiddebug(java.lang.String func, java.lang.Throwable exception)

        debug(dbgTag, func, exception);
    
public voiddoRun()
Treat the request available in 'packet' and send the result back to the client. Note: we overwrite 'packet' with the response bytes.

  
        // Trace the input packet
        //
        if (isTraceOn()) {
            trace("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 (isTraceOn() && (respPacket != null)) {
            trace("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 (isDebugOn()) {
                    if (e.getMessage().equals(InterruptSysCallMsg))
                        debug("doRun", "interrupted");
                    else {
                        debug("doRun", "i/o exception");
                        debug("doRun", e);
                    }
                }
            }
            catch(InterruptedIOException e) {
                if (isDebugOn()) {
                    debug("doRun", "interrupted");
                }
            }
            catch(Exception e) {
                if (isDebugOn()) {
                    debug("doRun", "failure when sending response");
                    debug("doRun", e);
                }
            }
        }
    
private com.sun.jmx.snmp.SnmpPduPacketexecuteSubRequest(com.sun.jmx.snmp.SnmpPduPacket req, java.lang.Object userData)
The method runs all the sub-requests associated to the current instance of SnmpRequestHandler.

    
        int errorStatus = SnmpDefinitions.snmpRspNoError ;
        int nbSubRequest= subs.size();
            
	int i=0;
        // 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= (SnmpSubRequestHandler) 
		    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 (isDebugOn()) {
			debug("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= (SnmpSubRequestHandler) 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 (isDebugOn()) {
                    debug("executeSubRequest", "an error occurs");
                }

                return newErrorResponsePdu(req, errorStatus, 
					   sub.getErrorIndex() + 1) ;
            }
	}
    
        // everything is ok
        //
        return null;
    
protected booleanisDebugOn()

        return Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP);
    
protected booleanisTraceOn()

        return Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_ADAPTOR_SNMP);
    
protected java.lang.StringmakeDebugTag()

        return "SnmpRequestHandler[" + adaptorServer.getProtocol() + ":" + 
	    adaptorServer.getPort() + "]";
    
com.sun.jmx.snmp.SnmpPduPacketmakeErrorVarbindPdu(com.sun.jmx.snmp.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);
    
private com.sun.jmx.snmp.SnmpPduPacketmakeGetBulkResponsePdu(com.sun.jmx.snmp.SnmpPduBulk req, java.lang.Object userData)
Here we make the response pdu for a bulk request. At this level, the result is never null.

   
        SnmpVarBind[] respVarBindList = null ;
    
        // 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) ;
    
private com.sun.jmx.snmp.SnmpPduPacketmakeGetSetResponsePdu(com.sun.jmx.snmp.SnmpPduRequest req, java.lang.Object userData)
Here we make the response pdu from a get/set request pdu. At this level, the result is never null.

   
        // 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 occured. The error is already 
	    // formatted by the executeSubRequest
            // method.
            return result;
        
        // So far so good. So we need to concatenate all the answers.
        //
        if (isTraceOn()) {
            trace("makeGetSetResponsePdu", 
		  "Build the unified response for request " + req.requestId);
        }
        return mergeResponses(req);
    
com.sun.jmx.snmp.SnmpPduPacketmakeNoMibErrorPdu(com.sun.jmx.snmp.SnmpPduRequest req, java.lang.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);
    
private com.sun.jmx.snmp.SnmpMessagemakeResponseMessage(com.sun.jmx.snmp.SnmpMessage reqMsg)
Here we make a response message from a request message. We return null if there is no message to reply.

        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 (isDebugOn()) {
                debug("makeResponseMessage", "message decoding failed");
		debug("makeResponseMessage",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 (isDebugOn()) {
                    debug("makeResponseMessage", 
			  "failure when encoding the response message");
                    debug("makeResponseMessage", x);
                }
            }
            catch(SnmpTooBigException x) {
                if (isDebugOn()) {
                    debug("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 (isDebugOn()) {
                        debug("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 (isDebugOn()) {
                                debug("makeResponseMessage", 
				      "response message is still too big");
                            }
                            old= pos;
                            pos= xx.getVarBindCount();
                            if (isDebugOn()) {
                                debug("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 (isDebugOn()) {
                        debug("makeResponseMessage", 
			      "failure when encoding the response message");
                        debug("makeResponseMessage", xx);
                    }
                }
                catch(SnmpTooBigException xx) {
                    try {
                        respPdu = newTooBigPdu(reqPdu) ;
                        respMsg = (SnmpMessage)pduFactory.
			    encodeSnmpPdu(respPdu, packet.getData().length) ;
                    }
                    catch(SnmpTooBigException xxx) {
                        respMsg = null ;
                        if (isDebugOn()) {
                            debug("makeResponseMessage", 
				  "'too big' is 'too big' !!!");
                        }
			adaptor.incSnmpSilentDrops(1);
                    }
                    catch(Exception xxx) {
			debug("makeResponseMessage", xxx);
                        respMsg = null ;
                    }
                }
                catch(Exception xx) {
		    debug("makeResponseMessage", xx);
                    respMsg = null ;
                }
            }
        }
        return respMsg ;
    
private java.net.DatagramPacketmakeResponsePacket(java.net.DatagramPacket reqPacket)
Here we make a response packet from a request packet. We return null if there no response packet to sent.

        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 (isDebugOn()) {
                debug("makeResponsePacket", "packet decoding failed");
		debug("makeResponsePacket", 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 (isDebugOn()) {
                    debug("makeResponsePacket", "response message is too big");
                }
                try {
                    respMsg = newTooBigMessage(reqMsg) ;
                    reqPacket.setLength(respMsg.encodeMessage(reqPacket.getData())) ;
                    respPacket = reqPacket ;
                }
                catch(SnmpTooBigException xx) {
                    if (isDebugOn()) {
                        debug("makeResponsePacket", "'too big' is 'too big' !!!");
                    }
		    adaptor.incSnmpSilentDrops(1);
                }
            }
        }
    
        return respPacket ;
    
private com.sun.jmx.snmp.SnmpPduPacketmakeResponsePdu(com.sun.jmx.snmp.SnmpPduPacket reqPdu, java.lang.Object userData)
Here we make a response pdu from a request pdu. We return null if there is no pdu to reply.

        
        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 (isTraceOn()) {
                        trace("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 (isDebugOn()) {
                            debug("makeResponsePdu", 
				  "failure when sending authentication trap");
                            debug("makeResponsePdu", x);
                        }
                    }
                }
            }
        }
        return respPdu ;
    
private com.sun.jmx.snmp.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= (SnmpSubRequestHandler) e.nextElement();
            sub.updateResult(result);
        }
   
        return result;
    
private com.sun.jmx.snmp.SnmpPduPacketmergeNextResponses(com.sun.jmx.snmp.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= (SnmpSubRequestHandler) 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 com.sun.jmx.snmp.SnmpPduPacketmergeResponses(com.sun.jmx.snmp.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= (SnmpSubRequestHandler) e.nextElement();
            sub.updateResult(result);
        }
        return newValidResponsePdu(req,result);
    
private com.sun.jmx.snmp.SnmpPduRequestnewErrorResponsePdu(com.sun.jmx.snmp.SnmpPduPacket req, int s, int i)
Make a response pdu with the specified error status and index. NOTE: the response pdu share its varBindList with the request pdu.

        SnmpPduRequest result = newValidResponsePdu(req, null) ;
        result.errorStatus = s ;
        result.errorIndex = i ;
        result.varBindList = req.varBindList ;

        ((SnmpAdaptorServer)adaptorServer).
	    updateErrorCounters(result.errorStatus) ;
    
        return result ;
    
private com.sun.jmx.snmp.SnmpMessagenewTooBigMessage(com.sun.jmx.snmp.SnmpMessage reqMsg)

        SnmpMessage result = null ;
        SnmpPduPacket reqPdu = null ;
    
        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.
	    debug("InternalError: ", x);
            throw new InternalError() ;
        }
    
        return result ;
    
private com.sun.jmx.snmp.SnmpPduPacketnewTooBigPdu(com.sun.jmx.snmp.SnmpPduPacket req)

        SnmpPduRequest result = 
	    newErrorResponsePdu(req, SnmpDefinitions.snmpRspTooBig, 0) ;
        result.varBindList = null ;
        return result ;
    
private com.sun.jmx.snmp.SnmpPduRequestnewValidResponsePdu(com.sun.jmx.snmp.SnmpPduPacket reqPdu, com.sun.jmx.snmp.SnmpVarBind[] varBindList)
Make a response pdu with the specified error status and index. NOTE: the response pdu share its varBindList with the request pdu.

        SnmpPduRequest result = new SnmpPduRequest() ;
    
        result.address = reqPdu.address ;
        result.port = reqPdu.port ;
        result.version = reqPdu.version ;
        result.community = reqPdu.community ;
        result.type = result.pduGetResponsePdu ;
        result.requestId = reqPdu.requestId ;
        result.errorStatus = SnmpDefinitions.snmpRspNoError ;
        result.errorIndex = 0 ;
        result.varBindList = varBindList ;
    
        ((SnmpAdaptorServer)adaptorServer).
	    updateErrorCounters(result.errorStatus) ;
    
        return result ;
    
private com.sun.jmx.snmp.SnmpPduPacketreduceResponsePdu(com.sun.jmx.snmp.SnmpPduPacket req, com.sun.jmx.snmp.SnmpPduPacket resp, int acceptedVbCount)

  
        // Reduction can be attempted only on bulk response
        //
        if (req.type != req.pduGetBulkRequestPdu) {
            if (isDebugOn()) {
                debug("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 = resp.varBindList.length ;
        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 (isDebugOn()) {
                debug("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 (isDebugOn()) {
                debug("reduceResponsePdu", 
		      (resp.varBindList.length - newVbList.length) + 
		      " items have been removed");
            }
            resp.varBindList = newVbList ;
        }
    
        return resp ;
    
private voidsplitBulkRequest(com.sun.jmx.snmp.SnmpPduBulk req, int nonRepeaters, int maxRepetitions, int R)
The method takes the incoming get bulk requests and split it into subrequests.

	// Send the getBulk to all agents
	//
	for(Enumeration e= mibs.elements(); e.hasMoreElements(); ) {
	    SnmpMibAgent agent = (SnmpMibAgent) e.nextElement();

	    if(isDebugOn())
		trace("splitBulkRequest", "Create a sub with : " + 
		      agent + " " + nonRepeaters + " " +
		      maxRepetitions + " " + R);

	    subs.put(agent, 
		     new SnmpSubBulkRequestHandler(adaptor,
						   agent, 
						   req, 
						   nonRepeaters, 
						   maxRepetitions, 
						   R));
	}
	return;
    
private voidsplitRequest(com.sun.jmx.snmp.SnmpPduRequest req)
The method takes the incoming requests and split it into subrequests.

    
        int nbAgents= mibs.size();
        SnmpMibAgent agent= (SnmpMibAgent) 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(); ) {
                SnmpMibAgent ag= (SnmpMibAgent) 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= (SnmpSubRequestHandler) 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);
        }
    
protected voidtrace(java.lang.String clz, java.lang.String func, java.lang.String info)

        Trace.send(Trace.LEVEL_TRACE, Trace.INFO_ADAPTOR_SNMP, clz,func,info);
    
protected voidtrace(java.lang.String func, java.lang.String info)

        trace(dbgTag, func, info);
    
private com.sun.jmx.snmp.SnmpPduPacketturboProcessingGetSet(com.sun.jmx.snmp.SnmpPduRequest req, java.lang.Object userData)
Optimize when there is only one sub request

  
        int errorStatus = SnmpDefinitions.snmpRspNoError ;
        SnmpSubRequestHandler sub= (SnmpSubRequestHandler) 
	    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 (isDebugOn()) {
                debug("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 (isTraceOn()) {
            trace("turboProcessingGetSet", 
		  "build the unified response for request " + req.requestId);
        }
        return mergeResponses(req);