diff --git a/.gitignore b/.gitignore
index 0111e02..a5a1e41 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,3 +39,9 @@ dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.mvn/wrapper/maven-wrapper.jar
+
+# IntelliJ IDEA files
+*.iml
+.idea/
+*.iws
+*.ipr
diff --git a/README.md b/README.md
index 9721f79..625ed2e 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,15 @@
-# oss-maven-template
+# SNMP Java Client
-![GitHub release (with filter)](https://img.shields.io/github/v/release/sentrysoftware/oss-maven-template)
-![Build](https://img.shields.io/github/actions/workflow/status/sentrysoftware/oss-maven-template/deploy.yml)
-![GitHub top language](https://img.shields.io/github/languages/top/sentrysoftware/oss-maven-template)
-![License](https://img.shields.io/github/license/sentrysoftware/oss-maven-template)
+![GitHub release (with filter)](https://img.shields.io/github/v/release/sentrysoftware/snmp)
+![Build](https://img.shields.io/github/actions/workflow/status/sentrysoftware/snmp/deploy.yml)
+![GitHub top language](https://img.shields.io/github/languages/top/sentrysoftware/snmp)
+![License](https://img.shields.io/github/license/sentrysoftware/snmp)
-Repository template for all Sentry open-source Java projects, published on Maven Central.
+This project is a fork of the excellent [Westhawk's SNMP Library for Java](https://snmp.westhawk.co.uk/) ([see also](https://code.google.com/archive/p/snmp123)).
+
+The SNMP Java client is designed to interact with remote hosts implementing SNMP v1, v2c, or v3 and allows to execute SNMP requests, including `Get` and `GetNext` requests as well as `Walk` and `Table` functionalities that represent an enhancements over traditional SNMP `Get` and `GetNext` methods.
+
+See [Project Documentation](https://sentrysoftware.github.io/snmp/) and the [Javadoc](https://sentrysoftware.github.io/snmp/apidocs/) for more information on how to use this library in your code.
## Build instructions
@@ -31,8 +35,7 @@ But it is strongly recommended to only use [GitHub Actions "Release to Maven Cen
## License
-License is Apache-2. Each source file must include the Apache-2 header (build will fail otherwise).
-To update source files with the proper header, simply execute the below command:
+License is GNU General Lesser Public License (LGPL) version 3.0. Each source file includes the LGPL-3 header (build will fail otherwise). To update source files with the proper header, simply execute the below command:
```bash
mvn license:update-file-header
diff --git a/pom.xml b/pom.xml
index 6494976..827f02c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,18 +2,18 @@
4.0.0
org.sentrysoftware
- MYARTIFACT
- MY PROJECT
- 0.1.00-SNAPSHOT
- SOME DESCRIPTION
- jar
+ snmp
+ SNMP Java Client
+ 1.0.00-SNAPSHOT
+ SNMP Client Library for Java
+ jar
Sentry Software
https://sentrysoftware.com
- https://github.com/sentrysoftware/MYREPO
+ https://sentrysoftware.github.io/snmp
2023
@@ -29,37 +29,56 @@
- Apache-2.0
- https://www.apache.org/licenses/LICENSE-2.0.txt
+ LGPL-3.0
+ https://www.gnu.org/licenses/lgpl+gpl-3.0.txt
repo
GitHub
- https://github.com/sentrysoftware/MYREPO/issues/
+ https://github.com/sentrysoftware/snmp/issues/
- scm:git:https://github.com/sentrysoftware/MYREPO.git
- https://github.com/sentrysoftware/MYREPO
+ scm:git:https://github.com/sentrysoftware/snmp.git
+ https://sentrysoftware.github.io/snmp
HEAD
- MY NAME (@MY_ID)
- MYNAME@sentrysoftware.com
+ Bertrand Martin (@bertysentry)
+ bertrand@sentrysoftware.com
- Project founder
+ maintainer
+
+
+
+ Nassim Boutekedjiret (@NassimBtk)
+ nassim@sentrysoftware.com
+
+ maintainer
+
+
+
+ Kawtar Bakour (@KawtarBK9)
+ kawtar@sentrysoftware.com
+
+ maintainer
+
+
+
+ Elyes Cherfa (@CherfaElyes)
+ elyes@sentrysoftware.com
+
+ maintainer
- 11
- 11
11
@@ -153,7 +172,7 @@
license-maven-plugin
2.3.0
- apache_v2
+ lgpl_v3
Sentry Software
Copyright %1$s %2$s
@@ -183,6 +202,9 @@
maven-javadoc-plugin
+
+ all,-missing
+
attach-javadocs
diff --git a/src/main/java/org/bouncycastle/crypto/BlockCipher.java b/src/main/java/org/bouncycastle/crypto/BlockCipher.java
new file mode 100644
index 0000000..4aec920
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/BlockCipher.java
@@ -0,0 +1,78 @@
+package org.bouncycastle.crypto;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+
+/**
+ * Block cipher engines are expected to conform to this interface.
+ */
+public interface BlockCipher
+{
+ /**
+ * Initialise the cipher.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException;
+
+ /**
+ * Return the name of the algorithm the cipher implements.
+ *
+ * @return the name of the algorithm the cipher implements.
+ */
+ public String getAlgorithmName();
+
+ /**
+ * Return the block size for this cipher (in bytes).
+ *
+ * @return the block size for this cipher in bytes.
+ */
+ public int getBlockSize();
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException;
+
+ /**
+ * Reset the cipher. After resetting the cipher is in the same state
+ * as it was after the last init (if there was one).
+ */
+ public void reset();
+}
diff --git a/src/main/java/org/bouncycastle/crypto/CipherKeyGenerator.java b/src/main/java/org/bouncycastle/crypto/CipherKeyGenerator.java
new file mode 100644
index 0000000..4c887ed
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/CipherKeyGenerator.java
@@ -0,0 +1,60 @@
+package org.bouncycastle.crypto;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.security.SecureRandom;
+
+/**
+ * The base class for symmetric, or secret, cipher key generators.
+ */
+public class CipherKeyGenerator
+{
+ protected SecureRandom random;
+ protected int strength;
+
+ /**
+ * initialise the key generator.
+ *
+ * @param param the parameters to be used for key generation
+ */
+ public void init(
+ KeyGenerationParameters param)
+ {
+ this.random = param.getRandom();
+ this.strength = (param.getStrength() + 7) / 8;
+ }
+
+ /**
+ * generate a secret key.
+ *
+ * @return a byte array containing the key value.
+ */
+ public byte[] generateKey()
+ {
+ byte[] key = new byte[strength];
+
+ random.nextBytes(key);
+
+ return key;
+ }
+}
diff --git a/src/main/java/org/bouncycastle/crypto/CipherParameters.java b/src/main/java/org/bouncycastle/crypto/CipherParameters.java
new file mode 100644
index 0000000..84a83ca
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/CipherParameters.java
@@ -0,0 +1,30 @@
+package org.bouncycastle.crypto;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * all parameter classes implement this.
+ */
+public interface CipherParameters
+{
+}
diff --git a/src/main/java/org/bouncycastle/crypto/DataLengthException.java b/src/main/java/org/bouncycastle/crypto/DataLengthException.java
new file mode 100644
index 0000000..2241c49
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/DataLengthException.java
@@ -0,0 +1,51 @@
+package org.bouncycastle.crypto;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * this exception is thrown if a buffer that is meant to have output
+ * copied into it turns out to be too short, or if we've been given
+ * insufficient input. In general this exception will get thrown rather
+ * than an ArrayOutOfBounds exception.
+ */
+public class DataLengthException
+ extends RuntimeCryptoException
+{
+ /**
+ * base constructor.
+ */
+ public DataLengthException()
+ {
+ }
+
+ /**
+ * create a DataLengthException with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ */
+ public DataLengthException(
+ String message)
+ {
+ super(message);
+ }
+}
diff --git a/src/main/java/org/bouncycastle/crypto/Digest.java b/src/main/java/org/bouncycastle/crypto/Digest.java
new file mode 100644
index 0000000..5aeb249
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/Digest.java
@@ -0,0 +1,73 @@
+package org.bouncycastle.crypto;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * interface that a message digest conforms to.
+ */
+public interface Digest
+{
+ /**
+ * return the algorithm name
+ *
+ * @return the algorithm name
+ */
+ public String getAlgorithmName();
+
+ /**
+ * return the size, in bytes, of the digest produced by this message digest.
+ *
+ * @return the size, in bytes, of the digest produced by this message digest.
+ */
+ public int getDigestSize();
+
+ /**
+ * update the message digest with a single byte.
+ *
+ * @param in the input byte to be entered.
+ */
+ public void update(byte in);
+
+ /**
+ * update the message digest with a block of bytes.
+ *
+ * @param in the byte array containing the data.
+ * @param inOff the offset into the byte array where the data starts.
+ * @param len the length of the data.
+ */
+ public void update(byte[] in, int inOff, int len);
+
+ /**
+ * close the digest, producing the final digest value. The doFinal
+ * call leaves the digest reset.
+ *
+ * @param out the array the digest is to be copied into.
+ * @param outOff the offset into the out array the digest is to start at.
+ */
+ public int doFinal(byte[] out, int outOff);
+
+ /**
+ * reset the digest back to it's initial state.
+ */
+ public void reset();
+}
diff --git a/src/main/java/org/bouncycastle/crypto/KeyGenerationParameters.java b/src/main/java/org/bouncycastle/crypto/KeyGenerationParameters.java
new file mode 100644
index 0000000..73441ac
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/KeyGenerationParameters.java
@@ -0,0 +1,70 @@
+package org.bouncycastle.crypto;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.security.SecureRandom;
+
+/**
+ * The base class for parameters to key generators.
+ */
+public class KeyGenerationParameters
+{
+ private SecureRandom random;
+ private int strength;
+
+ /**
+ * initialise the generator with a source of randomness
+ * and a strength (in bits).
+ *
+ * @param random the random byte source.
+ * @param strength the size, in bits, of the keys we want to produce.
+ */
+ public KeyGenerationParameters(
+ SecureRandom random,
+ int strength)
+ {
+ this.random = random;
+ this.strength = strength;
+ }
+
+ /**
+ * return the random source associated with this
+ * generator.
+ *
+ * @return the generators random source.
+ */
+ public SecureRandom getRandom()
+ {
+ return random;
+ }
+
+ /**
+ * return the bit strength for keys produced by this generator,
+ *
+ * @return the strength of the keys this generator produces (in bits).
+ */
+ public int getStrength()
+ {
+ return strength;
+ }
+}
diff --git a/src/main/java/org/bouncycastle/crypto/RuntimeCryptoException.java b/src/main/java/org/bouncycastle/crypto/RuntimeCryptoException.java
new file mode 100644
index 0000000..14efaf1
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/RuntimeCryptoException.java
@@ -0,0 +1,48 @@
+package org.bouncycastle.crypto;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * the foundation class for the exceptions thrown by the crypto packages.
+ */
+public class RuntimeCryptoException
+ extends RuntimeException
+{
+ /**
+ * base constructor.
+ */
+ public RuntimeCryptoException()
+ {
+ }
+
+ /**
+ * create a RuntimeCryptoException with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ */
+ public RuntimeCryptoException(
+ String message)
+ {
+ super(message);
+ }
+}
diff --git a/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java b/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java
new file mode 100644
index 0000000..75115c0
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java
@@ -0,0 +1,150 @@
+package org.bouncycastle.crypto.digests;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import org.bouncycastle.crypto.Digest;
+
+/**
+ * base implementation of MD4 family style digest as outlined in
+ * "Handbook of Applied Cryptography", pages 344 - 347.
+ */
+public abstract class GeneralDigest
+ implements Digest
+{
+ private byte[] xBuf;
+ private int xBufOff;
+
+ private long byteCount;
+
+ /**
+ * Standard constructor
+ */
+ protected GeneralDigest()
+ {
+ xBuf = new byte[4];
+ xBufOff = 0;
+ }
+
+ /**
+ * Copy constructor. We are using copy constructors in place
+ * of the Object.clone() interface as this interface is not
+ * supported by J2ME.
+ */
+ protected GeneralDigest(GeneralDigest t)
+ {
+ xBuf = new byte[t.xBuf.length];
+ System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
+
+ xBufOff = t.xBufOff;
+ byteCount = t.byteCount;
+ }
+
+ public void update(
+ byte in)
+ {
+ xBuf[xBufOff++] = in;
+
+ if (xBufOff == xBuf.length)
+ {
+ processWord(xBuf, 0);
+ xBufOff = 0;
+ }
+
+ byteCount++;
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ //
+ // fill the current word
+ //
+ while ((xBufOff != 0) && (len > 0))
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+
+ //
+ // process whole words.
+ //
+ while (len > xBuf.length)
+ {
+ processWord(in, inOff);
+
+ inOff += xBuf.length;
+ len -= xBuf.length;
+ byteCount += xBuf.length;
+ }
+
+ //
+ // load in the remainder.
+ //
+ while (len > 0)
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+ }
+
+ public void finish()
+ {
+ long bitLength = (byteCount << 3);
+
+ //
+ // add the pad bytes.
+ //
+ update((byte)128);
+
+ while (xBufOff != 0)
+ {
+ update((byte)0);
+ }
+
+ processLength(bitLength);
+
+ processBlock();
+ }
+
+ public void reset()
+ {
+ byteCount = 0;
+
+ xBufOff = 0;
+ for ( int i = 0; i < xBuf.length; i++ ) {
+ xBuf[i] = 0;
+ }
+ }
+
+ protected abstract void processWord(byte[] in, int inOff);
+
+ protected abstract void processLength(long bitLength);
+
+ protected abstract void processBlock();
+}
diff --git a/src/main/java/org/bouncycastle/crypto/digests/MD5Digest.java b/src/main/java/org/bouncycastle/crypto/digests/MD5Digest.java
new file mode 100644
index 0000000..3767f20
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/digests/MD5Digest.java
@@ -0,0 +1,324 @@
+package org.bouncycastle.crypto.digests;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+
+/**
+ * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347.
+ */
+public class MD5Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 16;
+
+ private int H1, H2, H3, H4; // IV's
+
+ private int[] X = new int[16];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public MD5Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public MD5Digest(MD5Digest t)
+ {
+ super(t);
+
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "MD5";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
+ | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
+
+ if (xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength & 0xffffffff);
+ X[15] = (int)(bitLength >>> 32);
+ }
+
+ private void unpackWord(
+ int word,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff] = (byte)word;
+ out[outOff + 1] = (byte)(word >>> 8);
+ out[outOff + 2] = (byte)(word >>> 16);
+ out[outOff + 3] = (byte)(word >>> 24);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ unpackWord(H1, out, outOff);
+ unpackWord(H2, out, outOff + 4);
+ unpackWord(H3, out, outOff + 8);
+ unpackWord(H4, out, outOff + 12);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables to the IV values.
+ */
+ public void reset()
+ {
+ super.reset();
+
+ H1 = 0x67452301;
+ H2 = 0xefcdab89;
+ H3 = 0x98badcfe;
+ H4 = 0x10325476;
+
+ xOff = 0;
+
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ //
+ // round 1 left rotates
+ //
+ private static final int S11 = 7;
+ private static final int S12 = 12;
+ private static final int S13 = 17;
+ private static final int S14 = 22;
+
+ //
+ // round 2 left rotates
+ //
+ private static final int S21 = 5;
+ private static final int S22 = 9;
+ private static final int S23 = 14;
+ private static final int S24 = 20;
+
+ //
+ // round 3 left rotates
+ //
+ private static final int S31 = 4;
+ private static final int S32 = 11;
+ private static final int S33 = 16;
+ private static final int S34 = 23;
+
+ //
+ // round 4 left rotates
+ //
+ private static final int S41 = 6;
+ private static final int S42 = 10;
+ private static final int S43 = 15;
+ private static final int S44 = 21;
+
+ /*
+ * rotate int x left n bits.
+ */
+ private int rotateLeft(
+ int x,
+ int n)
+ {
+ return (x << n) | (x >>> (32 - n));
+ }
+
+ /*
+ * F, G, H and I are the basic MD5 functions.
+ */
+ private int F(
+ int u,
+ int v,
+ int w)
+ {
+ return (u & v) | (~u & w);
+ }
+
+ private int G(
+ int u,
+ int v,
+ int w)
+ {
+ return (u & w) | (v & ~w);
+ }
+
+ private int H(
+ int u,
+ int v,
+ int w)
+ {
+ return u ^ v ^ w;
+ }
+
+ private int K(
+ int u,
+ int v,
+ int w)
+ {
+ return v ^ (u | ~w);
+ }
+
+ protected void processBlock()
+ {
+ int a = H1;
+ int b = H2;
+ int c = H3;
+ int d = H4;
+
+ //
+ // Round 1 - F cycle, 16 times.
+ //
+ a = rotateLeft((a + F(b, c, d) + X[ 0] + 0xd76aa478), S11) + b;
+ d = rotateLeft((d + F(a, b, c) + X[ 1] + 0xe8c7b756), S12) + a;
+ c = rotateLeft((c + F(d, a, b) + X[ 2] + 0x242070db), S13) + d;
+ b = rotateLeft((b + F(c, d, a) + X[ 3] + 0xc1bdceee), S14) + c;
+ a = rotateLeft((a + F(b, c, d) + X[ 4] + 0xf57c0faf), S11) + b;
+ d = rotateLeft((d + F(a, b, c) + X[ 5] + 0x4787c62a), S12) + a;
+ c = rotateLeft((c + F(d, a, b) + X[ 6] + 0xa8304613), S13) + d;
+ b = rotateLeft((b + F(c, d, a) + X[ 7] + 0xfd469501), S14) + c;
+ a = rotateLeft((a + F(b, c, d) + X[ 8] + 0x698098d8), S11) + b;
+ d = rotateLeft((d + F(a, b, c) + X[ 9] + 0x8b44f7af), S12) + a;
+ c = rotateLeft((c + F(d, a, b) + X[10] + 0xffff5bb1), S13) + d;
+ b = rotateLeft((b + F(c, d, a) + X[11] + 0x895cd7be), S14) + c;
+ a = rotateLeft((a + F(b, c, d) + X[12] + 0x6b901122), S11) + b;
+ d = rotateLeft((d + F(a, b, c) + X[13] + 0xfd987193), S12) + a;
+ c = rotateLeft((c + F(d, a, b) + X[14] + 0xa679438e), S13) + d;
+ b = rotateLeft((b + F(c, d, a) + X[15] + 0x49b40821), S14) + c;
+
+ //
+ // Round 2 - G cycle, 16 times.
+ //
+ a = rotateLeft((a + G(b, c, d) + X[ 1] + 0xf61e2562), S21) + b;
+ d = rotateLeft((d + G(a, b, c) + X[ 6] + 0xc040b340), S22) + a;
+ c = rotateLeft((c + G(d, a, b) + X[11] + 0x265e5a51), S23) + d;
+ b = rotateLeft((b + G(c, d, a) + X[ 0] + 0xe9b6c7aa), S24) + c;
+ a = rotateLeft((a + G(b, c, d) + X[ 5] + 0xd62f105d), S21) + b;
+ d = rotateLeft((d + G(a, b, c) + X[10] + 0x02441453), S22) + a;
+ c = rotateLeft((c + G(d, a, b) + X[15] + 0xd8a1e681), S23) + d;
+ b = rotateLeft((b + G(c, d, a) + X[ 4] + 0xe7d3fbc8), S24) + c;
+ a = rotateLeft((a + G(b, c, d) + X[ 9] + 0x21e1cde6), S21) + b;
+ d = rotateLeft((d + G(a, b, c) + X[14] + 0xc33707d6), S22) + a;
+ c = rotateLeft((c + G(d, a, b) + X[ 3] + 0xf4d50d87), S23) + d;
+ b = rotateLeft((b + G(c, d, a) + X[ 8] + 0x455a14ed), S24) + c;
+ a = rotateLeft((a + G(b, c, d) + X[13] + 0xa9e3e905), S21) + b;
+ d = rotateLeft((d + G(a, b, c) + X[ 2] + 0xfcefa3f8), S22) + a;
+ c = rotateLeft((c + G(d, a, b) + X[ 7] + 0x676f02d9), S23) + d;
+ b = rotateLeft((b + G(c, d, a) + X[12] + 0x8d2a4c8a), S24) + c;
+
+ //
+ // Round 3 - H cycle, 16 times.
+ //
+ a = rotateLeft((a + H(b, c, d) + X[ 5] + 0xfffa3942), S31) + b;
+ d = rotateLeft((d + H(a, b, c) + X[ 8] + 0x8771f681), S32) + a;
+ c = rotateLeft((c + H(d, a, b) + X[11] + 0x6d9d6122), S33) + d;
+ b = rotateLeft((b + H(c, d, a) + X[14] + 0xfde5380c), S34) + c;
+ a = rotateLeft((a + H(b, c, d) + X[ 1] + 0xa4beea44), S31) + b;
+ d = rotateLeft((d + H(a, b, c) + X[ 4] + 0x4bdecfa9), S32) + a;
+ c = rotateLeft((c + H(d, a, b) + X[ 7] + 0xf6bb4b60), S33) + d;
+ b = rotateLeft((b + H(c, d, a) + X[10] + 0xbebfbc70), S34) + c;
+ a = rotateLeft((a + H(b, c, d) + X[13] + 0x289b7ec6), S31) + b;
+ d = rotateLeft((d + H(a, b, c) + X[ 0] + 0xeaa127fa), S32) + a;
+ c = rotateLeft((c + H(d, a, b) + X[ 3] + 0xd4ef3085), S33) + d;
+ b = rotateLeft((b + H(c, d, a) + X[ 6] + 0x04881d05), S34) + c;
+ a = rotateLeft((a + H(b, c, d) + X[ 9] + 0xd9d4d039), S31) + b;
+ d = rotateLeft((d + H(a, b, c) + X[12] + 0xe6db99e5), S32) + a;
+ c = rotateLeft((c + H(d, a, b) + X[15] + 0x1fa27cf8), S33) + d;
+ b = rotateLeft((b + H(c, d, a) + X[ 2] + 0xc4ac5665), S34) + c;
+
+ //
+ // Round 4 - K cycle, 16 times.
+ //
+ a = rotateLeft((a + K(b, c, d) + X[ 0] + 0xf4292244), S41) + b;
+ d = rotateLeft((d + K(a, b, c) + X[ 7] + 0x432aff97), S42) + a;
+ c = rotateLeft((c + K(d, a, b) + X[14] + 0xab9423a7), S43) + d;
+ b = rotateLeft((b + K(c, d, a) + X[ 5] + 0xfc93a039), S44) + c;
+ a = rotateLeft((a + K(b, c, d) + X[12] + 0x655b59c3), S41) + b;
+ d = rotateLeft((d + K(a, b, c) + X[ 3] + 0x8f0ccc92), S42) + a;
+ c = rotateLeft((c + K(d, a, b) + X[10] + 0xffeff47d), S43) + d;
+ b = rotateLeft((b + K(c, d, a) + X[ 1] + 0x85845dd1), S44) + c;
+ a = rotateLeft((a + K(b, c, d) + X[ 8] + 0x6fa87e4f), S41) + b;
+ d = rotateLeft((d + K(a, b, c) + X[15] + 0xfe2ce6e0), S42) + a;
+ c = rotateLeft((c + K(d, a, b) + X[ 6] + 0xa3014314), S43) + d;
+ b = rotateLeft((b + K(c, d, a) + X[13] + 0x4e0811a1), S44) + c;
+ a = rotateLeft((a + K(b, c, d) + X[ 4] + 0xf7537e82), S41) + b;
+ d = rotateLeft((d + K(a, b, c) + X[11] + 0xbd3af235), S42) + a;
+ c = rotateLeft((c + K(d, a, b) + X[ 2] + 0x2ad7d2bb), S43) + d;
+ b = rotateLeft((b + K(c, d, a) + X[ 9] + 0xeb86d391), S44) + c;
+
+ H1 += a;
+ H2 += b;
+ H3 += c;
+ H4 += d;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+}
diff --git a/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java b/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java
new file mode 100644
index 0000000..3ab7459
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java
@@ -0,0 +1,280 @@
+package org.bouncycastle.crypto.digests;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+
+/**
+ * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349.
+ *
+ * It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5
+ * is the "endienness" of the word processing!
+ */
+public class SHA1Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 20;
+
+ private int H1, H2, H3, H4, H5;
+
+ private int[] X = new int[80];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public SHA1Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public SHA1Digest(SHA1Digest t)
+ {
+ super(t);
+
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+ H5 = t.H5;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SHA-1";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ X[xOff++] = ((in[inOff] & 0xff) << 24) | ((in[inOff + 1] & 0xff) << 16)
+ | ((in[inOff + 2] & 0xff) << 8) | ((in[inOff + 3] & 0xff));
+
+ if (xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ private void unpackWord(
+ int word,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff] = (byte)(word >>> 24);
+ out[outOff + 1] = (byte)(word >>> 16);
+ out[outOff + 2] = (byte)(word >>> 8);
+ out[outOff + 3] = (byte)word;
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength >>> 32);
+ X[15] = (int)(bitLength & 0xffffffff);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ unpackWord(H1, out, outOff);
+ unpackWord(H2, out, outOff + 4);
+ unpackWord(H3, out, outOff + 8);
+ unpackWord(H4, out, outOff + 12);
+ unpackWord(H5, out, outOff + 16);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ super.reset();
+
+ H1 = 0x67452301;
+ H2 = 0xefcdab89;
+ H3 = 0x98badcfe;
+ H4 = 0x10325476;
+ H5 = 0xc3d2e1f0;
+
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ //
+ // Additive constants
+ //
+ private static final int Y1 = 0x5a827999;
+ private static final int Y2 = 0x6ed9eba1;
+ private static final int Y3 = 0x8f1bbcdc;
+ private static final int Y4 = 0xca62c1d6;
+
+ private int f(
+ int u,
+ int v,
+ int w)
+ {
+ return ((u & v) | ((~u) & w));
+ }
+
+ private int h(
+ int u,
+ int v,
+ int w)
+ {
+ return (u ^ v ^ w);
+ }
+
+ private int g(
+ int u,
+ int v,
+ int w)
+ {
+ return ((u & v) | (u & w) | (v & w));
+ }
+
+ private int rotateLeft(
+ int x,
+ int n)
+ {
+ return (x << n) | (x >>> (32 - n));
+ }
+
+ protected void processBlock()
+ {
+ //
+ // expand 16 word block into 80 word block.
+ //
+ for (int i = 16; i <= 79; i++)
+ {
+ X[i] = rotateLeft((X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16]), 1);
+ }
+
+ //
+ // set up working variables.
+ //
+ int A = H1;
+ int B = H2;
+ int C = H3;
+ int D = H4;
+ int E = H5;
+
+ //
+ // round 1
+ //
+ for (int j = 0; j <= 19; j++)
+ {
+ int t = rotateLeft(A, 5) + f(B, C, D) + E + X[j] + Y1;
+
+ E = D;
+ D = C;
+ C = rotateLeft(B, 30);
+ B = A;
+ A = t;
+ }
+
+ //
+ // round 2
+ //
+ for (int j = 20; j <= 39; j++)
+ {
+ int t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y2;
+
+ E = D;
+ D = C;
+ C = rotateLeft(B, 30);
+ B = A;
+ A = t;
+ }
+
+ //
+ // round 3
+ //
+ for (int j = 40; j <= 59; j++)
+ {
+ int t = rotateLeft(A, 5) + g(B, C, D) + E + X[j] + Y3;
+
+ E = D;
+ D = C;
+ C = rotateLeft(B, 30);
+ B = A;
+ A = t;
+ }
+
+ //
+ // round 4
+ //
+ for (int j = 60; j <= 79; j++)
+ {
+ int t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y4;
+
+ E = D;
+ D = C;
+ C = rotateLeft(B, 30);
+ B = A;
+ A = t;
+ }
+
+ H1 += A;
+ H2 += B;
+ H3 += C;
+ H4 += D;
+ H5 += E;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+}
diff --git a/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java b/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java
new file mode 100644
index 0000000..be17280
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java
@@ -0,0 +1,550 @@
+package org.bouncycastle.crypto.engines;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * an implementation of the AES (Rijndael), from FIPS-197.
+ *
+ * For further details see: http://csrc.nist.gov/encryption/aes/.
+ *
+ * This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
+ * http://fp.gladman.plus.com/cryptography_technology/rijndael/
+ *
+ * There are three levels of tradeoff of speed vs memory
+ * Because java has no preprocessor, they are written as three separate classes from which to choose
+ *
+ * The fastest uses 8Kbytes of static tables to precompute round calculations, 4 256 word tables for encryption
+ * and 4 for decryption.
+ *
+ * The middle performance version uses only one 256 word table for each, for a total of 2Kbytes,
+ * adding 12 rotate operations per round to compute the values contained in the other tables from
+ * the contents of the first.
+ *
+ * The slowest version uses no static tables at all and computes the values in each round.
+ *
+ * This file contains the middle performance version with 2Kbytes of static tables for round precomputation.
+ *
+ */
+public class AESEngine
+ implements BlockCipher
+{
+ // The S box
+ private static final byte[] S = {
+ (byte)99, (byte)124, (byte)119, (byte)123, (byte)242, (byte)107, (byte)111, (byte)197,
+ (byte)48, (byte)1, (byte)103, (byte)43, (byte)254, (byte)215, (byte)171, (byte)118,
+ (byte)202, (byte)130, (byte)201, (byte)125, (byte)250, (byte)89, (byte)71, (byte)240,
+ (byte)173, (byte)212, (byte)162, (byte)175, (byte)156, (byte)164, (byte)114, (byte)192,
+ (byte)183, (byte)253, (byte)147, (byte)38, (byte)54, (byte)63, (byte)247, (byte)204,
+ (byte)52, (byte)165, (byte)229, (byte)241, (byte)113, (byte)216, (byte)49, (byte)21,
+ (byte)4, (byte)199, (byte)35, (byte)195, (byte)24, (byte)150, (byte)5, (byte)154,
+ (byte)7, (byte)18, (byte)128, (byte)226, (byte)235, (byte)39, (byte)178, (byte)117,
+ (byte)9, (byte)131, (byte)44, (byte)26, (byte)27, (byte)110, (byte)90, (byte)160,
+ (byte)82, (byte)59, (byte)214, (byte)179, (byte)41, (byte)227, (byte)47, (byte)132,
+ (byte)83, (byte)209, (byte)0, (byte)237, (byte)32, (byte)252, (byte)177, (byte)91,
+ (byte)106, (byte)203, (byte)190, (byte)57, (byte)74, (byte)76, (byte)88, (byte)207,
+ (byte)208, (byte)239, (byte)170, (byte)251, (byte)67, (byte)77, (byte)51, (byte)133,
+ (byte)69, (byte)249, (byte)2, (byte)127, (byte)80, (byte)60, (byte)159, (byte)168,
+ (byte)81, (byte)163, (byte)64, (byte)143, (byte)146, (byte)157, (byte)56, (byte)245,
+ (byte)188, (byte)182, (byte)218, (byte)33, (byte)16, (byte)255, (byte)243, (byte)210,
+ (byte)205, (byte)12, (byte)19, (byte)236, (byte)95, (byte)151, (byte)68, (byte)23,
+ (byte)196, (byte)167, (byte)126, (byte)61, (byte)100, (byte)93, (byte)25, (byte)115,
+ (byte)96, (byte)129, (byte)79, (byte)220, (byte)34, (byte)42, (byte)144, (byte)136,
+ (byte)70, (byte)238, (byte)184, (byte)20, (byte)222, (byte)94, (byte)11, (byte)219,
+ (byte)224, (byte)50, (byte)58, (byte)10, (byte)73, (byte)6, (byte)36, (byte)92,
+ (byte)194, (byte)211, (byte)172, (byte)98, (byte)145, (byte)149, (byte)228, (byte)121,
+ (byte)231, (byte)200, (byte)55, (byte)109, (byte)141, (byte)213, (byte)78, (byte)169,
+ (byte)108, (byte)86, (byte)244, (byte)234, (byte)101, (byte)122, (byte)174, (byte)8,
+ (byte)186, (byte)120, (byte)37, (byte)46, (byte)28, (byte)166, (byte)180, (byte)198,
+ (byte)232, (byte)221, (byte)116, (byte)31, (byte)75, (byte)189, (byte)139, (byte)138,
+ (byte)112, (byte)62, (byte)181, (byte)102, (byte)72, (byte)3, (byte)246, (byte)14,
+ (byte)97, (byte)53, (byte)87, (byte)185, (byte)134, (byte)193, (byte)29, (byte)158,
+ (byte)225, (byte)248, (byte)152, (byte)17, (byte)105, (byte)217, (byte)142, (byte)148,
+ (byte)155, (byte)30, (byte)135, (byte)233, (byte)206, (byte)85, (byte)40, (byte)223,
+ (byte)140, (byte)161, (byte)137, (byte)13, (byte)191, (byte)230, (byte)66, (byte)104,
+ (byte)65, (byte)153, (byte)45, (byte)15, (byte)176, (byte)84, (byte)187, (byte)22,
+ };
+
+ // The inverse S-box
+ private static final byte[] Si = {
+ (byte)82, (byte)9, (byte)106, (byte)213, (byte)48, (byte)54, (byte)165, (byte)56,
+ (byte)191, (byte)64, (byte)163, (byte)158, (byte)129, (byte)243, (byte)215, (byte)251,
+ (byte)124, (byte)227, (byte)57, (byte)130, (byte)155, (byte)47, (byte)255, (byte)135,
+ (byte)52, (byte)142, (byte)67, (byte)68, (byte)196, (byte)222, (byte)233, (byte)203,
+ (byte)84, (byte)123, (byte)148, (byte)50, (byte)166, (byte)194, (byte)35, (byte)61,
+ (byte)238, (byte)76, (byte)149, (byte)11, (byte)66, (byte)250, (byte)195, (byte)78,
+ (byte)8, (byte)46, (byte)161, (byte)102, (byte)40, (byte)217, (byte)36, (byte)178,
+ (byte)118, (byte)91, (byte)162, (byte)73, (byte)109, (byte)139, (byte)209, (byte)37,
+ (byte)114, (byte)248, (byte)246, (byte)100, (byte)134, (byte)104, (byte)152, (byte)22,
+ (byte)212, (byte)164, (byte)92, (byte)204, (byte)93, (byte)101, (byte)182, (byte)146,
+ (byte)108, (byte)112, (byte)72, (byte)80, (byte)253, (byte)237, (byte)185, (byte)218,
+ (byte)94, (byte)21, (byte)70, (byte)87, (byte)167, (byte)141, (byte)157, (byte)132,
+ (byte)144, (byte)216, (byte)171, (byte)0, (byte)140, (byte)188, (byte)211, (byte)10,
+ (byte)247, (byte)228, (byte)88, (byte)5, (byte)184, (byte)179, (byte)69, (byte)6,
+ (byte)208, (byte)44, (byte)30, (byte)143, (byte)202, (byte)63, (byte)15, (byte)2,
+ (byte)193, (byte)175, (byte)189, (byte)3, (byte)1, (byte)19, (byte)138, (byte)107,
+ (byte)58, (byte)145, (byte)17, (byte)65, (byte)79, (byte)103, (byte)220, (byte)234,
+ (byte)151, (byte)242, (byte)207, (byte)206, (byte)240, (byte)180, (byte)230, (byte)115,
+ (byte)150, (byte)172, (byte)116, (byte)34, (byte)231, (byte)173, (byte)53, (byte)133,
+ (byte)226, (byte)249, (byte)55, (byte)232, (byte)28, (byte)117, (byte)223, (byte)110,
+ (byte)71, (byte)241, (byte)26, (byte)113, (byte)29, (byte)41, (byte)197, (byte)137,
+ (byte)111, (byte)183, (byte)98, (byte)14, (byte)170, (byte)24, (byte)190, (byte)27,
+ (byte)252, (byte)86, (byte)62, (byte)75, (byte)198, (byte)210, (byte)121, (byte)32,
+ (byte)154, (byte)219, (byte)192, (byte)254, (byte)120, (byte)205, (byte)90, (byte)244,
+ (byte)31, (byte)221, (byte)168, (byte)51, (byte)136, (byte)7, (byte)199, (byte)49,
+ (byte)177, (byte)18, (byte)16, (byte)89, (byte)39, (byte)128, (byte)236, (byte)95,
+ (byte)96, (byte)81, (byte)127, (byte)169, (byte)25, (byte)181, (byte)74, (byte)13,
+ (byte)45, (byte)229, (byte)122, (byte)159, (byte)147, (byte)201, (byte)156, (byte)239,
+ (byte)160, (byte)224, (byte)59, (byte)77, (byte)174, (byte)42, (byte)245, (byte)176,
+ (byte)200, (byte)235, (byte)187, (byte)60, (byte)131, (byte)83, (byte)153, (byte)97,
+ (byte)23, (byte)43, (byte)4, (byte)126, (byte)186, (byte)119, (byte)214, (byte)38,
+ (byte)225, (byte)105, (byte)20, (byte)99, (byte)85, (byte)33, (byte)12, (byte)125,
+ };
+
+ // vector used in calculating key schedule (powers of x in GF(256))
+ private static final int[] rcon = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
+ 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 };
+
+ // precomputation tables of calculations for rounds
+ private static final int[] T0 =
+ {
+ 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff,
+ 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102,
+ 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d,
+ 0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
+ 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, 0xecadad41,
+ 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
+ 0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d,
+ 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
+ 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, 0x937171e2,
+ 0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795,
+ 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a,
+ 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
+ 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912,
+ 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc,
+ 0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7,
+ 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
+ 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040,
+ 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
+ 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0,
+ 0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
+ 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a,
+ 0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78,
+ 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, 0xc0404080,
+ 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
+ 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020,
+ 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18,
+ 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488,
+ 0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
+ 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0,
+ 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
+ 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b,
+ 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
+ 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992,
+ 0x0a06060c, 0x6c242448, 0xe45c5cb8, 0x5dc2c29f, 0x6ed3d3bd,
+ 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3,
+ 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
+ 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8,
+ 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4,
+ 0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a,
+ 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
+ 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96,
+ 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
+ 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7,
+ 0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
+ 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9,
+ 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9,
+ 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715,
+ 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
+ 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65,
+ 0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929,
+ 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d,
+ 0x3a16162c};
+
+private static final int[] Tinv0 =
+ {
+ 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b,
+ 0xf1459d1f, 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad,
+ 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526,
+ 0x8fa362b5, 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d,
+ 0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, 0xe75f8f03,
+ 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458,
+ 0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899,
+ 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d,
+ 0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 0xe07764b1,
+ 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 0x58684870, 0x19fd458f,
+ 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3,
+ 0x2aab5566, 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3,
+ 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a,
+ 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506,
+ 0x1f6234d1, 0x8afea6c4, 0x9d532e34, 0xa055f3a2, 0x32e18a05,
+ 0x75ebf6a4, 0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd,
+ 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491,
+ 0x055dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6,
+ 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7,
+ 0xdbeec879, 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000,
+ 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 0xfbff0efd,
+ 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68,
+ 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0x0fe75793, 0xd296eeb4,
+ 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
+ 0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0x0b0d090e,
+ 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af,
+ 0xbbdd99ee, 0xfd607fa3, 0x9f2601f7, 0xbcf5725c, 0xc53b6644,
+ 0x347efb5b, 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8,
+ 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85,
+ 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc,
+ 0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411,
+ 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322,
+ 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6,
+ 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, 0xe49d3a2c, 0x0d927850,
+ 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e,
+ 0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
+ 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x097826cd,
+ 0xf418596e, 0x01b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa,
+ 0x08cfbc21, 0xe6e815ef, 0xd99be7ba, 0xce366f4a, 0xd4099fea,
+ 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235,
+ 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 0x4a9804f1,
+ 0xf7daec41, 0x0e50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43,
+ 0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1,
+ 0x7f516546, 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb,
+ 0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, 0x8c61d79a,
+ 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7,
+ 0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418,
+ 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
+ 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16,
+ 0x0c25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08,
+ 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48,
+ 0x4257b8d0};
+
+ private int shift(
+ int r,
+ int shift)
+ {
+ return (((r >>> shift) | (r << (32 - shift))));
+ }
+
+ /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
+
+ private static final int m1 = 0x80808080;
+ private static final int m2 = 0x7f7f7f7f;
+ private static final int m3 = 0x0000001b;
+ private int FFmulX(int x) {
+ return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3));
+ }
+
+ /*
+ The following defines provide alternative definitions of FFmulX that might
+ give improved performance if a fast 32-bit multiply is not available.
+
+ private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & m2) << 1) ^ ((u >>> 3) | (u >>> 6)); }
+ private static final int m4 = 0x1b1b1b1b;
+ private int FFmulX(int x) { int u = x & m1; return ((x & m2) << 1) ^ ((u - (u >>> 7)) & m4); }
+
+ */
+
+ private int inv_mcol(int x) {
+ int f2 = FFmulX(x);
+ int f4 = FFmulX(f2);
+ int f8 = FFmulX(f4);
+ int f9 = x ^ f8;
+
+ return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24);
+ }
+
+ private int subWord(int x) {
+ return (S[x&255]&255 | ((S[(x>>8)&255]&255)<<8) | ((S[(x>>16)&255]&255)<<16) | S[(x>>24)&255]<<24);
+ }
+
+ /**
+ * Calculate the necessary round keys
+ * The number of calculations depends on key size and block size
+ * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
+ * This code is written assuming those are the only possible values
+ */
+ private int[][] generateWorkingKey(
+ byte[] key,
+ boolean forEncryption)
+ {
+ int KC = key.length / 4; // key length in words
+ int t;
+
+ if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length)) {
+ throw new IllegalArgumentException("Key length not 128/192/256 bits.");
+ }
+
+ ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes
+ int[][] W = new int[ROUNDS+1][4]; // 4 words in a block
+
+ //
+ // copy the key into the round key array
+ //
+
+ t = 0;
+ for (int i = 0; i < key.length; t++)
+ {
+ W[t >> 2][t & 3] = (key[i]&0xff) | ((key[i+1]&0xff) << 8) | ((key[i+2]&0xff) << 16) | (key[i+3] << 24);
+ i+=4;
+ }
+
+ //
+ // while not enough round key material calculated
+ // calculate new values
+ //
+ int k = (ROUNDS + 1) << 2;
+ for (int i = KC; (i < k); i++)
+ {
+ int temp = W[(i-1)>>2][(i-1)&3];
+ if ((i % KC) == 0) {
+ temp = subWord(shift(temp, 8)) ^ rcon[(i / KC)-1];
+ } else if ((KC > 6) && ((i % KC) == 4)) {
+ temp = subWord(temp);
+ }
+
+ W[i>>2][i&3] = W[(i - KC)>>2][(i-KC)&3] ^ temp;
+ }
+
+ if (!forEncryption) {
+ for (int j = 1; j < ROUNDS; j++) {
+ for (int i = 0; i < 4; i++){
+ W[j][i] = inv_mcol(W[j][i]);
+ }
+ }
+ }
+
+ return W;
+ }
+
+ private int ROUNDS;
+ private int[][] WorkingKey = null;
+ private int C0, C1, C2, C3;
+ private boolean forEncryption;
+
+ private static final int BLOCK_SIZE = 16;
+
+ /**
+ * default constructor - 128 bit block size.
+ */
+ public AESEngine()
+ {
+ }
+
+ /**
+ * initialise an AES cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ WorkingKey = generateWorkingKey(((KeyParameter)params).getKey(), forEncryption);
+ this.forEncryption = forEncryption;
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to AES init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "AES";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (WorkingKey == null)
+ {
+ throw new IllegalStateException("AES engine not initialised");
+ }
+
+ if ((inOff + (32 / 2)) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + (32 / 2)) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (forEncryption)
+ {
+ unpackBlock(in, inOff);
+ encryptBlock(WorkingKey);
+ packBlock(out, outOff);
+ }
+ else
+ {
+ unpackBlock(in, inOff);
+ decryptBlock(WorkingKey);
+ packBlock(out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ private final void unpackBlock(
+ byte[] bytes,
+ int off)
+ {
+ int index = off;
+
+ C0 = (bytes[index++] & 0xff);
+ C0 |= (bytes[index++] & 0xff) << 8;
+ C0 |= (bytes[index++] & 0xff) << 16;
+ C0 |= bytes[index++] << 24;
+
+ C1 = (bytes[index++] & 0xff);
+ C1 |= (bytes[index++] & 0xff) << 8;
+ C1 |= (bytes[index++] & 0xff) << 16;
+ C1 |= bytes[index++] << 24;
+
+ C2 = (bytes[index++] & 0xff);
+ C2 |= (bytes[index++] & 0xff) << 8;
+ C2 |= (bytes[index++] & 0xff) << 16;
+ C2 |= bytes[index++] << 24;
+
+ C3 = (bytes[index++] & 0xff);
+ C3 |= (bytes[index++] & 0xff) << 8;
+ C3 |= (bytes[index++] & 0xff) << 16;
+ C3 |= bytes[index++] << 24;
+ }
+
+ private final void packBlock(
+ byte[] bytes,
+ int off)
+ {
+ int index = off;
+
+ bytes[index++] = (byte)C0;
+ bytes[index++] = (byte)(C0 >> 8);
+ bytes[index++] = (byte)(C0 >> 16);
+ bytes[index++] = (byte)(C0 >> 24);
+
+ bytes[index++] = (byte)C1;
+ bytes[index++] = (byte)(C1 >> 8);
+ bytes[index++] = (byte)(C1 >> 16);
+ bytes[index++] = (byte)(C1 >> 24);
+
+ bytes[index++] = (byte)C2;
+ bytes[index++] = (byte)(C2 >> 8);
+ bytes[index++] = (byte)(C2 >> 16);
+ bytes[index++] = (byte)(C2 >> 24);
+
+ bytes[index++] = (byte)C3;
+ bytes[index++] = (byte)(C3 >> 8);
+ bytes[index++] = (byte)(C3 >> 16);
+ bytes[index++] = (byte)(C3 >> 24);
+ }
+
+
+ private final void encryptBlock(int[][] KW)
+ {
+ int r, r0, r1, r2, r3;
+
+ C0 ^= KW[0][0];
+ C1 ^= KW[0][1];
+ C2 ^= KW[0][2];
+ C3 ^= KW[0][3];
+
+ for (r = 1; r < ROUNDS - 1;) {
+ r0 = T0[C0&255] ^ shift(T0[(C1>>8)&255], 24) ^ shift(T0[(C2>>16)&255],16) ^ shift(T0[(C3>>24)&255],8) ^ KW[r][0];
+ r1 = T0[C1&255] ^ shift(T0[(C2>>8)&255], 24) ^ shift(T0[(C3>>16)&255], 16) ^ shift(T0[(C0>>24)&255], 8) ^ KW[r][1];
+ r2 = T0[C2&255] ^ shift(T0[(C3>>8)&255], 24) ^ shift(T0[(C0>>16)&255], 16) ^ shift(T0[(C1>>24)&255], 8) ^ KW[r][2];
+ r3 = T0[C3&255] ^ shift(T0[(C0>>8)&255], 24) ^ shift(T0[(C1>>16)&255], 16) ^ shift(T0[(C2>>24)&255], 8) ^ KW[r++][3];
+ C0 = T0[r0&255] ^ shift(T0[(r1>>8)&255], 24) ^ shift(T0[(r2>>16)&255], 16) ^ shift(T0[(r3>>24)&255], 8) ^ KW[r][0];
+ C1 = T0[r1&255] ^ shift(T0[(r2>>8)&255], 24) ^ shift(T0[(r3>>16)&255], 16) ^ shift(T0[(r0>>24)&255], 8) ^ KW[r][1];
+ C2 = T0[r2&255] ^ shift(T0[(r3>>8)&255], 24) ^ shift(T0[(r0>>16)&255], 16) ^ shift(T0[(r1>>24)&255], 8) ^ KW[r][2];
+ C3 = T0[r3&255] ^ shift(T0[(r0>>8)&255], 24) ^ shift(T0[(r1>>16)&255], 16) ^ shift(T0[(r2>>24)&255], 8) ^ KW[r++][3];
+ }
+
+ r0 = T0[C0&255] ^ shift(T0[(C1>>8)&255], 24) ^ shift(T0[(C2>>16)&255], 16) ^ shift(T0[(C3>>24)&255], 8) ^ KW[r][0];
+ r1 = T0[C1&255] ^ shift(T0[(C2>>8)&255], 24) ^ shift(T0[(C3>>16)&255], 16) ^ shift(T0[(C0>>24)&255], 8) ^ KW[r][1];
+ r2 = T0[C2&255] ^ shift(T0[(C3>>8)&255], 24) ^ shift(T0[(C0>>16)&255], 16) ^ shift(T0[(C1>>24)&255], 8) ^ KW[r][2];
+ r3 = T0[C3&255] ^ shift(T0[(C0>>8)&255], 24) ^ shift(T0[(C1>>16)&255], 16) ^ shift(T0[(C2>>24)&255], 8) ^ KW[r++][3];
+
+ // the final round's table is a simple function of S so we don't use a whole other four tables for it
+
+ C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24) ^ KW[r][0];
+ C1 = (S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24) ^ KW[r][1];
+ C2 = (S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2];
+ C3 = (S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3];
+
+ }
+
+ private final void decryptBlock(int[][] KW)
+ {
+ int r, r0, r1, r2, r3;
+
+ C0 ^= KW[ROUNDS][0];
+ C1 ^= KW[ROUNDS][1];
+ C2 ^= KW[ROUNDS][2];
+ C3 ^= KW[ROUNDS][3];
+
+ for (r = ROUNDS-1; r>1;) {
+ r0 = Tinv0[C0&255] ^ shift(Tinv0[(C3>>8)&255], 24) ^ shift(Tinv0[(C2>>16)&255], 16) ^ shift(Tinv0[(C1>>24)&255], 8) ^ KW[r][0];
+ r1 = Tinv0[C1&255] ^ shift(Tinv0[(C0>>8)&255], 24) ^ shift(Tinv0[(C3>>16)&255], 16) ^ shift(Tinv0[(C2>>24)&255], 8) ^ KW[r][1];
+ r2 = Tinv0[C2&255] ^ shift(Tinv0[(C1>>8)&255], 24) ^ shift(Tinv0[(C0>>16)&255], 16) ^ shift(Tinv0[(C3>>24)&255], 8) ^ KW[r][2];
+ r3 = Tinv0[C3&255] ^ shift(Tinv0[(C2>>8)&255], 24) ^ shift(Tinv0[(C1>>16)&255], 16) ^ shift(Tinv0[(C0>>24)&255], 8) ^ KW[r--][3];
+ C0 = Tinv0[r0&255] ^ shift(Tinv0[(r3>>8)&255], 24) ^ shift(Tinv0[(r2>>16)&255], 16) ^ shift(Tinv0[(r1>>24)&255], 8) ^ KW[r][0];
+ C1 = Tinv0[r1&255] ^ shift(Tinv0[(r0>>8)&255], 24) ^ shift(Tinv0[(r3>>16)&255], 16) ^ shift(Tinv0[(r2>>24)&255], 8) ^ KW[r][1];
+ C2 = Tinv0[r2&255] ^ shift(Tinv0[(r1>>8)&255], 24) ^ shift(Tinv0[(r0>>16)&255], 16) ^ shift(Tinv0[(r3>>24)&255], 8) ^ KW[r][2];
+ C3 = Tinv0[r3&255] ^ shift(Tinv0[(r2>>8)&255], 24) ^ shift(Tinv0[(r1>>16)&255], 16) ^ shift(Tinv0[(r0>>24)&255], 8) ^ KW[r--][3];
+ }
+
+ r0 = Tinv0[C0&255] ^ shift(Tinv0[(C3>>8)&255], 24) ^ shift(Tinv0[(C2>>16)&255], 16) ^ shift(Tinv0[(C1>>24)&255], 8) ^ KW[r][0];
+ r1 = Tinv0[C1&255] ^ shift(Tinv0[(C0>>8)&255], 24) ^ shift(Tinv0[(C3>>16)&255], 16) ^ shift(Tinv0[(C2>>24)&255], 8) ^ KW[r][1];
+ r2 = Tinv0[C2&255] ^ shift(Tinv0[(C1>>8)&255], 24) ^ shift(Tinv0[(C0>>16)&255], 16) ^ shift(Tinv0[(C3>>24)&255], 8) ^ KW[r][2];
+ r3 = Tinv0[C3&255] ^ shift(Tinv0[(C2>>8)&255], 24) ^ shift(Tinv0[(C1>>16)&255], 16) ^ shift(Tinv0[(C0>>24)&255], 8) ^ KW[r--][3];
+
+ // the final round's table is a simple function of Si so we don't use a whole other four tables for it
+
+ C0 = (Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0];
+ C1 = (Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24) ^ KW[0][1];
+ C2 = (Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24) ^ KW[0][2];
+ C3 = (Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24) ^ KW[0][3];
+ }
+}
diff --git a/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java b/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java
new file mode 100644
index 0000000..59541b3
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java
@@ -0,0 +1,511 @@
+package org.bouncycastle.crypto.engines;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * a class that provides a basic DES engine.
+ */
+public class DESEngine
+ implements BlockCipher
+{
+ protected static final int BLOCK_SIZE = 8;
+
+ private int[] workingKey = null;
+
+ /**
+ * standard constructor.
+ */
+ public DESEngine()
+ {
+ }
+
+ /**
+ * initialise a DES cipher.
+ *
+ * @param encrypting whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ workingKey = generateWorkingKey(encrypting,
+ ((KeyParameter)params).getKey());
+
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to DES init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "DES";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (workingKey == null)
+ {
+ throw new IllegalStateException("DES engine not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ desFunc(workingKey, in, inOff, out, outOff);
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * what follows is mainly taken from "Applied Cryptography", by
+ * Bruce Schneier, however it also bears great resemblance to Richard
+ * Outerbridge's D3DES...
+ */
+
+ static short[] Df_Key =
+ {
+ 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
+ 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
+ 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67
+ };
+
+ static short[] bytebit =
+ {
+ 0200, 0100, 040, 020, 010, 04, 02, 01
+ };
+
+ static int[] bigbyte =
+ {
+ 0x800000, 0x400000, 0x200000, 0x100000,
+ 0x80000, 0x40000, 0x20000, 0x10000,
+ 0x8000, 0x4000, 0x2000, 0x1000,
+ 0x800, 0x400, 0x200, 0x100,
+ 0x80, 0x40, 0x20, 0x10,
+ 0x8, 0x4, 0x2, 0x1
+ };
+
+ /*
+ * Use the key schedule specified in the Standard (ANSI X3.92-1981).
+ */
+
+ static byte[] pc1 =
+ {
+ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
+ 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
+ 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
+ 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
+ };
+
+ static byte[] totrot =
+ {
+ 1, 2, 4, 6, 8, 10, 12, 14,
+ 15, 17, 19, 21, 23, 25, 27, 28
+ };
+
+ static byte[] pc2 =
+ {
+ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
+ 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
+ 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
+ 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
+ };
+
+ static int[] SP1 = {
+ 0x01010400, 0x00000000, 0x00010000, 0x01010404,
+ 0x01010004, 0x00010404, 0x00000004, 0x00010000,
+ 0x00000400, 0x01010400, 0x01010404, 0x00000400,
+ 0x01000404, 0x01010004, 0x01000000, 0x00000004,
+ 0x00000404, 0x01000400, 0x01000400, 0x00010400,
+ 0x00010400, 0x01010000, 0x01010000, 0x01000404,
+ 0x00010004, 0x01000004, 0x01000004, 0x00010004,
+ 0x00000000, 0x00000404, 0x00010404, 0x01000000,
+ 0x00010000, 0x01010404, 0x00000004, 0x01010000,
+ 0x01010400, 0x01000000, 0x01000000, 0x00000400,
+ 0x01010004, 0x00010000, 0x00010400, 0x01000004,
+ 0x00000400, 0x00000004, 0x01000404, 0x00010404,
+ 0x01010404, 0x00010004, 0x01010000, 0x01000404,
+ 0x01000004, 0x00000404, 0x00010404, 0x01010400,
+ 0x00000404, 0x01000400, 0x01000400, 0x00000000,
+ 0x00010004, 0x00010400, 0x00000000, 0x01010004
+ };
+
+ static int[] SP2 = {
+ 0x80108020, 0x80008000, 0x00008000, 0x00108020,
+ 0x00100000, 0x00000020, 0x80100020, 0x80008020,
+ 0x80000020, 0x80108020, 0x80108000, 0x80000000,
+ 0x80008000, 0x00100000, 0x00000020, 0x80100020,
+ 0x00108000, 0x00100020, 0x80008020, 0x00000000,
+ 0x80000000, 0x00008000, 0x00108020, 0x80100000,
+ 0x00100020, 0x80000020, 0x00000000, 0x00108000,
+ 0x00008020, 0x80108000, 0x80100000, 0x00008020,
+ 0x00000000, 0x00108020, 0x80100020, 0x00100000,
+ 0x80008020, 0x80100000, 0x80108000, 0x00008000,
+ 0x80100000, 0x80008000, 0x00000020, 0x80108020,
+ 0x00108020, 0x00000020, 0x00008000, 0x80000000,
+ 0x00008020, 0x80108000, 0x00100000, 0x80000020,
+ 0x00100020, 0x80008020, 0x80000020, 0x00100020,
+ 0x00108000, 0x00000000, 0x80008000, 0x00008020,
+ 0x80000000, 0x80100020, 0x80108020, 0x00108000
+ };
+
+ static int[] SP3 = {
+ 0x00000208, 0x08020200, 0x00000000, 0x08020008,
+ 0x08000200, 0x00000000, 0x00020208, 0x08000200,
+ 0x00020008, 0x08000008, 0x08000008, 0x00020000,
+ 0x08020208, 0x00020008, 0x08020000, 0x00000208,
+ 0x08000000, 0x00000008, 0x08020200, 0x00000200,
+ 0x00020200, 0x08020000, 0x08020008, 0x00020208,
+ 0x08000208, 0x00020200, 0x00020000, 0x08000208,
+ 0x00000008, 0x08020208, 0x00000200, 0x08000000,
+ 0x08020200, 0x08000000, 0x00020008, 0x00000208,
+ 0x00020000, 0x08020200, 0x08000200, 0x00000000,
+ 0x00000200, 0x00020008, 0x08020208, 0x08000200,
+ 0x08000008, 0x00000200, 0x00000000, 0x08020008,
+ 0x08000208, 0x00020000, 0x08000000, 0x08020208,
+ 0x00000008, 0x00020208, 0x00020200, 0x08000008,
+ 0x08020000, 0x08000208, 0x00000208, 0x08020000,
+ 0x00020208, 0x00000008, 0x08020008, 0x00020200
+ };
+
+ static int[] SP4 = {
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802080, 0x00800081, 0x00800001, 0x00002001,
+ 0x00000000, 0x00802000, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00800080, 0x00800001,
+ 0x00000001, 0x00002000, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002001, 0x00002080,
+ 0x00800081, 0x00000001, 0x00002080, 0x00800080,
+ 0x00002000, 0x00802080, 0x00802081, 0x00000081,
+ 0x00800080, 0x00800001, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00000000, 0x00802000,
+ 0x00002080, 0x00800080, 0x00800081, 0x00000001,
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802081, 0x00000081, 0x00000001, 0x00002000,
+ 0x00800001, 0x00002001, 0x00802080, 0x00800081,
+ 0x00002001, 0x00002080, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002000, 0x00802080
+ };
+
+ static int[] SP5 = {
+ 0x00000100, 0x02080100, 0x02080000, 0x42000100,
+ 0x00080000, 0x00000100, 0x40000000, 0x02080000,
+ 0x40080100, 0x00080000, 0x02000100, 0x40080100,
+ 0x42000100, 0x42080000, 0x00080100, 0x40000000,
+ 0x02000000, 0x40080000, 0x40080000, 0x00000000,
+ 0x40000100, 0x42080100, 0x42080100, 0x02000100,
+ 0x42080000, 0x40000100, 0x00000000, 0x42000000,
+ 0x02080100, 0x02000000, 0x42000000, 0x00080100,
+ 0x00080000, 0x42000100, 0x00000100, 0x02000000,
+ 0x40000000, 0x02080000, 0x42000100, 0x40080100,
+ 0x02000100, 0x40000000, 0x42080000, 0x02080100,
+ 0x40080100, 0x00000100, 0x02000000, 0x42080000,
+ 0x42080100, 0x00080100, 0x42000000, 0x42080100,
+ 0x02080000, 0x00000000, 0x40080000, 0x42000000,
+ 0x00080100, 0x02000100, 0x40000100, 0x00080000,
+ 0x00000000, 0x40080000, 0x02080100, 0x40000100
+ };
+
+ static int[] SP6 = {
+ 0x20000010, 0x20400000, 0x00004000, 0x20404010,
+ 0x20400000, 0x00000010, 0x20404010, 0x00400000,
+ 0x20004000, 0x00404010, 0x00400000, 0x20000010,
+ 0x00400010, 0x20004000, 0x20000000, 0x00004010,
+ 0x00000000, 0x00400010, 0x20004010, 0x00004000,
+ 0x00404000, 0x20004010, 0x00000010, 0x20400010,
+ 0x20400010, 0x00000000, 0x00404010, 0x20404000,
+ 0x00004010, 0x00404000, 0x20404000, 0x20000000,
+ 0x20004000, 0x00000010, 0x20400010, 0x00404000,
+ 0x20404010, 0x00400000, 0x00004010, 0x20000010,
+ 0x00400000, 0x20004000, 0x20000000, 0x00004010,
+ 0x20000010, 0x20404010, 0x00404000, 0x20400000,
+ 0x00404010, 0x20404000, 0x00000000, 0x20400010,
+ 0x00000010, 0x00004000, 0x20400000, 0x00404010,
+ 0x00004000, 0x00400010, 0x20004010, 0x00000000,
+ 0x20404000, 0x20000000, 0x00400010, 0x20004010
+ };
+
+ static int[] SP7 = {
+ 0x00200000, 0x04200002, 0x04000802, 0x00000000,
+ 0x00000800, 0x04000802, 0x00200802, 0x04200800,
+ 0x04200802, 0x00200000, 0x00000000, 0x04000002,
+ 0x00000002, 0x04000000, 0x04200002, 0x00000802,
+ 0x04000800, 0x00200802, 0x00200002, 0x04000800,
+ 0x04000002, 0x04200000, 0x04200800, 0x00200002,
+ 0x04200000, 0x00000800, 0x00000802, 0x04200802,
+ 0x00200800, 0x00000002, 0x04000000, 0x00200800,
+ 0x04000000, 0x00200800, 0x00200000, 0x04000802,
+ 0x04000802, 0x04200002, 0x04200002, 0x00000002,
+ 0x00200002, 0x04000000, 0x04000800, 0x00200000,
+ 0x04200800, 0x00000802, 0x00200802, 0x04200800,
+ 0x00000802, 0x04000002, 0x04200802, 0x04200000,
+ 0x00200800, 0x00000000, 0x00000002, 0x04200802,
+ 0x00000000, 0x00200802, 0x04200000, 0x00000800,
+ 0x04000002, 0x04000800, 0x00000800, 0x00200002
+ };
+
+ static int[] SP8 = {
+ 0x10001040, 0x00001000, 0x00040000, 0x10041040,
+ 0x10000000, 0x10001040, 0x00000040, 0x10000000,
+ 0x00040040, 0x10040000, 0x10041040, 0x00041000,
+ 0x10041000, 0x00041040, 0x00001000, 0x00000040,
+ 0x10040000, 0x10000040, 0x10001000, 0x00001040,
+ 0x00041000, 0x00040040, 0x10040040, 0x10041000,
+ 0x00001040, 0x00000000, 0x00000000, 0x10040040,
+ 0x10000040, 0x10001000, 0x00041040, 0x00040000,
+ 0x00041040, 0x00040000, 0x10041000, 0x00001000,
+ 0x00000040, 0x10040040, 0x00001000, 0x00041040,
+ 0x10001000, 0x00000040, 0x10000040, 0x10040000,
+ 0x10040040, 0x10000000, 0x00040000, 0x10001040,
+ 0x00000000, 0x10041040, 0x00040040, 0x10000040,
+ 0x10040000, 0x10001000, 0x10001040, 0x00000000,
+ 0x10041040, 0x00041000, 0x00041000, 0x00001040,
+ 0x00001040, 0x00040040, 0x10000000, 0x10041000
+ };
+
+ /**
+ * generate an integer based working key based on our secret key
+ * and what we processing we are planning to do.
+ *
+ * Acknowledgements for this routine go to James Gillogly & Phil Karn.
+ * (whoever, and wherever they are!).
+ */
+ protected int[] generateWorkingKey(
+ boolean encrypting,
+ byte[] key)
+ {
+ int[] newKey = new int[32];
+ boolean[] pc1m = new boolean[56],
+ pcr = new boolean[56];
+
+ for (int j = 0; j < 56; j++ )
+ {
+ int l = pc1[j];
+
+ pc1m[j] = ((key[l >>> 3] & bytebit[l & 07]) != 0);
+ }
+
+ for (int i = 0; i < 16; i++)
+ {
+ int l, m, n;
+
+ if (encrypting)
+ {
+ m = i << 1;
+ }
+ else
+ {
+ m = (15 - i) << 1;
+ }
+
+ n = m + 1;
+ newKey[m] = newKey[n] = 0;
+
+ for (int j = 0; j < 28; j++)
+ {
+ l = j + totrot[i];
+ if ( l < 28 )
+ {
+ pcr[j] = pc1m[l];
+ }
+ else
+ {
+ pcr[j] = pc1m[l - 28];
+ }
+ }
+
+ for (int j = 28; j < 56; j++)
+ {
+ l = j + totrot[i];
+ if (l < 56 )
+ {
+ pcr[j] = pc1m[l];
+ }
+ else
+ {
+ pcr[j] = pc1m[l - 28];
+ }
+ }
+
+ for (int j = 0; j < 24; j++)
+ {
+ if (pcr[pc2[j]])
+ {
+ newKey[m] |= bigbyte[j];
+ }
+
+ if (pcr[pc2[j + 24]])
+ {
+ newKey[n] |= bigbyte[j];
+ }
+ }
+ }
+
+ //
+ // store the processed key
+ //
+ for (int i = 0; i != 32; i += 2)
+ {
+ int i1, i2;
+
+ i1 = newKey[i];
+ i2 = newKey[i + 1];
+
+ newKey[i] = ((i1 & 0x00fc0000) << 6) | ((i1 & 0x00000fc0) << 10)
+ | ((i2 & 0x00fc0000) >>> 10) | ((i2 & 0x00000fc0) >>> 6);
+
+ newKey[i + 1] = ((i1 & 0x0003f000) << 12) | ((i1 & 0x0000003f) << 16)
+ | ((i2 & 0x0003f000) >>> 4) | (i2 & 0x0000003f);
+ }
+
+ return newKey;
+ }
+
+ /**
+ * the DES engine.
+ */
+ protected void desFunc(
+ int[] wKey,
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int work, right, left;
+
+ left = (in[inOff + 0] & 0xff) << 24;
+ left |= (in[inOff + 1] & 0xff) << 16;
+ left |= (in[inOff + 2] & 0xff) << 8;
+ left |= (in[inOff + 3] & 0xff);
+
+ right = (in[inOff + 4] & 0xff) << 24;
+ right |= (in[inOff + 5] & 0xff) << 16;
+ right |= (in[inOff + 6] & 0xff) << 8;
+ right |= (in[inOff + 7] & 0xff);
+
+ work = ((left >>> 4) ^ right) & 0x0f0f0f0f;
+ right ^= work;
+ left ^= (work << 4);
+ work = ((left >>> 16) ^ right) & 0x0000ffff;
+ right ^= work;
+ left ^= (work << 16);
+ work = ((right >>> 2) ^ left) & 0x33333333;
+ left ^= work;
+ right ^= (work << 2);
+ work = ((right >>> 8) ^ left) & 0x00ff00ff;
+ left ^= work;
+ right ^= (work << 8);
+ right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff;
+ work = (left ^ right) & 0xaaaaaaaa;
+ left ^= work;
+ right ^= work;
+ left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff;
+
+ for (int round = 0; round < 8; round++)
+ {
+ int fval;
+
+ work = (right << 28) | (right >>> 4);
+ work ^= wKey[round * 4 + 0];
+ fval = SP7[ work & 0x3f];
+ fval |= SP5[(work >>> 8) & 0x3f];
+ fval |= SP3[(work >>> 16) & 0x3f];
+ fval |= SP1[(work >>> 24) & 0x3f];
+ work = right ^ wKey[round * 4 + 1];
+ fval |= SP8[ work & 0x3f];
+ fval |= SP6[(work >>> 8) & 0x3f];
+ fval |= SP4[(work >>> 16) & 0x3f];
+ fval |= SP2[(work >>> 24) & 0x3f];
+ left ^= fval;
+ work = (left << 28) | (left >>> 4);
+ work ^= wKey[round * 4 + 2];
+ fval = SP7[ work & 0x3f];
+ fval |= SP5[(work >>> 8) & 0x3f];
+ fval |= SP3[(work >>> 16) & 0x3f];
+ fval |= SP1[(work >>> 24) & 0x3f];
+ work = left ^ wKey[round * 4 + 3];
+ fval |= SP8[ work & 0x3f];
+ fval |= SP6[(work >>> 8) & 0x3f];
+ fval |= SP4[(work >>> 16) & 0x3f];
+ fval |= SP2[(work >>> 24) & 0x3f];
+ right ^= fval;
+ }
+
+ right = (right << 31) | (right >>> 1);
+ work = (left ^ right) & 0xaaaaaaaa;
+ left ^= work;
+ right ^= work;
+ left = (left << 31) | (left >>> 1);
+ work = ((left >>> 8) ^ right) & 0x00ff00ff;
+ right ^= work;
+ left ^= (work << 8);
+ work = ((left >>> 2) ^ right) & 0x33333333;
+ right ^= work;
+ left ^= (work << 2);
+ work = ((right >>> 16) ^ left) & 0x0000ffff;
+ left ^= work;
+ right ^= (work << 16);
+ work = ((right >>> 4) ^ left) & 0x0f0f0f0f;
+ left ^= work;
+ right ^= (work << 4);
+
+ out[outOff + 0] = (byte)((right >>> 24) & 0xff);
+ out[outOff + 1] = (byte)((right >>> 16) & 0xff);
+ out[outOff + 2] = (byte)((right >>> 8) & 0xff);
+ out[outOff + 3] = (byte)( right & 0xff);
+ out[outOff + 4] = (byte)((left >>> 24) & 0xff);
+ out[outOff + 5] = (byte)((left >>> 16) & 0xff);
+ out[outOff + 6] = (byte)((left >>> 8) & 0xff);
+ out[outOff + 7] = (byte)( left & 0xff);
+ }
+}
diff --git a/src/main/java/org/bouncycastle/crypto/generators/DESKeyGenerator.java b/src/main/java/org/bouncycastle/crypto/generators/DESKeyGenerator.java
new file mode 100644
index 0000000..f8129c5
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/generators/DESKeyGenerator.java
@@ -0,0 +1,45 @@
+package org.bouncycastle.crypto.generators;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import org.bouncycastle.crypto.CipherKeyGenerator;
+import org.bouncycastle.crypto.params.DESParameters;
+
+public class DESKeyGenerator
+ extends CipherKeyGenerator
+{
+ public byte[] generateKey()
+ {
+ byte[] newKey = new byte[DESParameters.DES_KEY_LENGTH];
+
+ do
+ {
+ random.nextBytes(newKey);
+
+ DESParameters.setOddParity(newKey);
+ }
+ while (DESParameters.isWeakKey(newKey, 0));
+
+ return newKey;
+ }
+}
diff --git a/src/main/java/org/bouncycastle/crypto/params/DESParameters.java b/src/main/java/org/bouncycastle/crypto/params/DESParameters.java
new file mode 100644
index 0000000..f19dfec
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/params/DESParameters.java
@@ -0,0 +1,129 @@
+package org.bouncycastle.crypto.params;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+public class DESParameters
+ extends KeyParameter
+{
+ public DESParameters(
+ byte[] key)
+ {
+ super(key);
+
+ if (isWeakKey(key, 0))
+ {
+ throw new IllegalArgumentException("attempt to create weak DES key");
+ }
+ }
+
+ /*
+ * DES Key length in bytes.
+ */
+ static public final int DES_KEY_LENGTH = 8;
+
+ /*
+ * Table of weak and semi-weak keys taken from Schneier pp281
+ */
+ static private final int N_DES_WEAK_KEYS = 16;
+
+ static private byte[] DES_weak_keys =
+ {
+ /* weak keys */
+ (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01,
+ (byte)0x1f,(byte)0x1f,(byte)0x1f,(byte)0x1f, (byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0x0e,
+ (byte)0xe0,(byte)0xe0,(byte)0xe0,(byte)0xe0, (byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xf1,
+ (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe, (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe,
+
+ /* semi-weak keys */
+ (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe, (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe,
+ (byte)0x1f,(byte)0xe0,(byte)0x1f,(byte)0xe0, (byte)0x0e,(byte)0xf1,(byte)0x0e,(byte)0xf1,
+ (byte)0x01,(byte)0xe0,(byte)0x01,(byte)0xe0, (byte)0x01,(byte)0xf1,(byte)0x01,(byte)0xf1,
+ (byte)0x1f,(byte)0xfe,(byte)0x1f,(byte)0xfe, (byte)0x0e,(byte)0xfe,(byte)0x0e,(byte)0xfe,
+ (byte)0x01,(byte)0x1f,(byte)0x01,(byte)0x1f, (byte)0x01,(byte)0x0e,(byte)0x01,(byte)0x0e,
+ (byte)0xe0,(byte)0xfe,(byte)0xe0,(byte)0xfe, (byte)0xf1,(byte)0xfe,(byte)0xf1,(byte)0xfe,
+ (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01, (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01,
+ (byte)0xe0,(byte)0x1f,(byte)0xe0,(byte)0x1f, (byte)0xf1,(byte)0x0e,(byte)0xf1,(byte)0x0e,
+ (byte)0xe0,(byte)0x01,(byte)0xe0,(byte)0x01, (byte)0xf1,(byte)0x01,(byte)0xf1,(byte)0x01,
+ (byte)0xfe,(byte)0x1f,(byte)0xfe,(byte)0x1f, (byte)0xfe,(byte)0x0e,(byte)0xfe,(byte)0x0e,
+ (byte)0x1f,(byte)0x01,(byte)0x1f,(byte)0x01, (byte)0x0e,(byte)0x01,(byte)0x0e,(byte)0x01,
+ (byte)0xfe,(byte)0xe0,(byte)0xfe,(byte)0xe0, (byte)0xfe,(byte)0xf1,(byte)0xfe,(byte)0xf1
+ };
+
+ /**
+ * DES has 16 weak keys. This method will check
+ * if the given DES key material is weak or semi-weak.
+ * Key material that is too short is regarded as weak.
+ *
+ * See "Applied
+ * Cryptography" by Bruce Schneier for more information.
+ *
+ * @return true if the given DES key material is weak or semi-weak,
+ * false otherwise.
+ */
+ public static boolean isWeakKey(
+ byte[] key,
+ int offset)
+ {
+ if (key.length - offset < DES_KEY_LENGTH)
+ {
+ throw new IllegalArgumentException("key material too short.");
+ }
+
+ nextkey: for (int i = 0; i < N_DES_WEAK_KEYS; i++)
+ {
+ for (int j = 0; j < DES_KEY_LENGTH; j++)
+ {
+ if (key[j + offset] != DES_weak_keys[i * DES_KEY_LENGTH + j])
+ {
+ continue nextkey;
+ }
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * DES Keys use the LSB as the odd parity bit. This can
+ * be used to check for corrupt keys.
+ *
+ * @param bytes the byte array to set the parity on.
+ */
+ public static void setOddParity(
+ byte[] bytes)
+ {
+ for (int i = 0; i < bytes.length; i++)
+ {
+ int b = bytes[i];
+ bytes[i] = (byte)((b & 0xfe) |
+ ((((b >> 1) ^
+ (b >> 2) ^
+ (b >> 3) ^
+ (b >> 4) ^
+ (b >> 5) ^
+ (b >> 6) ^
+ (b >> 7)) ^ 0x01) & 0x01));
+ }
+ }
+}
diff --git a/src/main/java/org/bouncycastle/crypto/params/KeyParameter.java b/src/main/java/org/bouncycastle/crypto/params/KeyParameter.java
new file mode 100644
index 0000000..5da2dff
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/params/KeyParameter.java
@@ -0,0 +1,52 @@
+package org.bouncycastle.crypto.params;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import org.bouncycastle.crypto.CipherParameters;
+
+public class KeyParameter
+ implements CipherParameters
+{
+ private byte[] key;
+
+ public KeyParameter(
+ byte[] key)
+ {
+ this(key, 0, key.length);
+ }
+
+ public KeyParameter(
+ byte[] key,
+ int keyOff,
+ int keyLen)
+ {
+ this.key = new byte[keyLen];
+
+ System.arraycopy(key, keyOff, this.key, 0, keyLen);
+ }
+
+ public byte[] getKey()
+ {
+ return key;
+ }
+}
diff --git a/src/main/java/org/sentrysoftware/example/Example.java b/src/main/java/org/sentrysoftware/example/Example.java
deleted file mode 100644
index 211d94a..0000000
--- a/src/main/java/org/sentrysoftware/example/Example.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.sentrysoftware.example;
-
-/*-
- * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
- * MY PROJECT
- * ჻჻჻჻჻჻
- * Copyright 2023 Sentry Software
- * ჻჻჻჻჻჻
- * 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.
- * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
- */
-
-/**
- * An Example class
- */
-public class Example {
-
- /**
- * The main function
- */
- public static void main() {
- System.out.println("Hello Open-source World!");
- }
-}
diff --git a/src/main/java/org/sentrysoftware/snmp/client/SnmpClient.java b/src/main/java/org/sentrysoftware/snmp/client/SnmpClient.java
new file mode 100644
index 0000000..7b404f2
--- /dev/null
+++ b/src/main/java/org/sentrysoftware/snmp/client/SnmpClient.java
@@ -0,0 +1,573 @@
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+package org.sentrysoftware.snmp.client;
+
+import uk.co.westhawk.snmp.pdu.BlockPdu;
+import uk.co.westhawk.snmp.stack.AsnObject;
+import uk.co.westhawk.snmp.stack.AsnObjectId;
+import uk.co.westhawk.snmp.stack.AsnOctets;
+import uk.co.westhawk.snmp.stack.PduException;
+import uk.co.westhawk.snmp.stack.SnmpConstants;
+import uk.co.westhawk.snmp.stack.SnmpContext;
+import uk.co.westhawk.snmp.stack.SnmpContextv2c;
+import uk.co.westhawk.snmp.stack.SnmpContextv3;
+import uk.co.westhawk.snmp.stack.SnmpContextv3Face;
+import uk.co.westhawk.snmp.stack.varbind;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class SnmpClient
+{
+ // Default SNMP port number
+ static public final int SNMP_PORT = 161;
+
+ // SNMP v1, v2c, v3
+ static public final int SNMP_V1 = 1;
+ static public final int SNMP_V2C = 2;
+ static public final int SNMP_V3 = 3;
+ static public final String SNMP_AUTH_MD5 = "MD5";
+ static public final String SNMP_AUTH_SHA = "SHA";
+ static public final String SNMP_PRIVACY_DES = "DES";
+ static public final String SNMP_PRIVACY_AES = "AES";
+ static public final String SNMP_NONE = "None";
+
+
+ private SnmpContext contextv1 = null;
+ private SnmpContextv2c contextv2c = null;
+ private SnmpContextv3 contextv3 = null;
+ private BlockPdu pdu;
+ private String host;
+ private int port;
+ private String community;
+ private int snmpVersion;
+ private String authUsername;
+ private String authType;
+ private String authPassword;
+ private String privacyType;
+ private String privacyPassword;
+ private int[] retryIntervals;
+ private String contextName;
+ private byte[] contextEngineID;
+ static public final String SOCKET_TYPE = "Standard";
+
+ /**
+ * Creates an SNMPClient instance, which connects to the specified SNMP agent with the specified credentials
+ * (depending on the version of SNMP)
+ * @param host The hostname/IP address of the SNMP agent we're querying
+ * @param port The port of the SNMP agent (should be 161)
+ * @param version The version of SNMP to use (1, 2 or 3)
+ * @param retryIntervals Timeout in milliseconds after which the elementary operations will be retried
+ * @param community (SNMP v1 and v2 only) The SNMP community
+ * @param authType (SNMP v3 only) The authentication method: "MD5", "SHA" or ""
+ * @param authUsername (SNMP v3 only) The username
+ * @param authPassword (SNMP v3 only) The password (in clear)
+ * @param privacyType (SNMP v3 only) The encryption type: "DES", "AES" or ""
+ * @param privacyPassword (SNMP v3 only) The encryption password
+ * @param contextName (SNMP v3 only) The context name
+ * @param contextID (SNMP v3 only) The context ID (??)
+ * @throws IllegalArgumentException when specified authType, privType are invalid
+ * @throws IllegalStateException when the specified properties lead to something that cannot work (i.e. privacy without authentication)
+ * @throws IOException when cannot initialize the SNMP context
+ */
+ public SnmpClient(String host, int port, int version, int[] retryIntervals,
+ String community,
+ String authType, String authUsername, String authPassword,
+ String privacyType, String privacyPassword,
+ String contextName, byte[] contextID) throws IOException {
+ // First, validate the inputs
+ validate(version, authType, privacyType);
+
+ // Sets the attributes of the class instance
+ this.host = host;
+ this.port = port;
+ this.snmpVersion = version;
+ this.retryIntervals = retryIntervals;
+ this.community = community;
+ this.authType = authType;
+ this.authUsername = authUsername;
+ this.authPassword = authPassword;
+ this.privacyType = privacyType;
+ this.privacyPassword = privacyPassword;
+ this.contextName = contextName;
+ this.contextEngineID = contextID;
+
+ // Properly create the SNMP context, based on these properties
+ initialize();
+ }
+
+
+ /**
+ * Validate the specified inputs. Throws an IllegalArgumentException if needed.
+ * @param version Specified version of the SNMP protocol
+ * @param authType Specified authType
+ * @param privacyType Specified privacyType
+ * @throws IllegalArgumentException when invalid inputs are specified
+ */
+ private void validate(int version, String authType, String privacyType) {
+
+ // In case of SNMP v3, check the authType and privType (if not empty)
+ if (version == SNMP_V3) {
+ if (authType != null) {
+ if (!authType.isEmpty()) {
+ if (!authType.equals(SNMP_AUTH_MD5) && !authType.equals(SNMP_AUTH_SHA)) {
+ throw new IllegalArgumentException("Invalid authentication method '" + authType + "' (must be either '" + SNMP_AUTH_MD5 + "' or '" + SNMP_AUTH_SHA + "' or empty)");
+ }
+ }
+ }
+
+ if (privacyType != null) {
+ if (!privacyType.isEmpty()) {
+ if (!privacyType.equals(SNMP_PRIVACY_DES) && !privacyType.equals(SNMP_PRIVACY_AES)) {
+ throw new IllegalArgumentException("Invalid privacy method '" + privacyType +"' (must be either '" + SNMP_PRIVACY_DES + "' or '" + SNMP_PRIVACY_AES + "' or empty)");
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Initialize the SNMPClient
+ *
+ * Creates the context to connect to the SNMP agent. Required before any actual operation is performed.
+ * @throws IOException when cannot create the SNMP context
+ * @throws IllegalStateException when there is an inconsistency in the properties that prevent us from moving forward
+ */
+ private void initialize() throws IOException {
+
+ // SNMP v2c
+ if (snmpVersion == SNMP_V2C) {
+ contextv2c = new SnmpContextv2c(host, port, null, SOCKET_TYPE);
+ contextv2c.setCommunity(community);
+ }
+
+ // SNMP v3
+ else if (snmpVersion == SNMP_V3) {
+ int authProtocolCode = 0;
+ int privacyProtocolCode = 0;
+ boolean authenticate = false;
+ boolean privacy = false;
+
+ // Some sanity check with the "context"
+ if (contextEngineID == null) { contextEngineID = new byte[0]; }
+ if (contextName == null) { contextName = ""; }
+
+ // Verify the username
+ if (authUsername == null) { authUsername = ""; }
+
+ // Verify and translate the authentication type
+ if (authType == null || authUsername == null || authPassword == null) {
+ authenticate = false;
+ authProtocolCode = 4;
+ authPassword = "";
+ }
+ else if (authType.isEmpty() || authUsername.isEmpty() || authPassword.isEmpty()) {
+ authenticate = false;
+ authProtocolCode = 4;
+ authPassword = "";
+ }
+ else if (authType.equals(SNMP_AUTH_MD5)) {
+ authenticate = true;
+ authProtocolCode = SnmpContextv3Face.MD5_PROTOCOL;
+ }
+ else if (authType.equals(SNMP_AUTH_SHA)) {
+ authenticate = true;
+ authProtocolCode = SnmpContextv3Face.SHA1_PROTOCOL;
+ }
+
+ // Verify the privacy thing
+ if (privacyType == null || privacyPassword == null) {
+ privacy = false;
+ }
+ else if (privacyType.isEmpty() || privacyPassword.isEmpty()) {
+ privacy = false;
+ }
+ else if (privacyType.equals(SNMP_PRIVACY_DES)) {
+ privacy = true;
+ privacyProtocolCode = SnmpContextv3Face.DES_ENCRYPT;
+ }
+ else if (privacyType.equals(SNMP_PRIVACY_AES)) {
+ privacy = true;
+ privacyProtocolCode = SnmpContextv3Face.AES_ENCRYPT;
+ }
+
+ // Privacy with no authentication is impossible
+ if (privacy && !authenticate) {
+ throw new IllegalStateException("Authentication is required for privacy to be enforced");
+ }
+
+ // Create the context
+ contextv3 = new SnmpContextv3(host, port, SOCKET_TYPE);
+ contextv3.setContextEngineId(contextEngineID);
+ contextv3.setContextName(contextName);
+ contextv3.setUserName(authUsername);
+ contextv3.setUseAuthentication(authenticate);
+ if (authenticate) {
+ contextv3.setUserAuthenticationPassword(authPassword);
+ contextv3.setAuthenticationProtocol(authProtocolCode);
+ contextv3.setUsePrivacy(privacy);
+ if (privacy) {
+ contextv3.setPrivacyProtocol(privacyProtocolCode);
+ contextv3.setUserPrivacyPassword(privacyPassword);
+ }
+ }
+ }
+
+ // SNMP v1 (default)
+ else {
+ contextv1 = new SnmpContext(host, port, SOCKET_TYPE);
+ contextv1.setCommunity(community);
+ }
+
+ // Small thing: set the prefix for hex values (default is "0x" but we're setting it to empty)
+ AsnOctets.setHexPrefix("");
+
+ // AsnObject.setDebug(15);
+
+ }
+
+ /**
+ * Releases the resources associated to this instance
+ * (or so at least we believe...)
+ */
+ public void freeResources() {
+ if (contextv1 != null) { contextv1.destroy(); contextv1 = null;}
+ if (contextv2c != null) { contextv2c.destroy(); contextv2c = null;}
+ if (contextv3 != null) { contextv3.destroy(); contextv3 = null;}
+
+ if (pdu != null) { pdu = null; }
+ }
+
+
+ /**
+ * Create the PDU and sets the timeout
+ *
Note: This method has been created just to avoid duplicate code in the get, getNext and walk functions
+ */
+ private void createPdu() {
+ // Create the PDU based on the proper context
+ if (snmpVersion == SNMP_V2C) { pdu = new BlockPdu(contextv2c); }
+ else if (snmpVersion == SNMP_V3) { pdu = new BlockPdu(contextv3); }
+ else { pdu = new BlockPdu(contextv1); }
+
+ // Set the timeout
+ if (retryIntervals != null) {
+ pdu.setRetryIntervals(retryIntervals);
+ }
+ }
+
+
+ /**
+ * Perform a GET operation on the specified OID
+ * @param oid OID on which to perform a GET operation
+ * @return Value of the specified OID
+ * @throws Exception in case of any problem
+ */
+ public String get(String oid) throws Exception {
+ createPdu();
+ pdu.setPduType(BlockPdu.GET);
+ pdu.addOid(oid);
+ return sendRequest().value;
+ }
+
+ /**
+ * Perform a GET operation on the specified OID and return the details of the result (including the type of the value)
+ * @param oid OID on which to perform a GET operation
+ * @return A string in the form of the OID, "string" and the value, separated by tabs (\t)
+ * @throws Exception in case of any problem
+ */
+ public String getWithDetails(String oid) throws Exception {
+ createPdu();
+ pdu.setPduType(BlockPdu.GET);
+ pdu.addOid(oid);
+ SnmpResult result = sendRequest();
+ return result.oid + "\t" + result.type + "\t" + result.value;
+ }
+
+ /**
+ * Perform a GETNEXT operation on the specified OID
+ * @param oid OID on which to perform a GETNEXT operation
+ * @return A string in the form of the OID, "string" and the value, separated by tabs (\t)
+ * @throws Exception in case of any problem
+ */
+ public String getNext(String oid) throws Exception {
+ createPdu();
+ pdu.setPduType(BlockPdu.GETNEXT);
+ pdu.addOid(oid);
+ SnmpResult result = sendRequest();
+ return result.oid + "\t" + result.type + "\t" + result.value;
+ }
+
+ /**
+ * Perform a WALK, i.e. a series of GETNEXT operations until we fall off the tree
+ * @param oid Root OID of the tree
+ * @return Result of the WALK operation, as a long String. Each pair of oid/value is separated with a linefeed (at least, for now!)
+ * @throws Exception
+ * @throws IllegalArgumentException for bad specified OIDs
+ */
+ public String walk(String oid) throws Exception {
+
+ StringBuilder walkResult = new StringBuilder();
+ String currentOID;
+ SnmpResult getNextResult;
+
+ // Sanity check?
+ if (oid == null) {
+ throw new IllegalArgumentException("Invalid SNMP Walk OID: null");
+ }
+ if (oid.length() < 3) {
+ throw new IllegalArgumentException("Invalid SNMP Walk OID: \"" + oid + "\"");
+ }
+
+ // Now, something special:
+ // In the walk loop below, we will catch any exception and break out of the loop
+ // if anything happens. At that point, we simply return what we have, i.e. just
+ // as if everything was okay. Doing so, we fail to report authentication problems.
+ // So, the code using this will think it's just okay, even though the QA team
+ // intentionally put bad credentials to verify the error message... See MATSYA-464.
+ //
+ // So, we're going to first run a getNext() for nothing, just so that
+ // this call will throw the proper exception in case of credentials problems.
+ getNext(oid);
+
+ currentOID = oid;
+ do {
+ createPdu();
+ pdu.setPduType(BlockPdu.GETNEXT);
+ pdu.addOid(currentOID);
+ try {
+ getNextResult = sendRequest();
+ }
+ catch (Exception e) {
+ // Something wrong? Get out of the loop and return what we have
+ break;
+ }
+
+ currentOID = getNextResult.oid;
+ if (!currentOID.startsWith(oid))
+ {
+ // We're off the tree, so get out of the loop
+ break;
+ }
+
+ // Append the result
+ walkResult.append(currentOID + "\t" + getNextResult.type + "\t" + getNextResult.value + "\n");
+
+ } while (walkResult.length() < 10 * 1048576); // 10 MB is the limit for the result of our WALK operation. Should be enough.
+
+ // Remove the trailing \n (if any)
+ int resultLength = walkResult.length();
+ if (resultLength > 0) {
+ return walkResult.substring(0, resultLength - 1);
+ }
+
+ // If nothing, return an empty string
+ return "";
+ }
+
+
+ /**
+ * Read the content of an SNMP table
+ * @param rootOID Root OID of the SNMP table
+ * @param selectColumnArray Array of numbers specifying the column numbers of the array to be read. Use "ID" for the row number.
+ * @return A semicolon-separated list of values
+ * @throws IllegalArgumentException when the specified arguments are wrong
+ * @throws Exception when the underlying SNMP API throws one
+ */
+ public List> table(String rootOID, String[] selectColumnArray) throws Exception {
+
+ // Sanity check
+ if (rootOID == null) {
+ throw new IllegalArgumentException("Invalid SNMP Table OID: null");
+ }
+ if (rootOID.length() < 3) {
+ throw new IllegalArgumentException("Invalid SNMP Table OID: \"" + rootOID + "\"");
+ }
+ if (selectColumnArray == null) {
+ throw new IllegalArgumentException("Invalid SNMP Table column numbers: null");
+ }
+ if (selectColumnArray.length < 1) {
+ throw new IllegalArgumentException("Invalid SNMP Table column numbers: none");
+ }
+
+ // First of all, retrieve the list of IDs in the table
+ // To do so, we need to see what is the first column number available (it may not be 1)
+ createPdu();
+ pdu.setPduType(BlockPdu.GETNEXT);
+ pdu.addOid(rootOID);
+ String firstValueOid = sendRequest().oid;
+ if (firstValueOid.isEmpty() || !firstValueOid.startsWith(rootOID)) {
+ // Empty table
+ return new ArrayList<>();
+ }
+
+ int tempIndex = firstValueOid.indexOf(".", rootOID.length() + 2);
+ if (tempIndex < 0) {
+ // Weird case, there is no "." after the rootOID in the OID of the first value we successfully got in the table
+ return new ArrayList<>();
+ }
+ String firstColumnOid = firstValueOid.substring(0, tempIndex);
+ int firstColumnOidLength = firstColumnOid.length();
+
+ // Now, find the list of row IDs in this column. We're going to do something like a walk, except we don't care about the values. Just the OIDs.
+ ArrayList IDArray = new ArrayList(0);
+ String currentOID = firstColumnOid;
+ SnmpResult getNextResult;
+ do {
+ // Get next until we get out of the tree
+ createPdu();
+ pdu.setPduType(BlockPdu.GETNEXT);
+ pdu.addOid(currentOID);
+ getNextResult = sendRequest();
+
+ currentOID = getNextResult.oid;
+
+ // Outside? Exit!
+ if (!currentOID.startsWith(firstColumnOid))
+ {
+ break;
+ }
+
+ // Add the right part of the OID in the list of IDs (the part to the right of the column OID)
+ IDArray.add(currentOID.substring(firstColumnOidLength + 1));
+
+ } while (IDArray.size() < 10000); // Not more than 10000 lines, please...
+
+ // And finally, build the result table
+ List> tableResult = new ArrayList<>();
+ for (String ID : IDArray) {
+ // For each row...
+ List row = new ArrayList<>();
+ for (String column : selectColumnArray) {
+ // For each column...
+
+ // If the column has to provide the ID of the row
+ if (column.equals("ID")) {
+ row.add(ID);
+ }
+ else {
+ // Keep going, even in case of a failure
+ try {
+ row.add(get(rootOID + "." + column + "." + ID));
+ }
+ catch (Exception e) {
+ row.add("");
+ }
+ }
+ }
+ tableResult.add(row);
+ }
+
+ // Return the result
+ return tableResult;
+ }
+
+
+ /**
+ * Sends the SNMP request and perform some minor interpretation of the result
+ * @return Result of the query in the form of a couple {oid;value} (SnmpResult)
+ * @throws PduException when an error happens at the SNMP layer
+ * @throws IOException when an error occurs at the network layer
+ * @throws Exception when we cannot get the value of the specified OID, because it does not exist
+ *
+ *
In case of no such OID, an exception is thrown.
+ * In case of empty value, the result will have the oid and an empty value.
+ */
+ private SnmpResult sendRequest() throws PduException, IOException, Exception {
+
+ // Declarations
+ SnmpResult result = new SnmpResult();
+
+ // Send the SNMP request
+ varbind var = pdu.getResponseVariableBinding();
+
+ // Retrieve the OID and value of the response (a varbind)
+ AsnObjectId oid = var.getOid();
+ AsnObject value = var.getValue();
+
+ // No such OID? Throw an exception (this needs to be caught gracefully by other functions)
+ byte valueType = value.getRespType();
+ if (valueType == SnmpConstants.SNMP_VAR_NOSUCHOBJECT ||
+ valueType == SnmpConstants.SNMP_VAR_NOSUCHINSTANCE ||
+ valueType == SnmpConstants.SNMP_VAR_ENDOFMIBVIEW) {
+ throw new Exception(value.getRespTypeString());
+ }
+
+ // Empty?
+ else if (valueType == SnmpConstants.ASN_NULL) {
+ result.oid = oid.toString();
+ result.type = "null";
+ }
+
+ // ASN_OCTET_STRING? (special case, because it may need to be displayed as an hexadecimal string)
+ // Normally, the API should take care of that, but this is not the case for 0x00:00:00:00 values, which are displayed as empty values
+ else if (valueType == SnmpConstants.ASN_OCTET_STR) {
+
+ result.oid = oid.toString();
+ result.type = "ASN_OCTET_STR";
+
+ // Map the value to the specific AsnOctets sub-class
+ AsnOctets octetStringValue = (AsnOctets)value;
+
+ // First, convert the value as a string, using toString().
+ // AsnOctets.toString() will convert the value to a normal string (with ASCII chars)
+ // or to the hexadecimal version of it, like 0x00:30:31:32 when the "normal" string is
+ // not printable
+ String octetStringValuetoString = octetStringValue.toString();
+
+ // Then forcibly convert the value to its hexadecimal representation, but replace ':' with blank spaces, to match with what PATROL does
+ String octetStringValuetoHex = octetStringValue.toHex().replace(':', ' ');
+
+ // So, if the toString() and the toHex() value have the same length, it means that toString() is actually returning
+ // the hexadecimal representation (yeah, there is no other way to retrieve that, the SNMP API does not tell us
+ // whether the value is printable or not)
+ // If the SNMP API judges that the value is not printable, then we will use the toHex() value, with ':' replaced with blank spaces.
+ // But there is another case: if the original value is just a series of 0x00 (nul) chars, the SNMP API converts that to an
+ // empty string, while we need to actually display 00 00 00 00...
+ // That's what we're doing in the code below
+
+ // If octetStringValuetoString is empty while the original value's length was greater than 0, then we'll need to convert it to hexadecimal
+ if (octetStringValuetoString.isEmpty() && octetStringValue.getBytes().length > 0) {
+ result.value = octetStringValuetoHex;
+ }
+ else if (octetStringValuetoString.length() == octetStringValuetoHex.length()) {
+ result.value = octetStringValuetoHex;
+ }
+ else {
+ result.value = octetStringValuetoString;
+ }
+ }
+
+ // Sets the result object
+ else {
+ result.oid = oid.toString();
+ result.type = value.getRespTypeString();
+ result.value = value.toString();
+ }
+
+ return result;
+
+ } // end of sendRequest
+
+
+}// end of class - SNMPClient
diff --git a/src/main/java/org/sentrysoftware/snmp/client/SnmpResult.java b/src/main/java/org/sentrysoftware/snmp/client/SnmpResult.java
new file mode 100644
index 0000000..be46745
--- /dev/null
+++ b/src/main/java/org/sentrysoftware/snmp/client/SnmpResult.java
@@ -0,0 +1,29 @@
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+package org.sentrysoftware.snmp.client;
+
+public class SnmpResult {
+ public String oid = "";
+ public String value = "";
+ public String type = "";
+}
\ No newline at end of file
diff --git a/src/main/java/uk/co/westhawk/snmp/beans/AnnexModemStatusBean.java b/src/main/java/uk/co/westhawk/snmp/beans/AnnexModemStatusBean.java
new file mode 100644
index 0000000..1958f90
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/beans/AnnexModemStatusBean.java
@@ -0,0 +1,815 @@
+// NAME
+// $RCSfile: AnnexModemStatusBean.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.22 $
+// CREATED
+// $Date: 2006/03/23 14:54:09 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ */
+
+package uk.co.westhawk.snmp.beans;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+
+import javax.swing.tree.*;
+import java.awt.*;
+import java.util.*;
+import java.text.*;
+import java.lang.*;
+import java.io.*;
+import java.beans.*;
+
+/**
+ *
+ * This bean is written for
+ *
+ * Remote Annex 2000
+ * access server.
+ *
+ *
+ *
+ * The server comes with the Xylogics specific MIBs, you can
+ * find them in the Annex software installation, I couldn't find them on
+ * the Web. I did not use them for this bean, however.
+ *
+ *
+ *
+ * This bean uses the
+ * CHARACTER-MIB
+ * and
+ * RS-232-MIB.
+ *
+ *
+ *
+ * This bean collects information about the modem status,
+ * connected to the server.
+ * It will only collect those modems (see charPortOperStatus) that are
+ * "up". It will then show if the modem is in use of not (see
+ * rs232InSigState).
+ *
+ *
+ *
+ * You can get the data via the getModemIndexes() and
+ * getPortStatus(Long index) methods. This way you can visualise
+ * the data yourself.
+ *
+ *
+ *
+ * You can also use the Swing JTree to visualise the modems.
+ * This bean implements the Swing TreeNode interface.
+ * The user has to set the setDefaultTreeModel, so this class can update all
+ * the nodes that are added, removed of changed.
+ * If this class is not the root of the JTree, you have to set
+ * the (TreeNode) parent of this class.
+ *
+ *
+ *
+ * The properties in the parent classes should be set, before calling
+ * the action() method. Via a TreeModelEvent the application/applet
+ * will be notified.
+ *
+ *
+ *
+ * We only have one Annex server, so I don't know how and if it
+ * works with more than 1. Please let us know if it doesn't work.
+ *
+ *
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setCommunityName
+ * @see SNMPRunBean#setUpdateInterval
+ * @see SNMPBean#addPropertyChangeListener
+ * @see SNMPBean#action
+ * @see GetNextPdu_vec
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.22 $ $Date: 2006/03/23 14:54:09 $
+ */
+public class AnnexModemStatusBean extends SNMPRunBean
+ implements Observer, TreeNode
+{
+ private static final String version_id =
+ "@(#)$Id: AnnexModemStatusBean.java,v 1.22 2006/03/23 14:54:09 birgit Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * A unique value for each character port. This perhaps
+ * corresponding to the same value of ifIndex when the
+ * character port is associated with a hardware port
+ * represented by an ifIndex.
+ *
+ * Syntax: INTEGER
+ *
+ * See the CHARACTER-MIB.
+ */
+ public final static String charPortIndex =
+ "1.3.6.1.2.1.19.2.1.1";
+ /**
+ * An administratively assigned name for the port, typically with
+ * some local significance.
+ *
+ * Syntax: DisplayString
+ *
+ * See CHARACTER-MIB.
+ */
+ public final static String charPortName =
+ "1.3.6.1.2.1.19.2.1.2";
+
+
+ /**
+ * The port's actual, operational state, independent
+ * of flow control.
+ *
+ * -
+ * 'up' indicates able to function normally.
+ * -
+ * 'down' indicates inability to function for administrative or
+ * operational reasons.
+ * -
+ * 'maintenance' indicates a maintenance mode, exclusive of normal
+ * operation, such as running a test.
+ * -
+ * 'absent' indicates that port hardware is not present.
+ * -
+ * 'active' indicates up with a user present (e.g. logged in).
+ *
+ *
+ *
+ * 'up' and 'active' correspond to ifOperStatus (rfc2863.mib) 'up'.
+ * 'down' and 'absent' correspond to ifOperStatus 'down'.
+ * 'maintenance' corresponds to ifOperStatus 'test'.
+ *
+ *
+ * Syntax: INTEGER
+ *
+ * See CHARACTER-MIB
+ * and IF-MIB-MIB.
+ */
+ public final static String charPortOperStatus =
+ "1.3.6.1.2.1.19.2.1.7";
+
+ /**
+ * The current signal state.
+ *
+ * Syntax: INTEGER
+ *
+ * See RS-232-MIB.
+ */
+ public final static String rs232InSigState =
+ "1.3.6.1.2.1.10.33.5.1.3";
+
+ private final static int NR_PORT_OID = 3;
+
+ /** charPortOperStatus up. */
+ public final static int portUP = 1;
+ /** charPortOperStatus down. */
+ public final static int portDOWN = 2;
+ /** charPortOperStatus maintenance. */
+ public final static int portMAINTENANCE = 3;
+ /** charPortOperStatus absent. */
+ public final static int portABSENT = 4;
+ /** charPortOperStatus active. */
+ public final static int portACTIVE = 5;
+
+ /**
+ * One of rs232InSigName values. If the dcd of rs232InSigState is
+ * on, that means that there is contact.
+ */
+ public final static int DCD = 6;
+
+ /** rs232InSigState none. */
+ public final static int sigNONE = 1;
+ /** rs232InSigState on. */
+ public final static int sigON = 2;
+ /** rs232InSigState off. */
+ public final static int sigOFF = 3;
+
+ public final static String [] sig_state =
+ {
+ "unknown",
+ "none",
+ "in use",
+ "not in use"
+ };
+
+ private GetNextPdu_vec pduGetNext;
+ private Hashtable modemIndexStatusHash;
+ private Hashtable modemHash;
+
+ private TreeNode parent;
+ private DefaultTreeModel treeModel;
+
+ private boolean isGetNextInFlight;
+ private Date lastUpdateDate = null;
+
+ private int deviceType = 0;
+ private int openCount = 0;
+ private int modemStatus = 0;
+
+/**
+ * The default constructor.
+ */
+public AnnexModemStatusBean()
+{
+ modemIndexStatusHash = new Hashtable();
+ modemHash = new Hashtable();
+}
+
+/**
+ * The constructor that will set the host and the port no.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ */
+public AnnexModemStatusBean(String h, int p)
+{
+ this(h, p, null);
+}
+
+/**
+ * The constructor that will set the host, the port no and the local
+ * bind address.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @param b the local bind address
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setBindAddress
+ *
+ * @since 4_14
+ */
+public AnnexModemStatusBean(String h, int p, String b)
+{
+ this();
+ setHost(h);
+ setPort(p);
+ setBindAddress(b);
+}
+
+/**
+ * Returns the date of the moment when this bean was last updated.
+ * This might be null when the first time the update was not finished.
+ *
+ * @return the last update date
+ */
+public Date getLastUpdateDate()
+{
+ return lastUpdateDate;
+}
+
+/**
+ * Returns the indexes (as Integers) of the voice modems that are
+ * open. Only the open voice modems of the card are saved.
+ *
+ * Use getPortStatus() or getPortStatusString() to get the status
+ * of the modem.
+ *
+ * @see #getPortStatus
+ * @see #getPortStatusString
+ */
+public Enumeration getModemIndexes()
+{
+ return modemIndexStatusHash.keys();
+}
+
+/**
+ * Returns the number of voice modems in the table.
+ */
+public synchronized int getModemCount()
+{
+ return modemIndexStatusHash.size();
+}
+
+/**
+ * Returns the name of the port.
+ *
+ * @param index The index of the port
+ * @return The name
+ *
+ */
+public String getPortName(Long index)
+{
+ String name = "";
+ Object obj = modemHash.get(index);
+ if (obj != null)
+ {
+ PortInfo pInfo = (PortInfo) obj;
+ name = pInfo.getName();
+ }
+ return name;
+}
+
+/**
+ * Returns the status of the modem as an int.
+ *
+ * @param index The index of the modem
+ * @return The status
+ *
+ * @see #getModemIndexes
+ */
+public int getPortStatus(Long index)
+{
+ int status = 0;
+ Object obj = modemIndexStatusHash.get(index);
+ if (obj != null)
+ {
+ status = ((Integer)obj).intValue();
+ }
+ return status;
+}
+
+/**
+ * Returns the String representation of the status of the modem.
+ *
+ * @param index The index of the modem
+ * @return The status
+ *
+ * @see #getModemIndexes
+ */
+public String getPortStatusString(Long index)
+{
+ int status = getPortStatus(index);
+ String str = sig_state[status];
+ return str;
+}
+
+/**
+ * Returns the children of the reciever as an Enumeration.
+ */
+public Enumeration children()
+{
+ return modemHash.elements();
+}
+
+/**
+ * Returns the number of children TreeNode
s the receiver
+ * contains.
+ */
+public int getChildCount()
+{
+ int sz = modemHash.size();
+ return sz;
+}
+
+/**
+ * Returns the child TreeNode
at index
+ * childIndex
.
+ */
+public TreeNode getChildAt(int childIndex)
+{
+ TreeNode node = null;
+ if (childIndex < modemHash.size())
+ {
+ Enumeration e = modemHash.elements();
+ for (int i=0; i<=childIndex; i++)
+ {
+ node = (TreeNode) e.nextElement();
+ }
+ }
+ return node;
+}
+
+/**
+ * Returns the index of node
in the receivers children.
+ * If the receiver does not contain node
, -1 will be
+ * returned.
+ */
+public int getIndex(TreeNode node)
+{
+ int ret = -1;
+ if (modemHash.contains(node))
+ {
+ boolean found = false;
+ Enumeration e = modemHash.elements();
+ while (e.hasMoreElements() && !found)
+ {
+ TreeNode n = (TreeNode) e.nextElement();
+ found = (n == node);
+ ret++;
+ }
+ }
+ return ret;
+}
+
+/**
+ * Returns the parent TreeNode
of the receiver.
+ */
+public TreeNode getParent()
+{
+ return parent;
+}
+
+/**
+ * Returns true if the receiver allows children.
+ */
+public boolean getAllowsChildren()
+{
+ return true;
+}
+
+/**
+ * Returns true if the receiver is a leaf.
+ */
+public boolean isLeaf()
+{
+ return false;
+}
+/**
+ * This method starts the action of the bean. It will initialises
+ * all variables before starting.
+ */
+public void action()
+{
+ if (isHostPortReachable())
+ {
+ lastUpdateDate = new Date();
+ isGetNextInFlight = false;
+ setRunning(true);
+ }
+}
+
+/**
+ * Implements the running of the bean.
+ *
+ * It will send the Pdu, if the previous one is not still in flight.
+ * @see SNMPRunBean#isRunning()
+ */
+public void run()
+{
+ while (context != null && isRunning())
+ {
+ if (isGetNextInFlight == false)
+ {
+ // start the GetNext loop again
+ isGetNextInFlight = true;
+
+ pduGetNext = new GetNextPdu_vec(context, NR_PORT_OID);
+ pduGetNext.addObserver(this);
+
+ pduGetNext.addOid(charPortIndex);
+ pduGetNext.addOid(charPortName);
+ pduGetNext.addOid(charPortOperStatus);
+ try
+ {
+ pduGetNext.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+
+ try
+ {
+ Thread.sleep(interval);
+ }
+ catch (InterruptedException ix)
+ {
+ ;
+ }
+ }
+}
+
+/**
+ * This method is called when the Pdu response is received. When all
+ * answers are received it will fire the property change event.
+ *
+ */
+public void update(Observable obs, Object ov)
+{
+ boolean loopHasEnded = false;
+
+ if (obs instanceof GetNextPdu_vec)
+ {
+ int portIndex, portStatus;
+ String portName;
+
+ varbind [] var;
+ pduGetNext = (GetNextPdu_vec) obs;
+
+ if (pduGetNext.isTimedOut() == false)
+ {
+ if (pduGetNext.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ var = (varbind []) ov;
+ if (var[0].getOid().toString().startsWith(charPortIndex))
+ {
+ portIndex = ((AsnInteger) var[0].getValue()).getValue();
+ portName = ((AsnOctets) var[1].getValue()).getValue();
+ portStatus = ((AsnInteger) var[2].getValue()).getValue();
+
+ Long indexInt = new Long(portIndex);
+ if (portStatus == portUP)
+ {
+ // I've found a port that has status up
+ // Store it for later use.
+
+ PortInfo pStatus =
+ (PortInfo) modemHash.get(indexInt);
+
+ if (pStatus == null)
+ {
+ pStatus = new PortInfo(portIndex, portName, this);
+ modemHash.put(indexInt, pStatus);
+ }
+
+ // Now I have to find out its sigState
+ String oid = rs232InSigState + "." + String.valueOf(portIndex)
+ + "." + String.valueOf(DCD);
+
+ try
+ {
+ GetPdu pduGet = new GetPdu(context);
+ pduGet.addOid(oid);
+ pduGet.addObserver(this);
+ pduGet.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+ else
+ {
+ // This port is not up, remove it from our info
+
+ modemIndexStatusHash.remove(indexInt);
+ modemHash.remove(indexInt);
+ }
+
+ // ask for the next modem
+ pduGetNext = new GetNextPdu_vec(context, NR_PORT_OID);
+ pduGetNext.addObserver(this);
+
+ pduGetNext.addOid(var[0].getOid().toString());
+ pduGetNext.addOid(var[1].getOid().toString());
+ pduGetNext.addOid(var[2].getOid().toString());
+ try
+ {
+ pduGetNext.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+ else
+ {
+ loopHasEnded = true;
+ }
+ }
+ else
+ {
+ // Actually the loop is ended when
+ // we have all the responses from pduGet's. Since I
+ // cannot control that, I do it this way.
+
+ loopHasEnded = true;
+ }
+ }
+ else
+ {
+ modemIndexStatusHash.clear();
+ modemHash.clear();
+ loopHasEnded = true;
+ }
+ }
+ else if (obs instanceof GetPdu)
+ {
+ GetPdu pduGet = (GetPdu) obs;
+ if (pduGet.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ varbind var = (varbind) ov;
+
+ AsnObjectId oid = var.getOid();
+ int sigStatus = ((AsnInteger) var.getValue()).getValue();
+
+ // the index is the one-but-last element in the OID
+ int len = oid.getSize();
+ long portIndex = oid.getElementAt(len-2);
+
+ Long indexInt = new Long(portIndex);
+ modemIndexStatusHash.put(indexInt,
+ new Integer(sigStatus));
+
+ PortInfo pStatus =
+ (PortInfo) modemHash.get(indexInt);
+
+ if (pStatus != null)
+ {
+ pStatus.setStatus(sigStatus);
+ }
+ }
+ }
+
+ if (loopHasEnded)
+ {
+ lastUpdateDate = new Date();
+ javax.swing.SwingUtilities.invokeLater(new TreeUpdate());
+ isGetNextInFlight = false;
+ }
+
+}
+
+/**
+ * Sets the parent for this TreeNode. If the parent is not set, this
+ * class should be the root of the TreeModel.
+ */
+public void setParent (TreeNode p)
+{
+ parent = p;
+}
+
+/**
+ * Sets the DefaultTreeModel for this TreeNode. The tree model is used
+ * for notifying when any of the nodes were added, removed or changed.
+ */
+public void setDefaultTreeModel (DefaultTreeModel model)
+{
+ treeModel = model;
+}
+
+/**
+ * Fire the property event.
+ *
+ * @see
+ * DefaultTreeModel#nodeStructureChanged
+ */
+protected void fireTreeModelChanged()
+{
+ if (treeModel != null)
+ {
+ treeModel.nodeStructureChanged(this);
+ }
+}
+
+class PortInfo extends Object implements TreeNode
+{
+ private TreeNode parent;
+ private int portIndex, sigStatus;
+ private String portName;
+
+public PortInfo(int ind, String nm, TreeNode par)
+{
+ this(ind, 0, nm, par);
+}
+
+public PortInfo(int ind, int st, String nm, TreeNode par)
+{
+ portIndex = ind;
+ sigStatus = st;
+ portName = nm;
+ parent = par;
+}
+
+public int getIndex()
+{
+ return portIndex;
+}
+
+public int getStatus()
+{
+ return sigStatus;
+}
+
+public void setStatus(int st)
+{
+ sigStatus = st;
+}
+
+public String getName()
+{
+ return portName;
+}
+
+public String toString()
+{
+ return ""+portIndex + " " + portName + " " + sig_state[sigStatus];
+}
+
+/**
+ * Returns the children of the reciever as an Enumeration.
+ */
+public Enumeration children()
+{
+ return null;
+}
+
+/**
+ * Returns the number of children TreeNode
s the receiver
+ * contains.
+ */
+public int getChildCount()
+{
+ return 0;
+}
+
+/**
+ * Returns the child TreeNode
at index
+ * childIndex
.
+ */
+public TreeNode getChildAt(int childIndex)
+{
+ return null;
+}
+
+/**
+ * Returns the index of node
in the receivers children.
+ * If the receiver does not contain node
, -1 will be
+ * returned.
+ */
+public int getIndex(TreeNode node)
+{
+ return -1;
+}
+
+/**
+ * Returns the parent TreeNode
of the receiver.
+ */
+public TreeNode getParent()
+{
+ return parent;
+}
+
+/**
+ * Returns true if the receiver allows children.
+ */
+public boolean getAllowsChildren()
+{
+ return true;
+}
+
+/**
+ * Returns true if the receiver is a leaf.
+ */
+public boolean isLeaf()
+{
+ return true;
+}
+
+} // end class PortInfo
+
+class TreeUpdate implements Runnable
+{
+ public void run()
+ {
+ fireTreeModelChanged();
+ firePropertyChange("modems", null, null);
+ }
+}
+
+}
+
diff --git a/src/main/java/uk/co/westhawk/snmp/beans/AscendActiveSessionBean.java b/src/main/java/uk/co/westhawk/snmp/beans/AscendActiveSessionBean.java
new file mode 100644
index 0000000..6d64d79
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/beans/AscendActiveSessionBean.java
@@ -0,0 +1,378 @@
+// NAME
+// $RCSfile: AscendActiveSessionBean.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.13 $
+// CREATED
+// $Date: 2006/01/25 18:08:55 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.beans;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+import java.awt.*;
+import java.util.*;
+import java.text.*;
+import java.lang.*;
+import java.io.*;
+import java.beans.*;
+
+/**
+ *
+ * This bean is written for the Ascend Router from
+ * Lucent Technologies, Inc.
+ *
+ * The Ascend Enterprise MIBs can be downloaded from
+ * ByteSphere.
+ *
+ *
+ *
+ * This bean collects information about the active session on an Ascend router.
+ *
+ *
+ *
+ * The properties in the parent classes should be set, before calling
+ * the action() method. Via a PropertyChangeEvent the application/applet
+ * will be notified.
+ *
+ *
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setCommunityName
+ * @see SNMPRunBean#setUpdateInterval
+ * @see SNMPBean#addPropertyChangeListener
+ * @see SNMPBean#action
+ * @see GetNextPdu_vec
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.13 $ $Date: 2006/01/25 18:08:55 $
+ *
+ */
+public class AscendActiveSessionBean extends SNMPRunBean implements Observer
+{
+ private static final String version_id =
+ "@(#)$Id: AscendActiveSessionBean.java,v 1.13 2006/01/25 18:08:55 birgit Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * A unique number identifying this active session.
+ * See the session.mib
+ */
+ public final static String ssnActiveCallReferenceNum =
+ "1.3.6.1.4.1.529.12.3.1.1";
+ /**
+ * The name of the remote user.
+ * See the session.mib
+ */
+ public final static String ssnActiveUserName =
+ "1.3.6.1.4.1.529.12.3.1.4";
+ /**
+ * The IP address of the remote user.
+ * See the session.mib
+ */
+ public final static String ssnActiveUserIPAddress =
+ "1.3.6.1.4.1.529.12.3.1.5";
+ /**
+ * The subnet mask of the remote user.
+ * See the session.mib
+ */
+ public final static String ssnActiveUserSubnetMask =
+ "1.3.6.1.4.1.529.12.3.1.6";
+ /**
+ * The current service provided to the remote user.
+ * See the session.mib
+ */
+ public final static String ssnActiveCurrentService =
+ "1.3.6.1.4.1.529.12.3.1.7";
+
+ private final static int NR_OID = 5;
+
+ private final static int none = 1;
+ private final static int other = 2; // none of the following
+ private final static int ppp = 3; // Point-To-Point Protocol
+ private final static int slip = 4; // Serial Line IP
+ private final static int mpp = 5; // Multichannel PPP
+ private final static int x25 = 6; // X.25
+ private final static int combinet = 7; // Combinet
+ private final static int frameRelay = 8; // Frame Relay
+ private final static int euraw = 9;
+ private final static int euui = 10;
+ private final static int telnet = 11; // telnet
+ private final static int telnetBinary = 12; // binary telnet
+ private final static int rawTcp = 13; // raw TCP
+ private final static int terminalServer = 14; // terminal server
+ private final static int mp = 15; // Multilink PPP
+ private final static int virtualConnect = 16; // Virtual Connect to a modem
+ private final static int dchannelX25 = 17; // D Channel X.25
+ private final static int dtpt = 18; // DTPT session to ZGR
+
+ private final static String msg_service[] =
+ {
+ "",
+ "none",
+ "other",
+ "ppp",
+ "slip",
+ "mpp",
+ "x25",
+ "combinet",
+ "frameRelay",
+ "euraw",
+ "euui",
+ "telnet",
+ "telnetBinary",
+ "rawTcp",
+ "terminalServer",
+ "mp",
+ "virtualConnect",
+ "dchannelX25",
+ "dtpt"
+ };
+
+ private GetNextPdu_vec pdu;
+
+ private boolean isGetNextInFlight;
+ private Date lastUpdateDate = null;
+
+ private int callReferenceNum = 0;
+ private String userName = "";
+ private String userIPAddress = "0.0.0.0";
+ private String userSubnetMask = "0.0.0.0";
+ private String currentService = "none";
+
+/**
+ * The default constructor.
+ */
+public AscendActiveSessionBean()
+{
+}
+
+/**
+ * The constructor that will set the host and the port no.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ */
+public AscendActiveSessionBean(String h, int p)
+{
+ this(h, p, null);
+}
+
+/**
+ * The constructor that will set the host, the port no and the local
+ * bind address.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @param b the local bind address
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setBindAddress
+ *
+ * @since 4_14
+ */
+public AscendActiveSessionBean(String h, int p, String b)
+{
+ this();
+ setHost(h);
+ setPort(p);
+ setBindAddress(b);
+}
+
+/**
+ * Returns the date of the moment when this bean was last updated.
+ * This might be null when the first time the update was not finished.
+ *
+ * @return the last update date
+ */
+public Date getLastUpdateDate()
+{
+ return lastUpdateDate;
+}
+
+/**
+ * Returns the name of the remote user of the Ascend active session.
+ *
+ * @return the name
+ */
+public String getUserName()
+{
+ return userName;
+}
+
+/**
+ * Returns the IP address of the remote user of the Ascend active
+ * session.
+ *
+ * @return the IP address
+ */
+public String getUserIPAddress()
+{
+ return userIPAddress;
+}
+
+/**
+ * Returns the subnet mask of the remote user of the Ascend active
+ * session.
+ *
+ * @return the subnet mask
+ */
+public String getUserSubnetMask()
+{
+ return userSubnetMask;
+}
+
+/**
+ * Returns the current service provided to the remote user of the Ascend
+ * active session.
+ *
+ * @return the current service
+ */
+public String getCurrentService()
+{
+ return currentService;
+}
+
+/**
+ * This method starts the action of the bean. It will initialises
+ * all variables before starting.
+ */
+public void action()
+{
+ if (isHostPortReachable())
+ {
+ lastUpdateDate = new Date();
+ isGetNextInFlight = false;
+ setRunning(true);
+ }
+}
+
+/**
+ * Implements the running of the bean.
+ *
+ * It will send the Pdu, if the previous one is not still in flight.
+ * @see SNMPRunBean#isRunning()
+ */
+public void run()
+{
+ while (context != null && isRunning())
+ {
+ if (isGetNextInFlight == false)
+ {
+ // start the GetNext loop again
+ isGetNextInFlight = true;
+ pdu = new GetNextPdu_vec(context, NR_OID);
+ pdu.addObserver(this);
+
+ pdu.addOid(ssnActiveCallReferenceNum);
+ pdu.addOid(ssnActiveUserName);
+ pdu.addOid(ssnActiveUserIPAddress);
+ pdu.addOid(ssnActiveUserSubnetMask);
+ pdu.addOid(ssnActiveCurrentService);
+ try
+ {
+ pdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+
+ try
+ {
+ Thread.sleep(interval);
+ }
+ catch (InterruptedException ix)
+ {
+ ;
+ }
+ }
+}
+
+/**
+ * This method is called when the Pdu response is received. When all
+ * answers are received it will fire the property change event.
+ *
+ * The answers are stored in a hashtable, this is done because the speed
+ * can only be calculated with the previous answer.
+ *
+ * @see SNMPBean#addPropertyChangeListener
+ */
+public void update(Observable obs, Object ov)
+{
+ int service;
+ varbind [] var;
+
+ pdu = (GetNextPdu_vec) obs;
+
+ if (pdu.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ var = (varbind []) ov;
+ callReferenceNum = ((AsnInteger) var[0].getValue()).getValue();
+
+ if (callReferenceNum > 0)
+ {
+ userName = ((AsnOctets) var[1].getValue()).getValue();
+ userIPAddress = ((AsnOctets) var[2].getValue()).getValue();
+ userSubnetMask = ((AsnOctets) var[3].getValue()).getValue();
+
+ service = ((AsnInteger) var[4].getValue()).getValue();
+ currentService = msg_service[service];
+ }
+
+ // the GetNext loop has ended
+ lastUpdateDate = new Date();
+ isGetNextInFlight = false;
+ firePropertyChange("services", null, null);
+ }
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/beans/DialogChannelStatusBean.java b/src/main/java/uk/co/westhawk/snmp/beans/DialogChannelStatusBean.java
new file mode 100644
index 0000000..2765f58
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/beans/DialogChannelStatusBean.java
@@ -0,0 +1,759 @@
+// NAME
+// $RCSfile: DialogChannelStatusBean.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.18 $
+// CREATED
+// $Date: 2006/02/02 15:49:39 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.beans;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+
+import javax.swing.tree.*;
+import java.awt.*;
+import java.util.*;
+import java.text.*;
+import java.lang.*;
+import java.io.*;
+import java.beans.*;
+
+/**
+ *
+ * This bean is written for a Dialogic card.
+ *
+ * The Dialogic MIBs come with their
+ * BoardWatch
+ * package. You will have to fill in a form before downloading it.
+ *
+ *
+ * This bean collects information about the voice channel status of the
+ * Dialogic card. It will only collect those channels that are open.
+ *
+ *
+ *
+ * You can get the data via the getChannelIndexes() and
+ * getChannelStatus(Integer index) methods. This way you can visualise
+ * the data yourself.
+ *
+ *
+ *
+ * You can also use the Swing JTree to visualise the channels.
+ * This bean implements the Swing TreeNode interface.
+ * The user has to set the setDefaultTreeModel, so this class can update all
+ * the nodes that are added, removed of changed.
+ * If this class is not the root of the JTree, you have to set
+ * the (TreeNode) parent of this class.
+ *
+ *
+ *
+ * The properties in the parent classes should be set, before calling
+ * the action() method. Via a TreeModelEvent the application/applet
+ * will be notified.
+ *
+ *
+ *
+ * We only have one (1) Dialogics card, so I don't know how and if it
+ * works with more than 1 card. Please let us know if it doesn't work.
+ *
+ *
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setCommunityName
+ * @see SNMPRunBean#setUpdateInterval
+ * @see SNMPBean#addPropertyChangeListener
+ * @see SNMPBean#action
+ * @see GetNextPdu_vec
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.18 $ $Date: 2006/02/02 15:49:39 $
+ *
+ */
+public class DialogChannelStatusBean extends SNMPRunBean
+ implements Observer, TreeNode
+{
+ private static final String version_id =
+ "@(#)$Id: DialogChannelStatusBean.java,v 1.18 2006/02/02 15:49:39 birgit Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * A unique value for each R4 device contained by the
+ * host. The value for each R4 device must remain
+ * constant at least from one re-initialization of the
+ * agent to the next re-initialization.
+ *
+ * See the dlgr4dev.mib.
+ */
+ public final static String dlgR4DeviceIndex =
+ "1.3.6.1.4.1.3028.2.1.1.2.1.1.1";
+
+ /**
+ * Release 4 Device Name. This is the name the application will
+ * use when opening the device (e.g. dxxxB1C1, dtiB1T1, msiB1C1)
+ * See the dlgr4dev.mib.
+ */
+ public final static String dlgR4DeviceName =
+ "1.3.6.1.4.1.3028.2.1.1.2.1.1.2";
+
+ /**
+ * An indication of the type of the device.
+ *
+ * -
+ * other - some other type of device unknown to the agent.
+ * -
+ * voice - A voice channel device. An entry exits in the
+ * dlgR4VoiceTable for this device.
+ * -
+ * dti - A DTI timeslot device. An entry exits in the
+ * dlgR4DTITable for this device.
+ * -
+ * isdn - An ISDN B-Channel device. An entry exits in the
+ * dlgR4ISDNTable for this device.
+ * -
+ * msi - An MSI station set device. An entry exits in the
+ * dlgR4MSITable for this device.
+ *
+ *
+ * See the dlgr4dev.mib.
+ */
+ public final static String dlgR4DeviceType =
+ "1.3.6.1.4.1.3028.2.1.1.2.1.1.3";
+
+ /**
+ * An indication of how many instances of this device is currently
+ * opened.
+ * See the dlgr4dev.mib.
+ */
+ public final static String dlgR4DeviceOpenCount =
+ "1.3.6.1.4.1.3028.2.1.1.2.1.1.5";
+
+ /**
+ * Indicates current activity status on the (voice) channel.
+ * See the dlgr4dev.mib.
+ */
+ public final static String dlgR4VoiceChannelStatus =
+ "1.3.6.1.4.1.3028.2.1.1.2.2.1.2";
+
+ private final static int NR_OID = 5;
+
+ // dlgR4DeviceType values
+ public final static int unknown = 1;
+ public final static int voice = 2;
+ public final static int dti = 3;
+ public final static int isdn = 4;
+ public final static int msi = 5;
+
+ // dlgR4VoiceChannelStatus values
+ public final static int idle = 1;
+ public final static int playing = 2;
+ public final static int recording = 3;
+ public final static int gettingDigits = 5;
+ public final static int blocked = 16;
+
+ public final static int dialing = 4;
+ public final static int playTone = 6;
+ public final static int sendingFax = 8;
+ public final static int receivingFax = 9;
+ public final static int betweenFAXPages = 10;
+ public final static int hookState = 11;
+ public final static int winking = 12;
+ public final static int callProgess = 13;
+ public final static int gettingR2MF = 14;
+
+ public final static String vch_status[] =
+ {
+ "",
+ "Channel not active",
+ "Playing Audio Data",
+ "Recording Audio Data",
+ "Dialing Digits",
+ "Collecting DTMF digits",
+ "Playing a tone",
+ "",
+ "Sending a FAX (VFX boards)",
+ "Receiving a FAX (VFX boards)",
+ "Between FAX pages (VFX boards)",
+ "Changing hook status to onhook or offhook",
+ "Performing a wink",
+ "Performing Call progress analysis",
+ "Retrieving R2MF digits",
+ "",
+ "Blocked"
+ };
+
+ private GetNextPdu_vec pdu;
+ private Hashtable channelIndexStatusHash;
+ private Hashtable channelHash;
+
+ private TreeNode parent;
+ private DefaultTreeModel treeModel;
+
+ private boolean isGetNextInFlight;
+ private Date lastUpdateDate = null;
+
+ private int deviceType = 0;
+ private String deviceName = "";
+ private int openCount = 0;
+ private int channelStatus = 0;
+
+/**
+ * The default constructor.
+ */
+public DialogChannelStatusBean()
+{
+ channelIndexStatusHash = new Hashtable();
+ channelHash = new Hashtable();
+}
+
+/**
+ * The constructor that will set the host and the port no.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ */
+public DialogChannelStatusBean(String h, int p)
+{
+ this(h, p, null);
+}
+
+/**
+ * The constructor that will set the host, the port no and the local
+ * bind address.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @param b the local bind address
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setBindAddress
+ *
+ * @since 4_14
+ */
+public DialogChannelStatusBean(String h, int p, String b)
+{
+ this();
+ setHost(h);
+ setPort(p);
+ setBindAddress(b);
+}
+
+/**
+ * Returns the date of the moment when this bean was last updated.
+ * This might be null when the first time the update was not finished.
+ *
+ * @return the last update date
+ */
+public Date getLastUpdateDate()
+{
+ return lastUpdateDate;
+}
+
+/**
+ * Returns the indexes (as Integers) of the voice channels that are
+ * open. Only the open voice channels of the card are saved.
+ *
+ * Use getChannelStatus() or getChannelStatusString() to get the status
+ * of the channel.
+ *
+ * @see #getChannelStatus
+ * @see #getChannelStatusString
+ */
+public Enumeration getChannelIndexes()
+{
+ return channelIndexStatusHash.keys();
+}
+
+/**
+ * Returns the number of voice channels in the table.
+ */
+public synchronized int getChannelCount()
+{
+ return channelIndexStatusHash.size();
+}
+
+/**
+ * Returns the name of the channel.
+ *
+ * @param index The index of the channel
+ * @return The name
+ *
+ */
+public String getChannelName(Integer index)
+{
+ String name = "";
+ Object obj = channelHash.get(index);
+ if (obj != null)
+ {
+ ChannelStatus chSt = (ChannelStatus) obj;
+ name = chSt.getName();
+ }
+ return name;
+}
+
+/**
+ * Returns the status of the channel as an int.
+ *
+ * @param index The index of the channel
+ * @return The status
+ *
+ * @see #getChannelIndexes
+ */
+public int getChannelStatus(Integer index)
+{
+ int status = 0;
+ Object obj = channelIndexStatusHash.get(index);
+ if (obj != null)
+ {
+ status = ((Integer)obj).intValue();
+ }
+ return status;
+}
+
+/**
+ * Returns the String representation of the status of the channel.
+ *
+ * @param index The index of the channel
+ * @return The status
+ *
+ * @see #getChannelIndexes
+ */
+public String getChannelStatusString(Integer index)
+{
+ int status = getChannelStatus(index);
+ String str = vch_status[status];
+ return str;
+}
+
+/**
+ * Returns the children of the reciever as an Enumeration.
+ */
+public Enumeration children()
+{
+ return channelHash.elements();
+}
+
+/**
+ * Returns the number of children TreeNode
s the receiver
+ * contains.
+ */
+public int getChildCount()
+{
+ int sz = channelHash.size();
+ return sz;
+}
+
+/**
+ * Returns the child TreeNode
at index
+ * childIndex
.
+ */
+public TreeNode getChildAt(int childIndex)
+{
+ TreeNode node = null;
+ if (childIndex < channelHash.size())
+ {
+ Enumeration e = channelHash.elements();
+ for (int i=0; i<=childIndex; i++)
+ {
+ node = (TreeNode) e.nextElement();
+ }
+ }
+ return node;
+}
+
+/**
+ * Returns the index of node
in the receivers children.
+ * If the receiver does not contain node
, -1 will be
+ * returned.
+ */
+public int getIndex(TreeNode node)
+{
+ int ret = -1;
+ if (channelHash.contains(node))
+ {
+ boolean found = false;
+ Enumeration e = channelHash.elements();
+ while (e.hasMoreElements() && !found)
+ {
+ TreeNode n = (TreeNode) e.nextElement();
+ found = (n == node);
+ ret++;
+ }
+ }
+ return ret;
+}
+
+/**
+ * Returns the parent TreeNode
of the receiver.
+ */
+public TreeNode getParent()
+{
+ return parent;
+}
+
+/**
+ * Returns true if the receiver allows children.
+ */
+public boolean getAllowsChildren()
+{
+ return true;
+}
+
+/**
+ * Returns true if the receiver is a leaf.
+ */
+public boolean isLeaf()
+{
+ return false;
+}
+/**
+ * This method starts the action of the bean. It will initialises
+ * all variables before starting.
+ */
+public void action()
+{
+ if (isHostPortReachable())
+ {
+ lastUpdateDate = new Date();
+ isGetNextInFlight = false;
+ setRunning(true);
+ }
+}
+
+/**
+ * Implements the running of the bean.
+ *
+ * It will send the Pdu, if the previous one is not still in flight.
+ * @see SNMPRunBean#isRunning()
+ */
+public void run()
+{
+ while (context != null && isRunning())
+ {
+ if (isGetNextInFlight == false)
+ {
+ // start the GetNext loop again
+ isGetNextInFlight = true;
+
+ pdu = new GetNextPdu_vec(context, NR_OID);
+ pdu.addObserver(this);
+
+ pdu.addOid(dlgR4DeviceIndex);
+ pdu.addOid(dlgR4DeviceName);
+ pdu.addOid(dlgR4DeviceType);
+ pdu.addOid(dlgR4DeviceOpenCount);
+ pdu.addOid(dlgR4VoiceChannelStatus);
+ try
+ {
+ pdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+
+ try
+ {
+ Thread.sleep(interval);
+ }
+ catch (InterruptedException ix)
+ {
+ ;
+ }
+ }
+}
+
+/**
+ * This method is called when the Pdu response is received. When all
+ * answers are received it will fire the property change event.
+ *
+ */
+public void update(Observable obs, Object ov)
+{
+ boolean hasEnded = false;
+ int index;
+ varbind [] var;
+
+ pdu = (GetNextPdu_vec) obs;
+
+ if (pdu.isTimedOut() == false)
+ {
+ if (pdu.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ var = (varbind []) ov;
+ if (var[0].getOid().toString().startsWith(dlgR4DeviceIndex))
+ {
+ index = ((AsnInteger) var[0].getValue()).getValue();
+ deviceName = ((AsnOctets) var[1].getValue()).getValue();
+ deviceType = ((AsnInteger) var[2].getValue()).getValue();
+ openCount = ((AsnInteger) var[3].getValue()).getValue();
+ channelStatus = ((AsnInteger) var[4].getValue()).getValue();
+
+ if (deviceType == voice)
+ {
+ Integer indexInt = new Integer(index);
+ if (openCount == 0)
+ {
+ channelIndexStatusHash.remove(indexInt);
+ channelHash.remove(indexInt);
+ }
+ else
+ {
+ channelIndexStatusHash.put(indexInt,
+ new Integer(channelStatus));
+
+ ChannelStatus cStatus =
+ (ChannelStatus) channelHash.get(indexInt);
+
+ if (cStatus == null)
+ {
+ cStatus = new ChannelStatus(index, channelStatus,
+ deviceName, this);
+ channelHash.put(indexInt, cStatus);
+ }
+ else
+ {
+ cStatus.setStatus(channelStatus);
+ }
+ }
+ }
+
+ // ask for the next channel
+ pdu = new GetNextPdu_vec(context, NR_OID);
+ pdu.addObserver(this);
+
+ pdu.addOid(var[0].getOid().toString());
+ pdu.addOid(var[1].getOid().toString());
+ pdu.addOid(var[2].getOid().toString());
+ pdu.addOid(var[3].getOid().toString());
+ pdu.addOid(var[4].getOid().toString());
+ try
+ {
+ pdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+ else
+ {
+ hasEnded = true;
+ }
+ }
+ else
+ {
+ hasEnded = true;
+ }
+ }
+ else
+ {
+ channelIndexStatusHash.clear();
+ channelHash.clear();
+ hasEnded = true;
+ }
+
+ if (hasEnded)
+ {
+ // the GetNext loop has ended
+ lastUpdateDate = new Date();
+ javax.swing.SwingUtilities.invokeLater(new TreeUpdate());
+ isGetNextInFlight = false;
+ }
+}
+
+/**
+ * Sets the parent for this TreeNode. If the parent is not set, this
+ * class should be the root of the TreeModel.
+ */
+public void setParent (TreeNode p)
+{
+ parent = p;
+}
+
+/**
+ * Sets the DefaultTreeModel for this TreeNode. The tree model is used
+ * for notifying when any of the nodes were added, removed or changed.
+ */
+public void setDefaultTreeModel (DefaultTreeModel model)
+{
+ treeModel = model;
+}
+
+/**
+ * Fire the property event.
+ *
+ * @see
+ * DefaultTreeModel#nodeStructureChanged
+ */
+protected void fireTreeModelChanged()
+{
+ if (treeModel != null)
+ {
+ treeModel.nodeStructureChanged(this);
+ }
+}
+
+class ChannelStatus extends Object implements TreeNode
+{
+ private TreeNode parent;
+ private int index, status;
+ private String name;
+
+public ChannelStatus(int ind, int st, String nm, TreeNode par)
+{
+ index = ind;
+ status = st;
+ name = nm;
+ parent = par;
+}
+
+public int getIndex()
+{
+ return index;
+}
+
+public int getStatus()
+{
+ return status;
+}
+
+public void setStatus(int st)
+{
+ status = st;
+}
+
+public String getName()
+{
+ return name;
+}
+
+public String toString()
+{
+ return ""+index + " " + name + " " + vch_status[status];
+}
+
+/**
+ * Returns the children of the reciever as an Enumeration.
+ */
+public Enumeration children()
+{
+ return null;
+}
+
+/**
+ * Returns the number of children TreeNode
s the receiver
+ * contains.
+ */
+public int getChildCount()
+{
+ return 0;
+}
+
+/**
+ * Returns the child TreeNode
at index
+ * childIndex
.
+ */
+public TreeNode getChildAt(int childIndex)
+{
+ return null;
+}
+
+/**
+ * Returns the index of node
in the receivers children.
+ * If the receiver does not contain node
, -1 will be
+ * returned.
+ */
+public int getIndex(TreeNode node)
+{
+ return -1;
+}
+
+/**
+ * Returns the parent TreeNode
of the receiver.
+ */
+public TreeNode getParent()
+{
+ return parent;
+}
+
+/**
+ * Returns true if the receiver allows children.
+ */
+public boolean getAllowsChildren()
+{
+ return true;
+}
+
+/**
+ * Returns true if the receiver is a leaf.
+ */
+public boolean isLeaf()
+{
+ return true;
+}
+
+} // end class ChannelStatus
+
+class TreeUpdate implements Runnable
+{
+ public void run()
+ {
+ fireTreeModelChanged();
+ firePropertyChange("modems", null, null);
+ }
+}
+
+}
+
diff --git a/src/main/java/uk/co/westhawk/snmp/beans/InterfaceIndexesBean.java b/src/main/java/uk/co/westhawk/snmp/beans/InterfaceIndexesBean.java
new file mode 100644
index 0000000..0abdae3
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/beans/InterfaceIndexesBean.java
@@ -0,0 +1,295 @@
+// NAME
+// $RCSfile: InterfaceIndexesBean.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.13 $
+// CREATED
+// $Date: 2006/01/25 18:08:55 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.beans;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+import java.awt.*;
+import java.util.*;
+import java.text.*;
+import java.lang.*;
+import java.io.*;
+import java.beans.*;
+
+/**
+ *
+ * This bean collects information about the number of interfaces on a
+ * system and their index.
+ *
+ *
+ *
+ * The number is the number of network interfaces (regardless of
+ * their current state) present on this system. The number
+ * will remain the same untill the next time the SNMP server is
+ * restarted. The interfaces may go up and down while running.
+ *
+ *
+ *
+ * The properties in the parent classes should be set, before calling
+ * the action() method. Via a PropertyChangeEvent the application/applet
+ * will be notified.
+ *
+ *
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setCommunityName
+ * @see SNMPRunBean#setUpdateInterval
+ * @see SNMPBean#addPropertyChangeListener
+ * @see SNMPBean#action
+ * @see InterfaceGetNextPdu
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.13 $ $Date: 2006/01/25 18:08:55 $
+ *
+ */
+public class InterfaceIndexesBean extends SNMPRunBean implements Observer
+{
+ private static final String version_id =
+ "@(#)$Id: InterfaceIndexesBean.java,v 1.13 2006/01/25 18:08:55 birgit Exp $ Copyright Westhawk Ltd";
+
+ private InterfaceGetNextPdu pdu;
+ private Hashtable interfaceHash;
+
+ private boolean isGetNextInFlight;
+ private Date lastUpdateDate = null;
+
+
+/**
+ * The default constructor.
+ */
+public InterfaceIndexesBean()
+{
+ interfaceHash = new Hashtable();
+}
+
+/**
+ * The constructor that will set the host and the port no.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ */
+public InterfaceIndexesBean(String h, int p)
+{
+ this(h, p, null);
+}
+
+/**
+ * The constructor that will set the host, the port no and the local
+ * bind address.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @param b the local bind address
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setBindAddress
+ *
+ * @since 4_14
+ */
+public InterfaceIndexesBean(String h, int p, String b)
+{
+ this();
+ setHost(h);
+ setPort(p);
+ setBindAddress(b);
+}
+
+/**
+ * Returns the date of the moment when this bean was last updated.
+ * This might be null when the first time the update was not finished.
+ *
+ * @return the last update date
+ */
+public Date getLastUpdateDate()
+{
+ return lastUpdateDate;
+}
+
+/**
+ * Returns the indexes (as Strings) of the current interfaces (the list
+ * of ifIndex).
+ */
+public Enumeration getInterfaceIndexes()
+{
+ return interfaceHash.keys();
+}
+
+/**
+ * Returns the indexes (as Strings) of the current interfaces (the list
+ * of ifIndex).
+ *
+ * @since 4_14
+ */
+public Set getInterfaceIndexSet()
+{
+ return interfaceHash.keySet();
+}
+
+/**
+ * Returns the number of current interfaces.
+ */
+public synchronized int getInterfaceCount()
+{
+ return interfaceHash.size();
+}
+
+/**
+ * This method starts the action of the bean. It will initialises
+ * all variables before starting.
+ */
+public void action()
+{
+ if (isHostPortReachable())
+ {
+ interfaceHash.clear();
+ lastUpdateDate = new Date();
+ isGetNextInFlight = false;
+ setRunning(true);
+ }
+}
+
+/**
+ * Implements the running of the bean.
+ *
+ * It will send the Pdu, if the previous one is not still in flight.
+ * @see SNMPRunBean#isRunning()
+ */
+public void run()
+{
+ while (context != null && isRunning())
+ {
+ if (isGetNextInFlight == false)
+ {
+ // start the GetNext loop again
+ isGetNextInFlight = true;
+ pdu = new InterfaceGetNextPdu(context);
+ pdu.addObserver(this);
+ pdu.addOids(null);
+ try
+ {
+ pdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+
+ try
+ {
+ Thread.sleep(interval);
+ }
+ catch (InterruptedException ix)
+ {
+ ;
+ }
+ }
+}
+
+/**
+ * This method is called when the Pdu response is received. When all
+ * answers are received it will fire the property change event.
+ *
+ * The answers are stored in a hashtable, this is done because the speed
+ * can only be calculated with the previous answer.
+ *
+ * @see SNMPBean#addPropertyChangeListener
+ */
+public void update(Observable obs, Object ov)
+{
+ InterfaceGetNextPdu prev;
+ String hashKey;
+
+ pdu = (InterfaceGetNextPdu) obs;
+ if (pdu.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ hashKey = String.valueOf(pdu.getIfIndex());
+ if ((prev = (InterfaceGetNextPdu)interfaceHash.get(hashKey)) != null)
+ {
+ pdu.getSpeed(prev);
+ }
+
+ // update the hashtable with the new answer
+ interfaceHash.put(hashKey, pdu);
+
+ // perform the GetNext on the just received answer
+ prev = pdu;
+ pdu = new InterfaceGetNextPdu(context);
+ pdu.addObserver(this);
+ pdu.addOids(prev);
+ try
+ {
+ pdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+ else
+ {
+ // the GetNext loop has ended
+ lastUpdateDate = new Date();
+ isGetNextInFlight = false;
+ firePropertyChange("InterfaceIndexes", null, null);
+ }
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/beans/IsHostReachableBean.java b/src/main/java/uk/co/westhawk/snmp/beans/IsHostReachableBean.java
new file mode 100644
index 0000000..325f537
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/beans/IsHostReachableBean.java
@@ -0,0 +1,317 @@
+// NAME
+// $RCSfile: IsHostReachableBean.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.14 $
+// CREATED
+// $Date: 2006/01/26 12:38:59 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.beans;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+import java.awt.*;
+import java.util.*;
+import java.text.*;
+import java.lang.*;
+import java.io.*;
+import java.beans.*;
+
+/**
+ *
+ * This bean will determine whether the host+port is up, by sending an
+ * UpSincePdu.
+ *
+ *
+ *
+ * The properties in the parent classes should be set, before calling
+ * the action() method. Via a PropertyChangeEvent the application/applet
+ * will be notified.
+ *
+ *
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setCommunityName
+ * @see SNMPBean#addPropertyChangeListener
+ * @see SNMPBean#action
+ * @see UpSincePdu
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.14 $ $Date: 2006/01/26 12:38:59 $
+ *
+ */
+public class IsHostReachableBean extends SNMPBean implements Observer
+{
+ private static final String version_id =
+ "@(#)$Id: IsHostReachableBean.java,v 1.14 2006/01/26 12:38:59 birgit Exp $ Copyright Westhawk Ltd";
+
+ private UpSincePdu pdu;
+
+ private Date upSince = null;
+ private boolean isReachable = false;
+
+ private SimpleDateFormat dateFormat;
+
+
+/**
+ * The default constructor.
+ */
+public IsHostReachableBean()
+{
+ dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss zzz");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
+}
+
+/**
+ * The constructor that will set the host and the port no.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ */
+public IsHostReachableBean(String h, int p)
+{
+ this(h, p, null);
+}
+
+/**
+ * The constructor that will set the host, the port no and the local
+ * bind address.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @param b the local bind address
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setBindAddress
+ *
+ * @since 4_14
+ */
+public IsHostReachableBean(String h, int p, String b)
+{
+ this();
+ setHost(h);
+ setPort(p);
+ setBindAddress(b);
+}
+
+/**
+ * Returns the date when the host went up. This might be null is no
+ * answer is received yet.
+ * @return the date
+ *
+ * @see SNMPBean#getMessage()
+ * @see #isReachable()
+ */
+public Date getUpSinceDate()
+{
+ return upSince;
+}
+
+/**
+ * Answer is set according to the received SNMP response.
+ * @see #getUpSinceDate()
+ */
+protected void setUpSinceDate(Date d)
+{
+ upSince = d;
+}
+
+/**
+ * Indicates whether the host + port is reachable.
+ * The host + port is reachable if a valid response is received from a
+ * UpSincePdu request.
+ * @return is the host + port + community name valid
+ *
+ * @see SNMPBean#getMessage()
+ * @see #getUpSinceDate()
+ */
+public boolean isReachable()
+{
+ return isReachable;
+}
+
+/**
+ * The reachable property is set according to the succes of making
+ * a connection and the response of the SNMP request.
+ * This method will fire a Property Change Event.
+ *
+ * @see #isReachable()
+ * @see SNMPBean#addPropertyChangeListener
+ */
+protected void setReachable(boolean b)
+{
+ boolean old;
+ old = isReachable;
+ isReachable = b;
+
+ firePropertyChange("Reachable", new Boolean (old),
+ new Boolean (isReachable));
+}
+
+
+/**
+ * This method performs the request and wait for it. It is not
+ * recommended to use the waitForSelf option, preferred is the action()
+ * method.
+ * Use it if it is really necessary to wait.
+ *
+ * @see SnmpContext
+ * @see #action()
+ * @see Pdu#waitForSelf()
+ */
+public void waitForSelfAction()
+throws PduException, IOException
+{
+ action(true);
+}
+
+/**
+ * This method actually performs the request. All properties should be
+ * set before this method is called.
+ *
+ * This will create a new SnmpContext and send a UpSincePdu SNMP
+ * request.
+ * If the connection fails, the reachable property will be set to false.
+ *
+ * @see SnmpContext
+ */
+public void action()
+throws PduException, IOException
+{
+ action(false);
+}
+
+protected void action(boolean wait)
+throws PduException, IOException
+{
+ if (host != null
+ &&
+ host.length() > 0
+ &&
+ port > 0)
+ {
+ try
+ {
+ if (context != null)
+ {
+ context.destroy();
+ }
+ context = new SnmpContext(host, port, bindAddr, socketType);
+ context.setCommunity(community);
+ setMessage("Connection to host " + host
+ + " is made succesfully");
+
+ if (wait == true)
+ {
+ pdu = new UpSincePdu(context, null);
+ if (pdu.waitForSelf())
+ {
+ this.update((Observable) pdu, (Object) null);
+ }
+ else
+ {
+ setMessage("No SNMP Response from " + host);
+ }
+ }
+ else
+ {
+ pdu = new UpSincePdu(context, this);
+ }
+ }
+ catch (IOException exc)
+ {
+ setMessage("IOException: " + exc.getMessage());
+ setReachable(false);
+ }
+ catch (RuntimeException exc)
+ {
+ setMessage("RuntimeException: " + exc.getMessage());
+ setReachable(false);
+ }
+ }
+}
+
+/**
+ * The update method according to the Observer interface, it will be
+ * called when the Pdu response is received.
+ * If there is no error it means that the host is reachable. If it is
+ * not reachable the message will contain the type of error, if it is
+ * reachable the message will say since when the host is up.
+ */
+public void update(Observable obs, Object ov)
+{
+ pdu = (UpSincePdu) obs;
+
+ if (pdu.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ setUpSinceDate(pdu.getDate());
+ setMessage("Host " + host + " is up since "
+ + dateFormat.format(getUpSinceDate()));
+ setReachable(true);
+ }
+ else
+ {
+ setUpSinceDate(null);
+ setMessage("SNMP Response: " + pdu.getErrorStatusString());
+ setReachable(false);
+ }
+}
+
+
+/**
+ * Destroys the context.
+ * @since 4_14
+ */
+public void freeResources()
+{
+ if (context != null)
+ {
+ context.destroy();
+ context = null;
+ }
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/beans/NTPrintQBean.java b/src/main/java/uk/co/westhawk/snmp/beans/NTPrintQBean.java
new file mode 100644
index 0000000..e95f189
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/beans/NTPrintQBean.java
@@ -0,0 +1,334 @@
+// NAME
+// $RCSfile: NTPrintQBean.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.13 $
+// CREATED
+// $Date: 2006/01/25 18:08:55 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.beans;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+import java.awt.*;
+import java.util.*;
+import java.text.*;
+import java.lang.*;
+import java.io.*;
+import java.beans.*;
+
+/**
+ *
+ * This bean collects the names of the print queues installed on
+ * a NT server. The NT mib is described in the
+ *
+ * LAN Manager MIB II for Windows NT Objects .
+ *
+ * You will have to register to the MSDN before accessing this page.
+ *
+ *
+ *
+ * The properties in the parent classes should be set, before calling
+ * the action() method. Via a PropertyChangeEvent the application/applet
+ * will be notified.
+ *
+ *
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setCommunityName
+ * @see SNMPRunBean#setUpdateInterval
+ * @see SNMPBean#addPropertyChangeListener
+ * @see SNMPBean#action
+ * @see GetNextPdu
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.13 $ $Date: 2006/01/25 18:08:55 $
+ *
+ */
+public class NTPrintQBean extends SNMPRunBean implements Observer
+{
+ private static final String version_id =
+ "@(#)$Id: NTPrintQBean.java,v 1.13 2006/01/25 18:08:55 birgit Exp $ Copyright Westhawk Ltd";
+
+ public final static String svPrintQName =
+ "1.3.6.1.4.1.77.1.2.29.1.1";
+
+ private int svPrintQName_len;
+ private GetNextPdu pdu;
+ private Hashtable printHash;
+
+ private boolean isGetNextInFlight;
+ private Date lastUpdateDate = null;
+
+
+/**
+ * The default constructor.
+ */
+public NTPrintQBean()
+{
+ printHash = new Hashtable();
+ svPrintQName_len = svPrintQName.length();
+}
+
+
+/**
+ * The constructor that will set the host and the port no.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ */
+public NTPrintQBean(String h, int p)
+{
+ this(h, p, null);
+}
+
+/**
+ * The constructor that will set the host, the port no and the local
+ * bind address.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @param b the local bind address
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setBindAddress
+ *
+ * @since 4_14
+ */
+public NTPrintQBean(String h, int p, String b)
+{
+ this();
+ setHost(h);
+ setPort(p);
+ setBindAddress(b);
+}
+
+/**
+ * Returns the date of the moment when this bean was last updated.
+ * This might be null when the first time the update was not finished.
+ *
+ * @return the last update date
+ */
+public Date getLastUpdateDate()
+{
+ return lastUpdateDate;
+}
+
+/**
+ * Returns the indices of the NT print queues.
+ * The OID of this print queue is a concatenation of the
+ * name (svPrintQName) OID and the print queue specific index.
+ * The index should be used to get the other properties of this print queue.
+ *
+ * @see #getIndex(String)
+ * @see #svPrintQName
+ */
+public Enumeration getIndices()
+{
+ return printHash.elements();
+}
+
+/**
+ * Returns the index of one of the print queues.
+ * The OID of this print
+ * queue is a concatenation of the name (svPrintQName) OID and the print
+ * queue specific index.
+ * The index should be used to get the other properties of this print queue.
+ *
+ * @param name The name of the print queue
+ * @return the print queue index, might be null if no print queue with such name
+ * exists
+ * @see #getIndices
+ * @see #getNames
+ */
+public String getIndex(String name)
+{
+ return (String) printHash.get(name);
+}
+
+/**
+ * Returns the names of the NT print queues (the list
+ * of svPrintQName).
+ */
+public Enumeration getNames()
+{
+ return printHash.keys();
+}
+
+/**
+ * Returns the number of NT print queues.
+ */
+public synchronized int getCount()
+{
+ return printHash.size();
+}
+
+/**
+ * This method starts the action of the bean. It will initialises
+ * all variables before starting.
+ */
+public void action()
+{
+ if (isHostPortReachable())
+ {
+ printHash.clear();
+ lastUpdateDate = new Date();
+ isGetNextInFlight = false;
+ setRunning(true);
+ }
+}
+
+/**
+ * Implements the running of the bean.
+ *
+ * It will send the Pdu, if the previous one is not still in flight.
+ * @see SNMPRunBean#isRunning()
+ */
+public void run()
+{
+ while (context != null && isRunning())
+ {
+ if (isGetNextInFlight == false)
+ {
+ // start the GetNext loop again
+ isGetNextInFlight = true;
+ pdu = new GetNextPdu(context);
+ pdu.addObserver(this);
+ pdu.addOid(svPrintQName);
+ try
+ {
+ pdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+
+ try
+ {
+ Thread.sleep(interval);
+ }
+ catch (InterruptedException ix)
+ {
+ ;
+ }
+ }
+}
+
+/**
+ * This method is called when the Pdu response is received. When all
+ * answers are received it will fire the property change event.
+ *
+ * The answers are stored in a hashtable, this is done because the speed
+ * can only be calculated with the previous answer.
+ *
+ * @see SNMPBean#addPropertyChangeListener
+ */
+public void update(Observable obs, Object ov)
+{
+ varbind var;
+ String hashKey;
+ String oid, index, name;
+
+ pdu = (GetNextPdu) obs;
+ if (pdu.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ var = (varbind) ov;
+ oid = "";
+ if (var != null)
+ {
+ oid = var.getOid().toString();
+ }
+ if (oid.startsWith(svPrintQName))
+ {
+ // index is the part of the oid AFTER the svPrintQName
+ index = oid.substring(svPrintQName_len+1);
+
+ name = ((AsnOctets) var.getValue()).getValue();
+
+ // update the hashtable with the new answer
+ printHash.put(name, index);
+
+ // perform the GetNext on the just received answer
+ pdu = new GetNextPdu(context);
+ pdu.addObserver(this);
+ pdu.addOid(oid);
+ try
+ {
+ pdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+ else
+ {
+ // the GetNext loop has ended
+ lastUpdateDate = new Date();
+ isGetNextInFlight = false;
+ firePropertyChange("resourceNames", null, null);
+ }
+ }
+ else
+ {
+ // the GetNext loop has ended
+ lastUpdateDate = new Date();
+ isGetNextInFlight = false;
+ firePropertyChange("resourceNames", null, null);
+ }
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/beans/NTServiceNamesBean.java b/src/main/java/uk/co/westhawk/snmp/beans/NTServiceNamesBean.java
new file mode 100644
index 0000000..85f59b7
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/beans/NTServiceNamesBean.java
@@ -0,0 +1,332 @@
+// NAME
+// $RCSfile: NTServiceNamesBean.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.13 $
+// CREATED
+// $Date: 2006/01/25 18:08:56 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.beans;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+import java.awt.*;
+import java.util.*;
+import java.text.*;
+import java.lang.*;
+import java.io.*;
+import java.beans.*;
+
+/**
+ *
+ * This bean collects the names of the network services installed on
+ * a NT server. The NT mib is described in the
+ *
+ * LAN Manager MIB II for Windows NT Objects .
+ *
+ * You will have to register to the MSDN before accessing this page.
+ *
+ *
+ *
+ * The properties in the parent classes should be set, before calling
+ * the action() method. Via a PropertyChangeEvent the application/applet
+ * will be notified.
+ *
+ *
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setCommunityName
+ * @see SNMPRunBean#setUpdateInterval
+ * @see SNMPBean#addPropertyChangeListener
+ * @see SNMPBean#action
+ * @see GetNextPdu
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.13 $ $Date: 2006/01/25 18:08:56 $
+ *
+ */
+public class NTServiceNamesBean extends SNMPRunBean implements Observer
+{
+ private static final String version_id =
+ "@(#)$Id: NTServiceNamesBean.java,v 1.13 2006/01/25 18:08:56 birgit Exp $ Copyright Westhawk Ltd";
+
+ public final static String svSvcName = "1.3.6.1.4.1.77.1.2.3.1.1";
+
+ private int svSvcName_len;
+ private GetNextPdu pdu;
+ private Hashtable serviceHash;
+
+ private boolean isGetNextInFlight;
+ private Date lastUpdateDate = null;
+
+
+/**
+ * The default constructor.
+ */
+public NTServiceNamesBean()
+{
+ serviceHash = new Hashtable();
+ svSvcName_len = svSvcName.length();
+}
+
+/**
+ * The constructor that will set the host and the port no.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ */
+public NTServiceNamesBean(String h, int p)
+{
+ this(h, p, null);
+}
+
+/**
+ * The constructor that will set the host, the port no and the local
+ * bind address.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @param b the local bind address
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setBindAddress
+ *
+ * @since 4_14
+ */
+public NTServiceNamesBean(String h, int p, String b)
+{
+ this();
+ setHost(h);
+ setPort(p);
+ setBindAddress(b);
+}
+
+/**
+ * Returns the date of the moment when this bean was last updated.
+ * This might be null when the first time the update was not finished.
+ *
+ * @return the last update date
+ */
+public Date getLastUpdateDate()
+{
+ return lastUpdateDate;
+}
+
+/**
+ * Returns the indices of the NT network services.
+ * The OID of this network service is a concatenation of the
+ * name (svSvcName) OID and the network service specific index.
+ * The index should be used to get the other properties of this service.
+ *
+ * @see #getIndex(String)
+ * @see #svSvcName
+ */
+public Enumeration getIndices()
+{
+ return serviceHash.elements();
+}
+
+/**
+ * Returns the index of one of the services.
+ * The OID of this network service is a concatenation of the
+ * name (svSvcName) OID and the network service specific index.
+ * The index should be used to get the other properties of this service.
+ *
+ * @param name The name of the service
+ * @return the service index, might be null if no service with such name
+ * exists
+ * @see #getIndices
+ * @see #getNames
+ */
+public String getIndex(String name)
+{
+ String ret = null;
+ if (name != null)
+ {
+ ret = (String) serviceHash.get(name);
+ }
+ return ret;
+}
+
+/**
+ * Returns the names of the NT network services (the list
+ * of svSvcName).
+ */
+public Enumeration getNames()
+{
+ return serviceHash.keys();
+}
+
+/**
+ * Returns the number of NT network services.
+ */
+public synchronized int getCount()
+{
+ return serviceHash.size();
+}
+
+/**
+ * This method starts the action of the bean. It will initialises
+ * all variables before starting.
+ */
+public void action()
+{
+ if (isHostPortReachable())
+ {
+ serviceHash.clear();
+ lastUpdateDate = new Date();
+ isGetNextInFlight = false;
+ setRunning(true);
+ }
+}
+
+/**
+ * Implements the running of the bean.
+ *
+ * It will send the Pdu, if the previous one is not still in flight.
+ * @see SNMPRunBean#isRunning()
+ */
+public void run()
+{
+ while (context != null && isRunning())
+ {
+ if (isGetNextInFlight == false)
+ {
+ // start the GetNext loop again
+ isGetNextInFlight = true;
+ pdu = new GetNextPdu(context);
+ pdu.addObserver(this);
+ pdu.addOid(svSvcName);
+ try
+ {
+ pdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+
+ try
+ {
+ Thread.sleep(interval);
+ }
+ catch (InterruptedException ix)
+ {
+ ;
+ }
+ }
+}
+
+/**
+ * This method is called when the Pdu response is received. When all
+ * answers are received it will fire the property change event.
+ *
+ * The answers are stored in a hashtable, this is done because the speed
+ * can only be calculated with the previous answer.
+ *
+ * @see SNMPBean#addPropertyChangeListener
+ */
+public void update(Observable obs, Object ov)
+{
+ varbind var;
+ String hashKey;
+ String oid, index, name;
+
+ pdu = (GetNextPdu) obs;
+ if (pdu.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ var = (varbind) ov;
+ oid = var.getOid().toString();
+ if (oid.startsWith(svSvcName))
+ {
+ // index is the part of the oid AFTER the svSvcName
+ index = oid.substring(svSvcName_len+1);
+
+ name = ((AsnOctets) var.getValue()).getValue();
+
+ // update the hashtable with the new answer
+ serviceHash.put(name, index);
+
+ // perform the GetNext on the just received answer
+ pdu = new GetNextPdu(context);
+ pdu.addObserver(this);
+ pdu.addOid(oid);
+ try
+ {
+ pdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+ else
+ {
+ // the GetNext loop has ended
+ lastUpdateDate = new Date();
+ isGetNextInFlight = false;
+ firePropertyChange("serviceNames", null, null);
+ }
+ }
+ else
+ {
+ // the GetNext loop has ended
+ lastUpdateDate = new Date();
+ isGetNextInFlight = false;
+ firePropertyChange("serviceNames", null, null);
+ }
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/beans/NTSharedResBean.java b/src/main/java/uk/co/westhawk/snmp/beans/NTSharedResBean.java
new file mode 100644
index 0000000..5baac9a
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/beans/NTSharedResBean.java
@@ -0,0 +1,335 @@
+// NAME
+// $RCSfile: NTSharedResBean.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.13 $
+// CREATED
+// $Date: 2006/01/25 18:08:56 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.beans;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+import java.awt.*;
+import java.util.*;
+import java.text.*;
+import java.lang.*;
+import java.io.*;
+import java.beans.*;
+
+/**
+ *
+ * This bean collects the names of the shared resources installed on
+ * a NT server. The NT mib is described in the
+ *
+ * LAN Manager MIB II for Windows NT Objects .
+ *
+ * You will have to register to the MSDN before accessing this page.
+ *
+ *
+ *
+ * The properties in the parent classes should be set, before calling
+ * the action() method. Via a PropertyChangeEvent the application/applet
+ * will be notified.
+ *
+ *
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setCommunityName
+ * @see SNMPRunBean#setUpdateInterval
+ * @see SNMPBean#addPropertyChangeListener
+ * @see SNMPBean#action
+ * @see GetNextPdu
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.13 $ $Date: 2006/01/25 18:08:56 $
+ *
+ */
+public class NTSharedResBean extends SNMPRunBean implements Observer
+{
+ private static final String version_id =
+ "@(#)$Id: NTSharedResBean.java,v 1.13 2006/01/25 18:08:56 birgit Exp $ Copyright Westhawk Ltd";
+
+ public final static String svShareName = "1.3.6.1.4.1.77.1.2.27.1.1";
+
+ private int svShareName_len;
+ private GetNextPdu pdu;
+ private Hashtable resourceHash;
+
+ private boolean isGetNextInFlight;
+ private Date lastUpdateDate = null;
+
+
+/**
+ * The default constructor.
+ */
+public NTSharedResBean()
+{
+ resourceHash = new Hashtable();
+ svShareName_len = svShareName.length();
+}
+
+/**
+ * The constructor that will set the host and the port no.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ */
+public NTSharedResBean(String h, int p)
+{
+ this(h, p, null);
+}
+
+/**
+ * The constructor that will set the host, the port no and the local
+ * bind address.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @param b the local bind address
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setBindAddress
+ *
+ * @since 4_14
+ */
+public NTSharedResBean(String h, int p, String b)
+{
+ this();
+ setHost(h);
+ setPort(p);
+ setBindAddress(b);
+}
+
+/**
+ * Returns the date of the moment when this bean was last updated.
+ * This might be null when the first time the update was not finished.
+ *
+ * @return the last update date
+ */
+public Date getLastUpdateDate()
+{
+ return lastUpdateDate;
+}
+
+/**
+ * Returns the indices of the NT shared resources.
+ * The OID of this shared resource is a concatenation of the
+ * name (svShareName) OID and the shared resource specific index.
+ * The index should be used to get the other properties of this resource.
+ *
+ * @see #getIndex(String)
+ * @see #svShareName
+ */
+public Enumeration getIndices()
+{
+ return resourceHash.elements();
+}
+
+/**
+ * Returns the index of one of the resources.
+ * The OID of this shared resource is a concatenation of the
+ * name (svShareName) OID and the shared resource specific index.
+ * The index should be used to get the other properties of this resource.
+ *
+ * @param name The name of the resource
+ * @return the resource index, might be null if no resource with such name
+ * exists
+ * @see #getIndices
+ * @see #getNames
+ */
+public String getIndex(String name)
+{
+ String ret = null;
+ if (name != null)
+ {
+ ret = (String) resourceHash.get(name);
+ }
+ return ret;
+}
+
+/**
+ * Returns the names of the NT shared resources (the list
+ * of svShareName).
+ */
+public Enumeration getNames()
+{
+ return resourceHash.keys();
+}
+
+/**
+ * Returns the number of NT shared resources.
+ */
+public synchronized int getCount()
+{
+ return resourceHash.size();
+}
+
+/**
+ * This method starts the action of the bean. It will initialises
+ * all variables before starting.
+ *
+ * @see SNMPBean#action
+ */
+public void action()
+{
+ if (isHostPortReachable())
+ {
+ resourceHash.clear();
+ lastUpdateDate = new Date();
+ isGetNextInFlight = false;
+ setRunning(true);
+ }
+}
+
+/**
+ * Implements the running of the bean.
+ *
+ * It will send the Pdu, if the previous one is not still in flight.
+ *
+ * @see SNMPRunBean#isRunning()
+ */
+public void run()
+{
+ while (context != null && isRunning())
+ {
+ if (isGetNextInFlight == false)
+ {
+ // start the GetNext loop again
+ isGetNextInFlight = true;
+ pdu = new GetNextPdu(context);
+ pdu.addObserver(this);
+ pdu.addOid(svShareName);
+ try
+ {
+ pdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+
+ try
+ {
+ Thread.sleep(interval);
+ }
+ catch (InterruptedException ix)
+ {
+ ;
+ }
+ }
+}
+
+/**
+ * This method is called when the Pdu response is received. When all
+ * answers are received it will fire the property change event.
+ *
+ * The answers are stored in a hashtable, this is done because the speed
+ * can only be calculated with the previous answer.
+ *
+ * @see SNMPBean#addPropertyChangeListener
+ */
+public void update(Observable obs, Object ov)
+{
+ varbind var;
+ String hashKey;
+ String oid, index, name;
+
+ pdu = (GetNextPdu) obs;
+ if (pdu.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ var = (varbind) ov;
+ oid = var.getOid().toString();
+ if (oid.startsWith(svShareName))
+ {
+ // index is the part of the oid AFTER the svShareName
+ index = oid.substring(svShareName_len+1);
+
+ name = ((AsnOctets) var.getValue()).getValue();
+
+ // update the hashtable with the new answer
+ resourceHash.put(name, index);
+
+ // perform the GetNext on the just received answer
+ pdu = new GetNextPdu(context);
+ pdu.addObserver(this);
+ pdu.addOid(oid);
+ try
+ {
+ pdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+ else
+ {
+ // the GetNext loop has ended
+ lastUpdateDate = new Date();
+ isGetNextInFlight = false;
+ firePropertyChange("resourceNames", null, null);
+ }
+ }
+ else
+ {
+ // the GetNext loop has ended
+ lastUpdateDate = new Date();
+ isGetNextInFlight = false;
+ firePropertyChange("resourceNames", null, null);
+ }
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/beans/NTUserNamesBean.java b/src/main/java/uk/co/westhawk/snmp/beans/NTUserNamesBean.java
new file mode 100644
index 0000000..8ab5f10
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/beans/NTUserNamesBean.java
@@ -0,0 +1,327 @@
+// NAME
+// $RCSfile: NTUserNamesBean.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.13 $
+// CREATED
+// $Date: 2006/01/25 18:08:56 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.beans;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+import java.awt.*;
+import java.util.*;
+import java.text.*;
+import java.lang.*;
+import java.io.*;
+import java.beans.*;
+
+/**
+ *
+ * This bean collects the names of the network users installed on
+ * a NT server. The NT mib is described in the
+ *
+ * LAN Manager MIB II for Windows NT Objects .
+ *
+ * You will have to register to the MSDN before accessing this page.
+ *
+ *
+ *
+ * The properties in the parent classes should be set, before calling
+ * the action() method. Via a PropertyChangeEvent the application/applet
+ * will be notified.
+ *
+ *
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setCommunityName
+ * @see SNMPRunBean#setUpdateInterval
+ * @see SNMPBean#addPropertyChangeListener
+ * @see SNMPBean#action
+ * @see GetNextPdu
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.13 $ $Date: 2006/01/25 18:08:56 $
+ *
+ */
+public class NTUserNamesBean extends SNMPRunBean implements Observer
+{
+ private static final String version_id =
+ "@(#)$Id: NTUserNamesBean.java,v 1.13 2006/01/25 18:08:56 birgit Exp $ Copyright Westhawk Ltd";
+
+ public final static String svUserName = "1.3.6.1.4.1.77.1.2.25.1.1";
+
+ private int svUserName_len;
+ private GetNextPdu pdu;
+ private Hashtable userHash;
+
+ private boolean isGetNextInFlight;
+ private Date lastUpdateDate = null;
+
+
+/**
+ * The default constructor.
+ */
+public NTUserNamesBean()
+{
+ userHash = new Hashtable();
+ svUserName_len = svUserName.length();
+}
+
+/**
+ * The constructor that will set the host and the port no.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ */
+public NTUserNamesBean(String h, int p)
+{
+ this(h, p, null);
+}
+
+/**
+ * The constructor that will set the host, the port no and the local
+ * bind address.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @param b the local bind address
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setBindAddress
+ *
+ * @since 4_14
+ */
+public NTUserNamesBean(String h, int p, String b)
+{
+ this();
+ setHost(h);
+ setPort(p);
+ setBindAddress(b);
+}
+
+/**
+ * Returns the date of the moment when this bean was last updated.
+ * This might be null when the first time the update was not finished.
+ *
+ * @return the last update date
+ */
+public Date getLastUpdateDate()
+{
+ return lastUpdateDate;
+}
+
+/**
+ * Returns the indices of the NT network users.
+ * The OID of this network user is a concatenation of the
+ * name (svUserName) OID and the network user specific index.
+ * The index should be used to get the other properties of this user.
+ *
+ * @see #getIndex(String)
+ * @see #svUserName
+ */
+public Enumeration getIndices()
+{
+ return userHash.elements();
+}
+
+/**
+ * Returns the index of one of the users.
+ * The OID of this network user is a concatenation of the
+ * name (svUserName) OID and the network user specific index.
+ * The index should be used to get the other properties of this user.
+ *
+ * @param name The name of the user
+ * @return the user index, might be null if no user with such name
+ * exists
+ * @see #getIndices
+ * @see #getNames
+ */
+public String getIndex(String name)
+{
+ return (String) userHash.get(name);
+}
+
+/**
+ * Returns the names of the NT network users (the list
+ * of svUserName).
+ */
+public Enumeration getNames()
+{
+ return userHash.keys();
+}
+
+/**
+ * Returns the number of NT network users.
+ */
+public synchronized int getCount()
+{
+ return userHash.size();
+}
+
+/**
+ * This method starts the action of the bean. It will initialises
+ * all variables before starting.
+ */
+public void action()
+{
+ if (isHostPortReachable())
+ {
+ userHash.clear();
+ lastUpdateDate = new Date();
+ isGetNextInFlight = false;
+ setRunning(true);
+ }
+}
+
+/**
+ * Implements the running of the bean.
+ *
+ * It will send the Pdu, if the previous one is not still in flight.
+ * @see SNMPRunBean#isRunning()
+ */
+public void run()
+{
+ while (context != null && isRunning())
+ {
+ if (isGetNextInFlight == false)
+ {
+ // start the GetNext loop again
+ isGetNextInFlight = true;
+ pdu = new GetNextPdu(context);
+ pdu.addObserver(this);
+ pdu.addOid(svUserName);
+ try
+ {
+ pdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+
+ try
+ {
+ Thread.sleep(interval);
+ }
+ catch (InterruptedException ix)
+ {
+ ;
+ }
+ }
+}
+
+/**
+ * This method is called when the Pdu response is received. When all
+ * answers are received it will fire the property change event.
+ *
+ * The answers are stored in a hashtable, this is done because the speed
+ * can only be calculated with the previous answer.
+ *
+ * @see SNMPBean#addPropertyChangeListener
+ */
+public void update(Observable obs, Object ov)
+{
+ varbind var;
+ String hashKey;
+ String oid, index, name;
+
+ pdu = (GetNextPdu) obs;
+ if (pdu.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ var = (varbind) ov;
+ oid = var.getOid().toString();
+ if (oid.startsWith(svUserName))
+ {
+ // index is the part of the oid AFTER the svUserName
+ index = oid.substring(svUserName_len+1);
+
+ name = ((AsnOctets) var.getValue()).getValue();
+
+ // update the hashtable with the new answer
+ userHash.put(name, index);
+
+ // perform the GetNext on the just received answer
+ pdu = new GetNextPdu(context);
+ pdu.addObserver(this);
+ pdu.addOid(oid);
+ try
+ {
+ pdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+ else
+ {
+ // the GetNext loop has ended
+ lastUpdateDate = new Date();
+ isGetNextInFlight = false;
+ firePropertyChange("userNames", null, null);
+ }
+ }
+ else
+ {
+ // the GetNext loop has ended
+ lastUpdateDate = new Date();
+ isGetNextInFlight = false;
+ firePropertyChange("userNames", null, null);
+ }
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/beans/NcdPerfDataBean.java b/src/main/java/uk/co/westhawk/snmp/beans/NcdPerfDataBean.java
new file mode 100644
index 0000000..deb21a3
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/beans/NcdPerfDataBean.java
@@ -0,0 +1,897 @@
+// NAME
+// $RCSfile: NcdPerfDataBean.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.12 $
+// CREATED
+// $Date: 2006/01/17 17:43:53 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.beans;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+import java.awt.*;
+import java.util.*;
+import java.text.*;
+import java.lang.*;
+import java.io.*;
+import java.beans.*;
+
+/**
+ *
+ * This bean collects information about a
+ * IBM Network Computer.
+ *
+ *
+ *
+ * It provide the following data:
+ *
+ *
+ * - the speed of the Ethernet Card
+ * - the available memory in bytes
+ * - the name of the user that is logged in
+ *
+ *
+ *
+ * A message will be set if some of the data is not available
+ *
+ *
+ *
+ * This class uses the NCDware v3.2 MIB, which was very kindly provided
+ * to me by Network Computing Devices, inc
+ * (NCD). This MIB is an extention of the older versions of the
+ * MIB
+ *
+ *
+ *
+ * The properties in the parent classes should be set, before calling
+ * the action() method. Via a PropertyChangeEvent the application/applet
+ * will be notified.
+ *
+ *
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setCommunityName
+ * @see #setUpdateInterval(int)
+ * @see #setUpdateInterval(String)
+ * @see SNMPBean#addPropertyChangeListener
+ * @see SNMPBean#action
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.12 $ $Date: 2006/01/17 17:43:53 $
+ */
+public class NcdPerfDataBean extends SNMPBean
+ implements PropertyChangeListener
+{
+ private static final String version_id =
+ "@(#)$Id: NcdPerfDataBean.java,v 1.12 2006/01/17 17:43:53 birgit Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * Used as propertyName when a propertyChangeEvent is fired because
+ * the speed was updated
+ */
+ public final static String speedPropertyName = "Speed";
+
+ /**
+ * Used as propertyName when a propertyChangeEvent is fired because
+ * the memory was updated
+ */
+ public final static String memoryPropertyName = "Memory";
+
+ /**
+ * Used as propertyName when a propertyChangeEvent is fired because
+ * the user name was updated
+ */
+ public final static String userPropertyName = "User";
+
+ /**
+ * Used as propertyName when a propertyChangeEvent is fired because
+ * a message was set
+ */
+ public final static String messagePropertyName = "Message";
+
+ /**
+ * Used as name when no one is logged in.
+ */
+ public final static String noLogin = "no one is logged in";
+
+ /**
+ * Used as name when the name is not available.
+ */
+ public final static String noName = "not available";
+
+
+ private ethernet ethernetData;
+ private user userData;
+ private memory memoryData;
+
+ private Date lastUpdateDate = null;
+
+ private int interval = 3000;
+ private long speed = -1;
+ private long memoryAvail = -1;
+ private String userName = "";
+
+/**
+ * The default constructor.
+ */
+public NcdPerfDataBean()
+{
+}
+
+/**
+ * Returns the speed (bits per second) of the ethernet card interface.
+ * @return the speed (b/s)
+ */
+public long getSpeed()
+{
+ return speed;
+}
+
+/**
+ * Returns the amount of RAM memory in bytes which is
+ * currently available.
+ *
+ * @return the memory in bytes
+ */
+public long getMemory()
+{
+ return memoryAvail;
+}
+
+/**
+ * Returns the login name of the user that is logged in.
+ *
+ * @return the user name
+ * @see #noLogin
+ * @see #noName
+ */
+public String getUserName()
+{
+ return userName;
+}
+
+/**
+ * Returns the update interval. This is the interval that the
+ * bean will sleep between 2 requests.
+ *
+ * @return the update interval in msec
+ * @see #setUpdateInterval(int)
+ * @see #setUpdateInterval(String)
+ */
+public int getUpdateInterval()
+{
+ return interval;
+}
+
+/**
+ * Sets the update interval. This is the interval that the
+ * bean will sleep between 2 requests.
+ * The default will be 3000 (= 3 sec).
+ *
+ * @param i the interval in msec
+ * @see #getUpdateInterval
+ * @see #setUpdateInterval(String)
+ */
+public void setUpdateInterval(int i)
+{
+ if (interval != i)
+ {
+ interval = i;
+ }
+}
+
+/**
+ * Sets the update interval as String.
+ *
+ * @param i the interval in msec as String
+ * @see #getUpdateInterval
+ * @see #setUpdateInterval(int)
+ */
+public void setUpdateInterval(String i)
+{
+ int iNo;
+ try
+ {
+ iNo = Integer.valueOf(i.trim()).intValue();
+ setUpdateInterval(iNo);
+ }
+ catch (NumberFormatException exp)
+ {
+ }
+}
+
+/**
+ * Returns the date of the moment when this bean was last updated.
+ * This might be null when the first time the update was not finished.
+ *
+ * @return the last update date
+ */
+public Date getLastUpdateDate()
+{
+ return lastUpdateDate;
+}
+
+/**
+ * This method starts sending the SNMP request. All properties should be
+ * set before this method is called.
+ *
+ * The actual sending will take place in the run method.
+ * It makes a new snmp context and initialises all variables before
+ * starting.
+ */
+public void action()
+{
+ if (isHostPortReachable())
+ {
+ lastUpdateDate = new Date();
+
+ if (ethernetData != null)
+ {
+ ethernetData.setRunning(false);
+ }
+ if (userData != null)
+ {
+ userData.setRunning(false);
+ }
+ if (memoryData != null)
+ {
+ memoryData.setRunning(false);
+ }
+ ethernetData = new ethernet(host, port, community, interval, context);
+ userData = new user(host, port, community, interval, context);
+ memoryData = new memory(host, port, community, interval, context);
+
+ ethernetData.addPropertyChangeListener(this);
+ userData.addPropertyChangeListener(this);
+ memoryData.addPropertyChangeListener(this);
+ }
+}
+
+protected void setMessage(String st)
+{
+ message = st;
+ firePropertyChange (NcdPerfDataBean.messagePropertyName,
+ null, message);
+}
+
+/**
+ * This method is called when a new value of the speed, memory, user or
+ * message is available. It will propagate this event to any listeners.
+ *
+ * @see #speedPropertyName
+ * @see #memoryPropertyName
+ * @see #userPropertyName
+ * @see #messagePropertyName
+ */
+public void propertyChange(PropertyChangeEvent e)
+{
+ Object src = e.getSource();
+ Object oldV = e.getOldValue();
+ Object newV= e.getNewValue();
+ String propName = e.getPropertyName();
+
+ if (propName.equals(messagePropertyName))
+ {
+ setMessage((String) newV);
+ }
+ else
+ {
+ if (src == ethernetData)
+ {
+ speed = ((Long) newV).longValue();
+ }
+ else if (src == userData)
+ {
+ userName = (String) newV;
+ }
+ else if (src == memoryData)
+ {
+ memoryAvail = ((Long) newV).longValue();
+ }
+
+ firePropertyChange (e.getPropertyName(), oldV, newV);
+ }
+}
+
+}
+
+
+/**
+ *
+ * This class is the super class of the classes ethernet, user and
+ * memory.
+ *
+ *
+ * @see user
+ * @see ethernet
+ * @see memory
+ */
+abstract class ncdPart extends SNMPRunBean
+{
+ Thread me;
+ protected boolean isPduInFlight;
+
+public abstract void doPdu()
+throws PduException, IOException;
+
+public ncdPart (String h, int p, String c, int i, SnmpContext con)
+{
+ // reuse the context of the NcdPrefData class, so do not call
+ // isHostPortReachable() !
+ context = con;
+ setHost(h);
+ setPort(p);
+ setCommunityName(c);
+ setUpdateInterval(i);
+
+ action();
+}
+
+protected void setMessage(String st)
+{
+ message = st;
+ firePropertyChange (NcdPerfDataBean.messagePropertyName,
+ null, message);
+}
+
+public void action()
+{
+ setRunning(true);
+}
+
+/**
+ *
+ * @see SNMPRunBean#isRunning()
+ */
+public void run()
+{
+ while (context != null && isRunning())
+ {
+ if (isPduInFlight == false)
+ {
+ isPduInFlight = true;
+ try
+ {
+ doPdu();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+
+ try
+ {
+ Thread.sleep(interval);
+ }
+ catch (InterruptedException ix)
+ {
+ ;
+ }
+ }
+}
+
+}
+
+/**
+ *
+ * This class collects information about the ethernet card.
+ *
+ *
+ *
+ * The first time it will search the interface table to find the entry
+ * describing the ethernet card. After it has been found, it will ask
+ * for the information to calculate the speed.
+ *
+ *
+ *
+ * If the ethernet card is not found, this class assumes that it is not
+ * available at all, and will not try again.
+ *
+ *
+ * @see user
+ * @see memory
+ */
+class ethernet extends ncdPart implements Observer
+{
+ private final static int ethernetType = 6;
+ private final static int statusUp = 1;
+
+ private final static String sysUpTime = "1.3.6.1.2.1.1.3.0";
+ private final static String ifIndex = "1.3.6.1.2.1.2.2.1.1";
+ private final static String ifType = "1.3.6.1.2.1.2.2.1.3";
+ private final static String ifOperStatus = "1.3.6.1.2.1.2.2.1.8";
+ private final static String ifInOctets = "1.3.6.1.2.1.2.2.1.10";
+ private final static String ifOutOctets = "1.3.6.1.2.1.2.2.1.16";
+
+ private long speed = -1;
+ private long prevSpeed = -1;
+ private long prevSys = -1;
+ private int prevOper = -1;
+ private long prevInO = -1;
+ private long prevOutO = -1;
+ private int index = -1;
+
+ GetNextPdu_vec typePdu;
+ GetPdu_vec ethernetPdu;
+
+ private boolean first = true;
+ private boolean foundEthernet = false;
+
+public ethernet (String h, int p, String c, int i, SnmpContext con)
+{
+ super(h, p, c, i, con);
+ first = true;
+ foundEthernet = false;
+
+ speed = -1;
+ prevSpeed = -1;
+ prevSys = -1;
+ prevOper = -1;
+ prevInO = -1;
+ prevOutO = -1;
+}
+
+public long getSpeed()
+{
+ return speed;
+}
+
+public void doPdu() throws PduException, IOException
+{
+ if (first)
+ {
+ // first go looking which interface is the ethernet one
+ typePdu = new GetNextPdu_vec(context, 2);
+ typePdu.addObserver(this);
+ typePdu.addOid(ifIndex);
+ typePdu.addOid(ifType);
+ typePdu.send();
+
+ first = false;
+ }
+ else if (foundEthernet)
+ {
+ ethernetPdu = new GetPdu_vec(context, 5);
+ ethernetPdu.addObserver(this);
+ ethernetPdu.addOid(sysUpTime);
+ ethernetPdu.addOid(ifType + "." + index);
+ ethernetPdu.addOid(ifOperStatus + "." + index);
+ ethernetPdu.addOid(ifInOctets + "." + index);
+ ethernetPdu.addOid(ifOutOctets + "." + index);
+ ethernetPdu.send();
+ }
+}
+
+public void update(Observable obs, Object ov)
+{
+ varbind [] vars;
+
+ if (obs == typePdu)
+ {
+ if (typePdu.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ vars = (varbind[]) ov;
+ if (vars[0].getOid().toString().startsWith(ifIndex))
+ {
+ int i = ((AsnInteger) vars[0].getValue()).getValue();
+ int t = ((AsnInteger) vars[1].getValue()).getValue();
+
+ if (t == ethernetType)
+ {
+ // found it!
+ index = i;
+ foundEthernet = true;
+ isPduInFlight = false;
+ }
+ else
+ {
+ // not found it, ask for the next one
+ typePdu = new GetNextPdu_vec(context, 2);
+ typePdu.addObserver(this);
+ typePdu.addOid(vars[0]);
+ typePdu.addOid(vars[1]);
+ try
+ {
+ typePdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+ }
+ else
+ {
+ setMessage("Ethernet interface not available!");
+ }
+ }
+ else
+ {
+ setMessage("Ethernet interface not available!");
+ }
+ }
+ else
+ {
+ speed = -1;
+ int oper = -1;
+ if (ethernetPdu.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ vars = (varbind[]) ov;
+
+ long sys = ((AsnUnsInteger) vars[0].getValue()).getValue();
+ int t = ((AsnInteger) vars[1].getValue()).getValue();
+ oper = ((AsnInteger) vars[2].getValue()).getValue();
+ long inO = ((AsnUnsInteger) vars[3].getValue()).getValue();
+ long outO = ((AsnUnsInteger) vars[4].getValue()).getValue();
+
+ if (t == ethernetType)
+ {
+ if (oper == statusUp && prevOper == statusUp)
+ {
+ long tdif = (sys - prevSys);
+ if (tdif != 0)
+ {
+ speed = ((inO - prevInO) + (outO - prevOutO))
+ / tdif * 100;
+
+ firePropertyChange (NcdPerfDataBean.speedPropertyName,
+ new Long(prevSpeed),
+ new Long(speed));
+ }
+ }
+
+ prevSys = sys;
+ prevInO = inO;
+ prevOutO = outO;
+ }
+ else
+ {
+ // the index has changed, start searching again
+ first = true;
+ foundEthernet = false;
+ }
+ }
+ prevSpeed = speed;
+ prevOper = oper;
+
+ isPduInFlight = false;
+ }
+}
+
+}
+
+/**
+ *
+ * This class collects information about the user that is logged in.
+ *
+ *
+ *
+ * The first time it will search the NCD environment table to find the
+ * entry describing the environment variable USER. After it has been found,
+ * it will ask for the information to calculate the speed.
+ *
+ *
+ *
+ * When it cannot be found, it will try to see the difference between
+ * the situation where nobody is logged in and the situation where such
+ * information will never be avaible since it does not concern a NCD.
+ *
+ *
+ *
+ * It is not so easy as it may seem. If the machine is shut off, it seem
+ * if the machine is not a NCD.
+ *
+ *
+ * @see ethernet
+ * @see memory
+ */
+class user extends ncdPart implements Observer
+{
+ private final static String USER = "USER";
+
+ private final static String ncdPrefEnvVarTableIndex =
+ "1.3.6.1.4.1.82.2.3.15.54.1.1";
+ private final static String ncdPrefEnvVarTableName =
+ "1.3.6.1.4.1.82.2.3.15.54.1.2";
+ private final static String ncdPrefEnvVarTableValue =
+ "1.3.6.1.4.1.82.2.3.15.54.1.3";
+
+ private int index = -1;
+ private String name = "";
+ private String prevName = "";
+
+ GetNextPdu_vec namePdu;
+ GetPdu_vec userPdu;
+
+ private boolean first = true;
+ private boolean isNcd = false;
+ private boolean foundUser = false;
+
+public user (String h, int p, String c, int i, SnmpContext con)
+{
+ super(h, p, c, i, con);
+ first = true;
+ isNcd = false;
+ foundUser = false;
+
+ userPdu = null;
+ name = "";
+ prevName = "";
+}
+
+public String getUserName()
+{
+ return name;
+}
+
+public void doPdu() throws PduException, IOException
+{
+ if (first
+ ||
+ (isNcd && !foundUser))
+ {
+ // first go looking which interface is the ethernet one
+ namePdu = new GetNextPdu_vec(context, 3);
+ namePdu.addObserver(this);
+ namePdu.addOid(ncdPrefEnvVarTableIndex);
+ namePdu.addOid(ncdPrefEnvVarTableName);
+ namePdu.addOid(ncdPrefEnvVarTableValue);
+ namePdu.send();
+
+ first = false;
+ }
+ else if (foundUser)
+ {
+ userPdu = new GetPdu_vec(context, 3);
+ userPdu.addObserver(this);
+ userPdu.addOid(ncdPrefEnvVarTableIndex + "." + index);
+ userPdu.addOid(ncdPrefEnvVarTableName + "." + index);
+ userPdu.addOid(ncdPrefEnvVarTableValue + "." + index);
+ userPdu.send();
+ }
+}
+
+public void update(Observable obs, Object ov)
+{
+ varbind [] vars;
+
+ if (obs == namePdu)
+ {
+
+ if (namePdu.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ vars = (varbind[]) ov;
+ if (vars[0].getOid().toString().startsWith(ncdPrefEnvVarTableIndex))
+ {
+ // as soon as one response concerns the NCD environment
+ // table, I assume it concerns a NCD machine.
+ isNcd = true;
+
+ int i = ((AsnInteger) vars[0].getValue()).getValue();
+ String n = ((AsnOctets) vars[1].getValue()).getValue();
+ String v = "";
+ if (vars[2].getValue() instanceof AsnOctets)
+ {
+ v = ((AsnOctets) vars[2].getValue()).getValue();
+ }
+
+ if (n.equals(USER))
+ {
+ // found it!
+ index = i;
+ foundUser = true;
+ name = v;
+ isPduInFlight = false;
+ }
+ else
+ {
+ // not found it, ask for the next one
+ namePdu = new GetNextPdu_vec(context, 3);
+ namePdu.addObserver(this);
+ namePdu.addOid(vars[0]);
+ namePdu.addOid(vars[1]);
+ namePdu.addOid(vars[2]);
+ try
+ {
+ namePdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+ }
+ else
+ {
+ if (isNcd)
+ {
+ name = NcdPerfDataBean.noLogin;
+ }
+ else
+ {
+ name = NcdPerfDataBean.noName;
+ }
+ if (!name.equals(prevName))
+ {
+ firePropertyChange (NcdPerfDataBean.userPropertyName,
+ prevName, name);
+ }
+
+ prevName = name;
+ isPduInFlight = false;
+ }
+ }
+ else
+ {
+ prevName = name;
+ isPduInFlight = false;
+ }
+ }
+ else
+ {
+ name = "";
+ if (userPdu.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ vars = (varbind[]) ov;
+
+ int i = ((AsnInteger) vars[0].getValue()).getValue();
+ String n = ((AsnOctets) vars[1].getValue()).getValue();
+ String v = "";
+ if (vars[2].getValue() instanceof AsnOctets)
+ {
+ v = ((AsnOctets) vars[2].getValue()).getValue();
+ }
+
+
+ name = v;
+ if (!name.equals(prevName))
+ {
+ firePropertyChange (NcdPerfDataBean.userPropertyName,
+ prevName, name);
+ }
+
+ }
+ else
+ {
+ first = true;
+ isNcd = true;
+ foundUser = false;
+ }
+
+ prevName = name;
+ isPduInFlight = false;
+ }
+}
+
+}
+
+/**
+ *
+ * This class collects information about the available memory.
+ *
+ *
+ *
+ * If this information is not available, probably because it is not a
+ * NCD machine, this class will not try again.
+ *
+ *
+ * @see ethernet
+ * @see user
+ */
+class memory extends ncdPart implements Observer
+{
+ private final static String ncdSysMemAvail =
+ "1.3.6.1.4.1.82.2.1.1.2.0";
+
+ GetPdu memoryPdu;
+ private long memory = -1;
+ private long prevMemory = -1;
+
+ private boolean first = true;
+ private boolean isAvailable = false;
+
+public memory (String h, int p, String c, int i, SnmpContext con)
+{
+ super(h, p, c, i, con);
+
+ first = true;
+ isAvailable = false;
+}
+
+public long getMemory()
+{
+ return memory;
+}
+
+public void doPdu() throws PduException, IOException
+{
+ if (first || isAvailable)
+ {
+ memoryPdu = new GetPdu(context);
+ memoryPdu.addOid(ncdSysMemAvail);
+ memoryPdu.addObserver(this);
+ first = false;
+ }
+}
+
+public void update(Observable obs, Object ov)
+{
+ varbind var;
+
+ memory = -1;
+ if (memoryPdu.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ var = (varbind) ov;
+
+ memory = ((AsnUnsInteger) var.getValue()).getValue();
+
+ firePropertyChange (NcdPerfDataBean.memoryPropertyName,
+ new Long(prevMemory),
+ new Long(memory));
+
+ isAvailable = true;
+ }
+ else
+ {
+ setMessage("Memory data not available!");
+ }
+ prevMemory = memory;
+ isPduInFlight = false;
+}
+
+}
+
diff --git a/src/main/java/uk/co/westhawk/snmp/beans/OneInterfaceBean.java b/src/main/java/uk/co/westhawk/snmp/beans/OneInterfaceBean.java
new file mode 100644
index 0000000..bbc6d19
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/beans/OneInterfaceBean.java
@@ -0,0 +1,290 @@
+// NAME
+// $RCSfile: OneInterfaceBean.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.14 $
+// CREATED
+// $Date: 2006/01/25 18:08:56 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.beans;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+import java.awt.*;
+import java.util.*;
+import java.text.*;
+import java.lang.*;
+import java.io.*;
+import java.beans.*;
+
+/**
+ *
+ * This bean collects information about one interface.
+ *
+ *
+ *
+ * The properties in the parent classes should be set, before calling
+ * the action() method. Via a PropertyChangeEvent the application/applet
+ * will be notified.
+ *
+ *
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setCommunityName
+ * @see SNMPRunBean#setUpdateInterval
+ * @see #setIndex(int)
+ * @see SNMPBean#addPropertyChangeListener
+ * @see SNMPBean#action
+ * @see InterfaceGetNextPdu
+ * @see InterfaceIndexesBean
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.14 $ $Date: 2006/01/25 18:08:56 $
+ */
+public class OneInterfaceBean extends SNMPRunBean implements Observer
+{
+ private static final String version_id =
+ "@(#)$Id: OneInterfaceBean.java,v 1.14 2006/01/25 18:08:56 birgit Exp $ Copyright Westhawk Ltd";
+
+ private InterfaceGetNextPdu pdu, prev;
+
+ private boolean isPduInFlight;
+ private Date lastUpdateDate = null;
+
+ private int index = 1;
+ private String descr = "";
+ private String operState = "";
+ private long speed = -1;
+
+
+/**
+ * The default constructor.
+ */
+public OneInterfaceBean()
+{
+}
+
+/**
+ * The constructor that will set the host and the port no.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ */
+public OneInterfaceBean(String h, int p)
+{
+ this(h, p, null);
+}
+
+/**
+ * The constructor that will set the host, the port no and the local
+ * bind address.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @param b the local bind address
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setBindAddress
+ *
+ * @since 4_14
+ */
+public OneInterfaceBean(String h, int p, String b)
+{
+ this();
+ setHost(h);
+ setPort(p);
+ setBindAddress(b);
+}
+
+/**
+ * Sets the index of the interface that will be requested.
+ * @param i the index
+ * @see #getIndex()
+ */
+public void setIndex(int i)
+{
+ if (index != i)
+ {
+ index = i;
+ }
+}
+
+/**
+ * Returns the index of the interface.
+ * @return the index
+ * @see #setIndex(int)
+ */
+public int getIndex()
+{
+ return index;
+}
+
+/**
+ * Returns the description of the interface.
+ * @return the description
+ */
+public String getDescription()
+{
+ return descr;
+}
+
+/**
+ * Returns the operation state of the interface.
+ * @return the operation state
+ */
+public String getOperStatusString()
+{
+ return operState;
+}
+
+/**
+ * Returns the speed (bits per second) of the interface.
+ * @return the speed
+ */
+public long getSpeed()
+{
+ return speed;
+}
+
+/**
+ * Returns the date of the moment when this bean was last updated.
+ * This might be null when the first time the update was not finished.
+ *
+ * @return the last update date
+ */
+public Date getLastUpdateDate()
+{
+ return lastUpdateDate;
+}
+
+/**
+ * This method starts sending the SNMP request. All properties should be
+ * set before this method is called.
+ *
+ * The actual sending will take place in the run method.
+ * It makes a new snmp context and initialises all variables before
+ * starting.
+ */
+public void action()
+{
+ if (isHostPortReachable())
+ {
+ lastUpdateDate = new Date();
+ isPduInFlight = false;
+ setRunning(true);
+ }
+}
+
+
+/**
+ * The run method according to the Runnable interface.
+ * This method will send the Pdu request, if the previous one is not
+ * still in flight.
+ * @see SNMPRunBean#isRunning()
+ */
+public void run()
+{
+ while (context != null && isRunning())
+ {
+ if (isPduInFlight == false)
+ {
+ isPduInFlight = true;
+ prev = pdu;
+ try
+ {
+ pdu = new InterfaceGetNextPdu(context);
+ pdu.addObserver(this);
+ pdu.addOids(index-1);
+ pdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+
+ try
+ {
+ Thread.sleep(interval);
+ }
+ catch (InterruptedException ix)
+ {
+ ;
+ }
+ }
+}
+
+/**
+ * The update method according to the Observer interface, it will be
+ * called when the Pdu response is received.
+ * The speed is calculated with the previous answer, after that the
+ * property change event is fired.
+ *
+ * @see SNMPBean#addPropertyChangeListener
+ */
+public void update(Observable obs, Object ov)
+{
+ if (pdu.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ if (prev != null)
+ {
+ speed = pdu.getSpeed(prev);
+ }
+
+ descr = pdu.getIfDescr();
+ operState = pdu.getIfOperStatusStr();
+
+ lastUpdateDate = new Date();
+ isPduInFlight = false;
+ firePropertyChange("Interface", null, null);
+ }
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/beans/OneNTPrintQBean.java b/src/main/java/uk/co/westhawk/snmp/beans/OneNTPrintQBean.java
new file mode 100644
index 0000000..81897f5
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/beans/OneNTPrintQBean.java
@@ -0,0 +1,290 @@
+// NAME
+// $RCSfile: OneNTPrintQBean.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.13 $
+// CREATED
+// $Date: 2006/01/25 18:08:56 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.beans;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+import java.awt.*;
+import java.util.*;
+import java.text.*;
+import java.lang.*;
+import java.io.*;
+import java.beans.*;
+
+/**
+ *
+ * This bean collects information about one NT print queue installed
+ * on a NT server. The NT mib is described in the
+ *
+ * LAN Manager MIB II for Windows NT Objects .
+ *
+ * You will have to register to the MSDN before accessing this page.
+ *
+ *
+ *
+ * The properties in the parent classes should be set, before calling
+ * the action() method. Via a PropertyChangeEvent the application/applet
+ * will be notified.
+ *
+ *
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setCommunityName
+ * @see SNMPRunBean#setUpdateInterval
+ * @see #setIndex(String)
+ * @see SNMPBean#addPropertyChangeListener
+ * @see SNMPBean#action
+ * @see GetPdu_vec
+ * @see NTPrintQBean
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.13 $ $Date: 2006/01/25 18:08:56 $
+ */
+public class OneNTPrintQBean extends SNMPRunBean implements Observer
+{
+ private static final String version_id =
+ "@(#)$Id: OneNTPrintQBean.java,v 1.13 2006/01/25 18:08:56 birgit Exp $ Copyright Westhawk Ltd";
+
+ private GetPdu_vec pdu;
+
+ private boolean isPduInFlight;
+ private Date lastUpdateDate = null;
+
+ private String index = "";
+ private String name = "";
+ private int jobs = 0;
+
+ private final static int NR_OID = 2;
+ private final static String svPrintQName =
+ "1.3.6.1.4.1.77.1.2.29.1.1";
+ private final static String svPrintQNumJobs =
+ "1.3.6.1.4.1.77.1.2.29.1.2";
+
+/**
+ * The default constructor.
+ */
+public OneNTPrintQBean()
+{
+}
+
+/**
+ * The constructor that will set the host and the port no.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ */
+public OneNTPrintQBean(String h, int p)
+{
+ this(h, p, null);
+}
+
+/**
+ * The constructor that will set the host, the port no and the local
+ * bind address.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @param b the local bind address
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setBindAddress
+ *
+ * @since 4_14
+ */
+public OneNTPrintQBean(String h, int p, String b)
+{
+ this();
+ setHost(h);
+ setPort(p);
+ setBindAddress(b);
+}
+
+
+/**
+ * Sets the index of the NT print queue that will be requested.
+ * @param ind the index
+ * @see #getIndex()
+ * @see NTPrintQBean#getIndex(String)
+ */
+public void setIndex(String ind)
+{
+ if (ind != null && ind.length() > 0)
+ {
+ index = ind;
+ }
+}
+
+/**
+ * Returns the index of the NT print queue.
+ * @return the index
+ * @see #setIndex(String)
+ */
+public String getIndex()
+{
+ return index;
+}
+
+/**
+ * Returns the name of the NT print queue.
+ * @return the name
+ */
+public String getName()
+{
+ return name;
+}
+
+/**
+ * Returns the number of jobs currently in this NT print queue.
+ * @return the number of jobs
+ */
+public int getNumJobs()
+{
+ return jobs;
+}
+
+/**
+ * Returns the date of the moment when this bean was last updated.
+ * This might be null when the first time the update was not finished.
+ *
+ * @return the last update date
+ */
+public Date getLastUpdateDate()
+{
+ return lastUpdateDate;
+}
+
+/**
+ * This method starts sending the SNMP request. All properties should be
+ * set before this method is called.
+ *
+ * The actual sending will take place in the run method.
+ * It makes a new snmp context and initialises all variables before
+ * starting.
+ */
+public void action()
+{
+ if (isHostPortReachable())
+ {
+ lastUpdateDate = new Date();
+ isPduInFlight = false;
+ setRunning(true);
+ }
+}
+
+
+/**
+ * The run method according to the Runnable interface.
+ * This method will send the Pdu request, if the previous one is not
+ * still in flight.
+ * @see SNMPRunBean#isRunning()
+ */
+public void run()
+{
+ while (context != null && isRunning())
+ {
+ String ind = getIndex();
+ if (isPduInFlight == false && ind != null && ind.length() > 0)
+ {
+ isPduInFlight = true;
+ pdu = new GetPdu_vec(context, NR_OID);
+ pdu.addObserver(this);
+ pdu.addOid(svPrintQName + "." + ind);
+ pdu.addOid(svPrintQNumJobs + "." + ind);
+ try
+ {
+ pdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+
+ try
+ {
+ Thread.sleep(interval);
+ }
+ catch (InterruptedException ix)
+ {
+ ;
+ }
+ }
+}
+
+/**
+ * The update method according to the Observer interface, it will be
+ * called when the Pdu response is received.
+ * The property change event is fired.
+ *
+ * @see SNMPBean#addPropertyChangeListener
+ */
+public void update(Observable obs, Object ov)
+{
+ pdu = (GetPdu_vec) obs;
+ varbind [] varbinds = (varbind []) ov;
+
+ if (pdu.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ name = ((AsnOctets) varbinds[0].getValue()).getValue();
+ jobs = ((AsnInteger) varbinds[1].getValue()).getValue();
+
+ lastUpdateDate = new Date();
+ isPduInFlight = false;
+ firePropertyChange("NTService", null, null);
+ }
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/beans/OneNTServiceBean.java b/src/main/java/uk/co/westhawk/snmp/beans/OneNTServiceBean.java
new file mode 100644
index 0000000..0d89d26
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/beans/OneNTServiceBean.java
@@ -0,0 +1,371 @@
+// NAME
+// $RCSfile: OneNTServiceBean.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.13 $
+// CREATED
+// $Date: 2006/01/25 18:08:56 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.beans;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+import java.awt.*;
+import java.util.*;
+import java.text.*;
+import java.lang.*;
+import java.io.*;
+import java.beans.*;
+
+/**
+ *
+ * This bean collects information about one NT network service installed
+ * on a NT server. The NT mib is described in the
+ *
+ * LAN Manager MIB II for Windows NT Objects .
+ *
+ * You will have to register to the MSDN before accessing this page.
+ *
+ *
+ *
+ * The properties in the parent classes should be set, before calling
+ * the action() method. Via a PropertyChangeEvent the application/applet
+ * will be notified.
+ *
+ *
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setCommunityName
+ * @see SNMPRunBean#setUpdateInterval
+ * @see #setIndex(String)
+ * @see SNMPBean#addPropertyChangeListener
+ * @see SNMPBean#action
+ * @see GetPdu_vec
+ * @see NTServiceNamesBean
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.13 $ $Date: 2006/01/25 18:08:56 $
+ */
+public class OneNTServiceBean extends SNMPRunBean implements Observer
+{
+ private static final String version_id =
+ "@(#)$Id: OneNTServiceBean.java,v 1.13 2006/01/25 18:08:56 birgit Exp $ Copyright Westhawk Ltd";
+
+ private GetPdu_vec pdu;
+
+ private boolean isPduInFlight;
+ private Date lastUpdateDate = null;
+
+ private String index = "";
+ private String name = "";
+ private String instState = "";
+ private String operState = "";
+ private boolean canUninst = false;
+ private boolean canPause = false;
+
+ private final static int NR_OID = 5;
+ private final static String svSvcName =
+ "1.3.6.1.4.1.77.1.2.3.1.1";
+ private final static String svSvcInstalledState =
+ "1.3.6.1.4.1.77.1.2.3.1.2";
+ private final static String svSvcOperatingState =
+ "1.3.6.1.4.1.77.1.2.3.1.3";
+ private final static String svSvcCanBeUninstalled =
+ "1.3.6.1.4.1.77.1.2.3.1.4";
+ private final static String svSvcCanBePaused =
+ "1.3.6.1.4.1.77.1.2.3.1.5";
+
+ public final static String msg_inst_state[] =
+ {
+ "unknown",
+ "uninstalled", // 1
+ "install pending", // 2
+ "uninstall pending", // 3
+ "installed" // 4
+ };
+
+ public final static String msg_oper_state[] =
+ {
+ "unknown",
+ "active", // 1
+ "continue pending", // 2
+ "pause pending", // 3
+ "paused" // 4
+ };
+
+ public final static int cannot_be_uninstalled = 1;
+ public final static int can_be_uninstalled = 2;
+
+ public final static int cannot_be_paused = 1;
+ public final static int can_be_paused = 2;
+
+
+/**
+ * The default constructor.
+ */
+public OneNTServiceBean()
+{
+}
+
+/**
+ * The constructor that will set the host and the port no.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ */
+public OneNTServiceBean(String h, int p)
+{
+ this(h, p, null);
+}
+
+/**
+ * The constructor that will set the host, the port no and the local
+ * bind address.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @param b the local bind address
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setBindAddress
+ *
+ * @since 4_14
+ */
+public OneNTServiceBean(String h, int p, String b)
+{
+ this();
+ setHost(h);
+ setPort(p);
+ setBindAddress(b);
+}
+
+/**
+ * Sets the index of the NT network service that will be requested.
+ * @param ind the index
+ * @see #getIndex()
+ * @see NTServiceNamesBean#getIndex(String)
+ */
+public void setIndex(String ind)
+{
+ if (ind != null && ind.length() > 0)
+ {
+ index = ind;
+ }
+}
+
+/**
+ * Returns the index of the NT network service.
+ * @return the index
+ * @see #setIndex(String)
+ */
+public String getIndex()
+{
+ return index;
+}
+
+/**
+ * Returns the name of the NT network service.
+ * @return the name
+ */
+public String getName()
+{
+ return name;
+}
+
+/**
+ * Returns the installation status of the NT network service.
+ * @return the installation status
+ * @see #msg_inst_state
+ */
+public String getInstalledState()
+{
+ return instState;
+}
+
+/**
+ * Returns the operating status of the NT network service.
+ * @return the operating status
+ * @see #msg_oper_state
+ */
+public String getOperatingState()
+{
+ return operState;
+}
+
+/**
+ * Returns if the NT network service can be uninstalled.
+ * @return the uninstalled option
+ * @see #can_be_uninstalled
+ * @see #cannot_be_uninstalled
+ */
+public boolean getCanBeUninstalled()
+{
+ return canUninst;
+}
+
+/**
+ * Returns if the NT network service can be paused.
+ * @return the paused option
+ * @see #can_be_paused
+ * @see #cannot_be_paused
+ */
+public boolean getCanBePaused()
+{
+ return canPause;
+}
+
+/**
+ * Returns the date of the moment when this bean was last updated.
+ * This might be null when the first time the update was not finished.
+ *
+ * @return the last update date
+ */
+public Date getLastUpdateDate()
+{
+ return lastUpdateDate;
+}
+
+/**
+ * This method starts sending the SNMP request. All properties should be
+ * set before this method is called.
+ *
+ * The actual sending will take place in the run method.
+ * It makes a new snmp context and initialises all variables before
+ * starting.
+ */
+public void action()
+{
+ if (isHostPortReachable())
+ {
+ lastUpdateDate = new Date();
+ isPduInFlight = false;
+ setRunning(true);
+ }
+}
+
+
+/**
+ * The run method according to the Runnable interface.
+ * This method will send the Pdu request, if the previous one is not
+ * still in flight.
+ * @see SNMPRunBean#isRunning()
+ */
+public void run()
+{
+ while (context != null && isRunning())
+ {
+ String ind = getIndex();
+ if (isPduInFlight == false && ind != null && ind.length() > 0)
+ {
+ isPduInFlight = true;
+ pdu = new GetPdu_vec(context, NR_OID);
+ pdu.addObserver(this);
+ pdu.addOid(svSvcName + "." + ind);
+ pdu.addOid(svSvcInstalledState + "." + ind);
+ pdu.addOid(svSvcOperatingState + "." + ind);
+ pdu.addOid(svSvcCanBeUninstalled + "." + ind);
+ pdu.addOid(svSvcCanBePaused + "." + ind);
+ try
+ {
+ pdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+
+ try
+ {
+ Thread.sleep(interval);
+ }
+ catch (InterruptedException ix)
+ {
+ ;
+ }
+ }
+}
+
+/**
+ * The update method according to the Observer interface, it will be
+ * called when the Pdu response is received.
+ * The property change event is fired.
+ *
+ * @see SNMPBean#addPropertyChangeListener
+ */
+public void update(Observable obs, Object ov)
+{
+ int nr;
+ pdu = (GetPdu_vec) obs;
+ varbind [] varbinds = (varbind []) ov;
+
+ if (pdu.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ name = ((AsnOctets) varbinds[0].getValue()).getValue();
+
+ nr = ((AsnInteger) varbinds[1].getValue()).getValue();
+ instState = msg_inst_state[nr];
+
+ nr = ((AsnInteger) varbinds[2].getValue()).getValue();
+ operState = msg_oper_state[nr];
+
+ nr = ((AsnInteger) varbinds[3].getValue()).getValue();
+ canUninst = (nr == can_be_uninstalled);
+
+ nr = ((AsnInteger) varbinds[4].getValue()).getValue();
+ canPause = (nr == can_be_paused);
+
+ lastUpdateDate = new Date();
+ isPduInFlight = false;
+ firePropertyChange("NTService", null, null);
+ }
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/beans/OneNTSharedResBean.java b/src/main/java/uk/co/westhawk/snmp/beans/OneNTSharedResBean.java
new file mode 100644
index 0000000..1fc8261
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/beans/OneNTSharedResBean.java
@@ -0,0 +1,318 @@
+// NAME
+// $RCSfile: OneNTSharedResBean.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.13 $
+// CREATED
+// $Date: 2006/01/25 18:08:56 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.beans;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+import java.awt.*;
+import java.util.*;
+import java.text.*;
+import java.lang.*;
+import java.io.*;
+import java.beans.*;
+
+/**
+ *
+ * This bean collects information about one NT shared resource installed
+ * on a NT server. The NT mib is described in the
+ *
+ * LAN Manager MIB II for Windows NT Objects .
+ *
+ * You will have to register to the MSDN before accessing this page.
+ *
+ *
+ *
+ * The properties in the parent classes should be set, before calling
+ * the action() method. Via a PropertyChangeEvent the application/applet
+ * will be notified.
+ *
+ *
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setCommunityName
+ * @see SNMPRunBean#setUpdateInterval
+ * @see #setIndex(String)
+ * @see SNMPBean#addPropertyChangeListener
+ * @see SNMPBean#action
+ * @see GetPdu_vec
+ * @see NTSharedResBean
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.13 $ $Date: 2006/01/25 18:08:56 $
+ */
+public class OneNTSharedResBean extends SNMPRunBean implements Observer
+{
+ private static final String version_id =
+ "@(#)$Id: OneNTSharedResBean.java,v 1.13 2006/01/25 18:08:56 birgit Exp $ Copyright Westhawk Ltd";
+
+ private GetPdu_vec pdu;
+
+ private boolean isPduInFlight;
+ private Date lastUpdateDate = null;
+
+ private String index = "";
+ private String name = "";
+ private String path = "";
+ private String comment = "";
+
+ private final static int NR_OID = 3;
+ private final static String svShareName =
+ "1.3.6.1.4.1.77.1.2.27.1.1";
+ private final static String svSharePath =
+ "1.3.6.1.4.1.77.1.2.27.1.2";
+ private final static String svShareComment =
+ "1.3.6.1.4.1.77.1.2.27.1.3";
+
+/**
+ * The default constructor.
+ */
+public OneNTSharedResBean()
+{
+}
+
+/**
+ * The constructor that will set the host and the port no.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ */
+public OneNTSharedResBean(String h, int p)
+{
+ this(h, p, null);
+}
+
+/**
+ * The constructor that will set the host, the port no and the local
+ * bind address.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @param b the local bind address
+ * @see SNMPBean#setHost
+ * @see SNMPBean#setPort
+ * @see SNMPBean#setBindAddress
+ *
+ * @since 4_14
+ */
+public OneNTSharedResBean(String h, int p, String b)
+{
+ this();
+ setHost(h);
+ setPort(p);
+ setBindAddress(b);
+}
+
+
+/**
+ * Sets the index of the NT shared resource that will be requested.
+ * @param ind the index
+ * @see #getIndex()
+ * @see NTSharedResBean#getIndex(String)
+ */
+public void setIndex(String ind)
+{
+ if (ind != null && ind.length() > 0)
+ {
+ index = ind;
+ }
+}
+
+/**
+ * Returns the index of the NT shared resource.
+ * @return the index
+ * @see #setIndex(String)
+ */
+public String getIndex()
+{
+ return index;
+}
+
+/**
+ * Returns the name of the NT shared resource.
+ * @return the name
+ */
+public String getName()
+{
+ return name;
+}
+
+/**
+ * Returns the local name (path) of the NT shared resource.
+ * @return the path
+ */
+public String getPath()
+{
+ return path;
+}
+
+/**
+ * Returns the comment associated with the NT shared resource.
+ * @return the comment
+ */
+public String getComment()
+{
+ return comment;
+}
+
+/**
+ * Returns the date of the moment when this bean was last updated.
+ * This might be null when the first time the update was not finished.
+ *
+ * @return the last update date
+ */
+public Date getLastUpdateDate()
+{
+ return lastUpdateDate;
+}
+
+/**
+ * This method starts sending the SNMP request. All properties should be
+ * set before this method is called.
+ *
+ * The actual sending will take place in the run method.
+ * It makes a new snmp context and initialises all variables before
+ * starting.
+ */
+public void action()
+{
+ if (isHostPortReachable())
+ {
+ lastUpdateDate = new Date();
+ isPduInFlight = false;
+ setRunning(true);
+ }
+}
+
+
+/**
+ * The run method according to the Runnable interface.
+ * This method will send the Pdu request, if the previous one is not
+ * still in flight.
+ * @see SNMPRunBean#isRunning()
+ */
+public void run()
+{
+ while (context != null && isRunning())
+ {
+ String ind = getIndex();
+ if (isPduInFlight == false && ind != null && ind.length() > 0)
+ {
+ isPduInFlight = true;
+ pdu = new GetPdu_vec(context, NR_OID);
+ pdu.addObserver(this);
+ pdu.addOid(svShareName + "." + ind);
+ pdu.addOid(svSharePath + "." + ind);
+ pdu.addOid(svShareComment + "." + ind);
+ try
+ {
+ pdu.send();
+ }
+ catch (PduException exc)
+ {
+ System.out.println("PduException " + exc.getMessage());
+ }
+ catch (IOException exc)
+ {
+ System.out.println("IOException " + exc.getMessage());
+ }
+ }
+
+ try
+ {
+ Thread.sleep(interval);
+ }
+ catch (InterruptedException ix)
+ {
+ ;
+ }
+ }
+}
+
+/**
+ * The update method according to the Observer interface, it will be
+ * called when the Pdu response is received.
+ * The property change event is fired.
+ *
+ * @see SNMPBean#addPropertyChangeListener
+ */
+public void update(Observable obs, Object ov)
+{
+ pdu = (GetPdu_vec) obs;
+ varbind [] varbinds = (varbind []) ov;
+
+ if (pdu.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ AsnObject asnobj;
+ name = ((AsnOctets) varbinds[0].getValue()).getValue();
+
+ asnobj = varbinds[1].getValue();
+ path = " ";
+ if (asnobj instanceof AsnOctets)
+ {
+ path = ((AsnOctets) asnobj).getValue();
+ }
+
+ asnobj = varbinds[2].getValue();
+ comment = " ";
+ if (asnobj instanceof AsnOctets)
+ {
+ comment = ((AsnOctets) asnobj).getValue();
+ }
+
+
+ lastUpdateDate = new Date();
+ isPduInFlight = false;
+ firePropertyChange("NTService", null, null);
+ }
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/beans/SNMPBean.java b/src/main/java/uk/co/westhawk/snmp/beans/SNMPBean.java
new file mode 100644
index 0000000..9f53f91
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/beans/SNMPBean.java
@@ -0,0 +1,473 @@
+// NAME
+// $RCSfile: SNMPBean.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.12 $
+// CREATED
+// $Date: 2006/01/26 12:38:30 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.beans;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+import java.awt.*;
+import java.util.*;
+import java.text.*;
+import java.lang.*;
+import java.io.*;
+import java.beans.*;
+
+/**
+ *
+ * This bean forms the base of the SNMP beans.
+ *
+ *
+ *
+ * It provides the setting of the properties that are always needed when
+ * sending a SNMP request:
+ *
+ *
+ * - host, default is localhost
+ * - port, default is 161
+ * - community name, default is public
+ * - bindAddr, default is null
+ * - socket type, default is Standard
+ *
+ *
+ *
+ * The bean will only come into action when the method action() is
+ * called. This should be done after the properties have been set.
+ *
+ *
+ *
+ * This bean also provide the methods for adding and removing property
+ * change listeners and firing property change events.
+ *
+ *
+ *
+ * Note: This bean will create a socket. This might result in a
+ * SecurityException because of the Java security policy.
+ *
+ *
+ * -
+ * If you are an applet: you're only connect back to its source web server
+ *
+ * -
+ * If you are an application or servlet: java allows you to send it. The
+ * host might refuse your connection.
+ *
+ *
+ *
+ *
+ * The SNMP request will only succeed if:
+ *
+ *
+ * -
+ * java security policy allows the opening of the socket
+ *
+ * -
+ * the host/port combination is reachable from your location (you can
+ * check that with the ping (command line) command.
+ *
+ * -
+ * the combination of OID and community name is correct
+ *
+ *
+ *
+ * @see SNMPRunBean
+ * @see IsHostReachableBean
+ * @see OneInterfaceBean
+ * @see InterfaceIndexesBean
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.12 $ $Date: 2006/01/26 12:38:30 $
+ *
+ */
+public abstract class SNMPBean
+{
+ private static final String version_id =
+ "@(#)$Id: SNMPBean.java,v 1.12 2006/01/26 12:38:30 birgit Exp $ Copyright Westhawk Ltd";
+
+ protected SnmpContext context = null;
+
+ protected String host = "localhost";
+ protected String bindAddr = null;
+ protected int port = 161;
+ protected String community = "public";
+ protected String socketType = SnmpContextBasisFace.STANDARD_SOCKET;
+ protected String message = "";
+
+ protected Vector propertyChangeListener = null;
+
+
+/**
+ * This method should send the SNMP request. All properties should be
+ * set before this method is called.
+ */
+public abstract void action()
+throws PduException, IOException;
+
+/**
+ * The default constructor.
+ */
+public SNMPBean()
+{
+ propertyChangeListener = new Vector();
+}
+
+/**
+ * The constructor that will set the host and the port no.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @see #setHost
+ * @see #setPort
+ */
+public SNMPBean(String h, int p)
+{
+ this(h, p, null, SnmpContextBasisFace.STANDARD_SOCKET);
+}
+
+/**
+ * The constructor that will set the host, the port no and the local
+ * bind address.
+ *
+ * @param h the hostname
+ * @param p the port no
+ * @param b the local bind address
+ * @param t the socket type
+ * @see #setHost
+ * @see #setPort
+ * @see #setBindAddress
+ * @see #setSocketType
+ *
+ * @since 4_14
+ */
+public SNMPBean(String h, int p, String b, String t)
+{
+ this();
+ setHost(h);
+ setPort(p);
+ setBindAddress(b);
+ setSocketType(t);
+}
+
+/**
+ * Returns the host (name or ipadress) which is addressed. This is the
+ * host where the SNMP server is running.
+ * @return the name of the host
+ * @see #setHost
+ */
+public String getHost()
+{
+ return host;
+}
+
+/**
+ * Sets the host (name or ipadress) which will be asked for the SNMP request.
+ * This is the host where the SNMP server is running.
+ * The default is localhost.
+ *
+ * This bean will only start the request when action is called.
+ *
+ * @see #getHost
+ */
+public void setHost(String h)
+{
+ if (h != null && h.length() > 0 && !host.equals(h))
+ {
+ host = h;
+ }
+}
+
+/**
+ * Returns the port no which is used. That is the no of the port on the
+ * host where the SNMP server is running.
+ * @see #setPort(int)
+ * @see #setPort(String)
+ */
+public int getPort()
+{
+ return port;
+}
+
+/**
+ * Sets the port no which is used. That should be the no of the port on the
+ * host where the SNMP server is running.
+ * The default is 161.
+ *
+ * This bean will only start the request when action is called.
+ *
+ * @param p The number of the port
+ * @see #getPort
+ * @see #setPort(String)
+ */
+public void setPort(int p)
+{
+ if (p > 0 && port != p)
+ {
+ port = p;
+ }
+}
+
+/**
+ * Sets the port no which is used as a String.
+ *
+ * @param p The number of the port as a String
+ * @see #getPort
+ * @see #setPort(int)
+ */
+public void setPort(String p)
+{
+ int pNo;
+ try
+ {
+ pNo = Integer.valueOf(p.trim()).intValue();
+ setPort(pNo);
+ }
+ catch (NumberFormatException exp)
+ {
+ }
+}
+
+/**
+ * Returns the community name that is used to send the SNMP request.
+ * @see #setCommunityName
+ */
+public String getCommunityName()
+{
+ return community;
+}
+
+/**
+ * Sets the community name that is used to send the SNMP request. The
+ * default is public.
+ * @see #getCommunityName
+ */
+public void setCommunityName(String c)
+{
+ if (c != null & !community.equals(c))
+ {
+ community = c;
+ if (context != null)
+ {
+ context.setCommunity(community);
+ }
+ }
+}
+
+/**
+ * Returns the local bind address.
+ * @return the name of the local bind address
+ * @see #setBindAddress
+ * @since 4_14
+ */
+public String getBindAddress()
+{
+ return bindAddr;
+}
+
+/**
+ * Sets the local bind address.
+ * The default is null.
+ *
+ * This bean will only start the request when action is called.
+ *
+ * @see #getBindAddress
+ * @since 4_14
+ */
+public void setBindAddress(String b)
+{
+ bindAddr = b;
+}
+
+
+
+/**
+ * Returns the socket type.
+ * @return the socket type.
+ * @see #setSocketType
+ * @since 4_14
+ */
+public String getSocketType()
+{
+ return socketType;
+}
+
+/**
+ * Sets socket type.
+ * The default is null.
+ *
+ * This bean will only start the request when action is called.
+ *
+ * @see #getSocketType
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @since 4_14
+ */
+public void setSocketType(String t)
+{
+ socketType = t;
+}
+
+
+
+/**
+ * Indicates whether the host is reachable.
+ * This method will try to make a new SnmpContext, if this works, it is
+ * reachable.
+ * If it does not work, the message will be set.
+ *
+ * @see SnmpContext
+ */
+protected boolean isHostPortReachable()
+{
+ boolean res = true;
+ if (host != null
+ &&
+ host.length() > 0
+ &&
+ port > 0)
+ {
+ try
+ {
+ if (context != null)
+ {
+ context.destroy();
+ context = null;
+ }
+
+ context = new SnmpContext(host, port, bindAddr, socketType);
+ context.setCommunity(community);
+ setMessage("Connection to host " + host
+ + " is made succesfully");
+ }
+ catch (IOException exc)
+ {
+ res = false;
+ setMessage("IOException: " + exc.getMessage());
+ }
+ catch (RuntimeException exc)
+ {
+ res = false;
+ setMessage("RuntimeException: " + exc.getMessage());
+ }
+ }
+ else
+ {
+ res = false;
+ }
+ return res;
+}
+
+/**
+ * Returns the message (if any). The message is used to give the user
+ * feedback if anything is happened with the request or the connection.
+ *
+ * @return the message
+ */
+public String getMessage()
+{
+ return message;
+}
+
+/**
+ * Returns the message (if any). The message is used to give the user
+ * feedback if anything is happened (usually when something went wrong)
+ * with the connection.
+ *
+ * @param st the message string
+ * @see #getMessage()
+ */
+protected void setMessage(String st)
+{
+ message = st;
+}
+
+
+/**
+ * Add a property change listener.
+ * @see #removePropertyChangeListener
+ */
+public synchronized void addPropertyChangeListener(PropertyChangeListener l)
+{
+ propertyChangeListener.addElement(l);
+}
+
+/**
+ * Remove a property change listener.
+ * @see #addPropertyChangeListener
+ */
+public synchronized void removePropertyChangeListener(PropertyChangeListener l)
+{
+ propertyChangeListener.removeElement(l);
+}
+
+/**
+ * Fire the property event.
+ *
+ * @see #removePropertyChangeListener
+ * @see #addPropertyChangeListener
+ * @see PropertyChangeEvent
+ * @see PropertyChangeListener
+ */
+protected void firePropertyChange(String property, Object old_v, Object new_v)
+{
+ Vector listeners;
+ synchronized(this)
+ {
+ listeners = (Vector) propertyChangeListener.clone();
+ }
+
+ PropertyChangeEvent event = new PropertyChangeEvent(this,
+ property, old_v, new_v);
+
+ int sz = listeners.size();
+ for (int i=0; iTim Panton
+ */
+
+package uk.co.westhawk.snmp.beans;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+import java.awt.*;
+import java.util.*;
+import java.text.*;
+import java.lang.*;
+import java.io.*;
+import java.beans.*;
+
+/**
+ *
+ * This bean forms the base of the Runnable SNMP beans.
+ * It extends the SNMPBean class.
+ *
+ *
+ *
+ * This bean is used when SNMP requests have to be sent continuously,
+ * instead of just once.
+ * For that purpose the update interval setUpdateInterval() can
+ * be set. The default value is 2000, i.e. 2 msec.
+ *
+ *
+ *
+ * When implementing an extention of this class, the method
+ * action() should
+ * be implemented. It should somehow start the run by calling
+ * setRunning(true).
+ * Stopping the thread might be called by the application or applet.
+ *
+ *
+ * @see OneInterfaceBean
+ * @see InterfaceIndexesBean
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.9 $ $Date: 2006/02/09 14:20:09 $
+ */
+public abstract class SNMPRunBean extends SNMPBean implements Runnable
+{
+ private static final String version_id =
+ "@(#)$Id: SNMPRunBean.java,v 1.9 2006/02/09 14:20:09 birgit Exp $ Copyright Westhawk Ltd";
+
+ protected int interval = 2000;
+ protected Thread me = null;
+ protected boolean running = false;
+
+
+/**
+ * Method according to the Runnable interface. This method should
+ * provide the continuous sending of a Pdu, with a sleeping interval set
+ * by setUpdateInterval().
+ *
+ * @see #setUpdateInterval(int)
+ * @see #setRunning
+ */
+public abstract void run();
+
+
+/**
+ * The default constructor
+ */
+public SNMPRunBean()
+{
+}
+
+
+/**
+ * Returns the update interval. This is the interval that the
+ * bean will sleep between 2 requests.
+ *
+ * @return the update interval in msec
+ * @see #setUpdateInterval(int)
+ * @see #setUpdateInterval(String)
+ */
+public int getUpdateInterval()
+{
+ return interval;
+}
+
+/**
+ * Sets the update interval. This is the interval that the
+ * bean will sleep between 2 requests.
+ * The default will be 2000 (= 2 sec).
+ *
+ * @param i the interval in msec
+ * @see #getUpdateInterval
+ * @see #setUpdateInterval(String)
+ */
+public void setUpdateInterval(int i)
+{
+ if (interval != i)
+ {
+ interval = i;
+ }
+}
+
+/**
+ * Sets the update interval as String.
+ *
+ * @param i the interval in msec as String
+ * @see #getUpdateInterval
+ * @see #setUpdateInterval(int)
+ */
+public void setUpdateInterval(String i)
+{
+ int iNo;
+ try
+ {
+ iNo = Integer.valueOf(i.trim()).intValue();
+ setUpdateInterval(iNo);
+ }
+ catch (NumberFormatException exp)
+ {
+ }
+}
+
+/**
+ * Returns if the bean is running.
+ * @return the running mode
+ * @see #setRunning
+ */
+public boolean isRunning()
+{
+ return running;
+}
+
+/**
+ * Starts or stops the thread.
+ * Starting this thread should be a result of calling the action()
+ * method, so should be implemented in the action method of any child
+ * class.
+ *
+ * Stopping this thread may be called by the application of applet.
+ * This method does NOT call Thread.stop() anymore. Every run() method
+ * should check isRunning(), so that when setRunning(false) is called,
+ * the run() method will stop running!!
+ *
+ * @see #isRunning
+ * @see SNMPBean#action()
+ */
+public synchronized void setRunning(boolean b)
+{
+ if (running != b)
+ {
+ running = b;
+
+ if (running)
+ {
+ if (me == null)
+ {
+ me = new Thread(this);
+ me.setPriority(Thread.MIN_PRIORITY);
+ }
+ me.start();
+ }
+ }
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/beans/UsmBeingDiscoveredBean.java b/src/main/java/uk/co/westhawk/snmp/beans/UsmBeingDiscoveredBean.java
new file mode 100644
index 0000000..0f96825
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/beans/UsmBeingDiscoveredBean.java
@@ -0,0 +1,313 @@
+// NAME
+// $RCSfile: UsmBeingDiscoveredBean.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.8 $
+// CREATED
+// $Date: 2009/03/05 15:51:42 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.beans;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+import uk.co.westhawk.snmp.event.*;
+import uk.co.westhawk.snmp.util.*;
+import java.util.*;
+
+/**
+ *
+ * This bean handles being discovered as an authoritative engine by an
+ * non-authoritative engine (SNMPv3 only).
+ *
+ *
+ *
+ * The discovery process consists of two steps:
+ * 1. first the SNMP engine ID has to be discovered,
+ * second the timeline details of the SNMP engine ID have to be discovered.
+ *
+ * 2. For the last step the username of the principal is needed.
+ *
+ * All these parameters should be provided by (your own) UsmAgent.
+ *
+ *
+ *
+ * This class is not very efficient. The private context
+ * discEngineIdContextIn will be the same for every SnmpContextv3 that
+ * creates this bean.
+ *
+ *
+ *
+ * See SNMP-USER-BASED-SM-MIB.
+ *
+ *
+ * @see SnmpContextv3#addRequestPduListener
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.8 $ $Date: 2009/03/05 15:51:42 $
+ */
+public class UsmBeingDiscoveredBean implements RequestPduListener
+{
+ private static final String version_id =
+ "@(#)$Id: UsmBeingDiscoveredBean.java,v 1.8 2009/03/05 15:51:42 birgita Exp $ Copyright Westhawk Ltd";
+
+ private UsmAgent usmAgent = null;
+ private SnmpContextv3 context = null;
+
+ // the context to receive incoming requests
+ private SnmpContextv3Discovery discEngineIdContextIn;
+ private SnmpContextv3Discovery discTimeLineContextIn;
+
+ // the context to send the answer back
+ private SnmpContextv3 discEngineIdContextOut;
+ private SnmpContextv3 discTimeLineContextOut;
+
+/**
+ * Constructor.
+ *
+ * @param myUsmAgent The usmAgent that will provide all the
+ * authoritative engine parameters
+ * @param myContext The context
+ *
+ * @see SnmpContextv3#addRequestPduListener
+ */
+public UsmBeingDiscoveredBean(SnmpContextv3 myContext, UsmAgent myUsmAgent)
+throws java.io.IOException
+{
+ usmAgent = myUsmAgent;
+ context = myContext;
+
+ if (AsnObject.debug > 4)
+ {
+ System.out.println(getClass().getName() + " Constructor:"
+ + "usmAgent=" + usmAgent.toString()
+ + "context=" + context.toString());
+ }
+ usmAgent.setSnmpContext(context);
+
+ discEngineIdContextIn = new SnmpContextv3Discovery(context.getSendToHostAddress(),
+ context.getPort(), context.getBindAddress(), context.getTypeSocket());
+ discEngineIdContextIn.setUserName("");
+ discEngineIdContextIn.setUseAuthentication(false);
+ discEngineIdContextIn.setUsePrivacy(false);
+ discEngineIdContextIn.setContextEngineId(SnmpUtilities.toBytes(usmAgent.getSnmpEngineId()));
+ discEngineIdContextIn.setContextName("");
+ discEngineIdContextIn.setUsmAgent(usmAgent);
+
+ discTimeLineContextIn = new SnmpContextv3Discovery(context.getSendToHostAddress(),
+ context.getPort(), context.getBindAddress(), context.getTypeSocket());
+ discTimeLineContextIn.setUserName(context.getUserName());
+ discTimeLineContextIn.setUseAuthentication(context.isUseAuthentication());
+ discTimeLineContextIn.setAuthenticationProtocol(context.getAuthenticationProtocol());
+ discTimeLineContextIn.setUserAuthenticationPassword(context.getUserAuthenticationPassword());
+ discTimeLineContextIn.setUsePrivacy(context.isUsePrivacy());
+ discTimeLineContextIn.setPrivacyProtocol(context.getPrivacyProtocol());
+ discTimeLineContextIn.setUserPrivacyPassword(context.getUserPrivacyPassword());
+ discTimeLineContextIn.setContextEngineId(SnmpUtilities.toBytes(usmAgent.getSnmpEngineId()));
+ discTimeLineContextIn.setContextName("");
+ discTimeLineContextIn.setUsmAgent(usmAgent);
+}
+
+/**
+ * @param lcontext The listening context for incoming (discovery) requests
+ * @see SnmpContextv3#addRequestPduListener
+ */
+public void addRequestPduListener(ListeningContextPool lcontext)
+throws java.io.IOException
+{
+ if (AsnObject.debug > 4)
+ {
+ System.out.println(getClass().getName()
+ + ".addRequestPduListener(" + lcontext.toString() + ")");
+ }
+ discEngineIdContextIn.addRequestPduListener(this, lcontext);
+ discTimeLineContextIn.addRequestPduListener(this, lcontext);
+}
+
+/**
+ * @param lcontext Stop listening on this listening context for incoming (discovery) requests
+ * @see SnmpContextv3#removeRequestPduListener
+ */
+public void removeRequestPduListener(ListeningContextPool lcontext)
+throws java.io.IOException
+{
+ if (AsnObject.debug > 4)
+ {
+ System.out.println(getClass().getName()
+ + ".removeRequestPduListener(" + lcontext.toString() + ")");
+ }
+ discEngineIdContextIn.removeRequestPduListener(this, lcontext);
+ discTimeLineContextIn.removeRequestPduListener(this, lcontext);
+}
+
+/**
+ * Receiving an incoming (discovery) PDU request.
+ */
+public void requestPduReceived(RequestPduEvent evt)
+{
+ Object src = evt.getSource();
+ int port = evt.getHostPort();
+ Pdu orgPdu = evt.getPdu();
+ if (src == discEngineIdContextIn)
+ {
+ sendEngineIdReport(orgPdu, port);
+ }
+ else
+ {
+ sendTimeLineReport(orgPdu, port);
+ }
+}
+
+/**
+ * Send back the snmp engine ID.
+ */
+protected void sendEngineIdReport(Pdu orgPdu, int port)
+{
+ if (AsnObject.debug > 4)
+ {
+ System.out.println(getClass().getName() + ".sendEngineIdReport()");
+ }
+
+ try
+ {
+ if (discEngineIdContextOut != null)
+ {
+ discEngineIdContextOut.destroy();
+ }
+ discEngineIdContextOut = new SnmpContextv3(discEngineIdContextIn.getHost(),
+ port, discEngineIdContextIn.getBindAddress(),
+ discEngineIdContextIn.getTypeSocket());
+ discEngineIdContextOut = (SnmpContextv3) discEngineIdContextIn.cloneParameters(discEngineIdContextOut);
+
+ Pdu repPdu = new ReportPdu(discEngineIdContextOut, orgPdu);
+ repPdu.addOid(usmStatsConstants.usmStatsUnknownEngineIDs,
+ new AsnUnsInteger(usmAgent.getUsmStatsUnknownEngineIDs()));
+ repPdu.send();
+ }
+ catch (java.io.IOException iexc)
+ {
+ if (AsnObject.debug > 4)
+ {
+ System.out.println(getClass().getName() + ".sendEngineIdReport(): "
+ + "IOException: " + iexc.getMessage());
+ }
+ }
+ catch (PduException pexc)
+ {
+ if (AsnObject.debug > 4)
+ {
+ System.out.println(getClass().getName() + ".sendEngineIdReport(): "
+ + "PduException: " + pexc.getMessage());
+ }
+ }
+}
+
+
+/**
+ * Send back the time lininess
+ */
+protected void sendTimeLineReport(Pdu orgPdu, int port)
+{
+ if (AsnObject.debug > 4)
+ {
+ System.out.println(getClass().getName() + ".sendTimeLineReport()");
+ }
+
+ try
+ {
+ if (discTimeLineContextOut != null)
+ {
+ discTimeLineContextOut.destroy();
+ }
+ discTimeLineContextOut = new SnmpContextv3(discTimeLineContextIn.getHost(),
+ port, discTimeLineContextIn.getBindAddress(),
+ discTimeLineContextIn.getTypeSocket());
+ discTimeLineContextOut = (SnmpContextv3) discTimeLineContextIn.cloneParameters(discTimeLineContextOut);
+
+ Pdu repPdu = new ReportPdu(discTimeLineContextOut, orgPdu);
+ repPdu.addOid(usmStatsConstants.usmStatsNotInTimeWindows,
+ new AsnUnsInteger(usmAgent.getUsmStatsNotInTimeWindows()));
+ repPdu.send();
+ }
+ catch (java.io.IOException iexc)
+ {
+ if (AsnObject.debug > 4)
+ {
+ System.out.println(getClass().getName() + ".sendTimeLineReport(): "
+ + "IOException: " + iexc.getMessage());
+ }
+ }
+ catch (PduException pexc)
+ {
+ if (AsnObject.debug > 4)
+ {
+ System.out.println(getClass().getName() + ".sendEngineIdReport(): "
+ + "PduException: " + pexc.getMessage());
+ }
+ }
+}
+
+
+/**
+ * Destroys all the contexts in use.
+ */
+public void freeResources()
+{
+ discEngineIdContextIn.destroy();
+ discEngineIdContextIn = null;
+
+ discTimeLineContextIn.destroy();
+ discTimeLineContextIn = null;
+
+ if (discEngineIdContextOut != null)
+ {
+ discEngineIdContextOut.destroy();
+ discEngineIdContextOut = null;
+ }
+ if (discTimeLineContextOut != null)
+ {
+ discTimeLineContextOut.destroy();
+ discTimeLineContextOut = null;
+ }
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/beans/UsmDiscoveryBean.java b/src/main/java/uk/co/westhawk/snmp/beans/UsmDiscoveryBean.java
new file mode 100644
index 0000000..e0ad24c
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/beans/UsmDiscoveryBean.java
@@ -0,0 +1,361 @@
+// NAME
+// $RCSfile: UsmDiscoveryBean.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.21 $
+// CREATED
+// $Date: 2009/03/05 15:51:42 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.beans;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+import java.util.*;
+
+/**
+ *
+ * This bean performs the SNMPv3 USM discovery process.
+ *
+ *
+ *
+ * The process consists of two steps: first the SNMP engine ID has to be
+ * discovered, second the timeline details of the SNMP engine ID have to
+ * be discovered. For the last step the username of the principal is
+ * needed.
+ *
+ *
+ *
+ * See SNMP-USER-BASED-SM-MIB.
+ *
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.21 $ $Date: 2009/03/05 15:51:42 $
+ */
+public class UsmDiscoveryBean
+{
+ private static final String version_id =
+ "@(#)$Id: UsmDiscoveryBean.java,v 1.21 2009/03/05 15:51:42 birgita Exp $ Copyright Westhawk Ltd";
+
+ private SnmpContextv3Pool context;
+ private String userName = null;
+ private String userAuthPassword = null;
+ private String userPrivPassword = null;
+ private int authProtocol, privProtocol;
+ private int retry_intervals[] = {500,1000,2000,5000,5000};
+
+/**
+ * Constructor.
+ *
+ * @param host The host to discover
+ * @param port The port to discover
+ * @see SnmpContextv3#SnmpContextv3(String, int)
+ * @see #startDiscovery()
+ */
+public UsmDiscoveryBean(String host, int port)
+throws java.io.IOException
+{
+ this(host, port, null, SnmpContextBasisFace.STANDARD_SOCKET);
+}
+
+/**
+ * Constructor.
+ *
+ * @param host The host to discover
+ * @param port The port to discover
+ * @param bindAddr The local address the server will bind to
+ * @param typeSocketA The type of socket to use.
+ *
+ * @see SnmpContextv3#SnmpContextv3(String, int, String, String)
+ * @see #startDiscovery()
+ */
+public UsmDiscoveryBean(String host, int port, String bindAddr, String typeSocketA)
+throws java.io.IOException
+{
+ context = new SnmpContextv3Pool(host, port, bindAddr, typeSocketA);
+}
+
+/**
+ * Sets the user's authentication details.
+ * With these details the time line details will be retrieved.
+ * If the user details are not set, only the engine ID will be
+ * discovered.
+ *
+ *
+ * The time line details only need to be known when the user want to
+ * send authenticated message to this SNMP engine.
+ *
+ *
+ * @param newUserName The user name
+ * @param newUserPassword The user authentication password
+ * @param protocol The user authentication protocol
+ *
+ * @see SnmpContextv3#setUserName(String)
+ * @see SnmpContextv3#setUserAuthenticationPassword(String)
+ * @see SnmpContextv3#setAuthenticationProtocol(int)
+ */
+public void setAuthenticationDetails(String newUserName, String newUserPassword,
+ int protocol)
+{
+ userName = newUserName;
+ userAuthPassword = newUserPassword;
+ authProtocol = protocol;
+}
+
+/**
+ * Sets the user's privacy details.
+ * With these details the time line details will be retrieved if needed.
+ *
+ *
+ * The time line details only need to be known when the user want to
+ * send authenticated message to this SNMP engine.
+ *
+ *
+ * @param newUserPassword The user privacy password
+ *
+ * @see SnmpContextv3#setUserPrivacyPassword(String)
+ */
+public void setPrivacyDetails(String newUserPassword, int protocol)
+{
+ userPrivPassword = newUserPassword;
+ privProtocol = protocol;
+}
+
+/**
+ * Sets the retry intervals of the PDU. The length of the array
+ * corresponds with the number of retries. Each entry in the array
+ * is the number of milliseconds of each try.
+ *
+ *
+ * If used, please set before sending!
+ *
+ *
+ * The default is {500, 1000, 2000, 5000, 5000}.
+ * It is good practice to make the interval bigger with each retry,
+ * if the numbers are the same the chance of collision is higher.
+ *
+ * @param rinterval The interval in msec of each retry
+ * @see Pdu#setRetryIntervals(int[])
+ */
+public void setRetryIntervals(int rinterval[])
+{
+ retry_intervals = rinterval;
+}
+
+/**
+ * Starts the discovery. This method will send a Pdu to discover the
+ * SNMP engine ID. Set the user details before calling this method, if
+ * you want the time line details to be discovered as well.
+ *
+ *
+ * This is a blocking call! It will return when it has done the whole
+ * discovery.
+ *
+ *
+ * @see #setAuthenticationDetails(String, String, int)
+ * @see #discoveryEngineId
+ * @see #discoveryTimeLine
+ */
+// Thanks to "Cochran, Steve A." ;
+// freeResources(); is called before throwing an exception
+public void startDiscovery()
+throws PduException, java.io.IOException
+{
+ try
+ {
+ discoveryEngineId();
+ }
+ catch (PduException exc)
+ {
+ // You shouldn't really get an exception when doing engineID
+ // discovery.
+ freeResources(); // <-- Steve
+ throw new PduException("Engine ID discovery: "
+ + exc.getMessage());
+ }
+
+ try
+ {
+ discoveryTimeLine();
+ }
+ catch (PduException exc)
+ {
+ // You can get an exception for authPriv. I noticed that when
+ // testing against MG-SOFT.
+ // Only throw the exception if the timeline was not discovered.
+
+ TimeWindow tWindow = TimeWindow.getCurrent();
+ String engineId =
+ tWindow.getSnmpEngineId(context.getSendToHostAddress(),
+ context.getPort());
+ if (tWindow.isTimeLineKnown(engineId) == false)
+ {
+ freeResources(); // <-- Steve
+ throw new PduException("Timeline discovery: "
+ + exc.getMessage());
+ }
+ }
+
+ if (AsnObject.debug > 4)
+ {
+ System.out.println(getClass().getName() + ".startDiscovery(): "
+ + "Done, context " + context.toString());
+ }
+
+ freeResources();
+}
+
+/**
+ * Destroy the context in use.
+ */
+public void freeResources()
+{
+ context.destroy();
+ context = null;
+}
+
+
+/**
+ * Starts the discovery of the SNMP engine ID.
+ *
+ *
+ * This is a blocking call! It will return when it has done the whole
+ * discovery.
+ *
+ *
+ * @see #startDiscovery
+ * @see #discoveryTimeLine
+ */
+protected void discoveryEngineId()
+throws PduException, java.io.IOException
+{
+ DiscoveryPdu pdu;
+
+ TimeWindow tWindow = TimeWindow.getCurrent();
+ String engineId = tWindow.getSnmpEngineId(context.getHost(),
+ context.getPort());
+
+ // Just check again to be sure
+ if (engineId == null)
+ {
+ if (AsnObject.debug > 4)
+ {
+ System.out.println(getClass().getName() + ".discoveryEngineId(): "
+ + "Starting discovery Engine ID ...");
+ }
+ context.setUserName("");
+ context.setUseAuthentication(false);
+ context.setUsePrivacy(false);
+ context.setContextEngineId(new byte[0]);
+ context.setContextName("");
+
+ pdu = new DiscoveryPdu(context);
+ pdu.setRetryIntervals(retry_intervals);
+ pdu.send();
+ pdu.waitForSelf();
+ varbind [] vars = pdu.getResponseVarbinds();
+ }
+}
+
+/**
+ * Starts the discovery of the Time line.
+ *
+ *
+ * This is a blocking call! It will return when it has done the whole
+ * discovery.
+ *
+ *
+ * @see #startDiscovery
+ * @see #discoveryEngineId
+ */
+protected void discoveryTimeLine()
+throws PduException, java.io.IOException
+{
+ DiscoveryPdu pdu;
+
+ TimeWindow tWindow = TimeWindow.getCurrent();
+ String engineId =
+ tWindow.getSnmpEngineId(context.getSendToHostAddress(),
+ context.getPort());
+
+ // The engineId should be known by now.
+ // Only do timeline discovery if it is not known yet.
+ if (tWindow.isTimeLineKnown(engineId) == false && userName != null)
+ {
+ if (AsnObject.debug > 4)
+ {
+ System.out.println(getClass().getName() + ".discoveryTimeLine(): "
+ + "Starting discovery Timeline ...");
+ }
+ context.setUserName(userName);
+ context.setUserAuthenticationPassword(userAuthPassword);
+ context.setUseAuthentication(true);
+ context.setAuthenticationProtocol(authProtocol);
+ context.setContextEngineId(new byte[0]);
+ context.setContextName("");
+
+ if (userPrivPassword != null)
+ {
+ context.setUsePrivacy(true);
+ context.setUserPrivacyPassword(userPrivPassword);
+ context.setPrivacyProtocol(privProtocol);
+ }
+ else
+ {
+ context.setUsePrivacy(false);
+ }
+
+ pdu = new DiscoveryPdu(context);
+ pdu.setRetryIntervals(retry_intervals);
+ pdu.send();
+ pdu.waitForSelf();
+ varbind [] vars = pdu.getResponseVarbinds();
+
+ if (AsnObject.debug > 4)
+ {
+ System.out.println("Did discovery time line");
+ }
+ }
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/event/DecodedPduEvent.java b/src/main/java/uk/co/westhawk/snmp/event/DecodedPduEvent.java
new file mode 100644
index 0000000..4633e76
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/event/DecodedPduEvent.java
@@ -0,0 +1,131 @@
+// NAME
+// $RCSfile: DecodedPduEvent.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.5 $
+// CREATED
+// $Date: 2006/02/09 14:30:18 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+package uk.co.westhawk.snmp.event;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+
+
+/**
+ * The DecodedPduEvent class. This class is delivered when a pdu is received.
+ *
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.5 $ $Date: 2006/02/09 14:30:18 $
+ */
+public abstract class DecodedPduEvent extends java.util.EventObject
+{
+ private static final String version_id =
+ "@(#)$Id: DecodedPduEvent.java,v 1.5 2006/02/09 14:30:18 birgit Exp $ Copyright Westhawk Ltd";
+
+ protected boolean consumed = false;
+
+ private int hostPort = -1;
+ private Pdu pdu;
+
+/**
+ * The constructor for a decoded pdu event. The SnmpContext classes
+ * will fire decoded pdu events.
+ *
+ * @param source The source (SnmpContext) of the event
+ * @param p The pdu
+ * @param prt The remote port number of the host where the pdu came from
+ *
+ * @see #getHostPort()
+ * @see #getPdu()
+ */
+public DecodedPduEvent(Object source, Pdu p, int prt)
+{
+ super(source);
+ pdu = p;
+ hostPort = prt;
+}
+
+
+
+/**
+ * The remote port number of the host where the pdu came from.
+ *
+ * @return The remote port number of the host or -1.
+ *
+ */
+public int getHostPort()
+{
+ return hostPort;
+}
+
+
+/**
+ * The pdu. The pdu is part of a decoded pdu event.
+ *
+ * @return The decoded Pdu.
+ */
+public Pdu getPdu()
+{
+ return pdu;
+}
+
+/**
+ * Consumes this event so that it will not be sent to any other
+ * listeners.
+ */
+public void consume()
+{
+ consumed = true;
+}
+
+/**
+ * Returns whether or not this event has been consumed.
+ * @see #consume
+ */
+public boolean isConsumed()
+{
+ return consumed;
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/event/RawPduEvent.java b/src/main/java/uk/co/westhawk/snmp/event/RawPduEvent.java
new file mode 100644
index 0000000..62160fc
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/event/RawPduEvent.java
@@ -0,0 +1,173 @@
+// NAME
+// $RCSfile: RawPduEvent.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.5 $
+// CREATED
+// $Date: 2006/02/09 14:30:18 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+package uk.co.westhawk.snmp.event;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+
+
+/**
+ * The RawPduEvent class. This class is delivered when a undecoded pdu
+ * is received.
+ *
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.5 $ $Date: 2006/02/09 14:30:18 $
+ */
+public class RawPduEvent extends java.util.EventObject
+{
+ private static final String version_id =
+ "@(#)$Id: RawPduEvent.java,v 1.5 2006/02/09 14:30:18 birgit Exp $ Copyright Westhawk Ltd";
+
+ protected boolean consumed = false;
+
+ private int version;
+ private String hostAddress;
+ private int hostPort = -1;
+ private byte [] message;
+
+
+/**
+ * The constructor for an undecoded pdu event. The ListeningContext
+ * class will fire undecoded pdu events.
+ *
+ * @param source The source (ListeningContext) of the event
+ * @param v The SNMP version of the pdu
+ * @param hn The IP address of the host where the pdu came from
+ * @param prt The remote port number of the host where the pdu came from
+ * @param mess The pdu in bytes
+ *
+ * @see #getVersion()
+ * @see #getHostAddress()
+ * @see #getHostPort()
+ * @see #getMessage()
+ */
+public RawPduEvent(Object source, int v, String hn, byte [] mess, int prt)
+{
+ super(source);
+ version = v;
+ hostAddress = hn;
+ message = mess;
+ hostPort = prt;
+}
+
+/**
+ * The SNMP version number of the pdu.
+ *
+ * @return The version number.
+ * @see #getHostAddress()
+ * @see #getMessage()
+ * @see SnmpConstants#SNMP_VERSION_1
+ * @see SnmpConstants#SNMP_VERSION_2c
+ * @see SnmpConstants#SNMP_VERSION_3
+ */
+public int getVersion()
+{
+ return version;
+}
+
+/**
+ * The IP address of the host where the pdu came from.
+ * Note, this is not necessarily the same as the IpAddress field in the
+ * SNMPv1 Pdu.
+ *
+ * @return The IP address of the host or null.
+ * @see #getVersion()
+ * @see #getMessage()
+ */
+public String getHostAddress()
+{
+ return hostAddress;
+}
+
+/**
+ * The pdu SNMP message in bytes. This is a copy of the original
+ * message.
+ *
+ * @return The pdu in bytes.
+ * @see #getVersion()
+ * @see #getHostAddress()
+ */
+public byte [] getMessage()
+{
+ return message;
+}
+
+/**
+ * The remote port number of the host where the pdu came from.
+ *
+ * @return The remote port number of the host or -1.
+ * @see #getVersion()
+ * @see #getMessage()
+ *
+ */
+public int getHostPort()
+{
+ return hostPort;
+}
+
+
+/**
+ * Consumes this event so that it will not be sent to any other
+ * listeners.
+ */
+public void consume()
+{
+ consumed = true;
+}
+
+/**
+ * Returns whether or not this event has been consumed.
+ * @see #consume
+ */
+public boolean isConsumed()
+{
+ return consumed;
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/event/RawPduListener.java b/src/main/java/uk/co/westhawk/snmp/event/RawPduListener.java
new file mode 100644
index 0000000..561f1e9
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/event/RawPduListener.java
@@ -0,0 +1,70 @@
+// NAME
+// $RCSfile: RawPduListener.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.3 $
+// CREATED
+// $Date: 2006/01/17 17:59:33 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+package uk.co.westhawk.snmp.event;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+
+/**
+ * The listener interface for receiving raw pdu events.
+ *
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.3 $ $Date: 2006/01/17 17:59:33 $
+ */
+public interface RawPduListener extends java.util.EventListener
+{
+ public static final String version_id =
+ "@(#)$Id: RawPduListener.java,v 1.3 2006/01/17 17:59:33 birgit Exp $ Copyright Westhawk Ltd";
+
+
+/**
+ * Invoked when a pdu is received.
+ */
+public void rawPduReceived(RawPduEvent evt);
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/event/RawPduReceivedSupport.java b/src/main/java/uk/co/westhawk/snmp/event/RawPduReceivedSupport.java
new file mode 100644
index 0000000..1f28f66
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/event/RawPduReceivedSupport.java
@@ -0,0 +1,179 @@
+// NAME
+// $RCSfile: RawPduReceivedSupport.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.5 $
+// CREATED
+// $Date: 2006/02/09 14:30:18 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+package uk.co.westhawk.snmp.event;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.util.*;
+import uk.co.westhawk.snmp.stack.*;
+
+/**
+ * This is a utility class that can be used by classes that support
+ * raw pdu listener functionality.
+ * You can use an instance of this class as a member field
+ * of your class and delegate various work to it.
+ *
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.5 $ $Date: 2006/02/09 14:30:18 $
+ */
+public class RawPduReceivedSupport
+{
+ public static final String version_id =
+ "@(#)$Id: RawPduReceivedSupport.java,v 1.5 2006/02/09 14:30:18 birgit Exp $ Copyright Westhawk Ltd";
+
+ private Object source;
+ private transient Vector pduListeners;
+
+/**
+ * The constructor.
+ *
+ * @param src The source (ListeningContext) of the pdu events when they are fired.
+ */
+public RawPduReceivedSupport(Object src)
+{
+ source = src;
+}
+
+/**
+ * Removes all the listeners.
+ */
+public synchronized void empty()
+{
+ if (pduListeners != null)
+ {
+ pduListeners.removeAllElements();
+ }
+}
+
+/**
+ * Returns the number of listeners.
+ *
+ * @return The number of listeners.
+ */
+public synchronized int getListenerCount()
+{
+ int c=0;
+ if (pduListeners != null)
+ {
+ c = pduListeners.size();
+ }
+ return c;
+}
+
+/**
+ * Adds the specified pdu listener to receive pdus.
+ */
+public synchronized void addRawPduListener(RawPduListener listener)
+{
+ if (pduListeners == null)
+ {
+ pduListeners = new Vector (5);
+ }
+ if (pduListeners.contains(listener) == false)
+ {
+ pduListeners.addElement(listener);
+ }
+}
+
+/**
+ * Removes the specified pdu listener.
+ */
+public synchronized void removeRawPduListener(RawPduListener listener)
+{
+ if (pduListeners != null)
+ {
+ pduListeners.removeElement(listener);
+ }
+}
+
+
+/**
+ * Fires an undecoded pdu event.
+ * The event is fired to all listeners, unless one of them consumes it.
+ * The idea is that for undecoded pdus it is very unlikely that more
+ * than one party (usually SnmpContext objects) is interested.
+ *
+ * @param version The SNMP version of the pdu
+ * @param hostAddress The IP address of the host where the pdu came from
+ * @param hostPort The remote port number of the host where the pdu came from
+ * @param message The pdu in bytes
+ *
+ * @return Whether or not the event has been consumed.
+ */
+public boolean fireRawPduReceived(int version, String hostAddress, int hostPort, byte [] message)
+{
+ boolean isConsumed = false;
+ Vector copyOfListeners = null;
+ if (pduListeners != null)
+ {
+ synchronized (pduListeners)
+ {
+ copyOfListeners = (Vector) pduListeners.clone();
+ }
+ }
+
+ if (copyOfListeners != null)
+ {
+ int l = message.length;
+ int sz = copyOfListeners.size();
+ for (int i=sz-1; i>=0 && isConsumed == false; i--)
+ {
+ RawPduListener listener = (RawPduListener) copyOfListeners.elementAt(i);
+
+ byte [] copyOfMessage = new byte[l];
+ System.arraycopy(message, 0, copyOfMessage, 0, l);
+ RawPduEvent evt = new RawPduEvent(source, version, hostAddress, copyOfMessage, hostPort);
+ listener.rawPduReceived(evt);
+ isConsumed = (evt.isConsumed());
+ }
+ }
+ return isConsumed;
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/event/RequestPduEvent.java b/src/main/java/uk/co/westhawk/snmp/event/RequestPduEvent.java
new file mode 100644
index 0000000..3669caf
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/event/RequestPduEvent.java
@@ -0,0 +1,88 @@
+// NAME
+// $RCSfile: RequestPduEvent.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.5 $
+// CREATED
+// $Date: 2006/02/09 14:30:18 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+package uk.co.westhawk.snmp.event;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+
+
+/**
+ * The RequestPduEvent class. This class is delivered when a pdu is received.
+ *
+ *
+ * RequestPduEvents are fired in case of a GetRequest, SetRequest,
+ * GetNextRequest, GetBulkRequest (SNMPv2c, SNMPv3), Inform
+ * (SNMPv2c, SNMPv3) PDU that could be decoded and matched by one
+ * of the SnmpContext classes.
+ *
+ *
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.5 $ $Date: 2006/02/09 14:30:18 $
+ */
+public class RequestPduEvent extends DecodedPduEvent
+{
+ private static final String version_id =
+ "@(#)$Id: RequestPduEvent.java,v 1.5 2006/02/09 14:30:18 birgit Exp $ Copyright Westhawk Ltd";
+
+/**
+ * The constructor for a decoded request pdu event. The SnmpContext
+ * classes will fire decoded request pdu events.
+ *
+ * @param source The source (SnmpContext) of the event
+ * @param pdu The pdu
+ * @param port The remote port number of the host where the pdu came from
+ *
+ */
+public RequestPduEvent(Object source, Pdu pdu, int port)
+{
+ super(source, pdu, port);
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/event/RequestPduListener.java b/src/main/java/uk/co/westhawk/snmp/event/RequestPduListener.java
new file mode 100644
index 0000000..3321bf9
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/event/RequestPduListener.java
@@ -0,0 +1,70 @@
+// NAME
+// $RCSfile: RequestPduListener.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.3 $
+// CREATED
+// $Date: 2006/01/17 17:59:33 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+package uk.co.westhawk.snmp.event;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+
+/**
+ * The listener interface for receiving decoded request pdu events.
+ *
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.3 $ $Date: 2006/01/17 17:59:33 $
+ */
+public interface RequestPduListener extends java.util.EventListener
+{
+ public static final String version_id =
+ "@(#)$Id: RequestPduListener.java,v 1.3 2006/01/17 17:59:33 birgit Exp $ Copyright Westhawk Ltd";
+
+
+/**
+ * Invoked when a pdu is received.
+ */
+public void requestPduReceived(RequestPduEvent evt);
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/event/RequestPduReceivedSupport.java b/src/main/java/uk/co/westhawk/snmp/event/RequestPduReceivedSupport.java
new file mode 100644
index 0000000..25eb446
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/event/RequestPduReceivedSupport.java
@@ -0,0 +1,165 @@
+// NAME
+// $RCSfile: RequestPduReceivedSupport.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.4 $
+// CREATED
+// $Date: 2006/01/17 17:59:33 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+package uk.co.westhawk.snmp.event;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.util.*;
+import uk.co.westhawk.snmp.stack.*;
+
+/**
+ * This is a utility class that can be used by classes that support
+ * request pdu listener functionality.
+ * You can use an instance of this class as a member field
+ * of your class and delegate various work to it.
+ *
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.4 $ $Date: 2006/01/17 17:59:33 $
+ */
+public class RequestPduReceivedSupport
+{
+ public static final String version_id =
+ "@(#)$Id: RequestPduReceivedSupport.java,v 1.4 2006/01/17 17:59:33 birgit Exp $ Copyright Westhawk Ltd";
+
+ private Object source;
+ private transient Vector pduListeners;
+
+/**
+ * The constructor.
+ *
+ * @param src The source (SnmpContext) of the pdu events when they are fired.
+ */
+public RequestPduReceivedSupport(Object src)
+{
+ source = src;
+}
+
+/**
+ * Removes all the listeners.
+ */
+public synchronized void empty()
+{
+ if (pduListeners != null)
+ {
+ pduListeners.removeAllElements();
+ }
+}
+
+/**
+ * Returns the number of listeners.
+ *
+ * @return The number of listeners.
+ */
+public synchronized int getListenerCount()
+{
+ int c=0;
+ if (pduListeners != null)
+ {
+ c = pduListeners.size();
+ }
+ return c;
+}
+
+/**
+ * Adds the specified pdu listener to receive pdus.
+ */
+public synchronized void addRequestPduListener(RequestPduListener listener)
+{
+ if (pduListeners == null)
+ {
+ pduListeners = new Vector (5);
+ }
+ if (pduListeners.contains(listener) == false)
+ {
+ pduListeners.addElement(listener);
+ }
+}
+
+/**
+ * Removes the specified pdu listener.
+ */
+public synchronized void removeRequestPduListener(RequestPduListener listener)
+{
+ if (pduListeners != null)
+ {
+ pduListeners.removeElement(listener);
+ }
+}
+
+
+/**
+ * Fires a decoded pdu event.
+ * The event is fired to all listeners, whether they consume it or not.
+ *
+ * @param pdu The decoded pdu pdu.
+ */
+public void fireRequestPduReceived(Pdu pdu, int hostPort)
+{
+ Vector copyOfListeners = null;
+ if (pduListeners != null)
+ {
+ synchronized (pduListeners)
+ {
+ copyOfListeners = (Vector) pduListeners.clone();
+ }
+ }
+
+ if (copyOfListeners != null)
+ {
+ int sz = copyOfListeners.size();
+ for (int i=sz-1; i>=0; i--)
+ {
+ RequestPduListener listener = (RequestPduListener) copyOfListeners.elementAt(i);
+
+ RequestPduEvent evt = new RequestPduEvent(source, pdu, hostPort);
+ listener.requestPduReceived(evt);
+ }
+ }
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/event/TrapEvent.java b/src/main/java/uk/co/westhawk/snmp/event/TrapEvent.java
new file mode 100644
index 0000000..3a77b81
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/event/TrapEvent.java
@@ -0,0 +1,81 @@
+// NAME
+// $RCSfile: TrapEvent.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.8 $
+// CREATED
+// $Date: 2006/02/09 14:30:18 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2001 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+package uk.co.westhawk.snmp.event;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+
+
+/**
+ * The TrapEvent class. This class is delivered when a trap is received.
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.8 $ $Date: 2006/02/09 14:30:18 $
+ */
+public class TrapEvent extends DecodedPduEvent
+{
+ private static final String version_id =
+ "@(#)$Id: TrapEvent.java,v 1.8 2006/02/09 14:30:18 birgit Exp $ Copyright Westhawk Ltd";
+
+
+/**
+ * The constructor for a decoded trap pdu event. The SnmpContext
+ * classes will fire decoded trap pdu events.
+ *
+ * @param source The source (SnmpContext) of the event
+ * @param pdu The pdu
+ * @param port The remote port number of the host where the pdu came from
+ *
+ */
+public TrapEvent(Object source, Pdu pdu, int port)
+{
+ super(source, pdu, port);
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/event/TrapListener.java b/src/main/java/uk/co/westhawk/snmp/event/TrapListener.java
new file mode 100644
index 0000000..5827d4f
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/event/TrapListener.java
@@ -0,0 +1,69 @@
+// NAME
+// $RCSfile: TrapListener.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.5 $
+// CREATED
+// $Date: 2006/01/17 17:43:53 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2001 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+package uk.co.westhawk.snmp.event;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+
+/**
+ * The listener interface for receiving decoded trap events.
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.5 $ $Date: 2006/01/17 17:43:53 $
+ */
+public interface TrapListener extends java.util.EventListener
+{
+ public static final String version_id =
+ "@(#)$Id: TrapListener.java,v 1.5 2006/01/17 17:43:53 birgit Exp $ Copyright Westhawk Ltd";
+
+
+/**
+ * Invoked when a trap is received.
+ */
+public void trapReceived(TrapEvent evt);
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/event/TrapReceivedSupport.java b/src/main/java/uk/co/westhawk/snmp/event/TrapReceivedSupport.java
new file mode 100644
index 0000000..7c23890
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/event/TrapReceivedSupport.java
@@ -0,0 +1,165 @@
+// NAME
+// $RCSfile: TrapReceivedSupport.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.6 $
+// CREATED
+// $Date: 2006/01/17 17:43:53 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2001 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+package uk.co.westhawk.snmp.event;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.util.*;
+import uk.co.westhawk.snmp.stack.*;
+
+/**
+ * This is a utility class that can be used by classes that support trap
+ * listener functionality.
+ * You can use an instance of this class as a member field
+ * of your class and delegate various work to it.
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.6 $ $Date: 2006/01/17 17:43:53 $
+ */
+public class TrapReceivedSupport
+{
+ public static final String version_id =
+ "@(#)$Id: TrapReceivedSupport.java,v 1.6 2006/01/17 17:43:53 birgit Exp $ Copyright Westhawk Ltd";
+
+ private Object source;
+ private transient Vector trapListeners;
+
+/**
+ * The constructor.
+ *
+ * @param src The source (SnmpContext) of the trap events when they are fired.
+ */
+public TrapReceivedSupport(Object src)
+{
+ source = src;
+}
+
+/**
+ * Removes all the listeners.
+ */
+public synchronized void empty()
+{
+ if (trapListeners != null)
+ {
+ trapListeners.removeAllElements();
+ }
+}
+
+/**
+ * Returns the number of listeners.
+ *
+ * @return The number of listeners.
+ */
+public synchronized int getListenerCount()
+{
+ int c=0;
+ if (trapListeners != null)
+ {
+ c = trapListeners.size();
+ }
+ return c;
+}
+
+/**
+ * Adds the specified trap listener to receive traps.
+ */
+public synchronized void addTrapListener(TrapListener listener)
+{
+ if (trapListeners == null)
+ {
+ trapListeners = new Vector (5);
+ }
+ if (trapListeners.contains(listener) == false)
+ {
+ trapListeners.addElement(listener);
+ }
+}
+
+/**
+ * Removes the specified trap listener.
+ */
+public synchronized void removeTrapListener(TrapListener listener)
+{
+ if (trapListeners != null)
+ {
+ trapListeners.removeElement(listener);
+ }
+}
+
+
+/**
+ * Fires a decoded trap event.
+ * The event is fired to all listeners, whether they consume it or not.
+ * This behaviour is different from the undecoded trap event.
+ *
+ * @param pdu The decoded trap pdu.
+ */
+public void fireTrapReceived(Pdu pdu, int hostPort)
+{
+ Vector copyOfListeners = null;
+ if (trapListeners != null)
+ {
+ synchronized (trapListeners)
+ {
+ copyOfListeners = (Vector) trapListeners.clone();
+ }
+ }
+
+ if (copyOfListeners != null)
+ {
+ int sz = copyOfListeners.size();
+ for (int i=sz-1; i>=0; i--)
+ {
+ TrapListener listener = (TrapListener) copyOfListeners.elementAt(i);
+
+ TrapEvent evt = new TrapEvent(source, pdu, hostPort);
+ listener.trapReceived(evt);
+ }
+ }
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/net/ContextSocketFace.java b/src/main/java/uk/co/westhawk/snmp/net/ContextSocketFace.java
new file mode 100644
index 0000000..369eb6b
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/net/ContextSocketFace.java
@@ -0,0 +1,152 @@
+// NAME
+// $RCSfile: ContextSocketFace.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.12 $
+// CREATED
+// $Date: 2006/02/09 14:30:19 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.net;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.io.*;
+
+/**
+ * The interface for the different type of sockets.
+ *
+ * @author Tim Panton
+ * @version $Revision: 1.12 $ $Date: 2006/02/09 14:30:19 $
+ */
+public interface ContextSocketFace
+{
+ static final String version_id =
+ "@(#)$Id: ContextSocketFace.java,v 1.12 2006/02/09 14:30:19 birgit Exp $ Copyright Westhawk Ltd";
+
+/**
+ * Creates the socket. This socket is used when listening for incoming
+ * requests or traps.
+ * Use only one (1) of the two create methods.
+ *
+ * @param port The local port number were we receive (listen for)
+ * packets
+ * @param bindAddr The local address the server will bind to when
+ * listening
+ *
+ * @see #create(String, int, String)
+ */
+public void create(int port, String bindAddr) throws IOException;
+
+/**
+ * Creates the socket. This socket is used to send out our requests. Use
+ * only one (1) of the two create methods.
+ *
+ * @param host The name of the host that is to receive our packets
+ * @param port The port number of the host
+ * @param bindAddr The local address the server will bind to when
+ * sending packets
+ *
+ * @see #create(int, String)
+ */
+public void create(String host, int port, String bindAddr) throws IOException;
+
+/**
+ * Returns the IP address of the host we sent the packet to.
+ * Only applicable when sending requests, not when (only) listening for
+ * incoming requests or traps.
+ *
+ * @return The IP address, or null when the hostname cannot be determined
+ * @see #getReceivedFromHostAddress
+ */
+public String getSendToHostAddress();
+
+/**
+ * Returns the IP address of the (latest) host of the packet we received.
+ * Only applicable when anything has been received.
+ * When sending a request, this will in most cases be the same host
+ * where we sent the original packet to.
+ *
+ * @return The IP address, or null when the hostname cannot be determined
+ * @see #getSendToHostAddress
+ */
+public String getReceivedFromHostAddress();
+
+/**
+ * Returns the address of the endpoint this socket is bound to, or null
+ * if it is not bound yet.
+ *
+ * @since 4_14
+ */
+public String getLocalSocketAddress();
+
+/**
+ * Returns the address of the endpoint this socket is connected to, or
+ * null if it is unconnected.
+ *
+ * @since 4_14
+ */
+public String getRemoteSocketAddress();
+
+/**
+ * Receives a packet from this socket. The StreamPortItem object
+ * contains the host and port the packet came from.
+ *
+ * @param maxRecvSize the maximum number of bytes to receive
+ * @return the packet
+ */
+public StreamPortItem receive(int maxRecvSize) throws IOException;
+
+/**
+ * Sends a packet from this socket.
+ * It can throw an "java.io.IOException: Invalid argument" when the
+ * bind address is incorrect for some reason.
+ *
+ * @param packet the packet
+ */
+public void send(byte[] packet) throws IOException;
+
+/**
+ * Closes this socket.
+ */
+public void close();
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/net/StandardSocket.java b/src/main/java/uk/co/westhawk/snmp/net/StandardSocket.java
new file mode 100644
index 0000000..52939d0
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/net/StandardSocket.java
@@ -0,0 +1,224 @@
+// NAME
+// $RCSfile: StandardSocket.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.13 $
+// CREATED
+// $Date: 2009/03/05 15:56:19 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.net;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.io.*;
+import java.net.*;
+import uk.co.westhawk.snmp.stack.*;
+
+/**
+ * This is a wrapper class around the standard DatagramSocket. This
+ * sends packets over UDP, which is standard in SNMP.
+ *
+ * @see DatagramSocket
+ * @author Tim Panton
+ * @version $Revision: 1.13 $ $Date: 2009/03/05 15:56:19 $
+ */
+public class StandardSocket implements ContextSocketFace
+{
+ static final String version_id =
+ "@(#)$Id: StandardSocket.java,v 1.13 2009/03/05 15:56:19 birgita Exp $ Copyright Westhawk Ltd";
+
+ private DatagramSocket soc=null;
+ private InetAddress sendToHostAddr;
+ private int sendToHostPort;
+ private InetAddress receiveFromHostAddr;
+ private int receiveFromHostPort;
+ private InetAddress locBindAddr = null;
+
+public StandardSocket()
+{
+}
+
+public void create(int port, String bindAddr) throws IOException
+{
+ sendToHostPort = port;
+ receiveFromHostPort = sendToHostPort; // initialise (once!)
+ try
+ {
+ locBindAddr = null;
+ if (bindAddr != null)
+ {
+ locBindAddr = InetAddress.getByName(bindAddr);
+ }
+ soc = new DatagramSocket(sendToHostPort, locBindAddr);
+ }
+ catch (SocketException exc)
+ {
+ String str = "Socket problem: port=" + port + ", bindAddr="
+ + bindAddr + " " + exc.getMessage();
+ throw (new IOException(str));
+ }
+}
+
+
+public void create(String host, int port, String bindAddr) throws IOException
+{
+ sendToHostPort = port;
+ receiveFromHostPort = sendToHostPort; // initialise (once!)
+ try
+ {
+ sendToHostAddr = InetAddress.getByName(host);
+ receiveFromHostAddr = sendToHostAddr; // initialise (once!)
+ locBindAddr = null;
+ if (bindAddr != null)
+ {
+ locBindAddr = InetAddress.getByName(bindAddr);
+ }
+ InetSocketAddress isa = new InetSocketAddress(locBindAddr, 0);
+ soc = new DatagramSocket(isa);
+ }
+ catch (SocketException exc)
+ {
+ String str = "Socket problem: host=" + host + ", port=" + port
+ + ", bindAddr=" + bindAddr + " " + exc.getMessage();
+ throw (new IOException(str));
+ }
+ catch (UnknownHostException exc)
+ {
+ String str = "Cannot find host " + host + " " + exc.getMessage();
+ throw (new IOException(str));
+ }
+}
+
+public String getReceivedFromHostAddress()
+{
+ String res = null;
+ if (receiveFromHostAddr != null)
+ {
+ res = receiveFromHostAddr.getHostAddress();
+ }
+ return res;
+}
+
+public String getSendToHostAddress()
+{
+ String res = null;
+ if (sendToHostAddr != null)
+ {
+ res = sendToHostAddr.getHostAddress();
+ }
+ return res;
+}
+
+public String getLocalSocketAddress()
+{
+ String res = null;
+ if (soc != null)
+ {
+ SocketAddress sa = soc.getLocalSocketAddress();
+ if (sa != null)
+ {
+ res = sa.toString();
+ }
+ }
+ return res;
+}
+
+public String getRemoteSocketAddress()
+{
+ String res = null;
+ if (soc != null)
+ {
+ SocketAddress sa = soc.getRemoteSocketAddress();
+ if (sa != null)
+ {
+ res = sa.toString();
+ }
+ }
+ return res;
+}
+
+public StreamPortItem receive(int maxRecvSize) throws IOException
+{
+ StreamPortItem item = null;
+ if (soc != null)
+ {
+ byte [] data = new byte[maxRecvSize];
+ DatagramPacket p = new DatagramPacket(data, maxRecvSize);
+
+ // timeout will throw an exception every 1000 secs whilst idle
+ // it is caught and ignored, but as a side effect it loops,
+ // checking 'me'
+ soc.setSoTimeout(1000);
+
+ soc.receive(p);
+ receiveFromHostAddr = p.getAddress();
+ receiveFromHostPort = p.getPort();
+
+ ByteArrayInputStream in = null;
+ in = new ByteArrayInputStream(p.getData(), 0, p.getLength());
+ item = new StreamPortItem(receiveFromHostAddr.getHostAddress(),
+ receiveFromHostPort, in);
+ p = null;
+ }
+ return item;
+}
+
+public void send(byte[] packet) throws IOException
+{
+ if (soc != null)
+ {
+ DatagramPacket pack = new DatagramPacket(packet, packet.length,
+ sendToHostAddr, sendToHostPort);
+ soc.send(pack);
+ }
+}
+
+public void close()
+{
+ if (soc != null)
+ {
+ soc.close();
+ soc = null;
+ }
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/net/StreamPortItem.java b/src/main/java/uk/co/westhawk/snmp/net/StreamPortItem.java
new file mode 100644
index 0000000..4306f3f
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/net/StreamPortItem.java
@@ -0,0 +1,131 @@
+// NAME
+// $RCSfile: StreamPortItem.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.4 $
+// CREATED
+// $Date: 2006/02/09 14:14:50 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.net;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.io.*;
+
+/**
+ * This is a holder class that associates the incoming packet stream
+ * with the remote port it came from.
+ *
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.4 $ $Date: 2006/02/09 14:14:50 $
+ */
+public class StreamPortItem
+{
+ static final String version_id =
+ "@(#)$Id: StreamPortItem.java,v 1.4 2006/02/09 14:14:50 birgit Exp $ Copyright Westhawk Ltd";
+
+ private String hostAddress;
+ private int port;
+ private ByteArrayInputStream stream;
+
+/**
+ * Constructor.
+ *
+ * @param address The host address
+ * @param newPort The remote port number
+ * @param in The incoming message
+ */
+public StreamPortItem(String address, int newPort, ByteArrayInputStream in)
+{
+ hostAddress = address;
+ port = newPort;
+ stream = in;
+}
+
+/**
+ * Returns the host addres where the message came from.
+ *
+ * @return The host address
+ */
+public String getHostAddress()
+{
+ return hostAddress;
+}
+
+/**
+ * Returns the remote port where the message came from.
+ *
+ * @return The remote port number
+ */
+public int getHostPort()
+{
+ return port;
+}
+
+/**
+ * Returns incoming message (or a copy of it).
+ *
+ * @return The message
+ */
+public ByteArrayInputStream getStream()
+{
+ return stream;
+}
+
+/**
+ * Returns the string representation.
+ *
+ * @return The string
+ */
+public String toString()
+{
+ StringBuffer buffer = new StringBuffer(getClass().getName());
+ buffer.append("[");
+ buffer.append("hostAddress=").append(hostAddress);
+ buffer.append(", hostPort=").append(port);
+ buffer.append(", #bytes=").append(stream.available());
+ buffer.append("]");
+ return buffer.toString();
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/net/TCPSocket.java b/src/main/java/uk/co/westhawk/snmp/net/TCPSocket.java
new file mode 100644
index 0000000..6ceced3
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/net/TCPSocket.java
@@ -0,0 +1,296 @@
+// NAME
+// $RCSfile: TCPSocket.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.8 $
+// CREATED
+// $Date: 2009/03/05 15:56:19 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.net;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.io.*;
+import java.net.*;
+import uk.co.westhawk.snmp.stack.*;
+
+/**
+ * This is a wrapper class around the standard Socket. This sends
+ * packets over TCP.
+ *
+ *
+ * This is part of what is called "Reliable SNMP". SNMP usually goes
+ * over UDP. That is why there is a retry mechanisme in SNMP. Sending
+ * SNMP over TCP will only work is your agent listens on TCP.
+ * See
+ * RFC 3430
+ *
+ *
+ *
+ * When listening for incoming packets, the Socket, that is created when
+ * accepting an incoming connection, is closed at the end.
+ * Because of this, it is NOT possible to send a response back over the
+ * same connection.
+ *
+ *
+ * @see Socket
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 1.8 $ $Date: 2009/03/05 15:56:19 $
+ */
+public class TCPSocket implements ContextSocketFace
+{
+ static final String version_id =
+ "@(#)$Id: TCPSocket.java,v 1.8 2009/03/05 15:56:19 birgita Exp $ Copyright Westhawk Ltd";
+
+ private ServerSocket serverSoc=null;
+ private Socket clientSoc=null;
+ private InetAddress sendToHostAddr;
+ private int sendToHostPort;
+ private InetAddress receiveFromHostAddr;
+ private int receiveFromHostPort;
+ private InetAddress locBindAddr;
+
+public TCPSocket()
+{
+}
+
+public void create(int port, String bindAddr) throws IOException
+{
+ sendToHostPort = port;
+ receiveFromHostPort = sendToHostPort; // initialise (once!)
+ try
+ {
+ locBindAddr = null;
+ if (bindAddr != null)
+ {
+ locBindAddr = InetAddress.getByName(bindAddr);
+ }
+ serverSoc = new ServerSocket(sendToHostPort, 50, locBindAddr);
+ }
+ catch (SocketException exc)
+ {
+ String str = "Socket problem: port=" + port + ", bindAddr="
+ + bindAddr + " " + exc.getMessage();
+ throw (new IOException(str));
+ }
+}
+
+
+public void create(String host, int port, String bindAddr) throws IOException
+{
+ sendToHostPort = port;
+ receiveFromHostPort = sendToHostPort; // initialise (once!)
+ try
+ {
+ sendToHostAddr = InetAddress.getByName(host);
+ receiveFromHostAddr = sendToHostAddr; // initialise (once!)
+ locBindAddr = null;
+ if (bindAddr != null)
+ {
+ locBindAddr = InetAddress.getByName(bindAddr);
+ }
+ clientSoc = new Socket(sendToHostAddr, sendToHostPort, locBindAddr, 0);
+ }
+ catch (SocketException exc)
+ {
+ String str = "Socket problem: host=" + host + ", port=" + port
+ + ", bindAddr=" + bindAddr + " " + exc.getMessage();
+ throw (new IOException(str));
+ }
+ catch (UnknownHostException exc)
+ {
+ String str = "Cannot find host " + host + " " + exc.getMessage();
+ throw (new IOException(str));
+ }
+}
+
+public String getReceivedFromHostAddress()
+{
+ String res = null;
+ if (receiveFromHostAddr != null)
+ {
+ res = receiveFromHostAddr.getHostAddress();
+ }
+ return res;
+}
+
+public String getSendToHostAddress()
+{
+ String res = null;
+ if (sendToHostAddr != null)
+ {
+ res = sendToHostAddr.getHostAddress();
+ }
+ return res;
+}
+
+public String getLocalSocketAddress()
+{
+ String res = null;
+ if (serverSoc != null)
+ {
+ SocketAddress sa = serverSoc.getLocalSocketAddress();
+ if (sa != null)
+ {
+ res = sa.toString();
+ }
+ }
+ else if (clientSoc != null)
+ {
+ SocketAddress sa = clientSoc.getLocalSocketAddress();
+ if (sa != null)
+ {
+ res = sa.toString();
+ }
+ }
+ return res;
+}
+
+public String getRemoteSocketAddress()
+{
+ String res = null;
+ if (clientSoc != null)
+ {
+ SocketAddress sa = clientSoc.getRemoteSocketAddress();
+ if (sa != null)
+ {
+ res = sa.toString();
+ }
+ }
+ else if (serverSoc != null)
+ {
+ //
+ }
+ return res;
+}
+
+public StreamPortItem receive(int maxRecvSize) throws IOException
+{
+ StreamPortItem item = null;
+ if (serverSoc != null)
+ {
+ byte [] data = new byte[maxRecvSize];
+
+ // timeout will throw an exception every 1000 secs whilst idle
+ // it is caught and ignored, but as a side effect it loops,
+ // checking 'me'
+ serverSoc.setSoTimeout(1000);
+
+ Socket newSocket = serverSoc.accept();
+
+ // copy newSocketIn into in
+ InputStream newSocketIn = newSocket.getInputStream();
+ newSocketIn.read(data, 0, data.length);
+
+ receiveFromHostAddr = newSocket.getInetAddress();
+ receiveFromHostPort = newSocket.getPort();
+
+ ByteArrayInputStream in = null;
+ in = new ByteArrayInputStream(data, 0, data.length);
+ item = new StreamPortItem(receiveFromHostAddr.getHostAddress(),
+ receiveFromHostPort, in);
+
+ newSocketIn.close();
+ newSocket.close();
+
+ newSocketIn = null;
+ newSocket = null;
+ }
+ else if (clientSoc != null)
+ {
+ byte [] data = new byte[maxRecvSize];
+
+ // timeout will throw an exception every 1000 secs whilst idle
+ // it is caught and ignored, but as a side effect it loops,
+ // checking 'me'
+ clientSoc.setSoTimeout(1000);
+
+ InputStream cin = clientSoc.getInputStream();
+ cin.read(data, 0, data.length);
+
+ receiveFromHostAddr = clientSoc.getInetAddress();
+ receiveFromHostPort = clientSoc.getPort();
+
+ ByteArrayInputStream in = null;
+ in = new ByteArrayInputStream(data, 0, data.length);
+ item = new StreamPortItem(receiveFromHostAddr.getHostAddress(),
+ receiveFromHostPort, in);
+ }
+ return item;
+}
+
+public void send(byte[] packet) throws IOException
+{
+ if (clientSoc != null)
+ {
+ OutputStream out = clientSoc.getOutputStream();
+ out.write(packet);
+ out.flush();
+ }
+}
+
+public void close()
+{
+ try
+ {
+ if (clientSoc != null)
+ {
+ clientSoc.close();
+ }
+ }
+ catch(IOException exc) {}
+
+ try
+ {
+ if (serverSoc != null)
+ {
+ serverSoc.close();
+ }
+ }
+ catch(IOException exc) {}
+
+ serverSoc = null;
+ clientSoc = null;
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/BlockPdu.java b/src/main/java/uk/co/westhawk/snmp/pdu/BlockPdu.java
new file mode 100644
index 0000000..dfd650e
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/BlockPdu.java
@@ -0,0 +1,402 @@
+// NAME
+// $RCSfile: BlockPdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.13 $
+// CREATED
+// $Date: 2006/01/17 17:43:53 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.stack.*;
+import java.util.*;
+
+/**
+ * The BlockPdu class is a wrapper class that will block until it
+ * receives the answer.
+ *
+ * @see Pdu
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.13 $ $Date: 2006/01/17 17:43:53 $
+ */
+public class BlockPdu extends Object
+{
+ private static final String version_id =
+ "@(#)$Id: BlockPdu.java,v 3.13 2006/01/17 17:43:53 birgit Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * The GET PDU type.
+ */
+ public final static int GET = 0;
+ /**
+ * The SET PDU type.
+ */
+ public final static int SET = 1;
+ /**
+ * The GETNEXT PDU type.
+ */
+ public final static int GETNEXT = 2;
+ /**
+ * The GETBULK PDU type. Note, the getBulkRequest was introduced in
+ * SNMPv2c. For that reason it should not be sent with SNMPv1.
+ */
+ public final static int GETBULK = 3;
+
+ protected Vector reqVarbinds;
+ private SnmpContextBasisFace context;
+ private Pdu pdu;
+ private int type = GET;
+ private int non_rep = 0;
+ private int max_rep = 0;
+ private int retry_intervals[] = null;
+
+/**
+ * Constructor.
+ *
+ * @param con The context of the request
+ */
+public BlockPdu(SnmpContextBasisFace con)
+{
+ context = con;
+ reqVarbinds = new Vector(1,1);
+}
+
+/**
+ * Adds an OID to the PDU.
+ *
+ * @param oid The oid
+ * @see Pdu#addOid(String)
+ */
+public void addOid(String oid)
+{
+ varbind vb = new varbind(oid);
+ addOid(vb);
+}
+
+/**
+ * Adds an OID to the PDU and the value that has to be set.
+ * This is only useful for the SET type.
+ *
+ * @param oid The oid
+ * @see SetPdu#addOid(String, AsnObject)
+ * @see #SET
+ */
+public void addOid(String oid, AsnObject val)
+{
+ varbind vb = new varbind(oid, val);
+ addOid(vb);
+}
+
+/**
+ * Adds an OID (object identifier) to the PDU and the value that has
+ * to be set.
+ * This is only useful for the SET type.
+ *
+ * @param oid The oid
+ * @param val The value
+ * @see Pdu#addOid(AsnObjectId, AsnObject)
+ * @see varbind
+ * @since 4_12
+ */
+public void addOid(AsnObjectId oid, AsnObject val)
+{
+ varbind vb = new varbind(oid, val);
+ addOid(vb);
+}
+
+/**
+ * Adds an OID (object identifier) to the PDU. The OID indicates which
+ * MIB variable we request or which MIB variable should be set.
+ *
+ * @param oid The oid
+ * @see Pdu#addOid(AsnObjectId)
+ * @see varbind
+ * @since 4_12
+ */
+public void addOid(AsnObjectId oid)
+{
+ varbind vb = new varbind(oid);
+ addOid(vb);
+}
+
+/**
+ * Adds an OID (object identifier) to the PDU.
+ *
+ * @param var The varbind
+ * @see #addOid(String)
+ */
+public void addOid(varbind var)
+{
+ reqVarbinds.addElement(var);
+}
+
+/**
+ * Sets the getBulkRequest parameters.
+ * This is only useful for the GETBULK type.
+ * If these parameters are not set, they both default to zero.
+ *
+ * @param nr The non repeaters.
+ * @param mr The max repetitions.
+ * @see GetBulkPdu#setMaxRepetitions(int)
+ * @see GetBulkPdu#setNonRepeaters(int)
+ * @see #GETBULK
+ */
+public void setBulkParameters(int nr, int mr)
+{
+ non_rep = nr;
+ max_rep = mr;
+}
+
+/**
+ * Adds a list of OIDs to the PDU.
+ *
+ * @param oids The OIDs to be added
+ */
+public void addOid(String[] oids)
+{
+ for (int i=0; i 0)
+ {
+ value = vars[0].getValue();
+ }
+ return value;
+}
+
+/**
+ * Sends the request and waits (blocks) for the response. Returns the
+ * values of the variable bindings in the response. If no response was
+ * received, this will be null.
+ *
+ * @return The values of the variable bindings in the response
+ * @see #sendAndWait()
+ */
+public AsnObject[] getResponseVariables()
+throws PduException, java.io.IOException
+{
+ AsnObject[] values = null;
+ varbind[] vars = sendAndWait();
+ if (vars != null)
+ {
+ values = new AsnObject[vars.length];
+ for (int i=0; i 0)
+ {
+ var = vars[0];
+ }
+ return var;
+}
+
+/**
+ * Sends the request and waits (blocks) for the response. Returns the
+ * variable bindings in the response. If no response was received, this
+ * will be null.
+ *
+ * @return The variable bindings in the response
+ * @see #sendAndWait()
+ */
+public varbind[] getResponseVariableBindings()
+throws PduException, java.io.IOException
+{
+ varbind[] vars = sendAndWait();
+ return vars;
+}
+
+/**
+ * Sends the request and waits (blocks) for the response. This is the core
+ * of the blocking getResponseVariableX() methods.
+ *
+ * @return The response, can be null if there was a timeout
+ * @see Pdu#send()
+ * @see Pdu#waitForSelf()
+ * @see Pdu#getResponseVarbinds()
+ */
+protected synchronized varbind[] sendAndWait()
+throws PduException, java.io.IOException
+{
+ int sz = reqVarbinds.size();
+ switch (type)
+ {
+ case SET:
+ {
+ pdu = new SetPdu_vec(context, sz);
+ break;
+ }
+ case GETNEXT:
+ {
+ pdu = new GetNextPdu_vec(context, sz);
+ break;
+ }
+ case GETBULK:
+ {
+ pdu = new GetBulkPdu(context);
+ ((GetBulkPdu)pdu).setNonRepeaters(non_rep);
+ ((GetBulkPdu)pdu).setMaxRepetitions(max_rep);
+ break;
+ }
+ default:
+ {
+ pdu = new GetPdu_vec(context, sz);
+ }
+ }
+ for (int i=0; iwww.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.stack.*;
+import java.util.*;
+
+/**
+ * This class is used to perform the SNMPv3 USM discovery.
+ * This PDU cannot have any OIDs.
+ *
+ *
+ * See SNMP-USER-BASED-SM-MIB.
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.15 $ $Date: 2006/11/29 16:12:50 $
+ */
+public class DiscoveryPdu extends GetPdu
+{
+ private static final String version_id =
+ "@(#)$Id: DiscoveryPdu.java,v 3.15 2006/11/29 16:12:50 birgit Exp $ Copyright Westhawk Ltd";
+
+ private SnmpContextv3Face context;
+
+/**
+ * Constructor.
+ *
+ * @param cntxt The v3 context of the PDU
+ */
+public DiscoveryPdu(SnmpContextv3Face cntxt)
+{
+ super(cntxt);
+ context = cntxt;
+}
+
+/**
+ * Cannot add any OID. This method is overwritten to prevent users from
+ * adding any OID.
+ *
+ * @exception IllegalArgumentException A discovery PDU cannot have any
+ * OID.
+ */
+public void addOid(String oid)
+throws IllegalArgumentException
+{
+ throw new IllegalArgumentException("DiscoveryPdu cannot have OID");
+}
+
+/**
+ * Cannot add any OID. This method is overwritten to prevent users from
+ * adding any OID.
+ *
+ * @exception IllegalArgumentException A discovery PDU cannot have any
+ * OID.
+ * @since 4_12
+ */
+public void addOid(String oid, AsnObject val)
+{
+ throw new IllegalArgumentException("DiscoveryPdu cannot have OID");
+}
+
+/**
+ * Cannot add any OID. This method is overwritten to prevent users from
+ * adding any OID.
+ *
+ * @exception IllegalArgumentException A discovery PDU cannot have any
+ * OID.
+ * @since 4_12
+ */
+public void addOid(AsnObjectId oid, AsnObject val)
+{
+ throw new IllegalArgumentException("DiscoveryPdu cannot have OID");
+}
+
+/**
+ * Cannot add any OID. This method is overwritten to prevent users from
+ * adding any OID.
+ *
+ * @exception IllegalArgumentException A discovery PDU cannot have any
+ * OID.
+ */
+public void addOid(varbind var)
+throws IllegalArgumentException
+{
+ throw new IllegalArgumentException("DiscoveryPdu cannot have OID");
+}
+
+/**
+ * Cannot add any OID. This method is overwritten to prevent users from
+ * adding any OID.
+ *
+ * @exception IllegalArgumentException A discovery PDU cannot have any
+ * OID.
+ * @since 4_12
+ */
+public void addOid(AsnObjectId oid)
+{
+ throw new IllegalArgumentException("DiscoveryPdu cannot have OID");
+}
+
+/**
+ * Sends the PDU.
+ * Note that all properties of the context have to be set before this
+ * point.
+ */
+public boolean send() throws java.io.IOException, PduException
+{
+ if (added == false)
+ {
+ // Moved this statement from the constructor because it
+ // conflicts with the way the SnmpContextXPool works.
+ added = context.addDiscoveryPdu(this);
+ }
+ Enumeration vbs = reqVarbinds.elements();
+ encodedPacket = context.encodeDiscoveryPacket(msg_type, getReqId(),
+ getErrorStatus(), getErrorIndex(), vbs, snmpv3MsgId);
+ addToTrans();
+ return added;
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/GetNextPdu_vec.java b/src/main/java/uk/co/westhawk/snmp/pdu/GetNextPdu_vec.java
new file mode 100644
index 0000000..7c82778
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/GetNextPdu_vec.java
@@ -0,0 +1,149 @@
+// NAME
+// $RCSfile: GetNextPdu_vec.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.13 $
+// CREATED
+// $Date: 2006/11/29 16:12:50 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ * original version by hargrave@dellgate.us.dell.com (Jordan Hargrave)
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.stack.*;
+import java.lang.*;
+
+/**
+ *
+ * The GetNextPdu_vec class will ask for a number of objects (OIDs), based
+ * on the GetNext request.
+ *
+ *
+ *
+ * Specify with addOid() the OIDs that should be requested with this
+ * PDU request. No more than count (see constructor) should be added.
+ * Add an Observer to the PDU with addObserver(), and send the PDU
+ * with send().
+ *
+ *
+ *
+ * If no exception occurred whilst receiving the response, the Object to the
+ * update() method of the Observer will be an array of
+ * varbinds, so they may contains any AsnObject type.
+ * If an exception occurred, that exception will be passed as the Object
+ * to the update() method.
+ *
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.13 $ $Date: 2006/11/29 16:12:50 $
+ * @see Pdu#addOid
+ * @see Pdu#send
+ * @see InterfaceGetNextPdu
+ * @see OneGetNextPdu
+ * @see varbind
+ */
+public class GetNextPdu_vec extends GetNextPdu
+{
+ private static final String version_id =
+ "@(#)$Id: GetNextPdu_vec.java,v 3.13 2006/11/29 16:12:50 birgit Exp $ Copyright Westhawk Ltd";
+
+ varbind[] value;
+
+ /**
+ * Constructor.
+ *
+ * @param con The context of the request
+ * @param count The number of OIDs to be get
+ */
+ public GetNextPdu_vec(SnmpContextBasisFace con, int count)
+ {
+ super(con);
+ value = new varbind[count];
+ }
+
+ /**
+ * The value of the request is set. This will be called by
+ * Pdu.fillin().
+ *
+ * @param n the index of the value
+ * @param var the value
+ * @see Pdu#new_value
+ */
+ protected void new_value(int n, varbind var)
+ {
+ if (n
+ * If no exception occurred whilst receiving the response, the Object to the
+ * update() method of the Observer will be an array of
+ * varbinds, so they may contains any AsnObject type.
+ * If an exception occurred, that exception will be passed as the Object
+ * to the update() method.
+ *
+ */
+ protected void tell_them()
+ {
+ notifyObservers(value);
+ }
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/GetPdu_vec.java b/src/main/java/uk/co/westhawk/snmp/pdu/GetPdu_vec.java
new file mode 100644
index 0000000..5eb10bc
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/GetPdu_vec.java
@@ -0,0 +1,148 @@
+// NAME
+// $RCSfile: GetPdu_vec.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.13 $
+// CREATED
+// $Date: 2006/11/29 16:12:50 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ * original version by hargrave@dellgate.us.dell.com (Jordan Hargrave)
+ */
+
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.stack.*;
+import java.lang.*;
+
+/**
+ *
+ * The GetPdu_vec class will ask for a number of objects (OIDs), based
+ * on the Get request.
+ *
+ *
+ *
+ * Specify with addOid() the OIDs that should be requested with this
+ * PDU request. No more than count (see constructor) should be added.
+ * Add an Observer to the PDU with addObserver(), and send the PDU
+ * with send().
+ *
+ *
+ *
+ * If no exception occurred whilst receiving the response, the Object to the
+ * update() method of the Observer will be an array of
+ * varbinds, so they may contains any AsnObject type.
+ * If an exception occurred, that exception will be passed as the Object
+ * to the update() method.
+ *
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.13 $ $Date: 2006/11/29 16:12:50 $
+ * @see Pdu#addOid
+ * @see Pdu#send
+ * @see varbind
+ * @see OneIntPdu
+ */
+public class GetPdu_vec extends GetPdu
+{
+ private static final String version_id =
+ "@(#)$Id: GetPdu_vec.java,v 3.13 2006/11/29 16:12:50 birgit Exp $ Copyright Westhawk Ltd";
+
+ varbind[] value;
+
+ /**
+ * Constructor.
+ *
+ * @param con The context of the request
+ * @param count The number of OIDs to be get
+ */
+ public GetPdu_vec(SnmpContextBasisFace con, int count)
+ {
+ super(con);
+ value = new varbind[count];
+ }
+
+ /**
+ * The value of the request is set. This will be called by
+ * Pdu.fillin().
+ *
+ * @param n the index of the value
+ * @param var the value
+ * @see Pdu#new_value
+ */
+ protected void new_value(int n, varbind var)
+ {
+ if (n
+ * If no exception occurred whilst receiving the response, the Object to the
+ * update() method of the Observer will be an array of
+ * varbinds, so they may contains any AsnObject type.
+ * If an exception occurred, that exception will be passed as the Object
+ * to the update() method.
+ *
+ */
+ protected void tell_them()
+ {
+ notifyObservers(value);
+ }
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/InformPdu_vec.java b/src/main/java/uk/co/westhawk/snmp/pdu/InformPdu_vec.java
new file mode 100644
index 0000000..bca22b2
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/InformPdu_vec.java
@@ -0,0 +1,142 @@
+// NAME
+// $RCSfile: InformPdu_vec.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.5 $
+// CREATED
+// $Date: 2006/11/29 16:12:50 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2002 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.stack.*;
+import java.lang.*;
+
+/**
+ *
+ * The InformPdu_vec class will inform a manager about a number of
+ * objects (OIDs), based on the Inform request.
+ *
+ *
+ *
+ * Specify with addOid()
the OIDs that should be informed with this
+ * InformPdu request. No more than count
(see constructor)
+ * should be added.
+ * Add an Observer to the InformPdu with addObserver()
, and
+ * send the InformPdu with send()
.
+ *
+ *
+ *
+ * Note, this PDU should be sent to port 162 (the default trap port) by
+ * default. You will have to create a SnmpContext with the
+ * ListeningContextFace.DEFAULT_TRAP_PORT as parameter!
+ *
+ *
+ *
+ * Inform Requests
+ * are sent between managers. It is a kind of 'acknowlegded' trap since
+ * the receiving end should send a Response Pdu as reply.
+ * The varbind list has the same elements as the TrapPduv2.
+ *
+ *
+ * @see Pdu#addOid
+ * @see Pdu#send
+ * @see varbind
+ * @see ListeningContextFace#DEFAULT_TRAP_PORT
+ * @since 4_12
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.5 $ $Date: 2006/11/29 16:12:50 $
+ */
+public class InformPdu_vec extends InformPdu
+{
+ private static final String version_id =
+ "@(#)$Id: InformPdu_vec.java,v 3.5 2006/11/29 16:12:50 birgit Exp $ Copyright Westhawk Ltd";
+
+ varbind[] value;
+
+/**
+ * Constructor.
+ *
+ * @param con The context of the request
+ * @param count The number of OIDs to be get
+ */
+public InformPdu_vec(SnmpContextBasisFace con, int count)
+{
+ super(con);
+ value = new varbind[count];
+}
+
+/**
+ * The value of the request is set. This will be called by
+ * InformPdu.fillin().
+ *
+ * @param n the index of the value
+ * @param var the value
+ * @see Pdu#new_value
+ */
+protected void new_value(int n, varbind var)
+{
+ if (n
+ * If no exception occurred whilst receiving the response, the Object to the
+ * update() method of the Observer will be an array of
+ * varbinds, so they may contains any AsnObject type.
+ * If an exception occurred, that exception will be passed as the Object
+ * to the update() method.
+ *
+ */
+protected void tell_them()
+{
+ notifyObservers(value);
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/InterfaceGetNextPdu.java b/src/main/java/uk/co/westhawk/snmp/pdu/InterfaceGetNextPdu.java
new file mode 100644
index 0000000..bb669fb
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/InterfaceGetNextPdu.java
@@ -0,0 +1,177 @@
+// NAME
+// $RCSfile: InterfaceGetNextPdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.17 $
+// CREATED
+// $Date: 2008/05/06 10:17:06 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+import java.util.*;
+
+
+/**
+ * The class InterfaceGetNextPdu.
+ *
+ * This file is auto generated by the StubBrowser utility, using Mibble.
+ * See the uk/co/westhawk/stub/ directory.
+ *
+ * Added speed parameter and methods by hand.
+
+ * Make sure that you replace the package name and classname placeholders.
+ * Also, move this file to the correct package directory.
+ * If these things are not done, this class will not compile correctly!!
+ *
+ * @version $Revision: 3.17 $ $Date: 2008/05/06 10:17:06 $
+ */
+public class InterfaceGetNextPdu extends InterfaceGetNextPduStub
+{
+ private static final String version_id =
+ "@(#)$Id: InterfaceGetNextPdu.java,v 3.17 2008/05/06 10:17:06 birgita Exp $ Copyright Westhawk Ltd";
+
+ protected long _speed;
+
+
+/**
+ * Constructor.
+ *
+ * @param con The context of the request
+ */
+public InterfaceGetNextPdu(SnmpContextBasisFace con)
+{
+ super(con);
+}
+
+
+/**
+ * Returns the last calculates speed.
+ *
+ * @see #getSpeed(InterfaceGetNextPdu)
+ */
+public long getSpeed()
+{
+ return _speed;
+}
+
+/**
+ * Calculates the speed of the interface. This is done by providing the
+ * method with the previous value of this interface. An interface
+ * is marked by its index. Do not confuse it
+ * with the previous interface ifInOctets the MIB.
+ * Total number of octets (received and transmitted) per second.
+ *
+ * @param old The previous value of this interface
+ */
+public long getSpeed(InterfaceGetNextPdu old)
+{
+ _speed = -1;
+ if (this._ifOperStatus > 0
+ &&
+ old._ifOperStatus > 0
+ &&
+ this._valid
+ &&
+ old._valid)
+ {
+ long tdiff = (this._sysUpTime - old._sysUpTime);
+ if (tdiff != 0)
+ {
+ long inO = this._ifInOctets - old._ifInOctets;
+ long outO = this._ifOutOctets - old._ifOutOctets;
+
+ _speed = 100 * (inO + outO) / tdiff;
+ }
+ }
+ else
+ {
+ _speed = -1;
+ }
+ return _speed;
+}
+
+
+/**
+ * Returns how many interfaces are present.
+ *
+ * @return the number of interfaces
+ */
+public static int getIfNumber(SnmpContextBasisFace con)
+throws PduException, java.io.IOException
+{
+ int ifNumber =0;
+
+ if (con != null)
+ {
+ OneIntPdu ifNumberPdu = new OneIntPdu(con, ifNumber_OID + ".0");
+ boolean answered = ifNumberPdu.waitForSelf();
+ boolean timedOut = ifNumberPdu.isTimedOut();
+ if (timedOut == false)
+ {
+ Integer intValue = ifNumberPdu.getValue();
+ if (intValue != null)
+ {
+ ifNumber = intValue.intValue();
+ }
+ }
+ }
+ return ifNumber;
+}
+
+
+public String toString()
+{
+ StringBuffer buffer = new StringBuffer(getClass().getName());
+ buffer.append("[");
+ buffer.append(super.toString());
+ buffer.append(", speed=").append(_speed);
+ buffer.append("]");
+ return buffer.toString();
+}
+
+
+}
+
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/InterfaceGetNextPduStub.java b/src/main/java/uk/co/westhawk/snmp/pdu/InterfaceGetNextPduStub.java
new file mode 100644
index 0000000..331cca3
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/InterfaceGetNextPduStub.java
@@ -0,0 +1,498 @@
+// NAME
+// $RCSfile: InterfaceGetNextPduStub.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.4 $
+// CREATED
+// $Date: 2006/11/29 16:12:50 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.pdu.*;
+import java.util.*;
+
+
+/**
+ * The class InterfaceGetNextPduStub.
+ *
+ * This file is auto generated by the StubBrowser utility, using Mibble.
+ * See the uk/co/westhawk/stub/ directory.
+ *
+ * Make sure that you replace the package name and classname placeholders.
+ * Also, move this file to the correct package directory.
+ * If these things are not done, this class will not compile correctly!!
+ *
+ * @version $Revision: 3.4 $ $Date: 2006/11/29 16:12:50 $
+ * @since 4_14
+ */
+public class InterfaceGetNextPduStub extends GetNextPdu
+{
+ private static final String version_id =
+ "@(#)$Id: InterfaceGetNextPduStub.java,v 3.4 2006/11/29 16:12:50 birgit Exp $ Copyright Westhawk Ltd";
+
+ public final static String sysUpTime_OID = "1.3.6.1.2.1.1.3";
+ public final static String ifNumber_OID = "1.3.6.1.2.1.2.1";
+ public final static String ifIndex_OID = "1.3.6.1.2.1.2.2.1.1";
+ public final static String ifDescr_OID = "1.3.6.1.2.1.2.2.1.2";
+ public final static String ifSpeed_OID = "1.3.6.1.2.1.2.2.1.5";
+ public final static String ifOperStatus_OID = "1.3.6.1.2.1.2.2.1.8";
+ public final static String ifInOctets_OID = "1.3.6.1.2.1.2.2.1.10";
+ public final static String ifOutOctets_OID = "1.3.6.1.2.1.2.2.1.16";
+
+ public final static int NO_SCAL = 2;
+ public final static int NO_COL = 6;
+ public final static int NO_OID = NO_SCAL + NO_COL;
+
+
+ public final static String scal_oids[] =
+ {
+ sysUpTime_OID,
+ ifNumber_OID,
+ };
+
+ public final static String col_oids[] =
+ {
+ ifIndex_OID,
+ ifDescr_OID,
+ ifSpeed_OID,
+ ifOperStatus_OID,
+ ifInOctets_OID,
+ ifOutOctets_OID,
+ };
+
+ public final static String all_oids[] =
+ {
+ sysUpTime_OID,
+ ifNumber_OID,
+ ifIndex_OID,
+ ifDescr_OID,
+ ifSpeed_OID,
+ ifOperStatus_OID,
+ ifInOctets_OID,
+ ifOutOctets_OID,
+ };
+
+
+ protected long _sysUpTime;
+ protected int _ifNumber;
+ protected int _ifIndex;
+ protected String _ifDescr;
+ protected long _ifSpeed;
+ protected HashMap _ifOperStatusMap = new HashMap(3);
+ protected int _ifOperStatus;
+ protected long _ifInOctets;
+ protected long _ifOutOctets;
+
+ protected boolean _valid = false;
+
+/**
+ * Constructor.
+ *
+ * @param con The context of the request
+ */
+public InterfaceGetNextPduStub(SnmpContextBasisFace con)
+{
+ super(con);
+ _ifOperStatusMap.put(new Integer(3), "testing");
+ _ifOperStatusMap.put(new Integer(1), "up");
+ _ifOperStatusMap.put(new Integer(2), "down");
+
+ _valid = false;
+}
+
+/**
+ * Constructor that will send the first request immediately.
+ *
+ * @param con The context of the request
+ * @param o the Observer that will be notified when the answer is
+ * received
+ */
+public InterfaceGetNextPduStub(SnmpContextBasisFace con, Observer o)
+throws PduException, java.io.IOException
+{
+ this(con);
+ addOids(null);
+ if (o != null)
+ {
+ addObserver(o);
+ }
+ send();
+}
+
+
+/**
+ * The method addOids is the basis for the GetNext functionality.
+ *
+ * If old is null, it initialises the varbinds from all_oids.
+ * If old is not null, it copies the column OIDs from the
+ * old InterfaceGetNextPduStub object.
+ * so the request continues where the previous one left.
+ *
+ * Note, the scalars and the columns OIDs are handled differently. The
+ * scalars are always copied from the original scal_oids, only the
+ * column OIDs are copied from the old
+ * InterfaceGetNextPduStub object.
+ */
+public void addOids(InterfaceGetNextPduStub old)
+{
+ if (old != null)
+ {
+ for (int i=0; iwww.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.stack.*;
+import java.util.*;
+
+
+/**
+ * The InterfacePdu class asks one interface for information, useful for admin
+ * purposes.
+ * See IF-MIB.
+ *
+ * @author Tim Panton
+ * @version $Revision: 3.19 $ $Date: 2006/11/29 16:12:50 $
+ * @see InterfacesPdu
+ *
+ */
+public class InterfacePdu extends GetPdu
+{
+ private static final String version_id =
+ "@(#)$Id: InterfacePdu.java,v 3.19 2006/11/29 16:12:50 birgit Exp $ Copyright Westhawk Ltd";
+
+ // see rfc 2863
+
+ /**
+ * ifNumber -
+ * The number of network interfaces (regardless of their current state)
+ * present on this system.
+ */
+ final static String IFNUMBER ="1.3.6.1.2.1.2.1.0";
+
+ /**
+ * sysUpTime -
+ * The time (in hundredths of a second) since the network management
+ * portion of the system was last re-initialized.
+ */
+ final static String SYS_UPTIME ="1.3.6.1.2.1.1.3";
+
+ /**
+ * ifDescr -
+ * A textual string containing information about the
+ * interface. This string should include the name of
+ * the manufacturer, the product name and the version
+ * of the hardware interface.
+ */
+ final static String DESCR ="1.3.6.1.2.1.2.2.1.2";
+
+ /**
+ * ifOperStatus -
+ * The current operational state of the interface.
+ * The testing(3) state indicates that no operational
+ * packets can be passed.
+ */
+ final static String OPR_STATUS ="1.3.6.1.2.1.2.2.1.8";
+
+ /**
+ * ifInOctets -
+ * The total number of octets received on the
+ * interface, including framing characters.
+ */
+ final static String IN_OCTETS ="1.3.6.1.2.1.2.2.1.10";
+
+ /**
+ * ifOutOctets -
+ * The total number of octets transmitted outOctets of the
+ * interface, including framing characters.
+ */
+ final static String OUT_OCTETS ="1.3.6.1.2.1.2.2.1.16";
+
+ /**
+ * The current operational state is up
+ */
+ final public static String UP = "up";
+ /**
+ * The current operational state is down
+ */
+ final public static String DOWN = "down";
+ /**
+ * The current operational state is testing
+ */
+ final public static String TESTING = "testing";
+ /**
+ * The current operational state is unknown
+ */
+ final public static String UNKNOWN = "unknown";
+
+ long sysUpTime;
+ int operStatus;
+ long inOctet;
+ long outOctet;
+ long speed;
+ int index;
+ String descr;
+ boolean valid = false;
+
+
+
+/**
+ * Constructor.
+ * It permits this package to create this PDU without data.
+ *
+ * @param con The context of the request
+ */
+InterfacePdu(SnmpContextBasisFace con)
+{
+ super(con);
+}
+
+/**
+ * Constructor that will send the request immediately.
+ *
+ * @param con the SnmpContextBasisFace
+ * @param o the Observer that will be notified when the answer is received
+ * @param interf the index of the requested interface
+ */
+public InterfacePdu(SnmpContextBasisFace con, Observer o, int interf)
+throws PduException, java.io.IOException
+{
+ super(con);
+
+ addOids(interf);
+ if (o!=null)
+ {
+ addObserver(o);
+ }
+ index = interf;
+ send();
+}
+
+/**
+ * Returns the index of the interface.
+ * @return the index
+ */
+public int getIndex()
+{
+ return index;
+}
+
+/**
+ * Returns the time (in hundredths of a second) since the network management
+ * portion of the system was last re-initialized.
+ */
+public long getSysUpTime()
+{
+ return sysUpTime;
+}
+
+/**
+ * Returns the description of the interface.
+ * @return the description
+ */
+public String getDescription()
+{
+ return descr;
+}
+
+/**
+ * Returns the operational state of the interface.
+ * @return the operational state
+ */
+public int getOperStatus()
+{
+ return operStatus;
+}
+
+/**
+ * Returns the string representation of the operational state of the
+ * interface.
+ * @return the operational state as string
+ * @see #getOperStatus()
+ * @see #getOperStatusString(int)
+ */
+public String getOperStatusString()
+{
+ return getOperStatusString(operStatus);
+}
+
+/**
+ * Returns the string representation of a operational state.
+ * @see #getOperStatusString()
+ */
+public String getOperStatusString(int status)
+{
+ String str = null;
+ switch (status)
+ {
+ case 1:
+ str = UP;
+ break;
+ case 2:
+ str = DOWN;
+ break;
+ case 3:
+ str = TESTING;
+ break;
+ default:
+ str = UNKNOWN;
+ }
+ return str;
+}
+
+/**
+ * Returns the total number of octets received on the
+ * interface, including framing characters.
+ */
+public long getInOctet()
+{
+ return inOctet;
+}
+
+ /**
+ * Returns the total number of octets transmitted outOctets of the
+ * interface, including framing characters.
+ */
+public long getOutOctet()
+{
+ return outOctet;
+}
+
+/**
+ * Calculates the speed of the interface. This is done by providing the
+ * method with the previous value of this interface. An interface
+ * is marked by its index.
+ *
+ * @param old The previous value of this interface
+ */
+public long getSpeed(InterfacePdu old)
+{
+ long speed = -1;
+ if ((this.operStatus <1) || (old.operStatus <1)
+ ||
+ !this.valid || !old.valid)
+ {
+ return -1;
+ }
+ long tdif = (this.sysUpTime - old.sysUpTime);
+ if (tdif != 0)
+ {
+ speed = 100 *((this.inOctet - old.inOctet)
+ + (this.outOctet - old.outOctet))/ tdif;
+ }
+ return speed;
+}
+
+void addOids(int interf)
+{
+ addOid(SYS_UPTIME+".0");
+ addOid(DESCR+"."+interf);
+ addOid(OPR_STATUS+"."+interf);
+ addOid(IN_OCTETS+"."+interf);
+ addOid(OUT_OCTETS+"."+interf);
+}
+
+/**
+ * The value of the request is set. This will be called by
+ * Pdu.fillin().
+ *
+ * @param n the index of the value
+ * @param res the value
+ * @see Pdu#new_value
+ */
+protected void new_value(int n, varbind res)
+{
+ AsnObject obj = res.getValue();
+ if (getErrorStatus() == AsnObject.SNMP_ERR_NOERROR)
+ {
+ try
+ {
+ switch (n)
+ {
+ case 0:
+ sysUpTime = ((AsnUnsInteger) obj).getValue();
+ break;
+ case 1:
+ descr = ((AsnOctets) obj).getValue();
+ break;
+ case 2:
+ operStatus = ((AsnInteger) obj).getValue();
+ break;
+ case 3:
+ inOctet = ((AsnUnsInteger) obj).getValue();
+ break;
+ case 4:
+ outOctet = ((AsnUnsInteger) obj).getValue();
+ valid = true;
+ break;
+ default:
+ valid = false;
+ }
+ }
+ catch(ClassCastException exc)
+ {
+ sysUpTime = 0;
+ descr = null;
+ operStatus = 0;
+ inOctet = 0;
+ outOctet = 0;
+ valid = false;
+ }
+ }
+ else
+ {
+ valid = false;
+ }
+}
+
+/**
+ * This method notifies all observers.
+ * This will be called by Pdu.fillin().
+ *
+ *
+ * Unless an exception occurred the Object to the update() method of the
+ * Observer will be a varbind, so any AsnObject type can be returned.
+ * In the case of an exception, that exception will be passed.
+ *
+ */
+protected void tell_them()
+{
+ notifyObservers(this);
+}
+
+/**
+ * Returns how many interfaces are present.
+ *
+ * @return the number of interfaces
+ */
+public static int getNumIfs(SnmpContextBasisFace con)
+throws PduException, java.io.IOException
+{
+ int ifCount =0;
+
+ if (con != null)
+ {
+ OneIntPdu numIfs = new OneIntPdu(con, IFNUMBER);
+ boolean answered = numIfs.waitForSelf();
+ boolean timedOut = numIfs.isTimedOut();
+ if (answered == true && timedOut == false)
+ {
+ ifCount = numIfs.getValue().intValue();
+ }
+ }
+ return ifCount;
+}
+
+
+}
+
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/InterfacesPdu.java b/src/main/java/uk/co/westhawk/snmp/pdu/InterfacesPdu.java
new file mode 100644
index 0000000..57540cb
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/InterfacesPdu.java
@@ -0,0 +1,135 @@
+// NAME
+// $RCSfile: InterfacesPdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.12 $
+// CREATED
+// $Date: 2006/11/29 16:12:50 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1996 - 1998 by Westhawk Ltd (www.westhawk.nl)
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.stack.*;
+import java.util.*;
+
+/**
+ * The InterfacesPdu class will ask for the number of current interfaces.
+ * For each interface it will send an InterfacePdu to get the
+ * information of the specific interface.
+ *
+ * @see InterfacePdu
+ *
+ * @author Tim Panton
+ * @version $Revision: 3.12 $ $Date: 2006/11/29 16:12:50 $
+ *
+ */
+public class InterfacesPdu extends InterfacePdu
+{
+ private static final String version_id =
+ "@(#)$Id: InterfacesPdu.java,v 3.12 2006/11/29 16:12:50 birgit Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * ifNumber
+ * The number of network interfaces (regardless of their current state)
+ * present on this system.
+ */
+ final static String IFNUMBER ="1.3.6.1.2.1.2.1.0";
+
+ InterfacePdu [] ifs;
+
+
+/**
+ * Constructor that will send the request immediately.
+ *
+ * @param con the SnmpContextBasisFace
+ * @param o the Observer that will be notified when the answer is received
+ * @param interfs the index of the requested interface
+ */
+public InterfacesPdu(SnmpContextBasisFace con, Observer o, int interfs)
+throws PduException, java.io.IOException
+{
+ super(con);
+ ifs = new InterfacePdu [interfs];
+ for (int interf=0; interf < interfs; interf++)
+ {
+ addOids(interf);
+ ifs[interf] = new InterfacePdu(con);
+ }
+ if (o!=null)
+ {
+ addObserver(o);
+ }
+ send();
+}
+
+
+/**
+ * Returns the interfaces.
+ *
+ * @return the interfaces as an array of InterfacePdu
+ */
+public InterfacePdu [] getInterfacePdus()
+{
+ return ifs;
+}
+
+/**
+ * The value of the request is set. This will be called by
+ * Pdu.fillin().
+ *
+ * @param n the index of the value
+ * @param res the value
+ * @see Pdu#new_value
+ */
+protected void new_value(int n, varbind res)
+{
+ int thif = n / 4;
+ if (thif < ifs.length)
+ {
+ ifs[thif].new_value(n%4,res);
+ }
+}
+
+
+}
+
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/OneGetBulkPdu.java b/src/main/java/uk/co/westhawk/snmp/pdu/OneGetBulkPdu.java
new file mode 100644
index 0000000..34d4fd8
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/OneGetBulkPdu.java
@@ -0,0 +1,147 @@
+// NAME
+// $RCSfile: OneGetBulkPdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.9 $
+// CREATED
+// $Date: 2006/01/17 17:43:53 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+
+/*
+ * Copyright (C) 2001 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.stack.*;
+import java.util.*;
+
+/**
+ *
+ * The OneGetBulkPdu class performs a getBulkRequest and collects
+ * the response varbinds into a Vector.
+ *
+ *
+ *
+ * If no exception occurred whilst receiving the response, the Object to the
+ * update() method of the Observer will be an Vector of
+ * varbinds, so they may contains any AsnObject type.
+ * If an exception occurred, that exception will be passed as the Object
+ * to the update() method.
+ *
+ *
+ *
+ * For SNMPv3: The receiver of a request PDU acts as the authoritative engine.
+ *
+ *
+ * @see varbind
+ * @see Vector
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.9 $ $Date: 2006/01/17 17:43:53 $
+ */
+public class OneGetBulkPdu extends GetBulkPdu
+{
+ private static final String version_id =
+ "@(#)$Id: OneGetBulkPdu.java,v 3.9 2006/01/17 17:43:53 birgit Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * The GetBulk request is the only request that will return more
+ * variables than you've sent.
+ */
+ Vector vars;
+
+/**
+ * Constructor.
+ *
+ * @param con The context (v2c or v3) of the PDU
+ */
+public OneGetBulkPdu(SnmpContextBasisFace con)
+{
+ super(con);
+ vars = new Vector();
+}
+
+
+/**
+ * Returns a vector with the response varbinds.
+ */
+public Vector getVarbinds()
+{
+ return vars;
+}
+
+
+/**
+ * The value of the request is set. This will be called by
+ * Pdu.fillin().
+ *
+ * @param n the index of the value
+ * @param a_var the value
+ * @see Pdu#new_value
+ */
+protected void new_value(int n, varbind a_var)
+{
+ if (n == 0)
+ {
+ vars = new Vector();
+ }
+ vars.addElement(a_var);
+}
+
+/**
+ * This method notifies all observers.
+ * This will be called by Pdu.fillin().
+ *
+ *
+ * If no exception occurred whilst receiving the response, the Object to the
+ * update() method of the Observer will be an Vector of
+ * varbinds, so they may contains any AsnObject type.
+ * If an exception occurred, that exception will be passed as the Object
+ * to the update() method.
+ *
+ *
+ * @see Vector
+ */
+protected void tell_them()
+{
+ notifyObservers(vars);
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/OneGetNextPdu.java b/src/main/java/uk/co/westhawk/snmp/pdu/OneGetNextPdu.java
new file mode 100644
index 0000000..47e29d0
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/OneGetNextPdu.java
@@ -0,0 +1,158 @@
+// NAME
+// $RCSfile: OneGetNextPdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.14 $
+// CREATED
+// $Date: 2006/01/17 17:49:53 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1996 - 1998 by Westhawk Ltd (www.westhawk.nl)
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.stack.*;
+import java.util.*;
+
+/**
+ *
+ * The OneGetNextPdu class will ask for one (1) object (oid), based on
+ * the GetNext request.
+ *
+ *
+ *
+ * Unless an exception occurred the Object to the update() method of the
+ * Observer will be a varbind, so any AsnObject type can be returned.
+ * In the case of an exception, that exception will be passed.
+ *
+ *
+ *
+ * For SNMPv3: The receiver of a request PDU acts as the authoritative engine.
+ *
+ *
+ * @see varbind
+ * @see InterfaceGetNextPdu
+ * @see GetNextPdu_vec
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.14 $ $Date: 2006/01/17 17:49:53 $
+ */
+public class OneGetNextPdu extends GetNextPdu
+{
+ private static final String version_id =
+ "@(#)$Id: OneGetNextPdu.java,v 3.14 2006/01/17 17:49:53 birgit Exp $ Copyright Westhawk Ltd";
+
+ varbind var;
+
+ /**
+ * Constructor.
+ *
+ * @param con The context of the request
+ */
+ public OneGetNextPdu(SnmpContextBasisFace con)
+ {
+ super(con);
+ }
+
+ /**
+ * Constructor that will send the request immediately. No Observer
+ * is set.
+ *
+ * @param con the SnmpContextBasisFace
+ * @param oid the oid
+ */
+ public OneGetNextPdu(SnmpContextBasisFace con, String oid)
+ throws PduException, java.io.IOException
+ {
+ this(con, oid, null);
+ }
+
+ /**
+ * Constructor that will send the request immediately.
+ *
+ * @param con the SnmpContextBasisFace
+ * @param oid the oid
+ * @param o the Observer that will be notified when the answer is received
+ */
+ public OneGetNextPdu(SnmpContextBasisFace con, String oid, Observer o)
+ throws PduException, java.io.IOException
+ {
+ super(con);
+ if (o != null)
+ {
+ addObserver(o);
+ }
+ addOid(oid);
+ send();
+ }
+
+ /**
+ * The value of the request is set. This will be called by
+ * Pdu.fillin().
+ *
+ * @param n the index of the value
+ * @param a_var the value
+ * @see Pdu#new_value
+ */
+ protected void new_value(int n, varbind a_var)
+ {
+ if (n == 0)
+ {
+ var = a_var;
+ }
+ }
+
+ /**
+ * This method notifies all observers.
+ * This will be called by Pdu.fillin().
+ *
+ *
+ * Unless an exception occurred the Object to the update() method of the
+ * Observer will be a varbind, so any AsnObject type can be returned.
+ * In the case of an exception, that exception will be passed.
+ *
+ */
+ protected void tell_them()
+ {
+ notifyObservers(var);
+ }
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/OneGetPdu.java b/src/main/java/uk/co/westhawk/snmp/pdu/OneGetPdu.java
new file mode 100644
index 0000000..325fbc6
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/OneGetPdu.java
@@ -0,0 +1,156 @@
+// NAME
+// $RCSfile: OneGetPdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.13 $
+// CREATED
+// $Date: 2006/01/17 17:49:53 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1996 - 1998 by Westhawk Ltd (www.westhawk.nl)
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.stack.*;
+import java.util.*;
+
+/**
+ *
+ * The OneGetPdu class will ask for one (1) object (OID), based on
+ * the Get request.
+ *
+ *
+ *
+ * Unless an exception occurred the Object to the update() method of the
+ * Observer will be a varbind, so any AsnObject type can be returned.
+ * In the case of an exception, that exception will be passed.
+ *
+ *
+ *
+ * For SNMPv3: The receiver of a request PDU acts as the authoritative engine.
+ *
+ *
+ * @see varbind
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.13 $ $Date: 2006/01/17 17:49:53 $
+ */
+public class OneGetPdu extends GetPdu
+{
+ private static final String version_id =
+ "@(#)$Id: OneGetPdu.java,v 3.13 2006/01/17 17:49:53 birgit Exp $ Copyright Westhawk Ltd";
+
+ varbind var;
+
+ /**
+ * Constructor.
+ *
+ * @param con The context of the request
+ */
+ public OneGetPdu(SnmpContextBasisFace con)
+ {
+ super(con);
+ }
+
+ /**
+ * Constructor that will send the request immediately. No Observer
+ * is set.
+ *
+ * @param con the SnmpContextBasisFace
+ * @param oid the oid
+ */
+ public OneGetPdu(SnmpContextBasisFace con, String oid)
+ throws PduException, java.io.IOException
+ {
+ this(con, oid, null);
+ }
+
+ /**
+ * Constructor that will send the request immediately.
+ *
+ * @param con the SnmpContextBasisFace
+ * @param oid the oid
+ * @param o the Observer that will be notified when the answer is received
+ */
+ public OneGetPdu(SnmpContextBasisFace con, String oid, Observer o)
+ throws PduException, java.io.IOException
+ {
+ super(con);
+ if (o != null)
+ {
+ addObserver(o);
+ }
+ addOid(oid);
+ send();
+ }
+
+ /**
+ * The value of the request is set. This will be called by
+ * Pdu.fillin().
+ *
+ * @param n the index of the value
+ * @param a_var the value
+ * @see Pdu#new_value
+ */
+ protected void new_value(int n, varbind a_var)
+ {
+ if (n == 0)
+ {
+ var = a_var;
+ }
+ }
+
+ /**
+ * This method notifies all observers.
+ * This will be called by Pdu.fillin().
+ *
+ *
+ * Unless an exception occurred the Object to the update() method of the
+ * Observer will be a varbind, so any AsnObject type can be returned.
+ * In the case of an exception, that exception will be passed.
+ *
+ */
+ protected void tell_them()
+ {
+ notifyObservers(var);
+ }
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/OneInformPdu.java b/src/main/java/uk/co/westhawk/snmp/pdu/OneInformPdu.java
new file mode 100644
index 0000000..0538ca6
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/OneInformPdu.java
@@ -0,0 +1,166 @@
+// NAME
+// $RCSfile: OneInformPdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.5 $
+// CREATED
+// $Date: 2006/02/09 14:20:09 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2002 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.stack.*;
+import java.util.*;
+
+/**
+ *
+ * The OneInformPdu class will inform a manager about one
+ * object (OIDs), based on the Inform request.
+ *
+ *
+ *
+ * This class represents the SNMP Inform Request PDU. Inform Requests
+ * are sent between managers. It is a kind of 'acknowlegded' trap since
+ * the receiving end should send a Response PDU as reply.
+ * The varbind list has the same elements as the TrapPduv2.
+ *
+ *
+ *
+ * Note, this PDU should be sent to port 162 (the default trap port) by
+ * default. You will have to create a SnmpContext with the
+ * ListeningContextFace.DEFAULT_TRAP_PORT as parameter!
+ *
+ *
+ *
+ * For SNMPv3: The receiver of an inform PDU acts as the authoritative engine.
+ *
+ *
+ * @deprecated As of 4_14, just use {@link InformPdu}
+ * @see InformPdu_vec
+ * @see varbind
+ * @see ListeningContextFace#DEFAULT_TRAP_PORT
+ * @since 4_12
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.5 $ $Date: 2006/02/09 14:20:09 $
+ */
+public class OneInformPdu extends InformPdu
+{
+ private static final String version_id =
+ "@(#)$Id: OneInformPdu.java,v 3.5 2006/02/09 14:20:09 birgit Exp $ Copyright Westhawk Ltd";
+
+ varbind var;
+
+/**
+ * Constructor.
+ *
+ * @param con The context (v2c or v3) of the PDU
+ */
+public OneInformPdu(SnmpContextBasisFace con)
+{
+ super(con);
+}
+
+/**
+ * Constructor that will send the request immediately. No Observer
+ * is set.
+ *
+ * @param con the SnmpContextBasisFace
+ * @param oid the oid
+ */
+public OneInformPdu(SnmpContextBasisFace con, String oid)
+throws PduException, java.io.IOException
+{
+ this(con, oid, null);
+}
+
+/**
+ * Constructor that will send the request immediately.
+ *
+ * @param con the SnmpContextBasisFace
+ * @param oid the oid
+ * @param o the Observer that will be notified when the answer is received
+ */
+public OneInformPdu(SnmpContextBasisFace con, String oid, Observer o)
+throws PduException, java.io.IOException
+{
+ super(con);
+ if (o != null)
+ {
+ addObserver(o);
+ }
+ addOid(oid);
+ send();
+}
+
+/**
+ * The value of the request is set. This will be called by
+ * InformPdu.fillin().
+ *
+ * @param n the index of the value
+ * @param a_var the value
+ * @see Pdu#new_value
+ */
+protected void new_value(int n, varbind a_var)
+{
+ if (n == 0)
+ {
+ var = a_var;
+ }
+}
+
+/**
+ * This method notifies all observers.
+ * This will be called by InformPdu.fillin().
+ *
+ *
+ * Unless an exception occurred the Object to the update() method of the
+ * Observer will be a varbind, so any AsnObject type can be returned.
+ * In the case of an exception, that exception will be passed.
+ *
+ */
+protected void tell_them()
+{
+ notifyObservers(var);
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/OneIntPdu.java b/src/main/java/uk/co/westhawk/snmp/pdu/OneIntPdu.java
new file mode 100644
index 0000000..53884e8
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/OneIntPdu.java
@@ -0,0 +1,189 @@
+// NAME
+// $RCSfile: OneIntPdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.14 $
+// CREATED
+// $Date: 2006/11/29 16:12:50 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.stack.*;
+import java.util.*;
+
+/**
+ *
+ * The OneIntPdu class will ask for one (1) object (oid) of the
+ * AsnInteger type, based on the Get request.
+ *
+ *
+ *
+ * Unless an exception occurred the Object to the update() method of the
+ * Observer will be an Integer.
+ * In the case of an exception, that exception will be passed.
+ *
+ *
+ *
+ * For SNMPv3: The receiver of a request PDU acts as the authoritative engine.
+ *
+ *
+ * @see GetPdu_vec
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.14 $ $Date: 2006/11/29 16:12:50 $
+ */
+public class OneIntPdu extends GetPdu
+{
+ private static final String version_id =
+ "@(#)$Id: OneIntPdu.java,v 3.14 2006/11/29 16:12:50 birgit Exp $ Copyright Westhawk Ltd";
+
+ Integer value;
+
+ /**
+ * Constructor.
+ *
+ * @param con The context of the request
+ */
+ public OneIntPdu(SnmpContextBasisFace con)
+ {
+ super(con);
+ }
+
+ /**
+ * Constructor that will send the request immediately. No Observer
+ * is set.
+ *
+ * @param con the SnmpContextBasisFace
+ * @param oid the oid
+ */
+ public OneIntPdu(SnmpContextBasisFace con, String oid)
+ throws PduException, java.io.IOException
+ {
+ this(con, oid, null);
+ }
+
+ /**
+ * Constructor that will send the request immediately.
+ *
+ * @param con the SnmpContextBasisFace
+ * @param oid the oid
+ * @param o the Observer that will be notified when the answer is received
+ */
+ public OneIntPdu(SnmpContextBasisFace con, String oid, Observer o)
+ throws PduException, java.io.IOException
+ {
+ super(con);
+ if (o != null)
+ {
+ addObserver(o);
+ }
+ addOid(oid);
+ send();
+ }
+
+
+ /**
+ * Returns the value (the answer) of this request.
+ *
+ * @return the value
+ */
+ public Integer getValue()
+ {
+ return value;
+ }
+
+ /**
+ * The value of the request is set. This will be called by
+ * Pdu.fillin().
+ *
+ * @param n the index of the value
+ * @param res the value
+ * @see Pdu#new_value
+ */
+ protected void new_value(int n, varbind res)
+ {
+ AsnObject val = res.getValue();
+ if (val instanceof AsnInteger)
+ {
+ AsnInteger va = (AsnInteger) res.getValue();
+ if (n == 0)
+ {
+ value = new Integer(va.getValue());
+ }
+ }
+ else
+ {
+ value = null;
+ }
+ }
+
+ /**
+ * This method notifies all observers.
+ * This will be called by Pdu.fillin().
+ *
+ *
+ * Unless an exception occurred the Object to the update() method of the
+ * Observer will be an Integer.
+ * In the case of an exception, that exception will be passed.
+ *
+ */
+ protected void tell_them()
+ {
+ notifyObservers(value);
+ }
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/OneSetPdu.java b/src/main/java/uk/co/westhawk/snmp/pdu/OneSetPdu.java
new file mode 100644
index 0000000..cdc68b7
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/OneSetPdu.java
@@ -0,0 +1,164 @@
+// NAME
+// $RCSfile: OneSetPdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.14 $
+// CREATED
+// $Date: 2006/01/17 17:49:53 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+
+/*
+ * Copyright (C) 1996 - 1998 by Westhawk Ltd (www.westhawk.nl)
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.stack.*;
+import java.util.*;
+
+/**
+ *
+ * The OneSetPdu class will set the value of one (1) object (oid), based
+ * on the Set request.
+ *
+ *
+ *
+ * Unless an exception occurred the Object to the update() method of the
+ * Observer will be a varbind, so any AsnObject type can be returned.
+ * In the case of an exception, that exception will be passed.
+ *
+ *
+ *
+ * For SNMPv3: The receiver of a request PDU acts as the authoritative engine.
+ *
+ *
+ * @deprecated As of 4_14, just use {@link SetPdu}
+ * @see varbind
+ * @see SetPdu_vec
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.14 $ $Date: 2006/01/17 17:49:53 $
+ */
+public class OneSetPdu extends SetPdu
+{
+ private static final String version_id =
+ "@(#)$Id: OneSetPdu.java,v 3.14 2006/01/17 17:49:53 birgit Exp $ Copyright Westhawk Ltd";
+
+ varbind var;
+
+ /**
+ * Constructor.
+ *
+ * @param con The context of the request
+ */
+ public OneSetPdu(SnmpContextBasisFace con)
+ {
+ super(con);
+ }
+
+ /**
+ * Constructor that will send the request immediately. No Observer
+ * is set.
+ *
+ * @param con the SnmpContextBasisFace
+ * @param oid the oid
+ * @param val The value
+ */
+ public OneSetPdu(SnmpContextBasisFace con, String oid, AsnObject val)
+ throws PduException, java.io.IOException
+ {
+ this(con, oid, val, null);
+ }
+
+ /**
+ * Constructor that will send the request immediately.
+ *
+ * @param con the SnmpContextBasisFace
+ * @param oid the oid
+ * @param val The value
+ * @param o the Observer that will be notified when the answer is received
+ */
+ public OneSetPdu(SnmpContextBasisFace con, String oid, AsnObject val, Observer o)
+ throws PduException, java.io.IOException
+ {
+ super(con);
+ if (o != null)
+ {
+ addObserver(o);
+ }
+ addOid(oid, val);
+ send();
+ }
+
+ /**
+ * The value of the request is set. This will be called by
+ * Pdu.fillin(). This is the value of the OID after the Set request
+ * was done. If the SNMP server allowed the set, this will be the
+ * same value as was set in SetPdu.addOid().
+ *
+ * @param n the index of the value
+ * @param a_var the value
+ * @see Pdu#new_value
+ * @see SetPdu#addOid(String, AsnObject)
+ */
+ protected void new_value(int n, varbind a_var)
+ {
+ if (n == 0)
+ {
+ var = a_var;
+ }
+ }
+
+ /**
+ * This method notifies all observers.
+ * This will be called by Pdu.fillin().
+ *
+ *
+ * Unless an exception occurred the Object to the update() method of the
+ * Observer will be a varbind, so any AsnObject type can be returned.
+ * In the case of an exception, that exception will be passed.
+ *
+ */
+ protected void tell_them()
+ {
+ notifyObservers(var);
+ }
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/OneTrapPduv1.java b/src/main/java/uk/co/westhawk/snmp/pdu/OneTrapPduv1.java
new file mode 100644
index 0000000..5f289af
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/OneTrapPduv1.java
@@ -0,0 +1,94 @@
+// NAME
+// $RCSfile: OneTrapPduv1.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.7 $
+// CREATED
+// $Date: 2006/03/23 14:54:09 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2001 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import java.util.*;
+import java.io.*;
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.util.*;
+
+/**
+ * This class represents the ASN SNMPv1 Trap PDU object.
+ * See RFC1157-SNMP.
+ *
+ * @deprecated As of 4_14, just use {@link TrapPduv1}
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.7 $ $Date: 2006/03/23 14:54:09 $
+ */
+public class OneTrapPduv1 extends TrapPduv1
+{
+ private static final String version_id =
+ "@(#)$Id: OneTrapPduv1.java,v 3.7 2006/03/23 14:54:09 birgit Exp $ Copyright Westhawk Ltd";
+
+
+/**
+ * Constructor.
+ *
+ * @param con The context v1 of the OneTrapPduv1
+ * @see SnmpContext
+ */
+public OneTrapPduv1(SnmpContext con)
+{
+ super(con);
+}
+
+/**
+ * Constructor.
+ *
+ * @param con The context v1 of the OneTrapPduv1
+ * @see SnmpContext
+ */
+public OneTrapPduv1(SnmpContextPool con)
+{
+ super(con);
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/OneTrapPduv2.java b/src/main/java/uk/co/westhawk/snmp/pdu/OneTrapPduv2.java
new file mode 100644
index 0000000..9d6da04
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/OneTrapPduv2.java
@@ -0,0 +1,88 @@
+// NAME
+// $RCSfile: OneTrapPduv2.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.9 $
+// CREATED
+// $Date: 2006/03/23 14:54:09 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2001 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import java.util.*;
+import java.io.*;
+
+import uk.co.westhawk.snmp.stack.*;
+import uk.co.westhawk.snmp.util.*;
+
+/**
+ * This class represents the ASN SNMPv2c (and higher) Trap PDU object.
+ * See RFC1157-SNMP.
+ *
+ *
+ * For SNMPv3: The sender of a trap PDU acts as the authoritative engine.
+ *
+ *
+ * @deprecated As of 4_14, just use {@link TrapPduv2}
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.9 $ $Date: 2006/03/23 14:54:09 $
+ */
+public class OneTrapPduv2 extends TrapPduv2
+{
+ private static final String version_id =
+ "@(#)$Id: OneTrapPduv2.java,v 3.9 2006/03/23 14:54:09 birgit Exp $ Copyright Westhawk Ltd";
+
+
+/**
+ * Constructor.
+ *
+ * @param con The context (v2c, v3) of the OneTrapPduv2
+ * @see SnmpContext
+ */
+public OneTrapPduv2(SnmpContextBasisFace con)
+{
+ super(con);
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/PassiveTrapPduv1.java b/src/main/java/uk/co/westhawk/snmp/pdu/PassiveTrapPduv1.java
new file mode 100644
index 0000000..6c1018a
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/PassiveTrapPduv1.java
@@ -0,0 +1,107 @@
+// NAME
+// $RCSfile: PassiveTrapPduv1.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.7 $
+// CREATED
+// $Date: 2006/03/23 14:54:09 $
+// COPYRIGHT
+// ERG Group Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2002 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.stack.*;
+
+/**
+ * This class represents the ASN SNMP v1 Trap PDU object
+ * that does not create a thread to send itself. It must be used with the
+ * context class PassiveSnmpContext. The original purpose of the
+ * Passive classes is to allow the stack to be used in environments where
+ * thread creation is unwanted, eg database JVMs such as Oracle JServer.
+ * See SNMPv2-PDU.
+ *
+ *
+ * See
+ * notes
+ * on how to send traps in an Oracle JServer environment.
+ *
+ *
+ * @see PassiveTrapPduv2
+ * @since 4_12
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.7 $ $Date: 2006/03/23 14:54:09 $
+ */
+public class PassiveTrapPduv1 extends TrapPduv1
+{
+ private static final String version_id =
+ "@(#)$Id: PassiveTrapPduv1.java,v 3.7 2006/03/23 14:54:09 birgit Exp $ Copyright ERG Group Ltd";
+
+/**
+ * Constructor.
+ *
+ * @param con The context (v1) of the PDU.
+ * This is of type PassiveSnmpContext to ensure that the correct threading
+ * behaviour occurs.
+ */
+public PassiveTrapPduv1(PassiveSnmpContext con)
+{
+ super(con);
+
+ // this makes the base class PDU believe that the trap is already
+ // awaiting transmission therefore it does not create a transmitter
+ // for this pdu
+ added = true;
+}
+
+/**
+ * Override of the operation in PDU. Send the trap in the
+ * callers thread. That is, don't create a sending thread
+ * or add it to a queue or anything, just go straight to the socket.
+ */
+public void addToTrans()
+{
+ sendme();
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/PassiveTrapPduv2.java b/src/main/java/uk/co/westhawk/snmp/pdu/PassiveTrapPduv2.java
new file mode 100644
index 0000000..30fb59c
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/PassiveTrapPduv2.java
@@ -0,0 +1,107 @@
+// NAME
+// $RCSfile: PassiveTrapPduv2.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.8 $
+// CREATED
+// $Date: 2006/03/23 14:54:09 $
+// COPYRIGHT
+// ERG Group Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2001 by ERG Group Ltd
+ * www.erggroup.com
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Mike Waters
+ */
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.stack.*;
+
+/**
+ * This class represents the ASN SNMP v2c (and higher) Trap PDU object
+ * that does not create a thread to send itself. It must be used with the
+ * context class PassiveSnmpContextv2c. The original purpose of the
+ * Passive classes is to allow the stack to be used in environments where
+ * thread creation is unwanted, eg database JVMs such as Oracle JServer.
+ * See SNMPv2-PDU.
+ *
+ *
+ * See
+ * notes
+ * on how to send traps in an Oracle JServer environment.
+ *
+ *
+ * @see PassiveTrapPduv1
+ * @since 4_12
+ *
+ * @author Mike Waters, ERG Group
+ * @version $Revision: 3.8 $ $Date: 2006/03/23 14:54:09 $
+ */
+public class PassiveTrapPduv2 extends TrapPduv2
+{
+ private static final String version_id =
+ "@(#)$Id: PassiveTrapPduv2.java,v 3.8 2006/03/23 14:54:09 birgit Exp $ Copyright ERG Group Ltd";
+
+/**
+ * Constructor.
+ *
+ * @param con The context (v2c) of the PDU.
+ * This is of type PassiveSnmpContextv2c to ensure that the correct threading
+ * behaviour occurs.
+ */
+public PassiveTrapPduv2(PassiveSnmpContextv2c con)
+{
+ super(con);
+
+ // this makes the base class PDU believe that the trap is already
+ // awaiting transmission therefore it does not create a transmitter
+ // for this pdu
+ added = true;
+}
+
+/**
+ * Override of the operation in PDU. Send the trap in the
+ * callers thread. That is, don't create a sending thread
+ * or add it to a queue or anything, just go straight to the socket.
+ */
+public void addToTrans()
+{
+ sendme();
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/SetPdu_vec.java b/src/main/java/uk/co/westhawk/snmp/pdu/SetPdu_vec.java
new file mode 100644
index 0000000..e75eaac
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/SetPdu_vec.java
@@ -0,0 +1,138 @@
+// NAME
+// $RCSfile: SetPdu_vec.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.14 $
+// CREATED
+// $Date: 2006/11/29 16:12:50 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1996 - 1998 by Westhawk Ltd (www.westhawk.nl)
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.stack.*;
+import java.lang.*;
+
+/**
+ *
+ * The SetPdu_vec class will set the value of a number of
+ * objects (OIDs), based on the Set request.
+ *
+ *
+ *
+ * Specify with addOid() the OIDs that should be requested with this
+ * PDU request. No more than count (see constructor) should be added.
+ * Add an Observer to the PDU with addObserver(), and send the PDU
+ * with send().
+ *
+ *
+ *
+ * If no exception occurred whilst receiving the response, the Object to the
+ * update() method of the Observer will be an array of
+ * varbinds, so they may contains any AsnObject type.
+ * If an exception occurred, that exception will be passed as the Object
+ * to the update() method.
+ *
+ *
+ * @see SetPdu#addOid
+ * @see Pdu#send
+ * @see varbind
+ * @see OneSetPdu
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.14 $ $Date: 2006/11/29 16:12:50 $
+ */
+public class SetPdu_vec extends SetPdu
+{
+ private static final String version_id =
+ "@(#)$Id: SetPdu_vec.java,v 3.14 2006/11/29 16:12:50 birgit Exp $ Copyright Westhawk Ltd";
+
+ varbind[] value;
+
+ /**
+ * Constructor.
+ *
+ * @param con The context of the request
+ * @param count The number of OIDs to be get
+ */
+ public SetPdu_vec(SnmpContextBasisFace con, int count)
+ {
+ super(con);
+ value = new varbind[count];
+ }
+
+ /**
+ * The value of the request is set. This will be called by
+ * Pdu.fillin(). These are the values of the OIDs after the Set request
+ * was done. If the SNMP server allowed the sets, these will be the
+ * same values as was set in SetPdu.addOid().
+ *
+ * @param n the index of the value
+ * @param var the value
+ * @see Pdu#new_value
+ * @see SetPdu#addOid(String, AsnObject)
+ */
+ protected void new_value(int n, varbind var)
+ {
+ if (n
+ * If no exception occurred whilst receiving the response, the
+ * Object to the update() method of the Observer will be an array of
+ * varbinds, so they may contains any AsnObject type. If an
+ * exception occurred, that exception will be passed as the Object
+ * to the update() method.
+ *
+ */
+ protected void tell_them()
+ {
+ notifyObservers(value);
+ }
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/pdu/UpSincePdu.java b/src/main/java/uk/co/westhawk/snmp/pdu/UpSincePdu.java
new file mode 100644
index 0000000..d808e01
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/pdu/UpSincePdu.java
@@ -0,0 +1,149 @@
+// NAME
+// $RCSfile: UpSincePdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.16 $
+// CREATED
+// $Date: 2006/11/29 16:12:50 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1996 - 1998 by Westhawk Ltd (www.westhawk.nl)
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.pdu;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.stack.*;
+import java.util.*;
+
+/**
+ * The UpSincePdu class will send a Get request for the sysUpTime and
+ * will calculate that date the system rebooted the last time.
+ *
+ * @author Tim Panton
+ * @version $Revision: 3.16 $ $Date: 2006/11/29 16:12:50 $
+ */
+public class UpSincePdu extends GetPdu
+{
+ private static final String version_id =
+ "@(#)$Id: UpSincePdu.java,v 3.16 2006/11/29 16:12:50 birgit Exp $ Copyright Westhawk Ltd";
+
+ Date since;
+ /**
+ * The oid of sysUpTime
+ */
+ public final static String SYSUPTIME="1.3.6.1.2.1.1.3.0";
+
+ /**
+ * Constructor that will send the request immediately.
+ *
+ * @param con The context of the request
+ * @param o the Observer that will be notified when the answer is received
+ */
+ public UpSincePdu(SnmpContextBasisFace con, Observer o)
+ throws PduException, java.io.IOException
+ {
+ super(con);
+ addOid(SYSUPTIME);
+ if (o != null)
+ {
+ addObserver(o);
+ }
+ send();
+ }
+
+
+ /**
+ * Returns the date when the system went up, (sysUpTime).
+ * @return the date
+ */
+ public Date getDate()
+ {
+ return since;
+ }
+
+ /**
+ * The value of the request is set. This will be called by
+ * Pdu.fillin().
+ *
+ * @param n the index of the value
+ * @param res the value
+ * @see Pdu#new_value
+ */
+ protected void new_value(int n, varbind res)
+ {
+ // given the uptime in centi seconds and the time now,
+ // calculate the time it rebooted
+
+ AsnObject val = res.getValue();
+ if (val instanceof AsnUnsInteger)
+ {
+ AsnUnsInteger va = (AsnUnsInteger) res.getValue();
+ if (n == 0)
+ {
+ long value = va.getValue();
+ Date now = new Date();
+ long then = now.getTime();
+ then -= 10 * value;
+ since = new Date(then);
+ }
+ }
+ else
+ {
+ since = null;
+ }
+ }
+
+ /**
+ * This method notifies all observers.
+ * This will be called by Pdu.fillin().
+ *
+ *
+ * Unless an exception occurred the Object to the update() method of the
+ * Observer will be a Date.
+ * In the case of an exception, that exception will be passed.
+ *
+ */
+ protected void tell_them()
+ {
+ notifyObservers(since);
+ }
+
+}
+
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AbstractSnmpContext.java b/src/main/java/uk/co/westhawk/snmp/stack/AbstractSnmpContext.java
new file mode 100644
index 0000000..6eadaa9
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AbstractSnmpContext.java
@@ -0,0 +1,1009 @@
+// NAME
+// $RCSfile: AbstractSnmpContext.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.33 $
+// CREATED
+// $Date: 2009/03/05 12:48:04 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.io.*;
+import java.util.*;
+import uk.co.westhawk.snmp.net.*;
+import uk.co.westhawk.snmp.event.*;
+import uk.co.westhawk.snmp.util.*;
+
+/**
+ * This class contains the abstract SNMP context that is needed by every
+ * Pdu to send a SNMP v1, v2c or v3 request.
+ * The context also provides functionality to receive PDUs.
+ *
+ *
+ * destroy()
should be called when the context is no longer
+ * used. This is the only way the threads will be stopped and garbage
+ * collected.
+ *
+ *
+ * @see SnmpContext
+ * @see SnmpContextv2c
+ * @see SnmpContextv3
+ *
+ * @author Tim Panton
+ * @version $Revision: 3.33 $ $Date: 2009/03/05 12:48:04 $
+ */
+public abstract class AbstractSnmpContext extends Object
+ implements SnmpContextBasisFace, Runnable, RawPduListener
+{
+ private static final String version_id =
+ "@(#)$Id: AbstractSnmpContext.java,v 3.33 2009/03/05 12:48:04 birgita Exp $ Copyright Westhawk Ltd";
+
+ private ContextSocketFace soc;
+ private Transmitter [] transmitters;
+ private Pdu [] pdus;
+ private Thread me;
+ private String basename;
+ private volatile boolean stopRequested;
+ // thanks to Nick Sheen nsheen@tippingpoint.com for pointing out that volatile is needed here
+
+ protected String typeSocket;
+ protected String hostname;
+ protected String bindAddr;
+ protected int hostPort;
+ protected int maxRecvSize;
+ protected boolean isDestroyed;
+ protected boolean anyPduExpectingResponse = false;
+ protected RequestPduReceivedSupport pduSupport;
+ protected TrapReceivedSupport trapSupport;
+
+
+/**
+ * Processes an incoming response. Has to be overload by each context.
+ * This is called in the run() method.
+ *
+ * @see #run
+ */
+protected abstract void processIncomingResponse(ByteArrayInputStream in)
+throws DecodingException, IOException;
+
+/**
+ * Encodes a PDU. This is for internal use only and should
+ * NOT be called by the developer.
+ * This is called by the the PDU itself and is added to the interface to
+ * cover the different kind of Contexts.
+ * Has to be overload by each context.
+ *
+ * @param msg_type The message type
+ * @param rId The message id
+ * @param errstat The error status
+ * @param errind The error index
+ * @param ve The varbind list
+ * @param obj Additional object (only used in SNMPv3)
+ * @return The encoded packet
+ */
+public abstract byte[] encodePacket(byte msg_type, int rId, int errstat,
+ int errind, Enumeration ve, Object obj)
+ throws IOException, EncodingException;
+
+/**
+ * Processes an incoming pdu (but not a response). Has to be overload by each context.
+ * @see #rawPduReceived
+ */
+public abstract Pdu processIncomingPdu(byte [] message) throws DecodingException, IOException;
+
+/**
+ * Returns the SNMP version of this context. Has to be overload by each
+ * context.
+ */
+public abstract int getVersion();
+
+/**
+ * Constructor.
+ * The Standard socket type will be used.
+ *
+ * @param host The host to which the Pdu will be sent
+ * @param port The port where the SNMP server will be
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ */
+protected AbstractSnmpContext(String host, int port) throws IOException
+{
+ this(host, port, null, STANDARD_SOCKET);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocketA should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the Pdu will be sent
+ * @param port The port where the SNMP server will be
+ * @param typeSocketA The type of socket to use.
+ *
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ */
+protected AbstractSnmpContext(String host, int port, String typeSocketA)
+throws IOException
+{
+ this(host, port, null, typeSocketA);
+}
+
+/**
+ * Constructor.
+ *
+ * If bindAddress is null, then the system will pick up a valid local
+ * address to bind the socket.
+ *
+ * The typeSocket will indicate which type of socket to use. This way
+ * different handlers can be provided.
+ * It should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the Pdu will be sent
+ * @param port The port where the SNMP server will be
+ * @param bindAddress The local address the server will bind to
+ * @param typeSocketA The type of socket to use.
+ *
+ * @exception IOException Thrown when the socket cannot be
+ * created.
+ *
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ * @since 4_14
+ */
+protected AbstractSnmpContext(String host, int port, String bindAddress, String typeSocketA)
+throws IOException
+{
+ pdus = new Pdu[MAXPDU];
+ hostname = host;
+ hostPort = port;
+ bindAddr = bindAddress;
+ typeSocket = typeSocketA;
+ transmitters = new Transmitter[MAXPDU];
+ basename = host+"_"+ port+"_"+bindAddress;
+ trapSupport = new TrapReceivedSupport(this);
+ pduSupport = new RequestPduReceivedSupport(this);
+
+ isDestroyed = false;
+ stopRequested = false;
+ maxRecvSize = MSS;
+
+ soc = getSocket(typeSocket);
+ if (soc != null)
+ {
+ soc.create(hostname, hostPort, bindAddr);
+ if (AsnObject.debug > 12)
+ {
+ System.out.println(getClass().getName()
+ + ": soc.getLocalSocketAddress() = "
+ + soc.getLocalSocketAddress());
+ System.out.println(getClass().getName()
+ + ": soc.getRemoteSocketAddress() = "
+ + soc.getRemoteSocketAddress());
+ }
+ }
+}
+
+
+/**
+ * Returns a new socket, based on a particular type.
+ * Parameter type is first compare do STANDARD_SOCKET and TCP_SOCKET. If
+ * that doesn't match, type is assumed to be a fully qualified classname.
+ *
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ */
+static ContextSocketFace getSocket(String type) throws IOException
+{
+ ContextSocketFace sf = null;
+ if (type != null)
+ {
+ String className = null;
+ if (type.equals(STANDARD_SOCKET))
+ {
+ className = "uk.co.westhawk.snmp.net.StandardSocket";
+ }
+ else if (type.equals(TCP_SOCKET))
+ {
+ className = "uk.co.westhawk.snmp.net.TCPSocket";
+ }
+ else
+ {
+ className = type;
+ }
+
+ try
+ {
+ Class cl = Class.forName(className);
+ Object obj = cl.newInstance();
+ sf = (ContextSocketFace) obj;
+ }
+ catch (ClassNotFoundException exc)
+ {
+ String str = "AbstractSnmpContext.getSocket(): ClassNotFound problem " + exc.getMessage() + ", type=" + type;
+ throw (new IOException(str));
+ }
+ catch (InstantiationException exc)
+ {
+ String str = "AbstractSnmpContext.getSocket(): Instantiation problem " + exc.getMessage() + ", type=" + type;
+ throw (new IOException(str));
+ }
+ catch (IllegalAccessException exc)
+ {
+ String str = "AbstractSnmpContext.getSocket(): IllegalAccess problem " + exc.getMessage() + ", type=" + type;
+ throw (new IOException(str));
+ }
+ catch (ClassCastException exc)
+ {
+ String str = "AbstractSnmpContext.getSocket(): ClassCast problem " + exc.getMessage() + ", type=" + type;
+ throw (new IOException(str));
+ }
+
+ if (sf == null)
+ {
+ String str = "AbstractSnmpContext.getSocket(): Cannot create socket " + type;
+ throw (new IOException(str));
+ }
+ else
+ {
+ if (AsnObject.debug > 12)
+ {
+ System.out.println("AbstractSnmpContext.getSocket(): New socket " + sf.getClass().getName());
+ }
+ }
+ }
+ return sf;
+}
+
+public String getHost()
+{
+ return hostname;
+}
+
+/**
+ * Returns the IP address string
+ * aaa.bbb.ccc.ddd (IPv4) or a:b:c:d:e:f:g:h (IPv6)
+ * of the host.
+ *
+ * @return The IP address of the host
+ * @deprecated As of 4_14, use {@link #getSendToHostAddress()}
+ */
+public String getHostAddress()
+{
+ return getSendToHostAddress();
+}
+
+public String getSendToHostAddress()
+{
+ String res = "";
+ if (soc != null)
+ {
+ res = soc.getSendToHostAddress();
+ }
+ return res;
+}
+
+public String getReceivedFromHostAddress()
+{
+ String res = "";
+ if (soc != null)
+ {
+ res = soc.getReceivedFromHostAddress();
+ }
+ return res;
+}
+
+
+public int getPort()
+{
+ return hostPort;
+}
+
+public String getBindAddress()
+{
+ return bindAddr;
+}
+
+public String getTypeSocket()
+{
+ return typeSocket;
+}
+
+/**
+ * Returns the maximum number of bytes this context will read from the
+ * socket. By default this will be set to MSS
(i.e. 1300).
+ *
+ * @since 4_12
+ * @see SnmpContextBasisFace#MSS
+ * @see #setMaxRecvSize(int)
+ * @return The number
+ */
+public int getMaxRecvSize()
+{
+ return maxRecvSize;
+}
+
+/**
+ * Sets the maximum number of bytes this context will read from the
+ * socket. By default this will be set to MSS
(i.e. 1300).
+ * The default size seems a reasonable size. The problem usually occurs
+ * when sending Bulk requests.
+ *
+ *
+ * If a packet arrives that is bigger than the maximum size of received
+ * bytes, the stack will try to decode it nevertheless. The usual
+ * error that will occur is:
+ *
+ *
+ * Error message: "Incorrect packet. No of bytes received less than packet length."
+ *
+ *
+ *
+ * Although UDP datagrams can be fragmented (fragmentation is part of
+ * the network layer (IP), not the transport layer (UDP/TCP)), some
+ * firewalls reject incoming fragments. Therefor it is best not to set
+ * maxRecvSize higher than the largest packet size you can get through
+ * your network topology.
+ *
+ *
+ *
+ * Thanks to Pete Kazmier (pete@kazmier.com) for the suggestion.
+ *
+ *
+ *
+ * Note, this property is NOT supported in any of the SNMPContextXXPool
+ * classes.
+ *
+ *
+ * @since 4_12
+ * @see SnmpContextBasisFace#MSS
+ * @see #getMaxRecvSize()
+ * @param no The new number
+ */
+public void setMaxRecvSize(int no)
+{
+ maxRecvSize = no;
+}
+
+/**
+ * Returns the thread usage of the AbstractSnmpContext.
+ * It returns a String in the form of =PO=QR--------------0
.
+ *
+ *
+ * The String represents the array of transmitters.
+ * Each character represents a transmitter slot.
+ * The transmitters form a thread pool of a maximum size, MAXPDU.
+ * Each transmitter is used to wait for one PDU response at a given
+ * moment in time.
+ * When the response is received the transmitter will stop running, but
+ * is not destroyed. It will be reused.
+ *
+ *
+ *
+ * Meaning of each character:
+ *
+ *
+ * -
a transmitter slot has not yet been allocated a thread
+ * =
there is a thread but it is idle
+ * A->Z
the thread is transmitting a Pdu
+ * -
+ * The last character represents the context's recv thread:
+ *
+ * 0
there isn't one
+ * 1
it exists but isn't running
+ * 2
it exists and is alive.
+ *
+ *
+ *
+ *
+ * @since 4_12
+ * @return The thread usage of the AbstractSnmpContext
+ */
+public String getDebugString()
+{
+ char [] cret = new char[MAXPDU+1];
+ for (int i=0;i
+ * It closes the socket.
+ * The thread will actually stop/finish when the run() finishes. Since
+ * the socket is closed, the run() will fall through almost instantly.
+ *
+ *
+ *
+ * Note: The thread(s) will not die immediately; this will take about
+ * half a minute.
+ *
+ *
+ * @see ListeningContext#destroy()
+ * @see ListeningContextPool#destroyPool()
+ */
+public synchronized void destroy()
+{
+ if (isDestroyed == false)
+ {
+ stopRequested = true;
+ if (AsnObject.debug > 12)
+ {
+ System.out.println(getClass().getName() + ".destroy(): Closing socket ");
+ }
+ soc.close();
+ isDestroyed = true;
+
+ // If run() has been started, then it will destroy the
+ // transmitter threads when it finishes. Otherwise they must be
+ // destroyed here.
+ if (me == null)
+ {
+ freeTransmitters();
+ }
+ }
+}
+
+public boolean isDestroyed()
+{
+ return isDestroyed;
+}
+
+/**
+ * This method will stop the thread.
+ * All transmitters, PDUs in flight and traplisteners will be removed
+ * when run() finishes.
+ *
+ * It does NOT close the socket.
+ * The thread will actually stop/finish when the run() finishes. That is when
+ * a packet arrives on the socket or when the socket times out.
+ *
+ *
+ *
+ * We have deprecated this method since there is no point in stopping
+ * the context, but not destroying it. The context cannot start again anyway.
+ * The difference between destroy() and stop() was not very clear.
+ *
+ *
+ * @deprecated As of version 4_12, should use {@link #destroy()}
+ * @see #destroy()
+ */
+public synchronized void stop()
+{
+ stopRequested = true;
+}
+
+/**
+ * We wait for any incoming packets. After receiving one, decode
+ * the packet into an Pdu. The Pdu will notify the observers waiting
+ * for an response.
+ *
+ *
+ * Thanks to Chris Barlock <barlock@us.ibm.com> who reported a
+ * NullPointerException in run() on variable 'me' and introduced the
+ * variable stopRequested.
+ *
+ */
+public void run()
+{
+ // while It is visible
+ while (!stopRequested)
+ {
+ // block for incoming packets
+ me.yield();
+ try
+ {
+ if (stopRequested)
+ {
+ break;
+ }
+
+ StreamPortItem item = soc.receive(maxRecvSize);
+ ByteArrayInputStream in = item.getStream();
+
+ if (AsnObject.debug > 10)
+ {
+ int nb = in.available();
+ byte [] bu = new byte[nb];
+ in.read(bu);
+ in.reset();
+
+ SnmpUtilities.dumpBytes(getClass().getName()
+ + ".run(): Received from "
+ + item.getHostAddress()
+ + ", from port " + item.getHostPort()
+ + ": ", bu);
+ }
+ processIncomingResponse(in);
+ }
+ catch (IOException exc)
+ {
+ if (exc instanceof InterruptedIOException)
+ {
+ if (AsnObject.debug > 15)
+ {
+ System.out.println(getClass().getName() + ".run(): Idle recv " + exc.getMessage());
+ }
+ }
+ else if (exc instanceof java.net.SocketException)
+ {
+ if (AsnObject.debug > 15)
+ {
+ System.out.println(getClass().getName() + ".run(): SocketException " + exc.getMessage());
+ }
+ }
+ else
+ {
+ if (AsnObject.debug > 0)
+ {
+ System.out.println(getClass().getName() + ".run(): "
+ + exc.getClass().getName() + " " + exc.getMessage());
+ exc.printStackTrace();
+ }
+ }
+ }
+ catch (DecodingException exc)
+ {
+ if (AsnObject.debug > 1)
+ {
+ System.out.println(getClass().getName() + ".run(): DecodingException: " + exc.getMessage());
+ }
+ }
+ catch (Exception exc)
+ {
+ if (AsnObject.debug > 1)
+ {
+ System.out.println(getClass().getName() + ".run(): Exception: " + exc.getMessage());
+ exc.printStackTrace();
+ }
+ }
+ catch (Error err)
+ {
+ if (AsnObject.debug > 1)
+ {
+ System.out.println(getClass().getName() + ".run(): Error: " + err.getMessage());
+ err.printStackTrace();
+ }
+ }
+ }
+
+ freeTransmitters();
+
+ trapSupport.empty();
+ pduSupport.empty();
+
+ // This used to actually create a listener. I do think this bug
+ // has been fixed, since no socket will be created in
+ // ListeningContextPool, unless a listener has been added.
+ ListeningContextPool lcontext =
+ new ListeningContextPool(ListeningContextFace.DEFAULT_TRAP_PORT, bindAddr, typeSocket);
+ lcontext.removeRawPduListenerFromPool(this);
+
+ me = null;
+ soc = null;
+}
+
+
+
+/*
+ * By moving activate() from the constructor to here, the parameter
+ * maxRecvSize, changed in setMaxRecvSize(), gets a chance to actually
+ * change before run() starts.
+ * Thanks to Dave Hunt who reported this
+ * problem.
+ */
+public synchronized void sendPacket(byte[] p)
+{
+ if (isDestroyed == false)
+ {
+ activate();
+ try
+ {
+ if (AsnObject.debug > 10)
+ {
+ SnmpUtilities.dumpBytes("Sending to "
+ + soc.getSendToHostAddress() + ": ", p);
+ }
+
+ // Seen it throw an "java.io.IOException: Invalid argument"
+ // when the bind address was wrong, i.e. the packet reach
+ // the host over the interface
+ soc.send(p);
+ }
+ catch (IOException exc)
+ {
+ if (AsnObject.debug > 0)
+ {
+ System.out.println(getClass().getName() + ".sendPacket(): "
+ + exc.getClass().getName()
+ + " " + exc.getMessage());
+ exc.printStackTrace();
+ }
+ }
+ }
+}
+
+Pdu getPdu(Integer ReqId)
+{
+ return getPdu(ReqId.intValue());
+}
+
+Pdu getPdu(int rid)
+{
+ Pdu ret = null;
+ for (int i=0; i< MAXPDU; i++)
+ {
+ if ((pdus[i] != null) && (pdus[i].getReqId() == rid))
+ {
+ ret = pdus[i];
+ break;
+ }
+ }
+ return ret;
+}
+
+public synchronized boolean removePdu(int rid)
+{
+ boolean ret = false;
+ for (int i=0; i< MAXPDU; i++)
+ {
+ if ((pdus[i] != null) && (pdus[i].getReqId() == rid))
+ {
+ pdus[i] = null;
+ ret = true;
+ break;
+ }
+ }
+ return ret;
+}
+
+public synchronized boolean addPdu(Pdu p)
+throws IOException, PduException
+{
+ boolean done = false;
+ if (isDestroyed == true)
+ {
+ throw new EncodingException("Context can no longer be used, since it is already destroyed");
+ }
+ else
+ {
+ // I only want to start the receive thread when any of the
+ // context's PDUs is actually expecting a response. See activate().
+ if (anyPduExpectingResponse == false)
+ {
+ anyPduExpectingResponse = p.isExpectingResponse();
+ }
+ for (int i=0; i 2)
+ {
+ System.out.println(getClass().getName() + ".rawPduReceived(): DecodingException: " + exc.getMessage());
+ }
+ }
+ catch(IOException exc)
+ {
+ if (AsnObject.debug > 0)
+ {
+ System.out.println(getClass().getName() + ".rawPduReceived(): IOException "+ exc.getMessage());
+ }
+ }
+
+ }
+ else
+ {
+ if (AsnObject.debug > 5)
+ {
+ System.out.println(getClass().getName() + ".rawPduReceived(): "
+ + "Pdu host (" + hostAddress
+ + "), does not correspond with context host ("
+ + this.getSendToHostAddress() + ")");
+ }
+ }
+ }
+ else
+ {
+ if (AsnObject.debug > 5)
+ {
+ String theirs = SnmpUtilities.getSnmpVersionString(version);
+ String ours = SnmpUtilities.getSnmpVersionString(this.getVersion());
+ System.out.println(getClass().getName() + ".rawPduReceived(): "
+ + "Pdu version " + theirs
+ + ", does not correspond with context version "
+ + ours);
+ }
+ }
+}
+
+Transmitter getTrans(int i)
+{
+ if (transmitters[i] == null)
+ {
+ transmitters[i] = new Transmitter(basename+"_v"+getVersion()+"_Trans"+i);
+ }
+ return transmitters[i];
+}
+
+/**
+ * Creates and starts the Receive thread that allows this context to
+ * receive packets.
+ * Subclasses may override this to adjust the threading behaviour.
+ *
+ * @see PassiveSnmpContext#activate()
+ * @see PassiveSnmpContextv2c#activate()
+ */
+protected void activate()
+{
+ // Only start the thread when 'me' is null (i.e. no thread is running)
+ // AND when anyPduExpectingResponse is true.
+ // This way a context that only sends (for example) traps, will not
+ // start a listing thread.
+ if (me == null && anyPduExpectingResponse == true)
+ {
+ me = new Thread(this, basename+"_v"+getVersion()+"_Receive");
+ me.setPriority(me.MAX_PRIORITY);
+ me.start();
+ }
+}
+
+
+/**
+ * Frees the transmitters.
+ *
+ * @see #run()
+ * @see #destroy()
+ * @since 5_1
+ */
+// In version 5_0, this code lived in run().
+// Thanks to Vincent Deconinck
+protected void freeTransmitters()
+{
+ for (int i=0;iwww.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * Thrown to indicate that the response PDU was received OK, but the PDU
+ * contains an error.
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.5 $ $Date: 2006/01/17 17:43:54 $
+ */
+public class AgentException extends PduException
+{
+ private static final String version_id =
+ "@(#)$Id: AgentException.java,v 3.5 2006/01/17 17:43:54 birgit Exp $ Copyright Westhawk Ltd";
+
+/**
+ * Constructs an AgentException with no specified detail message.
+ *
+ */
+public AgentException()
+{
+ super();
+}
+
+/**
+ * Constructs an AgentException with the specified detail
+ * message.
+ *
+ * @param str The detail message.
+ */
+public AgentException(String str)
+{
+ super(str);
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AsnDecoderBase.java b/src/main/java/uk/co/westhawk/snmp/stack/AsnDecoderBase.java
new file mode 100644
index 0000000..37beb03
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AsnDecoderBase.java
@@ -0,0 +1,174 @@
+// NAME
+// $RCSfile: AsnDecoderBase.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.3 $
+// CREATED
+// $Date: 2007/10/17 10:36:47 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ * original version by hargrave@dellgate.us.dell.com (Jordan Hargrave)
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.util.*;
+import java.io.*;
+import java.util.*;
+
+/**
+ * This class contains the general methods to decode bytes into a Pdu.
+ * We split the original class AsnDecoder into four classes.
+ *
+ * @since 4_14
+ * @author Tim Panton
+ * @version $Revision: 3.3 $ $Date: 2007/10/17 10:36:47 $
+ */
+class AsnDecoderBase extends Object
+{
+ private static final String version_id =
+ "@(#)$Id: AsnDecoderBase.java,v 3.3 2007/10/17 10:36:47 birgita Exp $ Copyright Westhawk Ltd";
+
+/**
+ * Reads the input into an asn sequence.
+ */
+AsnSequence getAsnSequence(InputStream in)
+throws IOException, DecodingException
+{
+ AsnSequence asnTopSeq = null;
+ AsnSequence dummy = new AsnSequence();
+ AsnObject obj = dummy.AsnReadHeader(in);
+ if (obj instanceof AsnSequence)
+ {
+ asnTopSeq = (AsnSequence) obj;
+ }
+ else
+ {
+ String msg = "AsnSequence was expected";
+ if (obj != null)
+ {
+ msg += " instead of " + obj.getRespTypeString();
+ }
+ else
+ {
+ msg += ", but is null";
+ }
+ throw new DecodingException(msg);
+ }
+ return asnTopSeq;
+}
+
+/**
+ * Returns the SNMP version number of the asn sequence.
+ */
+int getSNMPVersion(AsnSequence asnTopSeq) throws DecodingException
+{
+ int version = -1;
+ AsnObject obj = asnTopSeq.getObj(0);
+ if (obj instanceof AsnInteger)
+ {
+ AsnInteger v = (AsnInteger) obj;
+ version = v.getValue();
+ }
+ else
+ {
+ String msg = "SNMP version should be of type AsnInteger"
+ + " instead of " + obj.getRespTypeString();
+ throw new DecodingException(msg);
+ }
+ return version;
+}
+
+/**
+ * Returns the SNMP v1 and v2c community of the asn sequence.
+ */
+String getCommunity(AsnSequence asnTopSeq) throws DecodingException
+{
+ String comm ="";
+ AsnObject obj = asnTopSeq.getObj(1);
+ if (obj instanceof AsnOctets)
+ {
+ AsnOctets estat = (AsnOctets) obj;
+ comm = estat.getValue();
+ }
+ else
+ {
+ String msg = "community should be of type AsnOctets"
+ + " instead of " + obj.getRespTypeString();
+ throw new DecodingException(msg);
+ }
+ return comm;
+}
+
+
+AsnSequence getAsnHeaderData(AsnSequence asnTopSeq) throws DecodingException
+{
+ AsnSequence asnHeaderData = null;
+ AsnObject obj = asnTopSeq.getObj(1);
+ if (obj instanceof AsnSequence)
+ {
+ asnHeaderData = (AsnSequence) obj;
+ }
+ else
+ {
+ String msg = "asnHeaderData should be of type AsnSequence"
+ + " instead of " + obj.getRespTypeString();
+ throw new DecodingException(msg);
+ }
+ return asnHeaderData;
+}
+
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AsnDecoderv1.java b/src/main/java/uk/co/westhawk/snmp/stack/AsnDecoderv1.java
new file mode 100644
index 0000000..9a4c680
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AsnDecoderv1.java
@@ -0,0 +1,112 @@
+// NAME
+// $RCSfile: AsnDecoderv1.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.3 $
+// CREATED
+// $Date: 2006/02/09 14:16:36 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.util.*;
+import java.io.*;
+import java.util.*;
+
+/**
+ * This class contains the v1 specific methods to decode bytes into a Pdu.
+ * We split the original class AsnDecoder into four classes.
+ *
+ * @since 4_14
+ * @author Tim Panton
+ * @version $Revision: 3.3 $ $Date: 2006/02/09 14:16:36 $
+ */
+class AsnDecoderv1 extends AsnDecoderBase
+{
+ private static final String version_id =
+ "@(#)$Id: AsnDecoderv1.java,v 3.3 2006/02/09 14:16:36 birgit Exp $ Copyright Westhawk Ltd";
+
+
+/**
+ * This method creates an AsnPduSequence or an AsnTrapPduv1Sequence out of
+ * the characters of the InputStream for v1.
+ *
+ * @see AbstractSnmpContext#run
+ * @see SnmpContext#processIncomingResponse
+ * @see SnmpContext#processIncomingPdu
+ */
+AsnSequence DecodeSNMP(InputStream in, String community)
+throws IOException, DecodingException
+{
+ AsnSequence asnTopSeq = getAsnSequence(in);
+ int snmpVersion = getSNMPVersion(asnTopSeq);
+ if (snmpVersion != SnmpConstants.SNMP_VERSION_1)
+ {
+ String str = SnmpUtilities.getSnmpVersionString(snmpVersion);
+ String msg = "Wrong SNMP version: expected SNMPv1, received "
+ + str;
+ throw new DecodingException(msg);
+ }
+ String comm = getCommunity(asnTopSeq);
+ if (comm.equals(community) == false)
+ {
+ String msg = "Wrong community: expected "
+ + community + ", received " + comm;
+ throw new DecodingException(msg);
+ }
+
+ // The message is either a 'normal' PDU or a Trap v1 PDU.
+ AsnSequence seqPdu = null;
+ seqPdu = (AsnPduSequence) asnTopSeq.findPdu();
+ if (seqPdu == null)
+ {
+ seqPdu = (AsnTrapPduv1Sequence) asnTopSeq.findTrapPduv1();
+ }
+ return seqPdu;
+}
+
+
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AsnDecoderv2c.java b/src/main/java/uk/co/westhawk/snmp/stack/AsnDecoderv2c.java
new file mode 100644
index 0000000..e6bb033
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AsnDecoderv2c.java
@@ -0,0 +1,117 @@
+// NAME
+// $RCSfile: AsnDecoderv2c.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.3 $
+// CREATED
+// $Date: 2006/02/09 14:16:36 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * original version by hargrave@dellgate.us.dell.com (Jordan Hargrave)
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.util.*;
+import java.io.*;
+import java.util.*;
+
+/**
+ * This class contains the v2c specific methods to decode bytes into a Pdu.
+ * We split the original class AsnDecoder into four classes.
+ *
+ * @since 4_14
+ * @author Tim Panton
+ * @version $Revision: 3.3 $ $Date: 2006/02/09 14:16:36 $
+ */
+class AsnDecoderv2c extends AsnDecoderBase
+{
+ private static final String version_id =
+ "@(#)$Id: AsnDecoderv2c.java,v 3.3 2006/02/09 14:16:36 birgit Exp $ Copyright Westhawk Ltd";
+
+
+
+/**
+ * This method creates an AsnPduSequence out of the characters of the
+ * InputStream for v2c.
+ *
+ * @see AbstractSnmpContext#run
+ * @see SnmpContextv2c#processIncomingResponse
+ * @see SnmpContextv2c#processIncomingPdu
+ */
+AsnPduSequence DecodeSNMPv2c(InputStream in, String community)
+throws IOException, DecodingException
+{
+ AsnSequence asnTopSeq = getAsnSequence(in);
+ int snmpVersion = getSNMPVersion(asnTopSeq);
+ if (snmpVersion != SnmpConstants.SNMP_VERSION_2c)
+ {
+ String str = SnmpUtilities.getSnmpVersionString(snmpVersion);
+ String msg = "Wrong SNMP version: expected SNMPv2c, received "
+ + str;
+ throw new DecodingException(msg);
+ }
+ String comm = getCommunity(asnTopSeq);
+ if (comm.equals(community) == false)
+ {
+ String msg = "Wrong community: expected "
+ + community + ", received " + comm;
+ throw new DecodingException(msg);
+ }
+ AsnPduSequence Pdu = (AsnPduSequence) asnTopSeq.findPdu();
+ return Pdu;
+}
+
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AsnDecoderv3.java b/src/main/java/uk/co/westhawk/snmp/stack/AsnDecoderv3.java
new file mode 100644
index 0000000..0a34fdc
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AsnDecoderv3.java
@@ -0,0 +1,497 @@
+// NAME
+// $RCSfile: AsnDecoderv3.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.9 $
+// CREATED
+// $Date: 2009/03/05 12:48:59 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * original version by hargrave@dellgate.us.dell.com (Jordan Hargrave)
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.util.*;
+import java.io.*;
+import java.util.*;
+
+/**
+ * This class contains the v3 specific methods to decode bytes into a Pdu.
+ * We split the original class AsnDecoder into four classes.
+ *
+ * @since 4_14
+ * @author Tim Panton
+ * @version $Revision: 3.9 $ $Date: 2009/03/05 12:48:59 $
+ */
+class AsnDecoderv3 extends AsnDecoderBase implements usmStatsConstants
+{
+ private static final String version_id =
+ "@(#)$Id: AsnDecoderv3.java,v 3.9 2009/03/05 12:48:59 birgita Exp $ Copyright Westhawk Ltd";
+
+
+/**
+ * Returns the msgId of the SNMPv3 asn sequence.
+ */
+int getMsgId(AsnSequence asnTopSeq) throws DecodingException
+{
+ int msgId = -1;
+ AsnSequence asnHeaderData = getAsnHeaderData(asnTopSeq);
+ AsnObject obj = asnHeaderData.getObj(0);
+ if (obj instanceof AsnInteger)
+ {
+ AsnInteger value = (AsnInteger) obj;
+ msgId = value.getValue();
+ }
+ else
+ {
+ String msg = "msgId should be of type AsnInteger"
+ + " instead of " + obj.getRespTypeString();
+ throw new DecodingException(msg);
+ }
+ return msgId;
+}
+
+/**
+ * This method creates an AsnPduSequence out of the characters of the
+ * InputStream for v3.
+ *
+ * @see AbstractSnmpContext#run
+ * @see SnmpContextv3#processIncomingResponse
+ * @see SnmpContextv3#processIncomingPdu
+ */
+AsnSequence DecodeSNMPv3(InputStream in)
+throws IOException, DecodingException
+{
+ AsnSequence asnTopSeq = getAsnSequence(in);
+ int snmpVersion = getSNMPVersion(asnTopSeq);
+ if (snmpVersion != SnmpConstants.SNMP_VERSION_3)
+ {
+ String str = SnmpUtilities.getSnmpVersionString(snmpVersion);
+ String msg = "Wrong SNMP version: expected SNMPv3, received "
+ + str;
+ throw new DecodingException(msg);
+ }
+ else
+ {
+ int securityModel = -1;
+ AsnSequence asnHeaderData = getAsnHeaderData(asnTopSeq);
+ AsnObject obj = asnHeaderData.getObj(3);
+ if (obj instanceof AsnInteger)
+ {
+ AsnInteger value = (AsnInteger) obj;
+ securityModel = value.getValue();
+ if (securityModel != SnmpContextv3Face.USM_Security_Model)
+ {
+ String msg = "Wrong v3 Security Model: expected USM("
+ + SnmpContextv3Face.USM_Security_Model
+ + "), received "
+ + securityModel;
+ throw new DecodingException(msg);
+ }
+ }
+ else
+ {
+ String msg = "securityModel should be of type AsnInteger"
+ + " instead of " + obj.getRespTypeString();
+ throw new DecodingException(msg);
+ }
+ }
+ return asnTopSeq;
+}
+
+
+/**
+ * Processes the SNMP v3 AsnSequence.
+ * See section 3.2 of SNMP-USER-BASED-SM-MIB.
+ */
+AsnPduSequence processSNMPv3(SnmpContextv3Basis context, AsnSequence asnTopSeq, byte[] message, boolean amIAuthoritative)
+throws IOException, DecodingException
+{
+ AsnPduSequence pduSeq = null;
+
+ // if not correct, I'll just skip a lot of tests.
+ boolean isCorrect = asnTopSeq.isCorrect;
+
+ AsnSequence asnHeaderData = getAsnHeaderData(asnTopSeq);
+ //int msgId = ((AsnInteger)asnHeaderData.getObj(0)).getValue();
+ //int maxSize = ((AsnInteger)asnHeaderData.getObj(1)).getValue();
+ byte [] msgFlags = ((AsnOctets)asnHeaderData.getObj(2)).getBytes();
+ boolean isUseAuthentication = isUseAuthentication(msgFlags[0]);
+ boolean isUsePrivacy = isUsePrivacy(msgFlags[0]);
+
+ AsnOctets asnSecurityParameters = (AsnOctets)asnTopSeq.getObj(2);
+ AsnSequence usmObject = decodeUSM(asnSecurityParameters);
+
+ byte [] engineIdBytes = ((AsnOctets)usmObject.getObj(0)).getBytes();
+ String engineId = SnmpUtilities.toHexString(engineIdBytes);
+ int boots = ((AsnInteger)usmObject.getObj(1)).getValue();
+ int time = ((AsnInteger)usmObject.getObj(2)).getValue();
+ String userName = ((AsnOctets)usmObject.getObj(3)).getValue();
+ AsnOctets realFingerPrintObject = (AsnOctets)usmObject.getObj(4);
+ byte [] realFingerPrint = realFingerPrintObject.getBytes();
+ byte [] salt = ((AsnOctets)usmObject.getObj(5)).getBytes();
+
+ TimeWindow tWindow = TimeWindow.getCurrent();
+ if (amIAuthoritative == false)
+ {
+ /* engineId should not be empty, however net-snmp 5.3.0.1 has a
+ * bug (1427410) in their trapsess; it sends an empty engineId
+ */
+ if (engineId.length() > 0
+ &&
+ tWindow.isEngineIdOK(context.getReceivedFromHostAddress(),
+ context.getPort(), engineId) == false)
+ {
+ String msg = "Received engine Id ('" + engineId + "') is not correct.";
+ msg += " amIAuthoritative == false";
+ throw new DecodingException(msg);
+ }
+ else
+ {
+ // This should only happen once, if for some reason the sendto
+ // and receivedfrom addresses are different.
+ // It is a hack, but it needs to seem like the 'sendToHostAddress'
+ // has been discovered, else any other request sent to this
+ // address will try to do another discovery and the process
+ // starts again.
+ String sendToHostAddress = context.getSendToHostAddress();
+ String receivedFromHostAddress = context.getReceivedFromHostAddress();
+ if (sendToHostAddress.equals(receivedFromHostAddress) == false)
+ {
+ String storedEngineId;
+ storedEngineId = tWindow.getSnmpEngineId(sendToHostAddress, context.getPort());
+ if (storedEngineId == null)
+ {
+ tWindow.setSnmpEngineId(sendToHostAddress, context.getPort(), "00");
+ }
+ }
+ }
+ }
+ else
+ {
+ // amIAuthoritative == true
+ // Section 3.2 rfc
+ // engineId of length '0' -> discovery.
+ if (engineId.length() > 0
+ &&
+ tWindow.isEngineIdOK(context.getUsmAgent().MYFAKEHOSTNAME,
+ context.getPort(), engineId) == false)
+ {
+ String msg = "Received engine Id ('" + engineId + "') is not correct.";
+ msg += " amIAuthoritative == true";
+ throw new DecodingException(msg);
+ }
+ }
+
+ if (userName.equals(context.getUserName()) == false)
+ {
+ String msg = "Received userName ('" + userName + "') is not correct";
+ throw new DecodingException(msg);
+ }
+
+ // I'm not really supposed to encrypt before checking and doing
+ // authentication, but I would like to use the pduSeq
+ // So, I'll encrypt and save the possible exception.
+ DecodingException encryptionDecodingException = null;
+ IOException encryptionIOException = null;
+ try
+ {
+ AsnObject asnScopedObject = asnTopSeq.getObj(3);
+ AsnSequence asnPlainScopedPdu = null;
+ if (isUsePrivacy == true)
+ {
+ // if decryption was used, the asnScopedObject would be AsnOctets
+ byte[] privKey = null;
+ int prot = context.getAuthenticationProtocol();
+ if (prot == context.MD5_PROTOCOL)
+ {
+ byte[] passwKey = context.getPrivacyPasswordKeyMD5();
+ privKey = SnmpUtilities.getLocalizedKeyMD5(passwKey, engineId);
+ }
+ else
+ {
+ byte[] passwKey = context.getPrivacyPasswordKeySHA1();
+ privKey = SnmpUtilities.getLocalizedKeySHA1(passwKey, engineId);
+ }
+
+ AsnOctets asnEncryptedScopedPdu = (AsnOctets)asnScopedObject;
+ byte[] encryptedText = asnEncryptedScopedPdu.getBytes();
+
+ byte[] plainText = null;
+ int pprot = context.getPrivacyProtocol();
+ if (pprot == context.AES_ENCRYPT)
+ {
+ plainText = SnmpUtilities.AESdecrypt(encryptedText,
+ privKey, boots, time, salt);
+ }
+ else
+ {
+ plainText = SnmpUtilities.DESdecrypt(encryptedText,
+ salt, privKey);
+ }
+
+ if (AsnObject.debug > 10)
+ {
+ System.out.println("Encrypted PDU: ");
+ System.out.println("Decoding with : "+context.ProtocolNames[pprot]);
+ }
+
+ ByteArrayInputStream plainIn = new ByteArrayInputStream(plainText);
+ asnPlainScopedPdu = getAsnSequence(plainIn);
+ }
+ else
+ {
+ asnPlainScopedPdu = (AsnSequence)asnScopedObject;
+ }
+
+ byte [] contextId = ((AsnOctets)asnPlainScopedPdu.getObj(0)).getBytes();
+ String contextName = ((AsnOctets)asnPlainScopedPdu.getObj(1)).getValue();
+ pduSeq = (AsnPduSequence) asnPlainScopedPdu.findPdu();
+ }
+ catch (DecodingException exc)
+ {
+ encryptionDecodingException = exc;
+ }
+ catch (IOException exc)
+ {
+ encryptionIOException = exc;
+ }
+ if (pduSeq != null && engineId.length() == 0)
+ {
+ pduSeq.setSnmpv3Discovery(true);
+ }
+
+ boolean userIsUsingAuthentication = context.isUseAuthentication();
+ if (isCorrect == true && (isUseAuthentication != userIsUsingAuthentication))
+ {
+ String msg = "User " + userName + " does ";
+ if (userIsUsingAuthentication == false)
+ {
+ msg += "not ";
+ }
+ msg += "support authentication, but received message ";
+
+ if (isUseAuthentication)
+ {
+ msg += "with authentication.";
+ }
+ else
+ {
+ msg += "without authentication";
+ msg += getUsmStats(pduSeq);
+ }
+ throw new DecodingException(msg);
+ }
+
+ boolean isAuthentic = false;
+ if (isCorrect == true && isUseAuthentication == true)
+ {
+ int fpPos = realFingerPrintObject.getContentsPos();
+ if (AsnObject.debug > 10)
+ {
+ int fpLength = realFingerPrintObject.getContentsLength();
+ String str = "Pos finger print = " + fpPos
+ + ", len = " + fpLength;
+ SnmpUtilities.dumpBytes(str, realFingerPrint);
+ }
+
+ byte[] calcFingerPrint = null;
+ // Replace the real finger print with the dummy finger print
+ System.arraycopy(AsnEncoderv3.dummyFingerPrint, 0,
+ message, fpPos, realFingerPrint.length);
+ int prot = context.getAuthenticationProtocol();
+ if (prot == context.MD5_PROTOCOL)
+ {
+ byte[] passwKey = context.getAuthenticationPasswordKeyMD5();
+ byte[] authkey = SnmpUtilities.getLocalizedKeyMD5(passwKey,
+ engineId);
+ calcFingerPrint = SnmpUtilities.getFingerPrintMD5(authkey,
+ message);
+ }
+ else
+ {
+ byte[] passwKey = context.getAuthenticationPasswordKeySHA1();
+ byte[] authkey = SnmpUtilities.getLocalizedKeySHA1(passwKey,
+ engineId);
+ calcFingerPrint = SnmpUtilities.getFingerPrintSHA1(authkey,
+ message);
+ }
+
+ if (SnmpUtilities.areBytesEqual(realFingerPrint, calcFingerPrint) == false)
+ {
+ String msg = "Authentication comparison failed";
+ throw new DecodingException(msg);
+ }
+ else
+ {
+ if (pduSeq != null && boots == 0 && time == 0)
+ {
+ pduSeq.setSnmpv3Discovery(true);
+ }
+ if (tWindow.isOutsideTimeWindow(engineId, boots, time))
+ {
+ String msg = "Message is outside time window";
+ throw new DecodingException(msg);
+ }
+ isAuthentic = true;
+ }
+ }
+ tWindow.updateTimeWindow(engineId, boots, time, isAuthentic);
+
+ boolean userIsUsingPrivacy = context.isUsePrivacy();
+ if (isCorrect == true && (isUsePrivacy != userIsUsingPrivacy))
+ {
+ String msg = "User " + userName + " does ";
+ if (userIsUsingPrivacy == false)
+ {
+ msg += "not ";
+ }
+ msg += "support privacy, but received message ";
+ if (isUsePrivacy)
+ {
+ msg += "with privacy.";
+ }
+ else
+ {
+ msg += "without privacy";
+ msg += getUsmStats(pduSeq);
+ }
+ throw new DecodingException(msg);
+ }
+
+ if (encryptionDecodingException != null)
+ {
+ throw encryptionDecodingException;
+ }
+ if (encryptionIOException != null)
+ {
+ throw encryptionIOException;
+ }
+
+ if (pduSeq != null && isCorrect == false)
+ {
+ pduSeq.isCorrect = false;
+ }
+ return pduSeq;
+}
+
+
+private boolean isUseAuthentication(byte msgFlags)
+{
+ boolean isUseAuthentication = ((byte)(0x01) & msgFlags) > 0;
+ return isUseAuthentication;
+}
+
+
+private boolean isUsePrivacy(byte msgFlags)
+{
+ boolean isUsePrivacy = ((byte)(0x02) & msgFlags) > 0;
+ return isUsePrivacy;
+}
+
+
+private AsnSequence decodeUSM(AsnOctets asnSecurityParameters)
+throws IOException
+{
+ byte [] usmBytes = asnSecurityParameters.getBytes();
+ if (AsnObject.debug > 10)
+ {
+ SnmpUtilities.dumpBytes("Decoding USM:", usmBytes);
+ }
+
+ ByteArrayInputStream usmIn = new ByteArrayInputStream(usmBytes);
+ AsnSequence usmOctets = new AsnSequence(usmIn, usmBytes.length,
+ asnSecurityParameters.getContentsPos());
+ AsnSequence usmObject = (AsnSequence)usmOctets.getObj(0);
+ return usmObject;
+}
+
+
+/**
+ * Sometimes when an error occurs the usmStats is sent in the varbind
+ * list.
+ */
+private String getUsmStats(AsnPduSequence pduSeq)
+{
+ String msg = "";
+ AsnSequence varBind = (AsnSequence) pduSeq.getObj(3);
+ int size = varBind.getObjCount();
+ if (size > 0)
+ {
+ AsnSequence varSeq = (AsnSequence) varBind.getObj(0);
+ varbind vb = new varbind(varSeq);
+ AsnObjectId oid = vb.getOid();
+ boolean found=false;
+ int i=0;
+ while (i< usmStatsOids.length && found==false)
+ {
+ AsnObjectId usmOid = new AsnObjectId(usmStatsOids[i]);
+ found = (oid.startsWith(usmOid) == true);
+ i++;
+ }
+ if (found == true)
+ {
+ i--;
+ msg += ": " + usmStatsStrings[i] + " " + vb.getValue();
+ }
+ else
+ {
+ msg += ": " + vb;
+ }
+ }
+ return msg;
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AsnEncoderBase.java b/src/main/java/uk/co/westhawk/snmp/stack/AsnEncoderBase.java
new file mode 100644
index 0000000..1d0f670
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AsnEncoderBase.java
@@ -0,0 +1,115 @@
+// NAME
+// $RCSfile: AsnEncoderBase.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.2 $
+// CREATED
+// $Date: 2006/01/17 17:43:53 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ * original version by hargrave@dellgate.us.dell.com (Jordan Hargrave)
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.util.*;
+import java.io.*;
+import java.util.*;
+
+/**
+ * This class contains the general methods to encode a Pdu into bytes.
+ * We split the original class AsnEncoder into four classes.
+ *
+ * @since 4_14
+ * @author Tim Panton
+ * @version $Revision: 3.2 $ $Date: 2006/01/17 17:43:53 $
+ */
+class AsnEncoderBase extends Object
+{
+ private static final String version_id =
+ "@(#)$Id: AsnEncoderBase.java,v 3.2 2006/01/17 17:43:53 birgit Exp $ Copyright Westhawk Ltd";
+
+
+/**
+ * Encode PDU itself packet into bytes.
+ * The actual PDU encoding is the same for v1 to v3.
+ * Except for Trapv1, but we are not implementing that.
+ */
+protected AsnObject EncodePdu(byte msg_type,
+ int pduId, int errstat, int errind, Enumeration ve)
+ throws IOException
+{
+ AsnObject asnPduObject, asnVBObject;
+
+ // kind of request
+ asnPduObject = new AsnSequence(msg_type);
+ asnPduObject.add(new AsnInteger(pduId)); // reqid
+ asnPduObject.add(new AsnInteger(errstat)); // errstat
+ asnPduObject.add(new AsnInteger(errind)); // errindex
+
+ // Create VarbindList sequence
+ AsnObject asnVBLObject = asnPduObject.add(new AsnSequence());
+
+ // Add variable bindings
+ while (ve.hasMoreElements())
+ {
+ asnVBObject = asnVBLObject.add(new AsnSequence());
+ varbind vb = (varbind) ve.nextElement();
+ asnVBObject.add(vb.getOid());
+ asnVBObject.add(vb.getValue());
+ }
+
+ return asnPduObject;
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AsnEncoderv1.java b/src/main/java/uk/co/westhawk/snmp/stack/AsnEncoderv1.java
new file mode 100644
index 0000000..e23228b
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AsnEncoderv1.java
@@ -0,0 +1,184 @@
+// NAME
+// $RCSfile: AsnEncoderv1.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.3 $
+// CREATED
+// $Date: 2006/02/09 14:16:36 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ * original version by hargrave@dellgate.us.dell.com (Jordan Hargrave)
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.util.*;
+import java.io.*;
+import java.util.*;
+
+/**
+ * This class contains the v1 specific methods to encode a Pdu into bytes.
+ * We split the original class AsnEncoder into four classes.
+ *
+ * @since 4_14
+ * @author Tim Panton
+ * @version $Revision: 3.3 $ $Date: 2006/02/09 14:16:36 $
+ */
+class AsnEncoderv1 extends AsnEncoderBase
+{
+ private static final String version_id =
+ "@(#)$Id: AsnEncoderv1.java,v 3.3 2006/02/09 14:16:36 birgit Exp $ Copyright Westhawk Ltd";
+
+
+/**
+ * Encode SNMPv1 Trap packet into bytes.
+ */
+ByteArrayOutputStream EncodeSNMP(SnmpContext context, byte msg_type,
+ String enterprise, byte[] IpAddress, int generic_trap, int
+ specific_trap, long timeTicks, Enumeration ve)
+ throws IOException, EncodingException
+{
+ ByteArrayOutputStream bout;
+ AsnSequence asnTopSeq;
+
+ // Create authentication
+ asnTopSeq = new AsnSequence();
+ asnTopSeq.add(new AsnInteger(SnmpConstants.SNMP_VERSION_1));
+ asnTopSeq.add(new AsnOctets(context.getCommunity())); // community
+
+ // Create PDU sequence.
+ AsnObject asnPduObject = EncodeTrap1Pdu(msg_type, enterprise,
+ IpAddress, generic_trap, specific_trap, timeTicks, ve);
+
+ asnTopSeq.add(asnPduObject);
+
+ if (AsnObject.debug > 10)
+ {
+ System.out.println("\n" + getClass().getName() + ".EncodeSNMP(): ");
+ }
+ // Write SNMP object
+ bout = new ByteArrayOutputStream();
+ asnTopSeq.write(bout);
+ return bout;
+}
+
+/**
+ * Encode Trapv1 PDU itself packet into bytes.
+ */
+private AsnObject EncodeTrap1Pdu(byte msg_type,
+ String enterprise, byte[] IpAddress, int generic_trap, int
+ specific_trap, long timeTicks, Enumeration ve)
+ throws IOException
+{
+ AsnObject asnPduObject, asnVBObject;
+
+ // kind of request
+ asnPduObject = new AsnSequence(msg_type);
+ asnPduObject.add(new AsnObjectId(enterprise)); // enterprise
+
+ // agent-addr (thanks Donnie Love (dlove@idsonline.com) for
+ // pointing out that we should have used IPADDRESS type)
+ asnPduObject.add(new AsnOctets(IpAddress, AsnObject.IPADDRESS));
+
+ asnPduObject.add(new AsnInteger(generic_trap)); // generic-trap
+ asnPduObject.add(new AsnInteger(specific_trap)); // specific-trap
+ asnPduObject.add(new AsnUnsInteger(timeTicks)); // time-stap
+
+ // Create VarbindList sequence
+ AsnObject asnVBLObject = asnPduObject.add(new AsnSequence());
+
+ // Add variable bindings
+ while (ve.hasMoreElements())
+ {
+ asnVBObject = asnVBLObject.add(new AsnSequence());
+ varbind vb = (varbind) ve.nextElement();
+ asnVBObject.add(vb.getOid());
+ asnVBObject.add(vb.getValue());
+ }
+
+ return asnPduObject;
+}
+
+
+/**
+ * Encode SNMPv1 packet into bytes.
+ */
+ByteArrayOutputStream EncodeSNMP(SnmpContext context, byte msg_type,
+ int pduId, int errstat, int errind, Enumeration ve)
+ throws IOException, EncodingException
+{
+ ByteArrayOutputStream bout;
+ AsnSequence asnTopSeq;
+
+ // Create authentication
+ asnTopSeq = new AsnSequence();
+ asnTopSeq.add(new AsnInteger(AsnObject.SNMP_VERSION_1));
+ asnTopSeq.add(new AsnOctets(context.getCommunity())); // community
+
+ // Create PDU sequence.
+ AsnObject asnPduObject = EncodePdu(msg_type, pduId, errstat, errind, ve);
+ asnTopSeq.add(asnPduObject);
+
+ if (AsnObject.debug > 10)
+ {
+ System.out.println("\n" + getClass().getName() + ".EncodeSNMP(): ");
+ }
+ // Write SNMP object
+ bout = new ByteArrayOutputStream();
+ asnTopSeq.write(bout);
+ return bout;
+}
+
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AsnEncoderv2c.java b/src/main/java/uk/co/westhawk/snmp/stack/AsnEncoderv2c.java
new file mode 100644
index 0000000..c7878d9
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AsnEncoderv2c.java
@@ -0,0 +1,113 @@
+// NAME
+// $RCSfile: AsnEncoderv2c.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.3 $
+// CREATED
+// $Date: 2006/02/09 14:16:36 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ * original version by hargrave@dellgate.us.dell.com (Jordan Hargrave)
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.util.*;
+import java.io.*;
+import java.util.*;
+
+/**
+ * This class contains the v2c specific methods to encode a Pdu into bytes.
+ * We split the original class AsnEncoder into four classes.
+ *
+ * @since 4_14
+ * @author Tim Panton
+ * @version $Revision: 3.3 $ $Date: 2006/02/09 14:16:36 $
+ */
+class AsnEncoderv2c extends AsnEncoderBase
+{
+ private static final String version_id =
+ "@(#)$Id: AsnEncoderv2c.java,v 3.3 2006/02/09 14:16:36 birgit Exp $ Copyright Westhawk Ltd";
+
+
+/**
+ * Encode SNMPv2c packet into bytes.
+ */
+ByteArrayOutputStream EncodeSNMPv2c(SnmpContextv2c context, byte msg_type,
+ int pduId, int errstat, int errind, Enumeration ve)
+ throws IOException, EncodingException
+{
+ ByteArrayOutputStream bout;
+ AsnSequence asnTopSeq;
+
+ // Create authentication
+ asnTopSeq = new AsnSequence();
+ asnTopSeq.add(new AsnInteger(SnmpConstants.SNMP_VERSION_2c));
+ asnTopSeq.add(new AsnOctets(context.getCommunity())); // community
+
+ // Create PDU sequence.
+ AsnObject asnPduObject = EncodePdu(msg_type, pduId, errstat, errind, ve);
+ asnTopSeq.add(asnPduObject);
+
+ if (AsnObject.debug > 10)
+ {
+ System.out.println("\n" + getClass().getName() + ".EncodeSNMPv2c(): ");
+ }
+ // Write SNMP object
+ bout = new ByteArrayOutputStream();
+ asnTopSeq.write(bout);
+ return bout;
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AsnEncoderv3.java b/src/main/java/uk/co/westhawk/snmp/stack/AsnEncoderv3.java
new file mode 100644
index 0000000..92ea33e
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AsnEncoderv3.java
@@ -0,0 +1,313 @@
+// NAME
+// $RCSfile: AsnEncoderv3.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.5 $
+// CREATED
+// $Date: 2009/03/05 12:48:59 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ * original version by hargrave@dellgate.us.dell.com (Jordan Hargrave)
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.util.*;
+import java.io.*;
+import java.util.*;
+
+/**
+ * This class contains the v3 specific methods to encode a Pdu into bytes.
+ * We split the original class AsnEncoder into four classes.
+ *
+ * @since 4_14
+ * @author Tim Panton
+ * @version $Revision: 3.5 $ $Date: 2009/03/05 12:48:59 $
+ */
+class AsnEncoderv3 extends AsnEncoderBase
+{
+ private static final String version_id =
+ "@(#)$Id: AsnEncoderv3.java,v 3.5 2009/03/05 12:48:59 birgita Exp $ Copyright Westhawk Ltd";
+
+ // 12 zero octets
+ static byte dummyFingerPrint[] =
+ {
+ (byte)(0x0),
+ (byte)(0x0),
+ (byte)(0x0),
+ (byte)(0x0),
+ (byte)(0x0),
+ (byte)(0x0),
+ (byte)(0x0),
+ (byte)(0x0),
+ (byte)(0x0),
+ (byte)(0x0),
+ (byte)(0x0),
+ (byte)(0x0),
+ };
+
+/**
+ * Encode SNMPv3 packet into bytes.
+ */
+byte[] EncodeSNMPv3(SnmpContextv3Basis context,
+ int contextMsgId, TimeWindowNode node,
+ byte msg_type, int pduId, int errstat, int errind, Enumeration ve)
+ throws IOException, EncodingException
+{
+ ByteArrayOutputStream bout;
+ // Create authentication
+ AsnSequence asnTopSeq = new AsnSequence();
+
+ // msgGlobalData = HeaderData
+ AsnSequence asnHeaderData = new AsnSequence();
+ asnHeaderData.add(new AsnInteger(contextMsgId));
+ asnHeaderData.add(new AsnInteger(context.getMaxRecvSize()));
+ asnHeaderData.add(new AsnOctets(getMsgFlags(context, msg_type)));
+ asnHeaderData.add(new AsnInteger(context.USM_Security_Model));
+
+ // msgData = ScopedPdu (plaintext or encrypted)
+ AsnSequence asnPlainScopedPdu = new AsnSequence();
+ asnPlainScopedPdu.add(new AsnOctets(context.getContextEngineId()));
+ asnPlainScopedPdu.add(new AsnOctets(context.getContextName()));
+ // PDU sequence.
+ AsnObject asnPduObject = EncodePdu(msg_type, pduId, errstat, errind, ve);
+ asnPlainScopedPdu.add(asnPduObject);
+
+ // asnSecurityParameters
+ if (AsnObject.debug > 10)
+ {
+ System.out.println("\nEncode USM: node " + node.toString());
+ }
+ AsnSequence asnSecurityObject = new AsnSequence();
+ byte [] engineIdBytes = SnmpUtilities.toBytes(node.getSnmpEngineId());
+ asnSecurityObject.add(new AsnOctets(engineIdBytes));
+ asnSecurityObject.add(new AsnInteger(node.getSnmpEngineBoots()));
+ asnSecurityObject.add(new AsnInteger(node.getSnmpEngineTime()));
+ asnSecurityObject.add(new AsnOctets(context.getUserName()));
+
+ AsnOctets fingerPrintOct;
+ if (context.isUseAuthentication())
+ {
+ fingerPrintOct = new AsnOctets(dummyFingerPrint);
+ }
+ else
+ {
+ fingerPrintOct = new AsnOctets("");
+ }
+ asnSecurityObject.add(fingerPrintOct);
+
+ AsnOctets privOct;
+ AsnOctets asnEncryptedScopedPdu = null;
+ if (context.isUsePrivacy())
+ {
+ byte[] privKey = null;
+ int aprot = context.getAuthenticationProtocol();
+ if (aprot == context.MD5_PROTOCOL)
+ {
+ byte[] passwKey = context.getPrivacyPasswordKeyMD5();
+ privKey = SnmpUtilities.getLocalizedKeyMD5(passwKey,
+ node.getSnmpEngineId());
+ }
+ else
+ {
+ byte[] passwKey = context.getPrivacyPasswordKeySHA1();
+ privKey = SnmpUtilities.getLocalizedKeySHA1(passwKey,
+ node.getSnmpEngineId());
+ }
+
+ int pprot = context.getPrivacyProtocol();
+ byte [] salt = null;
+ if (pprot == context.AES_ENCRYPT)
+ {
+ salt = SnmpUtilities.getSaltAES();
+ }
+ else
+ {
+ salt = SnmpUtilities.getSaltDES(node.getSnmpEngineBoots());
+ }
+
+ privOct = new AsnOctets(salt);
+ bout = new ByteArrayOutputStream();
+ asnPlainScopedPdu.write(bout);
+
+ byte[] plaintext = bout.toByteArray();
+ byte[] encryptedText = null;
+ if (pprot == context.AES_ENCRYPT)
+ {
+ encryptedText = SnmpUtilities.AESencrypt(plaintext, privKey,
+ node.getSnmpEngineBoots(), node.getSnmpEngineTime(), salt);
+ }
+ else
+ {
+ encryptedText = SnmpUtilities.DESencrypt(plaintext, privKey, salt);
+ }
+
+ asnEncryptedScopedPdu = new AsnOctets(encryptedText);
+ if (AsnObject.debug > 10)
+ {
+ System.out.println("Encrypted body with "+context.ProtocolNames[pprot]);
+ }
+ }
+ else
+ {
+ privOct = new AsnOctets("");
+ }
+ asnSecurityObject.add(privOct);
+
+ ByteArrayOutputStream secOut = new ByteArrayOutputStream();
+ asnSecurityObject.write(secOut);
+ byte [] bytes = secOut.toByteArray();
+ AsnOctets asnSecurityParameters = new AsnOctets(bytes);
+
+
+ asnTopSeq.add(new AsnInteger(SnmpConstants.SNMP_VERSION_3));
+ asnTopSeq.add(asnHeaderData);
+ asnTopSeq.add(asnSecurityParameters);
+ if (context.isUsePrivacy())
+ {
+ asnTopSeq.add(asnEncryptedScopedPdu);
+ }
+ else
+ {
+ asnTopSeq.add(asnPlainScopedPdu);
+ }
+
+
+ if (AsnObject.debug > 10)
+ {
+ System.out.println("\n" + getClass().getName() + ".EncodeSNMPv3(): ");
+ }
+ // Write SNMP object
+ bout = new ByteArrayOutputStream();
+ asnTopSeq.write(bout);
+
+ int sz = bout.size();
+ if (sz > context.getMaxRecvSize())
+ {
+ throw new EncodingException("Packet size ("+ sz
+ + ") is > maximum size (" + context.getMaxRecvSize() +")");
+ }
+ byte[] message = bout.toByteArray();
+
+ // can only do this at after building the whole message
+ if (context.isUseAuthentication())
+ {
+ byte[] calcFingerPrint = null;
+
+ int prot = context.getAuthenticationProtocol();
+ if (prot == context.MD5_PROTOCOL)
+ {
+ byte[] passwKey = context.getAuthenticationPasswordKeyMD5();
+ byte[] authkey = SnmpUtilities.getLocalizedKeyMD5(passwKey,
+ node.getSnmpEngineId());
+ calcFingerPrint = SnmpUtilities.getFingerPrintMD5(authkey,
+ message);
+ }
+ else
+ {
+ byte[] passwKey = context.getAuthenticationPasswordKeySHA1();
+ byte[] authkey = SnmpUtilities.getLocalizedKeySHA1(passwKey,
+ node.getSnmpEngineId());
+ calcFingerPrint = SnmpUtilities.getFingerPrintSHA1(authkey,
+ message);
+ }
+
+ int usmPos = asnSecurityParameters.getContentsPos();
+ int fpPos = fingerPrintOct.getContentsPos();
+ fpPos += usmPos;
+ if (AsnObject.debug > 10)
+ {
+ int fpLength = fingerPrintOct.getContentsLength();
+ String str = "Pos finger print = " + fpPos
+ + ", len = " + fpLength;
+ SnmpUtilities.dumpBytes(str, calcFingerPrint);
+ }
+
+ // Replace the dummy finger print with the real finger print
+ System.arraycopy(calcFingerPrint, 0,
+ message, fpPos, dummyFingerPrint.length);
+ }
+ return message;
+}
+
+
+private byte[] getMsgFlags(SnmpContextv3Basis context, byte msg_type) throws EncodingException
+{
+ byte authMask = (byte)(0x0);
+ if (context.isUseAuthentication())
+ {
+ authMask = (byte)(0x1);
+ }
+ byte privMask = (byte)(0x0);
+ if (context.isUsePrivacy())
+ {
+ if (context.isUseAuthentication())
+ {
+ privMask = (byte)(0x2);
+ }
+ else
+ {
+ throw new EncodingException("Encryption without authentication is not allowed");
+ }
+ }
+ byte reportMask = (byte)(0x0);
+ if (context.isAuthoritative(msg_type) == false)
+ {
+ reportMask = (byte)(0x4);
+ }
+ byte [] msgFlags = new byte[1];
+ msgFlags[0] = (byte) (authMask | privMask | reportMask);
+ return msgFlags;
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AsnInteger.java b/src/main/java/uk/co/westhawk/snmp/stack/AsnInteger.java
new file mode 100644
index 0000000..8cf7052
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AsnInteger.java
@@ -0,0 +1,260 @@
+// NAME
+// $RCSfile: AsnInteger.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.14 $
+// CREATED
+// $Date: 2008/05/27 15:40:14 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ * original version by hargrave@dellgate.us.dell.com (Jordan Hargrave)
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * This class represents the ASN.1 32-bit signed integer
+ *
+ * @see SnmpConstants#ASN_INTEGER
+ *
+ * @author Tim Panton
+ * @version $Revision: 3.14 $ $Date: 2008/05/27 15:40:14 $
+ */
+public class AsnInteger extends AsnObject
+{
+ private static final String version_id =
+ "@(#)$Id: AsnInteger.java,v 3.14 2008/05/27 15:40:14 birgita Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * The internal value of AsnInteger.
+ */
+ protected int value;
+
+ /**
+ * Constructor.
+ *
+ * @param v The value of the AsnInteger
+ */
+ public AsnInteger(int v)
+ {
+ value = v;
+ type = ASN_INTEGER;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param in The input stream from which the value should be read
+ * @param len The length of the AsnInteger
+ */
+ public AsnInteger(InputStream in, int len) throws IOException
+ {
+ byte data[] = new byte[len];
+ if (len != in.read(data,0,len))
+ {
+ throw new IOException("AsnInteger(): Not enough data");
+ }
+ int val = bytesToInteger(data);
+ value = val;
+ }
+
+ /**
+ * Returns the value.
+ *
+ * @return The value of the AsnInteger
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Returns the string representation of the AsnInteger.
+ *
+ * @return The string of the AsnInteger
+ */
+ public String toString()
+ {
+ return (String.valueOf(value));
+ }
+
+ /**
+ * Returns the number of bytes the integer occupies.
+ */
+ int size()
+ {
+ int count, empty = 0x00, sign = 0x00;
+
+ if (value < 0)
+ {
+ empty = 0xFF;
+ sign = 0x80;
+ }
+
+ // 32-bit integer.. change to 56 to write 64-bit long
+ // loop through bytes in value while it is 'empty'
+ for(count=24; count>0; count-=8)
+ {
+ if ( ((value >> count) & 0xFF) != empty) break;
+ }
+ // Check sign bit.. make sure negative's MSB bit is 1,
+ // positives is 0
+ // (0x00000080 = 0x00 0x80) 0xFFFFFF01 => 0xFF 0x01
+ // (0x0000007F = 0x7F) 0xFFFFFF80 => 0x80
+ if (((value >> count) & 0x80) != sign) count += 8;
+ return (count>>3)+1;
+ }
+
+
+ /**
+ * Output integer.
+ */
+ void write(OutputStream out, int pos) throws IOException
+ {
+ int count, empty = 0x00, sign = 0x00;
+
+ if (value < 0)
+ {
+ empty = 0xFF;
+ sign = 0x80;
+ }
+
+ // Get count
+ for(count=24; count>0; count-=8)
+ {
+ if ( ((value >> count) & 0xFF) != empty) break;
+ }
+ if (((value >> count) & 0x80) != sign) count += 8;
+
+ // Build header and write value
+ AsnBuildHeader(out, ASN_INTEGER, (count>>3)+1);
+
+ if (debug > 10)
+ {
+ System.out.println("\tAsnInteger(): value = " + value
+ + ", pos = " + pos);
+ }
+
+ for(; count>=0; count-=8)
+ {
+ out.write((byte)((value >> count) & 0xFF));
+ }
+ }
+
+ /**
+ * Changes an array of bytes into an int.
+ * Thanks to Julien Conan (jconan@protego.net) for improving
+ * this method.
+ *
+ * @param data the array of bytes
+ * @return the int representation of the array
+ */
+ protected int bytesToInteger(byte[] data) throws IOException
+ {
+ DataInputStream dis = new DataInputStream(
+ new ByteArrayInputStream(data));
+
+ int val = 0;
+ int size = data.length;
+
+ /*
+ * First byte contains the sign if the number is negative. Do this
+ * only for AsnInteger
+ */
+ val = dis.readByte();
+
+ for (int n=1; ntrue if and only if the argument is not
+ * null
and is an AsnInteger
object that
+ * contains the same int
value as this object.
+ *
+ * @param obj the object to compare with.
+ * @return true
if the objects are the same;
+ * false
otherwise.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof AsnInteger)
+ {
+ return value == ((AsnInteger)obj).value;
+ }
+ return false;
+ }
+
+
+ /**
+ * Returns a hash code for this AsnInteger
.
+ *
+ * @return a hash code value for this object, equal to the
+ * primitive int
value represented by this
+ * AsnInteger
object.
+ */
+ public int hashCode()
+ {
+ return value;
+ }
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AsnNull.java b/src/main/java/uk/co/westhawk/snmp/stack/AsnNull.java
new file mode 100644
index 0000000..0efbf89
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AsnNull.java
@@ -0,0 +1,149 @@
+// NAME
+// $RCSfile: AsnNull.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.9 $
+// CREATED
+// $Date: 2008/05/27 15:40:14 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ * original version by hargrave@dellgate.us.dell.com (Jordan Hargrave)
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * This class represents the ASN.1 Null object
+ *
+ * @author Tim Panton
+ * @version $Revision: 3.9 $ $Date: 2008/05/27 15:40:14 $
+ */
+public class AsnNull extends AsnObject
+{
+ private static final String version_id =
+ "@(#)$Id: AsnNull.java,v 3.9 2008/05/27 15:40:14 birgita Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * Default Constructor.
+ */
+ public AsnNull()
+ {
+ type = ASN_NULL;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param in The input stream from which the value should be read
+ * @param len The length of the AsnInteger
+ */
+ public AsnNull(InputStream in, int len)
+ {
+ this();
+ }
+
+ /**
+ * Returns the string representation of the AsnNull.
+ *
+ * @return The string of the AsnNull
+ */
+ public String toString()
+ {
+ return "AsnNull";
+ }
+
+ void write(OutputStream out, int pos) throws IOException
+ {
+ AsnBuildHeader(out, ASN_NULL, 0);
+ }
+
+/**
+ * Compares this object to the specified object.
+ * The result is true
if and only if the argument is not
+ * null
and is a AsnNull
object.
+ *
+ * @param anObject the object to compare this AsnNull
+ * against.
+ * @return true
if the AsnNull
are equal;
+ * false
otherwise.
+ */
+public boolean equals(Object anObject)
+{
+ if (this == anObject)
+ {
+ return true;
+ }
+ if (anObject instanceof AsnNull)
+ {
+ AsnNull anotherNull = (AsnNull)anObject;
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ * Returns a hash code for this object.
+ * @return a hash code value for this object.
+ */
+public int hashCode()
+{
+ int h = 5;
+ return h;
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AsnObject.java b/src/main/java/uk/co/westhawk/snmp/stack/AsnObject.java
new file mode 100644
index 0000000..4546772
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AsnObject.java
@@ -0,0 +1,605 @@
+// NAME
+// $RCSfile: AsnObject.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.30 $
+// CREATED
+// $Date: 2006/03/23 14:54:09 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ * original version by hargrave@dellgate.us.dell.com (Jordan Hargrave)
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.io.*;
+import java.util.*;
+import uk.co.westhawk.snmp.util.*;
+
+/**
+ * This class represents the ASN.1 base class.
+ * SMIv1 RFC1155-SMI.
+ * SMIv2 SNMPv2-SMI.
+ *
+ *
+ * <ASN Object> = <type> <length> <ASN Object>
+ * or
+ * <ASN Object> = <type> <length> <value>
+ *
+ *
+ * @author Tim Panton
+ * @version $Revision: 3.30 $ $Date: 2006/03/23 14:54:09 $
+ */
+
+public abstract class AsnObject extends Object implements SnmpConstants
+{
+ private static final String version_id =
+ "@(#)$Id: AsnObject.java,v 3.30 2006/03/23 14:54:09 birgit Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * Indicates the level of debug printed. By default this is none
+ * (0).
+ * @see #setDebug(int)
+ */
+ public static int debug = 0;
+
+ /**
+ * The type of object.
+ */
+ protected byte type;
+
+ /**
+ * The starting position of the AsnObject in the SNMP sequence. That
+ * is the position of the 'type' byte.
+ */
+ protected int startPos = 0;
+
+ /**
+ * The length of the header. That is the number of bytes of the 'type'
+ * and 'length' fields. Since there are multiple valid encodings for
+ * a given AsnObject, this length is not fixed!
+ */
+ protected int headerLength = 0;
+
+ /**
+ * The length of the actual contents. That is the same as the value of
+ * the 'length' field.
+ */
+ protected int contentsLength = 0;
+
+ /**
+ * Flag to signal the object is of a correct type.
+ */
+ protected boolean isCorrect = true;
+
+ abstract void write (OutputStream out, int pos)
+ throws IOException, EncodingException;
+
+ /**
+ * Returns a string representation of the object.
+ * @return The string
+ */
+ public abstract String toString();
+
+/**
+ * Sets the new, global level of debug information for the stack package.
+ * The default value is zero, i.e. no debug info at all. All debug
+ * messages are printed to System.out.
+ *
+ * The following messages will appear when debug is > (greater than):
+ *
+ *
+ * 0
- IOExceptions that won't be thrown to the user
+ * 1
- DecodingExceptions that won't be thrown to the user (received message with wrong SNMP version)
+ * 2
- DecodingExceptions when trying to decode traps
+ * 3
- processIncomingResponse errors: (corresponding Pdu cannot be found)
+ * 4
- Discovery of EngineId, Timeline
+ * 5
- Receiving traps, version/host do not correspond
+ * 6
- Pdu messages, sending etc
+ * 10
- Asn decoding of incoming messages
+ * 12
- Transmitter messages, Socket messages
+ * 15
- Not so important IOExceptions, like InterruptedIOException
+ *
+ *
+ * @param newDebug the new debug value
+ */
+public static void setDebug(int newDebug)
+{
+ debug = newDebug;
+}
+
+ AsnObject AsnReadHeader(InputStream in) throws IOException
+ {
+ return AsnReadHeader(in, 0);
+ }
+
+ /**
+ * @param pos The starting position, i.e. the pos the 'type' byte.
+ */
+ AsnObject AsnReadHeader(InputStream in, int pos) throws IOException
+ {
+ int len, got;
+ AsnObject ret = null;
+ int had = in.available();
+
+ //Type byte
+ type = (byte) in.read();
+ if (type != -1)
+ {
+ len = getLengthPacket(in);
+ int off = in.available();
+ int headLength = had - off;
+
+ got = 0;
+ byte body[] = new byte[len];
+ if (len > 0)
+ {
+ got = in.read(body, 0, len);
+ }
+ if (got > -1)
+ {
+ // Always decode, unless in.read returned an error
+ // (i.e. got == -1):
+ //
+ // 1.
+ // If we haven't received all bytes (i.e. got < len)
+ // we will still try and decode as much as we can:
+ // Since body[] has the length 'len' (i.e. the
+ // length according to the packet), it will be padded with
+ // zero
+ //
+ // 2.
+ // If len was 0, got would have been been -1, but since
+ // no read was performed, got is 0.
+ // A len of 0 is a valid case however.
+
+ ByteArrayInputStream buf = new ByteArrayInputStream(body);
+ ret = AsnMakeMe(buf, type, len, pos, headLength);
+
+ if (got != len)
+ {
+ ret.isCorrect = false;
+ if (debug > 10)
+ {
+ System.out.println("\nAsnObject.AsnReadHeader():"
+ + " incorrect packet. Length = " + (int) len
+ + ", Got = " + got);
+ }
+ }
+ }
+ else
+ {
+ if (debug > 10)
+ {
+ System.out.println("\nAsnObject.AsnReadHeader(): Length = "
+ + (int) len
+ + ", Got = " + got
+ + ". Not processing any further.");
+ }
+ }
+ }
+ return ret;
+ }
+
+
+ AsnObject AsnMakeMe(InputStream in, byte t, int len, int pos,
+ int headLength) throws IOException
+ {
+ AsnObject me = this;
+ type = t;
+
+ switch (type)
+ {
+ case CONS_SEQ :
+ me = new AsnSequence(in, len, (pos+headLength));
+ break;
+ case GET_REQ_MSG :
+ case GETNEXT_REQ_MSG :
+ case SET_REQ_MSG :
+ case GETBULK_REQ_MSG :
+ case INFORM_REQ_MSG :
+ case GET_RSP_MSG :
+ case GET_RPRT_MSG :
+ case TRPV2_REQ_MSG :
+ me = new AsnPduSequence(in, len, (pos+headLength));
+ break;
+ case TRP_REQ_MSG :
+ me = new AsnTrapPduv1Sequence(in, len, (pos+headLength));
+ break;
+ case ASN_INTEGER :
+ me = new AsnInteger(in, len);
+ break;
+ case TIMETICKS :
+ case COUNTER :
+ case GAUGE :
+ case OBSOLETED_RFC1442_UINTEGER32 :
+ me = new AsnUnsInteger(in, len);
+ break;
+ case COUNTER64 :
+ me = new AsnUnsInteger64(in, len); // TODO test
+ break;
+ case ASN_OBJECT_ID :
+ me = new AsnObjectId(in, len);
+ break;
+ case IPADDRESS :
+ case ASN_OCTET_STR :
+ case OPAQUE :
+ case NSAP_ADDRESS :
+ me = new AsnOctets(in, len);
+ break;
+ case ASN_NULL :
+ me = new AsnNull(in, len);
+ break;
+ case SNMP_VAR_NOSUCHOBJECT:
+ case SNMP_VAR_NOSUCHINSTANCE:
+ case SNMP_VAR_ENDOFMIBVIEW:
+ me = new AsnPrimitive(type);
+ break;
+ default :
+ if (debug > 0)
+ {
+ System.out.println("AsnObject.AsnMakeMe():"
+ + " Bad Type 0x" + SnmpUtilities.toHex(type));
+ }
+ me = new AsnNull(in, len);
+ me.isCorrect = false;
+ break;
+ }
+ me.type = type;
+ me.startPos = pos;
+ me.headerLength = headLength;
+ me.contentsLength = len;
+
+ if (debug > 10)
+ {
+ System.out.println("AsnObject.AsnMakeMe():"
+ + " headerLength = " + me.headerLength
+ + ", contentsLength = " + me.contentsLength);
+ System.out.println("\ttype = 0x"
+ + SnmpUtilities.toHex(type)
+ + ", " + me.getRespTypeString()
+ + ", " + me.getClass().getName()
+ + ": value = " + me.toString()
+ + ", startPos = " + me.startPos
+ + ", correct = " + me.isCorrect);
+ }
+ return me;
+ }
+
+ /** Adds a child to the sequence
+ */
+ AsnObject add (AsnObject child)
+ {
+ return child;
+ }
+
+ /** recursively look for a pduSequence object
+ * if not overridden - then not a sequence -
+ */
+ AsnObject findPdu()
+ {
+ return null;
+ }
+
+ /** recursively look for a pduSequence object
+ * if not overridden - then not a sequence -
+ */
+ AsnObject findTrapPduv1()
+ {
+ return null;
+ }
+
+ /**
+ * Output ASN header.
+ */
+ void AsnBuildHeader(OutputStream out, byte t, int length)
+ throws IOException
+ {
+ int count;
+
+ type = t;
+ // Type byte
+ out.write(type);
+
+ // Length bytes
+ count = getLengthBytes(length);
+ headerLength = count + 1;
+ contentsLength = length;
+ if (debug > 10)
+ {
+ System.out.println("AsnBuildHeader(): "
+ + "type = 0x" + SnmpUtilities.toHex(type)
+ + ", headerLength = " + headerLength
+ + ", contentsLength = " + contentsLength);
+ }
+
+ if (count > 1)
+ {
+ // Write long form prefix byte
+ --count;
+ byte tmp = (byte) (0x80 | (byte) count);
+ out.write(tmp);
+ }
+ while(count!=0)
+ {
+ // Write length bytes
+ out.write((byte)((length >> (--count << 3)) & 0xFF));
+ }
+ }
+
+ int size() throws EncodingException
+ {
+ return 0;
+ }
+
+ /**
+ * Returns length field size for a packet length.
+ * Returns:
+ * 1 if length will fit in short form (0x00-0x7f)
+ * 2+ if length >= 0x80
+ */
+ int getLengthBytes(int length)
+ {
+ int mask, count;
+
+ if (length < 0x80)
+ {
+ // Short form.. 1 byte
+ return 1;
+ }
+ else
+ {
+ // Long form.. prefix byte + length bytes
+ mask = 0xFF000000;
+ for(count=4; (length&mask)==0; count--)
+ {
+ mask >>= 8;
+ }
+ return count+1;
+ }
+ }
+
+
+ int getLengthPacket(InputStream in) throws IOException
+ {
+ int length = 0;
+ byte mask =(byte) 0x7f;
+ byte len = (byte) in.read();
+
+ if ((0x80 & len) != 0)
+ {
+ // long form
+
+ int count = (mask & len);
+ if (count < 4)
+ {
+ byte data[] = new byte[count];
+ int n = in.read(data, 0, count);
+ if (n != count)
+ {
+ throw new IOException("AsnObject.getLengthPacket(): Not enough data");
+ }
+ else
+ {
+ /*
+ * Thanks to Julien Conan (jconan@protego.net)
+ * for improving this code.
+ */
+ DataInputStream dis = new DataInputStream(
+ new ByteArrayInputStream(data));
+
+ for (n=0; nTim Panton
+ * original version by hargrave@dellgate.us.dell.com (Jordan Hargrave)
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.io.*;
+import java.util.*;
+
+// unsigned 32-bit integers encoded in the following format:
+// MSB..LSB
+// 76543210
+// xyyyyyyy
+// .\ /
+// . \ /
+// . \ /
+// . +-------- OID bits
+// +------------ 0 if this is the last byte, 1 if additional bytes follow
+//
+// Output sid in the form: abcdefgh.ijklmnop.qrstuvwx.yzABCDEF
+//
+// if (abcd != 0) {
+// output 1.000abcd 1.efghijk 1.lmnopqr 1.stuvwxy 0.zABCDEF
+// } else if (efghijk != 0) {
+// output 1.efghijk 1.lmnopqr 1.stuvwxy 0.zABCDEF
+// } else if (lmnopqr != 0) {
+// output 1.lmnopqr 1.stuvwxy 0.zABCDEF
+// } else if (stuvwxy != 0) {
+// output 1.stuvwxy 0.zABCDEF
+// } else {
+// output 0.zABCDEF
+// }
+
+
+/**
+ * This class represents the ASN.1 ObjectID class. An Object ID (OID)
+ * identifies a variable in a MIB.
+ *
+ * @author Tim Panton
+ * @version $Revision: 3.25 $ $Date: 2008/08/19 13:34:13 $
+ */
+public class AsnObjectId extends AsnObject implements Comparable
+{
+ private static final String version_id =
+ "@(#)$Id: AsnObjectId.java,v 3.25 2008/08/19 13:34:13 birgita Exp $ Copyright Westhawk Ltd";
+
+ // Thanks to Ken Swanson (gks@navcomm1.dnrc.bell-labs.com) for
+ // pointing out that this should be an array of longs.
+
+ // default value for test purposes.
+ // private long value[] = {1,3,6,1,4,1,674,10889,2,1,0};
+ private long value[] = {};
+
+ /**
+ * Thanks to Robert Kostes .
+ * @see #toString(long[])
+ */
+ final static char[] digits = {'0','1','2','3','4','5','6','7','8','9'};
+
+/**
+ * The empty constructor.
+ */
+protected AsnObjectId()
+{
+ type = ASN_OBJECT_ID;
+}
+
+/**
+ * Constructor.
+ *
+ * @param in The input stream from which the value should be read
+ * @param len The length of the AsnInteger
+ */
+AsnObjectId(InputStream in, int len) throws IOException
+{
+ // get our data
+ byte data[] = new byte[len];
+ if (len != in.read(data,0,len))
+ {
+ throw new IOException("AsnObjectId(): Not enough data");
+ }
+
+ // now decide how many SID we will need
+ // count the bytes with 0 in the top bit - then add 1
+ int sids = 1; // first byte has 2 sids in it
+ for (int off=0; off= 0)
+ {
+ sids++;
+ }
+ }
+ // so allocate some space for the sids
+ value = new long[sids];
+
+ // decode the first two
+ if (len > 0)
+ {
+ value[0] = data[0] / 40;
+ if (value.length > 1)
+ {
+ value[1] = data[0] % 40;
+ }
+ }
+
+ // now decode the rest
+ int off = 1;
+ for (int idx=2; idx 0)
+ {
+ StringTokenizer tok = new StringTokenizer(s, ".");
+ int count = tok.countTokens();
+ oidArray = new long[count];
+
+ int n=0;
+ while (tok.hasMoreTokens())
+ {
+ try
+ {
+ String num = tok.nextToken();
+ Long val = Long.valueOf(num);
+ oidArray[n] = val.longValue();
+ n++;
+ }
+ catch (NumberFormatException exc)
+ {
+ throw new IllegalArgumentException("AsnObjectId(): Bad OID '"
+ + s + "' " + exc.getMessage());
+ }
+ catch (NoSuchElementException exc)
+ {
+ }
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("AsnObjectId(): Bad OID '"
+ + s + "' ");
+ }
+
+ return oidArray;
+}
+
+
+/**
+ * Checks if this OID starts with the specified prefix.
+ *
+ * @return true if starts with the prefix, false otherwise
+ */
+public boolean startsWith(AsnObjectId prefix)
+{
+ boolean sw = true;
+ if (prefix.value.length < this.value.length)
+ {
+ int pos=0;
+ while (pos < prefix.value.length && sw == true)
+ {
+ sw = (prefix.value[pos] == this.value[pos]);
+ pos++;
+ }
+ }
+ else
+ {
+ sw = false;
+ }
+ return sw;
+}
+
+/**
+ * Adds a single sub-identifier to the end of the OID.
+ *
+ * @param sub_oid The sub-identifier
+ */
+public void add(long sub_oid)
+{
+ int size = value.length;
+
+ long tmp_value[] = value;
+ value = new long[size+1];
+ System.arraycopy(tmp_value, 0, value, 0, size);
+ value[size] = sub_oid;
+}
+
+
+/**
+ * Adds a number of sub-identifiers to the end of the OID.
+ *
+ * @param sub_oid The sub-identifiers
+ * @see AsnOctets#toSubOid
+ */
+public void add(long[] sub_oid)
+{
+ int size1 = value.length;
+ int size2 = sub_oid.length;
+
+ long tmp_value[] = value;
+ value = new long[size1+size2];
+ System.arraycopy(tmp_value, 0, value, 0, size1);
+ System.arraycopy(sub_oid, 0, value, size1, size2);
+}
+
+
+/**
+ * Adds sub-identifiers to the end of the OID.
+ *
+ * @param s The sub-identifiers, format a[.b]*
+ */
+public void add(String s) throws IllegalArgumentException
+{
+ long [] sub_oid = toArrayOfLongs(s);
+ add(sub_oid);
+}
+
+/**
+ * Removes the last sub-identifier (if available) from this
+ * OID and returns it.
+ * @return The sub-identifier or -1 if there is no sub-identifier
+ * @since 6.1
+ */
+public long removeLast()
+{
+ long lastSubOid = -1;
+ int size = value.length;
+ if (size > 0)
+ {
+ // get the last sub-oid
+ size -= 1;
+ lastSubOid = value[size];
+
+ // remove the last sub-oid
+ long tmp_value[] = value;
+ value = new long[size];
+ System.arraycopy(tmp_value, 0, value, 0, size);
+ }
+ return lastSubOid;
+}
+
+
+/**
+ * Returns the total size of the object ID.
+ */
+int size() throws EncodingException
+{
+ int val, idx, len;
+
+ if (value.length > 1)
+ {
+ // First entry = OID[0]*40 + OID[1];
+ len = getSIDLen(value[0]*40 + value[1]);
+ for(idx=2; idx 10)
+ {
+ System.out.println("\tAsnObjectId(): value = " + this.toString()
+ + ", pos = " + pos);
+ }
+
+ // Output data bytes
+ if (value.length > 1)
+ {
+ // First entry = OID[0]*40 + OID[1];
+ EncodeSID(out, value[0]*40 + value[1]);
+ for(idx=2; idx>=7) != 0; count++)
+ ;
+ return count;
+}
+
+/**
+ * Encode OID subidentifier.
+ */
+private void EncodeSID(OutputStream out, long value) throws IOException
+{
+ byte mask = (byte)0x0F;
+ int count = 0;
+
+ // Upper mask is 4 bits
+ mask = 0xF;
+
+ // Loop while value and mask is zero
+ for(count=28; count>0; count-=7)
+ {
+ if (((value >> count) & mask) != 0) break;
+ mask = 0x7f;
+ }
+
+ // While count, output value. If this isn't the last byte, output
+ // 0x80 | value.
+ for(; count>=0; count-=7)
+ {
+ out.write((byte)(((value >> count) & mask) | (count>0 ? 0x80 : 0x00)) );
+ mask = 0x7f;
+ }
+}
+
+
+/**
+ * Returns the value of the AsnObjectId.
+ *
+ * @return The value (the OID)
+ */
+public String getValue()
+{
+ return toString();
+}
+
+
+/**
+ * Returns the string representation of the AsnObjectId.
+ *
+ * @return The string of the AsnObjectId
+ */
+public String toString()
+{
+ return toString(value);
+}
+
+/**
+ * Returns the string representation of the AsnObjectId.
+ *
+ * @return The string of the AsnObjectId
+ */
+public String toString(long v[])
+{
+ StringBuffer buffer = new StringBuffer("");
+ if (v.length > 0)
+ {
+ for (int n=0; n < v.length-1 && n<100 ; n++)
+ {
+ // optimization, thanks to Robert Kostes who
+ // did some profiling.
+ if (0 <= v[n] && v[n] <= 9)
+ {
+ // append a fixed char
+ int i = (int) v[n];
+ buffer.append(digits[i]);
+ }
+ else
+ {
+ // go through number conversion
+ buffer.append(v[n]);
+ }
+ buffer.append(".");
+ }
+ if (v.length-1 > 100)
+ {
+ buffer.append("[.. cut ..].");
+ }
+ buffer.append(v[v.length-1]);
+ }
+ return buffer.toString();
+}
+
+/**
+ * Returns the number of elements in the AsnObjectId.
+ * We cannot use size(), since that is already in use.
+ *
+ * @return the number of elements
+ */
+public int getSize()
+{
+ return value.length;
+}
+
+/**
+ * Returns the element in the AsnObjectId at the specified index.
+ *
+ * @param index The index
+ * @return the element at the specified index
+ * @exception ArrayIndexOutOfBoundsException if an invalid
+ * index was given
+ */
+public synchronized long getElementAt(int index)
+ throws ArrayIndexOutOfBoundsException
+{
+ if (index >= value.length)
+ {
+ throw new ArrayIndexOutOfBoundsException(index
+ + " >= " + value.length);
+ }
+ try
+ {
+ return value[index];
+ }
+ catch (ArrayIndexOutOfBoundsException exc)
+ {
+ throw new ArrayIndexOutOfBoundsException(index + " < 0");
+ }
+}
+
+/**
+ * Returns the last element in the AsnObjectId.
+ *
+ * @return the last element
+ * @exception ArrayIndexOutOfBoundsException if the
+ * AsnObjectId is empty.
+ * @since 6.1
+ */
+public long lastElement()
+ throws ArrayIndexOutOfBoundsException
+{
+ return getElementAt(value.length-1);
+}
+
+/**
+ * Returns the value of the AsnObjectId as an array of long. The value
+ * returned is a copy.
+ *
+ * @return The OID value
+ * @since 4_14
+ */
+public long[] getOid()
+{
+ int len = value.length;
+ long [] oida = new long[len];
+ System.arraycopy(value, 0, oida, 0, len);
+ return oida;
+}
+
+
+/**
+ * Returns a subset of the value of the AsnObjectId as an array of long.
+ * The value returned is a copy.
+ *
+ * @return The sub OID value
+ * @since 4_14
+ */
+public long[] getSubOid(int beginIndex, int endIndex)
+throws ArrayIndexOutOfBoundsException
+{
+ int len1 = value.length;
+ if (beginIndex < 0)
+ {
+ throw new ArrayIndexOutOfBoundsException(beginIndex + " < 0");
+ }
+ if (endIndex > len1)
+ {
+ throw new ArrayIndexOutOfBoundsException(endIndex + " > " + len1);
+ }
+ if (beginIndex > endIndex)
+ {
+ throw new ArrayIndexOutOfBoundsException(beginIndex + " > " + endIndex);
+ }
+
+ int len2 = endIndex - beginIndex;
+ long [] oida = new long[len2];
+ System.arraycopy(value, beginIndex, oida, 0, len2);
+ return oida;
+}
+
+
+
+/**
+ * Compares this OID to the specified object.
+ * The result is true
if and only if the argument is not
+ * null
and is a AsnObjectId
object that represents
+ * the same sequence of numbers as this object.
+ *
+ *
+ *
+ * Thanks to Eli Bishop (eli@graphesthesia.com) for the suggestion of
+ * adding it.
+ *
+ *
+ * @param anObject The object to compare this AsnObjectId
+ * against.
+ * @return true
if the AsnObjectId
are equal;
+ * false
otherwise.
+ */
+public boolean equals(Object anObject)
+{
+ if (this == anObject)
+ {
+ return true;
+ }
+ if (anObject instanceof AsnObjectId)
+ {
+ AsnObjectId anotherOid = (AsnObjectId)anObject;
+ int n = value.length;
+ if (n == anotherOid.value.length)
+ {
+ long v1[] = value;
+ long v2[] = anotherOid.value;
+ int i = 0;
+ int j = 0;
+ while (n-- != 0)
+ {
+ if (v1[i++] != v2[j++])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/**
+ * Returns a hash code for this OID.
+ * The hash value of the empty OID is zero.
+ *
+ * @return a hash code value for this object.
+ */
+public int hashCode()
+{
+ int h = 0;
+ if (h == 0)
+ {
+ int off = 0;
+ long val[] = value;
+ int len = value.length;
+
+ for (int i=0; i>> 32));
+ h = 31*h + hi;
+ }
+ }
+ return h;
+}
+
+
+/**
+ * @see Comparable#compareTo
+ * @see #compareTo(AsnObjectId)
+ * @since 6.1
+ */
+public int compareTo(Object o)
+{
+ return compareTo((AsnObjectId) o);
+}
+
+/**
+ * @see Comparable#compareTo
+ * Thanks to Josh Bers to providing this code.
+ * @since 6.1
+ */
+public int compareTo(AsnObjectId b)
+{
+ if (b == null)
+ {
+ throw new NullPointerException("Trying to compare with null");
+ }
+
+ int aElts = getSize();
+ int bElts = b.getSize();
+
+ if ((aElts == 0) && (bElts > 0))
+ {
+ return -1;
+ }
+ if ((bElts == 0) && (aElts > 0))
+ {
+ return 1;
+ }
+
+ for (int i=0; (i < aElts) && (i < bElts); i++)
+ {
+ if (getElementAt(i) != b.getElementAt(i))
+ {
+ if (getElementAt(i) > b.getElementAt(i))
+ {
+ return 1;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ }
+
+ // equal to the end of one object
+ if (aElts > bElts)
+ {
+ return 1;
+ }
+ else if (bElts > aElts)
+ {
+ return -1;
+ }
+
+ // both objects same
+ return 0;
+}
+
+
+/**
+ * Compares the n leftmost sub-identifiers with the given
+ * AsnObject in left-to-right direction.
+ * @param n The number of sub-identifiers to compare.
+ * @param b An AsnObject to compare with this object
+ * @return
+ *
+ * -
+ * 0, when the first 'n' sub-identifiers are the same.
+ *
+ * -
+ * -1 when the first 'n' sub-identifiers of this object are
+ * lexicographic less than those of b. This includes the case where
+ * this object is shorter than 'n' AND shorter than b.
+ *
+ * -
+ * 1 when the first 'n' sub-identifiers of this object are
+ * lexicographic greater than those of b.
+ *
+ *
+ * @since 6.1
+ */
+public int leftMostCompare(int n, AsnObjectId b)
+{
+ if (b == null)
+ {
+ throw new NullPointerException("Trying to compare with null");
+ }
+
+ int aElts = getSize();
+ int bElts = b.getSize();
+
+
+ int min = Math.min(aElts, bElts);
+ if (min < n)
+ {
+ if (aElts > bElts)
+ {
+ return 1;
+ }
+ else if (bElts > aElts)
+ {
+ return -1;
+ }
+ else
+ {
+ return this.compareTo(b);
+ }
+ }
+ else
+ {
+ // min >= n
+ long[] aOids = getSubOid(0, n);
+ long[] bOids = b.getSubOid(0, n);
+ AsnObjectId aCopy = new AsnObjectId(aOids);
+ AsnObjectId bCopy = new AsnObjectId(bOids);
+ return aCopy.compareTo(bCopy);
+ }
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AsnOctets.java b/src/main/java/uk/co/westhawk/snmp/stack/AsnOctets.java
new file mode 100644
index 0000000..4f785f7
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AsnOctets.java
@@ -0,0 +1,989 @@
+// NAME
+// $RCSfile: AsnOctets.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.39 $
+// CREATED
+// $Date: 2006/03/23 14:54:10 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ * original version by hargrave@dellgate.us.dell.com (Jordan Hargrave)
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.util.*;
+import java.io.*;
+import java.util.*;
+import java.net.InetAddress;
+import java.text.SimpleDateFormat;
+
+/**
+ * This class represents the ASN.1 Octet class.
+ * It can be used for Octets, Ip Addresses and Opaque primitive types.
+ *
+ * The Octets type (ASN_OCTET_STR) is used for some text convensions.
+ * This class supports the DateAndTime, DisplayString and
+ * InternationalDisplayString and Ipv6Address text convensions.
+ *
+ * Note, the SNMP representation of IPv4 and IPv6 is different:
+ *
+ * - IPv4: IPADDRESS (or ASN_OCTET_STR, see rfc 4001)
+ * - IPv6: ASN_OCTET_STR
+ *
+ * See also
+ * IPV6-TC,
+ * SNMPv2-PDU,
+ * INET-ADDRESS-MIB.
+ *
+ * @see SnmpConstants#ASN_OCTET_STR
+ * @see SnmpConstants#IPADDRESS
+ * @see SnmpConstants#OPAQUE
+ *
+ * @author Tim Panton
+ * @version $Revision: 3.39 $ $Date: 2006/03/23 14:54:10 $
+ */
+public class AsnOctets extends AsnObject
+{
+ private static final String version_id =
+ "@(#)$Id: AsnOctets.java,v 3.39 2006/03/23 14:54:10 birgit Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * The hexadecimal prefix that is used when printing a hexadecimal
+ * number in toString(). By default this is "0x".
+ */
+ public static String HEX_PREFIX = "0x";
+
+ /**
+ * The object that is used in toCalendar() to format the calendar
+ * representation of the Octets according to the DateAndTime text
+ * convension.
+ * The pattern is "yyyy-M-d,HH:mm:ss.SS,z".
+ *
+ * @see #getCalendar()
+ * @see #toCalendar()
+ * @see SimpleDateFormat
+ */
+ public static SimpleDateFormat CALFORMAT = new SimpleDateFormat("yyyy-M-d,HH:mm:ss.SS,z");
+
+ /**
+ * The default AsnOctetsPrintableFace object.
+ *
+ * @see #setPrintable
+ * @see DefaultAsnOctetsPrintable
+ */
+ public static AsnOctetsPrintableFace printableObject = new DefaultAsnOctetsPrintable();
+
+ byte value[];
+
+ /** Cache the hash code for the OID */
+ private int hash = 0;
+
+ /**
+ * Constructor. The type of the AsnOctets defaults to ASN_OCTET_STR.
+ *
+ * @param s The byte array representing the AsnOctets
+ * @see SnmpConstants#ASN_OCTET_STR
+ */
+ public AsnOctets(byte s[])
+ throws IllegalArgumentException
+ {
+ this(s, ASN_OCTET_STR);
+ }
+
+ /**
+ * Constructor to create a specific type of AsnOctets.
+ *
+ * @param s The byte array representing the AsnOctets
+ * @param t The type of the AsnOctets
+ * @see SnmpConstants#ASN_OCTET_STR
+ * @see SnmpConstants#IPADDRESS
+ * @see SnmpConstants#OPAQUE
+ */
+ public AsnOctets(byte s[], byte t)
+ throws IllegalArgumentException
+ {
+ value = s;
+ type = t;
+ if (value == null)
+ {
+ throw new IllegalArgumentException("Value is null");
+ }
+ }
+
+ /**
+ * Constructor. The type of the AsnOctets defaults to ASN_OCTET_STR.
+ *
+ * @param s The character array representing the AsnOctets
+ * @see SnmpConstants#ASN_OCTET_STR
+ */
+ public AsnOctets(char s[])
+ {
+ int idx;
+
+ value = new byte[s.length];
+ type = ASN_OCTET_STR;
+ for (idx=0; idx
+ * Note, the SNMP representation of IPv4 and IPv6 is different:
+ *
+ * - IPv4: IPADDRESS (or ASN_OCTET_STR, see rfc 4001)
+ * - IPv6: ASN_OCTET_STR
+ *
+ * See also
+ * IPV6-TC,
+ * SNMPv2-PDU,
+ * INET-ADDRESS-MIB.
+ *
+ * @param iad The Inet Address
+ *
+ * @see #AsnOctets(Inet4Address, byte)
+ */
+ public AsnOctets(InetAddress iad)
+ throws IllegalArgumentException
+ {
+ this(iad.getAddress(), ASN_OCTET_STR);
+ if (iad instanceof java.net.Inet4Address)
+ {
+ // IPv4
+ type = IPADDRESS;
+ }
+ else
+ {
+ // IPv6 is ASN_OCTET_STR, so do nothing
+ }
+ }
+
+
+ /**
+ * Constructor to create an ASN IPv4 Address.
+ * If the address is an IPv4 address, it can either be represented
+ * by IPADDRESS or as ASN_OCTET_STR.
+ *
+ * See also
+ * IPV6-TC,
+ * SNMPv2-PDU,
+ * INET-ADDRESS-MIB.
+ *
+ * @param iad The IPv4 Inet Address
+ * @param t The type of the AsnOctets
+ *
+ * @see #AsnOctets(InetAddress)
+ * @see SnmpConstants#IPADDRESS
+ * @see SnmpConstants#ASN_OCTET_STR
+ * @since 4_14
+ */
+ public AsnOctets(java.net.Inet4Address iad, byte t)
+ throws IllegalArgumentException
+ {
+ this(iad.getAddress(), t);
+ }
+
+
+ /**
+ * Constructor for DateAndTime text convension.
+ * See
+ * SNMPv2-TC
+ *
+ *
+ * field octets contents range
+ * ----- ------ -------- -----
+ * 1 1-2 year* 0..65536
+ * 2 3 month 1..12
+ * 3 4 day 1..31
+ * 4 5 hour 0..23
+ * 5 6 minutes 0..59
+ * 6 7 seconds 0..60
+ * (use 60 for leap-second)
+ * 7 8 deci-seconds 0..9
+ *
+ * 8 9 direction from UTC '+' / '-'
+ * 9 10 hours from UTC* 0..13
+ * 10 11 minutes from UTC 0..59
+ *
+ * SYNTAX OCTET STRING (SIZE (8 | 11))
+ *
+ *
+ * @since 4_14
+ */
+ public AsnOctets(Calendar cal)
+ {
+ value = new byte[11];
+ type = ASN_OCTET_STR;
+
+ int year = cal.get(Calendar.YEAR);
+ // Calendar: 0=January
+ int month = cal.get(Calendar.MONTH)+1;
+ int day = cal.get(Calendar.DAY_OF_MONTH);
+ int hour = cal.get(Calendar.HOUR_OF_DAY);
+ int min = cal.get(Calendar.MINUTE);
+ int sec = cal.get(Calendar.SECOND);
+ int msec = cal.get(Calendar.MILLISECOND);
+ int msecGMT = cal.get(Calendar.ZONE_OFFSET);
+
+ // The value of year is in network-byte order
+ // Is this correct?
+ value[0] = (byte) ((year / 256) % 256);
+ value[1] = (byte) (year % 256);
+
+ value[2] = (byte) (month & 0xFF);
+ value[3] = (byte) (day & 0xFF);
+ value[4] = (byte) (hour & 0xFF);
+ value[5] = (byte) (min & 0xFF);
+ value[6] = (byte) (sec & 0xFF);
+ value[7] = (byte) ((msec / 100) & 0xFF);
+
+ char dir = '\0';
+ if (msecGMT < 0)
+ {
+ dir = '-';
+ msecGMT = msecGMT * -1;
+ }
+ else
+ {
+ dir = '+';
+ }
+ value[8] = (byte) dir;
+
+ if (msecGMT == 0)
+ {
+ value[9] = 0x00;
+ value[10] = 0x00;
+ }
+ else
+ {
+ int minGMT = (int) (((double) msecGMT) / 1000.0 / 60.0);
+ if (minGMT == 0)
+ {
+ value[9] = 0x00;
+ value[10] = 0x00;
+ }
+ else
+ {
+ int hourGMT = (int) (minGMT / 60.0);
+ minGMT = minGMT - (hourGMT * 60);
+ value[9] = (byte) (hourGMT & 0xFF);
+ value[10] = (byte) (minGMT & 0xFF);
+ }
+ }
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param in The input stream from which the value should be read
+ * @param len The length of the AsnOctets
+ */
+ public AsnOctets(InputStream in, int len) throws IOException
+ {
+ value = new byte[len];
+ if (len != 0)
+ {
+ if (len == in.read(value,0,len))
+ {
+ String str = "";
+ //str = new String(value);
+ }
+ else
+ {
+ throw new IOException("AsnOctets(): Not enough data");
+ }
+ }
+ else
+ {
+ // if len is zero, the in.read will return -1
+ // a length of zero is a valid case.
+ ;
+ }
+ }
+
+ /**
+ * Sets the global hexadecimal prefix. This prefix will be used in
+ * toString() when it prints out a hexadecimal number. It is not
+ * used in toHex(). The default is "0x".
+ *
+ * @see #toString()
+ * @see #toHex()
+ * @see #HEX_PREFIX
+ */
+ public static void setHexPrefix(String newPrefix)
+ {
+ HEX_PREFIX = newPrefix;
+ }
+
+ /**
+ * Sets the global AsnOctetsPrintableFace printableObject. This
+ * object will be used in the toString() and the
+ * toInternationalDisplayString() methods.
+ *
+ * @see #toString
+ * @see #toInternationalDisplayString
+ * @since 4_14
+ */
+ public static void setPrintable(AsnOctetsPrintableFace obj)
+ {
+ if (obj != null)
+ {
+ printableObject = obj;
+ }
+ }
+
+
+ /**
+ * Returns the String value. Calls toString().
+ *
+ * @return The value of the AsnOctets
+ * @see #toString()
+ */
+ public String getValue()
+ {
+ return toString();
+ }
+
+ /**
+ * Returns the bytes. This returns a copy of the internal byte array.
+ *
+ * @return The bytes of the AsnOctets
+ */
+ public byte[] getBytes()
+ {
+ int len = value.length;
+ byte [] bytea = new byte[len];
+ System.arraycopy(value, 0, bytea, 0, len);
+ return bytea;
+ }
+
+ /**
+ * Returns the string representation of the AsnOctets.
+ *
+ * The string will have one of the following formats:
+ *
+ *
+ * - if this class represents an IP Address (v4), it will call
+ * toIpAddress()
+ * - <prefix>aa[:bb]*, if this class represents a non-printable
+ * string or has type OPAQUE.
+ * The output will be in hexadecimal numbers (see toHex()). It will be prefixed
+ * according to the hex. prefix value
+ * - a printable string, if this class seems printable
+ *
+ *
+ *
+ * When the type is ASN_OCTET_STR, this method uses the
+ * AsnOctetsPrintableFace.isPrintable() to determine whether or not
+ * the string is printable. If it is printable, it will use
+ * AsnOctetsPrintableFace.toInternationalDisplayString() to
+ * transform the Octets to a String.
+ *
+ *
+ *
+ * Note, the SNMP representation of IPv4 and IPv6 is different:
+ *
+ * - IPv4: IPADDRESS (or ASN_OCTET_STR, see rfc 4001)
+ * - IPv6: ASN_OCTET_STR
+ *
+ * See also
+ * IPV6-TC,
+ * SNMPv2-PDU,
+ * INET-ADDRESS-MIB.
+ *
+ * @see #HEX_PREFIX
+ * @see #setHexPrefix(String)
+ * @see #toHex
+ * @see #toIpAddress
+ * @see AsnOctetsPrintableFace#isPrintable
+ * @see AsnOctetsPrintableFace#toInternationalDisplayString
+ * @return The string representation of the AsnOctets
+ */
+ public String toString()
+ {
+ return toString(printableObject);
+ }
+
+ /**
+ * As toString(), but this methods will use this specific, one-off
+ * AsnOctetsPrintableFace object.
+ *
+ * @see #toString()
+ * @since 4_14
+ */
+ public String toString(AsnOctetsPrintableFace face)
+ {
+ String str = "";
+
+ if (type == IPADDRESS)
+ {
+ // for IPv4 only
+ str = toIpAddress();
+ }
+ else if (type == OPAQUE)
+ {
+ str = HEX_PREFIX + toHex();
+ }
+ else
+ {
+ boolean isPrintable = face.isPrintable(value);
+ if (isPrintable)
+ {
+ str = face.toInternationalDisplayString(value);
+ }
+ else
+ {
+ str = HEX_PREFIX + toHex();
+ }
+ }
+ return str;
+ }
+
+
+ int size()
+ {
+ return value.length;
+ }
+
+ void write(OutputStream out, int pos) throws IOException
+ {
+ int idx;
+
+ // Output header
+ AsnBuildHeader(out, type, value.length);
+ if (debug > 10)
+ {
+ System.out.println("\tAsnOctets(): value = " + toString()
+ + ", pos = " + pos);
+ }
+
+ // Output data
+ for (idx=0; idx
+ * IPv4: IPADDRESS (or ASN_OCTET_STR, see rfc 4001)
+ * IPv6: ASN_OCTET_STR
+ *
+ * See also
+ * IPV6-TC,
+ * SNMPv2-PDU,
+ * INET-ADDRESS-MIB.
+ *
+ * @return The IP Address representation.
+ * @see #toString
+ * @see #getIpAddress
+ * @see SnmpConstants#ASN_OCTET_STR
+ * @see SnmpConstants#IPADDRESS
+ */
+ /*
+ TODO: use Java's java.net.InetAddress, so it can be used for IPv4, and IPv6.
+ */
+ public String toIpAddress()
+ {
+ /* TODO: Does this work? Yes, but will not compile in jdk 1.2.X, and
+ * in order to load (a part of) the stack in Oracle, I need
+ * 1.2.X
+ */
+ /*
+ String str = "";
+ try
+ {
+ InetAddress iad = InetAddress.getByAddress(value);
+ str = iad.getHostAddress();
+ }
+ catch (java.net.UnknownHostException exc) { }
+ */
+
+ /*
+ */
+ StringBuffer sb = new StringBuffer(39);
+ int length;
+ long val;
+ length = value.length;
+ if (length > 0)
+ {
+ if (length > 4)
+ {
+ // IPv6
+ // Nicked this code from Inet6Address.numericToTextFormat
+ for (int i=0; i
+ * IPv4: IPADDRESS (or ASN_OCTET_STR, see rfc 4001)
+ * IPv6: ASN_OCTET_STR
+ *
+ * See also
+ * IPV6-TC,
+ * SNMPv2-PDU,
+ * INET-ADDRESS-MIB.
+ *
+ * @return The IP Address representation.
+ * @exception RuntimeException Thrown when the Octets does
+ * not represent an InetAddress or when the method internally throws
+ * an java.net.UnknownHostException
+ *
+ * @see #toString
+ * @see #toIpAddress
+ * @see SnmpConstants#ASN_OCTET_STR
+ * @see SnmpConstants#IPADDRESS
+ * @since 4_14
+ */
+ public InetAddress getIpAddress()
+ throws RuntimeException
+ {
+ InetAddress iad = null;
+ try
+ {
+ iad = InetAddress.getByAddress(value);
+ }
+ catch (java.net.UnknownHostException exc)
+ {
+ throw new RuntimeException(exc);
+ }
+ return iad;
+ }
+
+ /**
+ * Returns the positive long for an octet. Only if type is IPADDRESS
+ * can the value be negative anyway.
+ */
+ private long getPositiveValue(int index)
+ {
+ long val = (long) value[index];
+ if (val <0)
+ {
+ val += 256;
+ }
+ return val;
+ }
+
+ /**
+ * Returns this Octet as an hexadecimal String, without any prefix.
+ *
+ * @return The hex representation.
+ * @see #toString
+ */
+ public String toHex()
+ {
+ int length;
+ StringBuffer buffer = new StringBuffer("");
+
+ length = value.length;
+ if (length > 0)
+ {
+ for (int i=0; i
+ * DisplayString
+ * represents textual information taken from the NVT
+ * ASCII character set, as defined in pages 4, 10-11
+ * of RFC 854.
+ * Any object defined using this syntax
+ * may not exceed 255 characters in length.
+ * Basicly it is US-ASCII with some changes.
+ *
+ *
+ * @return The string representation.
+ * @see #toString
+ */
+ public String toDisplayString()
+ {
+ String str = "";
+ int length;
+
+ length = value.length;
+ if (length > 0)
+ {
+ try
+ {
+ str = new String(value, "US-ASCII");
+ }
+ catch (UnsupportedEncodingException exc)
+ {
+ str = new String(value);
+ }
+ str = str.trim();
+ }
+
+ return str;
+ }
+
+ /**
+ * Returns this Octet as an international display string (text
+ * convension).
+ * It calls AsnOctetsPrintableFace.toInternationalDisplayString().
+ *
+ * See
+ * HOST-RESOURCES-MIB
+ *
+ * @see AsnOctetsPrintableFace#toInternationalDisplayString
+ * @since 4_14
+ */
+ public String toInternationalDisplayString()
+ {
+ return toInternationalDisplayString(printableObject);
+ }
+
+
+ /**
+ * As toInternationalDisplayString(), but this methods will use this
+ * specific, one-off AsnOctetsPrintableFace object.
+ *
+ * @see #toInternationalDisplayString
+ * @since 4_14
+ */
+ public String toInternationalDisplayString(AsnOctetsPrintableFace face)
+ {
+ return face.toInternationalDisplayString(value);
+ }
+
+
+ /**
+ * Returns the String representation according to the DateAndTime
+ * convension.
+ * This string it returns is not exactly the same as the
+ * DISPLAY-HINT indicates.
+ * See
+ * SNMPv2-TC
+ *
+ * @since 4_14
+ * @exception RuntimeException Thrown when the number of
+ * Octets does not represent the DateAndTime length.
+ * @see #CALFORMAT
+ */
+ public String toCalendar()
+ throws RuntimeException
+ {
+ Calendar cal = this.getCalendar();
+ Date date = cal.getTime();
+ return CALFORMAT.format(date);
+ }
+
+ /**
+ * Returns the Octets as Calendar according to the DateAndTime text
+ * convension. You can only call this method if
+ * the syntax of this Octet is the DateAndTime text convension.
+ *
+ * @exception RuntimeException Thrown when the number of
+ * Octets does not represent the DateAndTime length.
+ *
+ * @since 4_14
+ * @see #AsnOctets(Calendar)
+ */
+ public Calendar getCalendar()
+ throws RuntimeException
+ {
+ Calendar cal = Calendar.getInstance();
+ if (value.length == 8 || value.length == 11)
+ {
+ int year = (int) ((getPositiveValue(0) * 256) + getPositiveValue(1));
+ // Calendar: 0=January
+ int month = value[2]-1;
+ int day = value[3];
+ int hour = value[4];
+ int min = value[5];
+ int sec = value[6];
+ int msec = value[7] * 100;
+ cal.set(year, month, day, hour, min, sec);
+ cal.set(Calendar.MILLISECOND, msec);
+
+ if (value.length == 11)
+ {
+ char dir = (char) value[8];
+ int hourUTC = value[9];
+ int minUTC = value[10];
+ int secUTC = (hourUTC * 60) * 60;
+
+ int msecGMT = secUTC * 1000;
+ if (dir == '-')
+ {
+ msecGMT = msecGMT * -1;
+ }
+
+ cal.set(Calendar.ZONE_OFFSET, msecGMT);
+ }
+ }
+ else
+ {
+ throw new RuntimeException("AsnOctets is not DateAndTime");
+ }
+ return cal;
+ }
+
+
+/**
+ * Converts this Octet to its corresponding sub-identifiers.
+ * Each octet will be encoded in a separate sub-identifier, by
+ * converting the octet into a positive long.
+ *
+ *
+ * Use this method when building an OID when this Octet specifies a
+ * conceptual row. For example ipNetToMediaEntry, see
+ * IP-MIB
+ * or SnmpCommunityEntry, see
+ * SNMP-COMMUNITY-MIB
+ *
+ *
+ *
+ * The variable length_implied
indicates that this MIB variable
+ * is preceded by the IMPLIED keyword:
+ *
+ *
+ * -
+ * The IMPLIED keyword can only be present for an Octet having
+ * a variable-length syntax (e.g., variable-length strings or object
+ * identifier-valued objects).
+ *
+ * -
+ * The IMPLIED keyword can only be associated with the last
+ * object in the INDEX clause.
+ *
+ * -
+ * The IMPLIED keyword may not be used on a variable-length
+ * string Octet if that string might have a value of zero-length.
+ *
+ *
+ *
+ *
+ * If the length is implied, no extra sub-identifier will be created to
+ * indicate its length.
+ * If the length is not implied, the first
+ * sub-identifier will be the length of the Octet.
+ *
+ *
+ *
+ * If this Octet is of type IPADDRESS, length_implied should be false.
+ *
+ *
+ *
+ * The mapping of the INDEX clause is
+ * explained in SNMPv2-SMI,
+ * section 7.7.
+ *
+ *
+ * @param length_implied Indicates if the length of this octet is
+ * implied.
+ *
+ * @see AsnObjectId#add(long[])
+ */
+public long [] toSubOid(boolean length_implied)
+{
+ long sub_oid[];
+ int index = 0;
+ int length = value.length;
+
+ if (length_implied)
+ {
+ sub_oid = new long[length];
+ }
+ else
+ {
+ sub_oid = new long[length+1];
+ sub_oid[0] = length;
+ index++;
+ }
+
+ for (int i=0; itrue if and only if the argument is not
+ * null
and is an AsnOctets
object that represents
+ * the same sequence of octets as this Octet.
+ *
+ * @param anObject the object to compare this AsnOctets
+ * against.
+ * @return true
if the AsnOctets
are equal;
+ * false
otherwise.
+ */
+public boolean equals(Object anObject)
+{
+ if (this == anObject)
+ {
+ return true;
+ }
+ if (anObject instanceof AsnOctets)
+ {
+ AsnOctets anotherOctet = (AsnOctets)anObject;
+ int n = value.length;
+ if (n == anotherOctet.value.length)
+ {
+ byte v1[] = value;
+ byte v2[] = anotherOctet.value;
+ int i = 0;
+ int j = 0;
+ while (n-- != 0)
+ {
+ if (v1[i++] != v2[j++])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/**
+ * Returns a hash code for this Octet. The hash code for a
+ * AsnOctets
object is computed as
+ *
+ * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
+ *
+ * using int
arithmetic, where s[i]
is the
+ * ith character of the Octet, n
is the length of
+ * the Octet, and ^
indicates exponentiation.
+ * (The hash value of the empty Octet is zero.)
+ *
+ * @return a hash code value for this Octet.
+ */
+public int hashCode()
+{
+ int h = hash;
+ if (h == 0)
+ {
+ int off = 0;
+ byte val[] = value;
+ int len = value.length;
+
+ for (int i=0; iwww.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * This interface contains the isPrintable() method that is used to decided
+ * whether or not an AsnOctets with type ASN_OCTET_STR is printable or not.
+ * This interface has no effect on the way AsnOctets with type IPADDRESS
+ * or OPAQUE are printed.
+ *
+ *
+ * When the type is ASN_OCTET_STR, the method tries to guess whether
+ * or not the string is printable; without the knowledge of the MIB
+ * it cannot distinguish between OctetString and any textual
+ * conventions, like DisplayString, InternationalDisplayString or DateAndTime.
+ *
+ *
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.5 $ $Date: 2006/03/23 14:54:10 $
+ */
+public interface AsnOctetsPrintableFace
+{
+ static final String version_id =
+ "@(#)$Id: AsnOctetsPrintableFace.java,v 3.5 2006/03/23 14:54:10 birgit Exp $ Copyright Westhawk Ltd";
+
+
+/**
+ * Returns whether or not the AsnOctets' byte array represent a printable
+ * string or not.
+ *
+ * @see AsnOctets#toCalendar()
+ * @see AsnOctets#toDisplayString()
+ * @see AsnOctets#toHex()
+ * @see AsnOctets#toString()
+ */
+public boolean isPrintable(byte[] value);
+
+
+
+/**
+ * This method provides the implemantation of the
+ * InternationalDisplayString text-convention. See
+ * HOST-RESOURCES-MIB.
+ *
+ *
+ * "This data type is used to model textual information
+ * in some character set. A network management station
+ * should use a local algorithm to determine which
+ * character set is in use and how it should be
+ * displayed. Note that this character set may be
+ * encoded with more than one octet per symbol, but will
+ * most often be NVT ASCII. When a size clause is
+ * specified for an object of this type, the size refers
+ * to the length in octets, not the number of symbols."
+ *
+ */
+public String toInternationalDisplayString(byte[] value);
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AsnPduSequence.java b/src/main/java/uk/co/westhawk/snmp/stack/AsnPduSequence.java
new file mode 100644
index 0000000..c9f89f0
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AsnPduSequence.java
@@ -0,0 +1,144 @@
+// NAME
+// $RCSfile: AsnPduSequence.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.10 $
+// CREATED
+// $Date: 2006/01/17 17:43:54 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ * original version by hargrave@dellgate.us.dell.com (Jordan Hargrave)
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * The AsnPduSequence class know how a Pdu v1 and v2c is build, it knows its
+ * sequence.
+ *
+ * @author Tim Panton
+ * @version $Revision: 3.10 $ $Date: 2006/01/17 17:43:54 $
+ */
+class AsnPduSequence extends AsnSequence
+{
+ private static final String version_id =
+ "@(#)$Id: AsnPduSequence.java,v 3.10 2006/01/17 17:43:54 birgit Exp $ Copyright Westhawk Ltd";
+
+ boolean snmpv3Discovery = false;
+
+ AsnPduSequence(InputStream in, int len, int pos) throws IOException
+ {
+ super(in,len,pos);
+ }
+
+ int getReqId()
+ {
+ AsnInteger rid = (AsnInteger) getObj(0);
+ return(rid.getValue());
+ }
+
+ int getWhatError()
+ {
+ AsnInteger estat = (AsnInteger) getObj(1);
+ return (estat.getValue());
+ }
+
+ int getWhereError()
+ {
+ AsnInteger estat = (AsnInteger) getObj(2);
+ return (estat.getValue());
+ }
+
+ AsnSequence getVarBind()
+ {
+ return (AsnSequence) getObj(3);
+ }
+
+ /**
+ * recursively look for a pduSequence object
+ * - got one :-)
+ */
+ AsnObject findPdu()
+ {
+ return this;
+ }
+
+ int getValue()
+ {
+ AsnSequence varBind = (AsnSequence) getObj(3);
+ AsnSequence varPair = (AsnSequence) varBind.getObj(0);
+ AsnInteger val = (AsnInteger) varPair.getObj(1);
+ int value = val.getValue();
+
+ return value;
+ }
+
+ boolean hadError()
+ {
+ return (SNMP_ERR_NOERROR != getWhatError());
+ }
+
+ boolean isSnmpv3Discovery()
+ {
+ return snmpv3Discovery;
+ }
+
+ void setSnmpv3Discovery(boolean b)
+ {
+ snmpv3Discovery = b;
+ }
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AsnPrimitive.java b/src/main/java/uk/co/westhawk/snmp/stack/AsnPrimitive.java
new file mode 100644
index 0000000..dac43d7
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AsnPrimitive.java
@@ -0,0 +1,145 @@
+// NAME
+// $RCSfile: AsnPrimitive.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.10 $
+// CREATED
+// $Date: 2006/01/17 17:43:54 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * This class represents the Exception values for SNMP v2c, v3:
+ * SNMP_VAR_NOSUCHOBJECT, SNMP_VAR_NOSUCHINSTANCE, SNMP_VAR_ENDOFMIBVIEW
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.10 $ $Date: 2006/01/17 17:43:54 $
+ * @see #SNMP_VAR_NOSUCHOBJECT
+ * @see #SNMP_VAR_NOSUCHINSTANCE
+ * @see #SNMP_VAR_ENDOFMIBVIEW
+ */
+public class AsnPrimitive extends AsnObject
+{
+ private static final String version_id =
+ "@(#)$Id: AsnPrimitive.java,v 3.10 2006/01/17 17:43:54 birgit Exp $ Copyright Westhawk Ltd";
+
+ private byte type;
+
+ /**
+ * Default Constructor.
+ *
+ * @param t The primitive type
+ * @see #SNMP_VAR_NOSUCHOBJECT
+ * @see #SNMP_VAR_NOSUCHINSTANCE
+ * @see #SNMP_VAR_ENDOFMIBVIEW
+ */
+ public AsnPrimitive(byte t)
+ {
+ type = t;
+ }
+
+ /**
+ * Returns the string representation of the AsnPrimitive.
+ *
+ * @return The string of the AsnPrimitive
+ */
+ public String toString()
+ {
+ String str = "AsnPrimitive ";
+ if (type == SNMP_VAR_NOSUCHOBJECT)
+ {
+ str = "No such object";
+ }
+ else if (type == SNMP_VAR_NOSUCHINSTANCE)
+ {
+ str = "No such instance";
+ }
+ else if (type == SNMP_VAR_ENDOFMIBVIEW)
+ {
+ str = "End of MIB view";
+ }
+ return str;
+ }
+
+ void write(OutputStream out, int pos) throws IOException
+ {
+ AsnBuildHeader(out, type, 0);
+ }
+
+
+ /**
+ * Compares this object to the specified object. The result is
+ * true
if and only if the argument is not
+ * null
and is an AsnPrimitive
object that
+ * contains the same type
as this object.
+ *
+ * @param obj the object to compare with.
+ * @return true
if the objects are the same;
+ * false
otherwise.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof AsnPrimitive)
+ {
+ return type == ((AsnPrimitive)obj).type;
+ }
+ return false;
+ }
+
+
+ /**
+ * Returns a hash code for this AsnPrimitive
.
+ *
+ * @return a hash code value for this object, equal to the
+ * type represented by this
+ * AsnPrimitive
object.
+ */
+ public int hashCode()
+ {
+ return (int) type;
+ }
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AsnSequence.java b/src/main/java/uk/co/westhawk/snmp/stack/AsnSequence.java
new file mode 100644
index 0000000..ee04554
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AsnSequence.java
@@ -0,0 +1,291 @@
+// NAME
+// $RCSfile: AsnSequence.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.15 $
+// CREATED
+// $Date: 2006/11/29 16:35:29 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ * original version by hargrave@dellgate.us.dell.com (Jordan Hargrave)
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.io.*;
+import java.util.*;
+
+
+/**
+ * This class represents the ASN.1 sequence class.
+ * This class contains a Sequence of AsnObjects.
+ *
+ * @author Tim Panton
+ * @version $Revision: 3.15 $ $Date: 2006/11/29 16:35:29 $
+ */
+class AsnSequence extends AsnObject
+{
+ private static final String version_id =
+ "@(#)$Id: AsnSequence.java,v 3.15 2006/11/29 16:35:29 birgit Exp $ Copyright Westhawk Ltd";
+
+ private Vector children;
+
+ /**
+ * Constructors.
+ */
+ AsnSequence()
+ {
+ this(CONS_SEQ);
+ }
+
+ /**
+ * Constructors.
+ */
+ AsnSequence(byte oddtype)
+ {
+ type = oddtype;
+ children = new Vector(1, 1);
+ }
+
+
+ /**
+ * Constructors.
+ * @param pos The position of the first child
+ */
+ AsnSequence(InputStream in, int len, int pos) throws IOException
+ {
+ this();
+ if (debug > 10)
+ {
+ System.out.println("AsnSequence(): Length = " + len
+ + ", Pos = " + pos);
+ }
+ AsnObject a = null;
+ while (true)
+ {
+ a = AsnReadHeader(in, pos);
+ if (a != null)
+ {
+ pos += (a.headerLength + a.contentsLength);
+ add(a);
+ }
+ else
+ {
+ break; // all done
+ }
+ }
+ }
+
+ /**
+ * Returns the string representation of the AsnSequence.
+ *
+ * @return The string of the AsnSequence
+ */
+ public String toString()
+ {
+ return "";
+ }
+
+ /**
+ * Adds a child to the sequence.
+ */
+ AsnObject add(AsnObject child)
+ {
+ if (child.isCorrect == true)
+ {
+ children.addElement(child);
+ }
+ return child;
+ }
+
+ /**
+ * Replaces one child by the other.
+ * This is used by v3 to insert the security / auth fingerprint.
+ */
+ AsnObject replaceChild(AsnObject oldChild, AsnObject newChild)
+ {
+ AsnObject ret = oldChild;
+ int at = children.indexOf(oldChild);
+ if (at > -1)
+ {
+ children.setElementAt(newChild, at);
+ ret = newChild;
+ }
+ return ret;
+ }
+
+ /**
+ * Returns the total size of the children.
+ */
+ int size() throws EncodingException
+ {
+ Enumeration childList = children.elements();
+ int cnt, sz = 0;
+
+ while(childList.hasMoreElements())
+ {
+ // Get size of child
+ cnt = ((AsnObject)childList.nextElement()).size();
+
+ // Add space for type byte & length encoding
+ cnt += (1+getLengthBytes(cnt));
+ sz += cnt;
+ }
+ return sz;
+ }
+
+ void write(OutputStream out)
+ throws IOException, EncodingException
+ {
+ write(out, 0);
+ }
+ void write(OutputStream out, int pos)
+ throws IOException, EncodingException
+ {
+ // Output header
+ int length = size();
+ startPos = pos;
+ AsnBuildHeader(out, type, length);
+ if (debug > 10)
+ {
+ System.out.println("\tAsnSequence.write(): begin, startPos = "
+ + startPos);
+ }
+
+ // Output children
+ pos += headerLength;
+ Enumeration childList = children.elements();
+ while(childList.hasMoreElements())
+ {
+ AsnObject child = ((AsnObject)childList.nextElement());
+ child.write(out, pos);
+ child.startPos = pos;
+ pos += child.headerLength + child.contentsLength;
+ }
+
+ if (debug > 10)
+ {
+ System.out.println("\tAsnSequence.write(): end");
+ }
+ }
+
+
+ /**
+ * recursively look for a pduSequence object.
+ */
+ AsnObject findPdu()
+ {
+ AsnObject res = null;
+
+ Enumeration childList = children.elements();
+ while(childList.hasMoreElements())
+ {
+ AsnObject child = ((AsnObject)childList.nextElement());
+ res = child.findPdu();
+ if (res != null)
+ {
+ break;
+ }
+ }
+
+ if (this.isCorrect == false && res != null)
+ {
+ res.isCorrect = false;
+ }
+ return res;
+ }
+
+ /**
+ * recursively look for a trapPduv1Sequence object.
+ */
+ AsnObject findTrapPduv1()
+ {
+ AsnObject res = null;
+
+ Enumeration childList = children.elements();
+ while(childList.hasMoreElements())
+ {
+ AsnObject child = ((AsnObject)childList.nextElement());
+ res = child.findTrapPduv1();
+ if (res != null)
+ {
+ break;
+ }
+ }
+ if (this.isCorrect == false && res != null)
+ {
+ res.isCorrect = false;
+ }
+ return res;
+ }
+
+ AsnObject getObj(int offset)
+ {
+ AsnObject res = new AsnNull();
+ try
+ {
+ res = (AsnObject) children.elementAt(offset);
+ }
+ catch (ArrayIndexOutOfBoundsException exc)
+ {
+ }
+ return res;
+ }
+
+ int getObjCount()
+ {
+ return children.size();
+ }
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AsnTrapPduv1Sequence.java b/src/main/java/uk/co/westhawk/snmp/stack/AsnTrapPduv1Sequence.java
new file mode 100644
index 0000000..6c1f574
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AsnTrapPduv1Sequence.java
@@ -0,0 +1,191 @@
+// NAME
+// $RCSfile: AsnTrapPduv1Sequence.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.6 $
+// CREATED
+// $Date: 2006/01/17 17:43:54 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2001 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * The AsnTrapPduv1Sequence class knows how a TrapPdu v1 is build, it knows its
+ * sequence.
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.6 $ $Date: 2006/01/17 17:43:54 $
+ */
+class AsnTrapPduv1Sequence extends AsnSequence
+{
+ private static final String version_id =
+ "@(#)$Id: AsnTrapPduv1Sequence.java,v 3.6 2006/01/17 17:43:54 birgit Exp $ Copyright Westhawk Ltd";
+
+AsnTrapPduv1Sequence(InputStream in, int len, int pos) throws IOException
+{
+ super(in,len,pos);
+}
+
+String getEnterprise() throws DecodingException
+{
+ String ent = "";
+ AsnObject obj = getObj(0);
+ if (obj instanceof AsnObjectId)
+ {
+ AsnObjectId rid = (AsnObjectId) obj;
+ ent = rid.getValue();
+ }
+ else
+ {
+ String msg = "TrapPduv1.Enterprise should be AsnObjectId"
+ + " instead of " + obj.getRespTypeString();
+ throw new DecodingException(msg);
+ }
+ return ent;
+}
+
+
+byte [] getIPAddress() throws DecodingException
+{
+ byte [] ip = null;
+ AsnObject obj = getObj(1);
+ if (obj instanceof AsnOctets)
+ {
+ AsnOctets estat = (AsnOctets) obj;
+ ip = estat.getBytes();
+ }
+ else
+ {
+ String msg = "TrapPduv1.IPAddress should be of type AsnOctets"
+ + " instead of " + obj.getRespTypeString();
+ throw new DecodingException(msg);
+ }
+ return ip;
+}
+
+int getGenericTrap() throws DecodingException
+{
+ int genTrap = -1;
+ AsnObject obj = getObj(2);
+ if (obj instanceof AsnInteger)
+ {
+ AsnInteger estat = (AsnInteger) obj;
+ genTrap = estat.getValue();
+ }
+ else
+ {
+ String msg = "TrapPduv1.GenericTrap should be of type AsnInteger"
+ + " instead of " + obj.getRespTypeString();
+ throw new DecodingException(msg);
+ }
+ return genTrap;
+}
+
+
+int getSpecificTrap() throws DecodingException
+{
+ int specTrap = -1;
+ AsnObject obj = getObj(3);
+ if (obj instanceof AsnInteger)
+ {
+ AsnInteger estat = (AsnInteger) obj;
+ specTrap = estat.getValue();
+ }
+ else
+ {
+ String msg = "TrapPduv1.SpecificTrap should be of type AsnInteger"
+ + " instead of " + obj.getRespTypeString();
+ throw new DecodingException(msg);
+ }
+ return specTrap;
+
+}
+
+long getTimeTicks() throws DecodingException
+{
+ long ticks = -1;
+ AsnObject obj = getObj(4);
+ if (obj instanceof AsnUnsInteger)
+ {
+ AsnUnsInteger estat = (AsnUnsInteger) obj;
+ ticks = estat.getValue();
+ }
+ else
+ {
+ String msg = "TrapPduv1.TimeTicks should be of type AsnUnsInteger"
+ + " instead of " + obj.getRespTypeString();
+ throw new DecodingException(msg);
+ }
+ return ticks;
+}
+
+AsnSequence getVarBind() throws DecodingException
+{
+ AsnSequence varb = null;
+ AsnObject obj = getObj(5);
+ if (obj instanceof AsnSequence)
+ {
+ varb = (AsnSequence) obj;
+ }
+ else
+ {
+ String msg = "TrapPduv1.VarBind should be of type AsnSequence"
+ + " instead of " + obj.getRespTypeString();
+ throw new DecodingException(msg);
+ }
+ return varb;
+}
+
+/**
+ * recursively look for a trapPduv1Sequence object
+ * - got one :-)
+ */
+AsnObject findTrapPduv1()
+{
+ return this;
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AsnUnsInteger.java b/src/main/java/uk/co/westhawk/snmp/stack/AsnUnsInteger.java
new file mode 100644
index 0000000..de59ab7
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AsnUnsInteger.java
@@ -0,0 +1,275 @@
+// NAME
+// $RCSfile: AsnUnsInteger.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.16 $
+// CREATED
+// $Date: 2006/01/17 17:43:54 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ * original version by hargrave@dellgate.us.dell.com (Jordan Hargrave)
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.io.*;
+import java.util.*;
+
+
+/**
+ * This class represents ASN.1 32-bit unsigned integer. It is used for
+ * TIMETICKS, COUNTER, GAUGE.
+ *
+ * @see SnmpConstants#TIMETICKS
+ * @see SnmpConstants#COUNTER
+ * @see SnmpConstants#GAUGE
+ *
+ * @author Tim Panton
+ * @version $Revision: 3.16 $ $Date: 2006/01/17 17:43:54 $
+ */
+public class AsnUnsInteger extends AsnObject
+{
+ private static final String version_id =
+ "@(#)$Id: AsnUnsInteger.java,v 3.16 2006/01/17 17:43:54 birgit Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * The internal value of AsnUnsInteger.
+ */
+ protected long value;
+
+ /**
+ * Constructor. The type of the AsnUnsInteger defaults to TIMETICKS.
+ *
+ * @param v The value of the AsnUnsInteger
+ * @see SnmpConstants#TIMETICKS
+ */
+ public AsnUnsInteger(long v)
+ {
+ this(v, TIMETICKS);
+ }
+
+ /**
+ * Constructor to create a specific type of AsnUnsInteger.
+ *
+ * @param v The value of the AsnUnsInteger
+ * @param t The type of the AsnUnsInteger
+ * @see SnmpConstants#TIMETICKS
+ * @see SnmpConstants#COUNTER
+ * @see SnmpConstants#GAUGE
+ */
+ public AsnUnsInteger(long v, byte t)
+ {
+ this.value = v;
+ this.type = t;
+ }
+
+
+ /**
+ * Constructor.
+ *
+ * @param in The input stream from which the value should be read
+ * @param len The length of the AsnUnsInteger
+ */
+ public AsnUnsInteger(InputStream in, int len) throws IOException
+ {
+ byte data[] = new byte[len];
+ if (len != in.read(data,0,len))
+ {
+ throw new IOException("AsnUnsInteger(): Not enough data");
+ }
+ long val = bytesToLong(data);
+ this.value = val;
+ }
+
+ /**
+ * Returns the value representation of the AsnUnsInteger.
+ *
+ * @return The value of the AsnUnsInteger
+ */
+ public long getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Returns the string representation of the AsnUnsInteger.
+ *
+ * @return The string of the AsnUnsInteger
+ */
+ public String toString()
+ {
+ return (String.valueOf(value));
+ }
+
+ /**
+ * Returns the number of bytes the integer occupies.
+ */
+ int size()
+ {
+ int count, empty = 0x00, sign = 0x00;
+
+ if (value < 0)
+ {
+ empty = 0xFF;
+ sign = 0x80;
+ }
+
+ // 32-bit integer.. change to 56 to write 64-bit long
+ // loop through bytes in value while it is 'empty'
+ for(count=24; count>0; count-=8)
+ {
+ if ( ((value >> count) & 0xFF) != empty) break;
+ }
+
+ // Check sign bit.. make sure negative's MSB bit is 1,
+ // positives is 0
+ // (0x00000080 = 0x00 0x80) 0xFFFFFF01 => 0xFF 0x01
+ // (0x0000007F = 0x7F) 0xFFFFFF80 => 0x80
+ if (((value >> count) & 0x80) != sign) count += 8;
+ return (count>>3)+1;
+ }
+
+
+ /**
+ * Output integer.
+ */
+ void write(OutputStream out, int pos) throws IOException
+ {
+ int count, empty = 0x00, sign = 0x00;
+
+ if (value < 0)
+ {
+ empty = 0xFF;
+ sign = 0x80;
+ }
+
+ // Get count
+ for(count=24; count>0; count-=8)
+ {
+ if ( ((value >> count) & 0xFF) != empty) break;
+ }
+ if (((value >> count) & 0x80) != sign) count += 8;
+
+ // Build header and write value
+ AsnBuildHeader(out, type, (count>>3)+1);
+
+ if (debug > 10)
+ {
+ System.out.println("\tAsnUnsInteger(): value = " + value
+ + ", pos = " + pos);
+ }
+
+ for(; count>=0; count-=8)
+ {
+ out.write((byte)((value >> count) & 0xFF));
+ }
+ }
+
+ /**
+ * Changes an array of bytes into a long.
+ * Thanks to Julien Conan (jconan@protego.net) for improving
+ * this method.
+ *
+ * @param data the array of bytes
+ * @return the int representation of the array
+ */
+ protected long bytesToLong(byte[] data) throws IOException
+ {
+ DataInputStream dis = new DataInputStream(
+ new ByteArrayInputStream(data));
+
+ long val = 0;
+ int size = data.length;
+
+ for (int n=0; ntrue if and only if the argument is not
+ * null
and is an AsnUnsInteger
object that
+ * contains the same long
value as this object.
+ *
+ * @param obj the object to compare with.
+ * @return true
if the objects are the same;
+ * false
otherwise.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof AsnUnsInteger)
+ {
+ return value == ((AsnUnsInteger)obj).value;
+ }
+ return false;
+ }
+
+
+ /**
+ * Returns a hash code for this AsnUnsInteger
.
+ *
+ * @return a hash code value for this object, equal to the
+ * hash of the primitive long
value represented
+ * by this AsnUnsInteger
object.
+ */
+ public int hashCode()
+ {
+ // nicked from Long.hashCode
+ return (int)(value ^ (value >>> 32));
+ }
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/AsnUnsInteger64.java b/src/main/java/uk/co/westhawk/snmp/stack/AsnUnsInteger64.java
new file mode 100644
index 0000000..cc010e8
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/AsnUnsInteger64.java
@@ -0,0 +1,257 @@
+// NAME
+// $RCSfile: AsnUnsInteger64.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.16 $
+// CREATED
+// $Date: 2009/03/05 13:11:33 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ * original version by hargrave@dellgate.us.dell.com (Jordan Hargrave)
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.io.*;
+import java.util.*;
+
+
+/**
+ * This class represents ASN.1 64-bit unsigned integer. It is used for
+ * COUNTER64.
+ *
+ * @see SnmpConstants#COUNTER64
+ *
+ * @author Tim Panton
+ * @version $Revision: 3.16 $ $Date: 2009/03/05 13:11:33 $
+ */
+public class AsnUnsInteger64 extends AsnObject
+{
+ private static final String version_id =
+ "@(#)$Id: AsnUnsInteger64.java,v 3.16 2009/03/05 13:11:33 birgita Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * The internal value of AsnUnsInteger64.
+ */
+ // TODO: move to BigInteger, since long is too small
+ protected long value;
+
+ /**
+ * Constructor.
+ *
+ * @param v The value of the AsnUnsInteger64
+ */
+ public AsnUnsInteger64(long v)
+ {
+ this.value = v;
+ this.type = COUNTER64;
+ }
+
+
+ /**
+ * Constructor.
+ *
+ * @param in The input stream from which the value should be read
+ * @param len The length of the AsnUnsInteger64
+ */
+ public AsnUnsInteger64(InputStream in, int len) throws IOException
+ {
+ byte data[] = new byte[len];
+ if (len != in.read(data,0,len))
+ {
+ throw new IOException("AsnUnsInteger64(): Not enough data");
+ }
+ this.value = bytesToLong(data);
+ }
+
+ /**
+ * Returns the value representation of the AsnUnsInteger64.
+ *
+ * @return The value of the AsnUnsInteger64
+ */
+ public long getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Returns the string representation of the AsnUnsInteger64.
+ *
+ * @return The string of the AsnUnsInteger64
+ */
+ public String toString()
+ {
+ return (String.valueOf(value));
+ }
+
+ /**
+ * Returns the number of bytes the integer occupies.
+ */
+ int size()
+ {
+ int count, empty = 0x00, sign = 0x00;
+
+ if (value < 0)
+ {
+ empty = 0xFF;
+ sign = 0x80;
+ }
+
+ // 64-bit integer.. change to 24 to write 32-bit long
+ // loop through bytes in value while it is 'empty'
+ for(count=56; count>0; count-=8)
+ {
+ if ( ((value >> count) & 0xFF) != empty) break;
+ }
+
+ // Check sign bit.. make sure negative's MSB bit is 1,
+ // positives is 0
+ // (0x00000080 = 0x00 0x80) 0xFFFFFF01 => 0xFF 0x01
+ // (0x0000007F = 0x7F) 0xFFFFFF80 => 0x80
+ if (((value >> count) & 0x80) != sign) count += 8;
+
+ return (count>>3)+1;
+ }
+
+
+ /**
+ * Output integer.
+ */
+ void write(OutputStream out, int pos) throws IOException
+ {
+ int count, empty = 0x00, sign = 0x00;
+
+ if (value < 0)
+ {
+ empty = 0xFF;
+ sign = 0x80;
+ }
+
+ // Get count
+ for(count=56; count>0; count-=8)
+ {
+ if ( ((value >> count) & 0xFF) != empty) break;
+ }
+ if (((value >> count) & 0x80) != sign) count += 8;
+
+ // Build header and write value
+ AsnBuildHeader(out, COUNTER64, (count>>3)+1);
+ if (debug > 10)
+ {
+ System.out.println("\tAsnUnsInteger64(): value = " + value
+ + ", pos = " + pos);
+ }
+ for(; count>=0; count-=8)
+ {
+ out.write((byte)((value >> count) & 0xFF));
+ }
+ }
+
+ /**
+ * Changes an array of bytes into a long.
+ * Thanks to Julien Conan (jconan@protego.net) for improving
+ * this method.
+ *
+ * @param data the array of bytes
+ * @return the int representation of the array
+ */
+ protected long bytesToLong(byte[] data) throws IOException
+ {
+ DataInputStream dis = new DataInputStream(
+ new ByteArrayInputStream(data));
+
+ long val = 0;
+ int size = data.length;
+
+ for (int n=0; ntrue if and only if the argument is not
+ * null
and is an AsnUnsInteger64
object that
+ * contains the same long
value as this object.
+ *
+ * @param obj the object to compare with.
+ * @return true
if the objects are the same;
+ * false
otherwise.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof AsnUnsInteger64)
+ {
+ return value == ((AsnUnsInteger64)obj).value;
+ }
+ return false;
+ }
+
+
+ /**
+ * Returns a hash code for this AsnUnsInteger64.
+ *
+ * @return a hash code value for this object, equal to the
+ * hash of the primitive long
value represented
+ * by this AsnUnsInteger64
object.
+ */
+ public int hashCode()
+ {
+ // nicked from Long.hashCode
+ return (int)(value ^ (value >>> 32));
+ }
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/BitsHelper.java b/src/main/java/uk/co/westhawk/snmp/stack/BitsHelper.java
new file mode 100644
index 0000000..f9a264c
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/BitsHelper.java
@@ -0,0 +1,175 @@
+// NAME
+// $RCSfile: BitsHelper.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.1 $
+// CREATED
+// $Date: 2006/03/23 15:09:48 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.io.*;
+
+/**
+ * This class help with the BITS construct. The AsnOctets class is
+ * growing too big, because of all the different representations.
+ *
+ * Note that BITS is different from the ANS.1 BIT STRING. Apparently BIT
+ * STRING was in v1, but was depreceated in favour of BITS.
+ *
+ *
+ * An instance with bits 0, 3 and 10 set will have the value:
+ *
+ * 10010000 00100000
+ * ^ ^ ^
+ * bit 0 3 10
+ *
+ * so will consist of the two bytes (octets) 0x90 & 0x20.
+ *
+ *
+ * See also
+ * section 7.1.4. of
+ * SNMPv2-SMI
+ * and section 8. (3) of
+ * SNMPv2-TM.
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.1 $ $Date: 2006/03/23 15:09:48 $
+ * @since 5_0
+ */
+public class BitsHelper
+{
+ private static final String version_id =
+ "@(#)$Id: BitsHelper.java,v 3.1 2006/03/23 15:09:48 birgit Exp $ Copyright Westhawk Ltd";
+
+
+/**
+ * Sets or unsets the flag (bit) on the specified index. The bit
+ * will be set to zero if toset is false, set to one if toset is
+ * true.
+ *
+ * Note, as a side effect the size of the asn octet might grow.
+ *
+ * @param oct The AsnOctets that represents the BITS
+ * @param index The index (0 - X)
+ * @param toset Whether to set (true) or unset (false) the bit
+ */
+public static void setFlagged(AsnOctets oct, int index, boolean toset)
+throws IllegalArgumentException
+{
+ if (index < 0)
+ {
+ throw new IllegalArgumentException("Illegal value index (" + index
+ + "). Shoud be greater than 0.");
+ }
+ else
+ {
+ byte mask;
+ int byteNo = index / 8;
+ int bitNo = index % 8;
+
+ // See if we've got enough bytes in our array.
+ // Reallocate if necessary.
+ int len = oct.value.length;
+ if (byteNo >= len)
+ {
+ int newLen = byteNo+1;
+ byte[] newValue = new byte[newLen];
+ System.arraycopy(oct.value, 0, newValue, 0, len);
+ oct.value = newValue;
+ }
+
+ if (toset == true)
+ {
+ mask = (byte) (0x80 >>> bitNo);
+ oct.value[byteNo] = (byte) (oct.value[byteNo] | mask);
+ }
+ else
+ {
+ mask = (byte) (0x7F >>> bitNo);
+ oct.value[byteNo] = (byte) (oct.value[byteNo] & mask);
+ }
+ }
+}
+
+
+/**
+ * Returns if the flag (bit) on the specified index is set. The bit
+ * will be set to zero if toset is false, set to one if toset is
+ * true.
+ *
+ * @param oct The AsnOctets that represents the BITS
+ * @param index The index (0 - X)
+ * @return Whether the bit is set (true) or unset (false)
+ */
+public static boolean isFlagged(AsnOctets oct, int index)
+throws IllegalArgumentException
+{
+ boolean isFlagged = false;
+ if (index < 0)
+ {
+ throw new IllegalArgumentException("Illegal value index (" + index
+ + "). Shoud be greater than 0.");
+ }
+ else
+ {
+ byte mask;
+ int byteNo = index / 8;
+ int bitNo = index % 8;
+
+ int len = oct.value.length;
+ if (byteNo < len)
+ {
+ // Shift the bit we're interested in to the far left.
+ // If the bit is one, the byte will be negative.
+ byte res = (byte) (oct.value[byteNo] << bitNo);
+ isFlagged = (res < 0);
+ }
+ }
+ return isFlagged;
+}
+
+
+}
+
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/DecodingException.java b/src/main/java/uk/co/westhawk/snmp/stack/DecodingException.java
new file mode 100644
index 0000000..dd22717
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/DecodingException.java
@@ -0,0 +1,84 @@
+// NAME
+// $RCSfile: DecodingException.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.5 $
+// CREATED
+// $Date: 2006/01/17 17:43:54 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * Thrown to indicate that the response PDU cannot be decoded.
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.5 $ $Date: 2006/01/17 17:43:54 $
+ */
+public class DecodingException extends PduException
+{
+ private static final String version_id =
+ "@(#)$Id: DecodingException.java,v 3.5 2006/01/17 17:43:54 birgit Exp $ Copyright Westhawk Ltd";
+
+/**
+ * Constructs a DecodingException with no specified detail message.
+ *
+ */
+public DecodingException()
+{
+ super();
+}
+
+/**
+ * Constructs a DecodingException with the specified detail
+ * message.
+ *
+ * @param str The detail message.
+ */
+public DecodingException(String str)
+{
+ super(str);
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/DefaultAsnOctetsPrintable.java b/src/main/java/uk/co/westhawk/snmp/stack/DefaultAsnOctetsPrintable.java
new file mode 100644
index 0000000..dd7cae3
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/DefaultAsnOctetsPrintable.java
@@ -0,0 +1,140 @@
+// NAME
+// $RCSfile: DefaultAsnOctetsPrintable.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.3 $
+// CREATED
+// $Date: 2006/01/17 17:43:54 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * Default implementation of AsnOctetsPrintableFace.
+ * This class has no effect on the way AsnOctets with type IPADDRESS
+ * or OPAQUE are printed.
+ *
+ *
+ * When the type is ASN_OCTET_STR, the method tries to guess whether
+ * or not the string is printable; without the knowledge of the MIB
+ * it cannot distinguish between OctetString and any textual
+ * conventions, like DisplayString, InternationalDisplayString or DateAndTime.
+ *
+ *
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.3 $ $Date: 2006/01/17 17:43:54 $
+ */
+public class DefaultAsnOctetsPrintable implements AsnOctetsPrintableFace
+{
+ static final String version_id =
+ "@(#)$Id: DefaultAsnOctetsPrintable.java,v 3.3 2006/01/17 17:43:54 birgit Exp $ Copyright Westhawk Ltd";
+
+public DefaultAsnOctetsPrintable()
+{
+}
+
+/**
+ * Returns whether or not the AsnOctets' byte array represent a printable
+ * string or not.
+ *
+ *
+ * This method can only make a rough guess. There is no way it always
+ * gets it right.
+ * It is much better to embed MIB knowledge in your implementation, and
+ * use toCalendar() or toDisplayString(), than calling toString().
+ *
+ *
+ * @see AsnOctets#toCalendar()
+ * @see AsnOctets#toDisplayString()
+ * @see AsnOctets#toHex()
+ * @see AsnOctets#toString()
+ */
+public boolean isPrintable(byte[] value)
+{
+ int length = value.length;
+ int b = ' '; // the first printable char in the ASCII table
+ int e = '~'; // the last printable char in the ASCII table
+
+ /*
+ * About the test for 'value[i] == 0':
+ * (Quote from one of our customers:)
+ * I've seen cases where there are embedded nulls in a sysdescr
+ * - not always at the end either - and we need to get complete
+ * data back from the device even in this situation.
+ */
+
+ boolean isPrintable = true;
+ int i=0;
+ while (i= b && value[i] <= e)
+ ||
+ Character.isWhitespace((char)value[i])
+ ||
+ value[i] == 0);
+ i++;
+ }
+
+ return isPrintable;
+}
+
+
+/**
+ * Returns the String according to the platform's default character set.
+ *
+ * @see AsnOctetsPrintableFace#toInternationalDisplayString(byte[] value)
+ */
+public String toInternationalDisplayString(byte[] value)
+{
+ String str = "";
+ if (value.length > 0)
+ {
+ // this will use the platform's default charset.
+ str = new String(value).trim();
+ }
+ return str;
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/DefaultTrapContext.java b/src/main/java/uk/co/westhawk/snmp/stack/DefaultTrapContext.java
new file mode 100644
index 0000000..58c52bb
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/DefaultTrapContext.java
@@ -0,0 +1,186 @@
+// NAME
+// $RCSfile: DefaultTrapContext.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.12 $
+// CREATED
+// $Date: 2009/03/05 13:12:50 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2001 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.io.*;
+import java.util.*;
+
+import uk.co.westhawk.snmp.event.*;
+import uk.co.westhawk.snmp.net.*;
+import uk.co.westhawk.snmp.util.*;
+
+
+/**
+ * The DefaultTrapContext class will enable this stack to receive traps.
+ * Only one (1) instance of the DefaultTrapContext can exist. The
+ * context will only start receiving (or listen for) traps when there is
+ * at least one listener registered. Two kind of listeners can be added;
+ * the normal and unhandled trap listeners.
+ * The normal trap listeners are added via the
+ * addTrapListener()
method,
+ * the unhandled trap listeners are added via the
+ * addUnhandledTrapListener()
.
+ *
+ *
+ * Use one of the getInstance()
methods to get the instance and add a trap
+ * listener. This class will fire undecoded trap events, i.e. the raw
+ * data is sent and no attempt is made to decode the data into a pdu.
+ *
+ *
+ *
+ * The SnmpContext classes provide functionality for decoded trap
+ * events. These classes will register themselves to the
+ * DefaultTrapContext object and only pass the event on if it matches
+ * their configuration.
+ *
+ *
+ *
+ *
+ * Note that because only one instance of this class
+ * can exist, the first call of getInstance()
will define
+ * the settings
+ * (i.e. port number and socket type) for the lifetime of the stack. All
+ * the subsequent calls of getInstance()
will return the existing
+ * instance, irrespective of the arguments.
+ *
+ *
+ *
+ * On UNIX and Linux operating systems the default port where trap are
+ * sent (i.e. 162) can only be opened as root.
+ *
+ *
+ *
+ * Note, this class is now deprecated. We are (very) slowly trying to
+ * move to a more general way of receiving packets and adding agent
+ * functionality. ListeningContext and ListeningContextPool allow the
+ * stack to listen to more than one port.
+ *
+ *
+ * @deprecated As of 4_14, replaced by {@link ListeningContext} and
+ * {@link ListeningContextPool}
+ *
+ * @see AbstractSnmpContext#addTrapListener
+ * @see ListeningContext
+ * @see ListeningContextPool
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.12 $ $Date: 2009/03/05 13:12:50 $
+ */
+public class DefaultTrapContext extends ListeningContext
+{
+ private static final String version_id =
+ "@(#)$Id: DefaultTrapContext.java,v 3.12 2009/03/05 13:12:50 birgita Exp $ Copyright Westhawk Ltd";
+
+ private static DefaultTrapContext current = null;
+
+/**
+ * Constructor.
+ * The Standard socket type will be used.
+ *
+ * @param port The local port where traps are received
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ */
+protected DefaultTrapContext(int port) throws IOException
+{
+ this(port, SnmpContextBasisFace.STANDARD_SOCKET);
+}
+
+/**
+ * Constructor.
+ *
+ * The typeSocket will indicate which type of socket to use. This way
+ * different handlers can be provided.
+ * It should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param port The local port where traps are received
+ * @param typeSocketA The type of socket to use.
+ *
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ */
+protected DefaultTrapContext(int port, String typeSocketA)
+throws IOException
+{
+ super(port, typeSocketA);
+}
+
+
+/**
+ * Returns the instance of DefaultTrapContext. It will create the
+ * instance if it didn't exists.
+ * See the note above.
+ */
+public static synchronized DefaultTrapContext getInstance(int port)
+throws IOException
+{
+ if (current == null)
+ {
+ current = new DefaultTrapContext(port);
+ }
+ return current;
+}
+
+/**
+ * Returns the instance of DefaultTrapContext. It will create the
+ * instance if it didn't exists.
+ * See the note above.
+ */
+public static synchronized DefaultTrapContext getInstance(int port, String typeSocketA)
+throws IOException
+{
+ if (current == null)
+ {
+ current = new DefaultTrapContext(port, typeSocketA);
+ }
+ return current;
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/DefaultUsmAgent.java b/src/main/java/uk/co/westhawk/snmp/stack/DefaultUsmAgent.java
new file mode 100644
index 0000000..316d706
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/DefaultUsmAgent.java
@@ -0,0 +1,298 @@
+// NAME
+// $RCSfile: DefaultUsmAgent.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.10 $
+// CREATED
+// $Date: 2009/03/05 15:51:42 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2001 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.beans.UsmDiscoveryBean;
+
+/**
+ * This implementation of UsmAgent tries to discover the parameters by
+ * doing the default USM discovery process on localhost.
+ *
+ *
+ * Note that it is not guaranteed that the agent will allow discovery
+ * by itself. Also, if the SNMP agent reboots while the stack is
+ * running, it will not pick up the new boots and time.
+ *
+ *
+ *
+ * Users are advised and encouraged to provide a better, more accurate
+ * implementation of UsmAgent.
+ *
+ *
+ *
+ * See SNMP-USER-BASED-SM-MIB.
+ *
+ * @see SnmpContextv3
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.10 $ $Date: 2009/03/05 15:51:42 $
+ */
+public class DefaultUsmAgent implements UsmAgent
+{
+ static final String version_id =
+ "@(#)$Id: DefaultUsmAgent.java,v 3.10 2009/03/05 15:51:42 birgita Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * The default name of the local host, localhost.
+ */
+ public final static String LOCAL_HOST = "localhost";
+
+ /**
+ * The default port number of the local host, 161.
+ */
+ public final static int LOCAL_PORT = 161;
+
+ private SnmpContextv3Basis context;
+ private String hostname;
+ private String hostaddress;
+ private int port;
+
+public DefaultUsmAgent()
+{
+ try
+ {
+ setAgentName(LOCAL_HOST);
+ }
+ catch (java.net.UnknownHostException exc)
+ {
+ hostname = LOCAL_HOST;
+ hostaddress = "127.0.0.1";
+ }
+ setAgentPort(LOCAL_PORT);
+}
+
+/**
+ * Returns the authoritative SNMP Engine ID. If the discovery failed,
+ * null will be returned.
+ *
+ * @return The Engine ID
+ */
+public String getSnmpEngineId()
+{
+ TimeWindow tWindow = TimeWindow.getCurrent();
+ String engineId = tWindow.getSnmpEngineId(hostaddress, port);
+ return engineId;
+}
+
+/**
+ * Returns the authoritative Engine Boots. If the discovery failed,
+ * 1 will be returned.
+ *
+ * @return The Engine Boots
+ */
+public int getSnmpEngineBoots()
+{
+ int boots = 1;
+ TimeWindowNode node = null;
+ TimeWindow tWindow = TimeWindow.getCurrent();
+ String engineId = tWindow.getSnmpEngineId(hostaddress, port);
+ if (engineId != null)
+ {
+ node = tWindow.getTimeLine(engineId);
+ }
+ if (node != null)
+ {
+ boots = node.getSnmpEngineBoots();
+ }
+ return boots;
+}
+
+/**
+ * Returns the authoritative Engine Time. If the discovery failed,
+ * 1 will be returned.
+ *
+ * @return The Engine Time
+ */
+public int getSnmpEngineTime()
+{
+ int time = 1;
+ TimeWindowNode node = null;
+ TimeWindow tWindow = TimeWindow.getCurrent();
+ String engineId = tWindow.getSnmpEngineId(hostaddress, port);
+ if (engineId != null)
+ {
+ node = tWindow.getTimeLine(engineId);
+ }
+ if (node != null)
+ {
+ time = node.getSnmpEngineTime();
+ }
+ return time;
+}
+
+/**
+ * Sets the SNMP context. It will do a discovery if needed.
+ */
+public void setSnmpContext(SnmpContextv3Basis c)
+{
+ context = c;
+ try
+ {
+ discoverIfNeeded();
+ }
+ catch (PduException exc)
+ {
+ if (AsnObject.debug > 4)
+ {
+ System.out.println(getClass().getName() + ".setSnmpContext(): "
+ + exc.getMessage());
+ }
+ }
+ catch (java.io.IOException exc)
+ {
+ if (AsnObject.debug > 4)
+ {
+ System.out.println(getClass().getName() + ".setSnmpContext(): "
+ + exc.getMessage());
+ }
+ }
+}
+
+/**
+ * Sets my own hostname, i.e. the name of the agent or authoritative
+ * engine. By default localhost is used.
+ * Sets the hostaddress as well, using java.net.InetAddress.
+ *
+ * @see #LOCAL_HOST
+ * @exception java.net.UnknownHostException Thrown when java.net.InetAddress cannot
+ * resolve the name
+ */
+public void setAgentName(String host)
+throws java.net.UnknownHostException
+{
+ hostname = host;
+ java.net.InetAddress ipAddr = java.net.InetAddress.getByName(hostname);
+ hostaddress = ipAddr.getHostAddress();
+}
+
+/**
+ * Sets my own port number, i.e. the port number of the agent
+ * or authoritative engine. By default 161 is used.
+ *
+ * @see #LOCAL_PORT
+ */
+public void setAgentPort(int p)
+{
+ port = p;
+}
+
+/**
+ * This discovers the USM timeliness of hostname and port as set by
+ * setAgentName() and setAgentPort(), but with all the other details
+ * taken from the SNMPv3 context.
+ *
+ * @see #setAgentName
+ * @see #setAgentPort
+ */
+void discoverIfNeeded()
+throws java.io.IOException, PduException
+{
+ UsmDiscoveryBean discBean = null;
+ boolean isNeeded = false;
+
+ TimeWindow tWindow = TimeWindow.getCurrent();
+ String engineId = tWindow.getSnmpEngineId(hostaddress, port);
+ if (engineId == null)
+ {
+ isNeeded = true;
+ discBean = new UsmDiscoveryBean(hostname,
+ port, context.getBindAddress(), context.getTypeSocket());
+ }
+
+ if (context.isUseAuthentication())
+ {
+ if (isNeeded)
+ {
+ discBean.setAuthenticationDetails(context.getUserName(),
+ context.getUserAuthenticationPassword(),
+ context.getAuthenticationProtocol());
+ }
+ else if (tWindow.isTimeLineKnown(engineId) == false)
+ {
+ isNeeded = true;
+ discBean = new UsmDiscoveryBean(
+ hostname, port, context.getBindAddress(),
+ context.getTypeSocket());
+ discBean.setAuthenticationDetails(context.getUserName(),
+ context.getUserAuthenticationPassword(),
+ context.getAuthenticationProtocol());
+ }
+
+ if (isNeeded && context.isUsePrivacy())
+ {
+ discBean.setPrivacyDetails(context.getUserPrivacyPassword(),
+ context.getPrivacyProtocol());
+ }
+ }
+
+ if (isNeeded)
+ {
+ discBean.startDiscovery();
+ discBean.freeResources();
+ }
+}
+
+/**
+ * @since 4_14
+ */
+public long getUsmStatsUnknownEngineIDs()
+{
+ return 0;
+}
+
+/**
+ * @since 4_14
+ */
+public long getUsmStatsNotInTimeWindows()
+{
+ return 0;
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/EncodingException.java b/src/main/java/uk/co/westhawk/snmp/stack/EncodingException.java
new file mode 100644
index 0000000..5956be2
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/EncodingException.java
@@ -0,0 +1,83 @@
+// NAME
+// $RCSfile: EncodingException.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.5 $
+// CREATED
+// $Date: 2006/01/17 17:43:54 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * Thrown to indicate that the PDU cannot be build or encoded.
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.5 $ $Date: 2006/01/17 17:43:54 $
+ */
+public class EncodingException extends PduException
+{
+ private static final String version_id =
+ "@(#)$Id: EncodingException.java,v 3.5 2006/01/17 17:43:54 birgit Exp $ Copyright Westhawk Ltd";
+
+/**
+ * Constructs an EncodingException with no specified detail message.
+ */
+public EncodingException()
+{
+ super();
+}
+
+/**
+ * Constructs an EncodingException with the specified detail
+ * message.
+ *
+ * @param str The detail message.
+ */
+public EncodingException(String str)
+{
+ super(str);
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/GetBulkPdu.java b/src/main/java/uk/co/westhawk/snmp/stack/GetBulkPdu.java
new file mode 100644
index 0000000..a6ed843
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/GetBulkPdu.java
@@ -0,0 +1,195 @@
+// NAME
+// $RCSfile: GetBulkPdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.17 $
+// CREATED
+// $Date: 2006/02/09 14:30:19 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+/**
+ * This class represents the SNMP GetBulk Pdu. This request has been
+ * added in SNMPv2c, hence is not supported by SNMPv1 agents.
+ *
+ *
+ * The request is processed on the agent side in the following way:
+ *
+ * // getNext (once) on the non_repeaters
+ * for (n=0; n<N; n++)
+ * {
+ * getNext(var[n]);
+ * }
+ * // getNext (max_repetitions times) on the repeaters
+ * for (m=1; m<M; m++)
+ * {
+ * for (r=1; r<R; r++)
+ * {
+ * getNext(var[N+r]);
+ * }
+ * }
+ *
+ *
+ *
+ * Where:
+ *
+ * L
is the number of vars in the request
+ * N = Max(Min(non_repeaters, L), 0)
+ * M = Max(max_repetitions, 0)
+ * R = L-N
+ *
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.17 $ $Date: 2006/02/09 14:30:19 $
+ */
+public class GetBulkPdu extends Pdu
+{
+ private static final String version_id =
+ "@(#)$Id: GetBulkPdu.java,v 3.17 2006/02/09 14:30:19 birgit Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * The value of the non_repeaters.
+ */
+ protected int non_repeaters = 0;
+ /**
+ * The value of the max_repetitions.
+ */
+ protected int max_repetitions = 0;
+
+/**
+ * Constructor.
+ * The GetBulkRequest has been added in SNMPv2. Its purpose is to
+ * retrieve a large amount of information with one request.
+ *
+ * @param con The context (v2c or v3) of the Pdu
+ */
+public GetBulkPdu(SnmpContextBasisFace con)
+{
+ super(con);
+ setMsgType(AsnObject.GETBULK_REQ_MSG);
+}
+
+/**
+ * Sets the non_repeaters. The non_repeaters specifies the number of
+ * variables in the varbind list for which a single lexicographic
+ * successor is to be returned.
+ * If they are not set, the value will be 0 (zero).
+ */
+public void setNonRepeaters(int no)
+{
+ // same field as error status in any other PDU.
+ non_repeaters = no;
+}
+
+/**
+ * Returns the non_repeaters.
+ */
+public int getNonRepeaters()
+{
+ return non_repeaters;
+}
+
+/**
+ * Sets the max_repetitions. The max_repetitions specifies the number of
+ * lexicographic successors to be returned for the remaining variables
+ * in the varbind list.
+ * If they are not set, the value will be 0 (zero).
+ */
+public void setMaxRepetitions(int no)
+{
+ // same field as error index in any other PDU.
+ max_repetitions = no;
+}
+
+/**
+ * Old method to set the max_repetitions. Was a spelling mistake,
+ * it is still in here for backwards compatibility.
+ *
+ * @deprecated Use {@link #setMaxRepetitions(int no)}.
+ * @see #setMaxRepetitions
+ */
+public void setMaxRepititions(int no)
+{
+ setMaxRepetitions(no);
+}
+
+/**
+ * Returns the max_repetitions.
+ */
+public int getMaxRepetitions()
+{
+ return max_repetitions;
+}
+
+/**
+ * Sends the Pdu.
+ *
+ *
+ * The GetBulk request has the same format as any other request, except
+ * that the error_status field is replaced by non_repeaters and the
+ * error_index field is replaces by max_repetitions.
+ *
+ * @see Pdu#send(int, int)
+ */
+public boolean send() throws java.io.IOException, PduException
+{
+ return send(non_repeaters, max_repetitions);
+}
+
+/**
+ * Returns a string representation of the object.
+ * @return The string
+ */
+public String toString()
+{
+ StringBuffer buffer = new StringBuffer(super.toString());
+ int l = buffer.length();
+ buffer.setLength(l-1);
+
+ buffer.append(", non_rep=").append(getNonRepeaters());
+ buffer.append(", max_rep=").append(getMaxRepetitions());
+ buffer.append("]");
+ return buffer.toString();
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/GetNextPdu.java b/src/main/java/uk/co/westhawk/snmp/stack/GetNextPdu.java
new file mode 100644
index 0000000..dafcae1
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/GetNextPdu.java
@@ -0,0 +1,89 @@
+// NAME
+// $RCSfile: GetNextPdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.8 $
+// CREATED
+// $Date: 2006/01/17 17:43:54 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * This class represents the SNMP GetNext Pdu.
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.8 $ $Date: 2006/01/17 17:43:54 $
+ * @see uk.co.westhawk.snmp.pdu.OneGetNextPdu
+ * @see uk.co.westhawk.snmp.pdu.GetNextPdu_vec
+ */
+public class GetNextPdu extends Pdu
+{
+ private static final String version_id =
+ "@(#)$Id: GetNextPdu.java,v 3.8 2006/01/17 17:43:54 birgit Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * Constructor.
+ *
+ * @param con The context of the Pdu
+ */
+ public GetNextPdu(SnmpContextBasisFace con)
+ {
+ super(con);
+ setMsgType(AsnObject.GETNEXT_REQ_MSG);
+ }
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/GetPdu.java b/src/main/java/uk/co/westhawk/snmp/stack/GetPdu.java
new file mode 100644
index 0000000..c913203
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/GetPdu.java
@@ -0,0 +1,77 @@
+// NAME
+// $RCSfile: GetPdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.3 $
+// CREATED
+// $Date: 2006/01/17 17:59:34 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * This class represents the (public) SNMP Get Pdu.
+ *
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.3 $ $Date: 2006/01/17 17:59:34 $
+ * @see uk.co.westhawk.snmp.pdu.OneGetPdu
+ * @see uk.co.westhawk.snmp.pdu.GetPdu_vec
+ */
+public class GetPdu extends Pdu
+{
+ private static final String version_id =
+ "@(#)$Id: GetPdu.java,v 3.3 2006/01/17 17:59:34 birgit Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * Constructor.
+ *
+ * @param con The context of the Pdu
+ */
+ public GetPdu(SnmpContextBasisFace con)
+ {
+ super(con);
+ setMsgType(AsnObject.GET_REQ_MSG);
+ }
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/InformPdu.java b/src/main/java/uk/co/westhawk/snmp/stack/InformPdu.java
new file mode 100644
index 0000000..6a51876
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/InformPdu.java
@@ -0,0 +1,97 @@
+// NAME
+// $RCSfile: InformPdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.5 $
+// CREATED
+// $Date: 2006/11/29 16:23:33 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2002 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * This class represents the SNMP Inform Request Pdu. This request has
+ * been added in SNMPv2c, hence is not supported by SNMPv1 agents.
+ *
+ *
+ * Inform Requests
+ * are sent between managers. It is an acknowlegded trap since
+ * the receiving end should send a Response Pdu as reply.
+ * The varbind list has the same elements as the TrapPduv2.
+ * See SNMPv2-PDU
+ *
+ *
+ *
+ * Note this PDU should be sent to port 162 (the default trap port) by
+ * default. You will have to create a SnmpContext with the
+ * ListeningContextFace.DEFAULT_TRAP_PORT as parameter!
+ *
+ *
+ *
+ * For SNMPv3: The sender of an inform PDU acts as the authoritative engine.
+ *
+ *
+ * @see TrapPduv2
+ * @see ListeningContextFace#DEFAULT_TRAP_PORT
+ * @since 4_12
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.5 $ $Date: 2006/11/29 16:23:33 $
+ */
+public class InformPdu extends Pdu
+{
+ private static final String version_id =
+ "@(#)$Id: InformPdu.java,v 3.5 2006/11/29 16:23:33 birgit Exp $ Copyright Westhawk Ltd";
+
+/**
+ * Constructor.
+ *
+ * @param con The context (v2c or v3) of the Pdu
+ */
+public InformPdu(SnmpContextBasisFace con)
+{
+ super(con);
+ setMsgType(AsnObject.INFORM_REQ_MSG);
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/ListeningContext.java b/src/main/java/uk/co/westhawk/snmp/stack/ListeningContext.java
new file mode 100644
index 0000000..a810919
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/ListeningContext.java
@@ -0,0 +1,568 @@
+// NAME
+// $RCSfile: ListeningContext.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.12 $
+// CREATED
+// $Date: 2009/03/05 13:24:00 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.io.*;
+import java.util.*;
+
+import uk.co.westhawk.snmp.event.*;
+import uk.co.westhawk.snmp.net.*;
+import uk.co.westhawk.snmp.util.*;
+
+
+/**
+ * The ListeningContext class will enable this stack to receive packets.
+ * This class replaces the deprecated DefaultTrapContext class.
+ * The context will only start receiving (or listen for) packets when there is
+ * at least one listener registered.
+ *
+ *
+ * Two kind of listeners can be added;
+ * the normal and unhandled PDU listeners.
+ * The normal PDU listeners are added via the
+ * addRawPduListener()
method,
+ * the unhandled PDU listeners are added via the
+ * addUnhandledRawPduListener()
.
+ * Both these listeners provide undecoded events.
+ *
+ *
+ *
+ * The SnmpContext classes provide functionality for decoded PDU and
+ * trap events. These classes will register themselves via the
+ * addRawPduListener()
to the ListeningContext object and
+ * only pass the (decoded) event on if it matches their configuration.
+ *
+ *
+ *
+ * On UNIX and Linux operating systems the default port where PDUs and
+ * traps are sent (i.e. 161 and 162) can only be opened
+ * as root.
+ *
+ *
+ *
+ * Only one process can listen on a certain port. To prevent more than
+ * one ListeningContext listening on the same port, use the
+ * ListeningContextPool class.
+ *
+ *
+ * @see ListeningContextPool
+ * @see AbstractSnmpContext#addTrapListener
+ * @see AbstractSnmpContext#addRequestPduListener
+ *
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.12 $ $Date: 2009/03/05 13:24:00 $
+ */
+public class ListeningContext implements ListeningContextFace, Runnable
+{
+ private static final String version_id =
+ "@(#)$Id: ListeningContext.java,v 3.12 2009/03/05 13:24:00 birgita Exp $ Copyright Westhawk Ltd";
+
+ private Object soc_lock = new Object();
+ // thanks to Nick Sheen nsheen@tippingpoint.com for pointing out that "" is interned by the VM
+ private static int counter;
+ private ContextSocketFace soc;
+ private Thread me;
+ private String basename;
+ private volatile boolean stopRequested;
+ // thanks to Nick Sheen nsheen@tippingpoint.com for pointing out that volatile is needed here
+
+ protected int maxRecvSize;
+ protected String typeSocket;
+ protected int hostPort;
+ protected String bindAddr;
+
+ transient private RawPduReceivedSupport pduSupport, unhandledSupport;
+
+/**
+ * Constructor, using the Standard socket type.
+ *
+ * @param port The local port where packets are received
+ *
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ */
+public ListeningContext(int port)
+{
+ this(port, null, SnmpContextBasisFace.STANDARD_SOCKET);
+}
+
+/**
+ * Constructor, using the Standard socket type.
+ *
+ * If bindAddress is null, it will accept connections on
+ * any/all local addresses. If you want to listen to
+ *
+ * -
+ * IPv4 only interfaces, use address "0.0.0.0"
+ *
+ * -
+ * IPv6 only interfaces, use address "::"
+ *
+ *
+ *
+ * @param port The local port where packets are received
+ * @param bindAddress The local address the server will bind to
+ *
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ */
+public ListeningContext(int port, String bindAddress)
+{
+ this(port, bindAddress, SnmpContextBasisFace.STANDARD_SOCKET);
+}
+
+/**
+ * Constructor.
+ *
+ * If bindAddress is null, it will accept connections on
+ * any/all local addresses. If you want to listen to
+ *
+ * -
+ * IPv4 only interfaces, use address "0.0.0.0"
+ *
+ * -
+ * IPv6 only interfaces, use address "::"
+ *
+ *
+ *
+ *
+ * The typeSocketA will indicate which type of socket to use. This way
+ * different handlers can be provided.
+ * This parameter should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ *
+ * Note, the TCP_SOCKET does not provide functionality to send a
+ * response back. Listening on such a socket is only useful when
+ * listening for traps.
+ *
+ *
+ * @param port The local port where packets are received
+ * @param bindAddress The local address the server will bind to
+ * @param typeSocketA The type of socket to use.
+ *
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ */
+public ListeningContext(int port, String bindAddress, String typeSocketA)
+{
+ hostPort = port;
+ bindAddr = bindAddress;
+ typeSocket = typeSocketA;
+
+ basename = ""+hostPort+"_"+bindAddr;
+
+ pduSupport = new RawPduReceivedSupport(this);
+ unhandledSupport = new RawPduReceivedSupport(this);
+ maxRecvSize = SnmpContextBasisFace.MSS;
+}
+
+
+public int getPort()
+{
+ return hostPort;
+}
+
+public String getBindAddress()
+{
+ return bindAddr;
+}
+
+public String getTypeSocket()
+{
+ return typeSocket;
+}
+
+
+public int getMaxRecvSize()
+{
+ return maxRecvSize;
+}
+public void setMaxRecvSize(int no)
+{
+ maxRecvSize = no;
+}
+
+/**
+ * This method will stop the thread listening for packets.
+ * All transmitters, PDUs in flight and traplisteners will be removed
+ * when run() finishes.
+ *
+ *
+ * It closes the socket.
+ * The thread will actually stop/finish when the run() finishes. Since
+ * the socket is closed, the run() will fall through almost instantly.
+ *
+ *
+ *
+ * Note that by calling this method the whole stack will stop listening
+ * for packets on this particular port! The listeners added via the
+ * SnmpContext classes are affected as well.
+ *
+ *
+ *
+ * When you add a new listener, the context will start listening again.
+ *
+ *
+ *
+ * Note: The thread(s) will not die immediately; this will take about
+ * half a minute.
+ *
+ */
+public void destroy()
+{
+ synchronized(soc_lock)
+ {
+ stopRequested = true;
+ if (soc != null)
+ {
+ if (AsnObject.debug > 12)
+ {
+ System.out.println(getClass().getName() + ".destroy(): Closing socket ");
+ }
+ soc.close();
+ }
+ }
+}
+
+/**
+ * We wait for any incoming PDUs and fire a rawpdu received (undecoded) event
+ * if we do.
+
+ *
+ * The undecoded events are fired to all normal listeners (added via
+ * addRawPduListener()), until one of them consumes it.
+ * The SnmpContext classes will consume the event if it matches their
+ * configuration.
+ *
+ *
+ *
+ * If none of them consume the event, the undecoded events are fired to
+ * all unhandled PDU listeners (added via addUnhandledRawPduListener()),
+ * until one of them consumes it.
+ *
+ *
+ * @see RawPduReceivedSupport#fireRawPduReceived
+ * @see #addRawPduListener(RawPduListener)
+ * @see #addUnhandledRawPduListener(RawPduListener)
+ */
+public void run()
+{
+ // while It is visible
+ while (!stopRequested)
+ {
+ // block for incoming packets
+ me.yield();
+ try
+ {
+ if (stopRequested)
+ {
+ break;
+ }
+
+ StreamPortItem item = soc.receive(maxRecvSize);
+ ByteArrayInputStream in = item.getStream();
+
+ String hostAddress = item.getHostAddress();
+ int port = item.getHostPort();
+
+ // read the bytes of the input stream into bu
+ int nb = in.available();
+ byte [] bu = new byte[nb];
+ in.read(bu);
+ in.close();
+
+ if (AsnObject.debug > 10)
+ {
+ SnmpUtilities.dumpBytes(getClass().getName()
+ + ".run(): Received from "
+ + hostAddress
+ + ", from port " + port
+ + ": ", bu);
+ }
+ KickProcessIncomingMessage thread =
+ new KickProcessIncomingMessage(hostAddress, port, bu);
+ thread.start();
+ }
+ catch (IOException exc)
+ {
+ if (exc instanceof InterruptedIOException)
+ {
+ if (AsnObject.debug > 15)
+ {
+ System.out.println(getClass().getName() + ".run(): Idle recv " + exc.getMessage());
+ }
+ }
+ else
+ {
+ if (AsnObject.debug > 0)
+ {
+ System.out.println(getClass().getName() + ".run(): IOException: " + exc.getMessage());
+ }
+ }
+ }
+ catch (Exception exc)
+ {
+ if (AsnObject.debug > 0)
+ {
+ System.out.println(getClass().getName() + ".run(): Exception: " + exc.getMessage());
+ exc.printStackTrace();
+ }
+ }
+ catch (Error err)
+ {
+ if (AsnObject.debug > 0)
+ {
+ System.out.println(getClass().getName() + ".run(): Error: " + err.getMessage());
+ err.printStackTrace();
+ }
+ }
+ }
+
+ me = null;
+ soc = null;
+ pduSupport.empty();
+ unhandledSupport.empty();
+}
+
+public void addRawPduListener(RawPduListener listener)
+throws IOException
+{
+ synchronized(soc_lock)
+ {
+ pduSupport.addRawPduListener(listener);
+ startListening();
+ }
+}
+
+public void removeRawPduListener(RawPduListener listener)
+{
+ synchronized(soc_lock)
+ {
+ pduSupport.removeRawPduListener(listener);
+ destroyIfNoListeners();
+ }
+}
+
+public void addUnhandledRawPduListener(RawPduListener listener)
+throws IOException
+{
+ synchronized(soc_lock)
+ {
+ unhandledSupport.addRawPduListener(listener);
+ startListening();
+ }
+}
+
+public void removeUnhandledRawPduListener(RawPduListener listener)
+{
+ synchronized(soc_lock)
+ {
+ unhandledSupport.removeRawPduListener(listener);
+ destroyIfNoListeners();
+ }
+}
+
+/**
+ * Creates the socket and starts listening for PDUs if we didn't do so
+ * already.
+ * This method is called in addRawPduListener() and
+ * addUnhandledRawPduListener().
+ *
+ * @exception IOException Thrown when the socket cannot be created.
+ * @see #addRawPduListener
+ * @see #addUnhandledRawPduListener
+ */
+private void startListening()
+throws IOException
+{
+ if (soc == null)
+ {
+ // create tempSoc first, so that when 'create' fails, soc
+ // will remain null.
+ ContextSocketFace tempSoc = AbstractSnmpContext.getSocket(typeSocket);
+ if (tempSoc != null)
+ {
+ tempSoc.create(hostPort, bindAddr);
+ soc = tempSoc;
+
+ if (AsnObject.debug > 12)
+ {
+ System.out.println(getClass().getName() + ".startListening()"
+ + ": soc.getLocalSocketAddress() = " + soc.getLocalSocketAddress());
+ System.out.println(getClass().getName() + ".startListening()"
+ + ": soc.getRemoteSocketAddress() = " + soc.getRemoteSocketAddress());
+ }
+ }
+ }
+ if (me == null)
+ {
+ stopRequested = false;
+ me = new Thread(this, basename+"_Listen");
+ me.setPriority(me.NORM_PRIORITY);
+ me.start();
+ }
+}
+
+
+/**
+ * Returns the hash key. This key is built out of all properties. It
+ * serves as key for the pool of contexts.
+ *
+ * @return The hash key
+ */
+public String getHashKey()
+{
+ String str = hostPort
+ + "_" + bindAddr
+ + "_" + typeSocket;
+ return str;
+}
+
+/**
+ * Returns a string representation of the object.
+ * @return The string
+ */
+public String toString()
+{
+ StringBuffer buffer = new StringBuffer("ListeningContext[");
+ buffer.append("port=").append(hostPort);
+ buffer.append(", bindAddress=").append(bindAddr);
+ buffer.append(", socketType=").append(typeSocket);
+ buffer.append(", #rawPduListeners=").append(pduSupport.getListenerCount());
+ buffer.append(", #rawPduUnhandledListeners=").append(unhandledSupport.getListenerCount());
+ buffer.append("]");
+ return buffer.toString();
+}
+
+/**
+ * Processes an incoming packet.
+ *
+ * @see #run
+ */
+protected void processIncomingMessage(String hostAddress,
+ int port, byte [] bu) throws DecodingException, IOException
+{
+ AsnDecoderBase rpdu = new AsnDecoderBase();
+ ByteArrayInputStream in = new ByteArrayInputStream(bu);
+ AsnSequence asnTopSeq = rpdu.getAsnSequence(in);
+ int version = rpdu.getSNMPVersion(asnTopSeq);
+
+ boolean isConsumed = pduSupport.fireRawPduReceived(version, hostAddress, port, bu);
+ if (isConsumed == false)
+ {
+ unhandledSupport.fireRawPduReceived(version, hostAddress, port, bu);
+ }
+}
+
+
+/**
+ * Only destroy this object when there are no more listeners.
+ *
+ * Thanks to Jeremy Stone (Jeremy.Stone@cyclone-technology.com).
+ * @since 6.1
+ */
+private void destroyIfNoListeners()
+{
+ if (pduSupport.getListenerCount() == 0
+ && unhandledSupport.getListenerCount() == 0)
+ {
+ destroy();
+ }
+}
+
+class KickProcessIncomingMessage extends Thread
+{
+ /**
+ * This class makes sure that dealing with an incoming packet is
+ * done at a separate thread so the ListeningContext can go back
+ * listening immediately.
+ * This will at some point be replaced by a Thread pool of
+ * some kind.
+ */
+ private String hostAddress;
+ private int port;
+ private byte [] bu;
+
+ KickProcessIncomingMessage(String newHostAddress, int newPort,
+ byte [] newBu)
+ {
+ hostAddress = newHostAddress;
+ port = newPort;
+ bu = newBu;
+ this.setPriority(Thread.MIN_PRIORITY);
+ this.setName(newHostAddress + "_" + newPort
+ + "_KickProcessIncomingMessage_" + counter);
+ counter++;
+ }
+
+ public void run()
+ {
+ try
+ {
+ processIncomingMessage(hostAddress, port, bu);
+ }
+ catch (IOException exc)
+ {
+ if (AsnObject.debug > 0)
+ {
+ System.out.println(getClass().getName() + ".run(): IOException: " + exc.getMessage());
+ }
+ }
+ catch (DecodingException exc)
+ {
+ if (AsnObject.debug > 1)
+ {
+ System.out.println(getClass().getName() + ".run(): DecodingException: " + exc.getMessage());
+ }
+ }
+ }
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/ListeningContextFace.java b/src/main/java/uk/co/westhawk/snmp/stack/ListeningContextFace.java
new file mode 100644
index 0000000..147c2fc
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/ListeningContextFace.java
@@ -0,0 +1,184 @@
+// NAME
+// $RCSfile: ListeningContextFace.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.6 $
+// CREATED
+// $Date: 2006/11/29 16:12:50 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.event.*;
+
+/**
+ * This interface contains the SNMP listening context methods.
+ *
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.6 $ $Date: 2006/11/29 16:12:50 $
+ */
+public interface ListeningContextFace
+{
+ static final String version_id =
+ "@(#)$Id: ListeningContextFace.java,v 3.6 2006/11/29 16:12:50 birgit Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * The default port number where we listen for traps (162).
+ */
+ public final static int DEFAULT_TRAP_PORT = 162;
+
+
+/**
+ * Returns the port number.
+ *
+ * @return The port no
+ */
+public int getPort();
+
+/**
+ * Returns the local address the server will bind to
+ * When the address is null, the socket accepts connections on
+ * any/all local addresses.
+ *
+ * @return The bind address
+ */
+public String getBindAddress();
+
+/**
+ * Returns the type of socket.
+ *
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ * @return The type of socket
+ */
+public String getTypeSocket();
+
+/**
+ * Returns the maximum number of bytes this context will read from the
+ * socket. By default this will be set to MSS
(i.e. 1300).
+ *
+ * @see SnmpContextBasisFace#MSS
+ * @see #setMaxRecvSize(int)
+ * @see AbstractSnmpContext#setMaxRecvSize(int)
+ * @return The number
+ */
+public int getMaxRecvSize();
+
+/**
+ * Sets the maximum number of bytes this context will read from the
+ * socket. By default this will be set to MSS
(i.e. 1300).
+ *
+ * @see SnmpContextBasisFace#MSS
+ * @see AbstractSnmpContext#getMaxRecvSize()
+ * @param no The new size
+ */
+public void setMaxRecvSize(int no);
+
+/**
+ * Removes the resouces held by this context.
+ * This method will stop the thread listening for packets.
+ */
+public void destroy();
+
+/**
+ * Adds the specified PDU listener to receive the undecoded PDUs.
+ * When a PDU is received the PDU received event is fired to all
+ * listeners, until one of them consumes it.
+ *
+ *
+ * All the SnmpContext objects use this method to listen for PDUs. When
+ * a SnmpContext object decodes the PDU succesfully, it will consume
+ * it.
+ *
+ *
+ *
+ * Only when a listener is added will this context create a listening socket.
+ *
+ *
+ * @param l The listener object
+ * @exception java.io.IOException Thrown when creating a listening
+ * socket fails
+ *
+ * @see RawPduReceivedSupport#fireRawPduReceived
+ * @see AbstractSnmpContext#addTrapListener
+ * @see AbstractSnmpContext#addRequestPduListener
+ * @see #addUnhandledRawPduListener(RawPduListener)
+ */
+public void addRawPduListener(RawPduListener l)
+throws java.io.IOException;
+
+/**
+ * Removes the specified PDU listener. When there are no more listeners,
+ * calls destroy().
+ *
+ * @param l The listener object
+ */
+public void removeRawPduListener(RawPduListener l);
+
+/**
+ * Adds the specified PDU listener to receive the undecoded PDUs when
+ * it was not handled (i.e. not consumed) by any of the PDU listeners in
+ * addRawPduListener().
+ *
+ *
+ * Only when a listener is added will this context create a listening socket.
+ *
+ *
+ * @param listener The listener object
+ * @exception java.io.IOException Thrown when creating a listening
+ * socket fails
+ *
+ * @see #addRawPduListener(RawPduListener)
+ */
+public void addUnhandledRawPduListener(RawPduListener listener)
+throws java.io.IOException;
+
+/**
+ * Removes the specified unhandled PDU listener. When there are no more
+ * listeners, calls destroy().
+ *
+ * @param listener The listener object
+ */
+public void removeUnhandledRawPduListener(RawPduListener listener);
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/ListeningContextPool.java b/src/main/java/uk/co/westhawk/snmp/stack/ListeningContextPool.java
new file mode 100644
index 0000000..6044fc3
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/ListeningContextPool.java
@@ -0,0 +1,505 @@
+// NAME
+// $RCSfile: ListeningContextPool.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.7 $
+// CREATED
+// $Date: 2009/03/05 13:27:41 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.util.*;
+import uk.co.westhawk.snmp.event.*;
+
+/**
+ * This class contains the pool of listening contexts. The usage of this
+ * class will prevent more than one ListeningContext trying to listen to
+ * the same port.
+ *
+ * @see ListeningContext
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.7 $ $Date: 2009/03/05 13:27:41 $
+ */
+public class ListeningContextPool implements ListeningContextFace
+{
+ private static final String version_id =
+ "@(#)$Id: ListeningContextPool.java,v 3.7 2009/03/05 13:27:41 birgita Exp $ Copyright Westhawk Ltd";
+
+ protected static Hashtable contextPool;
+
+ protected ListeningContext context = null;
+ protected String socketType;
+ protected String bindAddr;
+ protected int hostPort;
+
+/**
+ * Constructor, using the Standard socket type.
+ *
+ * @param port The local port where packets are received
+ *
+ * @see #ListeningContextPool(int, String)
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ */
+public ListeningContextPool(int port)
+{
+ this(port, null, SnmpContextBasisFace.STANDARD_SOCKET);
+}
+
+
+/**
+ * Constructor, using the Standard socket type.
+ *
+ * If bindAddress is null, it will accept connections on
+ * any/all local addresses. If you want to listen to
+ *
+ * -
+ * IPv4 only interfaces, use address "0.0.0.0"
+ *
+ * -
+ * IPv6 only interfaces, use address "::"
+ *
+ *
+ *
+ * @param port The local port where packets are received
+ * @param bindAddress The local address the server will bind to
+ *
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ */
+public ListeningContextPool(int port, String bindAddress)
+{
+ this(port, bindAddress, SnmpContextBasisFace.STANDARD_SOCKET);
+}
+
+
+/**
+ * Constructor.
+ *
+ * If bindAddress is null, it will accept connections on
+ * any/all local addresses. If you want to listen to
+ *
+ * -
+ * IPv4 only interfaces, use address "0.0.0.0"
+ *
+ * -
+ * IPv6 only interfaces, use address "::"
+ *
+ *
+ *
+ * The typeSocket will indicate which type of socket to use. This way
+ * different handlers can be provided.
+ *
+ *
+ * Note, the TCP_SOCKET does not provide functionality to send a
+ * response back. Listening on such a socket is only useful when
+ * listening for traps.
+ *
+ *
+ * @param port The local port where packets are received
+ * @param bindAddress The local address the server will bind to
+ * @param typeSocket The type of socket to use.
+ *
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ */
+public ListeningContextPool(int port, String bindAddress, String typeSocket)
+{
+ initPools();
+ hostPort = port;
+ bindAddr = bindAddress;
+ socketType = typeSocket;
+
+ context = getMatchingContext();
+}
+
+private static synchronized void initPools()
+{
+ if (contextPool == null)
+ {
+ contextPool = new Hashtable(5);
+ }
+}
+
+public int getPort()
+{
+ return hostPort;
+}
+
+public String getBindAddress()
+{
+ return bindAddr;
+}
+
+public String getTypeSocket()
+{
+ return socketType;
+}
+
+public int getMaxRecvSize()
+{
+ int res = SnmpContextBasisFace.MSS;
+ if (context != null)
+ {
+ res = context.getMaxRecvSize();
+ }
+ return res;
+}
+
+/**
+ * Sets the maximum number of bytes this context will read from the
+ * socket. By default this will be set to MSS
(i.e. 1300).
+ * Only the current context will be affected, not to all the
+ * contexts in the pool.
+ *
+ * @param no The new size
+ *
+ * @see SnmpContextBasisFace#MSS
+ * @see AbstractSnmpContext#getMaxRecvSize()
+ */
+public void setMaxRecvSize(int no)
+{
+ if (context == null)
+ {
+ context = getMatchingContext();
+ }
+ context.setMaxRecvSize(no);
+}
+
+/**
+ * Destroys the current context.
+ *
+ *
+ * Note that by calling this method the whole stack will stop listening
+ * for packets on the port this context was listening on! The listeners
+ * added via the SnmpContext classes are affected as well.
+ *
+ *
+ * @see #destroyPool()
+ * @see ListeningContextPool#destroy()
+ */
+public void destroy()
+{
+ synchronized(contextPool)
+ {
+ if (context != null)
+ {
+ String hashKey = context.getHashKey();
+
+ int count = 0;
+ Item item = (Item) contextPool.get(hashKey);
+
+ if (item != null)
+ {
+ count = item.getCounter();
+ count--;
+ item.setCounter(count);
+ }
+
+ if (count <=0)
+ {
+ contextPool.remove(hashKey);
+ context.destroy();
+ }
+ context = null;
+ }
+ }
+}
+
+/**
+ * Destroys all the contexts in the pool and empties the pool.
+ *
+ *
+ * Note that by calling this method the whole stack will stop listening
+ * for any packets! The listeners added via the
+ * SnmpContext classes are affected as well.
+ *
+ *
+ * @see #destroy()
+ */
+public void destroyPool()
+{
+ Hashtable copyOfPool = null;
+
+ synchronized(contextPool)
+ {
+ synchronized(contextPool)
+ {
+ copyOfPool = (Hashtable) contextPool.clone();
+ }
+ contextPool.clear();
+ }
+ context = null;
+
+ Enumeration keys = copyOfPool.keys();
+ while (keys.hasMoreElements())
+ {
+ String key = (String) keys.nextElement();
+ Item item = (Item) copyOfPool.get(key);
+ if (item != null)
+ {
+ ListeningContext cntxt = (ListeningContext) item.getContext();
+ cntxt.destroy();
+ }
+ }
+ copyOfPool.clear();
+}
+
+/**
+ * Returns a context from the pool.
+ * This methods checks for an existing context that matches all our
+ * properties. If such a context does not exist, a new one is created and
+ * added to the pool.
+ *
+ * @return A context from the pool
+ * @see #getHashKey
+ */
+protected ListeningContext getMatchingContext()
+{
+ Item item = null;
+ ListeningContext newContext = null;
+ String hashKey = getHashKey();
+
+ destroy();
+ synchronized(contextPool)
+ {
+ int count=0;
+ if (contextPool.containsKey(hashKey))
+ {
+ item = (Item) contextPool.get(hashKey);
+ newContext = item.getContext();
+ count = item.getCounter();
+ }
+ else
+ {
+ newContext = new ListeningContext(hostPort, bindAddr, socketType);
+ item = new Item(newContext);
+ contextPool.put(hashKey, item);
+ }
+ count++;
+ item.setCounter(count);
+ }
+ return newContext;
+}
+
+/**
+ * Dumps the pool of contexts. This is for debug purposes.
+ * @param title The title of the dump
+ */
+public void dumpContexts(String title)
+{
+ Hashtable copyOfPool = null;
+ synchronized(contextPool)
+ {
+ copyOfPool = (Hashtable) contextPool.clone();
+ }
+
+ System.out.println(title + " " + copyOfPool.size());
+ Enumeration keys = copyOfPool.keys();
+ int i=0;
+ while (keys.hasMoreElements())
+ {
+ String key = (String) keys.nextElement();
+ Item item = (Item) copyOfPool.get(key);
+
+ if (item != null)
+ {
+ int count = item.getCounter();
+ ListeningContext cntxt = item.getContext();
+
+ System.out.println("\tcontext: " + key + ", count: " + count
+ + ", index: " + i + ", " + cntxt.toString());
+ if (cntxt == context)
+ {
+ System.out.println("\t\tcurrent context");
+ }
+ i++;
+ }
+ }
+}
+
+/**
+ * Returns the hash key. This key is built out of all properties. It
+ * serves as key for the pool of contexts.
+ *
+ * @return The hash key
+ */
+public String getHashKey()
+{
+ String str = hostPort
+ + "_" + bindAddr
+ + "_" + socketType;
+ return str;
+}
+
+public void addRawPduListener(RawPduListener l)
+throws java.io.IOException
+{
+ if (context != null)
+ {
+ context.addRawPduListener(l);
+ }
+}
+public void removeRawPduListener(RawPduListener l)
+{
+ if (context != null)
+ {
+ context.removeRawPduListener(l);
+ }
+}
+
+
+/**
+ * Removes the specified PDU listener from all the contexts in the pool.
+ *
+ * @see ListeningContext#removeRawPduListener
+ */
+public void removeRawPduListenerFromPool(RawPduListener l)
+{
+ Hashtable copyOfPool = null;
+
+ if (contextPool != null)
+ {
+ synchronized(contextPool)
+ {
+ copyOfPool = (Hashtable) contextPool.clone();
+ }
+
+ Enumeration keys = copyOfPool.keys();
+ while (keys.hasMoreElements())
+ {
+ String key = (String) keys.nextElement();
+ Item item = (Item) copyOfPool.get(key);
+
+ if (item != null)
+ {
+ ListeningContext cntxt = item.getContext();
+ cntxt.removeRawPduListener(l);
+ }
+ }
+ }
+}
+
+
+public void addUnhandledRawPduListener(RawPduListener l)
+throws java.io.IOException
+{
+ if (context != null)
+ {
+ context.addUnhandledRawPduListener(l);
+ }
+}
+public void removeUnhandledRawPduListener(RawPduListener l)
+{
+ if (context != null)
+ {
+ context.removeUnhandledRawPduListener(l);
+ }
+}
+
+
+/**
+ * Returns a string representation of the object.
+ * @return The string
+ */
+public String toString()
+{
+ String res = "";
+ if (context != null)
+ {
+ res = context.toString();
+ }
+ return res;
+}
+
+
+class Item
+{
+ private ListeningContext context = null;
+ private int counter = 0;
+
+ /**
+ * Constructor.
+ *
+ * @param con The context
+ */
+ Item(ListeningContext con)
+ {
+ context = con;
+ counter = 0;
+ }
+
+
+ ListeningContext getContext()
+ {
+ return context;
+ }
+
+ int getCounter()
+ {
+ return counter;
+ }
+
+ void setCounter(int i)
+ {
+ counter = i;
+ }
+
+ /**
+ * Returns a string representation of the object.
+ * @return The string
+ */
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer("Item[");
+ buffer.append("context=").append(context.toString());
+ buffer.append(", counter=").append(counter);
+ buffer.append("]");
+ return buffer.toString();
+ }
+} // end Item
+
+
+} // end ListeningContextPool
+
+
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/MultiResponsePdu.java b/src/main/java/uk/co/westhawk/snmp/stack/MultiResponsePdu.java
new file mode 100644
index 0000000..0e32db2
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/MultiResponsePdu.java
@@ -0,0 +1,347 @@
+// NAME
+// $RCSfile: MultiResponsePdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.3 $
+// CREATED
+// $Date: 2007/10/17 10:44:09 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.util.*;
+
+
+/**
+ * This class can receive multiple responses.
+ * Typical usage includes sending a single PDU to a multicast /
+ * broadcast address so that multiple responses can be received from
+ * different sources.
+ *
+ *
+ * This class sets a single long timeout for the retry, so it sends the
+ * request only once.
+ * Opposite to its parent class, this class does not ignore the duplicate
+ * responses, and it will timeout by nature.
+ *
+ *
+ * Note:
+ *
+ * - Please realise that you might choke the stack and your network, when
+ * you use this class, even on a small subnet
+ * - This PDU will eat up transmit and receive resources, until it times out
+ * - This PDU cannot be used to receive traps
+ * - Authentication (and privacy) is by definition a unicast activity.
+ * You can find unauthenticated SNMPv3 engines, by broadcasting this PDU
+ * with a SnmpContextv3(Pool) with no authentication.
+ * Then you need to continue an authentication/privacy context and a (normal)
+ * PDU.
+ * In other words, finding SNMPv3 engines that only support
+ * authentication and/or privacy cannot be done via broadcasting.
+ *
+ *
+ *
+ *
+ *
+ * Thanks to Josh Bers <jbers@bbn.com>
+ *
+ *
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.3 $ $Date: 2007/10/17 10:44:09 $
+ */
+public class MultiResponsePdu extends Pdu
+{
+ private static final String version_id =
+ "@(#)$Id: MultiResponsePdu.java,v 3.3 2007/10/17 10:44:09 birgita Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * Hashtable to hold responses received from agents.
+ */
+ private Hashtable responses = new Hashtable();
+
+ /**
+ * IP address of current response
+ */
+ private String thisIP = null;
+
+
+ /**
+ * By default create a MultiResponsePdu that will wait for 3
+ * seconds for responses to come in from multiple sources. If you
+ * want to wait longer set the RetryInterval to a longer first
+ * timeout. To make the request more reliable, add more timeouts.
+ *
+ * @param con The context
+ */
+ public MultiResponsePdu(SnmpContextBasisFace con)
+ {
+ super(con);
+ setRetryIntervals(new int[]{3000});
+ }
+
+
+ /**
+ * Gets the IP address of the host of the most recent response received.
+ *
+ * @return The sourceAgent value
+ */
+ public String getSourceAgent()
+ {
+ return thisIP;
+ }
+
+
+ /**
+ * Gets the number of responses so far received
+ * to this request.
+ *
+ * @return The number of responses
+ */
+ public int getNumResponses()
+ {
+ return responses.size();
+ }
+
+
+ /**
+ * Prints out the list of received responses and their source IP
+ * addressses. Results will be ommitted if not yet received.
+ *
+ * @return String representation of this PDU and all its received
+ * responses
+ */
+ public String toString()
+ {
+ // loop over vector of responses and use Pdu.toString(boolean)
+ // to print out the received varbinds.
+ StringBuffer buffer = new StringBuffer();
+ if (!answered)
+ {
+ buffer.append(toString(false));
+ }
+ else
+ {
+ Enumeration ipaddrs = responses.keys();
+ String ipaddr = (String) ipaddrs.nextElement();
+ // set respVarbinds to each response in turn calling toString(true)
+ respVarbinds = (Vector) responses.get(ipaddr);
+
+ buffer.append(toString(true));
+ buffer.append(" rhost=").append(ipaddr);
+ int i=2;
+ while (ipaddrs.hasMoreElements())
+ {
+ ipaddr = (String) ipaddrs.nextElement();
+ respVarbinds = (Vector) responses.get(ipaddr);
+
+ buffer.append("\n\t");
+ buffer.append(printVars("respVarbinds"+i, respVarbinds));
+ buffer.append(" rhost=").append(ipaddr);
+ i++;
+ }
+ }
+ return buffer.toString();
+ }
+
+
+ /**
+ * Lets the observers know which source we received a response from.
+ */
+ protected void tell_them()
+ {
+ String sender = thisIP;
+ // if timed out then we are done waiting for replies.
+ if (isTimedOut())
+ {
+ sender = null;
+ }
+ else
+ {
+ // record this response for posterity
+ responses.put(sender, respVarbinds);
+ }
+
+ // tell all interested parties
+ notifyObservers(sender);
+
+ // free up space for next result
+ respVarbinds = null;
+ thisIP = null;
+ }
+
+
+
+
+ /**
+ * Fills in the received response.
+ *
+ * Now override fillin to fetch source ip address and not set answered
+ * you can get multiple responses by setting the timeout period long
+ * do this in the constructor.
+ *
+ * @param seq Description of Parameter
+ * @see Pdu#getResponseVarbinds()
+ */
+ void fillin(AsnPduSequence seq)
+ {
+ // this will be set to true (eventually) in handleNoAnswer()
+ if (answered)
+ {
+ if (AsnObject.debug > 6)
+ {
+ System.out.println(getClass().getName() + ".fillin(): "
+ + "Got a second answer to request " + getReqId());
+ }
+ return;
+ }
+
+ // check that we haven't already heard from this host before:
+ thisIP = getContext().getReceivedFromHostAddress();
+ if (responses.containsKey(thisIP))
+ {
+ if (AsnObject.debug > 6)
+ {
+ System.out.println(getClass().getName() + ".fillin(): "
+ + "Got a second answer from " + thisIP
+ + " to request " + getReqId());
+ }
+ return;
+ }
+
+ // fillin(null) can be called in case of a Decoding exception
+ if (seq != null)
+ {
+ if (seq.isCorrect == true)
+ {
+ int n = -1;
+ try
+ {
+ // Fill in the request id
+ this.req_id = seq.getReqId();
+ setErrorStatus(seq.getWhatError());
+ setErrorIndex(seq.getWhereError());
+
+ // The varbinds from the response/report are set in a
+ // new Vector.
+ AsnSequence varBind = seq.getVarBind();
+ int size = varBind.getObjCount();
+ respVarbinds = new Vector(size, 1);
+ for (n=0; nwww.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * This class contains the SNMP v1 context that is needed by a Pdu to
+ * send a SNMP v1 request in environments where thread creation is
+ * unwanted.
+ *
+ *
+ * This extends SnmpContext so that it does not create any
+ * threads to send PDUs. It must be used with the
+ * PDU class PassiveTrapPduv1. The original purpose of the
+ * Passive classes is to allow the stack to be used in environments where
+ * thread creation is unwanted, eg database JVMs such as Oracle JServer.
+ * See SNMPv2-PDU.
+ *
+ *
+ *
+ * See
+ * notes
+ * on how to send traps in an Oracle JServer environment.
+ *
+ *
+ * @see uk.co.westhawk.snmp.pdu.PassiveTrapPduv1
+ * @since 4_12
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.10 $ $Date: 2009/03/05 13:12:50 $
+ */
+public class PassiveSnmpContext extends SnmpContext
+{
+ private static final String version_id =
+ "@(#)$Id: PassiveSnmpContext.java,v 3.10 2009/03/05 13:12:50 birgita Exp $ Copyright Westhawk Ltd";
+
+
+/**
+ * Constructor.
+ *
+ * @param host The host to which the Pdu will be sent
+ * @param port The port where the SNMP server will be
+ * @see SnmpContext#SnmpContext(String, int)
+ */
+public PassiveSnmpContext(String host, int port)
+throws java.io.IOException
+{
+ super(host, port);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocketA should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the Pdu will be sent
+ * @param port The port where the SNMP server will be
+ * @param typeSocketA The type of socket to use.
+ *
+ * @see SnmpContext#SnmpContext(String, int, String)
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ */
+public PassiveSnmpContext(String host, int port, String typeSocketA)
+throws java.io.IOException
+{
+ super(host, port, typeSocketA);
+}
+
+
+/**
+ * Constructor.
+ *
+ * If bindAddress is null, then the system will pick up a valid local
+ * address to bind the socket.
+ *
+ * The typeSocketA will indicate which type of socket to use. This way
+ * different handlers can be provided.
+ * It should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the Pdu will be sent
+ * @param port The port where the SNMP server will be
+ * @param bindAddress The local address the server will bind to
+ * @param typeSocketA The type of socket to use.
+ *
+ * @exception java.io.IOException Thrown when the socket cannot be
+ * created.
+ *
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ * @since 4_14
+ */
+protected PassiveSnmpContext(String host, int port, String bindAddress, String typeSocketA)
+throws java.io.IOException
+{
+ super(host, port, bindAddress, typeSocketA);
+}
+
+
+/**
+ * Overrides the AbstractSnmpContext.activate() to do nothing.
+ * This prevents the creation of threads in the base class.
+ *
+ * @see AbstractSnmpContext#activate()
+ */
+protected void activate()
+{
+ // do nothing
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/PassiveSnmpContextv2c.java b/src/main/java/uk/co/westhawk/snmp/stack/PassiveSnmpContextv2c.java
new file mode 100644
index 0000000..72415fa
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/PassiveSnmpContextv2c.java
@@ -0,0 +1,158 @@
+// NAME
+// $RCSfile: PassiveSnmpContextv2c.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.10 $
+// CREATED
+// $Date: 2009/03/05 13:12:50 $
+// COPYRIGHT
+// ERG Group Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2001 by ERG Group Ltd
+ * www.erggroup.com
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Mike Waters
+ */
+
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * This class contains the SNMP v2c context that is needed by every Pdu to
+ * send a SNMP v2c request in environments where thread creation is
+ * unwanted.
+ *
+ *
+ * This extends SnmpContextv2c so that it does not create any
+ * threads to send PDUs. It must be used with the
+ * PDU class PassiveTrapPduv2. The original purpose of the
+ * Passive classes is to allow the stack to be used in environments where
+ * thread creation is unwanted, eg database JVMs such as Oracle JServer.
+ * See SNMPv2-PDU.
+ *
+ *
+ *
+ * See
+ * notes
+ * on how to send traps in an Oracle JServer environment.
+ *
+ *
+ * @see uk.co.westhawk.snmp.pdu.PassiveTrapPduv2
+ * @since 4_12
+ *
+ * @author Mike Waters, ERG Group
+ * @version $Revision: 3.10 $ $Date: 2009/03/05 13:12:50 $
+ */
+public class PassiveSnmpContextv2c extends SnmpContextv2c
+{
+ private static final String version_id =
+ "@(#)$Id: PassiveSnmpContextv2c.java,v 3.10 2009/03/05 13:12:50 birgita Exp $ Copyright Westhawk Ltd";
+
+
+/**
+ * Constructor.
+ *
+ * @param host The host to which the Pdu will be sent
+ * @param port The port where the SNMP server will be
+ * @see SnmpContextv2c#SnmpContextv2c(String, int)
+ */
+public PassiveSnmpContextv2c(String host, int port)
+throws java.io.IOException
+{
+ super(host, port);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocketA should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the Pdu will be sent
+ * @param port The port where the SNMP server will be
+ * @param typeSocketA The type of socket to use.
+ *
+ * @see SnmpContextv2c#SnmpContextv2c(String, int, String)
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ */
+public PassiveSnmpContextv2c(String host, int port, String typeSocketA)
+throws java.io.IOException
+{
+ super(host, port, typeSocketA);
+}
+
+/**
+ * Constructor.
+ *
+ * If bindAddress is null, then the system will pick up a valid local
+ * address to bind the socket.
+ *
+ * The typeSocketA will indicate which type of socket to use. This way
+ * different handlers can be provided.
+ * It should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the Pdu will be sent
+ * @param port The port where the SNMP server will be
+ * @param bindAddress The local address the server will bind to
+ * @param typeSocketA The type of socket to use.
+ *
+ * @exception java.io.IOException Thrown when the socket cannot be
+ * created.
+ *
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ */
+protected PassiveSnmpContextv2c(String host, int port, String bindAddress, String typeSocketA)
+throws java.io.IOException
+{
+ super(host, port, bindAddress, typeSocketA);
+}
+
+
+/**
+ * Overrides the AbstractSnmpContext.activate() to do nothing.
+ * This prevents the creation of threads in the base class.
+ *
+ * @see AbstractSnmpContext#activate()
+ */
+protected void activate()
+{
+ // do nothing
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/Pdu.java b/src/main/java/uk/co/westhawk/snmp/stack/Pdu.java
new file mode 100644
index 0000000..63d0e12
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/Pdu.java
@@ -0,0 +1,994 @@
+// NAME
+// $RCSfile: Pdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.33 $
+// CREATED
+// $Date: 2008/12/12 14:55:51 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import java.util.*;
+import java.io.*;
+
+import uk.co.westhawk.snmp.util.*;
+
+/**
+ * This class represents the ASN PDU object, this is the equivalent of
+ * a GetRequest PDU.
+ *
+ * @author Tim Panton
+ * @version $Revision: 3.33 $ $Date: 2008/12/12 14:55:51 $
+ */
+public abstract class Pdu extends Observable
+{
+ private static final String version_id =
+ "@(#)$Id: Pdu.java,v 3.33 2008/12/12 14:55:51 tpanton Exp $ Copyright Westhawk Ltd";
+
+ protected Vector reqVarbinds = null;
+ protected Vector respVarbinds = null;
+
+ private final static String TIMED_OUT = "Timed out";
+ private final static String [] errorStrings =
+ {
+ "No error",
+ "Value too big error",
+ "No such name error",
+ "Bad value error",
+ "Read only error",
+ "General error",
+ "No access error",
+ "Wrong type error",
+ "Wrong length error",
+ "Wrong encoding error",
+ "Wrong value error",
+ "No creation error",
+ "Inconsistent value error",
+ "Resource unavailable error",
+ "Commit failed error",
+ "Undo failed error",
+ "Authorization error",
+ "Not writable error",
+ "Inconsistent name error",
+ };
+
+ private static int next_id = 1;
+ private static final Object NEXT_ID_LOCK= new Object();
+
+ private int retry_intervals[] = {500,1000,2000,5000,5000};
+
+ protected byte[] encodedPacket = null;
+ protected SnmpContextBasisFace context;
+ protected boolean added = false;
+ protected byte msg_type;
+
+ int req_id;
+ protected Integer snmpv3MsgId = null;
+ protected int errstat;
+ protected int errind;
+
+ private Transmitter trans = null;
+ private int retries;
+ protected boolean answered;
+ private boolean got = false;
+ private boolean isTimedOut;
+ private PduException respException = null;
+
+/**
+ * The value of the response is set. This will be called by
+ * Pdu.fillin().
+ */
+protected void new_value(int n, varbind res) {}
+
+/**
+ * This method notifies all observers.
+ * This will be called by Pdu.fillin().
+ *
+ *
+ * The Object to the update() method of the Observer will be a varbind,
+ * unless an exception occurred.
+ * In the case of an exception, that exception will be passed.
+ * So watch out casting!
+ *
+ */
+protected void tell_them()
+{
+ notifyObservers();
+}
+
+/**
+ * Constructor.
+ *
+ * @param con The context of the PDU
+ * @see SnmpContext
+ * @see SnmpContextv2c
+ * @see SnmpContextv3
+ */
+public Pdu(SnmpContextBasisFace con)
+{
+ context = con;
+
+ // TODO: would not work if we ever were to send response or report!
+ // TODO: We would have to set the req_id!
+
+ // Added NEXT_ID_LOCK on suggestion of
+ // Victor Kirk
+ synchronized(NEXT_ID_LOCK)
+ {
+ req_id = next_id++;
+ }
+ errstat = AsnObject.SNMP_ERR_NOERROR;
+ errind = 0x00;
+ reqVarbinds = new Vector(1,1);
+ setMsgType(AsnObject.GET_REQ_MSG);
+ isTimedOut = false;
+
+ // if it is not set to false, PDUs that do not receive a response
+ // will not be filled in properly.
+ answered = false;
+}
+
+/**
+ * Returns the context of this PDU.
+ * @return The context
+ */
+public SnmpContextBasisFace getContext()
+{
+ return context;
+}
+
+/**
+ * Sets the retry intervals of the PDU. The length of the array
+ * corresponds with the number of retries. Each entry in the array
+ * is the number of milliseconds of each try.
+ *
+ *
+ * If used, please set before sending!
+ *
+ *
+ * The default is {500, 1000, 2000, 5000, 5000}.
+ * It is good practice to make the interval bigger with each retry,
+ * if the numbers are the same the chance of collision is higher.
+ *
+ * @param rinterval The interval in msec of each retry
+ */
+public void setRetryIntervals(int rinterval[])
+{
+ retry_intervals = rinterval;
+}
+
+public int[] getRetryIntervals()
+{
+ return retry_intervals;
+}
+
+/**
+ * Sends the PDU.
+ * Note that all properties of the context have to be set before this
+ * point.
+ */
+public boolean send() throws IOException, PduException
+{
+ return send(errstat, errind);
+}
+
+/**
+ * Sends the PDU. This method accommodates the GetBulk request.
+ *
+ * @param error_status The value of the error_status field.
+ * @param error_index The value of the error_index field.
+ * @see #send()
+ */
+protected boolean send(int error_status, int error_index)
+throws IOException, PduException
+{
+ if (added == false)
+ {
+ // Moved this statement from the constructor because it
+ // conflicts with the way the SnmpContextXPool works.
+ added = context.addPdu(this);
+ }
+ Enumeration vbs = reqVarbinds.elements();
+ encodedPacket = context.encodePacket(msg_type, req_id, error_status,
+ error_index, vbs, snmpv3MsgId);
+ addToTrans();
+ return added;
+}
+
+/**
+ * Adds the PDU to its transmitter. The transmitter is the thread that
+ * will be sent the PDU and then waits for the answer.
+ *
+ * @see #send
+ */
+protected void addToTrans()
+{
+ if (added && (trans != null))
+ {
+ // thanks to Ian Dowse for synchronisation
+ synchronized(trans)
+ {
+ trans.setPdu(this);
+ trans.stand();
+ }
+ }
+}
+
+/**
+ * Sends the actual packet and updates the retries.
+ *
+ * @see AbstractSnmpContext#sendPacket(byte[] p)
+ */
+protected boolean sendme()
+{
+ context.sendPacket(encodedPacket);
+ retries ++;
+
+ if (AsnObject.debug > 6)
+ {
+ System.out.println(getClass().getName() + ".sendme(): Sent Pdu reqId=" + req_id + ", retries "+retries);
+ }
+ return (retries > 3);
+}
+
+
+/**
+ * Sends the PDU.
+ * For backwards compatibility only. Please use send() instead.
+ * The community name will be passed to the SnmpContext. If using
+ * SnmpContextv3, the community name will be ignored.
+ *
+ * @param com The community name of the PDU in SNMPv1 and SNMPv2c.
+ * @deprecated Community name has moved to SnmpContext. Use {@link SnmpContext#setCommunity(String)}.
+ *
+ * @see SnmpContext#setCommunity
+ * @see #send
+ */
+public boolean send(String com) throws IOException, PduException
+{
+ if (context instanceof SnmpContext)
+ {
+ ((SnmpContext)context).setCommunity(com);
+ }
+ return send();
+}
+
+/**
+ * Adds an OID (object identifier) to the PDU. The OID indicates which
+ * MIB variable we request for or which MIB variable should be set.
+ *
+ * @param oid The oid
+ * @see #addOid(varbind)
+ * @see varbind
+ */
+public void addOid(String oid)
+{
+ varbind vb = new varbind(oid);
+ addOid(vb);
+}
+
+/**
+ * Adds an OID (object identifier) to the PDU. The OID indicates which
+ * MIB variable we request for or which MIB variable should be set.
+ *
+ * @param oid The oid
+ * @see #addOid(varbind)
+ * @see varbind
+ * @since 4_12
+ */
+public void addOid(AsnObjectId oid)
+{
+ varbind vb = new varbind(oid);
+ addOid(vb);
+}
+
+/**
+ * Adds an OID (object identifier) to the PDU and the value that has
+ * to be set. This method has moved from SetPdu to this class in version 4_12.
+ *
+ * @param oid The oid
+ * @param val The value
+ * @see Pdu#addOid
+ * @see varbind
+ * @since 4_12
+ */
+public void addOid(String oid, AsnObject val)
+{
+ varbind vb = new varbind(oid, val);
+ addOid(vb);
+}
+
+/**
+ * Adds an OID (object identifier) to the PDU and the value that has
+ * to be set.
+ *
+ *
+ * Thanks to Eli Bishop (eli@graphesthesia.com) for the suggestion.
+ *
+ *
+ * @param oid The oid
+ * @param val The value
+ * @see Pdu#addOid
+ * @see varbind
+ * @since 4_12
+ */
+public void addOid(AsnObjectId oid, AsnObject val)
+{
+ varbind vb = new varbind(oid, val);
+ addOid(vb);
+}
+
+/**
+ * Adds an OID (object identifier) to the PDU.
+ *
+ * @param var The varbind
+ * @see #addOid(String)
+ */
+public void addOid(varbind var)
+{
+ reqVarbinds.addElement(var);
+}
+
+/**
+ * Returns a copy of the varbinds used to build the request.
+ *
+ * @return the request varbinds of this PDU.
+ */
+public varbind[] getRequestVarbinds()
+{
+ int sz = reqVarbinds.size();
+ varbind[] arr = new varbind[sz];
+ reqVarbinds.copyInto(arr);
+ return arr;
+}
+
+/**
+ * Returns a copy of the varbinds received in the response.
+ * If there was no response (yet), null will be returned.
+ *
+ * @return the response varbinds of this PDU.
+ * @exception PduException An agent or decoding exception occurred
+ * whilst receiving the response.
+ *
+ * @see #getErrorStatus
+ * @see #notifyObservers
+ */
+public varbind[] getResponseVarbinds() throws PduException
+{
+ if (respException != null)
+ {
+ throw respException;
+ }
+
+ varbind[] arr = null;
+ if (respVarbinds != null)
+ {
+ int sz = respVarbinds.size();
+ arr = new varbind[sz];
+ respVarbinds.copyInto(arr);
+ }
+ return arr;
+}
+
+private void dump(Vector v, varbind[] array)
+{
+ int sz = v.size();
+ System.out.println("Vector: ");
+ for (int i=0; i 6)
+ {
+ System.out.println(getClass().getName() + ".setResponseException(): reqId=" + req_id + exc.getMessage());
+ }
+ respException = exc;
+}
+
+/**
+ * Returns the request id of the PDU.
+ *
+ * @return The ID
+ */
+public int getReqId()
+{
+ return req_id;
+}
+
+/**
+ * Returns the error index.
+ * The error index indicates which of the OIDs went wrong.
+ *
+ * @return the error index
+ * @see #getErrorStatus
+ */
+public int getErrorIndex()
+{
+ return errind;
+}
+
+/**
+ * Returns the error status as indicated by the error-status field in
+ * the reponse PDU. The error index will indicated which OID caused the
+ * error.
+ * In case of a decoding exception the error status
+ * will be set to one of the decoding errors:
+ *
+ * -
+ *
SnmpConstants.SNMP_ERR_DECODING_EXC
.
+ *
+ * -
+ *
SnmpConstants.SNMP_ERR_DECODINGASN_EXC
.
+ *
+ * -
+ *
SnmpConstants.SNMP_ERR_DECODINGPKTLNGTH_EXC
.
+ *
+ *
+ *
+ *
+ * The actual exception will be passed to your
+ * update(Observable ob, Object arg)
+ * method via the the parameter
+ * arg
.
+ *
+ *
+ * @return the error status
+ * @see #notifyObservers
+ * @see #getResponseVarbinds
+ * @see SnmpConstants#SNMP_ERR_NOERROR
+ * @see SnmpConstants#SNMP_ERR_DECODING_EXC
+ * @see SnmpConstants#SNMP_ERR_DECODINGASN_EXC
+ * @see SnmpConstants#SNMP_ERR_DECODINGPKTLNGTH_EXC
+ * @see #getErrorStatusString
+ * @see #getErrorIndex
+ */
+public int getErrorStatus()
+{
+ return errstat;
+}
+
+/**
+ * Returns the string representation of the error status.
+ *
+ * @return the error string
+ * @see #getErrorStatus
+ */
+public String getErrorStatusString()
+{
+ String errString = "";
+ if (errstat >= 0)
+ {
+ if (errstat < errorStrings.length)
+ {
+ errString = errorStrings[errstat];
+
+ if (errstat == AsnObject.SNMP_ERR_GENERR
+ &&
+ isTimedOut() == true)
+ {
+ errString = TIMED_OUT;
+ }
+ }
+ else
+ {
+ // they much be one of the DECODING*_EXC
+ if (respException != null)
+ {
+ errString = respException.getMessage();
+ }
+ else
+ {
+ errString = "Decoding Exception";
+ }
+ }
+ }
+ return errString;
+}
+
+/**
+ * Returns whether or not this PDU is timed out, i.e. it did not get
+ * a response.
+ * Its errorStatus will be set to AsnObject.SNMP_ERR_GENERR.
+ *
+ *
+ * Note that a SNMP agent can respond with an errorStatus of
+ * AsnObject.SNMP_ERR_GENERR as well, so getting a
+ * AsnObject.SNMP_ERR_GENERR does not necessarily mean that the request
+ * is timed out!
+ *
+ *
+ * @return true is the PDU was timed out
+ * @see #getErrorStatus
+ * @see SnmpConstants#SNMP_ERR_GENERR
+ */
+public boolean isTimedOut()
+{
+ return isTimedOut;
+}
+
+
+/**
+ * This method will wait until the answer is received, instead of
+ * continue with other stuff.
+ */
+public boolean waitForSelf()
+{
+ // Add an extra second to the waiting. This gives the PDU a chance
+ // to handle the timeout correctly before this thread wakes up.
+ long del = 1000;
+ for (int i=0; i< retry_intervals.length; i++)
+ {
+ del += retry_intervals[i];
+ }
+ boolean res = waitForSelf(del);
+
+ if (AsnObject.debug > 6)
+ {
+ System.out.println(getClass().getName() + ".waitForSelf(): reqId=" + req_id + " " + res);
+ }
+
+ // Should I??
+ if (!answered)
+ {
+ handleNoAnswer();
+ }
+
+ return res;
+}
+
+/**
+ * Returns the string representation of the PDU.
+ *
+ * @return The string of the PDU
+ */
+public String toString()
+{
+ return toString(false);
+}
+
+/**
+ * Returns the string representation of the PDU with or without the
+ * response varbinds.
+ *
+ * @param withRespVars Include the response varbinds or not
+ * @return The string of the PDU
+ */
+protected String toString(boolean withRespVars)
+{
+ StringBuffer buffer = new StringBuffer(getClass().getName());
+ buffer.append("[");
+ buffer.append("context=").append(context);
+ buffer.append(", reqId=").append(req_id);
+ buffer.append(", msgType=0x").append(SnmpUtilities.toHex(msg_type));
+
+ buffer.append(", ");
+ buffer.append(printVars("reqVarbinds", reqVarbinds));
+
+ if (withRespVars == true)
+ {
+ buffer.append(", ");
+ buffer.append(printVars("respVarbinds", respVarbinds));
+ }
+
+ buffer.append("]");
+ return buffer.toString();
+}
+
+/**
+ * Returns the string representation of the varbinds of the PDU.
+ *
+ * @see #toString(boolean)
+ * @since 4_14
+ */
+protected StringBuffer printVars(String title, Vector vars)
+{
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(title).append("=");
+ if (vars != null)
+ {
+ int sz = vars.size();
+ buffer.append("[");
+ for (int i=0; i 0)
+ {
+ buffer.append(", ");
+ }
+ varbind var = (varbind) vars.elementAt(i);
+ buffer.append(var.toString());
+ }
+ buffer.append("]");
+ }
+ else
+ {
+ buffer.append("null");
+ }
+ return buffer;
+}
+
+synchronized boolean waitForSelf(long delay)
+{
+ if (!got)
+ {
+ try
+ {
+ wait(delay);
+ }
+ catch (InterruptedException ix)
+ {
+ ;
+ }
+ }
+ return answered;
+}
+
+void transmit()
+{
+ transmit(true);
+}
+
+void transmit(boolean withRetries)
+{
+ if (withRetries == true)
+ {
+ int n=0;
+ answered=false;
+
+ while ((!context.isDestroyed()) && (!answered) && (n 6)
+ {
+ System.out.println(getClass().getName() + ".transmit(): Failed to remove reqId " + req_id);
+ }
+ }
+}
+
+void setTrans(Transmitter t)
+{
+ trans = t;
+}
+
+
+/**
+ * Returns the message type, this will indicate what kind of request we
+ * are dealing with.
+ * By default it will be set to the GET_REQ_MSG
+ *
+ * @return The message type
+ */
+public byte getMsgType()
+{
+ return msg_type;
+}
+
+/**
+ * Sets the message type, this will indicate what kind of request we
+ * are dealing with.
+ * By default it will be set to the GET_REQ_MSG
+ *
+ * @param type The message type
+ */
+protected void setMsgType(byte type)
+{
+ msg_type = type;
+}
+
+/**
+ * Sets the error status, indicating what went wrong.
+ *
+ * @param err the error status
+ * @see #getErrorIndex
+ * @see #getErrorStatusString
+ * @see #getErrorStatus
+ */
+protected void setErrorStatus(int err)
+{
+ errstat = err;
+ if (AsnObject.debug > 6)
+ {
+ System.out.println(getClass().getName() + ".setErrorStatus(): reqId=" + req_id + " " + errstat);
+ }
+ if (errstat != AsnObject.SNMP_ERR_NOERROR)
+ {
+ setResponseException(new AgentException(getErrorStatusString()));
+ }
+}
+
+/**
+ * Sets the error status and the exception, indicating what went wrong.
+ *
+ * @param err the error status
+ * @param exc the PDU Exception that was thrown whilst decoding
+ *
+ * @see #getErrorIndex
+ * @see #getErrorStatusString
+ * @see #getErrorStatus
+ */
+protected void setErrorStatus(int err, PduException exc)
+{
+ errstat = err;
+ setResponseException(exc);
+}
+
+/**
+ * Sets the error index, this indicates which of the OIDs went wrong.
+ * @param ind the error index
+ * @see #setErrorStatus(int)
+ * @see #getErrorIndex
+ */
+protected void setErrorIndex(int ind)
+{
+ errind = ind;
+}
+
+/**
+ * Returns whether or not this type of PDU is expecting some kind of response.
+ * This method is used in AbstractSnmpContext to help determine whether
+ * or not to start a thread that listens for a response when sending this
+ * PDU.
+ * The default is true.
+ *
+ * @return true if a response is expected, false if not.
+ * @since 4_14
+ */
+protected boolean isExpectingResponse()
+{
+ return true;
+}
+
+/**
+ * This method is called when no answer is received after all
+ * retries.
+ * The application is notified of this.
+ * See also fillin()
+ */
+private void handleNoAnswer()
+{
+ if (AsnObject.debug > 6)
+ {
+ System.out.println(getClass().getName() + ".handleNoAnswer(): reqId=" + req_id);
+ }
+
+ // it's a lie, but it will prevent this method from
+ // being called twice
+ answered=true;
+
+ isTimedOut = true;
+ setErrorStatus(AsnObject.SNMP_ERR_GENERR);
+ setErrorIndex(0);
+
+ setChanged();
+ tell_them();
+ clearChanged();
+
+ synchronized(this)
+ {
+ notify();
+ }
+}
+
+/**
+ * Fill in the received response.
+ * @see Pdu#getResponseVarbinds()
+ *
+ */
+void fillin(AsnPduSequence seq)
+{
+ if (answered)
+ {
+ if (AsnObject.debug > 6)
+ {
+ System.out.println(getClass().getName() + ".fillin(): Got a second answer to reqId " + req_id);
+ }
+ return;
+ }
+
+ // fillin(null) can be called in case of a Decoding exception
+ if (seq != null)
+ {
+ if (seq.isCorrect == true)
+ {
+ int n=-1;
+ try
+ {
+ // Fill in the request id
+ this.req_id = seq.getReqId();
+ setErrorStatus(seq.getWhatError());
+ setErrorIndex(seq.getWhereError());
+
+ // The varbinds from the response/report are set in a
+ // new Vector.
+ AsnSequence varBind = seq.getVarBind();
+ int size = varBind.getObjCount();
+ respVarbinds = new Vector(size, 1);
+ for (n=0; n
+ * In the case of an exception, the error status
+ * will be set to one of the decoding errors (see
+ * getErrorStatus
)
+ * and passed as the parameter
+ * arg
in the
+ * update(Observable obs, Object arg)
+ * method.
+ *
+ *
+ * @param arg The argument passed to update, can be a PduException.
+ * @see SnmpConstants#SNMP_ERR_DECODING_EXC
+ * @see #getErrorStatus
+ * @see #getResponseVarbinds
+ * @since 4.5
+ */
+public void notifyObservers(Object arg)
+{
+ if (respException != null)
+ {
+ super.notifyObservers(respException);
+ }
+ else
+ {
+ super.notifyObservers(arg);
+ }
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/PduException.java b/src/main/java/uk/co/westhawk/snmp/stack/PduException.java
new file mode 100644
index 0000000..87e955f
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/PduException.java
@@ -0,0 +1,82 @@
+// NAME
+// $RCSfile: PduException.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.5 $
+// CREATED
+// $Date: 2006/01/17 17:43:54 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.5 $ $Date: 2006/01/17 17:43:54 $
+ */
+public class PduException extends Exception
+{
+ private static final String version_id =
+ "@(#)$Id: PduException.java,v 3.5 2006/01/17 17:43:54 birgit Exp $ Copyright Westhawk Ltd";
+
+/**
+ * Constructs a PduException with no specified detail message.
+ *
+ */
+public PduException()
+{
+ super();
+}
+
+/**
+ * Constructs a PduException with the specified detail
+ * message.
+ *
+ * @param str The detail message.
+ */
+public PduException(String str)
+{
+ super(str);
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/ReportPdu.java b/src/main/java/uk/co/westhawk/snmp/stack/ReportPdu.java
new file mode 100644
index 0000000..be0edc1
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/ReportPdu.java
@@ -0,0 +1,172 @@
+// NAME
+// $RCSfile: ReportPdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.3 $
+// CREATED
+// $Date: 2006/01/17 17:59:34 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * This class represents the ASN SNMP Report PDU object.
+ * This class is used when requests are received that try to discover our
+ * SNMPv3 timeliness. This will only be the case then the stack acts as
+ * authoritative engine.
+ *
+ *
+ * Reports are not used (as far as we know) in normal
+ * manager - agent (authoritative - non authoritative) communication.
+ * Hence the reason why this stack does not support them in any other
+ * way.
+ *
+ *
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.3 $ $Date: 2006/01/17 17:59:34 $
+ */
+public class ReportPdu extends Pdu
+{
+ private static final String version_id =
+ "@(#)$Id: ReportPdu.java,v 3.3 2006/01/17 17:59:34 birgit Exp $ Copyright Westhawk Ltd";
+
+/**
+ * Constructor.
+ * The requestPdu is used to copy the necessary IDs to this PDU.
+ *
+ * @param con The context of the PDU
+ * @param requestPdu The original Request PDU
+ */
+public ReportPdu(SnmpContextBasisFace con, Pdu requestPdu)
+{
+ super(con);
+ setMsgType(AsnObject.GET_RPRT_MSG);
+ req_id = requestPdu.req_id;
+ snmpv3MsgId = requestPdu.snmpv3MsgId;
+}
+
+
+/**
+ * Sets the error status of this PDU. This indicates that an exception
+ * has occurred while processing the original request.
+ *
+ * @see SnmpConstants#SNMP_ERR_NOERROR
+ * @see SnmpConstants#SNMP_ERR_TOOBIG
+ * @see SnmpConstants#SNMP_ERR_NOSUCHNAME
+ * @see SnmpConstants#SNMP_ERR_BADVALUE
+ * @see SnmpConstants#SNMP_ERR_READONLY
+ * @see SnmpConstants#SNMP_ERR_GENERR
+ * @see SnmpConstants#SNMP_ERR_NOACCESS
+ * @see SnmpConstants#SNMP_ERR_WRONGTYPE
+ * @see SnmpConstants#SNMP_ERR_WRONGLENGTH
+ * @see SnmpConstants#SNMP_ERR_WRONGENCODING
+ * @see SnmpConstants#SNMP_ERR_WRONGVALUE
+ * @see SnmpConstants#SNMP_ERR_NOCREATION
+ * @see SnmpConstants#SNMP_ERR_INCONSISTENTVALUE
+ * @see SnmpConstants#SNMP_ERR_RESOURCEUNAVAILABLE
+ * @see SnmpConstants#SNMP_ERR_COMMITFAILED
+ * @see SnmpConstants#SNMP_ERR_UNDOFAILED
+ * @see SnmpConstants#SNMP_ERR_AUTHORIZATIONERR
+ * @see SnmpConstants#SNMP_ERR_NOTWRITABLE
+ * @see SnmpConstants#SNMP_ERR_INCONSISTENTNAME
+ */
+public void getErrorStatus(int errorStatus)
+{
+ errstat = errorStatus;
+}
+
+
+/**
+ * Sets the error index of this PDU. When the error status is not
+ * SNMP_ERR_NOERROR, it indicates the index of the variable in the
+ * varbind list that caused the exception.
+ */
+public void getErrorIndex(int errorIndex)
+{
+ errind = errorIndex;
+}
+
+/**
+ * The Report PDU does not get a response back. So it should be sent once.
+ */
+void transmit()
+{
+ transmit(false);
+}
+
+/**
+ * Returns the string representation of this object.
+ *
+ * @return The string of the PDU
+ */
+public String toString()
+{
+ return super.toString(true);
+}
+
+/**
+ * Has no meaning, since there is not response.
+ */
+protected void new_value(int n, varbind res){}
+
+/**
+ * Has no meaning, since there is not response.
+ */
+protected void tell_them(){}
+
+/**
+ * Returns that this type of PDU is not expecting a response.
+ * This method is used in AbstractSnmpContext to help determine whether
+ * or not to start a thread that listens for a response when sending this
+ * PDU.
+ * The default is false.
+ *
+ * @return true if a response is expected, false if not.
+ */
+protected boolean isExpectingResponse()
+{
+ return false;
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/ResponsePdu.java b/src/main/java/uk/co/westhawk/snmp/stack/ResponsePdu.java
new file mode 100644
index 0000000..2289f3b
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/ResponsePdu.java
@@ -0,0 +1,183 @@
+// NAME
+// $RCSfile: ResponsePdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.6 $
+// CREATED
+// $Date: 2006/11/30 14:45:50 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * This class represents the ASN SNMP Response PDU object.
+ * This class should be used when responding to an incoming request
+ * via a ListeningContext. Note that you should use the port of the
+ * RequestPduEvent (getHostPort()) when creating a SnmpContext.
+ *
+ *
+ * This class is not used when request are sent out by the
+ * stack and a response is received. In that case the OIDs of the
+ * response are integrated into the original request PDU.
+ *
+ *
+ *
+ * For SNMPv3: The sender of a response PDU acts as the authoritative engine.
+ *
+ *
+ * @see ListeningContext
+ * @see uk.co.westhawk.snmp.event.RequestPduEvent
+ * @see uk.co.westhawk.snmp.event.RequestPduEvent#getHostPort()
+ *
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.6 $ $Date: 2006/11/30 14:45:50 $
+ */
+public class ResponsePdu extends Pdu
+{
+ private static final String version_id =
+ "@(#)$Id: ResponsePdu.java,v 3.6 2006/11/30 14:45:50 birgit Exp $ Copyright Westhawk Ltd";
+
+/**
+ * Constructor.
+ * The requestPdu is used to copy the necessary IDs to this PDU.
+ *
+ * @param con The context of the PDU
+ * @param requestPdu The original Request PDU
+ */
+public ResponsePdu(SnmpContextBasisFace con, Pdu requestPdu)
+{
+ super(con);
+ setMsgType(AsnObject.GET_RSP_MSG);
+ req_id = requestPdu.req_id;
+ snmpv3MsgId = requestPdu.snmpv3MsgId;
+}
+
+
+/**
+ * Sets the error status of this PDU. This indicates that an exception
+ * has occurred while processing the original request.
+ *
+ * @see SnmpConstants#SNMP_ERR_NOERROR
+ * @see SnmpConstants#SNMP_ERR_TOOBIG
+ * @see SnmpConstants#SNMP_ERR_NOSUCHNAME
+ * @see SnmpConstants#SNMP_ERR_BADVALUE
+ * @see SnmpConstants#SNMP_ERR_READONLY
+ * @see SnmpConstants#SNMP_ERR_GENERR
+ * @see SnmpConstants#SNMP_ERR_NOACCESS
+ * @see SnmpConstants#SNMP_ERR_WRONGTYPE
+ * @see SnmpConstants#SNMP_ERR_WRONGLENGTH
+ * @see SnmpConstants#SNMP_ERR_WRONGENCODING
+ * @see SnmpConstants#SNMP_ERR_WRONGVALUE
+ * @see SnmpConstants#SNMP_ERR_NOCREATION
+ * @see SnmpConstants#SNMP_ERR_INCONSISTENTVALUE
+ * @see SnmpConstants#SNMP_ERR_RESOURCEUNAVAILABLE
+ * @see SnmpConstants#SNMP_ERR_COMMITFAILED
+ * @see SnmpConstants#SNMP_ERR_UNDOFAILED
+ * @see SnmpConstants#SNMP_ERR_AUTHORIZATIONERR
+ * @see SnmpConstants#SNMP_ERR_NOTWRITABLE
+ * @see SnmpConstants#SNMP_ERR_INCONSISTENTNAME
+ *
+ * @since 5_2
+ */
+public void setErrorStatus(int errorStatus)
+{
+ errstat = errorStatus;
+}
+
+
+/**
+ * Sets the error index of this PDU. When the error status is not
+ * SNMP_ERR_NOERROR, it indicates the index of the variable in the
+ * varbind list that caused the exception.
+ *
+ * @since 5_2
+ */
+public void setErrorIndex(int errorIndex)
+{
+ errind = errorIndex;
+}
+
+/**
+ * The Response PDU does not get a response back. So it should be sent once.
+ */
+void transmit()
+{
+ transmit(false);
+}
+
+/**
+ * Returns the string representation of this object.
+ *
+ * @return The string of the PDU
+ */
+public String toString()
+{
+ return super.toString(true);
+}
+
+/**
+ * Has no meaning, since there is not response.
+ */
+protected void new_value(int n, varbind res){}
+
+/**
+ * Has no meaning, since there is not response.
+ */
+protected void tell_them(){}
+
+/**
+ * Returns that this type of PDU is not expecting a response.
+ * This method is used in AbstractSnmpContext to help determine whether
+ * or not to start a thread that listens for a response when sending this
+ * PDU.
+ * The default is false.
+ *
+ * @return true if a response is expected, false if not.
+ */
+protected boolean isExpectingResponse()
+{
+ return false;
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/SetPdu.java b/src/main/java/uk/co/westhawk/snmp/stack/SetPdu.java
new file mode 100644
index 0000000..27c0aad
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/SetPdu.java
@@ -0,0 +1,92 @@
+// NAME
+// $RCSfile: SetPdu.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.9 $
+// CREATED
+// $Date: 2006/01/17 17:43:54 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * This class represents the SNMP Set Pdu.
+ *
+ * @see #addOid(String, AsnObject)
+ * @see #addOid(AsnObjectId, AsnObject)
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.9 $ $Date: 2006/01/17 17:43:54 $
+ */
+public class SetPdu extends Pdu
+{
+ private static final String version_id =
+ "@(#)$Id: SetPdu.java,v 3.9 2006/01/17 17:43:54 birgit Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * Constructor.
+ *
+ * @param con The context of the Pdu
+ */
+ public SetPdu(SnmpContextBasisFace con)
+ {
+ super(con);
+ setMsgType(AsnObject.SET_REQ_MSG);
+ }
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/SnmpConstants.java b/src/main/java/uk/co/westhawk/snmp/stack/SnmpConstants.java
new file mode 100644
index 0000000..565c75d
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/SnmpConstants.java
@@ -0,0 +1,376 @@
+// NAME
+// $RCSfile: SnmpConstants.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.10 $
+// CREATED
+// $Date: 2006/03/23 14:54:10 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/*
+ * Copyright (C) 2001 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+/**
+ * This interface contains most of the constants used in the stack.
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.10 $ $Date: 2006/03/23 14:54:10 $
+ */
+public interface SnmpConstants
+{
+ static final String version_id =
+ "@(#)$Id: SnmpConstants.java,v 3.10 2006/03/23 14:54:10 birgit Exp $ Copyright Westhawk Ltd";
+
+public static final byte ASN_BOOLEAN =(byte)(0x01);
+public static final byte ASN_INTEGER =(byte)(0x02);
+public static final byte ASN_BIT_STR =(byte)(0x03);
+public static final byte ASN_OCTET_STR =(byte)(0x04);
+public static final byte ASN_NULL =(byte)(0x05);
+public static final byte ASN_OBJECT_ID =(byte)(0x06);
+public static final byte ASN_SEQUENCE =(byte)(0x10);
+public static final byte ASN_SET =(byte)(0x11);
+
+public static final byte ASN_UNIVERSAL =(byte)(0x00);
+public static final byte ASN_APPLICATION =(byte)(0x40);
+public static final byte ASN_CONTEXT =(byte)(0x80);
+public static final byte ASN_PRIVATE =(byte)(0xC0);
+
+public static final byte ASN_PRIMITIVE =(byte)(0x00);
+public static final byte ASN_CONSTRUCTOR =(byte)(0x20);
+
+public static final byte ASN_LONG_LEN =(byte)(0x80);
+public static final byte ASN_EXTENSION_ID=(byte)(0x1F);
+public static final byte ASN_BIT8 =(byte)(0x80);
+
+public static final byte INTEGER =(byte)ASN_INTEGER;
+public static final byte STRING =(byte)ASN_OCTET_STR;
+public static final byte OBJID =(byte)ASN_OBJECT_ID;
+public static final byte NULLOBJ =(byte)ASN_NULL;
+
+/** IPv4 address only */
+// RFC 2578:
+public static final byte IPADDRESS =(byte)(ASN_APPLICATION | 0);
+public static final byte COUNTER =(byte)(ASN_APPLICATION | 1);
+public static final byte GAUGE =(byte)(ASN_APPLICATION | 2);
+public static final byte TIMETICKS =(byte)(ASN_APPLICATION | 3);
+public static final byte OPAQUE =(byte)(ASN_APPLICATION | 4);
+public static final byte COUNTER64 =(byte)(ASN_APPLICATION | 6);
+
+/**
+ * for OSI NSAP addresses (see
+ * RFC 1442,
+ * is obsoleted by
+ * RFC 2578).
+ */
+public static final byte NSAP_ADDRESS =(byte)(ASN_APPLICATION | 5);
+
+/**
+ * an unsigned 32-bit quantity (see
+ * RFC 1902,
+ * is obsoleted by
+ * SNMPv2-SMI).
+ *
+ *
+ * Was called UINTEGER32. Renamed it in version 4_13.
+ *
+ */
+public static final byte OBSOLETED_RFC1442_UINTEGER32 =(byte)(ASN_APPLICATION | 7);
+
+/**
+ * an unsigned 32-bit quantity. This equals GAUGE. (see
+ * SNMPv2-SMI).
+ */
+public static final byte SMI_V2_UINTEGER32 = GAUGE;
+
+/**
+ * Value for the GenericTrap
field in SNMPv1 Trap.
+ */
+public static final byte SNMP_TRAP_COLDSTART =(byte)(0x0);
+/**
+ * Value for the GenericTrap
field in SNMPv1 Trap.
+ */
+public static final byte SNMP_TRAP_WARMSTART =(byte)(0x1);
+/**
+ * Value for the GenericTrap
field in SNMPv1 Trap.
+ */
+public static final byte SNMP_TRAP_LINKDOWN =(byte)(0x2);
+/**
+ * Value for the GenericTrap
field in SNMPv1 Trap.
+ */
+public static final byte SNMP_TRAP_LINKUP =(byte)(0x3);
+/**
+ * Value for the GenericTrap
field in SNMPv1 Trap.
+ */
+public static final byte SNMP_TRAP_AUTHFAIL =(byte)(0x4);
+/**
+ * Value for the GenericTrap
field in SNMPv1 Trap.
+ */
+public static final byte SNMP_TRAP_EGPNEIGHBORLOSS =(byte)(0x5);
+/**
+ * Value for the GenericTrap
field in SNMPv1 Trap.
+ */
+public static final byte SNMP_TRAP_ENTERPRISESPECIFIC=(byte)(0x6);
+
+/**
+ * Indicated the agent does not implement the object referred to by
+ * this object identifier.
+ * Used in varbind list in response to SNMPv2c, SNMPv3 getRequest.
+ */
+public static final byte SNMP_VAR_NOSUCHOBJECT =(byte)(ASN_CONTEXT | ASN_PRIMITIVE | 0x0);
+/**
+ * Indicated that this object does not exists for this operation.
+ * Used in varbind list in response to SNMPv2c, SNMPv3 getRequest.
+ */
+public static final byte SNMP_VAR_NOSUCHINSTANCE =(byte)(ASN_CONTEXT | ASN_PRIMITIVE | 0x1);
+/**
+ * Indicated an attempt to reference an object identifier that is
+ * beyond the end of the MIB at the agent.
+ * Used in varbind list in response to SNMPv2c, SNMPv3 getRequest or getBulkRequest.
+ */
+public static final byte SNMP_VAR_ENDOFMIBVIEW =(byte)(ASN_CONTEXT | ASN_PRIMITIVE | 0x2);
+
+
+/**
+ * No error in the PDU response.
+ * Used in SNMPv1, SNMPv2c, SNMPv3.
+ */
+public static final byte SNMP_ERR_NOERROR =(byte)(0x00);
+/**
+ * The size of the generated response PDU would exceed a local
+ * limitation.
+ * Used in SNMPv1, SNMPv2c, SNMPv3.
+ */
+public static final byte SNMP_ERR_TOOBIG =(byte)(0x01);
+/**
+ * The object is not available or the object's name does not exactly
+ * match.
+ * Only used in SNMPv1.
+ */
+public static final byte SNMP_ERR_NOSUCHNAME =(byte)(0x02);
+/**
+ * The object does not manifest a type, length, and value
+ * that is consistent with that required for the variable.
+ * Only used in response to SNMPv1 SetRequest.
+ */
+public static final byte SNMP_ERR_BADVALUE =(byte)(0x03);
+/**
+ * The object can not be set, only read.
+ * Only used in response to SNMPv1 SetRequest.
+ */
+public static final byte SNMP_ERR_READONLY =(byte)(0x04);
+/**
+ * The value of an object cannot be retrieved for reasons
+ * not covered by any of other errors.
+ * Used in SNMPv1, SNMPv2c, SNMPv3.
+ */
+public static final byte SNMP_ERR_GENERR =(byte)(0x05);
+
+/**
+ * The variable binding's name specifies an existing or
+ * non-existent variable to which this request is/would be denied
+ * access because it is/would not be in the appropriate MIB view.
+ * Used in response to SNMPv2c, SNMPv3 SetRequest.
+ */
+public static final byte SNMP_ERR_NOACCESS =(byte)(0x06);
+/**
+ * The variable binding's value field specifies a type which is
+ * inconsistent with that required for all variables which share the
+ * same OBJECT IDENTIFIER prefix as the variable binding's name.
+ * Used in response to SNMPv2c, SNMPv3 SetRequest.
+ */
+public static final byte SNMP_ERR_WRONGTYPE =(byte)(0x07);
+/**
+ * The variable binding's value field specifies a length which is
+ * inconsistent with that required for all variables which share the
+ * same OBJECT IDENTIFIER prefix as the variable binding's name.
+ * Used in response to SNMPv2c, SNMPv3 SetRequest.
+ */
+public static final byte SNMP_ERR_WRONGLENGTH =(byte)(0x08);
+/**
+ * Otherwise, if the variable binding's value field contains an ASN.1
+ * encoding which is inconsistent with that field's ASN.1 tag.
+ * Used in response to SNMPv2c, SNMPv3 SetRequest.
+ */
+public static final byte SNMP_ERR_WRONGENCODING =(byte)(0x09);
+/**
+ * The variable binding's value field specifies a value which could
+ * under no circumstances be assigned to the variable.
+ * Used in response to SNMPv2c, SNMPv3 SetRequest.
+ */
+public static final byte SNMP_ERR_WRONGVALUE =(byte)(0x0A);
+/**
+ * The variable binding's name specifies a variable which does not
+ * exist and could not ever be created (even though some variables
+ * sharing the same OBJECT IDENTIFIER prefix might under some
+ * circumstances be able to be created).
+ * Used in response to SNMPv2c, SNMPv3 SetRequest.
+ */
+public static final byte SNMP_ERR_NOCREATION =(byte)(0x0B);
+/**
+ * The variable binding's value field specifies a value that could
+ * under other circumstances be held by the variable, but is presently
+ * inconsistent or otherwise unable to be assigned to the variable.
+ * Used in response to SNMPv2c, SNMPv3 SetRequest.
+ */
+public static final byte SNMP_ERR_INCONSISTENTVALUE =(byte)(0x0C);
+/**
+ * The assignment of the value specified by the variable binding's
+ * value field to the specified variable requires the allocation of a
+ * resource which is presently unavailable.
+ * Used in response to SNMPv2c, SNMPv3 SetRequest.
+ */
+public static final byte SNMP_ERR_RESOURCEUNAVAILABLE =(byte)(0x0D);
+/**
+ * Any of the assignments failed and all other assignments were
+ * undone.
+ * Used in response to SNMPv2c, SNMPv3 SetRequest.
+ */
+public static final byte SNMP_ERR_COMMITFAILED =(byte)(0x0E);
+/**
+ * Any of the assignments failed and all other assignments were
+ * undone, but is was not possible to undo all the assignments.
+ * Used in response to SNMPv2c, SNMPv3 SetRequest.
+ */
+public static final byte SNMP_ERR_UNDOFAILED =(byte)(0x0F);
+/**
+ * Users is has no access privileges.
+ * Used in SNMPv2c, SNMPv3.
+ */
+public static final byte SNMP_ERR_AUTHORIZATIONERR =(byte)(0x10);
+/**
+ *
+ * -
+ * There are no variables which share the same OBJECT IDENTIFIER
+ * prefix as the variable binding's name, and which are able to be
+ * created or modified no matter what new value is specified.
+ *
+ * -
+ * The variable binding's name specifies a variable which exists but
+ * can not be modified no matter what new value is specified.
+ *
+ *
+ * Used in response to SNMPv2c, SNMPv3 SetRequest.
+ */
+public static final byte SNMP_ERR_NOTWRITABLE =(byte)(0x11);
+/**
+ * The variable binding's name specifies a variable which does not
+ * exist but can not be created under the present circumstances (even
+ * though it could be created under other circumstances).
+ * Used in response to SNMPv2c, SNMPv3 SetRequest.
+ */
+public static final byte SNMP_ERR_INCONSISTENTNAME =(byte)(0x12);
+
+/**
+ * A general decoding exception occured whilst decoding the response.
+ */
+public static final byte SNMP_ERR_DECODING_EXC =(byte)(0x13);
+/**
+ * A specific decoding exception occured whilst decoding the response.
+ * The response PDU being decoded has a sub length wrong (not overall
+ * length necessarily), so the asn sequence can't get created.
+ */
+public static final byte SNMP_ERR_DECODINGASN_EXC =(byte)(0x14);
+/**
+ * A specific decoding exception occured whilst decoding the response.
+ * The received overall response PDU is shorter than the PDU header
+ * says it is.
+ */
+public static final byte SNMP_ERR_DECODINGPKTLNGTH_EXC = (byte)(0x15);
+
+/**
+ * The version number for SNMPv1.
+ */
+public static final byte SNMP_VERSION_1 =(byte)(0x0);
+/**
+ * The version number for SNMPv2c.
+ */
+public static final byte SNMP_VERSION_2c =(byte)(0x1);
+/**
+ * The version number for SNMPv2u.
+ */
+//public static final byte SNMP_VERSION_2u =(byte)(0x2);
+/**
+ * The version number for SNMPv3.
+ */
+public static final byte SNMP_VERSION_3 =(byte)(0x3);
+
+/**
+ * The GetRequest PDU type.
+ */
+static final byte GET_REQ_MSG =(byte)(ASN_CONTEXT | ASN_CONSTRUCTOR | 0x0);
+/**
+ * The GetNextRequest PDU type.
+ */
+static final byte GETNEXT_REQ_MSG =(byte)(ASN_CONTEXT | ASN_CONSTRUCTOR | 0x1);
+/**
+ * The Response PDU type.
+ */
+static final byte GET_RSP_MSG =(byte)(ASN_CONTEXT | ASN_CONSTRUCTOR | 0x2);
+/**
+ * The SetRequest PDU type.
+ */
+static final byte SET_REQ_MSG =(byte)(ASN_CONTEXT | ASN_CONSTRUCTOR | 0x3);
+/**
+ * The SNMPv1 Trap PDU type.
+ */
+static final byte TRP_REQ_MSG =(byte)(ASN_CONTEXT | ASN_CONSTRUCTOR | 0x4);
+
+/**
+ * The GetBulkRequest PDU type.
+ */
+static final byte GETBULK_REQ_MSG =(byte)(ASN_CONTEXT | ASN_CONSTRUCTOR | 0x5);
+/**
+ * The InformRequest PDU type.
+ */
+static final byte INFORM_REQ_MSG =(byte)(ASN_CONTEXT | ASN_CONSTRUCTOR | 0x6);
+/**
+ * The SNMPv2 (and SNMPv3) Trap PDU type.
+ */
+static final byte TRPV2_REQ_MSG =(byte)(ASN_CONTEXT | ASN_CONSTRUCTOR | 0x7);
+/**
+ * The GetReport PDU type.
+ */
+static final byte GET_RPRT_MSG =(byte)(ASN_CONTEXT | ASN_CONSTRUCTOR | 0x8);
+
+static final byte CONS_SEQ =(byte)(ASN_SEQUENCE | ASN_CONSTRUCTOR);
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/SnmpContext.java b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContext.java
new file mode 100644
index 0000000..3070552
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContext.java
@@ -0,0 +1,374 @@
+// NAME
+// $RCSfile: SnmpContext.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.25 $
+// CREATED
+// $Date: 2009/03/05 12:51:29 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.net.*;
+import java.io.*;
+import java.util.*;
+import uk.co.westhawk.snmp.event.*;
+
+/**
+ * This class contains the SNMP v1 context that is needed by every PDU to
+ * send a SNMP v1 request.
+ *
+ *
+ * destroy()
should be called when the context is no longer
+ * used. This is the only way the threads will be stopped and garbage
+ * collected.
+ *
+ *
+ * @see SnmpContextFace
+ * @see SnmpContextPool
+ * @author Tim Panton
+ * @version $Revision: 3.25 $ $Date: 2009/03/05 12:51:29 $
+ */
+public class SnmpContext extends AbstractSnmpContext
+implements SnmpContextFace, Cloneable
+{
+ private static final String version_id =
+ "@(#)$Id: SnmpContext.java,v 3.25 2009/03/05 12:51:29 birgita Exp $ Copyright Westhawk Ltd";
+
+ String community = SnmpContextFace.DEFAULT_COMMUNITY;
+
+/**
+ * Constructor.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @see AbstractSnmpContext#AbstractSnmpContext(String, int)
+ */
+public SnmpContext(String host, int port) throws IOException
+{
+ super(host, port);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocketA should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the Pdu will be sent
+ * @param port The port where the SNMP server will be
+ * @param typeSocketA The local address the server will bind to
+ *
+ * @see AbstractSnmpContext#AbstractSnmpContext(String, int, String)
+ */
+public SnmpContext(String host, int port, String typeSocketA)
+throws IOException
+{
+ super(host, port, typeSocketA);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocketA should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @param bindAddress The local address the server will bind to
+ * @param typeSocketA The type of socket to use.
+ *
+ * @see AbstractSnmpContext#AbstractSnmpContext(String, int, String, String)
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ * @since 4_14
+ */
+public SnmpContext(String host, int port, String bindAddress, String typeSocketA)
+throws IOException
+{
+ super(host, port, bindAddress, typeSocketA);
+}
+
+public int getVersion()
+{
+ return SnmpConstants.SNMP_VERSION_1;
+}
+
+public String getCommunity()
+{
+ return community;
+}
+
+public void setCommunity(String newCommunity)
+{
+ community = newCommunity;
+}
+
+public byte[] encodePacket(byte msg_type, int rId, int errstat,
+ int errind, Enumeration ve, Object obj)
+ throws IOException, EncodingException
+{
+ byte [] packet = null;
+ if (isDestroyed == true)
+ {
+ throw new EncodingException("Context can no longer be used, since it is already destroyed");
+ }
+ else
+ {
+ AsnEncoderv1 enc = new AsnEncoderv1();
+ ByteArrayOutputStream bay = enc.EncodeSNMP(this, msg_type, rId, errstat,
+ errind, ve);
+
+ int sz = bay.size();
+ if (sz > maxRecvSize)
+ {
+ throw new EncodingException("Packet size ("+ sz
+ + ") is > maximum size (" + maxRecvSize +")");
+ }
+ packet = bay.toByteArray();
+ }
+ return packet;
+}
+
+
+public byte[] encodePacket(byte msg_type, String enterprise,
+ byte[] IpAddress, int generic_trap, int specific_trap,
+ long timeTicks, Enumeration ve)
+ throws IOException, EncodingException
+{
+ byte [] packet = null;
+ AsnEncoderv1 enc = new AsnEncoderv1();
+ ByteArrayOutputStream bay = enc.EncodeSNMP(this, msg_type, enterprise,
+ IpAddress, generic_trap, specific_trap, timeTicks, ve);
+
+ int sz = bay.size();
+ if (sz > maxRecvSize)
+ {
+ throw new EncodingException("Packet size ("+ sz
+ + ") is > maximum size (" + maxRecvSize +")");
+ }
+ packet = bay.toByteArray();
+ return packet;
+}
+
+/**
+ * Processes an incoming SNMP v1 response.
+ */
+protected void processIncomingResponse(ByteArrayInputStream in)
+throws DecodingException, IOException
+{
+ AsnDecoderv1 rpdu = new AsnDecoderv1();
+ AsnSequence seqPdu = rpdu.DecodeSNMP(in, getCommunity());
+ if (seqPdu instanceof AsnPduSequence)
+ {
+ AsnPduSequence pduSeq = (AsnPduSequence) seqPdu;
+ if (pduSeq != null)
+ {
+ // got a message
+ Integer rid = new Integer(pduSeq.getReqId());
+ Pdu answ = getPdu(rid);
+ if (answ != null)
+ {
+ answ.fillin(pduSeq);
+ }
+ else
+ {
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName() + ".processIncomingResponse(): No Pdu with reqid " + rid.intValue());
+ }
+ }
+ }
+ else
+ {
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName() + ".processIncomingResponse(): Error - missing seq input");
+ }
+ }
+ }
+ else
+ {
+ // it must be a Trap
+ }
+}
+
+public Pdu processIncomingPdu(byte [] message)
+throws DecodingException, IOException
+{
+ AsnDecoderv1 rpdu = new AsnDecoderv1();
+ ByteArrayInputStream in = new ByteArrayInputStream(message);
+
+ Pdu pdu = null;
+ AsnSequence seqPdu = rpdu.DecodeSNMP(in, getCommunity());
+ if (seqPdu instanceof AsnTrapPduv1Sequence)
+ {
+ AsnTrapPduv1Sequence pduSeq = (AsnTrapPduv1Sequence) seqPdu;
+ if (pduSeq != null)
+ {
+ TrapPduv1 trapPdu = new TrapPduv1(this);
+ trapPdu.fillin(pduSeq);
+ pdu = trapPdu;
+ }
+ }
+ else
+ {
+ // must be an ordinary PDU
+ AsnPduSequence pduSeq = (AsnPduSequence) seqPdu;
+ if (pduSeq != null)
+ {
+ byte type = pduSeq.getRespType();
+ switch (type)
+ {
+ case SnmpConstants.GET_REQ_MSG:
+ pdu = new GetPdu(this);
+ break;
+ case SnmpConstants.GETNEXT_REQ_MSG:
+ pdu = new GetNextPdu(this);
+ break;
+ case SnmpConstants.SET_REQ_MSG:
+ pdu = new SetPdu(this);
+ break;
+ //case SnmpConstants.GET_RSP_MSG:
+ // A longly response should never be received here.
+ // They should come in via the processIncomingResponse
+ // route.
+ //case SnmpConstants.GETBULK_REQ_MSG:
+ // not in v1
+ //case SnmpConstants.INFORM_REQ_MSG:
+ // not in v1
+ //case SnmpConstants.GET_RPRT_MSG:
+ // not in v1
+ //case SnmpConstants.TRPV2_REQ_MSG:
+ // not in v1
+ default:
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName()
+ + ".ProcessIncomingPdu(): PDU received with type "
+ + pduSeq.getRespTypeString()
+ + ". Ignoring it.");
+ }
+ }
+
+ if (pdu != null)
+ {
+ pdu.fillin(pduSeq);
+ }
+ }
+ }
+ return pdu;
+}
+
+/**
+ * Returns a clone of this SnmpContext.
+ *
+ * @exception CloneNotSupportedException Thrown when the constructor
+ * generates an IOException
+ */
+public Object clone() throws CloneNotSupportedException
+{
+ SnmpContext clContext = null;
+ try
+ {
+ clContext = new SnmpContext(hostname, hostPort, bindAddr, typeSocket);
+ clContext.setCommunity(new String(community));
+ }
+ catch (IOException exc)
+ {
+ throw new CloneNotSupportedException("IOException "
+ + exc.getMessage());
+ }
+ return clContext;
+}
+
+
+/**
+ * Returns the hash key. This key is built out of all properties. It
+ * serves as key for a hashtable of (v1) contexts.
+ *
+ * @since 4_14
+ * @return The hash key
+ */
+public String getHashKey()
+{
+ String str = hostname
+ + "_" + hostPort
+ + "_" + bindAddr
+ + "_" + typeSocket
+ + "_" + community
+ + "_v" + getVersion();
+ return str;
+}
+
+/**
+ * Returns a string representation of the object.
+ *
+ * @return The string
+ */
+public String toString()
+{
+ StringBuffer buffer = new StringBuffer("SnmpContext[");
+ buffer.append("host=").append(hostname);
+ buffer.append(", port=").append(hostPort);
+ buffer.append(", bindAddress=").append(bindAddr);
+ buffer.append(", socketType=").append(typeSocket);
+ buffer.append(", community=").append(community);
+ buffer.append(", #trapListeners=").append(trapSupport.getListenerCount());
+ buffer.append(", #pduListeners=").append(pduSupport.getListenerCount());
+ buffer.append("]");
+ return buffer.toString();
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextBasisFace.java b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextBasisFace.java
new file mode 100644
index 0000000..a9b45bb
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextBasisFace.java
@@ -0,0 +1,495 @@
+// NAME
+// $RCSfile: SnmpContextBasisFace.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.9 $
+// CREATED
+// $Date: 2006/11/29 16:25:19 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.event.*;
+import uk.co.westhawk.snmp.net.*;
+
+/**
+ * This interface contains the SNMP context interface that is needed
+ * by every PDU to send a SNMP v1, v2c and v3 request. The context also
+ * provides functionality to receive incoming PDUs.
+ *
+ * @see SnmpContext
+ * @see SnmpContextv2c
+ * @see SnmpContextv3
+ *
+ * @author Tim Panton
+ * @version $Revision: 3.9 $ $Date: 2006/11/29 16:25:19 $
+ */
+public interface SnmpContextBasisFace
+{
+ static final String version_id =
+ "@(#)$Id: SnmpContextBasisFace.java,v 3.9 2006/11/29 16:25:19 birgit Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * The default port number where SNMP requests are sent to (161).
+ */
+ public final static int DEFAULT_PORT = 161;
+ /**
+ * The Standard Socket type.
+ */
+ public final static String STANDARD_SOCKET = "Standard";
+ /**
+ * The TCP Socket type.
+ */
+ public final static String TCP_SOCKET = "TCP";
+
+ /**
+ * The Maximum number of outstanding PDUs one context can handle at a
+ * given moment in time.
+ */
+ final static int MAXPDU = 20; // if you have more than 20 oustanding PDUS
+ // change the algorythm :-)
+ /**
+ * The Maximum size of a message in octets (1300).
+ */
+ final static int MSS = 1300; // maximum recv size;
+
+/**
+ * Returns the SNMP version of the context.
+ *
+ * @see SnmpConstants#SNMP_VERSION_1
+ * @see SnmpConstants#SNMP_VERSION_2c
+ * @see SnmpConstants#SNMP_VERSION_3
+ *
+ * @return The version
+ */
+public int getVersion();
+
+/**
+ * Returns the host.
+ *
+ * @return The host
+ */
+public String getHost();
+
+/**
+ * Returns the port number.
+ *
+ * @return The port no
+ */
+public int getPort();
+
+/**
+ * Returns the local bind address.
+ * If bindAddress is null, then the system will pick up a valid local
+ * address to bind the socket.
+ *
+ * @return The local bind address
+ * @since 4_14
+ */
+public String getBindAddress();
+
+/**
+ * Returns the type of socket.
+ *
+ * @see #STANDARD_SOCKET
+ * @see #TCP_SOCKET
+ * @return The type of socket
+ */
+public String getTypeSocket();
+
+/**
+ * Returns the IP address string
+ * aaa.bbb.ccc.ddd (IPv4) or a:b:c:d:e:f:g:h (IPv6)
+ * of the host the packets where sent to.
+ *
+ * @return The IP address of the host the packets where sent to.
+ * @see ContextSocketFace#getSendToHostAddress
+ * @since 4_14
+ */
+public String getSendToHostAddress();
+
+/**
+ * Returns the IP address string
+ * aaa.bbb.ccc.ddd (IPv4) or a:b:c:d:e:f:g:h (IPv6)
+ * of the (latest) host the packets where received from.
+ *
+ * @return The IP address of the (latest) host the packets where received from.
+ * @see ContextSocketFace#getReceivedFromHostAddress
+ * @since 4_14
+ */
+public String getReceivedFromHostAddress();
+
+/**
+ * Adds a PDU to the context. This is for internal use only and should
+ * NOT be called by the developer.
+ * This is called by the the Pdu itself and is added to the interface to
+ * cover the different kind of Contexts.
+ *
+ * @param pdu the PDU
+ * @return whether the PDU has been successfully added
+ */
+public boolean addPdu(Pdu pdu)
+throws java.io.IOException, PduException;
+
+/**
+ * Removes a PDU from the context. This is for internal use only and should
+ * NOT be called by the developer.
+ * This is called by the the PDU itself and is added to the interface to
+ * cover the different kind of Contexts.
+ *
+ * @param requestId the PDU request id
+ * @return whether the PDU has been successfully removed
+ */
+public boolean removePdu(int requestId);
+
+/**
+ * Encodes a PDU. This is for internal use only and should
+ * NOT be called by the developer.
+ * This is called by the the PDU itself and is added to the interface to
+ * cover the different kind of Contexts.
+ *
+ * @param msg_type The message type
+ * @param rId The message id
+ * @param errstat The error status
+ * @param errind The error index
+ * @param ve The varbind list
+ * @param obj Additional object (only used in SNMPv3)
+ * @return The encoded packet
+ */
+public byte[] encodePacket(byte msg_type, int rId, int errstat, int errind,
+ java.util.Enumeration ve, Object obj)
+ throws java.io.IOException, EncodingException;
+
+/**
+ * Sends an encoded PDU. This is for internal use only and should
+ * NOT be called by the developer.
+ * This is called by the the PDU itself and is added to the interface to
+ * cover the different kind of Contexts.
+ *
+ * @param packet The encoded packet
+ */
+public void sendPacket(byte[] packet);
+
+/**
+ * Removes the resouces held by this context. Should be called by the
+ * user/developer when the context is no longer needed.
+ */
+public void destroy();
+
+/**
+ * Returns whether or not this context has been destroyed.
+ * @since 4_14
+ */
+public boolean isDestroyed();
+
+/**
+ * Adds the specified trap listener to receive traps on the default trap
+ * port 162 from the host that matches this context.
+ *
+ *
+ * The ListeningContext class will do the actual listening for traps.
+ * This context will add itself to a ListeningContextPool object and
+ * will only pass the event to its listeners if the pdu matches this
+ * context and is a trap pdu.
+ *
+ *
+ * @param l The trap listener
+ * @see #addTrapListener(TrapListener, int)
+ * @see ListeningContextFace#DEFAULT_TRAP_PORT
+ */
+public void addTrapListener(TrapListener l) throws java.io.IOException;
+
+/**
+ * Removes the specified trap listener from listening for packets on
+ * the default trap port 162.
+ *
+ *
+ * The listener will not be removed from all ListeningContext objects
+ * that are in the ListeningContextPool. In order to do that, use
+ * ListeningContextPool.removeTrapListenerFromPool()
+ *
+ *
+ * @param l The trap listener
+ * @see #removeTrapListener(TrapListener, int)
+ * @see ListeningContextFace#DEFAULT_TRAP_PORT
+ */
+public void removeTrapListener(TrapListener l) throws java.io.IOException;
+
+/**
+ * Adds the specified trap listener to receive traps on the specified
+ * port from the host that matches this context.
+ *
+ *
+ * The ListeningContext class will do the actual listening for traps.
+ * This context will add itself to a ListeningContextPool object and
+ * will only pass the event to its listeners if the pdu matches this
+ * context and is a trap pdu.
+ *
+ *
+ * @see ListeningContextPool#ListeningContextPool(int, String, String)
+ * @see ListeningContextPool#addRawPduListener(RawPduListener)
+ *
+ * @param l The trap listener
+ * @param port The port the traps are received on
+ * @since 4_14
+ */
+public void addTrapListener(TrapListener l, int port) throws java.io.IOException;
+
+/**
+ * Removes the specified trap listener from listening for packets on the
+ * specified port.
+ *
+ *
+ * The listener will not be removed from all ListeningContext objects
+ * that are in the ListeningContextPool. In order to do that, use
+ * ListeningContextPool.removeTrapListenerFromPool()
+ *
+ *
+ * @see ListeningContextPool#ListeningContextPool(int, String, String)
+ * @see ListeningContextPool#removeRawPduListener(RawPduListener)
+ * @see ListeningContextPool#removeRawPduListenerFromPool(RawPduListener)
+ *
+ * @param l The trap listener
+ * @param port The port the traps are received on
+ * @since 4_14
+ */
+public void removeTrapListener(TrapListener l, int port) throws java.io.IOException;
+
+/**
+ * Adds the specified trap listener to receive traps on the specified
+ * listening context that matches this context.
+ *
+ *
+ * The ListeningContext class will do the actual listening for traps.
+ * This context will add itself to a ListeningContextPool object and
+ * will only pass the event to its listeners if the pdu matches this
+ * context and is a trap pdu.
+ *
+ *
+ * @see ListeningContextPool#ListeningContextPool(int, String, String)
+ * @see ListeningContextPool#addRawPduListener(RawPduListener)
+ *
+ * @param l The trap listener
+ * @param lcontext The listening context
+ * @since 4_14
+ */
+public void addTrapListener(TrapListener l, ListeningContextPool lcontext) throws java.io.IOException;
+
+/**
+ * Removes the specified trap listener from listening for packets on the
+ * specified listening context.
+ *
+ *
+ * The listener will not be removed from all ListeningContext objects
+ * that are in the ListeningContextPool. In order to do that, use
+ * ListeningContextPool.removeTrapListenerFromPool()
+ *
+ *
+ * @see ListeningContextPool#ListeningContextPool(int, String, String)
+ * @see ListeningContextPool#removeRawPduListener(RawPduListener)
+ * @see ListeningContextPool#removeRawPduListenerFromPool(RawPduListener)
+ *
+ * @param l The trap listener
+ * @param lcontext The listening context
+ * @since 4_14
+ */
+public void removeTrapListener(TrapListener l, ListeningContextPool lcontext) throws java.io.IOException;
+
+/**
+ * Adds the specified request pdu listener to receive PDUs on the
+ * default request pdu port 161 from the host that matches
+ * this context.
+ *
+ *
+ * The ListeningContext class will do the actual listening for PDUs.
+ * This context will add itself to a ListeningContextPool object and
+ * will only pass the event to its listeners if the pdu matches this
+ * context and is a request pdu.
+ *
+ *
+ *
+ * Don't use the TCP_SOCKET when listening for request PDUs. It doesn't
+ * provide functionality to send a response back.
+ *
+ *
+ * @see #addRequestPduListener(RequestPduListener, int)
+ * @see SnmpContextBasisFace#DEFAULT_PORT
+ *
+ * @param l The request PDU listener
+ * @since 4_14
+ */
+public void addRequestPduListener(RequestPduListener l) throws java.io.IOException;
+
+/**
+ * Removes the specified request pdu listener from listening for packets
+ * on the default request pdu port 161.
+ *
+ *
+ * The listener will not be removed from all ListeningContext objects
+ * that are in the ListeningContextPool. In order to do that, use
+ * ListeningContextPool.removeRequestPduListenerFromPool()
+ *
+ *
+ * @see #removeRequestPduListener(RequestPduListener, int)
+ * @see SnmpContextBasisFace#DEFAULT_PORT
+ *
+ * @param l The request PDU listener
+ * @since 4_14
+ */
+public void removeRequestPduListener(RequestPduListener l) throws java.io.IOException;
+
+/**
+ * Adds the specified request pdu listener to receive PDUs on the specified
+ * port from the host that matches this context.
+ *
+ *
+ * The ListeningContext class will do the actual listening for PDUs.
+ * This context will add itself to a ListeningContextPool object and
+ * will only pass the event to its listeners if the pdu matches this
+ * context and is a request pdu.
+ *
+ *
+ *
+ * Don't use the TCP_SOCKET when listening for request PDUs. It doesn't
+ * provide functionality to send a response back.
+ *
+ *
+ * @see ListeningContextPool#ListeningContextPool(int, String, String)
+ * @see ListeningContextPool#addRawPduListener(RawPduListener)
+ *
+ * @param l The request PDU listener
+ * @param port The port the request PDUs are received on
+ * @since 4_14
+ */
+public void addRequestPduListener(RequestPduListener l, int port) throws java.io.IOException;
+
+/**
+ * Removes the specified request pdu listener from listening for packets
+ * on the specified port.
+ *
+ *
+ * The listener will not be removed from all ListeningContext objects
+ * that are in the ListeningContextPool. In order to do that, use
+ * ListeningContextPool.removeRequestPduListenerFromPool()
+ *
+ *
+ * @see ListeningContextPool#ListeningContextPool(int, String, String)
+ * @see ListeningContextPool#removeRawPduListener(RawPduListener)
+ * @see ListeningContextPool#removeRawPduListenerFromPool(RawPduListener)
+ *
+ * @param l The request PDU listener
+ * @param port The port the request PDUs are received on
+ * @since 4_14
+ */
+public void removeRequestPduListener(RequestPduListener l, int port) throws java.io.IOException;
+
+/**
+ * Adds the specified request pdu listener to receive PDUs on the
+ * specified listening context that matches this context.
+ *
+ *
+ * The ListeningContext class will do the actual listening for PDUs.
+ * This context will add itself to a ListeningContextPool object and
+ * will only pass the event to its listeners if the pdu matches this
+ * context and is a request pdu.
+ *
+ *
+ *
+ * Don't use the TCP_SOCKET when listening for request PDUs. It doesn't
+ * provide functionality to send a response back.
+ *
+ *
+ * @see ListeningContextPool#ListeningContextPool(int, String, String)
+ * @see ListeningContextPool#addRawPduListener(RawPduListener)
+ *
+ * @param l The request PDU listener
+ * @param lcontext The listening context
+ * @since 4_14
+ */
+public void addRequestPduListener(RequestPduListener l, ListeningContextPool lcontext) throws java.io.IOException;
+
+/**
+ * Removes the specified request pdu listener from listening for packets
+ * on the specified listening context.
+ *
+ *
+ * The listener will not be removed from all ListeningContext objects
+ * that are in the ListeningContextPool. In order to do that, use
+ * ListeningContextPool.removeRequestPduListenerFromPool()
+ *
+ *
+ * @see ListeningContextPool#ListeningContextPool(int, String, String)
+ * @see ListeningContextPool#removeRawPduListener(RawPduListener)
+ * @see ListeningContextPool#removeRawPduListenerFromPool(RawPduListener)
+ *
+ * @param l The request PDU listener
+ * @param lcontext The listening context
+ * @since 4_14
+ */
+public void removeRequestPduListener(RequestPduListener l, ListeningContextPool lcontext) throws java.io.IOException;
+
+/**
+ * Processes an incoming PDU. The context will try to process the
+ * incoming PDU, using the SNMP version and other security
+ * parameters. If any of these do not correspond, a DecodingException
+ * will be thrown.
+ */
+public Pdu processIncomingPdu(byte [] message)
+throws DecodingException, java.io.IOException;
+
+/**
+ * Returns a clone of this SnmpContext.
+ *
+ * @since 4_14
+ * @exception CloneNotSupportedException Thrown when the constructor
+ * generates an IOException or when in one of the Pool classes.
+ */
+public Object clone() throws CloneNotSupportedException;
+
+/**
+ * Returns the hash key. This key is built out of all properties.
+ *
+ * @since 4_14
+ * @return The hash key
+ */
+public String getHashKey();
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextFace.java b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextFace.java
new file mode 100644
index 0000000..6a9de3b
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextFace.java
@@ -0,0 +1,90 @@
+// NAME
+// $RCSfile: SnmpContextFace.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.13 $
+// CREATED
+// $Date: 2006/02/09 14:19:05 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.event.*;
+
+/**
+ * This interface contains the (basic) SNMP context interface that is needed
+ * by every PDU to send a SNMP v1 request. The context also
+ * provides functionality to receive incoming PDUs.
+ *
+ * @see SnmpContext
+ * @see SnmpContextv2c
+ * @see SnmpContextv3
+ *
+ * @author Tim Panton
+ * @version $Revision: 3.13 $ $Date: 2006/02/09 14:19:05 $
+ */
+public interface SnmpContextFace extends SnmpContextBasisFace
+{
+ static final String version_id =
+ "@(#)$Id: SnmpContextFace.java,v 3.13 2006/02/09 14:19:05 birgit Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * The default community name. This is public.
+ */
+ public final static String DEFAULT_COMMUNITY = "public";
+
+/**
+ * Returns the community name.
+ */
+public String getCommunity();
+
+
+/**
+ * Sets the community name.
+ * This community name will be used for all PDUs sent with this context.
+ * The default community name is public.
+ *
+ * @see #DEFAULT_COMMUNITY
+ */
+public void setCommunity(String newCommunity);
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextPool.java b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextPool.java
new file mode 100644
index 0000000..c821f57
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextPool.java
@@ -0,0 +1,611 @@
+// NAME
+// $RCSfile: SnmpContextPool.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.22 $
+// CREATED
+// $Date: 2009/03/05 13:27:41 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.util.*;
+import uk.co.westhawk.snmp.event.*;
+
+/**
+ * This class contains the pool of SNMP v1 contexts.
+ * This class reuses the existings contexts instead of creating a new
+ * one every time.
+ *
+ * Every time a property changes the pool is checked for a SnmpContext
+ * context that matches all the new properties of this class. If no such
+ * context exists, a new one is made.
+ * The PDUs associated with the old context remain associated with the
+ * old context.
+ *
+ *
+ *
+ * A counter indicates the number of times the context is referenced.
+ * The counter is decreased when destroy()
is called.
+ * When the counter reaches zero, the context is released.
+ *
+ *
+ *
+ * Note that because the underlying context can change when a property
+ * is changed and the PDUs remain associated with the old context, all
+ * properties have to be set BEFORE a PDU is sent.
+ *
+ *
+ *
+ * Thanks to Seon Lee (slee@virtc.com) for reporting thread safety
+ * problems.
+ *
+ *
+ * @see SnmpContext
+ * @see SnmpContextv2cPool
+ * @see SnmpContextv3Pool
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.22 $ $Date: 2009/03/05 13:27:41 $
+ */
+public class SnmpContextPool implements SnmpContextFace
+{
+ private static final String version_id =
+ "@(#)$Id: SnmpContextPool.java,v 3.22 2009/03/05 13:27:41 birgita Exp $ Copyright Westhawk Ltd";
+
+ protected static Hashtable contextPool;
+
+ protected SnmpContext context = null;
+ protected String hostname, socketType, bindAddr;
+ protected int hostPort;
+ protected String community = SnmpContextFace.DEFAULT_COMMUNITY;
+
+/**
+ * Constructor, using the Standard socket.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @see SnmpContext#SnmpContext(String, int)
+ */
+public SnmpContextPool(String host, int port) throws java.io.IOException
+{
+ this(host, port, SnmpContextFace.DEFAULT_COMMUNITY, null, STANDARD_SOCKET);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocket should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @param typeSocket The type of socket to use.
+ *
+ * @see SnmpContext#SnmpContext(String, int, String)
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ */
+public SnmpContextPool(String host, int port, String typeSocket)
+throws java.io.IOException
+{
+ this(host, port, SnmpContextFace.DEFAULT_COMMUNITY, null, typeSocket);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocket should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @since 4_12
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @param comm The community name.
+ * @param typeSocket The type of socket to use.
+ *
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ */
+public SnmpContextPool(String host, int port, String comm, String typeSocket)
+throws java.io.IOException
+{
+ this(host, port, comm, null, typeSocket);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocket should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @param comm The community name.
+ * @param bindAddress The local address the server will bind to
+ * @param typeSocket The type of socket to use.
+ *
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ * @since 4_14
+ */
+public SnmpContextPool(String host, int port, String comm, String bindAddress, String typeSocket)
+throws java.io.IOException
+{
+ initPools();
+ hostname = host;
+ hostPort = port;
+ community = comm;
+ bindAddr = bindAddress;
+ socketType = typeSocket;
+
+ context = getMatchingContext();
+}
+
+private static synchronized void initPools()
+{
+ if (contextPool == null)
+ {
+ contextPool = new Hashtable(5);
+ }
+}
+
+public int getVersion()
+{
+ return SnmpConstants.SNMP_VERSION_1;
+}
+
+public String getHost()
+{
+ return hostname;
+}
+
+public int getPort()
+{
+ return hostPort;
+}
+
+public String getBindAddress()
+{
+ return bindAddr;
+}
+
+public String getTypeSocket()
+{
+ return socketType;
+}
+
+public String getSendToHostAddress()
+{
+ String res = null;
+ if (context != null)
+ {
+ res = context.getSendToHostAddress();
+ }
+ return res;
+}
+
+public String getReceivedFromHostAddress()
+{
+ String res = null;
+ if (context != null)
+ {
+ res = context.getReceivedFromHostAddress();
+ }
+ return res;
+}
+
+
+public String getCommunity()
+{
+ return community;
+}
+
+public void setCommunity(String newCommunity)
+{
+ if (newCommunity != null
+ &&
+ newCommunity.equals(community) == false)
+
+ {
+ community = newCommunity;
+ try
+ {
+ context = getMatchingContext();
+ }
+ catch (java.io.IOException exc) { }
+ }
+}
+
+public boolean addPdu(Pdu pdu)
+throws java.io.IOException, PduException
+{
+ if (context == null)
+ {
+ context = getMatchingContext();
+ }
+ return context.addPdu(pdu);
+}
+
+public boolean removePdu(int requestId)
+{
+ boolean res = false;
+ if (context != null)
+ {
+ res = context.removePdu(requestId);
+ }
+ return res;
+}
+
+/**
+ * Encodes a PDU packet.
+ */
+public byte[] encodePacket(byte msg_type, int rId, int errstat,
+ int errind, Enumeration ve, Object obj)
+ throws java.io.IOException, EncodingException
+{
+ byte[] res = null;
+ if (context != null)
+ {
+ res = context.encodePacket(msg_type, rId, errstat, errind, ve,
+ obj);
+ }
+ return res;
+}
+
+public void sendPacket(byte[] packet)
+{
+ if (context != null)
+ {
+ context.sendPacket(packet);
+ }
+}
+
+/**
+ * Releases the resources held by this context. This method will
+ * decrement the reference counter. When the reference counter reaches
+ * zero the actual context is removed from the pool and destroyed.
+ */
+public void destroy()
+{
+ synchronized(contextPool)
+ {
+ if (context != null)
+ {
+ String hashKey = context.getHashKey();
+
+ int count = 0;
+ SnmpContextPoolItem item = (SnmpContextPoolItem) contextPool.get(hashKey);
+ if (item != null)
+ {
+ count = item.getCounter();
+ count--;
+ item.setCounter(count);
+ }
+
+ if (count <= 0)
+ {
+ contextPool.remove(hashKey);
+ context.destroy();
+ }
+ context = null;
+ }
+ }
+}
+
+
+/**
+ * Destroys all the contexts (v1 and v2c) in the pool and empties the pool.
+ * The underlying implementation uses the same hashtable for both the v1
+ * and the v2c contexts.
+ *
+ * @see #destroy()
+ * @since 4_14
+ */
+public void destroyPool()
+{
+ Hashtable copyOfPool = null;
+
+ synchronized(contextPool)
+ {
+ synchronized(contextPool)
+ {
+ copyOfPool = (Hashtable) contextPool.clone();
+ }
+ contextPool.clear();
+ }
+ context = null;
+
+ Enumeration keys = copyOfPool.keys();
+ while (keys.hasMoreElements())
+ {
+ String key = (String) keys.nextElement();
+ SnmpContextPoolItem item = (SnmpContextPoolItem) copyOfPool.get(key);
+ if (item != null)
+ {
+ SnmpContextBasisFace cntxt = (SnmpContextBasisFace) item.getContext();
+ cntxt.destroy();
+ }
+ }
+ copyOfPool.clear();
+}
+
+
+public boolean isDestroyed()
+{
+ boolean isDestroyed = true;
+ if (context != null)
+ {
+ isDestroyed = context.isDestroyed();
+ }
+ return isDestroyed;
+}
+
+
+/**
+ * Returns a context from the pool.
+ * The pre-existing context (if there is any) is destroyed.
+ * This methods checks for an existing context that matches all our
+ * properties. If such a context does not exist, a new one is created and
+ * added to the pool.
+ *
+ * @return A context from the pool
+ * @see #getHashKey
+ */
+protected SnmpContext getMatchingContext() throws java.io.IOException
+{
+ SnmpContextPoolItem item = null;
+ SnmpContext newContext = null;
+ String hashKey = getHashKey();
+
+ destroy();
+ synchronized(contextPool)
+ {
+ int count=0;
+ if (contextPool.containsKey(hashKey))
+ {
+ item = (SnmpContextPoolItem) contextPool.get(hashKey);
+ newContext = (SnmpContext) item.getContext();
+ count = item.getCounter();
+ }
+ else
+ {
+ newContext = new SnmpContext(hostname, hostPort, bindAddr, socketType);
+ newContext.setCommunity(community);
+ item = new SnmpContextPoolItem(newContext);
+ contextPool.put(hashKey, item);
+ }
+ count++;
+ item.setCounter(count);
+ }
+ return newContext;
+}
+
+/**
+ * Dumps the pool of contexts. This is for debug purposes.
+ * @param title The title of the dump
+ */
+public void dumpContexts(String title)
+{
+ System.out.println(title + " " + contextPool.size() + " context(s)");
+ Enumeration keys = contextPool.keys();
+ int i=0;
+ while (keys.hasMoreElements())
+ {
+ String key = (String) keys.nextElement();
+ SnmpContextPoolItem item = (SnmpContextPoolItem) contextPool.get(key);
+ if (item != null)
+ {
+ int count = item.getCounter();
+ SnmpContext cntxt = (SnmpContext) item.getContext();
+
+ if (cntxt == context)
+ {
+ System.out.println("\tcurrent context: ");
+ }
+ System.out.println("\tcontext " + i + ": " + key + ", count: " + count
+ + ", " + cntxt.toString() + "\n"
+ + ", " + cntxt.getDebugString());
+ i++;
+ }
+ }
+}
+
+/**
+ * Returns the hash key. This key is built out of all properties. It
+ * serves as key for the hashtable of (v1) contexts.
+ *
+ * @return The hash key
+ */
+public String getHashKey()
+{
+ String str = hostname
+ + "_" + hostPort
+ + "_" + bindAddr
+ + "_" + socketType
+ + "_" + community
+ + "_v" + getVersion();
+ return str;
+}
+
+/**
+ * Adds the specified trap listener. The listener will be added to the
+ * current context, not to all the contexts in the hashtable.
+ *
+ * @see SnmpContext#addTrapListener
+ */
+public void addTrapListener(TrapListener l) throws java.io.IOException
+{
+ if (context != null)
+ {
+ context.addTrapListener(l);
+ }
+}
+
+/**
+ * Removes the specified trap listener. The listener will be removed
+ * from the current context, not from all the contexts in the
+ * hashtable.
+ *
+ * @see SnmpContext#removeTrapListener
+ */
+public void removeTrapListener(TrapListener l) throws java.io.IOException
+{
+ if (context != null)
+ {
+ context.removeTrapListener(l);
+ }
+}
+
+public void addTrapListener(TrapListener l, int port) throws java.io.IOException
+{
+ if (context != null)
+ {
+ context.addTrapListener(l, port);
+ }
+}
+public void removeTrapListener(TrapListener l, int port) throws java.io.IOException
+{
+ if (context != null)
+ {
+ context.removeTrapListener(l, port);
+ }
+}
+
+public void addTrapListener(TrapListener l, ListeningContextPool lcontext) throws java.io.IOException
+{
+ if (context != null)
+ {
+ context.addTrapListener(l, lcontext);
+ }
+}
+public void removeTrapListener(TrapListener l, ListeningContextPool lcontext) throws java.io.IOException
+{
+ if (context != null)
+ {
+ context.removeTrapListener(l, lcontext);
+ }
+}
+
+public void addRequestPduListener(RequestPduListener l) throws java.io.IOException
+{
+ if (context != null)
+ {
+ context.addRequestPduListener(l);
+ }
+}
+public void removeRequestPduListener(RequestPduListener l) throws java.io.IOException
+{
+ if (context != null)
+ {
+ context.removeRequestPduListener(l);
+ }
+}
+public void addRequestPduListener(RequestPduListener l, int port) throws java.io.IOException
+{
+ if (context != null)
+ {
+ context.addRequestPduListener(l, port);
+ }
+}
+public void removeRequestPduListener(RequestPduListener l, int port) throws java.io.IOException
+{
+ if (context != null)
+ {
+ context.removeRequestPduListener(l, port);
+ }
+}
+public void addRequestPduListener(RequestPduListener l, ListeningContextPool lcontext) throws java.io.IOException
+{
+ if (context != null)
+ {
+ context.addRequestPduListener(l, lcontext);
+ }
+}
+public void removeRequestPduListener(RequestPduListener l, ListeningContextPool lcontext) throws java.io.IOException
+{
+ if (context != null)
+ {
+ context.removeRequestPduListener(l, lcontext);
+ }
+}
+
+/**
+ * Processes the incoming PDU with the current context.
+ *
+ * @see SnmpContext#processIncomingPdu
+ */
+public Pdu processIncomingPdu(byte [] message)
+throws DecodingException, java.io.IOException
+{
+ Pdu pdu = null;
+ if (context != null)
+ {
+ pdu = context.processIncomingPdu(message);
+ }
+ return pdu;
+}
+
+/**
+ * Returns a string representation of the object.
+ * @return The string
+ */
+public String toString()
+{
+ String res = "";
+ if (context != null)
+ {
+ res = context.toString();
+ }
+ return res;
+}
+
+/**
+ * This method is not supported. It will throw a CloneNotSupportedException.
+ *
+ * @since 4_14
+ */
+public Object clone() throws CloneNotSupportedException
+{
+ throw new CloneNotSupportedException();
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextPoolItem.java b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextPoolItem.java
new file mode 100644
index 0000000..8e778aa
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextPoolItem.java
@@ -0,0 +1,119 @@
+// NAME
+// $RCSfile: SnmpContextPoolItem.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.4 $
+// CREATED
+// $Date: 2006/01/17 17:33:04 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2002 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.util.*;
+import uk.co.westhawk.snmp.event.*;
+
+/**
+ * This class contains one context and one reference counter.
+ * The reference counter
+ * maintains how many objects reference this context.
+ * It is a helper class for the context pools, to improve the
+ * synchronisation.
+ *
+ * @see SnmpContextPool
+ * @see SnmpContextv2cPool
+ * @see SnmpContextv3Pool
+ * @since 4_12
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.4 $ $Date: 2006/01/17 17:33:04 $
+ */
+class SnmpContextPoolItem
+{
+ private static final String version_id =
+ "@(#)$Id: SnmpContextPoolItem.java,v 3.4 2006/01/17 17:33:04 birgit Exp $ Copyright Westhawk Ltd";
+
+ private SnmpContextBasisFace context = null;
+ private int counter = 0;
+
+/**
+ * Constructor.
+ *
+ * @param con The context
+ */
+SnmpContextPoolItem(SnmpContextBasisFace con)
+{
+ context = con;
+ counter = 0;
+}
+
+
+SnmpContextBasisFace getContext()
+{
+ return context;
+}
+
+int getCounter()
+{
+ return counter;
+}
+
+void setCounter(int i)
+{
+ counter = i;
+}
+
+/**
+ * Returns a string representation of the object.
+ * @return The string
+ */
+public String toString()
+{
+ StringBuffer buffer = new StringBuffer("SnmpContextPoolItem[");
+ buffer.append("context=").append(context.toString());
+ buffer.append(", counter=").append(counter);
+ buffer.append("]");
+ return buffer.toString();
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv2c.java b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv2c.java
new file mode 100644
index 0000000..b8a4eec
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv2c.java
@@ -0,0 +1,303 @@
+// NAME
+// $RCSfile: SnmpContextv2c.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.16 $
+// CREATED
+// $Date: 2009/03/05 12:54:04 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2001 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.net.*;
+import java.io.*;
+import java.util.*;
+import uk.co.westhawk.snmp.event.*;
+
+/**
+ * This class contains the SNMP v2c context that is needed by every PDU to
+ * send a SNMP v2c request.
+ *
+ *
+ * destroy()
should be called when the context is no longer
+ * used. This is the only way the threads will be stopped and garbage
+ * collected.
+ *
+ *
+ * @see SnmpContextv2cFace
+ * @see SnmpContextv2cPool
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.16 $ $Date: 2009/03/05 12:54:04 $
+ */
+public class SnmpContextv2c extends SnmpContext
+implements SnmpContextv2cFace, Cloneable
+{
+ private static final String version_id =
+ "@(#)$Id: SnmpContextv2c.java,v 3.16 2009/03/05 12:54:04 birgita Exp $ Copyright Westhawk Ltd";
+
+
+/**
+ * Constructor.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @see AbstractSnmpContext#AbstractSnmpContext(String, int)
+ */
+public SnmpContextv2c(String host, int port) throws IOException
+{
+ super(host, port);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocketA should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the Pdu will be sent
+ * @param port The port where the SNMP server will be
+ * @param typeSocketA The local address the server will bind to
+ *
+ * @see AbstractSnmpContext#AbstractSnmpContext(String, int, String)
+ */
+public SnmpContextv2c(String host, int port, String typeSocketA)
+throws IOException
+{
+ super(host, port, typeSocketA);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocketA should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @param bindAddress The local address the server will bind to
+ * @param typeSocketA The type of socket to use.
+ *
+ * @see AbstractSnmpContext#AbstractSnmpContext(String, int, String, String)
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ * @since 4_14
+ */
+public SnmpContextv2c(String host, int port, String bindAddress, String typeSocketA)
+throws IOException
+{
+ super(host, port, bindAddress, typeSocketA);
+}
+
+public int getVersion()
+{
+ return SnmpConstants.SNMP_VERSION_2c;
+}
+
+
+public byte[] encodePacket(byte msg_type, int rId, int errstat,
+ int errind, Enumeration ve, Object obj)
+ throws IOException, EncodingException
+{
+ byte [] packet = null;
+ if (isDestroyed == true)
+ {
+ throw new EncodingException("Context can no longer be used, since it is already destroyed");
+ }
+ else
+ {
+ AsnEncoderv2c enc = new AsnEncoderv2c();
+ ByteArrayOutputStream bay = enc.EncodeSNMPv2c(this, msg_type, rId, errstat,
+ errind, ve);
+
+ int sz = bay.size();
+ if (sz > maxRecvSize)
+ {
+ throw new EncodingException("Packet size ("+ sz
+ + ") is > maximum size (" + maxRecvSize +")");
+ }
+ packet = bay.toByteArray();
+ }
+ return packet;
+}
+
+/**
+ * Processes an incoming SNMP v2c response.
+ */
+protected void processIncomingResponse(ByteArrayInputStream in)
+throws DecodingException, IOException
+{
+ AsnDecoderv2c rpdu = new AsnDecoderv2c();
+ AsnPduSequence pduSeq = rpdu.DecodeSNMPv2c(in, getCommunity());
+ if (pduSeq != null)
+ {
+ // got a message
+ Integer rid = new Integer(pduSeq.getReqId());
+ Pdu answ = getPdu(rid);
+ if (answ != null)
+ {
+ answ.fillin(pduSeq);
+ }
+ else
+ {
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName() + ".processIncomingResponse(): No Pdu with reqid " + rid.intValue());
+ }
+ }
+ }
+ else
+ {
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName() + ".processIncomingResponse(): Error - missing seq input");
+ }
+ }
+}
+
+public Pdu processIncomingPdu(byte [] message)
+throws DecodingException, IOException
+{
+ AsnDecoderv2c rpdu = new AsnDecoderv2c();
+ ByteArrayInputStream in = new ByteArrayInputStream(message);
+ AsnPduSequence pduSeq = rpdu.DecodeSNMPv2c(in, getCommunity());
+
+ Pdu pdu = null;
+ if (pduSeq != null)
+ {
+ byte type = pduSeq.getRespType();
+ switch (type)
+ {
+ case SnmpConstants.GET_REQ_MSG:
+ pdu = new GetPdu(this);
+ break;
+ case SnmpConstants.GETNEXT_REQ_MSG:
+ pdu = new GetNextPdu(this);
+ break;
+ case SnmpConstants.SET_REQ_MSG:
+ pdu = new SetPdu(this);
+ break;
+ case SnmpConstants.GETBULK_REQ_MSG:
+ pdu = new GetBulkPdu(this);
+ break;
+ case SnmpConstants.INFORM_REQ_MSG:
+ pdu = new InformPdu(this);
+ break;
+ //case SnmpConstants.GET_RSP_MSG:
+ // A longly response should never be received here.
+ // They should come in via the processIncomingResponse
+ // route.
+ //case SnmpConstants.GET_RPRT_MSG:
+ // Reports are part of v3 timeliness communication
+ case SnmpConstants.TRPV2_REQ_MSG:
+ pdu = new TrapPduv2(this);
+ break;
+ default:
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName()
+ + ".ProcessIncomingPdu(): PDU received with type "
+ + pduSeq.getRespTypeString()
+ + ". Ignoring it.");
+ }
+ }
+
+ if (pdu != null)
+ {
+ pdu.fillin(pduSeq);
+ }
+ }
+ return pdu;
+}
+
+/**
+ * Returns a clone of this SnmpContextv2c.
+ *
+ * @exception CloneNotSupportedException Thrown when the constructor
+ * generates an IOException
+ */
+public Object clone() throws CloneNotSupportedException
+{
+ SnmpContextv2c clContext = null;
+ try
+ {
+ clContext = new SnmpContextv2c(hostname, hostPort, bindAddr, typeSocket);
+ clContext.setCommunity(new String(community));
+ }
+ catch (IOException exc)
+ {
+ throw new CloneNotSupportedException("IOException "
+ + exc.getMessage());
+ }
+ return clContext;
+}
+
+/**
+ * Returns the hash key. This key is built out of all properties. It
+ * serves as key for a hashtable of (v2c) contexts.
+ *
+ * @since 4_14
+ * @return The hash key
+ */
+public String getHashKey()
+{
+ return super.getHashKey();
+}
+
+/**
+ * Returns a string representation of the object.
+ *
+ * @return The string
+ */
+public String toString()
+{
+ StringBuffer buffer = new StringBuffer("SnmpContextv2c[");
+ buffer.append("host=").append(hostname);
+ buffer.append(", port=").append(hostPort);
+ buffer.append(", bindAddress=").append(bindAddr);
+ buffer.append(", socketType=").append(typeSocket);
+ buffer.append(", community=").append(community);
+ buffer.append(", #trapListeners=").append(trapSupport.getListenerCount());
+ buffer.append(", #pduListeners=").append(pduSupport.getListenerCount());
+ buffer.append("]");
+ return buffer.toString();
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv2cFace.java b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv2cFace.java
new file mode 100644
index 0000000..9a90f2a
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv2cFace.java
@@ -0,0 +1,67 @@
+// NAME
+// $RCSfile: SnmpContextv2cFace.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.7 $
+// CREATED
+// $Date: 2006/01/17 17:43:54 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * This interface contains the SNMP context interface that is needed by every
+ * PDU to send a SNMP v2c request.
+ *
+ * @see SnmpContext
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.7 $ $Date: 2006/01/17 17:43:54 $
+ */
+public interface SnmpContextv2cFace extends SnmpContextFace
+{
+ static final String version_id =
+ "@(#)$Id: SnmpContextv2cFace.java,v 3.7 2006/01/17 17:43:54 birgit Exp $ Copyright Westhawk Ltd";
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv2cPool.java b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv2cPool.java
new file mode 100644
index 0000000..ae74a70
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv2cPool.java
@@ -0,0 +1,211 @@
+// NAME
+// $RCSfile: SnmpContextv2cPool.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.15 $
+// CREATED
+// $Date: 2009/03/05 13:27:41 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.util.*;
+
+/**
+ * This class contains the pool of SNMP v2c contexts.
+ * It extends the SnmpContextPool and is similar in every way, except it
+ * uses a pool of SnmpContextv2c.
+ *
+ *
+ * Thanks to Seon Lee (slee@virtc.com) for reporting thread safety
+ * problems.
+ *
+ *
+ * @see SnmpContextv2c
+ * @see SnmpContextPool
+ * @see SnmpContextv3Pool
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.15 $ $Date: 2009/03/05 13:27:41 $
+ */
+public class SnmpContextv2cPool extends SnmpContextPool
+ implements SnmpContextv2cFace
+{
+ private static final String version_id =
+ "@(#)$Id: SnmpContextv2cPool.java,v 3.15 2009/03/05 13:27:41 birgita Exp $ Copyright Westhawk Ltd";
+
+
+/**
+ * Constructor.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @see SnmpContextv2c#SnmpContextv2c(String, int)
+ */
+public SnmpContextv2cPool(String host, int port) throws java.io.IOException
+{
+ super(host, port, STANDARD_SOCKET);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocket should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @param typeSocket The type of socket to use.
+ *
+ * @see SnmpContextv2c#SnmpContextv2c(String, int, String)
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ */
+public SnmpContextv2cPool(String host, int port, String typeSocket)
+throws java.io.IOException
+{
+ super(host, port, typeSocket);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocket should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @param comm The community name.
+ * @param typeSocket The type of socket to use.
+ *
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ *
+ * @since 4_14
+ */
+public SnmpContextv2cPool(String host, int port, String comm, String typeSocket)
+throws java.io.IOException
+{
+ super(host, port, comm, null, typeSocket);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocket should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @param comm The community name.
+ * @param bindAddress The local address the server will bind to
+ * @param typeSocket The type of socket to use.
+ *
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ *
+ * @since 4_14
+ */
+public SnmpContextv2cPool(String host, int port, String comm, String bindAddress, String typeSocket)
+throws java.io.IOException
+{
+ super(host, port, comm, bindAddress, typeSocket);
+}
+
+public int getVersion()
+{
+ return SnmpConstants.SNMP_VERSION_2c;
+}
+
+/**
+ * Returns a v2c context from the pool.
+ * The pre-existing context (if there is any) is destroyed.
+ * This methods checks for an existing context that matches all our
+ * properties. If such a context does not exist, a new one is created and
+ * added to the pool.
+ *
+ * This method actually returns a SnmpContextv2c, although it doesn't
+ * look like it.
+ *
+ * @return A context (v2c) from the pool
+ * @see #getHashKey
+ * @see SnmpContext
+ * @see SnmpContextv2c
+ */
+protected SnmpContext getMatchingContext() throws java.io.IOException
+{
+ SnmpContextPoolItem item = null;
+ SnmpContextv2c newContext = null;
+ String hashKey = getHashKey();
+
+ destroy();
+ synchronized(contextPool)
+ {
+ int count=0;
+ if (contextPool.containsKey(hashKey))
+ {
+ item = (SnmpContextPoolItem) contextPool.get(hashKey);
+ newContext = (SnmpContextv2c) item.getContext();
+ count = item.getCounter();
+ }
+ else
+ {
+ newContext = new SnmpContextv2c(hostname, hostPort, bindAddr, socketType);
+ newContext.setCommunity(community);
+ item = new SnmpContextPoolItem(newContext);
+ contextPool.put(hashKey, item);
+ }
+ count++;
+ item.setCounter(count);
+ }
+ return newContext;
+}
+
+/**
+ * This method is not supported. It will throw a CloneNotSupportedException.
+ *
+ * @since 4_14
+ */
+public Object clone() throws CloneNotSupportedException
+{
+ throw new CloneNotSupportedException();
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv3.java b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv3.java
new file mode 100644
index 0000000..ca49bcc
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv3.java
@@ -0,0 +1,498 @@
+// NAME
+// $RCSfile: SnmpContextv3.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.31 $
+// CREATED
+// $Date: 2009/03/05 13:12:50 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.net.*;
+import java.io.*;
+import java.util.*;
+
+import uk.co.westhawk.snmp.pdu.*;
+import uk.co.westhawk.snmp.util.*;
+import uk.co.westhawk.snmp.event.*;
+import uk.co.westhawk.snmp.beans.*;
+
+/**
+ * This class contains the SNMP v3 context that is needed by every PDU to
+ * send a SNMP v3 request.
+ * Most of the work is done by SnmpContextv3Basis, like doing discovery.
+ *
+ *
+ * Now that the stack can send traps and receive requests,
+ * it needs to be able to act as an
+ * authoritative SNMP engine. This is done via the interface UsmAgent.
+ * The DefaultUsmAgent is not guaranteed to work; agents (or rather
+ * authoritative engines) should provide a better implementation.
+ *
+ *
+ *
+ * This class adds a UsmBeingDiscoveredBean as listener. This bean
+ * handles any incoming discovery PDU. Only when acting as
+ * authoritative engine should there be any discovery PDU.
+ *
+ *
+ * @see SnmpContextv3Face
+ * @see SnmpContextv3Pool
+ * @see TimeWindow
+ * @see DefaultUsmAgent
+ * @see UsmAgent
+ * @see #setUsmAgent(UsmAgent)
+ * @see UsmDiscoveryBean
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.31 $ $Date: 2009/03/05 13:12:50 $
+ */
+public class SnmpContextv3 extends SnmpContextv3Basis
+{
+ private static final String version_id =
+ "@(#)$Id: SnmpContextv3.java,v 3.31 2009/03/05 13:12:50 birgita Exp $ Copyright Westhawk Ltd";
+
+ private UsmBeingDiscoveredBean myDiscBean = null;
+
+/**
+ * Constructor.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @see AbstractSnmpContext#AbstractSnmpContext(String, int)
+ */
+public SnmpContextv3(String host, int port) throws IOException
+{
+ super(host, port);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocketA should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the Pdu will be sent
+ * @param port The port where the SNMP server will be
+ * @param typeSocketA The local address the server will bind to
+ *
+ * @see AbstractSnmpContext#AbstractSnmpContext(String, int, String)
+ */
+public SnmpContextv3(String host, int port, String typeSocketA)
+throws IOException
+{
+ super(host, port, typeSocketA);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocketA should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @param bindAddress The local address the server will bind to
+ * @param typeSocketA The type of socket to use.
+ *
+ * @see AbstractSnmpContext#AbstractSnmpContext(String, int, String, String)
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ * @since 4_14
+ */
+public SnmpContextv3(String host, int port, String bindAddress, String typeSocketA)
+throws IOException
+{
+ super(host, port, bindAddress, typeSocketA);
+}
+
+
+/**
+ * Makes sure the UsmBeingDiscoveredBean is added as RequestPduListener,
+ * so that discovery requests are handled. When listening for incoming
+ * requests, the stack become authoritative. You have (!) to create a
+ * proper usmAgent so the stack can be discovered.
+ *
+ *
+ * Don't use the TCP_SOCKET when listening for request PDUs. It doesn't
+ * provide functionality to send a response back.
+ *
+ *
+ * @see #removeRequestPduListener(RequestPduListener, ListeningContextPool)
+ * @see UsmBeingDiscoveredBean
+ * @see SnmpContextv3Basis#setUsmAgent(UsmAgent)
+ *
+ * @param l The request PDU listener
+ * @param lcontext The listening context
+ */
+public void addRequestPduListener(RequestPduListener l, ListeningContextPool lcontext)
+throws IOException
+{
+ super.addRequestPduListener(l, lcontext);
+
+ if (myDiscBean == null)
+ {
+ myDiscBean = new UsmBeingDiscoveredBean(this, usmAgent);
+ }
+ myDiscBean.addRequestPduListener(lcontext);
+}
+
+
+/**
+ * Removes the UsmBeingDiscoveredBean as listener.
+ *
+ * @see #addRequestPduListener(RequestPduListener, ListeningContextPool)
+ *
+ * @param l The request PDU listener
+ * @param lcontext The listening context
+ */
+public void removeRequestPduListener(RequestPduListener l, ListeningContextPool lcontext)
+throws IOException
+{
+ super.removeRequestPduListener(l, lcontext);
+ if (myDiscBean != null)
+ {
+ myDiscBean.removeRequestPduListener(lcontext);
+ myDiscBean.freeResources();
+ myDiscBean = null;
+ }
+}
+
+
+/**
+ * Processes an incoming PDU, that is not a Discovery PDU.
+ *
+ * See SNMP-USER-BASED-SM-MIB.
+ *
+ *
+ *
+ * This method calls first processPotentialTrap and then
+ * processPotentialRequest. The reason this code is split up is because
+ * in one case the stack acts as authoritative engine and as non
+ * authoritative engine in the other..
+ *
+ *
+ * @see #rawPduReceived
+ * @see #processPotentialTrap
+ * @see #processPotentialRequest
+ */
+public Pdu processIncomingPdu(byte [] message)
+throws DecodingException, IOException
+{
+ String msg = checkContextSanity();
+ if (msg != null)
+ {
+ throw new DecodingException(msg);
+ }
+ int l = message.length;
+ byte [] copyOfMessage1 = new byte[l];
+ byte [] copyOfMessage2 = new byte[l];
+ System.arraycopy(message, 0, copyOfMessage1, 0, l);
+ System.arraycopy(message, 0, copyOfMessage2, 0, l);
+
+ AsnDecoderv3 rpdu = new AsnDecoderv3();
+ ByteArrayInputStream in = new ByteArrayInputStream(message);
+ AsnSequence asnTopSeq = rpdu.DecodeSNMPv3(in);
+ int msgId = rpdu.getMsgId(asnTopSeq);
+
+ Pdu pdu = null;
+
+ DecodingException encryptionDecodingException1 = null;
+ IOException encryptionIOException1 = null;
+ try
+ {
+ pdu = processPotentialTrap(rpdu, asnTopSeq, copyOfMessage1);
+ }
+ catch(DecodingException exc)
+ {
+ encryptionDecodingException1 = exc;
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName()
+ + ".processPotentialTrap(): DecodingException: "
+ + exc.getMessage());
+ }
+ }
+ catch(IOException exc)
+ {
+ encryptionIOException1 = exc;
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName()
+ + ".processPotentialTrap(): IOException: "
+ + exc.getMessage());
+ }
+ }
+
+ DecodingException encryptionDecodingException2 = null;
+ IOException encryptionIOException2 = null;
+ if (pdu == null)
+ {
+ try
+ {
+ pdu = processPotentialRequest(rpdu, asnTopSeq, copyOfMessage2);
+ }
+ catch(DecodingException exc)
+ {
+ encryptionDecodingException2 = exc;
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName()
+ + ".processPotentialRequest(): DecodingException: "
+ + exc.getMessage());
+ }
+ }
+ catch(IOException exc)
+ {
+ encryptionIOException2 = exc;
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName()
+ + ".processPotentialRequest(): IOException: "
+ + exc.getMessage());
+ }
+ }
+ }
+
+
+ if (pdu != null)
+ {
+ pdu.snmpv3MsgId = new Integer(msgId);
+ }
+ else
+ {
+ if (encryptionIOException2 != null)
+ {
+ throw encryptionIOException2;
+ }
+ if (encryptionDecodingException2 != null)
+ {
+ throw encryptionDecodingException2;
+ }
+ if (encryptionIOException1 != null)
+ {
+ throw encryptionIOException1;
+ }
+ if (encryptionDecodingException1 != null)
+ {
+ throw encryptionDecodingException1;
+ }
+ }
+ return pdu;
+}
+
+
+/**
+ * Processes an incoming PDU, to see if it is a Trap.
+ * This method is called by processIncomingPdu.
+ *
+ * When receiving traps the stack is non authoritative.
+ *
+ * @see #processIncomingPdu
+ * @see #processPotentialRequest
+ * @since 4_14
+ */
+public Pdu processPotentialTrap(AsnDecoderv3 rpdu, AsnSequence asnTopSeq,
+ byte [] message)
+throws DecodingException, IOException
+{
+ // decode as Non Authoratative engine
+ AsnPduSequence pduSeq = rpdu.processSNMPv3(this, asnTopSeq, message, false);
+ Pdu pdu = null;
+ if (pduSeq != null)
+ {
+ byte type = pduSeq.getRespType();
+ if (type == SnmpConstants.TRPV2_REQ_MSG)
+ {
+ pdu = new TrapPduv2(this);
+ pdu.fillin(pduSeq);
+
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName()
+ + ".processPotentialTrap(): PDU received with type "
+ + pduSeq.getRespTypeString()
+ + ". Not ignoring it!");
+ }
+ }
+ else
+ {
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName()
+ + ".processPotentialTrap(): PDU received is not TRPV2_REQ_MSG"
+ + ". Ignoring it.");
+ }
+ }
+ }
+ else
+ {
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName()
+ + ".processPotentialTrap(): pduSeq == null"
+ + ". Ignoring it.");
+ }
+ }
+ return pdu;
+}
+
+
+/**
+ * Processes an incoming PDU, to see if it is a Request.
+ * This method is called by processIncomingPdu.
+ *
+ * When receiving pdu requests the stack is authoritative.
+ *
+ * @see #processIncomingPdu
+ * @see #processPotentialTrap
+ * @since 4_14
+ */
+public Pdu processPotentialRequest(AsnDecoderv3 rpdu, AsnSequence asnTopSeq,
+ byte [] message)
+throws DecodingException, IOException
+{
+ // decode as Authoratative engine
+ AsnPduSequence pduSeq = rpdu.processSNMPv3(this, asnTopSeq, message, true);
+ Pdu pdu = null;
+ if (pduSeq != null)
+ {
+ byte type = pduSeq.getRespType();
+ if (type == SnmpConstants.GET_REQ_MSG && pduSeq.isSnmpv3Discovery() == true)
+ {
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName()
+ + ".ProcessIncomingPdu(): received discovery pdu"
+ + ". Ignoring it.");
+ }
+ }
+ else
+ {
+ switch (type)
+ {
+ case SnmpConstants.GET_REQ_MSG:
+ pdu = new GetPdu(this);
+ pdu.fillin(pduSeq);
+ break;
+ case SnmpConstants.GETNEXT_REQ_MSG:
+ pdu = new GetNextPdu(this);
+ pdu.fillin(pduSeq);
+ break;
+ case SnmpConstants.SET_REQ_MSG:
+ pdu = new SetPdu(this);
+ pdu.fillin(pduSeq);
+ break;
+ case SnmpConstants.GETBULK_REQ_MSG:
+ pdu = new GetBulkPdu(this);
+ pdu.fillin(pduSeq);
+ break;
+ case SnmpConstants.INFORM_REQ_MSG:
+ pdu = new InformPdu(this);
+ pdu.fillin(pduSeq);
+ break;
+ //case SnmpConstants.GET_RSP_MSG:
+ // A lonely response should never be received here.
+ // They should come in via the processIncomingResponse
+ // route.
+ //case SnmpConstants.GET_RPRT_MSG:
+ // Reports are part of v3 timeliness communication.
+ //case SnmpConstants.TRPV2_REQ_MSG:
+ // Traps should have been decoded in
+ // processPotentialTrap() above
+ default:
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName()
+ + ".processPotentialRequest(): PDU received with type "
+ + pduSeq.getRespTypeString()
+ + ". Ignoring it.");
+ }
+ }
+
+ if (pdu != null)
+ {
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName()
+ + ".processPotentialRequest(): PDU received with type "
+ + pduSeq.getRespTypeString()
+ + ". Not ignoring it!");
+ }
+ }
+ }
+ }
+ else
+ {
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName()
+ + "..processPotentialRequest(): pduSeq == null"
+ + ". Ignoring it.");
+ }
+ }
+ return pdu;
+}
+
+
+/**
+ * Returns a clone of this SnmpContextv3.
+ *
+ * @exception CloneNotSupportedException Thrown when the constructor
+ * generates an IOException
+ */
+public Object clone() throws CloneNotSupportedException
+{
+ SnmpContextv3 clContext = null;
+ try
+ {
+ clContext = new SnmpContextv3(hostname, hostPort, bindAddr, typeSocket);
+ clContext = (SnmpContextv3) cloneParameters(clContext);
+ }
+ catch (IOException exc)
+ {
+ throw new CloneNotSupportedException("IOException "
+ + exc.getMessage());
+ }
+ return clContext;
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv3Basis.java b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv3Basis.java
new file mode 100644
index 0000000..9eac387
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv3Basis.java
@@ -0,0 +1,1159 @@
+// NAME
+// $RCSfile: SnmpContextv3Basis.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.17 $
+// CREATED
+// $Date: 2009/03/05 15:51:42 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.net.*;
+import java.io.*;
+import java.util.*;
+
+import uk.co.westhawk.snmp.pdu.*;
+import uk.co.westhawk.snmp.util.*;
+import uk.co.westhawk.snmp.event.*;
+import uk.co.westhawk.snmp.beans.*;
+
+/**
+ * This class contains the basis for the SNMP v3 contexts that is needed
+ * by every PDU to send a SNMP v3 request.
+ *
+ *
+ * This class will perform the v3 discovery of the SNMP engine ID and
+ * time line if necessary. This is done with the classes
+ * TimeWindow
and UsmDiscoveryBean
.
+ *
+ *
+ *
+ * Now that the stack can send traps and receive requests,
+ * it needs to be able to act as an
+ * authoritative SNMP engine. This is done via the interface UsmAgent.
+ * The DefaultUsmAgent is not guaranteed to work; agents (or rather
+ * authoritative engines) should provide a better implementation.
+ *
+ *
+ *
+ * This class will use the User Security Model (USM) as described in
+ * SNMP-USER-BASED-SM-MIB.
+ * See also RFC 3411.
+ *
+ *
+ *
+ * It is advised to set all the properties of this class before any PDU,
+ * using this class, is sent.
+ * All properties are being used to encode the message. Some properties are
+ * being used to decode the Response or Report PDU.
+ * When any of these last properties were changed in between flight there
+ * is a possibility the decoding fails, causing a
+ * DecodingException
.
+ *
+ *
+ *
+ * destroy()
should be called when the context is no longer
+ * used. This is the only way the threads will be stopped and garbage
+ * collected.
+ *
+ *
+ * @see SnmpContextv3Face
+ * @see SnmpContextv3Pool
+ * @see TimeWindow
+ * @see UsmAgent
+ * @see DefaultUsmAgent
+ * @see #setUsmAgent(UsmAgent)
+ * @see UsmDiscoveryBean
+ *
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.17 $ $Date: 2009/03/05 15:51:42 $
+ */
+public abstract class SnmpContextv3Basis extends AbstractSnmpContext
+implements SnmpContextv3Face, Cloneable
+{
+ private static final String version_id =
+ "@(#)$Id: SnmpContextv3Basis.java,v 3.17 2009/03/05 15:51:42 birgita Exp $ Copyright Westhawk Ltd";
+
+ protected String userName = Default_UserName;
+ protected boolean useAuthentication = false;
+ protected String userAuthenticationPassword;
+ protected byte[] userAuthKeyMD5 = null;
+ protected byte[] userAuthKeySHA1 = null;
+ protected int authenticationProtocol = MD5_PROTOCOL;
+ protected int privacyProtocol = DES_ENCRYPT ;
+ protected boolean usePrivacy = false;
+ protected String userPrivacyPassword;
+ protected byte[] userPrivKeyMD5 = null;
+ protected byte[] userPrivKeySHA1 = null;
+ protected byte [] contextEngineId = new byte[0];
+ protected String contextName = Default_ContextName;
+ protected UsmAgent usmAgent = null;
+
+ private Hashtable msgIdHash = new Hashtable(MAXPDU);
+ private static int next_id = 1;
+
+/**
+ * Constructor.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @see AbstractSnmpContext#AbstractSnmpContext(String, int)
+ */
+public SnmpContextv3Basis(String host, int port) throws IOException
+{
+ this(host, port, null, STANDARD_SOCKET);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocketA should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the Pdu will be sent
+ * @param port The port where the SNMP server will be
+ * @param typeSocketA The local address the server will bind to
+ *
+ * @see AbstractSnmpContext#AbstractSnmpContext(String, int, String)
+ */
+public SnmpContextv3Basis(String host, int port, String typeSocketA)
+throws IOException
+{
+ this(host, port, null, typeSocketA);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocketA should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @param bindAddress The local address the server will bind to
+ * @param typeSocketA The type of socket to use.
+ *
+ * @see AbstractSnmpContext#AbstractSnmpContext(String, int, String)
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ * @since 4_14
+ */
+public SnmpContextv3Basis(String host, int port, String bindAddress, String typeSocketA)
+throws IOException
+{
+ super(host, port, bindAddress, typeSocketA);
+
+ if (TimeWindow.getCurrent() == null)
+ {
+ TimeWindow timew = new TimeWindow();
+ }
+ setUsmAgent(createUsmAgent());
+}
+
+public int getVersion()
+{
+ return SnmpConstants.SNMP_VERSION_3;
+}
+
+/**
+ * Returns the username.
+ *
+ * @return the username
+ */
+public String getUserName()
+{
+ return userName;
+}
+
+/**
+ * Sets the username.
+ * This username will be used for all PDUs sent with this context.
+ * The username corresponds to the 'msgUserName' in
+ * SNMP-USER-BASED-SM-MIB.
+ * The default value is "initial".
+ *
+ * @param newUserName The new username
+ * @see #Default_UserName
+ */
+public void setUserName(String newUserName)
+{
+ userName = newUserName;
+}
+
+/**
+ * Returns if authentication is used or not.
+ * By default no authentication will be used.
+ *
+ * @return true if authentication is used, false if not
+ */
+public boolean isUseAuthentication()
+{
+ return useAuthentication;
+}
+
+/**
+ * Sets whether authentication has to be used.
+ * By default no authentication will be used.
+ *
+ * @param newUseAuthentication The use of authentication
+ */
+public void setUseAuthentication(boolean newUseAuthentication)
+{
+ useAuthentication = newUseAuthentication;
+}
+
+/**
+ * Returns the user authentication password.
+ * This password will be transformed into the user authentication secret key.
+ *
+ * @return The user authentication password
+ */
+public String getUserAuthenticationPassword()
+{
+ return userAuthenticationPassword;
+}
+
+/**
+ * Sets the user authentication password.
+ * This password will be transformed into the user authentication secret
+ * key. A user MUST set this password.
+ *
+ * @param newUserAuthPassword The user authentication password
+ */
+public void setUserAuthenticationPassword(String newUserAuthPassword)
+{
+ if (newUserAuthPassword != null
+ &&
+ newUserAuthPassword.equals(userAuthenticationPassword) == false)
+ {
+ userAuthenticationPassword = newUserAuthPassword;
+ userAuthKeyMD5 = null;
+ userAuthKeySHA1 = null;
+ }
+}
+
+/**
+ * Sets the protocol to be used for authentication.
+ * This can either be MD5 or SHA-1.
+ * By default MD5 will be used.
+ *
+ * @param protocol The authentication protocol to be used
+ * @see #MD5_PROTOCOL
+ * @see #SHA1_PROTOCOL
+ */
+public void setAuthenticationProtocol(int protocol)
+throws IllegalArgumentException
+{
+ if (protocol == MD5_PROTOCOL || protocol == SHA1_PROTOCOL)
+ {
+ if (protocol != authenticationProtocol)
+ {
+ authenticationProtocol = protocol;
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("Authentication Protocol "
+ + "should be MD5 or SHA1");
+ }
+}
+
+/**
+ * Returns the protocol to be used for authentication.
+ * This can either be MD5 or SHA-1.
+ * By default MD5 will be used.
+ *
+ * @return The authentication protocol to be used
+ * @see #MD5_PROTOCOL
+ * @see #SHA1_PROTOCOL
+ */
+public int getAuthenticationProtocol()
+{
+ return authenticationProtocol;
+}
+
+/**
+ * Sets the protocol to be used for privacy.
+ * This can either be DES or AES.
+ * By default DES will be used.
+ *
+ * @param protocol The privacy protocol to be used
+ * @see SnmpContextv3Face#AES_ENCRYPT
+ * @see SnmpContextv3Face#DES_ENCRYPT
+ */
+public void setPrivacyProtocol(int protocol)
+throws IllegalArgumentException
+{
+ if (protocol == DES_ENCRYPT || protocol == AES_ENCRYPT)
+ {
+ if (protocol != privacyProtocol)
+ {
+ privacyProtocol = protocol;
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("Privacy Encryption "
+ + "should be AES or DES");
+ }
+}
+
+/**
+ * Returns the protocol to be used for privacy.
+ * This can either be DES or AES.
+ * By default DES will be used.
+ *
+ * @return The privacy protocol to be used
+ * @see SnmpContextv3Face#AES_ENCRYPT
+ * @see SnmpContextv3Face#DES_ENCRYPT
+ */
+public int getPrivacyProtocol()
+{
+ return privacyProtocol;
+}
+
+byte[] getAuthenticationPasswordKeyMD5()
+{
+ if (userAuthKeyMD5 == null)
+ {
+ userAuthKeyMD5 = SnmpUtilities.passwordToKeyMD5(userAuthenticationPassword);
+ }
+ return userAuthKeyMD5;
+}
+
+byte[] getAuthenticationPasswordKeySHA1()
+{
+ if (userAuthKeySHA1 == null)
+ {
+ userAuthKeySHA1 = SnmpUtilities.passwordToKeySHA1(userAuthenticationPassword);
+ }
+ return userAuthKeySHA1;
+}
+
+
+byte[] getPrivacyPasswordKeyMD5()
+{
+ if (userPrivKeyMD5 == null)
+ {
+ userPrivKeyMD5 = SnmpUtilities.passwordToKeyMD5(userPrivacyPassword);
+ }
+ return userPrivKeyMD5;
+}
+
+byte[] getPrivacyPasswordKeySHA1()
+{
+ if (userPrivKeySHA1 == null)
+ {
+ userPrivKeySHA1 = SnmpUtilities.passwordToKeySHA1(userPrivacyPassword);
+ }
+ return userPrivKeySHA1;
+}
+
+
+/**
+ * Returns if privacy is used or not.
+ * By default privacy is not used.
+ *
+ * @return true if privacy is used, false if not
+ */
+public boolean isUsePrivacy()
+{
+ return usePrivacy;
+}
+
+/**
+ * Sets whether privacy has to be used.
+ * By default privacy is not used.
+ * Note, privacy (encryption) without authentication is not allowed.
+ *
+ * @param newUsePrivacy The use of privacy
+ */
+public void setUsePrivacy(boolean newUsePrivacy)
+{
+ usePrivacy = newUsePrivacy;
+}
+
+/**
+ * Returns the user privacy password.
+ * This password will be transformed into the user privacy secret key.
+ *
+ * @return The user privacy password
+ */
+public String getUserPrivacyPassword()
+{
+ return userPrivacyPassword;
+}
+
+
+/**
+ * Sets the user privacy password.
+ * This password will be transformed into the user privacy secret
+ * key. A user must set this password in order to use privacy.
+ *
+ * @param newUserPrivacyPassword The user privacy password
+ */
+public void setUserPrivacyPassword(String newUserPrivacyPassword)
+{
+ if (newUserPrivacyPassword != null
+ &&
+ newUserPrivacyPassword.equals(userPrivacyPassword) == false)
+ {
+ userPrivacyPassword = newUserPrivacyPassword;
+ userPrivKeyMD5 = null;
+ userPrivKeySHA1 = null;
+ }
+}
+
+
+/**
+ * Sets the contextEngineID.
+ * See RFC 3411.
+ *
+ * A contextEngineID uniquely
+ * identifies an SNMP entity that may realize an instance of a context
+ * with a particular contextName.
+ *
+ *
+ * Note, when the stack is an authoritative engine, this parameter should
+ * equal the UsmAgent.getSnmpEngineId(). See the StackUsage
+ * documentation for an explanation.
+ *
+ *
+ *
+ * If the contextEngineID is of length zero, the encoder will use the (discovered)
+ * snmpEngineId.
+ *
+ *
+ * @see UsmAgent#getSnmpEngineId()
+ * @param newContextEngineId The contextEngineID
+ */
+public void setContextEngineId(byte [] newContextEngineId)
+throws IllegalArgumentException
+{
+ if (newContextEngineId != null)
+ {
+ contextEngineId = newContextEngineId;
+ }
+ else
+ {
+ throw new IllegalArgumentException("contextEngineId is null");
+ }
+}
+
+/**
+ * Returns the contextEngineID.
+ *
+ * @return The contextEngineID
+ */
+public byte [] getContextEngineId()
+{
+ return contextEngineId;
+}
+
+/**
+ * Sets the contextName.
+ * See RFC 3411.
+ *
+ * A contextName is used to name a context. Each contextName MUST be
+ * unique within an SNMP entity.
+ * By default this is "" (the empty String).
+ *
+ * @param newContextName The contextName
+ * @see #Default_ContextName
+ */
+public void setContextName(String newContextName)
+{
+ contextName = newContextName;
+}
+
+/**
+ * Returns the contextName.
+ *
+ * @return The contextName
+ */
+public String getContextName()
+{
+ return contextName;
+}
+
+/**
+ * Adds a discovery pdu. This method adds the PDU (without checking if
+ * discovery is needed).
+ *
+ * @param pdu the discovery pdu
+ * @return pdu is succesful added
+ * @see AbstractSnmpContext#addPdu(Pdu)
+ * @see #addPdu(Pdu)
+ */
+public boolean addDiscoveryPdu(DiscoveryPdu pdu)
+throws IOException, PduException
+{
+ // since this is a DiscoveryPdu we do not check for discovery :-)
+ return this.addPdu(pdu, false);
+}
+
+/**
+ * Adds a PDU. This method adds the PDU and blocks until it has all the
+ * discovery parameters it needs.
+ *
+ * @param pdu the PDU
+ * @return pdu is succesful added
+ * @see AbstractSnmpContext#addPdu(Pdu)
+ * @see #addDiscoveryPdu(DiscoveryPdu)
+ */
+public boolean addPdu(Pdu pdu)
+throws IOException, PduException
+{
+ return this.addPdu(pdu, true);
+}
+
+/**
+ * Creates the USM agent.
+ * @see DefaultUsmAgent
+ * @see #isAuthoritative
+ */
+protected UsmAgent createUsmAgent()
+{
+ return new DefaultUsmAgent();
+}
+
+/**
+ * Sets the UsmAgent, needed when this stack is used as authoritative
+ * SNMP engine. This interface provides authentiation details, like its
+ * clock and its Engine ID.
+ *
+ * @see DefaultUsmAgent
+ * @param agent The USM authoritative interface
+ * @since 4_14
+ */
+public void setUsmAgent(UsmAgent agent)
+{
+ usmAgent = agent;
+}
+
+/**
+ * Returns the UsmAgent.
+ * @see #setUsmAgent
+ * @since 4_14
+ */
+public UsmAgent getUsmAgent()
+{
+ return usmAgent;
+}
+
+/**
+ * Adds a PDU. This method adds the PDU and checks if discovery is
+ * needed depending on the parameter checkDiscovery
.
+ * If discovery is needed this method will block until it has done so.
+ * Discovery is only needed if the stack is non authoritative.
+ *
+ *
+ * This method stores the SNMPv3 msgId and PDU
+ * request id in a Hashtable.
+ * Since the encoding only happens once and every retry sends the same
+ * encoded packet, only one msgId is used.
+ *
+ *
+ * @param pdu the PDU
+ * @param checkDiscovery check if discovery is needed
+ * @return pdu is succesful added
+ * @see AbstractSnmpContext#addPdu(Pdu)
+ * @see #addDiscoveryPdu(DiscoveryPdu)
+ * @see #addPdu(Pdu)
+ */
+protected boolean addPdu(Pdu pdu, boolean checkDiscovery)
+throws IOException, PduException
+{
+ // TODO, when sending response or report, the msgId should be set!
+ Integer msgId = pdu.snmpv3MsgId;
+ if (msgId == null)
+ {
+ msgId = new Integer(next_id++);
+ }
+ else if (pdu.isExpectingResponse() == true)
+ {
+ // generate a new msgId, even if this is already set. The user
+ // could be adding the same PDU more than once to the
+ // context.
+ msgId = new Integer(next_id++);
+ }
+ pdu.snmpv3MsgId = msgId;
+
+ msgIdHash.put(msgId, new Integer(pdu.req_id));
+ if (AsnObject.debug > 6)
+ {
+ System.out.println(getClass().getName() + ".addPdu(): msgId="
+ + msgId.toString() + ", Pdu reqId=" + pdu.req_id);
+ }
+
+ if (checkDiscovery == true && isAuthoritative(pdu.getMsgType()) == false)
+ {
+ discoverIfNeeded(pdu);
+ }
+
+ boolean added = super.addPdu(pdu);
+ return added;
+}
+
+/**
+ * Removes a PDU. This removes the PDU from the AbstractSnmpContext and
+ * clears the link with the SNMPv3 msgId.
+ *
+ * @param rid the PDU request id
+ * @return whether the PDU has been successfully removed
+ * @see AbstractSnmpContext#removePdu(int)
+ */
+public synchronized boolean removePdu(int rid)
+{
+ boolean removed = super.removePdu(rid);
+ if (removed)
+ {
+ Enumeration keys = msgIdHash.keys();
+ Integer msgIdI = null;
+ boolean found = false;
+ while (keys.hasMoreElements() && found == false)
+ {
+ msgIdI = (Integer) keys.nextElement();
+ Integer pduIdI = (Integer) msgIdHash.get(msgIdI);
+ found = (pduIdI.intValue() == rid);
+ }
+ if (found)
+ {
+ msgIdHash.remove(msgIdI);
+ }
+ }
+ return removed;
+}
+
+/**
+ * Encodes a discovery PDU packet. This methods encodes without checking
+ * if the discovery parameters are all known.
+ */
+public byte[] encodeDiscoveryPacket(byte msg_type, int rId, int errstat,
+ int errind, Enumeration ve, Object obj)
+ throws IOException, EncodingException
+{
+ String engineId = "";
+ TimeWindow tWindow = TimeWindow.getCurrent();
+ if (tWindow.isSnmpEngineIdKnown(getSendToHostAddress(), hostPort) == true)
+ {
+ engineId = tWindow.getSnmpEngineId(getSendToHostAddress(), hostPort);
+ }
+ TimeWindowNode node = new TimeWindowNode(engineId, 0, 0);
+
+ return actualEncodePacket(msg_type, rId, errstat, errind, ve, node,
+ obj);
+}
+
+/**
+ * Encodes a PDU. This is for internal use only and should
+ * NOT be called by the developer.
+ * This is called by the the PDU itself and is added to the interface to
+ * cover the different kind of Contexts.
+ *
+ *
+ * When the stack is
+ *
+ *
+ * -
+ * authoritative, the timeline details are retrieved from the UsmAgent.
+ *
+ * -
+ * non authoritative, this methods first checks if all the discovery
+ * parameters are known;
+ *
+ * -
+ * If so, it encodes and returns the bytes.
+ *
+ * -
+ * If not, it will throw an EncodingException.
+ *
+ *
+ *
+ *
+ *
+ * @see #isAuthoritative(byte)
+ * @param msg_type The message type
+ * @param rId The message id
+ * @param errstat The error status
+ * @param errind The error index
+ * @param ve The varbind list
+ * @param obj Additional object (only used in SNMPv3)
+ * @return The encoded packet
+ */
+public byte[] encodePacket(byte msg_type, int rId, int errstat,
+ int errind, Enumeration ve, Object obj)
+ throws IOException, EncodingException
+{
+ TimeWindowNode node = null;
+ if (isDestroyed == true)
+ {
+ throw new EncodingException("Context can no longer be used, since it is already destroyed");
+ }
+ else
+ {
+ TimeWindow tWindow = TimeWindow.getCurrent();
+ if (isAuthoritative(msg_type) == true)
+ {
+ usmAgent.setSnmpContext(this);
+ if (usmAgent.getSnmpEngineId() == null)
+ {
+ throw new EncodingException("UsmAgent "
+ + usmAgent.getClass().getName()
+ + " should provide Engine ID!");
+ }
+ tWindow.updateTimeWindow(usmAgent.getSnmpEngineId(),
+ usmAgent.getSnmpEngineBoots(), usmAgent.getSnmpEngineTime(),
+ this.isUseAuthentication());
+ node = tWindow.getTimeLine(usmAgent.getSnmpEngineId());
+ }
+ else
+ {
+ if (tWindow.isSnmpEngineIdKnown(getSendToHostAddress(), hostPort) == false)
+ {
+ throw new EncodingException("Engine ID of host "
+ + getSendToHostAddress()
+ + ", port " + hostPort
+ + " is unknown (rId="
+ + rId + "). Perform discovery.");
+ }
+ String engineId = tWindow.getSnmpEngineId(getSendToHostAddress(), hostPort);
+ node = new TimeWindowNode(engineId, 0, 0);
+
+ if (isUseAuthentication())
+ {
+ if (tWindow.isTimeLineKnown(engineId) == true)
+ {
+ node = tWindow.getTimeLine(engineId);
+ }
+ else
+ {
+ throw new EncodingException("Time Line of Engine ID of host "
+ + getSendToHostAddress() + ", port " + hostPort + " is unknown. "
+ + "Perform discovery.");
+ }
+ }
+ }
+ }
+ return actualEncodePacket(msg_type, rId, errstat, errind, ve, node,
+ obj);
+}
+
+
+/**
+ * Checks the sanity of the context and returns an error message when it
+ * is not correct.
+ */
+protected String checkContextSanity()
+{
+ String ret = null;
+ if (usePrivacy == true)
+ {
+ if (userPrivacyPassword == null)
+ {
+ ret = "userPrivacyPassword is null, but usePrivacy is true";
+ }
+ else if (userPrivacyPassword.length() == 0)
+ {
+ ret = "userPrivacyPassword is empty, but usePrivacy is true";
+ }
+ else if (useAuthentication == false)
+ {
+ ret = "useAuthentication is false, but usePrivacy is true";
+ }
+ }
+
+ if (useAuthentication == true)
+ {
+ if (userAuthenticationPassword == null)
+ {
+ ret = "userAuthenticationPassword is null, but useAuthentication is true";
+ }
+ else if (userAuthenticationPassword.length() == 0)
+ {
+ ret = "userAuthenticationPassword is empty, but useAuthentication is true";
+ }
+ }
+ return ret;
+}
+
+
+/**
+ * Does the actual encoding.
+ *
+ * @see #encodeDiscoveryPacket
+ * @see #encodePacket
+ */
+protected byte[] actualEncodePacket(byte msg_type, int rId, int errstat,
+ int errind, Enumeration ve, TimeWindowNode node, Object obj)
+ throws IOException, EncodingException
+{
+ AsnEncoderv3 enc = new AsnEncoderv3();
+ String msg = checkContextSanity();
+ if (msg != null)
+ {
+ throw new EncodingException(msg);
+ }
+
+ int msgId = ((Integer)obj).intValue();
+ if (AsnObject.debug > 6)
+ {
+ System.out.println(getClass().getName() + ".actualEncodePacket(): msgId="
+ + msgId + ", Pdu reqId=" + rId);
+ }
+ byte[] packet = enc.EncodeSNMPv3(this, msgId, node,
+ msg_type, rId, errstat, errind, ve);
+
+ return packet;
+}
+
+/**
+ * Processes an incoming SNMP v3 response.
+ */
+protected void processIncomingResponse(ByteArrayInputStream in)
+throws DecodingException, IOException
+{
+ AsnDecoderv3 rpdu = new AsnDecoderv3();
+ // don't have to check for context sanity here: if the request was
+ // fine, so should be the response
+ byte [] bu = null;
+ // need to duplicate the message for V3 to rewrite
+ int nb = in.available();
+ bu = new byte[nb];
+ in.read(bu);
+ in = new ByteArrayInputStream(bu);
+
+ AsnSequence asnTopSeq = rpdu.DecodeSNMPv3(in);
+ int msgId = rpdu.getMsgId(asnTopSeq);
+ Integer rid = (Integer) msgIdHash.get(new Integer(msgId));
+ if (rid != null)
+ {
+ if (AsnObject.debug > 6)
+ {
+ System.out.println(getClass().getName() + ".processIncomingResponse(): msgId="
+ + msgId + ", Pdu reqId=" + rid);
+ }
+ Pdu pdu = getPdu(rid);
+ try
+ {
+ AsnPduSequence pduSeq = rpdu.processSNMPv3(this, asnTopSeq, bu, false);
+ if (pduSeq != null)
+ {
+ // got a message
+ Integer rid2 = new Integer(pduSeq.getReqId());
+ if (AsnObject.debug > 6)
+ {
+ System.out.println(getClass().getName() + ".processIncomingResponse():"
+ + " rid2=" + rid2);
+ }
+
+ Pdu newPdu = null;
+ if (rid2.intValue() != rid.intValue())
+ {
+ newPdu = getPdu(rid2);
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName() + ".processIncomingResponse(): "
+ + "pduReqId of msgId (" + rid.intValue()
+ + ") != pduReqId of Pdu (" + rid2.intValue()
+ + ")");
+ }
+ if (newPdu == null)
+ {
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName() + ".processIncomingResponse(): "
+ + "Using pduReqId of msgId (" + rid.intValue() + ")");
+ }
+ }
+ }
+
+ if (newPdu != null)
+ {
+ pdu = newPdu;
+ }
+ }
+ else
+ {
+ if (AsnObject.debug > 6)
+ {
+ System.out.println(getClass().getName() + ".processIncomingResponse():"
+ + " pduSeq is null.");
+ }
+ }
+
+ if (pdu != null)
+ {
+ pdu.fillin(pduSeq);
+ }
+ else
+ {
+ if (AsnObject.debug > 6)
+ {
+ System.out.println(getClass().getName() + ".processIncomingResponse(): No Pdu with reqid " + rid.intValue());
+ }
+ }
+ }
+ catch (DecodingException exc)
+ {
+ if (pdu != null)
+ {
+ pdu.setErrorStatus(AsnObject.SNMP_ERR_DECODING_EXC, exc);
+ pdu.fillin(null);
+ }
+ else
+ {
+ throw exc;
+ }
+ }
+ }
+ else
+ {
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName() + ".processIncomingResponse(): Pdu of msgId " + msgId
+ + " is already answered");
+ }
+ rid = new Integer(-1);
+ }
+}
+
+/**
+ * Returns if we send this PDU in authoritative role or not.
+ * The engine who sends a Response, a Trapv2 or a Report is
+ * authoritative.
+ *
+ * @since 4_14
+ * @return true if authoritative, false if not.
+ */
+// Note: for when adding INFORM
+// When sending an INFORM, the receiver is the authoritative engine, so
+// the INFORM does NOT have to be added to this list!
+protected boolean isAuthoritative(byte msg_type)
+{
+ return (msg_type == AsnObject.GET_RSP_MSG
+ ||
+ msg_type == AsnObject.TRPV2_REQ_MSG
+ ||
+ msg_type == AsnObject.GET_RPRT_MSG);
+}
+
+void discoverIfNeeded(Pdu pdu)
+throws IOException, PduException
+{
+ UsmDiscoveryBean discBean = null;
+ boolean isNeeded = false;
+
+ TimeWindow tWindow = TimeWindow.getCurrent();
+ String engineId = tWindow.getSnmpEngineId(getSendToHostAddress(), hostPort);
+ if (engineId == null)
+ {
+ isNeeded = true;
+ discBean = new UsmDiscoveryBean(
+ getSendToHostAddress(), hostPort, bindAddr, typeSocket);
+ discBean.setRetryIntervals(pdu.getRetryIntervals());
+ }
+
+ if (isUseAuthentication())
+ {
+ if (isNeeded)
+ {
+ discBean.setAuthenticationDetails(userName,
+ userAuthenticationPassword, authenticationProtocol);
+ }
+ else if (tWindow.isTimeLineKnown(engineId) == false)
+ {
+ isNeeded = true;
+ discBean = new UsmDiscoveryBean(
+ getSendToHostAddress(), hostPort, bindAddr, typeSocket);
+ discBean.setAuthenticationDetails(userName,
+ userAuthenticationPassword, authenticationProtocol);
+ discBean.setRetryIntervals(pdu.getRetryIntervals());
+ }
+
+ if (isNeeded && isUsePrivacy())
+ {
+ discBean.setPrivacyDetails(userPrivacyPassword, privacyProtocol);
+ }
+ }
+
+ if (isNeeded)
+ {
+ discBean.startDiscovery();
+
+ }
+
+ // If contextEngineId is null or of length zero, set
+ // it to the snmpEngineId.
+ if (contextEngineId == null || contextEngineId.length == 0)
+ {
+ engineId = tWindow.getSnmpEngineId(getSendToHostAddress(), hostPort);
+ setContextEngineId(SnmpUtilities.toBytes(engineId));
+ }
+}
+
+
+/**
+ * Adds the specified request pdu listener to receive PDUs on the
+ * specified listening context that matches this context.
+ * This method will call usmAgent.setSnmpContext(this).
+ *
+ *
+ * Don't use the TCP_SOCKET when listening for request PDUs. It doesn't
+ * provide functionality to send a response back.
+ *
+ *
+ * @see AbstractSnmpContext#addRequestPduListener(RequestPduListener, ListeningContextPool)
+ *
+ * @param l The request PDU listener
+ * @param lcontext The listening context
+ */
+public void addRequestPduListener(RequestPduListener l, ListeningContextPool lcontext)
+throws IOException
+{
+ super.addRequestPduListener(l, lcontext);
+
+ usmAgent.setSnmpContext(this);
+ TimeWindow tWindow = TimeWindow.getCurrent();
+ if (usmAgent.getSnmpEngineId() == null)
+ {
+ throw new IOException("UsmAgent "
+ + usmAgent.getClass().getName()
+ + " should provide Engine ID!");
+ }
+ tWindow.setSnmpEngineId(usmAgent.MYFAKEHOSTNAME, hostPort, usmAgent.getSnmpEngineId());
+ tWindow.updateTimeWindow(usmAgent.getSnmpEngineId(),
+ usmAgent.getSnmpEngineBoots(), usmAgent.getSnmpEngineTime(),
+ this.isUseAuthentication());
+}
+
+
+
+/**
+ * Copies all parameters into another SnmpContextv3.
+ */
+public Object cloneParameters(SnmpContextv3Face clContext)
+{
+ clContext.setUserName(new String(userName));
+ clContext.setUseAuthentication(useAuthentication);
+ if (userAuthenticationPassword != null)
+ {
+ clContext.setUserAuthenticationPassword(
+ new String(userAuthenticationPassword));
+ }
+ clContext.setAuthenticationProtocol(authenticationProtocol);
+
+ clContext.setUsePrivacy(usePrivacy);
+ if (userPrivacyPassword != null)
+ {
+ clContext.setUserPrivacyPassword(new String(userPrivacyPassword));
+ }
+ clContext.setPrivacyProtocol(privacyProtocol);
+
+ clContext.setContextName(new String(contextName));
+
+ int l = contextEngineId.length;
+ byte[] newContextEngineId = new byte[l];
+ System.arraycopy(contextEngineId, 0, newContextEngineId, 0, l);
+ clContext.setContextEngineId(newContextEngineId);
+
+ clContext.setUsmAgent(usmAgent);
+ return clContext;
+}
+
+/**
+ * Returns the hash key. This key is built out of all properties. It
+ * serves as key for a hashtable of (v3) contexts.
+ *
+ * @since 4_14
+ * @return The hash key
+ */
+public String getHashKey()
+{
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(hostname);
+ buffer.append("_").append(hostPort);
+ buffer.append("_").append(bindAddr);
+ buffer.append("_").append(typeSocket);
+ buffer.append("_").append(useAuthentication);
+ buffer.append("_").append(ProtocolNames[authenticationProtocol]);
+ buffer.append("_").append(ProtocolNames[privacyProtocol]);
+ buffer.append("_").append(userAuthenticationPassword);
+ buffer.append("_").append(userName);
+ buffer.append("_").append(usePrivacy);
+ buffer.append("_").append(userPrivacyPassword);
+ buffer.append("_").append(SnmpUtilities.toHexString(contextEngineId));
+ buffer.append("_").append(contextName);
+ buffer.append("_v").append(getVersion());
+
+ return buffer.toString();
+}
+
+/**
+ * Returns a string representation of the object.
+ * @return The string
+ */
+public String toString()
+{
+ StringBuffer buffer = new StringBuffer(getClass().getName() + "[");
+ buffer.append("host=").append(hostname);
+ buffer.append(", sendToHost=").append(getSendToHostAddress());
+ buffer.append(", port=").append(hostPort);
+ buffer.append(", bindAddress=").append(bindAddr);
+ buffer.append(", socketType=").append(typeSocket);
+ buffer.append(", contextEngineId=").append(SnmpUtilities.toHexString(contextEngineId));
+ buffer.append(", contextName=").append(contextName);
+ buffer.append(", userName=").append(userName);
+ buffer.append(", useAuthentication=").append(useAuthentication);
+ buffer.append(", authenticationProtocol=").append(ProtocolNames[authenticationProtocol]);
+ buffer.append(", userAuthenticationPassword=").append(userAuthenticationPassword);
+ buffer.append(", usePrivacy=").append(usePrivacy);
+ buffer.append(", privacyProtocol=").append(ProtocolNames[privacyProtocol]);
+ buffer.append(", userPrivacyPassword=").append(userPrivacyPassword);
+ buffer.append(", #trapListeners=").append(trapSupport.getListenerCount());
+ buffer.append(", #pduListeners=").append(pduSupport.getListenerCount());
+ buffer.append("]");
+ return buffer.toString();
+}
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv3Discovery.java b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv3Discovery.java
new file mode 100644
index 0000000..c89b52a
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv3Discovery.java
@@ -0,0 +1,224 @@
+// NAME
+// $RCSfile: SnmpContextv3Discovery.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.11 $
+// CREATED
+// $Date: 2009/03/05 13:12:50 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2005 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.net.*;
+import java.io.*;
+import java.util.*;
+
+import uk.co.westhawk.snmp.pdu.*;
+import uk.co.westhawk.snmp.util.*;
+import uk.co.westhawk.snmp.event.*;
+import uk.co.westhawk.snmp.beans.*;
+
+/**
+ * This class contains the SNMP v3 discovery context that is used by
+ * UsmBeingDiscoveredBean, when this stack is being discovered.
+ * Most of the work is done by SnmpContextv3Basis.
+ *
+ *
+ * Now that the stack can send traps and receive requests,
+ * it needs to be able to act as an
+ * authoritative SNMP engine. This is done via the interface UsmAgent.
+ * The DefaultUsmAgent is not guaranteed to work; agents (or rather
+ * authoritative engines) should provide a better implementation.
+ *
+ *
+ * @see DefaultUsmAgent
+ * @see UsmBeingDiscoveredBean
+ *
+ * @since 4_14
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.11 $ $Date: 2009/03/05 13:12:50 $
+ */
+public class SnmpContextv3Discovery extends SnmpContextv3Basis
+{
+ private static final String version_id =
+ "@(#)$Id: SnmpContextv3Discovery.java,v 3.11 2009/03/05 13:12:50 birgita Exp $ Copyright Westhawk Ltd";
+
+
+/**
+ * Constructor.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @see AbstractSnmpContext#AbstractSnmpContext(String, int)
+ */
+public SnmpContextv3Discovery(String host, int port) throws IOException
+{
+ super(host, port);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocketA should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the Pdu will be sent
+ * @param port The port where the SNMP server will be
+ * @param typeSocketA The local address the server will bind to
+ *
+ * @see AbstractSnmpContext#AbstractSnmpContext(String, int, String)
+ */
+public SnmpContextv3Discovery(String host, int port, String typeSocketA)
+throws IOException
+{
+ super(host, port, typeSocketA);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocketA should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @param bindAddress The local address the server will bind to
+ * @param typeSocketA The type of socket to use.
+ *
+ * @see AbstractSnmpContext#AbstractSnmpContext(String, int, String, String)
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ * @since 4_14
+ */
+public SnmpContextv3Discovery(String host, int port, String bindAddress, String typeSocketA)
+throws IOException
+{
+ super(host, port, bindAddress, typeSocketA);
+}
+
+
+/**
+ * Processes an incoming Discovery (and only Discovery) PDU.
+ *
+ * See SNMP-USER-BASED-SM-MIB.
+ *
+ *
+ * @see #rawPduReceived
+ */
+public Pdu processIncomingPdu(byte [] message)
+throws DecodingException, IOException
+{
+ String msg = checkContextSanity();
+ if (msg != null)
+ {
+ throw new DecodingException(msg);
+ }
+ int l = message.length;
+ byte [] copyOfMessage = new byte[l];
+ System.arraycopy(message, 0, copyOfMessage, 0, l);
+
+ AsnDecoderv3 rpdu = new AsnDecoderv3();
+ ByteArrayInputStream in = new ByteArrayInputStream(message);
+ AsnSequence asnTopSeq = rpdu.DecodeSNMPv3(in);
+ int msgId = rpdu.getMsgId(asnTopSeq);
+ AsnPduSequence pduSeq = rpdu.processSNMPv3(this, asnTopSeq, copyOfMessage, true);
+
+ Pdu pdu = null;
+ if (pduSeq != null)
+ {
+ byte type = pduSeq.getRespType();
+ if (type == SnmpConstants.GET_REQ_MSG && pduSeq.isSnmpv3Discovery() == true)
+ {
+ pdu = new GetPdu(this);
+ }
+ else
+ {
+ /*
+ These cannot be sent as discovery pdu;
+ SnmpConstants.GETNEXT_REQ_MSG
+ SnmpConstants.SET_REQ_MSG
+ SnmpConstants.GETBULK_REQ_MSG
+ SnmpConstants.INFORM_REQ_MSG
+ SnmpConstants.GET_RSP_MSG
+ SnmpConstants.GET_RPRT_MSG
+ SnmpConstants.TRPV2_REQ_MSG
+ */
+
+ if (AsnObject.debug > 3)
+ {
+ System.out.println(getClass().getName()
+ + ".ProcessIncomingPdu(): PDU received with type "
+ + pduSeq.getRespTypeString()
+ + ". Ignoring it.");
+ }
+ }
+
+ if (pdu != null)
+ {
+ pdu.fillin(pduSeq);
+ pdu.snmpv3MsgId = new Integer(msgId);
+ }
+ }
+ return pdu;
+}
+
+/**
+ * Returns a clone of this SnmpContextv3.
+ *
+ * @exception CloneNotSupportedException Thrown when the constructor
+ * generates an IOException
+ */
+public Object clone() throws CloneNotSupportedException
+{
+ SnmpContextv3Discovery clContext = null;
+ try
+ {
+ clContext = new SnmpContextv3Discovery(hostname, hostPort, bindAddr, typeSocket);
+ clContext = (SnmpContextv3Discovery) cloneParameters(clContext);
+ }
+ catch (IOException exc)
+ {
+ throw new CloneNotSupportedException("IOException "
+ + exc.getMessage());
+ }
+ return clContext;
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv3Face.java b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv3Face.java
new file mode 100644
index 0000000..3de4522
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv3Face.java
@@ -0,0 +1,361 @@
+// NAME
+// $RCSfile: SnmpContextv3Face.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.20 $
+// CREATED
+// $Date: 2009/03/05 12:56:17 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import uk.co.westhawk.snmp.pdu.*;
+
+/**
+ * This interface contains the SNMP context interface that is needed by every
+ * PDU to send a SNMP v3 request.
+ *
+ * See SNMP-USER-BASED-SM-MIB,
+ * RFC 3411,
+ * RFC 3826 (AES)
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.20 $ $Date: 2009/03/05 12:56:17 $
+ */
+public interface SnmpContextv3Face extends SnmpContextBasisFace
+{
+ static final String version_id =
+ "@(#)$Id: SnmpContextv3Face.java,v 3.20 2009/03/05 12:56:17 birgita Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * The SNMPv1 security model. This has value 1.
+ * The stack does not implement this security model.
+ */
+ public final static int SNMPv1_Security_Model = (byte)(0x1);
+
+ /**
+ * The SNMPv2c security model. This has value 2.
+ * The stack does not implement this security model.
+ */
+ public final static int SNMPv2c_Security_Model = (byte)(0x2);
+
+ /**
+ * The USM security model. This has value 3.
+ * This stack only implements this security model!
+ */
+ public final static int USM_Security_Model = (byte)(0x3);
+
+ /**
+ * The MD5 protocol type.
+ */
+ public final static int MD5_PROTOCOL=0;
+
+ /**
+ * The SHA-1 protocol type.
+ */
+ public final static int SHA1_PROTOCOL=1;
+
+ /**
+ * The DES encryption type.
+ */
+ public final static int DES_ENCRYPT=2;
+
+ /**
+ * The AES 128 encryption type.
+ */
+ public final static int AES_ENCRYPT=3;
+
+ /**
+ * The default value for the (security) user name. This is
+ * "initial".
+ */
+ public final static String Default_UserName = "initial";
+
+ /**
+ * The default Context Name. This is the zero length string, i.e. "".
+ */
+ public final static String Default_ContextName = "";
+
+ /**
+ * The array with the String represensations of the protocols.
+ */
+ public final static String ProtocolNames [] =
+ {
+ "MD5",
+ "SHA1",
+ "DES",
+ "AES"
+ };
+
+/**
+ * Returns the username.
+ *
+ * @return the username
+ */
+public String getUserName();
+
+/**
+ * Sets the username.
+ * This username will be used for all PDUs sent with this context.
+ * The username corresponds to the 'msgUserName' in
+ * SNMP-USER-BASED-SM-MIB.
+ * The default value is "initial".
+ *
+ * @param newUserName The new username
+ */
+public void setUserName(String newUserName);
+
+/**
+ * Returns if authentication is used or not.
+ * By default no authentication will be used.
+ *
+ * @return true if authentication is used, false if not
+ */
+public boolean isUseAuthentication();
+
+/**
+ * Sets whether authentication has to be used.
+ * By default no authentication will be used.
+ *
+ * @param newUseAuthentication The use of authentication
+ */
+public void setUseAuthentication(boolean newUseAuthentication);
+
+/**
+ * Returns the user authentication password.
+ * This password will be transformed into the user authentication secret key.
+ *
+ * @return The user authentication password
+ */
+public String getUserAuthenticationPassword();
+
+/**
+ * Sets the user authentication password.
+ * This password will be transformed into the user authentication secret
+ * key. A user MUST set this password.
+ *
+ * @param newUserAuthPassword The user authentication password
+ */
+public void setUserAuthenticationPassword(String newUserAuthPassword)
+throws IllegalArgumentException;
+
+/**
+ * Sets the protocol to be used for authentication.
+ * This can either be MD5 or SHA-1.
+ * By default MD5 will be used.
+ *
+ * @param protocol The authentication protocol to be used
+ * @see #MD5_PROTOCOL
+ * @see #SHA1_PROTOCOL
+ */
+public void setAuthenticationProtocol(int protocol)
+throws IllegalArgumentException;
+
+/**
+ * Returns the protocol to be used for authentication.
+ * This can either be MD5 or SHA-1.
+ * By default MD5 will be used.
+ *
+ * @return The authentication protocol to be used
+ * @see #MD5_PROTOCOL
+ * @see #SHA1_PROTOCOL
+ */
+public int getAuthenticationProtocol();
+
+/**
+ * Sets the protocol to be used for privacy.
+ * This can either be DES or AES.
+ * By default DES will be used.
+ *
+ * @param protocol The privacy protocol to be used
+ * @see #DES_ENCRYPT
+ * @see #AES_ENCRYPT
+ */
+public void setPrivacyProtocol(int protocol)
+throws IllegalArgumentException;
+
+/**
+ * Returns the protocol to be used for privacy.
+ * This can either be DES or AES.
+ * By default DES will be used.
+ *
+ * @return The privacy protocol to be used
+ * @see #DES_ENCRYPT
+ * @see #AES_ENCRYPT
+ */
+public int getPrivacyProtocol();
+
+/**
+ * Returns if privacy is used or not.
+ * By default no privacy will be used.
+ *
+ * @return true if privacy is used, false if not
+ */
+public boolean isUsePrivacy();
+
+/**
+ * Sets whether privacy has to be used.
+ * By default no privacy will be used.
+ *
+ * @param newUsePrivacy The use of privacy
+ */
+public void setUsePrivacy(boolean newUsePrivacy);
+
+/**
+ * Returns the user privacy password.
+ * This password will be transformed into the user privacy secret key.
+ *
+ * @return The user privacy password
+ */
+public String getUserPrivacyPassword();
+
+/**
+ * Sets the user privacy password.
+ * This password will be transformed into the user privacy secret
+ * key. A user MUST set this password.
+ *
+ * @param newUserAuthPassword The user privacy password
+ */
+public void setUserPrivacyPassword(String newUserAuthPassword)
+throws IllegalArgumentException;
+
+
+/**
+ * Sets the contextEngineID.
+ * See RFC 3411.
+ *
+ * A contextEngineID uniquely
+ * identifies an SNMP entity that may realize an instance of a context
+ * with a particular contextName.
+ *
+ *
+ * Note, when the stack is an authoritative engine, this parameter should
+ * equal the UsmAgent.getSnmpEngineId(). See the StackUsage
+ * documentation for an explanation.
+ *
+ *
+ *
+ * If the contextEngineID is of length zero, the encoder will use the (discovered)
+ * snmpEngineId.
+ *
+ *
+ * @see UsmAgent#getSnmpEngineId()
+ * @param newContextEngineId The contextEngineID
+ */
+public void setContextEngineId(byte [] newContextEngineId)
+throws IllegalArgumentException;
+
+/**
+ * Returns the contextEngineID.
+ *
+ * @return The contextEngineID
+ */
+public byte [] getContextEngineId();
+
+/**
+ * Sets the contextName.
+ * See RFC 3411.
+ *
+ * A contextName is used to name a context. Each contextName MUST be
+ * unique within an SNMP entity.
+ * By default this is "".
+ *
+ * @param newContextName The contextName
+ * @see #Default_ContextName
+ */
+public void setContextName(String newContextName);
+
+/**
+ * Returns the contextName.
+ *
+ * @return The contextName
+ */
+public String getContextName();
+
+/**
+ * Adds a discovery PDU.
+ * This is for internal use only and should
+ * NOT be called by the developer.
+ *
+ * This is called by the the PDU itself and is added to the interface to
+ * cover the different kind of Contexts.
+ * @param pdu the discovery PDU
+ * @return PDU is succesful added
+ */
+public boolean addDiscoveryPdu(DiscoveryPdu pdu)
+throws java.io.IOException, PduException;
+
+
+/**
+ * Encodes a discovery PDU.
+ * This is for internal use only and should
+ * NOT be called by the developer.
+ *
+ * This is called by the the PDU itself and is added to the interface to
+ * cover the different kind of Contexts.
+ * @return The encoded packet
+ */
+public byte[] encodeDiscoveryPacket(byte msg_type, int rId, int errstat,
+ int errind, java.util.Enumeration ve, Object obj)
+ throws java.io.IOException, EncodingException;
+
+
+/**
+ * Sets the UsmAgent, needed when this stack is used as authoritative
+ * SNMP engine. This interface provides authentiation details, like its
+ * clock and its Engine ID.
+ *
+ * @since 4_14
+ * @param agent The USM authoritative interface
+ */
+public void setUsmAgent(UsmAgent agent);
+
+/**
+ * Returns the UsmAgent.
+ *
+ * @since 4_14
+ * @see #setUsmAgent
+ */
+public UsmAgent getUsmAgent();
+
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv3Pool.java b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv3Pool.java
new file mode 100644
index 0000000..380d429
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/SnmpContextv3Pool.java
@@ -0,0 +1,854 @@
+// NAME
+// $RCSfile: SnmpContextv3Pool.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.27 $
+// CREATED
+// $Date: 2009/03/05 13:27:41 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import uk.co.westhawk.snmp.pdu.*;
+import uk.co.westhawk.snmp.util.*;
+import uk.co.westhawk.snmp.event.*;
+import java.util.*;
+
+/**
+ * This class contains the pool of SNMP v3 contexts.
+ * This class reuses the existings contexts instead of creating a new
+ * one every time.
+ *
+ * Every time a property changes the pool is checked for a SnmpContextv3
+ * context that matches all the new properties of this class. If no such
+ * context exists, a new one is made.
+ * The PDUs associated with the old context remain associated with the
+ * old context.
+ *
+ *
+ *
+ * A counter indicates the number of times the context is referenced.
+ * The counter is decreased when destroy()
is called.
+ * When the counter
+ * reaches zero, the context is released.
+ *
+ *
+ *
+ * Note that because the underlying context can change when a property
+ * is changed and the PDUs remain associated with the old context, all
+ * properties have to be set BEFORE a PDU is sent.
+ *
+ *
+ * @see SnmpContextv3
+ * @see SnmpContextPool
+ * @see SnmpContextv2cPool
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.27 $ $Date: 2009/03/05 13:27:41 $
+ */
+public class SnmpContextv3Pool implements SnmpContextv3Face
+{
+ private static final String version_id =
+ "@(#)$Id: SnmpContextv3Pool.java,v 3.27 2009/03/05 13:27:41 birgita Exp $ Copyright Westhawk Ltd";
+
+ protected static Hashtable contextPool;
+
+ protected String hostname, socketType, bindAddr;
+ protected int hostPort;
+
+ protected SnmpContextv3 context = null;
+ protected String userName = "";
+ protected boolean useAuthentication = false;
+ protected String userAuthenticationPassword = "";
+ protected boolean usePrivacy = false;
+ protected String userPrivacyPassword = "";
+ protected int authenticationProtocol = MD5_PROTOCOL;
+ protected byte [] contextEngineId = new byte[0];
+ protected String contextName = Default_ContextName;
+ protected UsmAgent usmAgent = null;
+
+ protected boolean hasChanged = false;
+ protected int privacyProtocol = DES_ENCRYPT;
+
+/**
+ * Constructor, using the Standard socket.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @see SnmpContextv3#SnmpContextv3(String, int)
+ */
+public SnmpContextv3Pool(String host, int port) throws java.io.IOException
+{
+ this(host, port, null, STANDARD_SOCKET);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocket should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @param typeSocket The type of socket to use.
+ *
+ * @see SnmpContextv3#SnmpContextv3(String, int, String)
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ */
+public SnmpContextv3Pool(String host, int port, String typeSocket)
+throws java.io.IOException
+{
+ this(host, port, null, typeSocket);
+}
+
+/**
+ * Constructor.
+ * Parameter typeSocket should be either STANDARD_SOCKET, TCP_SOCKET or a
+ * fully qualified classname.
+ *
+ * @param host The host to which the PDU will be sent
+ * @param port The port where the SNMP server will be
+ * @param bindAddress The local address the server will bind to
+ * @param typeSocket The type of socket to use.
+ *
+ * @see SnmpContextv3#SnmpContextv3(String, int, String)
+ * @see SnmpContextBasisFace#STANDARD_SOCKET
+ * @see SnmpContextBasisFace#TCP_SOCKET
+ *
+ * @since 4_14
+ */
+public SnmpContextv3Pool(String host, int port, String bindAddress, String typeSocket)
+throws java.io.IOException
+{
+ initPools();
+ hostname = host;
+ hostPort = port;
+ bindAddr = bindAddress;
+ socketType = typeSocket;
+
+ // No point in creating a context, a lot of the parameters
+ // are probably going to be set.
+ //context = getMatchingContext();
+}
+
+private static synchronized void initPools()
+{
+ if (contextPool == null)
+ {
+ contextPool = new Hashtable(5);
+ }
+}
+/**
+ * Returns the SNMP version of the context.
+ *
+ * @return The version
+ */
+public int getVersion()
+{
+ return SnmpConstants.SNMP_VERSION_3;
+}
+
+/**
+ * Returns the host.
+ *
+ * @return The host
+ */
+public String getHost()
+{
+ return hostname;
+}
+
+/**
+ * Returns the port number.
+ *
+ * @return The port no
+ */
+public int getPort()
+{
+ return hostPort;
+}
+
+public String getBindAddress()
+{
+ return bindAddr;
+}
+
+/**
+ * Returns the type of socket.
+ *
+ * @return The type of socket
+ */
+public String getTypeSocket()
+{
+ return socketType;
+}
+
+public String getSendToHostAddress()
+{
+ String res = null;
+ if (context != null)
+ {
+ res = context.getSendToHostAddress();
+ }
+ return res;
+}
+
+public String getReceivedFromHostAddress()
+{
+ String res = null;
+ if (context != null)
+ {
+ res = context.getReceivedFromHostAddress();
+ }
+ return res;
+}
+
+
+public String getUserName()
+{
+ return userName;
+}
+
+public void setUserName(String newUserName)
+{
+ if (newUserName != null && newUserName.equals(userName) == false)
+ {
+ userName = newUserName;
+ hasChanged = true;
+ }
+}
+
+public boolean isUseAuthentication()
+{
+ return useAuthentication;
+}
+
+public void setUseAuthentication(boolean newUseAuthentication)
+{
+ if (newUseAuthentication != useAuthentication)
+ {
+ useAuthentication = newUseAuthentication;
+ hasChanged = true;
+ }
+}
+
+public String getUserAuthenticationPassword()
+{
+ return userAuthenticationPassword;
+}
+
+public void setUserAuthenticationPassword(String newUserAuthenticationPd)
+{
+ if (newUserAuthenticationPd != null
+ &&
+ newUserAuthenticationPd.equals(userAuthenticationPassword) == false)
+ {
+ userAuthenticationPassword = newUserAuthenticationPd;
+ hasChanged = true;
+ }
+}
+
+public void setPrivacyProtocol(int protocol) throws IllegalArgumentException
+{
+ if (protocol == AES_ENCRYPT || protocol == DES_ENCRYPT)
+ {
+ if (protocol != privacyProtocol)
+ {
+ privacyProtocol = protocol;
+ hasChanged = true;
+ }
+ }
+ else
+ {
+ hasChanged = false;
+ throw new IllegalArgumentException("Privacy Protocol "
+ + "should be DES or AES");
+ }
+}
+
+public void setAuthenticationProtocol(int protocol)
+throws IllegalArgumentException
+{
+ if (protocol == MD5_PROTOCOL || protocol == SHA1_PROTOCOL)
+ {
+ if (protocol != authenticationProtocol)
+ {
+ authenticationProtocol = protocol;
+ hasChanged = true;
+ }
+ }
+ else
+ {
+ hasChanged = false;
+ throw new IllegalArgumentException("Authentication Protocol "
+ + "should be MD5 or SHA1");
+ }
+}
+
+
+public int getPrivacyProtocol()
+{
+ return privacyProtocol;
+}
+
+
+public int getAuthenticationProtocol()
+{
+ return authenticationProtocol;
+}
+
+public boolean isUsePrivacy()
+{
+ return usePrivacy;
+}
+
+public void setUsePrivacy(boolean newUsePrivacy)
+{
+ if (newUsePrivacy != usePrivacy)
+ {
+ usePrivacy = newUsePrivacy;
+ hasChanged = true;
+ }
+}
+
+public String getUserPrivacyPassword()
+{
+ return userPrivacyPassword;
+}
+
+public void setUserPrivacyPassword(String newUserPrivacyPd)
+{
+ if (newUserPrivacyPd != null
+ &&
+ newUserPrivacyPd.equals(userPrivacyPassword) == false)
+ {
+ userPrivacyPassword = newUserPrivacyPd;
+ hasChanged = true;
+ }
+}
+
+
+public void setContextEngineId(byte [] newContextEngineId)
+throws IllegalArgumentException
+{
+ if (newContextEngineId != null)
+ {
+ if (newContextEngineId.equals(contextEngineId) == false)
+ {
+ contextEngineId = newContextEngineId;
+ hasChanged = true;
+ }
+ }
+ else
+ {
+ hasChanged = false;
+ throw new IllegalArgumentException("contextEngineId is null");
+ }
+}
+
+public byte [] getContextEngineId()
+{
+ return contextEngineId;
+}
+
+public void setContextName(String newContextName)
+{
+ if (newContextName != null
+ &&
+ newContextName.equals(contextName) == false)
+ {
+ contextName = newContextName;
+ hasChanged = true;
+ }
+}
+
+public String getContextName()
+{
+ return contextName;
+}
+
+
+public void setUsmAgent(UsmAgent newAgent)
+{
+ if (newAgent != null
+ &&
+ newAgent != usmAgent)
+ {
+ usmAgent = newAgent;
+ hasChanged = true;
+ }
+}
+
+public UsmAgent getUsmAgent()
+{
+ return usmAgent;
+}
+
+public boolean addDiscoveryPdu(DiscoveryPdu pdu)
+throws java.io.IOException, PduException, IllegalArgumentException
+{
+ if (hasChanged == true || context == null)
+ {
+ context = getMatchingContext();
+ }
+ return context.addDiscoveryPdu(pdu);
+}
+
+public boolean addPdu(Pdu pdu)
+throws java.io.IOException, PduException, IllegalArgumentException
+{
+ if (hasChanged == true || context == null)
+ {
+ context = getMatchingContext();
+ }
+ return context.addPdu(pdu);
+}
+
+public boolean removePdu(int requestId)
+{
+ boolean res = false;
+ if (context != null)
+ {
+ res = context.removePdu(requestId);
+ }
+ return res;
+}
+
+public byte [] encodeDiscoveryPacket(byte msg_type, int rId, int errstat,
+ int errind, Enumeration ve, Object obj)
+ throws java.io.IOException, EncodingException
+{
+ byte [] res = null;
+ if (context != null)
+ {
+ res = context.encodeDiscoveryPacket(msg_type, rId, errstat, errind, ve, obj);
+ }
+ return res;
+}
+
+
+public byte [] encodePacket(byte msg_type, int rId, int errstat,
+ int errind, Enumeration ve, Object obj)
+ throws java.io.IOException, EncodingException
+{
+ byte [] res = null;
+ if (context != null)
+ {
+ res = context.encodePacket(msg_type, rId, errstat, errind, ve,
+ obj);
+ }
+ return res;
+}
+
+public void sendPacket(byte[] packet)
+{
+ if (context != null)
+ {
+ context.sendPacket(packet);
+ }
+}
+
+/**
+ * Releases the resources held by this context. This method will
+ * decrement the reference counter. When the reference counter reaches
+ * zero the actual context is removed from the pool and destroyed.
+ */
+public void destroy()
+{
+ synchronized(contextPool)
+ {
+ if (context != null)
+ {
+ String hashKey = context.getHashKey();
+
+ int count = 0;
+ SnmpContextPoolItem item = (SnmpContextPoolItem) contextPool.get(hashKey);
+ if (item != null)
+ {
+ count = item.getCounter();
+ count--;
+ item.setCounter(count);
+ }
+
+ if (count <= 0)
+ {
+ contextPool.remove(hashKey);
+ context.destroy();
+ }
+ context = null;
+ }
+ }
+}
+
+/**
+ * Destroys all the contexts in the pool and empties the pool.
+ *
+ * @see #destroy()
+ * @since 4_14
+ */
+public void destroyPool()
+{
+ Hashtable copyOfPool = null;
+
+ synchronized(contextPool)
+ {
+ synchronized(contextPool)
+ {
+ copyOfPool = (Hashtable) contextPool.clone();
+ }
+ contextPool.clear();
+ }
+ context = null;
+ hasChanged = true;
+
+ Enumeration keys = copyOfPool.keys();
+ while (keys.hasMoreElements())
+ {
+ String key = (String) keys.nextElement();
+ SnmpContextPoolItem item = (SnmpContextPoolItem) copyOfPool.get(key);
+ if (item != null)
+ {
+ SnmpContextBasisFace cntxt = (SnmpContextBasisFace) item.getContext();
+ cntxt.destroy();
+ }
+ }
+ copyOfPool.clear();
+}
+
+
+public boolean isDestroyed()
+{
+ boolean isDestroyed = true;
+ if (context != null)
+ {
+ isDestroyed = context.isDestroyed();
+ }
+ return isDestroyed;
+}
+
+/**
+ * Returns a context from the pool.
+ * The pre-existing context (if there is any) is destroyed.
+ * This methods checks for an existing context that matches all our
+ * properties. If such a context does not exist, a new one is created and
+ * added to the pool.
+ *
+ * @return A context from the pool
+ * @see #getHashKey
+ */
+protected SnmpContextv3 getMatchingContext()
+throws java.io.IOException, IllegalArgumentException
+{
+ SnmpContextPoolItem item = null;
+ SnmpContextv3 newContext = null;
+ String hashKey = getHashKey();
+
+ destroy();
+ synchronized(contextPool)
+ {
+ int count=0;
+ if (contextPool.containsKey(hashKey))
+ {
+ item = (SnmpContextPoolItem) contextPool.get(hashKey);
+ newContext = (SnmpContextv3) item.getContext();
+ count = item.getCounter();
+ }
+ else
+ {
+ newContext = new SnmpContextv3(hostname, hostPort, bindAddr, socketType);
+ newContext.setContextEngineId(contextEngineId);
+ newContext.setContextName(contextName);
+ newContext.setUserName(userName);
+ newContext.setUseAuthentication(useAuthentication);
+ newContext.setUserAuthenticationPassword(userAuthenticationPassword);
+ newContext.setAuthenticationProtocol(authenticationProtocol);
+ newContext.setUsePrivacy(usePrivacy);
+ newContext.setUserPrivacyPassword(userPrivacyPassword);
+ newContext.setUsmAgent(usmAgent);
+ newContext.setPrivacyProtocol(privacyProtocol);
+
+ item = new SnmpContextPoolItem(newContext);
+ contextPool.put(hashKey, item);
+ }
+ hasChanged = false;
+ count++;
+ item.setCounter(count);
+ }
+ return newContext;
+}
+
+/**
+ * Dumps the pool of contexts. This is for debug purposes.
+ * @param title The title of the dump
+ */
+public void dumpContexts(String title)
+{
+ try
+ {
+ if (hasChanged == true)
+ {
+ context = getMatchingContext();
+ }
+ }
+ catch (java.io.IOException exc)
+ {
+ if (AsnObject.debug > 0)
+ {
+ System.out.println(getClass().getName() + ".dumpContexts(): " + exc.getMessage());
+ }
+ }
+
+ System.out.println(title + " " + contextPool.size() + " context(s)");
+ Enumeration keys = contextPool.keys();
+ int i=0;
+ while (keys.hasMoreElements())
+ {
+ String key = (String) keys.nextElement();
+ SnmpContextPoolItem item = (SnmpContextPoolItem) contextPool.get(key);
+ if (item != null)
+ {
+ int count = item.getCounter();
+ SnmpContextv3 cntxt = (SnmpContextv3) item.getContext();
+
+ if (cntxt == context)
+ {
+ System.out.println("\tcurrent context: ");
+ }
+ System.out.println("\tcontext " + i + ": " + key + ", count: " + count
+ + ", " + cntxt.toString() + "\n"
+ + ", " + cntxt.getDebugString());
+ i++;
+ }
+ }
+ System.out.println("\thasChanged: " + hasChanged);
+}
+
+
+/**
+ * Returns the hash key. This key is built out of all properties. It
+ * serves as key for the hashtable of (v3) contexts.
+ *
+ * @return The hash key
+ */
+public String getHashKey()
+{
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(hostname);
+ buffer.append("_").append(hostPort);
+ buffer.append("_").append(bindAddr);
+ buffer.append("_").append(socketType);
+ buffer.append("_").append(useAuthentication);
+ buffer.append("_").append(ProtocolNames[authenticationProtocol]);
+ buffer.append("_").append(ProtocolNames[privacyProtocol]);
+ buffer.append("_").append(userAuthenticationPassword);
+ buffer.append("_").append(userName);
+ buffer.append("_").append(usePrivacy);
+ buffer.append("_").append(userPrivacyPassword);
+ buffer.append("_").append(SnmpUtilities.toHexString(contextEngineId));
+ buffer.append("_").append(contextName);
+ buffer.append("_v").append(getVersion());
+
+ return buffer.toString();
+}
+
+public void addTrapListener(TrapListener l) throws java.io.IOException
+{
+ if (hasChanged == true || context == null)
+ {
+ context = getMatchingContext();
+ }
+ context.addTrapListener(l);
+}
+
+public void removeTrapListener(TrapListener l) throws java.io.IOException
+{
+ if (hasChanged == true || context == null)
+ {
+ context = getMatchingContext();
+ }
+ context.removeTrapListener(l);
+}
+
+public void addTrapListener(TrapListener l, int port) throws java.io.IOException
+{
+ if (hasChanged == true || context == null)
+ {
+ context = getMatchingContext();
+ }
+ context.addTrapListener(l, port);
+}
+
+public void removeTrapListener(TrapListener l, int port) throws java.io.IOException
+{
+ if (hasChanged == true || context == null)
+ {
+ context = getMatchingContext();
+ }
+ context.removeTrapListener(l, port);
+}
+
+
+public void addTrapListener(TrapListener l, ListeningContextPool lcontext) throws java.io.IOException
+{
+ if (hasChanged == true || context == null)
+ {
+ context = getMatchingContext();
+ }
+ context.addTrapListener(l, lcontext);
+}
+
+public void removeTrapListener(TrapListener l, ListeningContextPool lcontext) throws java.io.IOException
+{
+ if (hasChanged == true || context == null)
+ {
+ context = getMatchingContext();
+ }
+ context.removeTrapListener(l, lcontext);
+}
+
+
+public void addRequestPduListener(RequestPduListener l) throws java.io.IOException
+{
+ if (hasChanged == true || context == null)
+ {
+ context = getMatchingContext();
+ }
+ context.addRequestPduListener(l);
+}
+
+public void removeRequestPduListener(RequestPduListener l) throws java.io.IOException
+{
+ if (hasChanged == true || context == null)
+ {
+ context = getMatchingContext();
+ }
+ context.removeRequestPduListener(l);
+}
+
+public void addRequestPduListener(RequestPduListener l, int port) throws java.io.IOException
+{
+ if (hasChanged == true || context == null)
+ {
+ context = getMatchingContext();
+ }
+ context.addRequestPduListener(l, port);
+}
+
+public void removeRequestPduListener(RequestPduListener l, int port) throws java.io.IOException
+{
+ if (hasChanged == true || context == null)
+ {
+ context = getMatchingContext();
+ }
+ context.removeRequestPduListener(l, port);
+}
+
+
+public void addRequestPduListener(RequestPduListener l, ListeningContextPool lcontext) throws java.io.IOException
+{
+ if (hasChanged == true || context == null)
+ {
+ context = getMatchingContext();
+ }
+ context.addRequestPduListener(l, lcontext);
+}
+
+public void removeRequestPduListener(RequestPduListener l, ListeningContextPool lcontext) throws java.io.IOException
+{
+ if (hasChanged == true || context == null)
+ {
+ context = getMatchingContext();
+ }
+ context.removeRequestPduListener(l, lcontext);
+}
+
+
+public Pdu processIncomingPdu(byte [] message)
+throws DecodingException, java.io.IOException
+{
+ if (hasChanged == true || context == null)
+ {
+ context = getMatchingContext();
+ }
+
+ Pdu pdu = null;
+ pdu = context.processIncomingPdu(message);
+ return pdu;
+}
+
+/**
+ * Returns a string representation of the object.
+ * @return The string
+ */
+public String toString()
+{
+ String res = "";
+ try
+ {
+ if (hasChanged == true || context == null)
+ {
+ context = getMatchingContext();
+ }
+ res = context.toString();
+ }
+ catch (java.io.IOException exc)
+ {
+ if (AsnObject.debug > 0)
+ {
+ System.out.println(getClass().getName() + ".toString(): " + exc.getMessage());
+ }
+ }
+
+ return res;
+}
+
+/**
+ * This method is not supported. It will throw a CloneNotSupportedException.
+ *
+ * @since 4_14
+ */
+public Object clone() throws CloneNotSupportedException
+{
+ throw new CloneNotSupportedException();
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/TimeWindow.java b/src/main/java/uk/co/westhawk/snmp/stack/TimeWindow.java
new file mode 100644
index 0000000..42ec7c7
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/TimeWindow.java
@@ -0,0 +1,518 @@
+// NAME
+// $RCSfile: TimeWindow.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.15 $
+// CREATED
+// $Date: 2007/04/12 12:55:28 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ */
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import java.util.*;
+
+/**
+ * TimeWindow contains the lookup tables for the engine Id information.
+ * TimeWindow should be created only once. Use the
+ * getCurrent()
+ * method to access any other method, i.e.
+ *
+ * if (TimeWindow.getCurrent() == null)
+ * {
+ * TimeWindow timew = new TimeWindow();
+ * }
+ * boolean known = TimeWindow.getCurrent().isSnmpEngineIdKnown(hostaddr, port);
+ *
+ *
+ *
+ * This class contains two lookup tables. One that maps the
+ * host address+port onto the SNMP engine ID and one that keeps the SNMP
+ * engine ID with the timeline details about this engine.
+ *
+ *
+ * @see #getCurrent()
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.15 $ $Date: 2007/04/12 12:55:28 $
+ */
+public class TimeWindow
+{
+ private static final String version_id =
+ "@(#)$Id: TimeWindow.java,v 3.15 2007/04/12 12:55:28 birgita Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * The maximum number of seconds the engine time in the PDU is allowed
+ * to differ from my estimated engine time. Values 150
.
+ */
+ public final static int MaxTimeDifference = 150;
+
+ private static TimeWindow current = null;
+
+ // lookup table hostaddr:port -> engine id
+ private Hashtable hostLookup;
+
+ // lookup table engine id -> TimeWindowNode
+ private Hashtable engineLookup;
+
+ private long startTime;
+
+/**
+ * Constructor.
+ */
+public TimeWindow()
+{
+ if (current == null)
+ {
+ current = this;
+
+ hostLookup = new Hashtable(5);
+ engineLookup = new Hashtable(5);
+ }
+}
+
+/**
+ * Returns the current reference to this class.
+ * TimeWindow should be created only once. Use this method
+ * to access any other method, i.e.
+ *
+ * if (TimeWindow.getCurrent() == null)
+ * {
+ * TimeWindow timew = new TimeWindow();
+ * }
+ * boolean known = TimeWindow.getCurrent().isSnmpEngineIdKnown(hostaddr, port);
+ *
+ *
+ * @return the current time window
+ */
+public static TimeWindow getCurrent()
+{
+ return current;
+}
+
+/**
+ * Returns the snmp engine ID. This method will lookup the engine ID
+ * based on the host address and port. If it the engine ID is not known, null
+ * will be returned.
+ *
+ * @param hostaddr The host address of the engine ID
+ * @param port The port number of the engine ID
+ * @return the snmp engine ID
+ * @see #isSnmpEngineIdKnown(String, int)
+ */
+public String getSnmpEngineId(String hostaddr, int port)
+{
+ String key = getKey(hostaddr, port);
+ String snmpEngineId = (String) hostLookup.get(key);
+ return snmpEngineId;
+}
+
+/**
+ * Returns if the snmp engine ID is known. This method will lookup if the
+ * engine ID belonging to this hostaddr and port is known.
+ *
+ * When the SNMP engine ID is known, this doesn't necessarily mean that
+ * the timeline details of this engine ID are known, since it takes a
+ * second discovery step to find out.
+ *
+ *
+ * @param hostaddr The host address of the engine ID
+ * @param port The port number of the engine ID
+ * @return whether the snmp engine ID is known
+ */
+public boolean isSnmpEngineIdKnown(String hostaddr, int port)
+{
+ String key = getKey(hostaddr, port);
+ return hostLookup.containsKey(key);
+}
+
+/**
+ * Sets the SNMP engine ID that belongs to the specified hostaddr and port.
+ * The old SNMP engine ID (if any) will be overwritten.
+ *
+ * @param hostaddr The host address of the engine ID
+ * @param port The port number of the engine ID
+ * @param snmpEngineId The engine ID
+ */
+public void setSnmpEngineId(String hostaddr, int port, String snmpEngineId)
+{
+ String key = getKey(hostaddr, port);
+ if (AsnObject.debug > 4)
+ {
+ System.out.println();
+ System.out.println(getClass().getName() + ".setSnmpEngineId(): hostaddr '"
+ + hostaddr + "', port '" + port
+ + "', snmpEngineId '" + snmpEngineId
+ + "', key '" + key + "'"
+ );
+ }
+ hostLookup.put(key, snmpEngineId);
+}
+
+/**
+ * Checks if the engine ID is OK. If there is no engine ID known for
+ * this hostaddr and port, the specified engine ID is added to the table.
+ *
+ * If there is
+ * already an engine ID for this hostaddr and port, the method returns true
+ * if the specified engine ID is the same as the existing one, and false if
+ * they differ. In the latter case the engine ID in the table is not updated.
+ *
+ *
+ * @param hostaddr The host address of the engine ID
+ * @param port The port number of the engine ID
+ * @param snmpEngineId The engine ID
+ * @return whether the engine ID matches the stored engine ID
+ *
+ * @see #setSnmpEngineId(String, int, String)
+ */
+public boolean isEngineIdOK(String hostaddr, int port, String snmpEngineId)
+{
+ boolean ok = true;
+ String key = getKey(hostaddr, port);
+ if (hostLookup.containsKey(key) == false)
+ {
+ setSnmpEngineId(hostaddr, port, snmpEngineId);
+ }
+ else
+ {
+ String myEngineId = getSnmpEngineId(hostaddr, port);
+ if (myEngineId.equalsIgnoreCase(snmpEngineId) == false)
+ {
+ ok = false;
+ }
+ }
+
+ if (AsnObject.debug > 4)
+ {
+ System.out.println();
+ System.out.println(getClass().getName() + ".isEngineIdOK(): hostaddr '"
+ + hostaddr + "', port '" + port
+ + "', snmpEngineId '" + snmpEngineId
+ + "', ok " + ok);
+ }
+ return ok;
+}
+
+/**
+ * Returns if the timeline details of this snmp engine ID are known.
+ *
+ * @param snmpEngineId The engine ID
+ * @return whether the timeline details are known
+ */
+public boolean isTimeLineKnown(String snmpEngineId)
+{
+ return engineLookup.containsKey(snmpEngineId);
+}
+
+/**
+ * Returns if the time details are outside the time window.
+ * When a response or report is received, the stack first checks the time
+ * window before updating it. It always does an update afterwards, even if
+ * the message was outside the time window!
+ *
+ * @param snmpEngineId The SNMP engine ID
+ * @param bootsA The SNMP engine boots
+ * @param timeA The SNMP engine time
+ * @return true if outside or when no details can be found, false if
+ * inside time window
+ * @see #updateTimeWindow(String, int, int, boolean)
+ */
+public boolean isOutsideTimeWindow(String snmpEngineId, int bootsA,
+ int timeA)
+{
+ boolean isOut = false;
+
+ TimeWindowNode node = getTimeLine(snmpEngineId);
+ if (node != null)
+ {
+ int bootsL = node.getSnmpEngineBoots();
+ int timeL = node.getSnmpEngineTime();
+ if (bootsA == TimeWindowNode.maxTime
+ ||
+ bootsA < bootsL
+ ||
+ (bootsA == bootsL && timeA < (timeL-MaxTimeDifference)))
+ {
+ isOut = true;
+ }
+ }
+ else
+ {
+ // We don't have any info, so by definition it is not out.
+ isOut = false;
+ }
+ return isOut;
+}
+
+/**
+ * Tries to update the time window and returns if succeeded.
+ * When a response or report is received, first check the time window
+ * before updating it.
+ *
+ *
+ * An update will only occur if the message was authentic
+ * and the bootsA and timeA meet the requirements.
+ * New data will be inserted if the (bootsA > 0), irrespectively
+ * whether the message was authentic or not.
+ *
+ *
+ * @param snmpEngineId The SNMP engine ID
+ * @param bootsA The SNMP engine boots
+ * @param timeA The SNMP engine time
+ * @return true if update succeeded, or false when not succeeded or when
+ * no details could be found.
+ * @see #isOutsideTimeWindow(String, int, int)
+ */
+public boolean updateTimeWindow(String snmpEngineId, int bootsA, int
+timeA, boolean isAuthentic)
+{
+ boolean updated = false;
+
+ TimeWindowNode node = getTimeLine(snmpEngineId);
+ if (node != null)
+ {
+ if (isAuthentic)
+ {
+ int bootsL = node.getSnmpEngineBoots();
+ int latestL = node.getLatestReceivedEngineTime();
+
+ if (bootsA > bootsL
+ ||
+ (bootsA == bootsL && timeA > latestL))
+ {
+ synchronized (this)
+ {
+ node.setSnmpEngineBoots(bootsA);
+ node.setSnmpEngineTime(timeA);
+ updated = true;
+ }
+ }
+ }
+ }
+ else if (bootsA > 0 || timeA > 0)
+ {
+ // @since 5_2, initially it didn't save when bootsA equals zero
+ node = new TimeWindowNode(snmpEngineId, bootsA, timeA);
+ setTimeLine(snmpEngineId, node);
+ }
+
+ if (AsnObject.debug > 4)
+ {
+ System.out.println();
+ System.out.println(getClass().getName() + ".updateTimeWindow(): snmpEngineId '"
+ + snmpEngineId
+ + "', bootsA " + bootsA
+ + ", timeA " + timeA
+ + ", isAuthentic " + isAuthentic
+ + ", updated " + updated);
+ }
+ return updated;
+}
+
+/**
+ * Clear all timing information for the given engine ID.
+ *
+ * This stinks, but occasionally the router's time window will
+ * slip outside of the acceptable window or will reboot without
+ * updating its "reboots" parameter. If you care more about
+ * security than functionality then never ever use this.
+ * Added on request of Steve A Cochran (steve@more.net).
+ * @param snmpEngineId The engine to clear
+ *
+ * @since 5_2
+ */
+public void clearTimeWindow(String snmpEngineId)
+{
+ if (engineLookup.containsKey(snmpEngineId))
+ {
+ // Remove from engine lookup table
+ engineLookup.remove(snmpEngineId);
+
+ // Remove any entries in the hostLookup table that point to
+ // this snmpEngineId
+ Vector v = new Vector();
+ Iterator i = hostLookup.keySet().iterator();
+ while (i.hasNext())
+ {
+ String key = (String)(i.next());
+ if ((hostLookup.get(key)).equals(snmpEngineId))
+ {
+ v.add(key);
+ }
+ }
+ i = v.iterator();
+ while (i.hasNext())
+ {
+ hostLookup.remove(i.next());
+ }
+ }
+}
+
+
+/**
+ * Updates the estimated engine time of all gathered time details.
+ * It calculates the seconds that passed since the last call and
+ * updates all time window nodes accordingly.
+ *
+ * @see #setTimeLine(String, TimeWindowNode)
+ * @see #getTimeLine(String)
+ */
+protected void updateTimeWindows()
+{
+ if (engineLookup.size() > 0)
+ {
+ long now = System.currentTimeMillis();
+ long milli = now - startTime;
+ int sec = (int)(milli / 1000L);
+
+ long lostMillis = milli - (sec * 1000L);
+ if (lostMillis < 0L)
+ {
+ lostMillis = 0L;
+ }
+ startTime = now - lostMillis;
+
+ Enumeration nodes = engineLookup.elements();
+ while (nodes.hasMoreElements())
+ {
+ TimeWindowNode node = (TimeWindowNode) nodes.nextElement();
+ node.incrementSnmpEngineTime(sec);
+ }
+ }
+ else
+ {
+ startTime = System.currentTimeMillis();
+ }
+}
+
+
+/**
+ * Returns the key to the engine ID lookup table, based on the specified
+ * host address and port.
+ *
+ * @param hostaddr The host address
+ * @param port The port
+ * @return the key
+ */
+protected String getKey(String hostaddr, int port)
+{
+ return hostaddr + ":" + port;
+}
+
+/**
+ * Returns the timeline details of the snmp engine ID.
+ * If there are no matching timeline details for this engine ID, null
+ * will be returned.
+ * The timeline details will be updated before the node is retrieved
+ * from the table.
+ *
+ * @param snmpEngineId The engine ID
+ * @return The timeline details
+ * @see #updateTimeWindows()
+ */
+protected TimeWindowNode getTimeLine(String snmpEngineId)
+{
+ updateTimeWindows();
+ TimeWindowNode node = (TimeWindowNode) engineLookup.get(snmpEngineId);
+ return node;
+}
+
+/**
+ * Sets the timeline details of the snmp engine ID.
+ * The timeline details will be updated before the node is put
+ * in the table.
+ *
+ * @param snmpEngineId The engine ID
+ * @param newNode The added time window node node
+ * @return The timeline details
+ * @see #updateTimeWindows()
+ */
+protected TimeWindowNode setTimeLine(String snmpEngineId,
+ TimeWindowNode newNode)
+{
+ updateTimeWindows();
+ engineLookup.put(snmpEngineId, newNode);
+ if (AsnObject.debug > 4)
+ {
+ System.out.println();
+ System.out.println(getClass().getName() + ".setTimeLine(): snmpEngineId "
+ + snmpEngineId
+ + ", node " + newNode);
+ }
+ return newNode;
+}
+
+/**
+ * Returns the string representation.
+ *
+ * @since 4_14
+ */
+public String toString()
+{
+ StringBuffer buffer = new StringBuffer(this.getClass().getName());
+ buffer.append("[");
+
+ Enumeration enum1 = hostLookup.keys();
+ while (enum1.hasMoreElements())
+ {
+ String key = (String) enum1.nextElement();
+ String snmpEngineId = (String) hostLookup.get(key);
+ TimeWindowNode node = (TimeWindowNode) engineLookup.get(snmpEngineId);
+ buffer.append("\n\t(");
+ if (node == null)
+ {
+ buffer.append("key=").append(key);
+ buffer.append(", engineId=").append(snmpEngineId);
+ }
+ else
+ {
+ buffer.append("key=").append(key).append(", ");
+ buffer.append(node.toString());
+ }
+ buffer.append(") ");
+ }
+
+ buffer.append("]");
+ return buffer.toString();
+}
+
+
+
+}
+
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/TimeWindowNode.java b/src/main/java/uk/co/westhawk/snmp/stack/TimeWindowNode.java
new file mode 100644
index 0000000..6484fc8
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/TimeWindowNode.java
@@ -0,0 +1,189 @@
+// NAME
+// $RCSfile: TimeWindowNode.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.10 $
+// CREATED
+// $Date: 2006/01/17 17:43:54 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ */
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * Node that contains the timeline information of one SNMP Engine ID.
+ * This entry has to be filled in via Discovery.
+ * The node will serve as entry in a lookup table.
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.10 $ $Date: 2006/01/17 17:43:54 $
+ */
+class TimeWindowNode
+{
+ private static final String version_id =
+ "@(#)$Id: TimeWindowNode.java,v 3.10 2006/01/17 17:43:54 birgit Exp $ Copyright Westhawk Ltd";
+
+ public final static int maxTime = 2147483647; // 2^31 -1
+
+ private String snmpEngineId;
+
+ private int snmpEngineBoots = 0;
+ private int snmpEngineTime = 0;
+ private int latestReceivedEngineTime = 0;
+
+/**
+ * Constructor.
+ *
+ * @param engId The engine ID
+ */
+public TimeWindowNode(String engId)
+{
+ this(engId, 0, 0);
+}
+
+/**
+ * Constructor.
+ *
+ * @param engId The engine ID
+ * @param boots The engine boots
+ * @param time The engine time
+ */
+public TimeWindowNode(String engId, int boots, int time)
+{
+ snmpEngineId = engId;
+ snmpEngineBoots = boots;
+ snmpEngineTime = time;
+ latestReceivedEngineTime = time;
+}
+
+
+/**
+ * Returns the snmp engine ID.
+ *
+ * @return the snmp engine ID
+ */
+public String getSnmpEngineId()
+{
+ return snmpEngineId;
+}
+
+/**
+ * Sets the SNMP engine boots
+ *
+ * @param newSnmpEngineBoots The SNMP engine boots
+ */
+public void setSnmpEngineBoots(int newSnmpEngineBoots)
+{
+ snmpEngineBoots = newSnmpEngineBoots;
+}
+
+/**
+ * Returns the SNMP engine boots
+ *
+ * @return The SNMP engine boots
+ */
+public int getSnmpEngineBoots()
+{
+ return snmpEngineBoots;
+}
+
+/**
+ * Sets the SNMP engine time. It also sets the latest received engine
+ * time.
+ *
+ * @param newSnmpEngineTime The SNMP engine time
+ */
+public void setSnmpEngineTime(int newSnmpEngineTime)
+{
+ snmpEngineTime = newSnmpEngineTime;
+ latestReceivedEngineTime = newSnmpEngineTime;
+}
+
+/**
+ * Returns the (estimated) SNMP engine time
+ *
+ * @return The SNMP engine time
+ */
+public int getSnmpEngineTime()
+{
+ return snmpEngineTime;
+}
+
+/**
+ * Increments the engine time. This mechanisme maintains the loosely
+ * time synchronisation.
+ */
+public synchronized void incrementSnmpEngineTime(int incr)
+{
+ snmpEngineTime += incr;
+ if (snmpEngineTime > maxTime)
+ {
+ snmpEngineBoots++;
+ snmpEngineTime -= maxTime;
+ }
+}
+
+/**
+ * Returns the latest received engine time for an engine ID
+ *
+ * @return The latest received engine time
+ */
+public int getLatestReceivedEngineTime()
+{
+ return latestReceivedEngineTime;
+}
+
+/**
+ * Returns a string representation of the object.
+ * @return The string
+ */
+public String toString()
+{
+ StringBuffer buffer = new StringBuffer(this.getClass().getName());
+ buffer.append("[");
+ buffer.append("engineId=").append(snmpEngineId);
+ buffer.append(", engineBoots=").append(snmpEngineBoots);
+ buffer.append(", engineTime=").append(snmpEngineTime);
+ buffer.append(", latestReceivedEngineTime=").append(latestReceivedEngineTime);
+ buffer.append("]");
+ return buffer.toString();
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/Transmitter.java b/src/main/java/uk/co/westhawk/snmp/stack/Transmitter.java
new file mode 100644
index 0000000..d13d25c
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/Transmitter.java
@@ -0,0 +1,189 @@
+// NAME
+// $RCSfile: Transmitter.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.15 $
+// CREATED
+// $Date: 2007/02/05 15:01:20 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1996 - 1998 by Westhawk Ltd (www.westhawk.nl)
+ * Copyright (C) 1998 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+import java.util.*;
+
+/**
+ * Transmitter is a thread that sends PDUs, when done
+ * it waits.
+ *
+ * @author Tim Panton
+ * @version $Revision: 3.15 $ $Date: 2007/02/05 15:01:20 $
+*/
+class Transmitter extends Object implements Runnable
+{
+ private static final String version_id =
+ "@(#)$Id: Transmitter.java,v 3.15 2007/02/05 15:01:20 birgita Exp $ Copyright Westhawk Ltd";
+
+ Pdu pdu = null;
+ Thread me;
+ String myName;
+
+ Transmitter(String name)
+ {
+ me = new Thread(this,name);
+ me.setPriority(me.MIN_PRIORITY);
+ if (AsnObject.debug > 12)
+ {
+ System.out.println("Transmitter(): Made thread " + name);
+ }
+ myName =name;
+ me.start();
+ }
+
+ /**
+ * The method for the Runnable interface.
+ *
+ * It will do a sit() untill stand() wakes it up. The Pdu will then
+ * be transmitted
+ *
+ * @see #sit()
+ * @see #stand()
+ * @see Pdu#transmit()
+ */
+ public void run()
+ {
+ while (me != null)
+ {
+ sit();
+ synchronized (this)
+ {
+ if (pdu != null)
+ {
+ pdu.transmit();
+ // I will say this only once....
+ pdu = null;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the string representation of the Transmitter.
+ *
+ * @return The string of the Transmitter
+ */
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer(getClass().getName());
+ buffer.append("[");
+ buffer.append("name=").append(myName);
+ buffer.append("]");
+ return buffer.toString();
+ }
+
+ synchronized void setPdu(Pdu p)
+ {
+ pdu = p;
+ }
+
+ /**
+ * This method is the counterpart of stand().
+ *
+ * It does not more than waiting to be notified.
+ *
+ * @see #stand()
+ * @see #run()
+ */
+ synchronized void sit()
+ {
+ while ((me != null) && (pdu == null))
+ {
+ try
+ {
+ wait();
+ }
+ catch (InterruptedException iw)
+ {
+ ;
+ }
+
+ }
+ }
+
+ /**
+ * This method is the counterpart of sit().
+ *
+ * The Pdu will call this method when it is sent.
+ * This method will notify itself and in the end it is transmitted
+ * in run.
+ *
+ * @see #sit()
+ * @see #run()
+ * @see Pdu#send
+ */
+ synchronized void stand()
+ {
+ notifyAll();
+ }
+
+ /**
+ * It may be sleeping (as opposed to wait()ing
+ * so send it a kick.
+ */
+ void interruptMe()
+ {
+ // unsafe ?
+ if (me != null)
+ {
+ me.interrupt();
+ }
+ }
+
+ void destroy()
+ {
+ me = null;
+ pdu=null;
+ stand();
+ }
+}
+
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/TrapPduv1.java b/src/main/java/uk/co/westhawk/snmp/stack/TrapPduv1.java
new file mode 100644
index 0000000..d77b0f5
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/TrapPduv1.java
@@ -0,0 +1,390 @@
+// NAME
+// $RCSfile: TrapPduv1.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.14 $
+// CREATED
+// $Date: 2007/10/17 10:44:09 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2001 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import java.util.*;
+import java.io.*;
+import java.net.*;
+
+import uk.co.westhawk.snmp.util.*;
+
+/**
+ * This class represents the ASN SNMPv1 Trap PDU object.
+ * See RFC1157-SNMP.
+ *
+ *
+ * Note that the SNMPv1 Trap PDU is the only PDU with a different PDU
+ * format. It has additional fields like enterprise
,
+ * ipAddress
, genericTrap
,
+ * specificTrap
and timeTicks
.
+ *
+ *
+ * @see TrapPduv2
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.14 $ $Date: 2007/10/17 10:44:09 $
+ */
+public class TrapPduv1 extends Pdu
+{
+ private static final String version_id =
+ "@(#)$Id: TrapPduv1.java,v 3.14 2007/10/17 10:44:09 birgita Exp $ Copyright Westhawk Ltd";
+
+ private String enterprise;
+ private byte[] IpAddress;
+ private int generic_trap;
+ private int specific_trap;
+ private long timeTicks;
+
+ private final static String [] genericTrapStrings =
+ {
+ "Cold Start",
+ "Warm Start",
+ "Link Down",
+ "Link Up",
+ "Authentication Failure",
+ "EGP Neighbor Loss",
+ "Enterprise Specific",
+ };
+
+/**
+ * Constructor.
+ *
+ * @param con The context (v1) of the TrapPduv1
+ * @see SnmpContext
+ */
+public TrapPduv1(SnmpContext con)
+{
+ super(con);
+ setMsgType(AsnObject.TRP_REQ_MSG);
+
+ generic_trap = AsnObject.SNMP_TRAP_WARMSTART;
+}
+
+/**
+ * Constructor.
+ *
+ * @param con The context pool (v1) of the TrapPduv1
+ * @see SnmpContext
+ */
+public TrapPduv1(SnmpContextPool con)
+{
+ super(con);
+ setMsgType(AsnObject.TRP_REQ_MSG);
+
+ generic_trap = AsnObject.SNMP_TRAP_WARMSTART;
+}
+
+/**
+ * Sets the type of object generating the trap. This parameter is based on
+ * the sysObjectId.
+ */
+public void setEnterprise(String var)
+{
+ enterprise = var;
+}
+/**
+ * Returns the type of object generating the trap.
+ */
+public String getEnterprise()
+{
+ return enterprise;
+}
+
+/**
+ * Sets the IP Address of the object generating the trap.
+ */
+public void setIpAddress(byte[] var)
+{
+ IpAddress = var;
+}
+/**
+ * Returns the IP Address of the object generating the trap.
+ */
+public byte[] getIpAddress()
+{
+ return IpAddress;
+}
+
+/**
+ * Sets the generic trap type. By default the warmStart is sent.
+ *
+ * @see SnmpConstants#SNMP_TRAP_COLDSTART
+ * @see SnmpConstants#SNMP_TRAP_WARMSTART
+ * @see SnmpConstants#SNMP_TRAP_LINKDOWN
+ * @see SnmpConstants#SNMP_TRAP_LINKUP
+ * @see SnmpConstants#SNMP_TRAP_AUTHFAIL
+ * @see SnmpConstants#SNMP_TRAP_EGPNEIGHBORLOSS
+ * @see SnmpConstants#SNMP_TRAP_ENTERPRISESPECIFIC
+ */
+public void setGenericTrap(int var)
+{
+ generic_trap = var;
+}
+/**
+ * Returns the generic trap type.
+ */
+public int getGenericTrap()
+{
+ return generic_trap;
+}
+/**
+ * Returns the string representation of the generic trap.
+ *
+ * @return the generic trap string
+ * @see #getGenericTrap
+ */
+public String getGenericTrapString()
+{
+ String trapStr = "";
+ if (generic_trap > -1 && generic_trap < genericTrapStrings.length)
+ {
+ trapStr = genericTrapStrings[generic_trap];
+ }
+ return trapStr;
+}
+
+/**
+ * Sets the specific trap code.
+ */
+public void setSpecificTrap(int var)
+{
+ specific_trap = var;
+}
+/**
+ * Returns the specific trap code.
+ */
+public int getSpecificTrap()
+{
+ return specific_trap;
+}
+
+/**
+ * Sets the sysUpTime of the agent.
+ *
+ *
+ * RFC1155-SMI: TimeTicks:
+ * This application-wide type represents a non-negative integer which
+ * counts the time in hundredths of a second since some epoch. When
+ * object types are defined in the MIB which use this ASN.1 type, the
+ * description of the object type identifies the reference epoch.
+ *
+ */
+public void setTimeTicks(long var)
+{
+ timeTicks = var;
+}
+/**
+ * Returns the sysUpTime of the agent.
+ *
+ * @see #setTimeTicks
+ */
+public long getTimeTicks()
+{
+ return timeTicks;
+}
+
+
+/**
+ * Sends the TrapPduv1. Since the Trap v1 PDU has a different format
+ * (sigh), a different encoding message has to be called.
+ *
+ * Note that all properties of the context have to be set before this
+ * point.
+ */
+public boolean send() throws IOException, PduException
+{
+ if (added == false)
+ {
+ // Moved this statement from the constructor because it
+ // conflicts with the way the SnmpContextXPool works.
+ added = context.addPdu(this);
+ }
+ Enumeration vbs = reqVarbinds.elements();
+ encodedPacket = ((SnmpContext)context).encodePacket(msg_type, enterprise,
+ IpAddress, generic_trap, specific_trap, timeTicks, vbs);
+ addToTrans();
+ return added;
+}
+
+/**
+ * The trap PDU does not get a response back. So it should be sent once.
+ */
+void transmit()
+{
+ transmit(false);
+}
+
+/**
+ * Returns the string representation of this object.
+ *
+ * @return The string of the PDU
+ */
+public String toString()
+{
+ String iPAddressStr = "null";
+ if (IpAddress != null)
+ {
+ iPAddressStr = (new AsnOctets(IpAddress)).toIpAddress();
+ }
+ StringBuffer buffer = new StringBuffer(getClass().getName());
+ buffer.append("[");
+ buffer.append("context=").append(context);
+ buffer.append(", reqId=").append(getReqId() );
+ buffer.append(", msgType=0x").append(SnmpUtilities.toHex(msg_type));
+ buffer.append(", enterprise=").append(enterprise);
+ buffer.append(", IpAddress=").append(iPAddressStr);
+ buffer.append(", generic_trap=").append(getGenericTrapString());
+ buffer.append(", specific_trap=").append(specific_trap);
+ buffer.append(", timeTicks=").append(timeTicks);
+
+ buffer.append(", reqVarbinds=");
+ if (reqVarbinds != null)
+ {
+ int sz = reqVarbinds.size();
+ buffer.append("[");
+ for (int i=0; inot expecting a response.
+ * This method is used in AbstractSnmpContext to help determine whether
+ * or not to start a thread that listens for a response when sending this
+ * PDU.
+ * The default is false.
+ *
+ * @return true if a response is expected, false if not.
+ * @since 4_14
+ */
+protected boolean isExpectingResponse()
+{
+ return false;
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/TrapPduv2.java b/src/main/java/uk/co/westhawk/snmp/stack/TrapPduv2.java
new file mode 100644
index 0000000..7163c08
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/TrapPduv2.java
@@ -0,0 +1,152 @@
+// NAME
+// $RCSfile: TrapPduv2.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.11 $
+// CREATED
+// $Date: 2006/03/23 14:54:10 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2001 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * This class represents the ASN SNMP v2c (and higher) Trap PDU object.
+ * This PDU is not supported in SNMPv1.
+ *
+ *
+ * See SNMPv2-PDU;
+ * The variable bindings list contains the following pairs of object
+ * names and values:
+
+ - sysUpTime.0
+ (SNMPv2-MIB)
+
+ - snmpTrapOID.0: part of the trap group in the SNMPv2 MIB
+ (SNMPv2-MIB)
+
+ - If the OBJECTS clause is present in the corresponding
+ invocation of the macro NOTIFICATION-TYPE, then each corresponding
+ variable and its value are copied to the variable-bindings field.
+
+ - Additional variables may be included at the option of the agent.
+
+
+ *
+ *
+ * For SNMPv3: The sender of a trap PDU acts as the authoritative engine.
+ *
+ *
+ * @see TrapPduv1
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.11 $ $Date: 2006/03/23 14:54:10 $
+ */
+public class TrapPduv2 extends Pdu
+{
+ private static final String version_id =
+ "@(#)$Id: TrapPduv2.java,v 3.11 2006/03/23 14:54:10 birgit Exp $ Copyright Westhawk Ltd";
+
+/**
+ * Constructor.
+ *
+ * @param con The context (v2c or v3) of the PDU
+ * @throws IllegalArgumentException if the context version is
+ * SNMPv1
+ */
+public TrapPduv2(SnmpContextBasisFace con)
+{
+ super(con);
+ setMsgType(AsnObject.TRPV2_REQ_MSG);
+
+ if (con.getVersion() == SnmpConstants.SNMP_VERSION_1)
+ {
+ throw new IllegalArgumentException("A TrapPduv2"
+ + " can only be sent with an SNMPv2c or SNMPv3 context."
+ + " NOT with an SNMPv1 context!");
+ }
+}
+
+/**
+ * The trap PDU does not get a response back. So it should be sent once.
+ *
+ */
+void transmit()
+{
+ transmit(false);
+}
+
+/**
+ * Returns the string representation of this object.
+ *
+ * @return The string of the PDU
+ */
+public String toString()
+{
+ return super.toString(true);
+}
+
+/**
+ * Has no meaning, since there is not response.
+ */
+protected void new_value(int n, varbind res){}
+
+/**
+ * Has no meaning, since there is not response.
+ */
+protected void tell_them(){}
+
+/**
+ * Returns that this type of PDU is not expecting a response.
+ * This method is used in AbstractSnmpContext to help determine whether
+ * or not to start a thread that listens for a response when sending this
+ * PDU.
+ * The default is false.
+ *
+ * @return true if a response is expected, false if not.
+ * @since 4_14
+ */
+protected boolean isExpectingResponse()
+{
+ return false;
+}
+
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/UsmAgent.java b/src/main/java/uk/co/westhawk/snmp/stack/UsmAgent.java
new file mode 100644
index 0000000..c1ea118
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/UsmAgent.java
@@ -0,0 +1,133 @@
+// NAME
+// $RCSfile: UsmAgent.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.8 $
+// CREATED
+// $Date: 2006/03/23 14:54:10 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2001 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * This interface provides the SNMPv3 USM (User-Based Security Model)
+ * authoritative details.
+ *
+ *
+ * When the stack is used as authoritative SNMP engine it has to send
+ * its Engine ID and clock (i.e. Engine Boots and Engine Time) with each
+ * message.
+ * The engine who sends a Response, a Trapv2 or a Report is
+ * authoritative.
+ *
+ *
+ *
+ * Since this stack has no means in providing this information, this
+ * interface has to be implemented by the user.
+ *
+ *
+ *
+ * See SNMP-USER-BASED-SM-MIB.
+ *
+ * @see SnmpContextv3#setUsmAgent
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.8 $ $Date: 2006/03/23 14:54:10 $
+ */
+public interface UsmAgent
+{
+ static final String version_id =
+ "@(#)$Id: UsmAgent.java,v 3.8 2006/03/23 14:54:10 birgit Exp $ Copyright Westhawk Ltd";
+
+/**
+ * This name ("_myusmagent") is used to create an entry in the TimeWindow
+ * for the stack to act as authoritative engine.
+ */
+public String MYFAKEHOSTNAME = "_myusmagent";
+
+/**
+ * Returns the authoritative SNMP Engine ID.
+ * It uniquely and unambiguously identifies the SNMP engine, within an
+ * administrative domain.
+ *
+ *
+ * The Engine ID is the (case insensitive) string representation of a
+ * hexadecimal number, without any prefix, for example
+ * 010000a1d41e4946.
+ *
+ * @see uk.co.westhawk.snmp.util.SnmpUtilities#toBytes(String)
+ */
+public String getSnmpEngineId();
+
+/**
+ * Returns the authoritative Engine Boots.
+ * It is a count of the number of times the SNMP engine has
+ * re-booted/re-initialized since snmpEngineID was last configured.
+ */
+public int getSnmpEngineBoots();
+
+/**
+ * Returns the authoritative Engine Time.
+ * It is the number of seconds since the snmpEngineBoots counter was
+ * last incremented.
+ */
+public int getSnmpEngineTime();
+
+/**
+ * Returns the value of the usmStatsUnknownEngineIDs counter.
+ * The stack needs this when responding to a discovery request.
+ */
+public long getUsmStatsUnknownEngineIDs();
+
+/**
+ * Returns the value of the usmStatsNotInTimeWindows counter.
+ * The stack needs this when responding to a discovery request.
+ */
+public long getUsmStatsNotInTimeWindows();
+
+/**
+ * Sets the current snmp context.
+ */
+public void setSnmpContext(SnmpContextv3Basis context);
+}
+
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/usmStatsConstants.java b/src/main/java/uk/co/westhawk/snmp/stack/usmStatsConstants.java
new file mode 100644
index 0000000..df9254b
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/usmStatsConstants.java
@@ -0,0 +1,138 @@
+// NAME
+// $RCSfile: usmStatsConstants.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.7 $
+// CREATED
+// $Date: 2006/03/23 14:54:10 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2001 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ * This interface contains the OIDs for the usmStats variables.
+ * These variables are returned with the SNMPv3 usm security model when
+ * an error occurs.
+ *
+ * They are part of the
+ * SNMP-USER-BASED-SM-MIB mib.
+ *
+ * @see SnmpContextv3
+ *
+ * @author Birgit Arkesteijn
+ * @version $Revision: 3.7 $ $Date: 2006/03/23 14:54:10 $
+ */
+public interface usmStatsConstants
+{
+ static final String version_id =
+ "@(#)$Id: usmStatsConstants.java,v 3.7 2006/03/23 14:54:10 birgit Exp $ Copyright Westhawk Ltd";
+
+ /**
+ * The total number of packets received by the SNMP engine which
+ * were dropped because they requested a securityLevel that was
+ * unknown to the SNMP engine or otherwise unavailable.
+ */
+ public final static String usmStatsUnsupportedSecLevels = "1.3.6.1.6.3.15.1.1.1";
+
+ /**
+ * The total number of packets received by the SNMP engine which were
+ * dropped because they appeared outside of the authoritative SNMP
+ * engine's window.
+ */
+ public final static String usmStatsNotInTimeWindows = "1.3.6.1.6.3.15.1.1.2";
+
+ /**
+ * The total number of packets received by the SNMP engine which
+ * were dropped because they referenced a user that was not known to
+ * the SNMP engine.
+ */
+ public final static String usmStatsUnknownUserNames = "1.3.6.1.6.3.15.1.1.3";
+
+ /**
+ * The total number of packets received by the SNMP engine which
+ * were dropped because they referenced an snmpEngineID that was not
+ * known to the SNMP engine.
+ */
+ public final static String usmStatsUnknownEngineIDs = "1.3.6.1.6.3.15.1.1.4";
+
+ /**
+ * The total number of packets received by the SNMP engine which
+ * were dropped because they didn't contain the expected digest
+ * value.
+ */
+ public final static String usmStatsWrongDigests = "1.3.6.1.6.3.15.1.1.5";
+
+ /**
+ * The total number of packets received by the SNMP engine which
+ * were dropped because they could not be decrypted.
+ */
+ public final static String usmStatsDecryptionErrors = "1.3.6.1.6.3.15.1.1.6";
+
+ /**
+ * The array with all the usmStats dotted OIDs in it.
+ */
+ public final static String [] usmStatsOids=
+ {
+ usmStatsUnsupportedSecLevels,
+ usmStatsNotInTimeWindows,
+ usmStatsUnknownUserNames,
+ usmStatsUnknownEngineIDs,
+ usmStatsWrongDigests,
+ usmStatsDecryptionErrors
+ };
+
+ /**
+ * The array with all the usmStats verbal OIDs in it.
+ */
+ public final static String [] usmStatsStrings=
+ {
+ "usmStatsUnsupportedSecLevels",
+ "usmStatsNotInTimeWindows",
+ "usmStatsUnknownUserNames",
+ "usmStatsUnknownEngineIDs",
+ "usmStatsWrongDigests",
+ "usmStatsDecryptionErrors"
+ };
+
+}
+
diff --git a/src/main/java/uk/co/westhawk/snmp/stack/varbind.java b/src/main/java/uk/co/westhawk/snmp/stack/varbind.java
new file mode 100644
index 0000000..4181b49
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/stack/varbind.java
@@ -0,0 +1,218 @@
+// NAME
+// $RCSfile: varbind.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 3.10 $
+// CREATED
+// $Date: 2007/10/17 10:47:47 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 1995, 1996 by West Consulting BV
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+/*
+ * Copyright (C) 1996 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.stack;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+
+/**
+ *
+ * This class represents the variable bindings to a PDU.
+ * A variable consists of a name (an AsnObjectId) and a value (an
+ * AsnObject)
+ *
+ *
+ *
+ * The varbind is usually passed to the Observers of the PDU when
+ * notifying them.
+ *
+ *
+ * @see Pdu#addOid(varbind)
+ * @see Pdu#addOid(String, AsnObject)
+ * @author Tim Panton
+ * @version $Revision: 3.10 $ $Date: 2007/10/17 10:47:47 $
+ */
+public class varbind extends Object
+{
+ private static final String version_id =
+ "@(#)$Id: varbind.java,v 3.10 2007/10/17 10:47:47 birgita Exp $ Copyright Westhawk Ltd";
+
+ private AsnObjectId name;
+ private AsnObject value;
+
+ /**
+ * Constructor.
+ * It will clone the varbind given as parameter.
+ *
+ * @param var The varbind
+ */
+ public varbind (varbind var)
+ {
+ name = var.name;
+ value = var.value;
+ }
+
+ /**
+ * Constructor.
+ * The name will be set to the Oid, the value will be set to
+ * AsnNull. This is usually used in Get or GetNext requests.
+ *
+ * @param Oid The oid
+ * @see AsnNull
+ */
+ public varbind(String Oid)
+ {
+ this(new AsnObjectId(Oid), new AsnNull());
+ }
+
+ /**
+ * Constructor.
+ * The name will be set to the Oid, the value will be set to
+ * AsnNull. This is usually used in Get or GetNext requests.
+ *
+ * @param Oid The oid
+ * @see AsnNull
+ */
+ public varbind(AsnObjectId Oid)
+ {
+ this(Oid, new AsnNull());
+ }
+
+ /**
+ * Constructor.
+ * The name and value will be set.
+ * This is usually used in Set requests.
+ *
+ * @param Oid The oid
+ * @param val The value for the varbind
+ */
+ public varbind(String Oid, AsnObject val)
+ {
+ this(new AsnObjectId(Oid), val);
+ }
+
+ /**
+ * Constructor.
+ * The name and value will be set.
+ * This is usually used in Set requests.
+ *
+ * @param Oid The oid
+ * @param val The value for the varbind
+ * @since 4_12
+ */
+ public varbind(AsnObjectId Oid, AsnObject val)
+ {
+ name = Oid;
+ value = val;
+ }
+
+ varbind(AsnSequence vb)
+ throws IllegalArgumentException
+ {
+ Object obj = vb.getObj(0);
+ if (obj instanceof AsnObjectId)
+ {
+ name = (AsnObjectId) obj;
+ value = vb.getObj(1);
+ }
+ else
+ {
+ String msg = "First object should be AsnObjectId, but is ";
+ if (obj != null)
+ {
+ msg += obj.getClass().getName();
+ }
+ else
+ {
+ msg += "null";
+ }
+ throw new IllegalArgumentException(msg);
+ }
+ }
+
+ /**
+ * Returns the oid, this is the name of the varbind.
+ *
+ * @return the name as an AsnObjectId
+ */
+ public AsnObjectId getOid()
+ {
+ return name;
+ }
+
+ /**
+ * Returns the value of the varbind.
+ *
+ * @return the value as AsnObject
+ */
+ public AsnObject getValue()
+ {
+ return value;
+ }
+
+ Object setValue(AsnSequence vb)
+ throws IllegalArgumentException
+ {
+ varbind tmp = new varbind(vb);
+ name = tmp.name;
+ value = tmp.value;
+ return value;
+ }
+
+ /**
+ * Returns the string representation of the varbind.
+ *
+ * @return The string of the varbind
+ */
+ public String toString()
+ {
+ return (name.toString() + ": " + value.toString());
+ }
+}
diff --git a/src/main/java/uk/co/westhawk/snmp/util/SnmpUtilities.java b/src/main/java/uk/co/westhawk/snmp/util/SnmpUtilities.java
new file mode 100644
index 0000000..6b460f5
--- /dev/null
+++ b/src/main/java/uk/co/westhawk/snmp/util/SnmpUtilities.java
@@ -0,0 +1,1108 @@
+// NAME
+// $RCSfile: SnmpUtilities.java,v $
+// DESCRIPTION
+// [given below in javadoc format]
+// DELTA
+// $Revision: 1.27 $
+// CREATED
+// $Date: 2009/03/05 12:57:57 $
+// COPYRIGHT
+// Westhawk Ltd
+// TO DO
+//
+
+/*
+ * Copyright (C) 2000 - 2006 by Westhawk Ltd
+ * www.westhawk.co.uk
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ * This software is provided "as is" without express or implied
+ * warranty.
+ * author Tim Panton
+ */
+
+package uk.co.westhawk.snmp.util;
+
+/*-
+ * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
+ * SNMP Java Client
+ * ჻჻჻჻჻჻
+ * Copyright 2023 Sentry Software, Westhawk
+ * ჻჻჻჻჻჻
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
+ */
+import java.io.*;
+import java.util.*;
+import uk.co.westhawk.snmp.stack.*;
+
+import org.bouncycastle.crypto.*;
+import org.bouncycastle.crypto.digests.*;
+import org.bouncycastle.crypto.params.*;
+import org.bouncycastle.crypto.engines.*;
+
+
+/**
+ * This class contains utilities for key and authentication encoding.
+ * See SNMP-USER-BASED-SM-MIB.
+ *
+ * @author Tim Panton
+ * @version $Revision: 1.27 $ $Date: 2009/03/05 12:57:57 $
+ */
+public class SnmpUtilities extends Object
+{
+ private static final String version_id =
+ "@(#)$Id: SnmpUtilities.java,v 1.27 2009/03/05 12:57:57 birgita Exp $ Copyright Westhawk Ltd";
+
+ final static int ONEMEG = 1048576;
+ final static int SALT_LENGTH = 8; // in bytes
+
+ private static int salt_count = -1;
+ private static long asalt;
+
+
+/**
+ * Returns the String representation of the SNMP version number.
+ * @param version The version number
+ * @return The corresponding String.
+ */
+public static String getSnmpVersionString(int version)
+{
+ String versionString;
+
+ switch (version)
+ {
+ case SnmpConstants.SNMP_VERSION_1:
+ versionString = "SNMPv1";
+ break;
+ case SnmpConstants.SNMP_VERSION_2c:
+ versionString = "SNMPv2c";
+ break;
+ case SnmpConstants.SNMP_VERSION_3:
+ versionString = "SNMPv3";
+ break;
+ default:
+ versionString = "Unsupported version no " + version;
+ }
+ return versionString;
+}
+
+/**
+ * Converts a hexadecimal ASCII string to a byte array. The method is case
+ * insensitive, so F7 works as well as f7. The string should have
+ * the form F7d820 and should omit the '0x'.
+ * This method is the reverse of toHexString
.
+ *
+ * @param hexStr The string representing a hexadecimal number
+ * @return the byte array of hexStr
+ * @see #toHexString(byte[])
+ */
+public static byte [] toBytes(String hexStr)
+{
+ byte mask = (byte) 0x7F;
+ byte [] bytes = new byte[0];
+
+ if (hexStr != null)
+ {
+ hexStr = hexStr.toUpperCase();
+ int len = hexStr.length();
+ bytes = new byte[(len/2)];
+ int sPos=0; // position in hexStr
+ int bPos=0; // position in bytes
+ while (sPos 255))
+ {
+ throw new IllegalArgumentException("Valid byte values are between 0 and 255."
+ + "Got " + l);
+ }
+ ret = (byte)(l);
+ return ret;
+}
+
+
+/**
+ * Converts an array of long values to its array of byte values.
+ *
+ * @param l The array of longs
+ * @return The array of bytes
+ * @throws IllegalArgumentException when one of the longs is not in between 0 and 255.
+ *
+ * @see #longToByte(long)
+ * @since 4_14
+ */
+public static byte[] longToByte(long[] l) throws IllegalArgumentException
+{
+ int len = l.length;
+ byte [] ret = new byte[len];
+ for (int i=0; itoBytes.
+ *
+ * @param bytes The byte array
+ * @return The string representing the byte array
+ * @see #toBytes(String)
+ */
+public static String toHexString(byte[] bytes)
+{
+ String str = "";
+ if (bytes != null)
+ {
+ int len = bytes.length;
+ for (int i=0; i> 4) & 0x0F;
+ val2 = (val & 0x0F);
+
+ return ("" + HEX_DIGIT[val1] + HEX_DIGIT[val2]);
+}
+
+final static char[] HEX_DIGIT = {'0','1','2','3','4','5','6','7',
+ '8','9','A','B','C','D','E','F'};
+
+
+/**
+ * Compaires two byte arrays and returns if they are equal.
+ *
+ * @param array1 the first byte array
+ * @param array2 the second byte array
+ * @return whether they are equal of not.
+ */
+public static boolean areBytesEqual(byte[] array1, byte[] array2)
+{
+ boolean same = true;
+ int len1 = array1.length;
+ if (len1 == array2.length)
+ {
+ int i=0;
+ while (iSNMP-USER-BASED-SM-MIB.
+ *
+ * @param passwKey The password key
+ * @param engineId The SNMP engine Id
+ * @see SnmpContextv3#setUserAuthenticationPassword(String)
+ * @see #passwordToKeyMD5(String)
+ */
+public static byte [] getLocalizedKeyMD5(byte[] passwKey, String engineId)
+{
+ byte [] ret = null;
+ MD5Digest mdc = new MD5Digest();
+ mdc.reset();
+
+ byte [] beid = toBytes(engineId);
+ if ((beid != null) && (passwKey != null))
+ {
+ // see page 169 of 0-13-021453-1 A Practical Guide to SNMP
+ mdc.update(passwKey, 0, passwKey.length);
+ mdc.update(beid, 0, beid.length);
+ mdc.update(passwKey, 0, passwKey.length);
+ ret = new byte[mdc.getDigestSize()];
+ mdc.doFinal(ret, 0);
+ }
+ return ret;
+}
+
+/**
+ * Converts the user's password and the SNMP Engine Id to the localized key
+ * using the SHA protocol.
+ *
+ * @param passwKey The printable user password
+ * @param engineId The SNMP engine Id
+ * @see SnmpContextv3#setUserAuthenticationPassword(String)
+ */
+public static byte [] getLocalizedKeySHA1(byte[] passwKey, String engineId)
+{
+ byte [] ret = null;
+ SHA1Digest mdc = new SHA1Digest();
+ mdc.reset();
+
+ byte [] beid = toBytes(engineId);
+ if ((beid != null) && (passwKey != null))
+ {
+ // see page 169 of 0-13-021453-1 A Practical Guide to SNMP
+ mdc.update(passwKey, 0, passwKey.length);
+ mdc.update(beid, 0, beid.length);
+ mdc.update(passwKey, 0, passwKey.length);
+ ret = new byte[mdc.getDigestSize()];
+ mdc.doFinal(ret, 0);
+ }
+ return ret;
+}
+
+
+/**
+ * Converts the user's password to an authentication key using the SHA1
+ * protocol. Note, this is not the same as generating the localized key
+ * as is
+ * described in SNMP-USER-BASED-SM-MIB.
+ *
+ * @param password The printable user password
+ * @see SnmpContextv3#setUserAuthenticationPassword(String)
+ * @see #getLocalizedKeyMD5
+ */
+public static byte [] passwordToKeySHA1(String password)
+{
+ SHA1Digest sha;
+ byte [] ret =null;
+ sha = new SHA1Digest();
+ byte [] passwordBuf = new byte[64];
+ int pl = password.length();
+ byte [] pass = new byte[pl];
+
+ // copy to byte array - stripping off top byte
+ for (int i=0;i 1) ? new Date() : null ;
+
+ synchronized (sha)
+ {
+ while (count < ONEMEG)
+ {
+ int cp = 0;
+ int i=0;
+ while (i<64)
+ {
+ int pim = passwordIndex % pl;
+ int len = 64 - cp ;
+ int pr = pl - pim;
+ if (len > pr)
+ {
+ len = pr;
+ }
+ System.arraycopy(pass, pim, passwordBuf, cp, len);
+ i+= len;
+ cp+=len;
+ passwordIndex += len;
+ }
+
+ // need to optimize this.....
+ sha.update(passwordBuf, 0, passwordBuf.length);
+ count += 64;
+ }
+ // implicit that ONEMEG % 64 == 0
+ ret = new byte[sha.getDigestSize()];
+ sha.doFinal(ret, 0);
+ }
+
+ if (AsnObject.debug > 1)
+ {
+ Date now = new Date();
+ long diff = now.getTime() - then.getTime();
+ System.out.println("(Complex) pass to key takes " + diff/1000.0);
+ }
+
+ return ret;
+}
+/**
+ * Converts the user's password to an authentication key using the MD5
+ * protocol. Note, this is not the same as generating the localized key
+ * as is
+ * described in SNMP-USER-BASED-SM-MIB.
+ *
+ * @param password The printable user password
+ * @see SnmpContextv3#setUserAuthenticationPassword(String)
+ * @see #getLocalizedKeyMD5
+ */
+public static byte [] passwordToKeyMD5(String password)
+{
+ MD5Digest mdc;
+ byte [] ret =null;
+ mdc = new MD5Digest();
+ byte [] passwordBuf = new byte[64];
+ int pl = password.length();
+ byte [] pass = new byte[pl];
+
+ // copy to byte array - stripping off top byte
+ for (int i=0;i 1) ? new Date() : null ;
+ synchronized (mdc)
+ {
+ while (count < ONEMEG)
+ {
+ int cp = 0;
+ int i=0;
+ while (i<64)
+ {
+ int pim = passwordIndex % pl;
+ int len = 64 - cp ;
+ int pr = pl - pim;
+ if (len > pr)
+ {
+ len = pr;
+ }
+ System.arraycopy(pass, pim, passwordBuf, cp, len);
+ i+= len;
+ cp+=len;
+ passwordIndex += len;
+ }
+ mdc.update(passwordBuf, 0, passwordBuf.length);
+ count += 64;
+ }
+ // implicit that ONEMEG % 64 == 0
+ ret = new byte[mdc.getDigestSize()];
+ mdc.doFinal(ret, 0);
+ }
+
+ if (AsnObject.debug > 1)
+ {
+ Date now = new Date();
+ long diff = now.getTime() - then.getTime();
+ System.out.println("(Complex) pass to key takes "+diff/1000.0);
+ }
+
+ return ret;
+}
+
+
+/**
+ * Returns the 12 byte MD5 fingerprint.
+ * @param key The key
+ * @param message The message
+ * @see #getFingerPrintSHA1
+ */
+public final static byte [] getFingerPrintMD5(byte [] key, byte [] message)
+{
+ if ((AsnObject.debug > 5) && (key.length != 16))
+ {
+ System.out.println("MD5 key length wrong");
+ }
+ return getFingerPrint(key, message, false);
+}
+
+/**
+ * Returns the 12 byte SHA1 fingerprint.
+ * @param key The key
+ * @param message The message
+ * @see #getFingerPrintMD5
+ */
+public final static byte [] getFingerPrintSHA1(byte [] key, byte [] message)
+{
+ if ((AsnObject.debug > 5) && (key.length != 20))
+ {
+ System.out.println("SHA1 key length wrong");
+ }
+ return getFingerPrint(key, message, true);
+}
+
+
+/**
+ * Returns the DES salt.
+ * The "salt" value is generated by concatenating the 32-bit
+ * snmpEngineBoots value with a 32-bit counter value that the encryption
+ * engine maintains. This 32-bit counter will be initialised to some
+ * arbitrary value at boot time.
+ *
+ *
+ * See "A Practical Guide to SNMPv3 and Network Management" section 6.8
+ * Privacy, p 194.
+ *
+ *
+ * @param snmpEngineBoots The (estimated) boots of the authoritative engine
+ * @return The salt
+ */
+public final static byte[] getSaltDES(int snmpEngineBoots)
+{
+ if (salt_count == -1)
+ {
+ // initialise the 2nd part of the salt
+ Random rand = new Random();
+ salt_count = rand.nextInt();
+ }
+ byte [] salt = new byte[SALT_LENGTH];
+ setBytesFromInt(salt, snmpEngineBoots, 0);
+ setBytesFromInt(salt, salt_count, SALT_LENGTH/2);
+ salt_count++;
+ return salt;
+}
+
+/*
+ *
+ * The 64-bit integer is then put into the msgPrivacyParameters field encoded
+ * as an OCTET STRING of length 8 octets.
+ * The integer is then modified for the subsequent message.
+ * We recommend that it is incremented by one until it reaches its
+ * maximum value,
+ * at which time it is wrapped.
+ * An implementation can use any method to vary the value of the local
+ * 64-bit integer,
+ * providing the chosen method never generates a duplicate IV for the
+ * same key.
+ *
+ */
+
+/**
+ * Returns the AES salt.
+ * @return The salt
+ */
+public static byte[] getSaltAES()
+{
+ if (asalt == 0)
+ {
+ java.security.SecureRandom rand = new java.security.SecureRandom();
+ asalt = rand.nextLong();
+ }
+ else
+ {
+ asalt ++;
+ }
+ byte [] tsalt = new byte[8];
+ setBytesFromLong(tsalt, asalt, 0);
+ return tsalt;
+}
+
+/**
+ * Returns the DES key.
+ * The 16-byte secret privacy key is made up of 8 bytes that
+ * make up the DES key and 8 bytes used as a preinitialisation
+ * vector.
+ *
+ * @param secretPrivacyKey The secret privacy key
+ * @return The key
+ */
+public final static byte[] getDESKey(byte[] secretPrivacyKey)
+throws PduException
+{
+ byte [] desKey = new byte[8];
+ if (secretPrivacyKey.length < 16)
+ {
+ throw new PduException("SnmpUtilities.getDESKey():"
+ + " secretPrivacyKey is < 16");
+ }
+ System.arraycopy(secretPrivacyKey, 0, desKey, 0, 8);
+ return desKey;
+}
+
+/**
+ * Returns the first 128 bits of the localized key Kul are used as the
+ * AES encryption key.
+ * @param secretPrivacyKey The secret privacy key
+ * @return The key
+ */
+public final static byte[] getAESKey(byte[] secretPrivacyKey)
+throws PduException
+{
+ byte [] aesKey = new byte[16];
+ if (secretPrivacyKey.length < 16)
+ {
+ throw new PduException("SnmpUtilities.getAESKey():"
+ + " secretPrivacyKey is < 16");
+ }
+ System.arraycopy(secretPrivacyKey, 0, aesKey, 0, 16);
+ return aesKey;
+}
+
+
+/**
+ * Returns the DES initial value.
+ * The 16-byte secret privacy key is made up of 8 bytes that
+ * make up the DES key and 8 bytes used as a preinitialisation
+ * vector.
+ * The initialization vector that is used by the DES algorithm is the
+ * result of the 8-byte preinitialisation vector XOR-ed with the 8-byte
+ * "salt".
+ *
+ * @param secretPrivacyKey The secret privacy key
+ * @param salt The salt
+ * @return The initial value
+ */
+public final static byte[] getDESInitialValue(byte[] secretPrivacyKey,
+ byte [] salt) throws PduException
+{
+ byte [] initV = new byte[8];
+ if (secretPrivacyKey.length < 16)
+ {
+ throw new PduException("SnmpUtilities.getInitialValue():"
+ + " secretPrivacyKey is < 16");
+ }
+
+ int spk = 8;
+ for (int i=0; i 0)
+ {
+ div ++;
+ }
+ int newL = div*8;
+ byte[] paddedOrig = new byte[newL];
+ System.arraycopy(plain, 0, paddedOrig, 0, l);
+ for (int i=l; i
+ *
+ * If the length of the data portion is not a multiple of 8 bytes, the
+ * message is discarded.
+ *
+ *
+ * The first encrypted text block is decrypted. The decryption result is
+ * XOR-ed with the initialization vector, and the result is the first
+ * plaintext block.
+ *
+ *
+ * The rest of the encrypted text blocks are treated similarly. They are
+ * decrypted, with the results being XOR-ed with the previous encrypted
+ * text block to obtain the plaintext block.
+ *
+ *
+ *
+ * @param encryptedText The encrypted text
+ * @param salt The salt
+ * @param secretPrivacyKey The secret privacy key
+ * @return The decrypted bytes
+ */
+public final static byte[] DESdecrypt(byte[] encryptedText, byte[] salt,
+ byte[] secretPrivacyKey) throws DecodingException
+{
+ int l = encryptedText.length;
+ int div = l / 8;
+ int mod = l % 8;
+ if (mod != 0)
+ {
+ throw new DecodingException("SnmpUtilities.decrypt():"
+ + " The encrypted scoped PDU should be a multiple of 8 bytes");
+ }
+
+ byte[] desKey = null;
+ byte[] iv = null;
+ try
+ {
+ desKey = getDESKey(secretPrivacyKey);
+ iv = getDESInitialValue(secretPrivacyKey, salt);
+ }
+ catch (PduException exc)
+ {
+ throw new DecodingException(exc.getMessage());
+ }
+
+ DESEngine des = new DESEngine();
+ DESParameters param = new DESParameters(desKey);
+ des.init(false, param);
+
+ byte[] plain = new byte[l];
+ byte [] in = new byte[8];
+ byte [] out = new byte[8];
+ byte [] cipherText = iv;
+ int posPlain = 0;
+ int posEncr = 0;
+ for (int b=0; b>> 24) & 0xFF);
+ ret[j++] = (byte)((v >>> 16) & 0xFF);
+ ret[j++] = (byte)((v >>> 8) & 0xFF);
+ ret[j++] = (byte)((v >>> 0) & 0xFF);
+}
+
+final static void setBytesFromLong(byte[] ret, long value, int offs)
+{
+ long v = value ;
+ int j = offs;
+ ret[j++] = (byte)((v >>> 56) & 0xFF);
+ ret[j++] = (byte)((v >>> 48) & 0xFF);
+ ret[j++] = (byte)((v >>> 40) & 0xFF);
+ ret[j++] = (byte)((v >>> 32) & 0xFF);
+ ret[j++] = (byte)((v >>> 24) & 0xFF);
+ ret[j++] = (byte)((v >>> 16) & 0xFF);
+ ret[j++] = (byte)((v >>> 8) & 0xFF);
+ ret[j++] = (byte)((v >>> 0) & 0xFF);
+}
+
+}
diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md
index 149e5aa..39cbcc8 100644
--- a/src/site/markdown/index.md
+++ b/src/site/markdown/index.md
@@ -1,3 +1,64 @@
-# Documentation
+# SNMP Java Client
+The SNMP Java client enables you to run SNMP operations, including:
-This is the documentation.
+- SNMP Client initialization
+- Execution of single requests (`Get` and `GetNext`) , as well as multiple request functionalities (`Walk` and `Table`)
+- Request execution on remote devices, supporting SNMP v1, v2c, or v3 implementations
+
+# How to run the SNMP Client inside Java
+
+Add SNMP in the list of dependencies in your [Maven pom.xml](pom.xml):
+
+```
+
+
+
+ org.sentrysoftware
+ snmp
+ ${project.version}
+
+
+```
+
+Invoke the SNMP Client:
+
+```
+ public static void main(String[] args) throws Exception {
+ final String hostname = "my-hostname";
+ final int port = 161;
+ final int version = SnmpClient.SNMP_V2C;
+ final int[] retryIntervals = { 500, 1000, 2000 };
+ final String community = "my-community";
+ final String authType = null; // SnmpClient.SNMP_AUTH_MD5;
+ final String authUsername = null; // "my-username";
+ final String authPassword = null; // "my-auth-password";
+ final String privacyType = null; // SnmpClient.SNMP_PRIVACY_AES;
+ final String privacyPassword = null; // "my-privacy-password";
+ final String contextName = null; // "my-context-name";
+ final byte[] contextID = {};
+
+ // Initialize the SNMP Client
+ final SnmpClient snmpClient = new SnmpClient(
+ hostname,
+ port,
+ version,
+ retryIntervals,
+ community,
+ authType,
+ authUsername,
+ authPassword,
+ privacyType,
+ privacyPassword,
+ contextName,
+ contextID
+ );
+
+ // MIB 2 DOD OID
+ final String oid = "1.3.6";
+
+ // Perform a GetNext operation on the specified MIB 2 OID
+ final String result = snmpClient.getNext(oid);
+
+ System.out.println("SNMP GetNext Result: " + result);
+ }
+```
diff --git a/src/site/resources/images/sentry-logo-179x75px.png b/src/site/resources/images/sentry-logo-179x75px.png
index bdd5fa5..42e53f7 100644
Binary files a/src/site/resources/images/sentry-logo-179x75px.png and b/src/site/resources/images/sentry-logo-179x75px.png differ
diff --git a/src/site/site.xml b/src/site/site.xml
index b6f8d7f..542653c 100644
--- a/src/site/site.xml
+++ b/src/site/site.xml
@@ -9,18 +9,22 @@
true
- open source,oss
+ snmp
+
+ images/sentry-logo-179x75px.png
+ https://sentrysoftware.com
+
-