All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.snmp4j.agent.CommandProcessor Maven / Gradle / Ivy

There is a newer version: 3.8.1
Show newest version
/*_############################################################################
  _## 
  _##  SNMP4J-Agent 2 - CommandProcessor.java  
  _## 
  _##  Copyright (C) 2005-2014  Frank Fock (SNMP4J.org)
  _##  
  _##  Licensed under the Apache License, Version 2.0 (the "License");
  _##  you may not use this file except in compliance with the License.
  _##  You may obtain a copy of the License at
  _##  
  _##      http://www.apache.org/licenses/LICENSE-2.0
  _##  
  _##  Unless required by applicable law or agreed to in writing, software
  _##  distributed under the License is distributed on an "AS IS" BASIS,
  _##  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  _##  See the License for the specific language governing permissions and
  _##  limitations under the License.
  _##  
  _##########################################################################*/

package org.snmp4j.agent;

import java.util.*;

import org.snmp4j.*;
import org.snmp4j.agent.mo.lock.LockRequest;
import org.snmp4j.agent.request.*;
import org.snmp4j.agent.security.*;
import org.snmp4j.event.*;
import org.snmp4j.mp.*;
import org.snmp4j.smi.*;
import org.snmp4j.util.*;
import org.snmp4j.agent.util.TemporaryList;
import org.snmp4j.agent.mo.snmp.CoexistenceInfo;
import org.snmp4j.agent.mo.snmp.CoexistenceInfoProvider;
import org.snmp4j.log.LogAdapter;
import org.snmp4j.log.LogFactory;

/**
 * The {@code CommandProcessor} is the central glue code that puts together
 * the various sub-systems of a SNMP agent.
 *
 * @author Frank Fock
 * @version 1.0
 */
public class CommandProcessor
    implements CommandResponder, NotificationOriginator {

  private static final LogAdapter logger =
      LogFactory.getLogger(CommandProcessor.class);

  /**
   * The maximum request timeout supported by this command processor
   * (by default 300.000 ms = 5 min).
   */
  private static final int MAX_INTERNAL_REQUEST_TIMEOUT = 300000;

  protected WorkerPool threadPool = null;
  protected VACM vacm = null;
  protected Vector moServers;
  protected List ownContextEngineIDs = new ArrayList(2);
  protected final Vector> pduHandler = new Vector>();
  protected TemporaryList requestList;
  protected RequestFactory requestFactory;
  protected NotificationOriginator notificationOriginator;
  protected ProxyMap proxyForwarder;
  protected CoexistenceInfoProvider coexistenceProvider;

  private transient Vector counterListeners;

  /**
   * Creates a {@code CommandProcessor} and registers all PDU types
   * with the supplied contextEngineID as well as with
   * {@link MPv3#LOCAL_ENGINE_ID} as required by RFC 5343.
   * @param contextEngineID
   *    the custom engine ID to use (should equal the engineID
   *    of the agent, i.e. USM).
   */
  public CommandProcessor(OctetString contextEngineID) {
    this.ownContextEngineIDs.add(contextEngineID);
    this.ownContextEngineIDs.add(MPv3.LOCAL_ENGINE_ID);
    moServers = new Vector();
    requestList = new TemporaryList(MAX_INTERNAL_REQUEST_TIMEOUT);
    pduHandler.add(new GetHandler());
    pduHandler.add(new GetNextHandler());
    pduHandler.add(new SetHandler());
    pduHandler.add(new GetBulkHandler());
    requestFactory = new DefaultRequestFactory();
  }

  /**
   * Sets the internal request timeout. Any request must return within this
   * amount of milli-seconds. Default is five minutes.
   * @param timeoutMillis
   *    the maximum number of milli-seconds a request can be processed.
   * @since 1.3
   */
  public void setInternalRequestTimeout(int timeoutMillis) {
    requestList.setTimeout(timeoutMillis);
  }

  /**
   * Gets the internal request timeout millis.
   * @return
   *    the maximum number of milli-seconds a request can be processed.
   * @since 1.3
   */
  public int getInternalRequestTimeout() {
    return requestList.getTimeout();
  }

  public void processPdu(CommandResponderEvent event) {
    if (event.getPDU() != null) {
      CoexistenceInfo cinfo = null;
      OctetString sname = new OctetString(event.getSecurityName());
      if (event.getPDU() instanceof ScopedPDU) {
        ScopedPDU spdu = (ScopedPDU)event.getPDU();
        cinfo = new CoexistenceInfo(sname,
                                    spdu.getContextEngineID(),
                                    spdu.getContextName());
      }
      else if (coexistenceProvider != null) {
        CoexistenceInfo[] cinfos =
            coexistenceProvider.getCoexistenceInfo(sname);
        if ((cinfos != null) && (cinfos.length > 0)) {
          for (CoexistenceInfo cinfo1 : cinfos) {
            if (coexistenceProvider.passesFilter(event.getPeerAddress(),
                cinfo1)) {
              cinfo = cinfo1;
              break;
            }
          }
          if (cinfo == null) {
            logger.warn("Access attempt from "+event.getPeerAddress()+
                        " denied because of source address filtering");

            fireIncrementCounter(
                new CounterEvent(this,
                                 SnmpConstants.snmpInBadCommunityNames));
            return;
          }
          event.setMaxSizeResponsePDU(cinfo.getMaxMessageSize());
        }
        else {
          if (logger.isInfoEnabled()) {
            logger.info("Community name '"+sname+
                        "' not found in SNMP-COMMUNITY-MIB");
          }
          fireIncrementCounter(
              new CounterEvent(this,
                               SnmpConstants.snmpInBadCommunityNames));
          return;
        }
      }
      if ((cinfo == null) ||
          (ownContextEngineIDs.contains(cinfo.getContextEngineID()))) {
        event.setProcessed(true);
        Command command = new Command(event, cinfo);
        if (threadPool != null) {
          threadPool.execute(command);
        }
        else {
          command.run();
        }
      }
      else if (proxyForwarder != null) {
        ProxyForwardRequest request =
            new ProxyForwardRequest(event, cinfo);
        ProxyForwarder proxy =
            proxyForwarder.get(cinfo.getContextEngineID(),
                               request.getProxyType());
        ProxyCommand command = new ProxyCommand(proxy, request);
        if (proxy != null) {
          if (logger.isDebugEnabled()) {
            logger.debug("Processsing proxy request with proxy forwarder "+
                         proxy);
          }
          if (threadPool != null) {
            threadPool.execute(command);
          }
          else {
            command.run();
          }
        }
        else {
          fireIncrementCounter(new CounterEvent(this,
                                                SnmpConstants.snmpProxyDrops));
        }
      }
      else {
        fireIncrementCounter(new CounterEvent(this,
                                              SnmpConstants.snmpSilentDrops));
      }
    }
  }

  /**
   * Sets the internal thread pool for task execution.
   *
   * @param threadPool
   *    a pool of workers/threads which can execute tasks.
   * @deprecated Use {@link #setWorkerPool} instead
   */
  public void setThreadPool(WorkerPool threadPool) {
    this.threadPool = threadPool;
  }

  /**
   * Sets the internal thread pool for task execution.
   *
   * @param threadPool
   *    a pool of workers/threads which can execute tasks.
   * @since 1.9
   */
  public void setWorkerPool(WorkerPool threadPool) {
    this.threadPool = threadPool;
  }

  public VACM getVacm() {
    return vacm;
  }

  public void setVacm(VACM vacm) {
    this.vacm = vacm;
  }
  public OctetString getContextEngineID() {
    return ownContextEngineIDs.get(0);
  }
  public void setContextEngineID(OctetString contextEngineID) {
    this.ownContextEngineIDs.set(0,contextEngineID);
  }

  /**
   * Sends notification/inform messages to all registered targets. This method
   * uses the internal {@link ThreadPool} to send the message(s) via the
   * NotificationOriginator
   * (see {@link #getNotificationOriginator}) to the targets specified by the
   * SnmpTargetMIB and SnmpNotificationMIB instances supplied to the
   * notification originator.
   *
   * @param context
   *    the context name of the context on whose behalf this notification has
   *    been generated.
   * @param notificationID
   *    the object ID that uniquely identifies this notification. For SNMPv1
   *    traps, the notification ID has to be build using the rules provided
   *    by RFC 2576.
   * @param vbs
   *    an array of VariableBinding instances representing the
   *    payload of the notification.
   * @return
   *    an array of ResponseEvent instances or NotificationTask instance if
   *    the notification has been send asynchronously. Since the
   *    NotificationOriginator determines on behalf of the
   *    SNMP-NOTIFICTON-MIB contents whether a notification is sent as
   *    trap/notification or as inform request, the returned array will contain
   *    an element for each addressed target, but only a response PDU for
   *    inform targets.
   *    

* null will be returned when sending the notification failed * because there is no {@link NotificationOriginator} set. *

* NOTE: If this command processor is using a ThreadPool then the returned * object will be {@link NotificationTask} instance. If all response have * been received {@link Object#notify()} will be called on the returned * NotificationTask object by the sending thread. */ public Object notify(final OctetString context, final OID notificationID, final VariableBinding[] vbs) { return notify(context, notificationID, null, vbs); } public Object notify(OctetString context, OID notificationID, TimeTicks sysUpTime, VariableBinding[] vbs) { if (notificationOriginator != null) { NotificationTask notifyTask = new NotificationTask(notificationOriginator, context, notificationID, sysUpTime, vbs); if (threadPool != null) { threadPool.execute(notifyTask); return notifyTask; } else { notifyTask.run(); return notifyTask.getResponses(); } } else { logger.warn("Could not sent notification '"+notificationID+"'="+ Arrays.asList(vbs)+" because NotificationOriginator not set"); } return null; } public void setNotificationOriginator(NotificationOriginator notificationOriginator) { this.notificationOriginator = notificationOriginator; } public void setCoexistenceProvider(CoexistenceInfoProvider coexistenceProvider) { this.coexistenceProvider = coexistenceProvider; } public ProxyForwarder addProxyForwarder(ProxyForwarder proxyForwarder, OctetString contextEngineID, int proxyType) { if (this.proxyForwarder == null) { this.proxyForwarder = new ProxyMap(); } return this.proxyForwarder.add(proxyForwarder, contextEngineID, proxyType); } public ProxyForwarder removeProxyForwarder(OctetString contextEngineID, int proxyType) { if (proxyForwarder != null) { return proxyForwarder.remove(contextEngineID, proxyType); } return null; } protected RequestHandler getHandler(int pduType) { synchronized (pduHandler) { for (RequestHandler handler : pduHandler) { if (handler.isSupported(pduType)) { return handler; } } } return null; } protected void dispatchCommand(CommandResponderEvent command, CoexistenceInfo cinfo) { RequestHandler handler = getHandler(command.getPDU().getType()); if (handler != null) { processRequest(command, cinfo, handler); } else { sendUnknownPDUHandlersReport(command); } } private void sendUnknownPDUHandlersReport(CommandResponderEvent command) { logger.info("No PDU handler found for request "+command); CounterEvent counter = new CounterEvent(this, SnmpConstants.snmpUnknownPDUHandlers); fireIncrementCounter(counter); if ((command.getMessageProcessingModel() == MessageProcessingModel.MPv3) && (command.getPDU() instanceof ScopedPDU)) { ScopedPDU request = (ScopedPDU) command.getPDU(); ScopedPDU report = new ScopedPDU(); report.setContextEngineID(request.getContextEngineID()); report.setContextName(request.getContextName()); report.setType(PDU.REPORT); report.add(new VariableBinding(counter.getOid(), counter.getCurrentValue())); sendResponse(command, report); } else { PDU resp = (PDU) command.getPDU().clone(); resp.setErrorStatus(PDU.genErr); sendResponse(command, resp); } } protected void processRequest(CommandResponderEvent command, CoexistenceInfo cinfo, RequestHandler handler) { SnmpRequest req = requestFactory.createRequest(command, cinfo); requestList.add(req); MOServer server = null; OctetString context = req.getContext(); OctetString viewName = getViewName(command, cinfo, req.getViewType()); if (viewName == null) { setAuthorizationError(req, VACM.VACM_NO_SUCH_VIEW); } else { req.setViewName(viewName); server = getServer(context); processRequest(server, handler, req); } finalizeRequest(command, req, server); } protected void reprocessRequest(MOServer server, SnmpRequest req) { RequestHandler handler = getHandler(req.getSource().getPDU().getType()); if (handler != null) { req.resetProcessedStatus(); req.incReprocessCounter(); processRequest(server, handler, req); } else { sendUnknownPDUHandlersReport(req.getSource()); } } /** * Processes (or re-process) a request and try to complete the request (thus * to complete any incomplete subrequests). * * @param server * the {@code MOServer} instance to use for accessing instrumentation. * @param handler * the {@code RequestHandler} to use to process the request. * @param req * the {@code Request}. * @param * the {@code Request} type to process. * @param * the source object that created the request for processing. * @param * the response PDU type created by the request processing. */ protected , Source, Response> void processRequest(MOServer server, RequestHandler handler, R req) { if (server == null) { logger.error("No server for "+req.getContext()+ " found -> request cannot be processed"); req.setErrorStatus(SnmpConstants.SNMP_ERROR_GENERAL_ERROR); } else { handler.processPdu(req, server); } } protected void finalizeRequest(CommandResponderEvent command, SnmpRequest req, MOServer server) { if (req.isComplete()) { requestList.remove(req); // send response sendResponse(command, req.getResponse()); if (server != null) { release(server, req); } } } protected void release(MOServer server, SnmpRequest req) { for (Iterator it = req.iterator(); it.hasNext();) { SubRequest sreq = it.next(); if (sreq.getTargetMO() != null) { server.unlock(req, sreq.getTargetMO()); } } } protected void sendResponse(CommandResponderEvent requestEvent, PDU response) { MessageDispatcher disp = requestEvent.getMessageDispatcher(); try { if (response.getBERLength() > requestEvent.getMaxSizeResponsePDU()) { // response is tooBig if (response.getType() != PDU.REPORT) { if (requestEvent.getPDU().getType() == PDU.GETBULK) { while ((response.size() > 0) && (response.getBERLength() > requestEvent.getMaxSizeResponsePDU())) { response.trim(); } } else { response.clear(); response.setRequestID(requestEvent.getPDU().getRequestID()); response.setErrorStatus(PDU.tooBig); } } if (response.getBERLength() > requestEvent.getMaxSizeResponsePDU()) { fireIncrementCounter(new CounterEvent(this, SnmpConstants.snmpSilentDrops)); return; } } StatusInformation status = new StatusInformation(); StateReference stateRef = requestEvent.getStateReference(); if (stateRef == null) { logger.warn("No state reference available for requestEvent="+ requestEvent+". Cannot return response="+response); } else { stateRef.setTransportMapping(requestEvent.getTransportMapping()); disp.returnResponsePdu(requestEvent.getMessageProcessingModel(), requestEvent.getSecurityModel(), requestEvent.getSecurityName(), requestEvent.getSecurityLevel(), response, requestEvent.getMaxSizeResponsePDU(), requestEvent.getStateReference(), status); } } catch (MessageException ex) { logger.error("Failed to send response to request "+requestEvent, ex); } } protected void setAuthorizationError(Request req, int vacmStatus) { if (req.size() > 0) { SubRequest sreq = (SubRequest) req.iterator().next(); sreq.getStatus().setErrorStatus(PDU.authorizationError); } else { req.setErrorStatus(PDU.authorizationError); } } public void addPduHandler(RequestHandler handler) { pduHandler.add(handler); } public void removePduHandler(RequestHandler handler) { pduHandler.remove(handler); } public void addMOServer(MOServer server) { moServers.add(server); } public void removeMOServer(MOServer server) { moServers.remove(server); } public MOServer getServer(OctetString context) { for (MOServer s : moServers) { if (s.isContextSupported(context)) { return s; } } return null; } public TemporaryList getRequestList() { return requestList; } public NotificationOriginator getNotificationOriginator() { return notificationOriginator; } public ProxyMap getProxyForwarder() { return proxyForwarder; } public CoexistenceInfoProvider getCoexistenceProvider() { return coexistenceProvider; } class Command implements WorkerTask { private CommandResponderEvent request; private CoexistenceInfo cinfo; public Command(CommandResponderEvent event, CoexistenceInfo cinfo) { this.request = event; this.cinfo = cinfo; } public void run() { dispatchCommand(request, cinfo); } public void terminate() { } public void join() throws InterruptedException { } public void interrupt() { } } class ProxyCommand implements WorkerTask { private ProxyForwardRequest request; private ProxyForwarder forwarder; public ProxyCommand(ProxyForwarder forwarder, ProxyForwardRequest event) { this.forwarder = forwarder; this.request = event; } public void run() { if (forwarder.forward(request)) { PDU response = request.getResponsePDU(); if (response != null) { sendResponse(request.getCommandEvent(), response); } } else if (request.getProxyType() != ProxyForwarder.PROXY_TYPE_NOTIFY) { // proxy drop CounterEvent cevent = new CounterEvent(this, SnmpConstants.snmpProxyDrops); fireIncrementCounter(cevent); CommandResponderEvent cre = request.getCommandEvent(); if ((cre.getMessageProcessingModel() == MPv3.ID) && (cre.getStateReference() != null)) { ScopedPDU reportPDU = new ScopedPDU(); reportPDU.setType(PDU.REPORT); reportPDU.setContextEngineID(request.getContextEngineID()); reportPDU.setContextName(request.getContext()); reportPDU.add(new VariableBinding(SnmpConstants.snmpProxyDrops, cevent.getCurrentValue())); sendResponse(request.getCommandEvent(), reportPDU); } } } public void terminate() { // we cannot terminate (gracefully) this task while it is being executed } public void join() throws InterruptedException { } public void interrupt() { } } protected OctetString getViewName(CommandResponderEvent req, CoexistenceInfo cinfo, int viewType) { return vacm.getViewName(cinfo.getContextName(), cinfo.getSecurityName(), req.getSecurityModel(), req.getSecurityLevel(), viewType); } protected void processNextSubRequest(SnmpRequest request, MOServer server, OctetString context, SubRequest sreq) throws NoSuchElementException { // We can be sure to have a default context scope here because // the inner class SnmpSubRequest creates it! DefaultMOContextScope scope = (DefaultMOContextScope) sreq.getScope(); MOQuery query = sreq.getQuery(); if (query == null) { query = new VACMQuery(context, scope.getLowerBound(), scope.isLowerIncluded(), scope.getUpperBound(), scope.isUpperIncluded(), request.getViewName(), false, request); sreq.setQuery(query); } ManagedObject mo; LockRequest lockRequest = new LockRequest(request, requestList.getTimeout()); while (!sreq.getStatus().isProcessed()) { mo = server.lookup(query, lockRequest); if (mo == null) { if (logger.isDebugEnabled()) { logger.debug("EndOfMibView at scope="+scope+" and query "+query); } sreq.getVariableBinding().setVariable(Null.endOfMibView); sreq.getStatus().setPhaseComplete(true); continue; } try { if (logger.isDebugEnabled()) { logger.debug("Processing NEXT query "+query+" with "+mo+ " sub-request with index "+sreq.getIndex()); } boolean counter64Skip = false; if ((!mo.next(sreq)) || (counter64Skip = ((request.getMessageProcessingModel() == MPv1.ID) && (sreq.getVariableBinding().getSyntax() == SMIConstants.SYNTAX_COUNTER64)))) { sreq.getVariableBinding().setVariable(Null.instance); if (counter64Skip) { scope.lowerBound = sreq.getVariableBinding().getOid(); scope.lowerIncluded = false; sreq.getStatus().setProcessed(false); } else { scope.substractScope(mo.getScope()); // don't forget to update VACM query: query.substractScope(mo.getScope()); } } } catch (Exception moex) { if (logger.isDebugEnabled()) { moex.printStackTrace(); } logger.error("Exception occurred while executing NEXT query: "+ moex.getMessage(), moex); if (sreq.getStatus().getErrorStatus() == PDU.noError) { sreq.getStatus().setErrorStatus(PDU.genErr); } if (SNMP4JSettings.isForwardRuntimeExceptions()) { throw new RuntimeException(moex); } } finally { unlockManagedObjectIfLockedByLookup(server, mo, lockRequest); } } } /** * Unlock the provided {@link ManagedObject} if the also provided {@link LockRequest} indicates * that the managed object was locked by a preceding {@link MOServer#lookup(MOQuery, LockRequest)} operation. * @param server * a MOServer that put the lock. * @param mo * the possibly locked managed object. * @param lockRequest * the lock request with the status of the (potentially acquired) lock. * @since 2.4.0 */ protected void unlockManagedObjectIfLockedByLookup(MOServer server, ManagedObject mo, LockRequest lockRequest) { switch (lockRequest.getLockRequestStatus()) { case locked: case lockedAfterTimeout: server.unlock(lockRequest.getLockOwner(), mo); } } public synchronized void addCounterListener(CounterListener l) { if (counterListeners == null) { counterListeners = new Vector(2); } counterListeners.add(l); } public synchronized void removeCounterListener(CounterListener l) { if (counterListeners != null) { counterListeners.remove(l); } } protected void fireIncrementCounter(CounterEvent event) { if (counterListeners != null) { Vector listeners = counterListeners; int count = listeners.size(); for (int i = 0; i < count; i++) { (listeners.elementAt(i)).incrementCounter(event); } } } private static void initRequestPhase(Request request) { if (request.getPhase() == Request.PHASE_INIT) { request.nextPhase(); } } class GetNextHandler implements RequestHandler { public void processPdu(SnmpRequest request, MOServer server) { initRequestPhase(request); OctetString context = request.getContext(); try { Iterator it = request.iterator(); while (it.hasNext()) { SubRequest sreq = it.next(); processNextSubRequest(request, server, context, sreq); } } catch (NoSuchElementException nsex) { if (logger.isDebugEnabled()) { nsex.printStackTrace(); } logger.error("SubRequest not found"); request.setErrorStatus(PDU.genErr); } } public boolean isSupported(int pduType) { return (pduType == PDU.GETNEXT); } } class SetHandler implements RequestHandler { public void prepare(OctetString context, SnmpRequest request, MOServer server) { try { Iterator it = request.iterator(); LockRequest lockRequest = new LockRequest(request, requestList.getTimeout()); while ((!request.isPhaseComplete()) && (it.hasNext())) { SubRequest sreq = it.next(); if (sreq.isComplete()) { continue; } MOScope scope = sreq.getScope(); MOQuery query = sreq.getQuery(); if (query == null) { // create a query for write access query = new VACMQuery(context, scope.getLowerBound(), scope.isLowerIncluded(), scope.getUpperBound(), scope.isUpperIncluded(), request.getViewName(), true, request); sreq.setQuery(query); } if (!query.getScope().isCovered( new DefaultMOContextScope(context, scope))) { sreq.getStatus().setErrorStatus(PDU.noAccess); } else { ManagedObject mo = server.lookup(query, lockRequest); if (mo == null) { if ((query instanceof VACMQuery) && (!((VACMQuery)query).isAccessAllowed(scope.getLowerBound()))){ sreq.getStatus().setErrorStatus(PDU.noAccess); } else { sreq.getStatus().setErrorStatus(PDU.noCreation); } break; } sreq.setTargetMO(mo); if (lockRequest.getLockRequestStatus() == LockRequest.LockStatus.lockTimedOut) { logger.warn("Set request " + request + " failed because "+mo+" could not be locked"); if (sreq.getStatus().getErrorStatus() == PDU.noError) { sreq.getStatus().setErrorStatus(PDU.genErr); } } else { try { mo.prepare(sreq); } catch (Exception moex) { logger.error("Set request " + request + " failed with exception", moex); if (sreq.getStatus().getErrorStatus() == PDU.noError) { sreq.getStatus().setErrorStatus(PDU.genErr); } if (SNMP4JSettings.isForwardRuntimeExceptions()) { throw new RuntimeException(moex); } } } } } } catch (NoSuchElementException nsex) { if (logger.isDebugEnabled()) { nsex.printStackTrace(); } logger.error("Cannot find sub-request: ", nsex); request.setErrorStatus(PDU.genErr); } } public void processPdu(SnmpRequest request, MOServer server) { OctetString context = request.getContext(); try { while (request.getPhase() < Request.PHASE_2PC_CLEANUP) { int phase = request.nextPhase(); switch (phase) { case Request.PHASE_2PC_PREPARE: { prepare(context, request, server); break; } case Request.PHASE_2PC_COMMIT: { commit(context, request, server); break; } case Request.PHASE_2PC_UNDO: { undo(context, request, server); break; } case Request.PHASE_2PC_CLEANUP: { cleanup(context, request, server); return; } } if (!request.isPhaseComplete()) { // request needs to be reprocessed later! return; } } } catch (Exception ex) { if (logger.isDebugEnabled()) { ex.printStackTrace(); } logger.error("Failed to process SET request, trying to clean it up...", ex); if (SNMP4JSettings.isForwardRuntimeExceptions()) { throw new RuntimeException(ex); } } cleanup(context, request, server); } protected void undo(OctetString context, SnmpRequest request, MOServer server) { try { Iterator it = request.iterator(); while (it.hasNext()) { SubRequest sreq = it.next(); if (sreq.isComplete()) { continue; } OID oid = sreq.getVariableBinding().getOid(); ManagedObject mo = sreq.getTargetMO(); if (mo == null) { DefaultMOContextScope scope = new DefaultMOContextScope(context, oid, true, oid, true); mo = server.lookup(new MOQueryWithSource(scope, true, request)); } if (mo == null) { sreq.getStatus().setErrorStatus(PDU.undoFailed); continue; } try { mo.undo(sreq); } catch (Exception moex) { if (logger.isDebugEnabled()) { moex.printStackTrace(); } logger.error(moex); if (sreq.getStatus().getErrorStatus() == PDU.noError) { sreq.getStatus().setErrorStatus(PDU.undoFailed); } if (SNMP4JSettings.isForwardRuntimeExceptions()) { throw new RuntimeException(moex); } } } } catch (NoSuchElementException nsex) { if (logger.isDebugEnabled()) { nsex.printStackTrace(); } logger.error("Cannot find sub-request: ", nsex); request.setErrorStatus(PDU.genErr); } } protected void commit(OctetString context, SnmpRequest request, MOServer server) { try { Iterator it = request.iterator(); while ((request.getErrorStatus() == PDU.noError) && (it.hasNext())) { SnmpSubRequest sreq = it.next(); if (sreq.isComplete()) { continue; } OID oid = sreq.getVariableBinding().getOid(); ManagedObject mo = sreq.getTargetMO(); if (mo == null) { DefaultMOContextScope scope = new DefaultMOContextScope(context, oid, true, oid, true); mo = server.lookup(new MOQueryWithSource(scope, true, request)); } if (mo == null) { sreq.getStatus().setErrorStatus(PDU.commitFailed); continue; } try { mo.commit(sreq); } catch (Exception moex) { if (logger.isDebugEnabled()) { moex.printStackTrace(); } logger.error(moex); if (sreq.getStatus().getErrorStatus() == PDU.noError) { sreq.getStatus().setErrorStatus(PDU.commitFailed); } if (SNMP4JSettings.isForwardRuntimeExceptions()) { throw new RuntimeException(moex); } } } } catch (NoSuchElementException nsex) { if (logger.isDebugEnabled()) { nsex.printStackTrace(); } logger.error("Cannot find sub-request: ", nsex); request.setErrorStatus(PDU.genErr); } } protected void cleanup(OctetString context, SnmpRequest request, MOServer server) { try { Iterator it = request.iterator(); while (it.hasNext()) { SubRequest sreq = it.next(); if (sreq.isComplete()) { continue; } OID oid = sreq.getVariableBinding().getOid(); ManagedObject mo = sreq.getTargetMO(); if (mo == null) { DefaultMOContextScope scope = new DefaultMOContextScope(context, oid, true, oid, true); mo = server.lookup(new DefaultMOQuery(scope)); } if (mo == null) { sreq.completed(); continue; } server.unlock(sreq.getRequest(), mo); try { mo.cleanup(sreq); sreq.getStatus().setPhaseComplete(true); } catch (Exception moex) { if (logger.isDebugEnabled()) { moex.printStackTrace(); } logger.error(moex); if (SNMP4JSettings.isForwardRuntimeExceptions()) { throw new RuntimeException(moex); } } } } catch (NoSuchElementException nsex) { logger.error("Cannot find sub-request: ", nsex); if (logger.isDebugEnabled()) { nsex.printStackTrace(); } } } public boolean isSupported(int pduType) { return (pduType == PDU.SET); } } class GetHandler implements RequestHandler { public boolean isSupported(int pduType) { return (pduType == PDU.GET); } public void processPdu(SnmpRequest request, MOServer server) { initRequestPhase(request); OctetString context = request.getContext(); try { Iterator it = request.iterator(); LockRequest lockRequest = new LockRequest(request, requestList.getTimeout()); while (it.hasNext()) { SubRequest sreq = it.next(); MOScope scope = sreq.getScope(); MOQuery query = sreq.getQuery(); if (query == null) { query = new VACMQuery(context, scope.getLowerBound(), scope.isLowerIncluded(), scope.getUpperBound(), scope.isUpperIncluded(), request.getViewName(), false, request); sreq.setQuery(query); } ManagedObject mo = server.lookup(query, lockRequest); if (mo == null) { sreq.getVariableBinding().setVariable(Null.noSuchObject); sreq.getStatus().setPhaseComplete(true); continue; } try { mo.get(sreq); if ((request.getMessageProcessingModel() == MPv1.ID) && (sreq.getVariableBinding().getSyntax() == SMIConstants.SYNTAX_COUNTER64)) { sreq.getVariableBinding().setVariable(Null.noSuchInstance); } } catch (Exception moex) { if (logger.isDebugEnabled()) { moex.printStackTrace(); } logger.warn(moex); if (sreq.getStatus().getErrorStatus() == PDU.noError) { sreq.getStatus().setErrorStatus(PDU.genErr); } if (SNMP4JSettings.isForwardRuntimeExceptions()) { throw new RuntimeException(moex); } } finally { unlockManagedObjectIfLockedByLookup(server, mo, lockRequest); } } } catch (NoSuchElementException nsex) { if (logger.isDebugEnabled()) { nsex.printStackTrace(); } logger.error("SubRequest not found"); request.setErrorStatus(PDU.genErr); } } } class GetBulkHandler implements RequestHandler { public boolean isSupported(int pduType) { return (pduType == PDU.GETBULK); } public void processPdu(SnmpRequest request, MOServer server) { initRequestPhase(request); OctetString context = request.getContext(); int nonRep = request.getNonRepeaters(); try { Iterator it = request.iterator(); int i = 0; // non repeaters for (; ((i < nonRep) && it.hasNext()); i++) { SnmpSubRequest sreq = it.next(); if (!sreq.isComplete()) { processNextSubRequest(request, server, context, sreq); } } // repetitions if (request.getMaxRepetitions() > 0) { for (; it.hasNext(); i++) { SnmpSubRequest sreq = it.next(); if (!sreq.isComplete()) { processNextSubRequest(request, server, context, sreq); sreq.updateNextRepetition(); } } } else { for (; it.hasNext(); i++) { SnmpSubRequest sreq = it.next(); sreq.completed(); } } } catch (NoSuchElementException nsex) { if (logger.isDebugEnabled()) { logger.debug("GETBULK request response PDU size limit reached"); } } } } class VACMQuery extends MOQueryWithSource { private OctetString viewName; /** * Creates a VACMQuery for read-only access. * @param context * the context for the query, an empty OctetString denotes the default * context. * @param lowerBound * the lower bound OID. * @param isLowerIncluded * indicates whether the lower bound should be included or not. * @param upperBound * the upper bound OID or null if no upper bound is * specified. * @param isUpperIncluded * indicates whether the upper bound should be included or not. * @param viewName * the view name to use for the query. * @deprecated * Use a constructor with source reference parameter instead. */ public VACMQuery(OctetString context, OID lowerBound, boolean isLowerIncluded, OID upperBound, boolean isUpperIncluded, OctetString viewName) { super(new DefaultMOContextScope(context, lowerBound, isLowerIncluded, upperBound, isUpperIncluded), false, null); this.viewName = viewName; } /** * Creates a VACMQuery for read-only access. * @param context * the context for the query, an empty OctetString denotes the default * context. * @param lowerBound * the lower bound OID. * @param isLowerIncluded * indicates whether the lower bound should be included or not. * @param upperBound * the upper bound OID or null if no upper bound is * specified. * @param isUpperIncluded * indicates whether the upper bound should be included or not. * @param viewName * the view name to use for the query. * @param isWriteAccessIntended * indicates if this query is issued on behalf of a SNMP SET request * or not. * @param source * the source ({@link Request}) object on whose behalf this query is * executed. * @since 1.1 */ public VACMQuery(OctetString context, OID lowerBound, boolean isLowerIncluded, OID upperBound, boolean isUpperIncluded, OctetString viewName, boolean isWriteAccessIntended, SnmpRequest source) { super(new DefaultMOContextScope(context, lowerBound, isLowerIncluded, upperBound, isUpperIncluded), isWriteAccessIntended, source); this.viewName = viewName; } public boolean isSearchQuery() { MOContextScope scope = getScope(); return ((!scope.isLowerIncluded()) && ((scope.getUpperBound() == null) || (!scope.getUpperBound().equals(scope.getLowerBound())))); } public boolean matchesQuery(ManagedObject managedObject) { OID oid; if (isSearchQuery()) { oid = managedObject.find(getScope()); if (oid == null) { return false; } } else { oid = getScope().getLowerBound(); } return (vacm.isAccessAllowed(viewName, oid) == VACM.VACM_OK); } public boolean isAccessAllowed(OID oid) { return (vacm.isAccessAllowed(viewName, oid) == VACM.VACM_OK); } public String toString() { return super.toString()+ "[viewName="+viewName+"]"; } } static class DefaultRequestFactory implements RequestFactory { public SnmpRequest createRequest( CommandResponderEvent initiatingEvent, CoexistenceInfo cinfo) { return new SnmpRequest(initiatingEvent, cinfo); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy