You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
631 lines
23 KiB
631 lines
23 KiB
/*
|
|
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
|
|
|
|
package com.sun.jmx.snmp.daemon;
|
|
|
|
|
|
|
|
// java import
|
|
//
|
|
import java.util.logging.Level;
|
|
import java.util.Vector;
|
|
|
|
// jmx imports
|
|
//
|
|
import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER;
|
|
import com.sun.jmx.snmp.SnmpPdu;
|
|
import com.sun.jmx.snmp.SnmpVarBind;
|
|
import com.sun.jmx.snmp.SnmpDefinitions;
|
|
import com.sun.jmx.snmp.SnmpStatusException;
|
|
import com.sun.jmx.snmp.SnmpEngine;
|
|
|
|
// SNMP Runtime import
|
|
//
|
|
import com.sun.jmx.snmp.agent.SnmpMibAgent;
|
|
import com.sun.jmx.snmp.agent.SnmpMibRequest;
|
|
import com.sun.jmx.snmp.ThreadContext;
|
|
import com.sun.jmx.snmp.internal.SnmpIncomingRequest;
|
|
|
|
class SnmpSubRequestHandler implements SnmpDefinitions, Runnable {
|
|
|
|
protected SnmpIncomingRequest incRequest = null;
|
|
protected SnmpEngine engine = null;
|
|
/**
|
|
* V3 enabled Adaptor. Each Oid is added using updateRequest method.
|
|
*/
|
|
protected SnmpSubRequestHandler(SnmpEngine engine,
|
|
SnmpIncomingRequest incRequest,
|
|
SnmpMibAgent agent,
|
|
SnmpPdu req) {
|
|
this(agent, req);
|
|
init(engine, incRequest);
|
|
}
|
|
|
|
/**
|
|
* V3 enabled Adaptor.
|
|
*/
|
|
protected SnmpSubRequestHandler(SnmpEngine engine,
|
|
SnmpIncomingRequest incRequest,
|
|
SnmpMibAgent agent,
|
|
SnmpPdu req,
|
|
boolean nouse) {
|
|
this(agent, req, nouse);
|
|
init(engine, incRequest);
|
|
}
|
|
/**
|
|
* SNMP V1/V2 . To be called with updateRequest.
|
|
*/
|
|
protected SnmpSubRequestHandler(SnmpMibAgent agent, SnmpPdu req) {
|
|
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
|
|
SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(),
|
|
"constructor", "creating instance for request " + String.valueOf(req.requestId));
|
|
}
|
|
|
|
version= req.version;
|
|
type= req.type;
|
|
this.agent= agent;
|
|
|
|
// We get a ref on the pdu in order to pass it to SnmpMibRequest.
|
|
reqPdu = req;
|
|
|
|
//Pre-allocate room for storing varbindlist and translation table.
|
|
//
|
|
int length= req.varBindList.length;
|
|
translation= new int[length];
|
|
varBind= new NonSyncVector<SnmpVarBind>(length);
|
|
}
|
|
|
|
/**
|
|
* SNMP V1/V2 The constructor initialize the subrequest with the whole varbind list contained
|
|
* in the original request.
|
|
*/
|
|
@SuppressWarnings("unchecked") // cast to NonSyncVector<SnmpVarBind>
|
|
protected SnmpSubRequestHandler(SnmpMibAgent agent,
|
|
SnmpPdu req,
|
|
boolean nouse) {
|
|
this(agent,req);
|
|
|
|
// The translation table is easy in this case ...
|
|
//
|
|
int max= translation.length;
|
|
SnmpVarBind[] list= req.varBindList;
|
|
for(int i=0; i < max; i++) {
|
|
translation[i]= i;
|
|
((NonSyncVector<SnmpVarBind>)varBind).addNonSyncElement(list[i]);
|
|
}
|
|
}
|
|
|
|
SnmpMibRequest createMibRequest(Vector<SnmpVarBind> vblist,
|
|
int protocolVersion,
|
|
Object userData) {
|
|
|
|
// This is an optimization:
|
|
// The SnmpMibRequest created in the check() phase is
|
|
// reused in the set() phase.
|
|
//
|
|
if (type == pduSetRequestPdu && mibRequest != null)
|
|
return mibRequest;
|
|
|
|
//This is a request comming from an SnmpV3AdaptorServer.
|
|
//Full power.
|
|
SnmpMibRequest result = null;
|
|
if(incRequest != null) {
|
|
result = SnmpMibAgent.newMibRequest(engine,
|
|
reqPdu,
|
|
vblist,
|
|
protocolVersion,
|
|
userData,
|
|
incRequest.getPrincipal(),
|
|
incRequest.getSecurityLevel(),
|
|
incRequest.getSecurityModel(),
|
|
incRequest.getContextName(),
|
|
incRequest.getAccessContext());
|
|
} else {
|
|
result = SnmpMibAgent.newMibRequest(reqPdu,
|
|
vblist,
|
|
protocolVersion,
|
|
userData);
|
|
}
|
|
// If we're doing the check() phase, we store the SnmpMibRequest
|
|
// so that we can reuse it in the set() phase.
|
|
//
|
|
if (type == pduWalkRequest)
|
|
mibRequest = result;
|
|
|
|
return result;
|
|
}
|
|
|
|
void setUserData(Object userData) {
|
|
data = userData;
|
|
}
|
|
|
|
public void run() {
|
|
|
|
try {
|
|
final ThreadContext oldContext =
|
|
ThreadContext.push("SnmpUserData",data);
|
|
try {
|
|
switch(type) {
|
|
case pduGetRequestPdu:
|
|
// Invoke a get operation
|
|
//
|
|
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
|
|
SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(),
|
|
"run", "[" + Thread.currentThread() +
|
|
"]:get operation on " + agent.getMibName());
|
|
}
|
|
|
|
agent.get(createMibRequest(varBind,version,data));
|
|
break;
|
|
|
|
case pduGetNextRequestPdu:
|
|
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
|
|
SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(),
|
|
"run", "[" + Thread.currentThread() +
|
|
"]:getNext operation on " + agent.getMibName());
|
|
}
|
|
//#ifdef DEBUG
|
|
agent.getNext(createMibRequest(varBind,version,data));
|
|
break;
|
|
|
|
case pduSetRequestPdu:
|
|
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
|
|
SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(),
|
|
"run", "[" + Thread.currentThread() +
|
|
"]:set operation on " + agent.getMibName());
|
|
}
|
|
agent.set(createMibRequest(varBind,version,data));
|
|
break;
|
|
|
|
case pduWalkRequest:
|
|
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
|
|
SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(),
|
|
"run", "[" + Thread.currentThread() +
|
|
"]:check operation on " + agent.getMibName());
|
|
}
|
|
agent.check(createMibRequest(varBind,version,data));
|
|
break;
|
|
|
|
default:
|
|
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
|
|
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpSubRequestHandler.class.getName(),
|
|
"run", "[" + Thread.currentThread() +
|
|
"]:unknown operation (" + type + ") on " +
|
|
agent.getMibName());
|
|
}
|
|
errorStatus= snmpRspGenErr;
|
|
errorIndex= 1;
|
|
break;
|
|
|
|
}// end of switch
|
|
|
|
} finally {
|
|
ThreadContext.restore(oldContext);
|
|
}
|
|
} catch(SnmpStatusException x) {
|
|
errorStatus = x.getStatus() ;
|
|
errorIndex= x.getErrorIndex();
|
|
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
|
|
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpSubRequestHandler.class.getName(),
|
|
"run", "[" + Thread.currentThread() +
|
|
"]:an Snmp error occurred during the operation", x);
|
|
}
|
|
}
|
|
catch(Exception x) {
|
|
errorStatus = SnmpDefinitions.snmpRspGenErr ;
|
|
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
|
|
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpSubRequestHandler.class.getName(),
|
|
"run", "[" + Thread.currentThread() +
|
|
"]:a generic error occurred during the operation", x);
|
|
}
|
|
}
|
|
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
|
|
SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(),
|
|
"run", "[" + Thread.currentThread() + "]:operation completed");
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------
|
|
//
|
|
// This function does a best-effort to map global error status
|
|
// to SNMP v1 valid global error status.
|
|
//
|
|
// An SnmpStatusException can contain either:
|
|
// <li> v2 local error codes (that should be stored in the varbind)</li>
|
|
// <li> v2 global error codes </li>
|
|
// <li> v1 global error codes </li>
|
|
//
|
|
// v2 local error codes (noSuchInstance, noSuchObject) are
|
|
// transformed in a global v1 snmpRspNoSuchName error.
|
|
//
|
|
// v2 global error codes are transformed in the following way:
|
|
//
|
|
// If the request was a GET/GETNEXT then either
|
|
// snmpRspNoSuchName or snmpRspGenErr is returned.
|
|
//
|
|
// Otherwise:
|
|
// snmpRspNoAccess, snmpRspInconsistentName
|
|
// => snmpRspNoSuchName
|
|
// snmpRspAuthorizationError, snmpRspNotWritable, snmpRspNoCreation
|
|
// => snmpRspReadOnly (snmpRspNoSuchName for GET/GETNEXT)
|
|
// snmpRspWrong*
|
|
// => snmpRspBadValue (snmpRspNoSuchName for GET/GETNEXT)
|
|
// snmpRspResourceUnavailable, snmpRspRspCommitFailed,
|
|
// snmpRspUndoFailed
|
|
// => snmpRspGenErr
|
|
//
|
|
// -------------------------------------------------------------
|
|
//
|
|
static final int mapErrorStatusToV1(int errorStatus, int reqPduType) {
|
|
// Map v2 codes onto v1 codes
|
|
//
|
|
if (errorStatus == SnmpDefinitions.snmpRspNoError)
|
|
return SnmpDefinitions.snmpRspNoError;
|
|
|
|
if (errorStatus == SnmpDefinitions.snmpRspGenErr)
|
|
return SnmpDefinitions.snmpRspGenErr;
|
|
|
|
if (errorStatus == SnmpDefinitions.snmpRspNoSuchName)
|
|
return SnmpDefinitions.snmpRspNoSuchName;
|
|
|
|
if ((errorStatus == SnmpStatusException.noSuchInstance) ||
|
|
(errorStatus == SnmpStatusException.noSuchObject) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspNoAccess) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspInconsistentName) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspAuthorizationError)){
|
|
|
|
return SnmpDefinitions.snmpRspNoSuchName;
|
|
|
|
} else if ((errorStatus ==
|
|
SnmpDefinitions.snmpRspAuthorizationError) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspNotWritable)) {
|
|
|
|
if (reqPduType == SnmpDefinitions.pduWalkRequest)
|
|
return SnmpDefinitions.snmpRspReadOnly;
|
|
else
|
|
return SnmpDefinitions.snmpRspNoSuchName;
|
|
|
|
} else if ((errorStatus == SnmpDefinitions.snmpRspNoCreation)) {
|
|
|
|
return SnmpDefinitions.snmpRspNoSuchName;
|
|
|
|
} else if ((errorStatus == SnmpDefinitions.snmpRspWrongType) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspWrongLength) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspWrongEncoding) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspWrongValue) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspWrongLength) ||
|
|
(errorStatus ==
|
|
SnmpDefinitions.snmpRspInconsistentValue)) {
|
|
|
|
if ((reqPduType == SnmpDefinitions.pduSetRequestPdu) ||
|
|
(reqPduType == SnmpDefinitions.pduWalkRequest))
|
|
return SnmpDefinitions.snmpRspBadValue;
|
|
else
|
|
return SnmpDefinitions.snmpRspNoSuchName;
|
|
|
|
} else if ((errorStatus ==
|
|
SnmpDefinitions.snmpRspResourceUnavailable) ||
|
|
(errorStatus ==
|
|
SnmpDefinitions.snmpRspCommitFailed) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspUndoFailed)) {
|
|
|
|
return SnmpDefinitions.snmpRspGenErr;
|
|
|
|
}
|
|
|
|
// At this point we should have a V1 error code
|
|
//
|
|
if (errorStatus == SnmpDefinitions.snmpRspTooBig)
|
|
return SnmpDefinitions.snmpRspTooBig;
|
|
|
|
if( (errorStatus == SnmpDefinitions.snmpRspBadValue) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspReadOnly)) {
|
|
if ((reqPduType == SnmpDefinitions.pduSetRequestPdu) ||
|
|
(reqPduType == SnmpDefinitions.pduWalkRequest))
|
|
return errorStatus;
|
|
else
|
|
return SnmpDefinitions.snmpRspNoSuchName;
|
|
}
|
|
|
|
// We have a snmpRspGenErr, or something which is not defined
|
|
// in RFC1905 => return a snmpRspGenErr
|
|
//
|
|
return SnmpDefinitions.snmpRspGenErr;
|
|
|
|
}
|
|
|
|
// -------------------------------------------------------------
|
|
//
|
|
// This function does a best-effort to map global error status
|
|
// to SNMP v2 valid global error status.
|
|
//
|
|
// An SnmpStatusException can contain either:
|
|
// <li> v2 local error codes (that should be stored in the varbind)</li>
|
|
// <li> v2 global error codes </li>
|
|
// <li> v1 global error codes </li>
|
|
//
|
|
// v2 local error codes (noSuchInstance, noSuchObject)
|
|
// should not raise this level: they should have been stored in the
|
|
// varbind earlier. If they, do there is nothing much we can do except
|
|
// to transform them into:
|
|
// <li> a global snmpRspGenErr (if the request is a GET/GETNEXT) </li>
|
|
// <li> a global snmpRspNoSuchName otherwise. </li>
|
|
//
|
|
// v2 global error codes are transformed in the following way:
|
|
//
|
|
// If the request was a GET/GETNEXT then snmpRspGenErr is returned.
|
|
// (snmpRspGenErr is the only global error that is expected to be
|
|
// raised by a GET/GETNEXT request).
|
|
//
|
|
// Otherwise the v2 code itself is returned
|
|
//
|
|
// v1 global error codes are transformed in the following way:
|
|
//
|
|
// snmpRspNoSuchName
|
|
// => snmpRspNoAccess (snmpRspGenErr for GET/GETNEXT)
|
|
// snmpRspReadOnly
|
|
// => snmpRspNotWritable (snmpRspGenErr for GET/GETNEXT)
|
|
// snmpRspBadValue
|
|
// => snmpRspWrongValue (snmpRspGenErr for GET/GETNEXT)
|
|
//
|
|
// -------------------------------------------------------------
|
|
//
|
|
static final int mapErrorStatusToV2(int errorStatus, int reqPduType) {
|
|
// Map v1 codes onto v2 codes
|
|
//
|
|
if (errorStatus == SnmpDefinitions.snmpRspNoError)
|
|
return SnmpDefinitions.snmpRspNoError;
|
|
|
|
if (errorStatus == SnmpDefinitions.snmpRspGenErr)
|
|
return SnmpDefinitions.snmpRspGenErr;
|
|
|
|
if (errorStatus == SnmpDefinitions.snmpRspTooBig)
|
|
return SnmpDefinitions.snmpRspTooBig;
|
|
|
|
// For get / getNext / getBulk the only global error
|
|
// (PDU-level) possible is genErr.
|
|
//
|
|
if ((reqPduType != SnmpDefinitions.pduSetRequestPdu) &&
|
|
(reqPduType != SnmpDefinitions.pduWalkRequest)) {
|
|
if(errorStatus == SnmpDefinitions.snmpRspAuthorizationError)
|
|
return errorStatus;
|
|
else
|
|
return SnmpDefinitions.snmpRspGenErr;
|
|
}
|
|
|
|
// Map to noSuchName
|
|
// if ((errorStatus == SnmpDefinitions.snmpRspNoSuchName) ||
|
|
// (errorStatus == SnmpStatusException.noSuchInstance) ||
|
|
// (errorStatus == SnmpStatusException.noSuchObject))
|
|
// return SnmpDefinitions.snmpRspNoSuchName;
|
|
|
|
// SnmpStatusException.noSuchInstance and
|
|
// SnmpStatusException.noSuchObject can't happen...
|
|
|
|
if (errorStatus == SnmpDefinitions.snmpRspNoSuchName)
|
|
return SnmpDefinitions.snmpRspNoAccess;
|
|
|
|
// Map to notWritable
|
|
if (errorStatus == SnmpDefinitions.snmpRspReadOnly)
|
|
return SnmpDefinitions.snmpRspNotWritable;
|
|
|
|
// Map to wrongValue
|
|
if (errorStatus == SnmpDefinitions.snmpRspBadValue)
|
|
return SnmpDefinitions.snmpRspWrongValue;
|
|
|
|
// Other valid V2 codes
|
|
if ((errorStatus == SnmpDefinitions.snmpRspNoAccess) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspInconsistentName) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspAuthorizationError) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspNotWritable) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspNoCreation) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspWrongType) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspWrongLength) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspWrongEncoding) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspWrongValue) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspWrongLength) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspInconsistentValue) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspResourceUnavailable) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspCommitFailed) ||
|
|
(errorStatus == SnmpDefinitions.snmpRspUndoFailed))
|
|
return errorStatus;
|
|
|
|
// Ivalid V2 code => genErr
|
|
return SnmpDefinitions.snmpRspGenErr;
|
|
}
|
|
|
|
static final int mapErrorStatus(int errorStatus,
|
|
int protocolVersion,
|
|
int reqPduType) {
|
|
if (errorStatus == SnmpDefinitions.snmpRspNoError)
|
|
return SnmpDefinitions.snmpRspNoError;
|
|
|
|
// Too bad, an error occurs ... we need to translate it ...
|
|
//
|
|
if (protocolVersion == SnmpDefinitions.snmpVersionOne)
|
|
return mapErrorStatusToV1(errorStatus,reqPduType);
|
|
if (protocolVersion == SnmpDefinitions.snmpVersionTwo ||
|
|
protocolVersion == SnmpDefinitions.snmpVersionThree)
|
|
return mapErrorStatusToV2(errorStatus,reqPduType);
|
|
|
|
return SnmpDefinitions.snmpRspGenErr;
|
|
}
|
|
|
|
/**
|
|
* The method returns the error status of the operation.
|
|
* The method takes into account the protocol version.
|
|
*/
|
|
protected int getErrorStatus() {
|
|
if (errorStatus == snmpRspNoError)
|
|
return snmpRspNoError;
|
|
|
|
return mapErrorStatus(errorStatus,version,type);
|
|
}
|
|
|
|
/**
|
|
* The method returns the error index as a position in the var bind list.
|
|
* The value returned by the method corresponds to the index in the original
|
|
* var bind list as received by the SNMP protocol adaptor.
|
|
*/
|
|
protected int getErrorIndex() {
|
|
if (errorStatus == snmpRspNoError)
|
|
return -1;
|
|
|
|
// An error occurs. We need to be carefull because the index
|
|
// we are getting is a valid SNMP index (so range starts at 1).
|
|
// FIX ME: Shall we double-check the range here ?
|
|
// The response is : YES :
|
|
if ((errorIndex == 0) || (errorIndex == -1))
|
|
errorIndex = 1;
|
|
|
|
return translation[errorIndex -1];
|
|
}
|
|
|
|
/**
|
|
* The method updates the varbind list of the subrequest.
|
|
*/
|
|
protected void updateRequest(SnmpVarBind var, int pos) {
|
|
int size= varBind.size();
|
|
translation[size]= pos;
|
|
varBind.addElement(var);
|
|
}
|
|
|
|
/**
|
|
* The method updates a given var bind list with the result of a
|
|
* previsouly invoked operation.
|
|
* Prior to calling the method, one must make sure that the operation was
|
|
* successful. As such the method getErrorIndex or getErrorStatus should be
|
|
* called.
|
|
*/
|
|
protected void updateResult(SnmpVarBind[] result) {
|
|
|
|
if (result == null) return;
|
|
final int max=varBind.size();
|
|
final int len=result.length;
|
|
for(int i= 0; i< max ; i++) {
|
|
// bugId 4641694: must check position in order to avoid
|
|
// ArrayIndexOutOfBoundException
|
|
final int pos=translation[i];
|
|
if (pos < len) {
|
|
result[pos] =
|
|
(SnmpVarBind)((NonSyncVector)varBind).elementAtNonSync(i);
|
|
} else {
|
|
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
|
|
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpSubRequestHandler.class.getName(),
|
|
"updateResult","Position `"+pos+"' is out of bound...");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void init(SnmpEngine engine,
|
|
SnmpIncomingRequest incRequest) {
|
|
this.incRequest = incRequest;
|
|
this.engine = engine;
|
|
}
|
|
|
|
// PRIVATE VARIABLES
|
|
//------------------
|
|
|
|
/**
|
|
* Store the protocol version to handle
|
|
*/
|
|
protected int version= snmpVersionOne;
|
|
|
|
/**
|
|
* Store the operation type. Remember if the type is Walk, it means
|
|
* that we have to invoke the check method ...
|
|
*/
|
|
protected int type= 0;
|
|
|
|
/**
|
|
* Agent directly handled by the sub-request handler.
|
|
*/
|
|
protected SnmpMibAgent agent;
|
|
|
|
/**
|
|
* Error status.
|
|
*/
|
|
protected int errorStatus= snmpRspNoError;
|
|
|
|
/**
|
|
* Index of error.
|
|
* A value of -1 means no error.
|
|
*/
|
|
protected int errorIndex= -1;
|
|
|
|
/**
|
|
* The varbind list specific to the current sub request.
|
|
* The vector must contain object of type SnmpVarBind.
|
|
*/
|
|
protected Vector<SnmpVarBind> varBind;
|
|
|
|
/**
|
|
* The array giving the index translation between the content of
|
|
* <VAR>varBind</VAR> and the varbind list as specified in the request.
|
|
*/
|
|
protected int[] translation;
|
|
|
|
/**
|
|
* Contextual object allocated by the SnmpUserDataFactory.
|
|
**/
|
|
protected Object data;
|
|
|
|
/**
|
|
* The SnmpMibRequest that will be passed to the agent.
|
|
*
|
|
**/
|
|
private SnmpMibRequest mibRequest = null;
|
|
|
|
/**
|
|
* The SnmpPdu that will be passed to the request.
|
|
*
|
|
**/
|
|
private SnmpPdu reqPdu = null;
|
|
|
|
// All the methods of the Vector class are synchronized.
|
|
// Synchronization is a very expensive operation. In our case it is not always
|
|
// required...
|
|
//
|
|
@SuppressWarnings("serial") // we never serialize this
|
|
class NonSyncVector<E> extends Vector<E> {
|
|
|
|
public NonSyncVector(int size) {
|
|
super(size);
|
|
}
|
|
|
|
final void addNonSyncElement(E obj) {
|
|
ensureCapacity(elementCount + 1);
|
|
elementData[elementCount++] = obj;
|
|
}
|
|
|
|
@SuppressWarnings("unchecked") // cast to E
|
|
final E elementAtNonSync(int index) {
|
|
return (E) elementData[index];
|
|
}
|
|
};
|
|
}
|