0001: /*_############################################################################
0002: _##
0003: _## SNMP4J - MPv3.java
0004: _##
0005: _## Copyright (C) 2003-2008 Frank Fock and Jochen Katz (SNMP4J.org)
0006: _##
0007: _## Licensed under the Apache License, Version 2.0 (the "License");
0008: _## you may not use this file except in compliance with the License.
0009: _## You may obtain a copy of the License at
0010: _##
0011: _## http://www.apache.org/licenses/LICENSE-2.0
0012: _##
0013: _## Unless required by applicable law or agreed to in writing, software
0014: _## distributed under the License is distributed on an "AS IS" BASIS,
0015: _## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0016: _## See the License for the specific language governing permissions and
0017: _## limitations under the License.
0018: _##
0019: _##########################################################################*/
0020:
0021: package org.snmp4j.mp;
0022:
0023: import java.io.*;
0024: import java.net.*;
0025: import java.nio.ByteBuffer;
0026: import java.util.*;
0027:
0028: import org.snmp4j.*;
0029: import org.snmp4j.asn1.*;
0030: import org.snmp4j.event.*;
0031: import org.snmp4j.log.*;
0032: import org.snmp4j.security.*;
0033: import org.snmp4j.smi.*;
0034: import org.snmp4j.util.PDUFactory;
0035: import org.snmp4j.util.DefaultPDUFactory;
0036:
0037: /**
0038: * The <code>MPv3</code> is the message processing model for SNMPv3.
0039: *
0040: * @author Frank Fock
0041: * @version 1.9.1
0042: */
0043: public class MPv3 implements MessageProcessingModel {
0044:
0045: public static final int ID = MessageProcessingModel.MPv3;
0046: public static final int MPv3_REPORTABLE_FLAG = 4;
0047: public static final int MAX_MESSAGE_ID = 2147483647;
0048:
0049: public static final int MAXLEN_ENGINE_ID = 32;
0050: public static final int MINLEN_ENGINE_ID = 5;
0051:
0052: private static final int MAX_HEADER_PAYLOAD_LENGTH =
0053: // length of msgFlags
0054: new OctetString("\0").getBERLength() +
0055: // length of msgID, msgMaxSize, securityModel
0056: 3 * new Integer32(Integer.MAX_VALUE).getBERLength();
0057:
0058: private static final int MAX_HEADER_LENGTH = MAX_HEADER_PAYLOAD_LENGTH
0059: + BER.getBERLengthOfLength(MAX_HEADER_PAYLOAD_LENGTH) + 1;
0060:
0061: private SecurityProtocols securityProtocols;
0062:
0063: private static final LogAdapter logger = LogFactory
0064: .getLogger(MPv3.class);
0065: private SecurityModels securityModels;
0066:
0067: private Cache cache;
0068: private Hashtable engineIDs;
0069: private byte[] localEngineID;
0070:
0071: private int currentMsgID = new Random().nextInt(MAX_MESSAGE_ID);
0072:
0073: // Enterprise ID of AGENT++
0074: private static int enterpriseID = 4976;
0075:
0076: private CounterSupport counterSupport;
0077:
0078: transient Vector snmpEngineListeners;
0079:
0080: protected PDUFactory incomingPDUFactory = new PDUFactory() {
0081: public PDU createPDU(Target target) {
0082: return new ScopedPDU();
0083: }
0084: };
0085:
0086: /**
0087: * Creates a MPv3 with a default local engine ID.
0088: */
0089: public MPv3() {
0090: this (createLocalEngineID(), null);
0091: }
0092:
0093: /**
0094: * Creates a MPv3 with a supplied local engine ID.
0095: * @param localEngineID
0096: * the local engine ID. Its length must be >= 5 and <= 32.
0097: */
0098: public MPv3(byte[] localEngineID) {
0099: this (localEngineID, null);
0100: setLocalEngineID(localEngineID);
0101: }
0102:
0103: /**
0104: * Creates a MPv3 with a supplied local engine ID and {@link PDUFactory}
0105: * for incoming messages.
0106: * @param localEngineID
0107: * the local engine ID. Its length must be >= 5 and <= 32.
0108: * @param incomingPDUFactory
0109: * a {@link PDUFactory}. If <code>null</code> the default factory will be
0110: * used which creates {@link ScopedPDU} instances.
0111: * @since 1.9.1
0112: */
0113: public MPv3(byte[] localEngineID, PDUFactory incomingPDUFactory) {
0114: if (incomingPDUFactory != null) {
0115: this .incomingPDUFactory = incomingPDUFactory;
0116: }
0117: engineIDs = new Hashtable();
0118: cache = new Cache();
0119: securityProtocols = SecurityProtocols.getInstance();
0120: securityModels = SecurityModels.getInstance();
0121: counterSupport = CounterSupport.getInstance();
0122: setLocalEngineID(localEngineID);
0123: }
0124:
0125: /**
0126: * Creates a local engine ID based on the local IP address.
0127: * @return
0128: * a new local engine ID.
0129: */
0130: public static byte[] createLocalEngineID() {
0131: byte[] engineID = new byte[5];
0132: engineID[0] = (byte) (0x80 | ((enterpriseID >> 24) & 0xFF));
0133: engineID[1] = (byte) ((enterpriseID >> 16) & 0xFF);
0134: engineID[2] = (byte) ((enterpriseID >> 8) & 0xFF);
0135: engineID[3] = (byte) (enterpriseID & 0xFF);
0136: engineID[4] = 1;
0137: OctetString os = new OctetString();
0138: try {
0139: os.setValue(InetAddress.getLocalHost().getAddress());
0140: } catch (UnknownHostException ex) {
0141: logger
0142: .debug("Local host cannot be determined for creation of local engine ID");
0143: engineID[4] = 4;
0144: os.setValue("SNMP4J".getBytes());
0145: }
0146: OctetString ownEngineID = new OctetString(engineID);
0147: ownEngineID.append(os);
0148: return ownEngineID.getValue();
0149: }
0150:
0151: /**
0152: * Creates a local engine ID based on the ID string supplied
0153: * @param id
0154: * an ID string.
0155: * @return
0156: * a new local engine ID.
0157: */
0158: public static byte[] createLocalEngineID(OctetString id) {
0159: byte[] engineID = new byte[5];
0160: engineID[0] = (byte) (0x80 | ((enterpriseID >> 24) & 0xFF));
0161: engineID[1] = (byte) ((enterpriseID >> 16) & 0xFF);
0162: engineID[2] = (byte) ((enterpriseID >> 8) & 0xFF);
0163: engineID[3] = (byte) (enterpriseID & 0xFF);
0164: engineID[4] = 4;
0165: OctetString ownEngineID = new OctetString(engineID);
0166: ownEngineID.append(id);
0167: return ownEngineID.getValue();
0168: }
0169:
0170: /**
0171: * Sets the local engine ID. This value must not be changed after message
0172: * processing has been started.
0173: * @param engineID
0174: * the local engine ID. Its length must be >= 5 and <= 32.
0175: */
0176: public void setLocalEngineID(byte[] engineID) {
0177: if ((engineID == null) || (engineID.length < MINLEN_ENGINE_ID)
0178: || (engineID.length > MAXLEN_ENGINE_ID)) {
0179: throw new IllegalArgumentException(
0180: "Illegal (local) engine ID");
0181: }
0182: this .localEngineID = engineID;
0183: }
0184:
0185: /**
0186: * Gets a copy of the local engine ID.
0187: * @return
0188: * a byte array containing the local engine ID.
0189: */
0190: public byte[] getLocalEngineID() {
0191: byte[] retval = new byte[localEngineID.length];
0192: System.arraycopy(localEngineID, 0, retval, 0,
0193: localEngineID.length);
0194: return retval;
0195: }
0196:
0197: /**
0198: * Creates and initializes the default security protocols.
0199: * @see SecurityProtocols#addDefaultProtocols()
0200: */
0201: public void initDefaults() {
0202: securityProtocols.addDefaultProtocols();
0203: }
0204:
0205: /**
0206: * Gets an authentication protocol for the supplied ID.
0207: * @param id
0208: * an authentication protocol OID.
0209: * @return
0210: * an <code>AuthenticationProtocol</code> instance if the supplied ID
0211: * is supported, otherwise <code>null</code> is returned.
0212: */
0213: public AuthenticationProtocol getAuthProtocol(OID id) {
0214: return securityProtocols.getAuthenticationProtocol(id);
0215: }
0216:
0217: /**
0218: * Gets an privacy protocol for the supplied ID.
0219: * @param id
0220: * an privacy protocol OID.
0221: * @return
0222: * an <code>PrivacyProtocol</code> instance if the supplied ID
0223: * is supported, otherwise <code>null</code> is returned.
0224: */
0225: public PrivacyProtocol getPrivProtocol(OID id) {
0226: return securityProtocols.getPrivacyProtocol(id);
0227: }
0228:
0229: /**
0230: * Gets the security model for the supplied ID.
0231: * @param id
0232: * a security model ID.
0233: * @return
0234: * a <code>SecurityModel</code> instance if the supplied ID
0235: * is supported, otherwise <code>null</code> is returned.
0236: */
0237: public SecurityModel getSecurityModel(int id) {
0238: return securityModels.getSecurityModel(new Integer32(id));
0239: }
0240:
0241: public int getID() {
0242: return ID;
0243: }
0244:
0245: public boolean isProtocolVersionSupported(int version) {
0246: return (version == SnmpConstants.version3);
0247: }
0248:
0249: /**
0250: * Adds an engine ID (other than the local engine ID) to the internal storage.
0251: * @param address
0252: * the <code>Address</code> of the remote SNMP engine.
0253: * @param engineID
0254: * the engine ID of the remote SNMP engine.
0255: * @return
0256: * <code>true</code> if the engine ID has been added, <code>false</code>
0257: * otherwise (if the supplied <code>engineID</code> equals the local one).
0258: */
0259: public boolean addEngineID(Address address, OctetString engineID) {
0260: if (!Arrays.equals(this .localEngineID, engineID.getValue())) {
0261: engineIDs.put(address, engineID);
0262: if (snmpEngineListeners != null) {
0263: fireEngineChanged(new SnmpEngineEvent(this ,
0264: SnmpEngineEvent.ADDED_ENGINE_ID, engineID,
0265: address));
0266: }
0267: return true;
0268: }
0269: return false;
0270: }
0271:
0272: /**
0273: * Gets the engine ID associated with the supplied address from the local
0274: * storage and fires the corresponding {@link SnmpEngineEvent}.
0275: * @param address
0276: * the <code>Address</code> of the remote SNMP engine.
0277: * @return
0278: * the engine ID of the remote SNMP engine or <code>null</code> if there
0279: * is no entry for <code>address</code> in the local storage.
0280: */
0281: public OctetString getEngineID(Address address) {
0282: return (OctetString) engineIDs.get(address);
0283: }
0284:
0285: /**
0286: * Removes an engine ID association from the local storage and fires the
0287: * corresponding {@link SnmpEngineEvent}.
0288: * @param address
0289: * the <code>Address</code> of the remote SNMP engine for whose engine ID
0290: * is to be removed.
0291: * @return
0292: * the removed engine ID of the remote SNMP engine or <code>null</code> if
0293: * there is no entry for <code>address</code> in the local storage.
0294: */
0295: public OctetString removeEngineID(Address address) {
0296: OctetString engineID = (OctetString) engineIDs.remove(address);
0297: if ((engineID != null) && (snmpEngineListeners != null)) {
0298: fireEngineChanged(new SnmpEngineEvent(this ,
0299: SnmpEngineEvent.REMOVED_ENGINE_ID, engineID,
0300: address));
0301: }
0302: return engineID;
0303: }
0304:
0305: /**
0306: * The <code>CacheEntry</code> class holds state reference information
0307: * for the MPv3 message processing model for a single message.
0308: * @author Frank Fock
0309: * @version 1.0
0310: */
0311: protected static class CacheEntry extends StateReference {
0312: int msgID;
0313: long transactionID;
0314: byte[] secEngineID;
0315: SecurityModel secModel;
0316: byte[] secName;
0317: int secLevel;
0318: byte[] contextEngineID;
0319: byte[] contextName;
0320: SecurityStateReference secStateReference;
0321: int errorCode;
0322:
0323: public CacheEntry(int msgID, long reqID, byte[] secEngineID,
0324: SecurityModel secModel, byte[] secName, int secLevel,
0325: byte[] contextEngineID, byte[] contextName,
0326: SecurityStateReference secStateReference, int errorCode) {
0327: this .msgID = msgID;
0328: this .transactionID = reqID;
0329: this .secEngineID = secEngineID;
0330: this .secModel = secModel;
0331: this .secName = secName;
0332: this .secLevel = secLevel;
0333: this .contextEngineID = contextEngineID;
0334: this .contextName = contextName;
0335: this .secStateReference = secStateReference;
0336: this .errorCode = errorCode;
0337: }
0338: }
0339:
0340: /**
0341: * The <code>Cache</code> stores state reference information for the MPv3.
0342: * @author Frank Fock
0343: * @version 1.0
0344: */
0345: protected static class Cache {
0346:
0347: private Map entries = new WeakHashMap(25);
0348:
0349: /**
0350: * Adds a <code>StateReference</code> to the cache.
0351: * The <code>PduHandle</code> of the supplied entry will be set to
0352: * <code>null</code> while the entry is part of the cache, because the
0353: * cache uses a <code>WeakHashMap</code> internally which uses the
0354: * <code>PduHandle</code> as key. When
0355: * @param entry
0356: * the state reference to add.
0357: * @return
0358: * {@link SnmpConstants#SNMP_MP_DOUBLED_MESSAGE} if the entry already
0359: * exists and {@link SnmpConstants#SNMP_MP_OK} on success.
0360: */
0361: public synchronized int addEntry(StateReference entry) {
0362: if (logger.isDebugEnabled()) {
0363: logger.debug("Adding cache entry: " + entry);
0364: }
0365: StateReference existing = (StateReference) entries
0366: .get(entry.getPduHandle());
0367: if (existing != null) {
0368: if (existing.equals(entry)) {
0369: if (logger.isDebugEnabled()) {
0370: logger.debug("Doubled message: " + entry);
0371: }
0372: return SnmpConstants.SNMP_MP_DOUBLED_MESSAGE;
0373: }
0374: }
0375: // add it
0376: PduHandle key = entry.getPduHandle();
0377: // because we are using a weak has map for the cache, we need to null out
0378: // our key from the entry.
0379: entry.setPduHandle(null);
0380: entries.put(key, entry);
0381: return SnmpConstants.SNMP_MP_OK;
0382: }
0383:
0384: /**
0385: * Get the first cache entry with specified message ID.
0386: * @param msgID
0387: * a message ID.
0388: * @return
0389: * a <code>StateReference</code> instance with the given message ID or
0390: * <code>null</code> if such an entry cannot be found.
0391: */
0392: /*
0393: public StateReference getEntry(int msgID) {
0394: for (Iterator it = entries.iterator(); it.hasNext(); ) {
0395: StateReference e = (StateReference) it.next();
0396: if (e.getMsgID() == msgID) {
0397: return e;
0398: }
0399: }
0400: return null;
0401: }
0402: */
0403: /**
0404: * Delete the cache entry with the supplied <code>PduHandle</code>.
0405: * @param pduHandle
0406: * a pduHandle.
0407: * @return
0408: * <code>true</code> if an entry has been deleted, <code>false</code>
0409: * otherwise.
0410: */
0411: public synchronized boolean deleteEntry(PduHandle pduHandle) {
0412: StateReference e = (StateReference) entries
0413: .remove(pduHandle);
0414: return (e != null);
0415: }
0416:
0417: /**
0418: * Pop the cache entry with the supplied ID from the cache.
0419: * @param msgID
0420: * a message ID.
0421: * @return
0422: * a <code>CacheEntry</code> instance with the given message ID or
0423: * <code>null</code> if such an entry cannot be found. If a cache entry
0424: * is returned, the same is removed from the cache.
0425: */
0426: public synchronized StateReference popEntry(int msgID) {
0427: for (Iterator it = entries.keySet().iterator(); it
0428: .hasNext();) {
0429: PduHandle key = (PduHandle) it.next();
0430: StateReference e = (StateReference) entries.get(key);
0431: if ((e != null) && (e.getMsgID() == msgID)) {
0432: it.remove();
0433: e.setPduHandle(key);
0434: if (logger.isDebugEnabled()) {
0435: logger.debug("Removed cache entry: " + e);
0436: }
0437: return e;
0438: }
0439: }
0440: return null;
0441: }
0442: }
0443:
0444: /**
0445: * The <code>HeaderData</code> represents the message header information
0446: * of SNMPv3 message.
0447: * @author Frank Fock
0448: * @version 1.0
0449: */
0450: protected static class HeaderData implements BERSerializable {
0451:
0452: public static final byte FLAG_AUTH = 0x01;
0453: public static final byte FLAG_PRIV = 0x02;
0454:
0455: Integer32 msgID = new Integer32(0);
0456: Integer32 msgMaxSize = new Integer32(Integer.MAX_VALUE);
0457: OctetString msgFlags = new OctetString(new byte[1]);
0458: Integer32 securityModel = new Integer32(
0459: SecurityModel.SECURITY_MODEL_ANY);
0460:
0461: public void setMsgID(int msgID) {
0462: this .msgID.setValue(msgID);
0463: }
0464:
0465: public int getMsgID() {
0466: return msgID.getValue();
0467: }
0468:
0469: public void setMsgMaxSize(int msgMaxSize) {
0470: this .msgMaxSize.setValue(msgMaxSize);
0471: }
0472:
0473: public int getMsgMaxSize() {
0474: return msgMaxSize.getValue();
0475: }
0476:
0477: public void setMsgFlags(int flags) {
0478: this .msgFlags.getValue()[0] = (byte) flags;
0479: }
0480:
0481: public int getMsgFlags() {
0482: return msgFlags.getValue()[0] & 0xFF;
0483: }
0484:
0485: public void setSecurityModel(int model) {
0486: securityModel.setValue(model);
0487: }
0488:
0489: public int getSecurityModel() {
0490: return securityModel.getValue();
0491: }
0492:
0493: public int getBERPayloadLength() {
0494: int length = msgID.getBERLength();
0495: length += msgMaxSize.getBERLength();
0496: length += msgFlags.getBERLength();
0497: length += securityModel.getBERLength();
0498: return length;
0499: }
0500:
0501: public int getBERLength() {
0502: int length = getBERPayloadLength();
0503: length += BER.getBERLengthOfLength(length) + 1;
0504: return length;
0505: }
0506:
0507: public void decodeBER(BERInputStream message)
0508: throws IOException {
0509: BER.MutableByte type = new BER.MutableByte();
0510: int length = BER.decodeHeader(message, type);
0511: if (type.getValue() != BER.SEQUENCE) {
0512: throw new IOException(
0513: "Unexpected sequence header type: "
0514: + type.getValue());
0515: }
0516: msgID.decodeBER(message);
0517: msgMaxSize.decodeBER(message);
0518: if (msgMaxSize.getValue() < 484) {
0519: throw new IOException("Invalid msgMaxSize: "
0520: + msgMaxSize);
0521: }
0522: msgFlags.decodeBER(message);
0523: if (msgFlags.length() != 1) {
0524: throw new IOException("Message flags length != 1: "
0525: + msgFlags.length());
0526: }
0527: securityModel.decodeBER(message);
0528: if (logger.isDebugEnabled()) {
0529: logger.debug("SNMPv3 header decoded: msgId=" + msgID
0530: + ", msgMaxSize=" + msgMaxSize + ", msgFlags="
0531: + msgFlags.toHexString() + ", secModel="
0532: + securityModel);
0533: }
0534: BER.checkSequenceLength(length, this );
0535: }
0536:
0537: public void encodeBER(OutputStream outputStream)
0538: throws IOException {
0539: BER.encodeHeader(outputStream, BER.SEQUENCE,
0540: getBERPayloadLength());
0541: msgID.encodeBER(outputStream);
0542: msgMaxSize.encodeBER(outputStream);
0543: msgFlags.encodeBER(outputStream);
0544: securityModel.encodeBER(outputStream);
0545: }
0546: }
0547:
0548: /**
0549: * Gets unique message ID.
0550: * @return
0551: * a message ID >= 1 and <= {@link #MAX_MESSAGE_ID}.
0552: */
0553: public synchronized int getNextMessageID() {
0554: if (currentMsgID >= MAX_MESSAGE_ID) {
0555: currentMsgID = 1;
0556: }
0557: return currentMsgID++;
0558: }
0559:
0560: /**
0561: * Gets the security protocols supported by this <code>MPv3</code>.
0562: * @return
0563: * return a <code>SecurityProtocols</code>.
0564: */
0565: public SecurityProtocols getSecurityProtocols() {
0566: return securityProtocols;
0567: }
0568:
0569: /**
0570: * Sets the security protocols for this <code>MPv3</code>.
0571: * @param securityProtocols SecurityProtocols
0572: */
0573: public void setSecurityProtocols(SecurityProtocols securityProtocols) {
0574: this .securityProtocols = securityProtocols;
0575: }
0576:
0577: /**
0578: * Gets the default security model to be used for engine ID discovery.
0579: * @return
0580: * a security model ID.
0581: * @see USM#getID()
0582: */
0583: protected int getDefaultSecurityModel() {
0584: return SecurityModel.SECURITY_MODEL_USM;
0585: }
0586:
0587: public void releaseStateReference(PduHandle pduHandle) {
0588: cache.deleteEntry(pduHandle);
0589: }
0590:
0591: public int prepareOutgoingMessage(Address transportAddress,
0592: int maxMessageSize, int messageProcessingModel,
0593: int securityModel, byte[] securityName, int securityLevel,
0594: PDU pdu, boolean expectResponse, PduHandle sendPduHandle,
0595: Address destTransportAddress,
0596: BEROutputStream outgoingMessage) throws IOException {
0597: if (!(pdu instanceof ScopedPDU)) {
0598: throw new IllegalArgumentException(
0599: "MPv3 only accepts ScopedPDU instances as pdu parameter");
0600: }
0601: ScopedPDU scopedPDU = (ScopedPDU) pdu;
0602: // lookup engine ID
0603: byte[] secEngineID = null;
0604: OctetString securityEngineID = (OctetString) engineIDs
0605: .get(transportAddress);
0606: if (securityEngineID != null) {
0607: secEngineID = securityEngineID.getValue();
0608: if (scopedPDU.getContextEngineID().length() == 0) {
0609: if (logger.isDebugEnabled()) {
0610: logger
0611: .debug("Context engine ID of scoped PDU is empty! Setting it to authoritative engine ID: "
0612: + securityEngineID.toHexString());
0613: }
0614: scopedPDU.setContextEngineID(new OctetString(
0615: secEngineID));
0616: }
0617: } else {
0618: secEngineID = new byte[0];
0619: }
0620:
0621: // determine request type
0622: if (pdu.isConfirmedPdu()) {
0623: if (secEngineID.length == 0) {
0624: securityLevel = SecurityLevel.NOAUTH_NOPRIV;
0625: securityModel = getDefaultSecurityModel();
0626: // do not send any management information
0627: scopedPDU = (ScopedPDU) scopedPDU.clone();
0628: scopedPDU.clear();
0629: }
0630: } else {
0631: if (scopedPDU.getContextEngineID().length() == 0) {
0632: if (logger.isDebugEnabled()) {
0633: logger
0634: .debug("Context engine ID of unconfirmed scoped PDU is empty! "
0635: + "Setting it to local engine ID");
0636: }
0637: scopedPDU.setContextEngineID(new OctetString(
0638: localEngineID));
0639: }
0640: }
0641:
0642: // get length of scoped PDU
0643: int scopedPDULength = pdu.getBERLength();
0644: BEROutputStream scopedPdu = new BEROutputStream(ByteBuffer
0645: .allocate(scopedPDULength));
0646:
0647: scopedPDU.encodeBER(scopedPdu);
0648:
0649: HeaderData headerData = new HeaderData();
0650: int flags = 0;
0651: switch (securityLevel) {
0652: case SecurityLevel.NOAUTH_NOPRIV:
0653: flags = 0;
0654: break;
0655: case SecurityLevel.AUTH_NOPRIV:
0656: flags = 1;
0657: break;
0658: case SecurityLevel.AUTH_PRIV:
0659: flags = 3;
0660: break;
0661: }
0662: if (scopedPDU.isConfirmedPdu()) {
0663: flags |= MPv3_REPORTABLE_FLAG;
0664: } else {
0665: secEngineID = localEngineID;
0666: }
0667:
0668: int msgID = getNextMessageID();
0669: headerData.setMsgFlags(flags);
0670: headerData.setMsgID(msgID);
0671: headerData.setMsgMaxSize(maxMessageSize);
0672: headerData.setSecurityModel(securityModel);
0673:
0674: ByteBuffer globalDataBuffer = ByteBuffer.allocate(headerData
0675: .getBERLength());
0676: BEROutputStream globalDataOutputStream = new BEROutputStream(
0677: globalDataBuffer);
0678: headerData.encodeBER(globalDataOutputStream);
0679:
0680: BERInputStream scopedPDUInput = new BERInputStream(scopedPdu
0681: .rewind());
0682:
0683: SecurityModel secModel = securityModels
0684: .getSecurityModel(new Integer32(securityModel));
0685: if (secModel == null) {
0686: return SnmpConstants.SNMP_MP_UNSUPPORTED_SECURITY_MODEL;
0687: }
0688: // output data
0689: SecurityParameters securityParameters = secModel
0690: .newSecurityParametersInstance();
0691:
0692: int status = secModel.generateRequestMessage(
0693: messageProcessingModel, globalDataBuffer.array(),
0694: maxMessageSize, securityModel, secEngineID,
0695: securityName, securityLevel, scopedPDUInput,
0696: securityParameters, outgoingMessage);
0697: if (status == SnmpConstants.SNMPv3_USM_OK) {
0698: if (expectResponse) {
0699: cache.addEntry(new StateReference(msgID, flags,
0700: maxMessageSize, sendPduHandle,
0701: transportAddress, null, secEngineID, secModel,
0702: securityName, securityLevel, scopedPDU
0703: .getContextEngineID().getValue(),
0704: scopedPDU.getContextName().getValue(), null,
0705: status));
0706: }
0707: }
0708: return status;
0709: }
0710:
0711: public int prepareResponseMessage(int messageProcessingModel,
0712: int maxMessageSize, int securityModel, byte[] securityName,
0713: int securityLevel, PDU pdu, int maxSizeResponseScopedPDU,
0714: StateReference stateReference,
0715: StatusInformation statusInformation,
0716: BEROutputStream outgoingMessage) throws IOException {
0717: /** Leave entry in cache or remove it? RFC3414 §3.1.a.1 says discard it*/
0718: StateReference cacheEntry = cache.popEntry(stateReference
0719: .getMsgID());
0720: if (cacheEntry == null) {
0721: return SnmpConstants.SNMP_MP_UNKNOWN_MSGID;
0722: }
0723:
0724: // get length of scoped PDU
0725: // get length of scoped PDU
0726: int scopedPDULength = pdu.getBERLength();
0727: BEROutputStream scopedPDU;
0728: // check length
0729: if (scopedPDULength > maxSizeResponseScopedPDU) {
0730: PDU tooBigPDU = new ScopedPDU((ScopedPDU) pdu);
0731: tooBigPDU.clear();
0732: tooBigPDU.setRequestID(pdu.getRequestID());
0733: tooBigPDU.setErrorStatus(SnmpConstants.SNMP_ERROR_TOO_BIG);
0734: tooBigPDU.setErrorIndex(0);
0735: scopedPDULength = tooBigPDU.getBERLength();
0736: scopedPDU = new BEROutputStream(ByteBuffer
0737: .allocate(scopedPDULength));
0738: tooBigPDU.encodeBER(scopedPDU);
0739: } else {
0740: scopedPDU = new BEROutputStream(ByteBuffer
0741: .allocate(scopedPDULength));
0742: pdu.encodeBER(scopedPDU);
0743: }
0744:
0745: HeaderData headerData = new HeaderData();
0746: int flags = 0;
0747: switch (securityLevel) {
0748: case SecurityLevel.NOAUTH_NOPRIV:
0749: flags = 0;
0750: break;
0751: case SecurityLevel.AUTH_NOPRIV:
0752: flags = 1;
0753: break;
0754: case SecurityLevel.AUTH_PRIV:
0755: flags = 3;
0756: break;
0757: }
0758: // response message is not reportable
0759: headerData.setMsgFlags(flags);
0760: headerData.setMsgID(stateReference.getMsgID());
0761: headerData.setMsgMaxSize(maxMessageSize);
0762: headerData.setSecurityModel(securityModel);
0763:
0764: ByteBuffer globalDataBuffer = ByteBuffer.allocate(headerData
0765: .getBERLength());
0766: BEROutputStream globalDataOutputStream = new BEROutputStream(
0767: globalDataBuffer);
0768: headerData.encodeBER(globalDataOutputStream);
0769:
0770: OctetString securityEngineID;
0771: switch (pdu.getType()) {
0772: case PDU.RESPONSE:
0773: case PDU.TRAP:
0774: case PDU.REPORT:
0775: case PDU.V1TRAP:
0776: securityEngineID = new OctetString(localEngineID);
0777: break;
0778: default:
0779: securityEngineID = new OctetString(cacheEntry
0780: .getSecurityEngineID());
0781: }
0782:
0783: BERInputStream scopedPDUInput = new BERInputStream(scopedPDU
0784: .rewind());
0785:
0786: SecurityModel secModel = securityModels
0787: .getSecurityModel(new Integer32(securityModel));
0788: // output data
0789: SecurityParameters securityParameters = secModel
0790: .newSecurityParametersInstance();
0791:
0792: int status = secModel.generateResponseMessage(getID(),
0793: globalDataBuffer.array(), maxMessageSize,
0794: securityModel, securityEngineID.getValue(),
0795: securityName, securityLevel, scopedPDUInput, cacheEntry
0796: .getSecurityStateReference(),
0797: securityParameters, outgoingMessage);
0798: return status;
0799: }
0800:
0801: /**
0802: * Sends a report message.
0803: * @param messageDispatcher
0804: * Send the message on behalf the supplied MessageDispatcher instance.
0805: * @param pdu ScopedPDU
0806: * If <code>null</code>, then contextEngineID, contextName, and requestID
0807: * of the report generated will be zero length and zero respective.
0808: * Otherwise these values are extracted from the PDU.
0809: * @param securityLevel
0810: * The security level to use when sending this report.
0811: * @param securityModel
0812: * The security model to use when sending this report.
0813: * @param securityName
0814: * The security name to use when sending this report.
0815: * @param maxSizeResponseScopedPDU
0816: * the maximum size of of the report message (will be most likely ignored
0817: * because a report should always fit in 484 bytes).
0818: * @param payload
0819: * the variable binding to include in the report message.
0820: * @param stateReference
0821: * the state reference associated with the original message.
0822: * @return
0823: * an SNMP MPv3 error code or 0 if the report has been send successfully.
0824: */
0825: public int sendReport(MessageDispatcher messageDispatcher,
0826: ScopedPDU pdu, int securityLevel, int securityModel,
0827: OctetString securityName, int maxSizeResponseScopedPDU,
0828: StateReference stateReference, VariableBinding payload) {
0829: ScopedPDU reportPDU = new ScopedPDU();
0830: reportPDU.setType(PDU.REPORT);
0831: if (pdu != null) {
0832: reportPDU.setContextEngineID(pdu.getContextEngineID());
0833: reportPDU.setContextName(pdu.getContextName());
0834: reportPDU.setRequestID(pdu.getRequestID());
0835: }
0836: reportPDU.add(payload);
0837: StatusInformation statusInformation = new StatusInformation();
0838: try {
0839: int status = messageDispatcher.returnResponsePdu(getID(),
0840: securityModel, securityName.getValue(),
0841: securityLevel, reportPDU, maxSizeResponseScopedPDU,
0842: stateReference, statusInformation);
0843: if (status != SnmpConstants.SNMP_ERROR_SUCCESS) {
0844: logger.warn("Error while sending report: " + status);
0845: return SnmpConstants.SNMP_MP_ERROR;
0846: }
0847: } catch (MessageException mex) {
0848: logger.error("Error while sending report: "
0849: + mex.getMessage());
0850: return SnmpConstants.SNMP_MP_ERROR;
0851: }
0852: return SnmpConstants.SNMP_MP_OK;
0853: }
0854:
0855: public int prepareDataElements(MessageDispatcher messageDispatcher,
0856: Address transportAddress, BERInputStream wholeMsg,
0857: Integer32 messageProcessingModel, Integer32 securityModel,
0858: OctetString securityName, Integer32 securityLevel,
0859: MutablePDU pdu, PduHandle sendPduHandle,
0860: Integer32 maxSizeResponseScopedPDU,
0861: StatusInformation statusInformation,
0862: MutableStateReference mutableStateReference) {
0863: try {
0864: StateReference stateReference = new StateReference();
0865: // check if there is transport mapping information
0866: if (mutableStateReference.getStateReference() != null) {
0867: stateReference
0868: .setTransportMapping(mutableStateReference
0869: .getStateReference()
0870: .getTransportMapping());
0871: }
0872: messageProcessingModel.setValue(MPv3);
0873: wholeMsg.mark(16);
0874:
0875: BER.MutableByte type = new BER.MutableByte();
0876: int length = BER.decodeHeader(wholeMsg, type);
0877: if (type.getValue() != BER.SEQUENCE) {
0878: return SnmpConstants.SNMP_MP_PARSE_ERROR;
0879: }
0880: long lengthOfLength = wholeMsg.getPosition();
0881: wholeMsg.reset();
0882: wholeMsg.mark(length);
0883: if (wholeMsg.skip(lengthOfLength) != lengthOfLength) {
0884: return SnmpConstants.SNMP_MP_PARSE_ERROR;
0885: }
0886:
0887: Integer32 snmpVersion = new Integer32();
0888: snmpVersion.decodeBER(wholeMsg);
0889: if (snmpVersion.getValue() != SnmpConstants.version3) {
0890: // internal error -> should not happen
0891: throw new RuntimeException(
0892: "Internal error unexpected snmp version read");
0893: }
0894: // decode SNMPv3 header
0895: HeaderData header = new HeaderData();
0896: header.decodeBER(wholeMsg);
0897: securityModel.setValue(header.getSecurityModel());
0898:
0899: stateReference.setMsgID(header.getMsgID());
0900: stateReference.setMsgFlags(header.getMsgFlags());
0901: stateReference.setAddress(transportAddress);
0902:
0903: mutableStateReference.setStateReference(stateReference);
0904:
0905: // the usm has to recalculate this value
0906: maxSizeResponseScopedPDU.setValue(header.msgMaxSize
0907: .getValue()
0908: - MAX_HEADER_LENGTH);
0909:
0910: ScopedPDU scopedPdu = new ScopedPDU();
0911: pdu.setPdu(scopedPdu);
0912:
0913: SecurityModel secModel = securityModels
0914: .getSecurityModel(securityModel);
0915: if (secModel == null) {
0916: logger
0917: .error("RFC3412 §7.2.4 - Unsupported security model: "
0918: + securityModel);
0919: CounterEvent event = new CounterEvent(this ,
0920: SnmpConstants.snmpUnknownSecurityModels);
0921: fireIncrementCounter(event);
0922: return SnmpConstants.SNMP_MP_UNSUPPORTED_SECURITY_MODEL;
0923: }
0924:
0925: // determine security level
0926: switch (header.getMsgFlags() & 0x03) {
0927: case 3: {
0928: securityLevel.setValue(SecurityLevel.AUTH_PRIV);
0929: break;
0930: }
0931: case 0: {
0932: securityLevel.setValue(SecurityLevel.NOAUTH_NOPRIV);
0933: break;
0934: }
0935: case 1: {
0936: securityLevel.setValue(SecurityLevel.AUTH_NOPRIV);
0937: break;
0938: }
0939: default: {
0940: securityLevel.setValue(SecurityLevel.NOAUTH_NOPRIV);
0941: logger
0942: .debug("RFC3412 §7.2.5 - Invalid message (illegal msgFlags)");
0943: CounterEvent event = new CounterEvent(this ,
0944: SnmpConstants.snmpInvalidMsgs);
0945: fireIncrementCounter(event);
0946: // do not send back report
0947: return SnmpConstants.SNMP_MP_INVALID_MESSAGE;
0948: }
0949: }
0950:
0951: int secParametersPosition = (int) wholeMsg.getPosition();
0952: // get security parameters
0953: SecurityParameters secParameters = secModel
0954: .newSecurityParametersInstance();
0955: secParameters.decodeBER(wholeMsg);
0956: secParameters
0957: .setSecurityParametersPosition(secParametersPosition);
0958:
0959: // reportable flag
0960: boolean reportableFlag = ((header.getMsgFlags() & 0x04) > 0);
0961:
0962: OctetString securityEngineID = new OctetString();
0963: // create a new security state reference
0964: SecurityStateReference secStateReference = secModel
0965: .newSecurityStateReference();
0966: // create output stream for scoped PDU
0967: // may be optimized by an output stream that maps directly into the
0968: // original input
0969: wholeMsg.reset();
0970:
0971: BEROutputStream scopedPDU = new BEROutputStream();
0972: int status = secModel.processIncomingMsg(snmpVersion
0973: .getValue(), header.getMsgMaxSize()
0974: - MAX_HEADER_LENGTH, secParameters, secModel,
0975: securityLevel.getValue(),
0976: wholeMsg,
0977: // output parameters
0978: securityEngineID, securityName, scopedPDU,
0979: maxSizeResponseScopedPDU, secStateReference,
0980: statusInformation);
0981: wholeMsg.close();
0982: if (status == SnmpConstants.SNMPv3_USM_OK) {
0983: try {
0984: BERInputStream scopedPduStream = new BERInputStream(
0985: scopedPDU.rewind());
0986: scopedPdu.decodeBER(scopedPduStream);
0987: sendPduHandle.setTransactionID(scopedPdu
0988: .getRequestID().getValue());
0989:
0990: // add the engine ID to the local cache.
0991: addEngineID(transportAddress, securityEngineID);
0992: } catch (IOException iox) {
0993: logger.warn("ASN.1 parse error: "
0994: + iox.getMessage());
0995: if (logger.isDebugEnabled()) {
0996: iox.printStackTrace();
0997: }
0998: CounterEvent event = new CounterEvent(this ,
0999: SnmpConstants.snmpInASNParseErrs);
1000: fireIncrementCounter(event);
1001: return SnmpConstants.SNMP_MP_PARSE_ERROR;
1002: }
1003: if (((scopedPdu.getContextEngineID() == null) || (scopedPdu
1004: .getContextEngineID().length() == 0))
1005: && ((scopedPdu.getType() != PDU.RESPONSE) && (scopedPdu
1006: .getType() != PDU.REPORT))) {
1007: CounterEvent event = new CounterEvent(this ,
1008: SnmpConstants.snmpUnknownPDUHandlers);
1009: fireIncrementCounter(event);
1010: VariableBinding errorIndication = new VariableBinding(
1011: event.getOid(), event.getCurrentValue());
1012: statusInformation
1013: .setErrorIndication(errorIndication);
1014: status = SnmpConstants.SNMP_MP_UNKNOWN_PDU_HANDLERS;
1015: }
1016: }
1017:
1018: if (status != SnmpConstants.SNMPv3_USM_OK) {
1019: if ((reportableFlag)
1020: && (statusInformation.getErrorIndication() != null)) {
1021: // RFC3412 §7.2.6.a - generate a report
1022: try {
1023: if (scopedPDU.getBuffer() != null) {
1024: BERInputStream scopedPduStream = new BERInputStream(
1025: scopedPDU.rewind());
1026: scopedPdu.decodeBER(scopedPduStream);
1027: } else { // incoming message could not be decoded
1028: scopedPdu = null;
1029: }
1030: } catch (IOException iox) {
1031: logger.warn(iox);
1032: scopedPdu = null;
1033: }
1034:
1035: StateReference cacheEntry = new StateReference(
1036: header.getMsgID(), header.getMsgFlags(),
1037: maxSizeResponseScopedPDU.getValue(),
1038: sendPduHandle, transportAddress, null,
1039: securityEngineID.getValue(), secModel,
1040: securityName.getValue(), securityLevel
1041: .getValue(),
1042: (scopedPdu == null) ? new byte[0]
1043: : scopedPdu.getContextEngineID()
1044: .getValue(),
1045: (scopedPdu == null) ? new byte[0]
1046: : scopedPdu.getContextName()
1047: .getValue(),
1048: secStateReference, status);
1049: cache.addEntry(cacheEntry);
1050:
1051: int reportStatus = sendReport(messageDispatcher,
1052: scopedPdu, statusInformation
1053: .getSecurityLevel().getValue(),
1054: secModel.getID(), securityName,
1055: maxSizeResponseScopedPDU.getValue(),
1056: stateReference, statusInformation
1057: .getErrorIndication());
1058: if (reportStatus != SnmpConstants.SNMP_MP_OK) {
1059: logger
1060: .warn("Sending report failed with error code: "
1061: + reportStatus);
1062: }
1063: }
1064: return SnmpConstants.SNMP_MP_USM_ERROR;
1065: }
1066:
1067: stateReference.setAddress(transportAddress);
1068: stateReference.setSecurityName(securityName.getValue());
1069: stateReference.setContextEngineID(scopedPdu
1070: .getContextEngineID().getValue());
1071: stateReference.setContextName(scopedPdu.getContextName()
1072: .getValue());
1073: stateReference
1074: .setMaxSizeResponseScopedPDU(maxSizeResponseScopedPDU
1075: .getValue());
1076: stateReference.setMsgID(header.getMsgID());
1077: stateReference.setMsgFlags(header.getMsgFlags());
1078: stateReference.setSecurityEngineID(securityEngineID
1079: .getValue());
1080: stateReference.setSecurityLevel(securityLevel.getValue());
1081: stateReference.setSecurityModel(secModel);
1082: stateReference.setSecurityStateReference(secStateReference);
1083: stateReference.setPduHandle(sendPduHandle);
1084:
1085: if ((scopedPdu.getType() == PDU.RESPONSE)
1086: || (scopedPdu.getType() == PDU.REPORT)) {
1087: StateReference cacheEntry = cache.popEntry(header
1088: .getMsgID());
1089: if (cacheEntry != null) {
1090: if (logger.isDebugEnabled()) {
1091: logger
1092: .debug("RFC3412 §7.2.10 - Received PDU (msgID="
1093: + header.getMsgID()
1094: + ") is a response or "
1095: + "an internal class message. PduHandle.transactionID = "
1096: + cacheEntry.getPduHandle()
1097: .getTransactionID());
1098: }
1099: sendPduHandle.copyFrom(cacheEntry.getPduHandle());
1100:
1101: if (scopedPdu.getType() == PDU.REPORT) {
1102:
1103: statusInformation.setContextEngineID(scopedPdu
1104: .getContextEngineID().getValue());
1105: statusInformation.setContextName(scopedPdu
1106: .getContextName().getValue());
1107: statusInformation
1108: .setSecurityLevel(securityLevel);
1109:
1110: if (((cacheEntry.getSecurityEngineID().length != 0) && (!securityEngineID
1111: .equals(cacheEntry
1112: .getSecurityEngineID())))
1113: || (secModel.getID() != cacheEntry
1114: .getSecurityModel().getID())
1115: || ((!securityName.equals(cacheEntry
1116: .getSecurityName()) && (securityName
1117: .length() != 0)))) {
1118: if (logger.isDebugEnabled()) {
1119: logger
1120: .debug("RFC 3412 §7.2.11 - Received report message does not match sent message");
1121: }
1122: //cache.deleteEntry(cacheEntry.getPduHandle());
1123: mutableStateReference
1124: .setStateReference(null);
1125: return SnmpConstants.SNMP_MP_MATCH_ERROR;
1126: }
1127: if (!addEngineID(cacheEntry.getAddress(),
1128: securityEngineID)) {
1129: if (logger.isWarnEnabled()) {
1130: logger
1131: .warn("Engine ID '"
1132: + securityEngineID
1133: + "' could not be added to engine ID cache for "
1134: + "target address '"
1135: + cacheEntry
1136: .getAddress()
1137: + "' because engine ID matches local engine ID");
1138: }
1139: }
1140: //cache.deleteEntry(cacheEntry.getPduHandle());
1141: mutableStateReference.setStateReference(null);
1142: logger.debug("MPv3 finished");
1143: return SnmpConstants.SNMP_MP_OK;
1144: }
1145: if (scopedPdu.getType() == PDU.RESPONSE) {
1146: if (((!securityEngineID.equals(cacheEntry
1147: .getSecurityEngineID())) && (cacheEntry
1148: .getSecurityEngineID().length != 0))
1149: || (secModel.getID() != cacheEntry
1150: .getSecurityModel().getID())
1151: || (!securityName.equals(cacheEntry
1152: .getSecurityName()))
1153: || (securityLevel.getValue() != cacheEntry
1154: .getSecurityLevel())
1155: || ((!scopedPdu
1156: .getContextEngineID()
1157: .equals(
1158: cacheEntry
1159: .getContextEngineID())) && (cacheEntry
1160: .getContextEngineID().length != 0))
1161: || ((!scopedPdu
1162: .getContextName()
1163: .equals(
1164: cacheEntry
1165: .getContextName()) && (cacheEntry
1166: .getContextName().length != 0)))) {
1167: logger
1168: .debug("RFC 3412 §7.2.12.b - Received response message does not match sent message");
1169: //cache.deleteEntry(cacheEntry.getPduHandle());
1170: mutableStateReference
1171: .setStateReference(null);
1172: return SnmpConstants.SNMP_MP_MATCH_ERROR;
1173: }
1174: //cache.deleteEntry(cacheEntry.getPduHandle());
1175: mutableStateReference.setStateReference(null);
1176: logger.debug("MPv3 finished");
1177: return SnmpConstants.SNMP_MP_OK;
1178: }
1179: } else {
1180: if (logger.isDebugEnabled()) {
1181: logger
1182: .debug("RFC3412 §7.2.10 - Received PDU (msgID="
1183: + header.getMsgID()
1184: + ") is a response or "
1185: + "internal class message, but cached "
1186: + "information for the msgID could not be found");
1187: }
1188: return SnmpConstants.SNMP_MP_UNKNOWN_MSGID;
1189: }
1190: } else {
1191: logger
1192: .debug("RFC3412 §7.2.10 - Received PDU is NOT a response or "
1193: + "internal class message -> unchanged PduHandle = "
1194: + sendPduHandle);
1195: }
1196: switch (scopedPdu.getType()) {
1197: case PDU.GET:
1198: case PDU.GETBULK:
1199: case PDU.GETNEXT:
1200: case PDU.INFORM:
1201: case PDU.SET: {
1202: if (securityEngineID.length() == 0) {
1203: logger
1204: .debug("Received confirmed message with 0 length security engine ID");
1205: } else if (!securityEngineID.equals(localEngineID)) {
1206: if (logger.isDebugEnabled()) {
1207: logger
1208: .debug("RFC 3412 §7.2.13.a - Security engine ID "
1209: + securityEngineID
1210: .toHexString()
1211: + " does not match local engine ID "
1212: + new OctetString(localEngineID)
1213: .toHexString());
1214: }
1215: mutableStateReference.setStateReference(null);
1216: return SnmpConstants.SNMP_MP_INVALID_ENGINEID;
1217: }
1218: int cacheStatus = cache.addEntry(stateReference);
1219: if (cacheStatus == SnmpConstants.SNMP_MP_DOUBLED_MESSAGE) {
1220: mutableStateReference.setStateReference(null);
1221: }
1222: return SnmpConstants.SNMP_MP_OK;
1223: }
1224: case PDU.TRAP:
1225: case PDU.V1TRAP: {
1226: mutableStateReference.setStateReference(null);
1227: return SnmpConstants.SNMP_MP_OK;
1228: }
1229: }
1230: // this line should not be reached
1231: return SnmpConstants.SNMP_MP_ERROR;
1232: } catch (IOException iox) {
1233: logger.warn("MPv3 parse error: " + iox.getMessage());
1234: if (logger.isDebugEnabled()) {
1235: iox.printStackTrace();
1236: }
1237: return SnmpConstants.SNMP_MP_PARSE_ERROR;
1238: }
1239: }
1240:
1241: /**
1242: * Sets the security models supported by this MPv3.
1243: * @param securityModels
1244: * a <code>SecurityModels</code> instance.
1245: */
1246: public void setSecurityModels(SecurityModels securityModels) {
1247: this .securityModels = securityModels;
1248: }
1249:
1250: /**
1251: * Gets the security models supported by this MPv3.
1252: * @return
1253: * a <code>SecurityModels</code> instance.
1254: */
1255: public SecurityModels getSecurityModels() {
1256: return securityModels;
1257: }
1258:
1259: /**
1260: * Gets the enterprise ID used for creating the local engine ID.
1261: * @return
1262: * an enterprise ID as registered by the IANA (see http://www.iana.org).
1263: */
1264: public static int getEnterpriseID() {
1265: return enterpriseID;
1266: }
1267:
1268: /**
1269: * Sets the IANA enterprise ID to be used for creating local engine ID by
1270: * {@link #createLocalEngineID()}.
1271: * @param newEnterpriseID
1272: * an enterprise ID as registered by the IANA (see http://www.iana.org).
1273: */
1274: public static void setEnterpriseID(int newEnterpriseID) {
1275: enterpriseID = newEnterpriseID;
1276: }
1277:
1278: /**
1279: * Fire a counter incrementation event.
1280: * @param e CounterEvent
1281: */
1282: protected void fireIncrementCounter(CounterEvent e) {
1283: counterSupport.fireIncrementCounter(e);
1284: }
1285:
1286: /**
1287: * Gets the counter support instance that can be used to register for
1288: * counter incremnetation events.
1289: * @return
1290: * a <code>CounterSupport</code> instance that is used to fire
1291: * {@link CounterEvent}.
1292: */
1293: public CounterSupport getCounterSupport() {
1294: return counterSupport;
1295: }
1296:
1297: /**
1298: * Sets the counter support instance. By default, the singleton instance
1299: * provided by the {@link CounterSupport} instance is used.
1300: * @param counterSupport
1301: * a <code>CounterSupport</code> subclass instance.
1302: */
1303: public void setCounterSupport(CounterSupport counterSupport) {
1304: if (counterSupport == null) {
1305: throw new NullPointerException();
1306: }
1307: this .counterSupport = counterSupport;
1308: }
1309:
1310: /**
1311: * Adds a SNMP engine listener that needs to be informed about changes to
1312: * the engine ID cache.
1313: * @param l
1314: * a <code>SnmpEngineListener</code> instance.
1315: * @since 1.6
1316: */
1317: public synchronized void addSnmpEngineListener(SnmpEngineListener l) {
1318: if (snmpEngineListeners == null) {
1319: snmpEngineListeners = new Vector();
1320: }
1321: snmpEngineListeners.add(l);
1322: }
1323:
1324: /**
1325: * Removes a SNMP engine listener.
1326: * @param l
1327: * a <code>SnmpEngineListener</code> instance.
1328: * @since 1.6
1329: */
1330: public synchronized void removeSnmpEngineListener(
1331: SnmpEngineListener l) {
1332: if (snmpEngineListeners != null) {
1333: snmpEngineListeners.remove(l);
1334: }
1335: }
1336:
1337: /**
1338: * Creates a PDU class that is used to parse incoming SNMP messages.
1339: * @param target
1340: * the <code>target</code> parameter must be ignored.
1341: * @return
1342: * a {@link ScopedPDU} instance by default.
1343: * @since 1.9.1
1344: */
1345: public PDU createPDU(Target target) {
1346: return new ScopedPDU();
1347: }
1348:
1349: /**
1350: * Fires a SNMP engine event the registered listeners.
1351: * @param engineEvent
1352: * the <code>SnmpEngineEvent</code> instance to fire.
1353: * @since 1.6
1354: */
1355: protected void fireEngineChanged(SnmpEngineEvent engineEvent) {
1356: if (snmpEngineListeners != null) {
1357: Vector listeners = snmpEngineListeners;
1358: int count = listeners.size();
1359: for (int i = 0; i < count; i++) {
1360: ((SnmpEngineListener) listeners.elementAt(i))
1361: .engineChanged(engineEvent);
1362: }
1363: }
1364: }
1365: }
|