0001: /*
0002: * SNMP Package
0003: *
0004: * Copyright (C) 2004, Jonathan Sevy <jsevy@mcs.drexel.edu>
0005: *
0006: * This is free software. Redistribution and use in source and binary forms, with
0007: * or without modification, are permitted provided that the following conditions
0008: * are met:
0009: *
0010: * 1. Redistributions of source code must retain the above copyright notice, this
0011: * list of conditions and the following disclaimer.
0012: * 2. Redistributions in binary form must reproduce the above copyright notice,
0013: * this list of conditions and the following disclaimer in the documentation
0014: * and/or other materials provided with the distribution.
0015: * 3. The name of the author may not be used to endorse or promote products
0016: * derived from this software without specific prior written permission.
0017: *
0018: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
0019: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
0020: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
0021: * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
0023: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0024: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
0025: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0026: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0027: *
0028: */
0029:
0030: package snmp;
0031:
0032: import java.io.*;
0033: import java.net.*;
0034:
0035: /**
0036: * The class SNMPv1CommunicationInterface defines methods for communicating with SNMP entities.
0037: * The approach is that from version 1 of SNMP, using no encryption of data. Communication occurs
0038: * via UDP, using port 161, the standard SNMP port, unless an alternate (non-standard) port is
0039: * supplied in the constructor.
0040: */
0041:
0042: public class SNMPv1CommunicationInterface {
0043: public static final int SNMP_PORT = 161;
0044:
0045: // port to which requests will be sent
0046: private int remotePort = SNMP_PORT;
0047:
0048: // largest size for datagram packet payload; based on
0049: // RFC 1157, need to handle messages of at least 484 bytes
0050: private int receiveBufferSize = 512;
0051:
0052: private int version;
0053: private InetAddress hostAddress;
0054: private String community;
0055: DatagramSocket dSocket;
0056:
0057: public int requestID = 1;
0058:
0059: /**
0060: * Construct a new communication object to communicate with the specified host using the
0061: * given community name. The version setting should be either 0 (version 1) or 1 (version 2,
0062: * a la RFC 1157).
0063: */
0064:
0065: public SNMPv1CommunicationInterface(int version,
0066: InetAddress hostAddress, String community)
0067: throws SocketException {
0068: this (version, hostAddress, community, SNMP_PORT);
0069: }
0070:
0071: /**
0072: * Construct a new communication object to communicate with the specified host using the
0073: * given community name, and sending requests to the specified port. The version setting
0074: * should be either 0 (version 1) or 1 (version 2, a la RFC 1157).
0075: */
0076:
0077: public SNMPv1CommunicationInterface(int version,
0078: InetAddress hostAddress, String community, int remotePort)
0079: throws SocketException {
0080: this .remotePort = remotePort;
0081: this .version = version;
0082: this .hostAddress = hostAddress;
0083: this .community = community;
0084:
0085: dSocket = new DatagramSocket();
0086: dSocket.setSoTimeout(15000); //15 seconds
0087: }
0088:
0089: /**
0090: * Permits setting timeout value for underlying datagram socket (in milliseconds).
0091: */
0092:
0093: public void setSocketTimeout(int socketTimeout)
0094: throws SocketException {
0095: dSocket.setSoTimeout(socketTimeout);
0096: }
0097:
0098: /**
0099: * Close the "connection" with the device.
0100: */
0101:
0102: public void closeConnection() throws SocketException {
0103: dSocket.close();
0104: }
0105:
0106: /**
0107: * Retrieve all MIB variable values subsequent to the starting object identifier
0108: * given in startID (in dotted-integer notation). Return as SNMPVarBindList object.
0109: * Uses SNMPGetNextRequests to retrieve variable values in sequence.
0110: * @throws IOException Thrown when timeout experienced while waiting for response to request.
0111: * @throws SNMPBadValueException
0112: */
0113:
0114: public SNMPVarBindList retrieveAllMIBInfo(String startID)
0115: throws IOException, SNMPBadValueException {
0116: // send GetNextRequests until receive
0117: // an error message or a repeat of the object identifier we sent out
0118: SNMPVarBindList retrievedVars = new SNMPVarBindList();
0119:
0120: int errorStatus = 0;
0121: int errorIndex = 0;
0122:
0123: SNMPObjectIdentifier requestedObjectIdentifier = new SNMPObjectIdentifier(
0124: startID);
0125: SNMPVariablePair nextPair = new SNMPVariablePair(
0126: requestedObjectIdentifier, new SNMPNull());
0127: SNMPSequence varList = new SNMPSequence();
0128: varList.addSNMPObject(nextPair);
0129: SNMPPDU pdu = new SNMPPDU(SNMPBERCodec.SNMPGETNEXTREQUEST,
0130: requestID, errorStatus, errorIndex, varList);
0131: SNMPMessage message = new SNMPMessage(version, community, pdu);
0132: byte[] messageEncoding = message.getBEREncoding();
0133: DatagramPacket outPacket = new DatagramPacket(messageEncoding,
0134: messageEncoding.length, hostAddress, remotePort);
0135:
0136: dSocket.send(outPacket);
0137:
0138: while (errorStatus == 0) {
0139:
0140: DatagramPacket inPacket = new DatagramPacket(
0141: new byte[receiveBufferSize], receiveBufferSize);
0142:
0143: dSocket.receive(inPacket);
0144:
0145: byte[] encodedMessage = inPacket.getData();
0146:
0147: SNMPMessage receivedMessage = new SNMPMessage(SNMPBERCodec
0148: .extractNextTLV(encodedMessage, 0).value);
0149: //errorStatus = ((BigInteger)((SNMPInteger)((receivedMessage.getPDU()).getSNMPObjectAt(1))).getValue()).intValue();
0150:
0151: varList = (receivedMessage.getPDU()).getVarBindList();
0152: SNMPSequence newPair = (SNMPSequence) (varList
0153: .getSNMPObjectAt(0));
0154:
0155: SNMPObjectIdentifier newObjectIdentifier = (SNMPObjectIdentifier) (newPair
0156: .getSNMPObjectAt(0));
0157: SNMPObject newValue = newPair.getSNMPObjectAt(1);
0158:
0159: retrievedVars.addSNMPObject(newPair);
0160:
0161: if (requestedObjectIdentifier.equals(newObjectIdentifier))
0162: break;
0163:
0164: requestedObjectIdentifier = newObjectIdentifier;
0165:
0166: requestID++;
0167: nextPair = new SNMPVariablePair(requestedObjectIdentifier,
0168: new SNMPNull());
0169: varList = new SNMPSequence();
0170: varList.addSNMPObject(nextPair);
0171: pdu = new SNMPPDU(SNMPBERCodec.SNMPGETNEXTREQUEST,
0172: requestID, errorStatus, errorIndex, varList);
0173: message = new SNMPMessage(version, community, pdu);
0174: messageEncoding = message.getBEREncoding();
0175: outPacket = new DatagramPacket(messageEncoding,
0176: messageEncoding.length, hostAddress, remotePort);
0177:
0178: dSocket.send(outPacket);
0179:
0180: }
0181:
0182: return retrievedVars;
0183:
0184: }
0185:
0186: private String hexByte(byte b) {
0187: int pos = b;
0188: if (pos < 0)
0189: pos += 256;
0190: String returnString = new String();
0191: returnString += Integer.toHexString(pos / 16);
0192: returnString += Integer.toHexString(pos % 16);
0193: return returnString;
0194: }
0195:
0196: /**
0197: * Retrieve the MIB variable value corresponding to the object identifier
0198: * given in itemID (in dotted-integer notation). Return as SNMPVarBindList object; if no
0199: * such variable (either due to device not supporting it, or community name having incorrect
0200: * access privilege), SNMPGetException thrown
0201: * @throws IOException Thrown when timeout experienced while waiting for response to request.
0202: * @throws SNMPBadValueException
0203: * @throws SNMPGetException Thrown if supplied OID has value that can't be retrieved
0204: */
0205:
0206: public SNMPVarBindList getMIBEntry(String itemID)
0207: throws IOException, SNMPBadValueException, SNMPGetException {
0208: // send GetRequest to specified host to retrieve specified object identifier
0209:
0210: SNMPVarBindList retrievedVars = new SNMPVarBindList();
0211:
0212: int errorStatus = 0;
0213: int errorIndex = 0;
0214:
0215: SNMPObjectIdentifier requestedObjectIdentifier = new SNMPObjectIdentifier(
0216: itemID);
0217: SNMPVariablePair nextPair = new SNMPVariablePair(
0218: requestedObjectIdentifier, new SNMPNull());
0219: SNMPSequence varList = new SNMPSequence();
0220: varList.addSNMPObject(nextPair);
0221: SNMPPDU pdu = new SNMPPDU(SNMPBERCodec.SNMPGETREQUEST,
0222: requestID, errorStatus, errorIndex, varList);
0223:
0224: SNMPMessage message = new SNMPMessage(version, community, pdu);
0225:
0226: byte[] messageEncoding = message.getBEREncoding();
0227:
0228: /*
0229: System.out.println("Request Message bytes:");
0230:
0231: for (int i = 0; i < messageEncoding.length; ++i)
0232: System.out.print(hexByte(messageEncoding[i]) + " ");
0233: */
0234:
0235: DatagramPacket outPacket = new DatagramPacket(messageEncoding,
0236: messageEncoding.length, hostAddress, remotePort);
0237:
0238: dSocket.send(outPacket);
0239:
0240: while (true) // wait until receive reply for requestID & OID (or error)
0241: {
0242:
0243: DatagramPacket inPacket = new DatagramPacket(
0244: new byte[receiveBufferSize], receiveBufferSize);
0245:
0246: dSocket.receive(inPacket);
0247:
0248: byte[] encodedMessage = inPacket.getData();
0249:
0250: /*
0251: System.out.println("Message bytes:");
0252:
0253: for (int i = 0; i < encodedMessage.length; ++i)
0254: {
0255: System.out.print(hexByte(encodedMessage[i]) + " ");
0256: }
0257: */
0258:
0259: SNMPMessage receivedMessage = new SNMPMessage(SNMPBERCodec
0260: .extractNextTLV(encodedMessage, 0).value);
0261: SNMPPDU receivedPDU = receivedMessage.getPDU();
0262:
0263: // check request identifier; if incorrect, just ignore packet and continue waiting
0264: if (receivedPDU.getRequestID() == requestID) {
0265:
0266: // check error status; if retrieval problem, throw SNMPGetException
0267: if (receivedPDU.getErrorStatus() != 0)
0268: throw new SNMPGetException("OID " + itemID
0269: + " not available for retrieval",
0270: receivedPDU.getErrorIndex(), receivedPDU
0271: .getErrorStatus());
0272:
0273: varList = receivedPDU.getVarBindList();
0274: SNMPSequence newPair = (SNMPSequence) (varList
0275: .getSNMPObjectAt(0));
0276:
0277: SNMPObjectIdentifier newObjectIdentifier = (SNMPObjectIdentifier) (newPair
0278: .getSNMPObjectAt(0));
0279: SNMPObject newValue = newPair.getSNMPObjectAt(1);
0280:
0281: // check the object identifier to make sure the correct variable has been received;
0282: // if not, just continue waiting for receive
0283: if (newObjectIdentifier.toString().equals(itemID)) {
0284: // got the right one; add it to retrieved var list and break!
0285: retrievedVars.addSNMPObject(newPair);
0286: break;
0287: }
0288:
0289: }
0290:
0291: }
0292:
0293: requestID++;
0294:
0295: return retrievedVars;
0296:
0297: }
0298:
0299: /**
0300: * Retrieve the MIB variable values corresponding to the object identifiers
0301: * given in the array itemID (in dotted-integer notation). Return as SNMPVarBindList object;
0302: * if no such variable (either due to device not supporting it, or community name having incorrect
0303: * access privilege), SNMPGetException thrown
0304: * @throws IOException Thrown when timeout experienced while waiting for response to request.
0305: * @throws SNMPBadValueException
0306: * @throws SNMPGetException Thrown if one of supplied OIDs has value that can't be retrieved
0307: */
0308:
0309: public SNMPVarBindList getMIBEntry(String[] itemID)
0310: throws IOException, SNMPBadValueException, SNMPGetException {
0311: // send GetRequest to specified host to retrieve values of specified object identifiers
0312:
0313: SNMPVarBindList retrievedVars = new SNMPVarBindList();
0314: SNMPSequence varList = new SNMPSequence();
0315:
0316: int errorStatus = 0;
0317: int errorIndex = 0;
0318:
0319: for (int i = 0; i < itemID.length; i++) {
0320: SNMPObjectIdentifier requestedObjectIdentifier = new SNMPObjectIdentifier(
0321: itemID[i]);
0322: SNMPVariablePair nextPair = new SNMPVariablePair(
0323: requestedObjectIdentifier, new SNMPNull());
0324: varList.addSNMPObject(nextPair);
0325: }
0326:
0327: SNMPPDU pdu = new SNMPPDU(SNMPBERCodec.SNMPGETREQUEST,
0328: requestID, errorStatus, errorIndex, varList);
0329:
0330: SNMPMessage message = new SNMPMessage(version, community, pdu);
0331:
0332: byte[] messageEncoding = message.getBEREncoding();
0333:
0334: /*
0335: System.out.println("Request Message bytes:");
0336:
0337: for (int i = 0; i < messageEncoding.length; ++i)
0338: System.out.print(hexByte(messageEncoding[i]) + " ");
0339: */
0340:
0341: DatagramPacket outPacket = new DatagramPacket(messageEncoding,
0342: messageEncoding.length, hostAddress, remotePort);
0343:
0344: dSocket.send(outPacket);
0345:
0346: while (true) // wait until receive reply for requestID & OID (or error)
0347: {
0348:
0349: DatagramPacket inPacket = new DatagramPacket(
0350: new byte[receiveBufferSize], receiveBufferSize);
0351:
0352: dSocket.receive(inPacket);
0353:
0354: byte[] encodedMessage = inPacket.getData();
0355:
0356: /*
0357: System.out.println("Message bytes:");
0358:
0359: for (int i = 0; i < encodedMessage.length; ++i)
0360: {
0361: System.out.print(hexByte(encodedMessage[i]) + " ");
0362: }
0363: */
0364:
0365: SNMPMessage receivedMessage = new SNMPMessage(SNMPBERCodec
0366: .extractNextTLV(encodedMessage, 0).value);
0367: SNMPPDU receivedPDU = receivedMessage.getPDU();
0368:
0369: // check request identifier; if incorrect, just ignore packet and continue waiting
0370: if (receivedPDU.getRequestID() == requestID) {
0371:
0372: // check error status; if retrieval problem, throw SNMPGetException
0373: if (receivedPDU.getErrorStatus() != 0) {
0374: // determine error index
0375: errorIndex = receivedPDU.getErrorIndex();
0376: throw new SNMPGetException("OID "
0377: + itemID[errorIndex - 1]
0378: + " not available for retrieval",
0379: errorIndex, receivedPDU.getErrorStatus());
0380: }
0381:
0382: // copy info from retrieved sequence to var bind list
0383: varList = receivedPDU.getVarBindList();
0384:
0385: for (int i = 0; i < varList.size(); i++) {
0386: SNMPSequence newPair = (SNMPSequence) (varList
0387: .getSNMPObjectAt(i));
0388:
0389: SNMPObjectIdentifier newObjectIdentifier = (SNMPObjectIdentifier) (newPair
0390: .getSNMPObjectAt(0));
0391: SNMPObject newValue = newPair.getSNMPObjectAt(1);
0392:
0393: if (newObjectIdentifier.toString()
0394: .equals(itemID[i])) {
0395: retrievedVars.addSNMPObject(newPair);
0396: } else {
0397: // wrong OID; throw GetException
0398: throw new SNMPGetException("OID " + itemID[i]
0399: + " expected at index " + i + ", OID "
0400: + newObjectIdentifier + " received",
0401: i + 1, SNMPRequestException.FAILED);
0402: }
0403: }
0404:
0405: break;
0406:
0407: }
0408:
0409: }
0410:
0411: requestID++;
0412:
0413: return retrievedVars;
0414:
0415: }
0416:
0417: /**
0418: * Retrieve the MIB variable value corresponding to the object identifier following that
0419: * given in itemID (in dotted-integer notation). Return as SNMPVarBindList object; if no
0420: * such variable (either due to device not supporting it, or community name having incorrect
0421: * access privilege), variable value will be SNMPNull object
0422: * @throws IOException Thrown when timeout experienced while waiting for response to request.
0423: * @throws SNMPBadValueException
0424: * @throws SNMPGetException Thrown if one the OID following the supplied OID has value that can't be retrieved
0425: */
0426:
0427: public SNMPVarBindList getNextMIBEntry(String itemID)
0428: throws IOException, SNMPBadValueException, SNMPGetException {
0429: // send GetRequest to specified host to retrieve specified object identifier
0430:
0431: SNMPVarBindList retrievedVars = new SNMPVarBindList();
0432:
0433: int errorStatus = 0;
0434: int errorIndex = 0;
0435:
0436: SNMPObjectIdentifier requestedObjectIdentifier = new SNMPObjectIdentifier(
0437: itemID);
0438: SNMPVariablePair nextPair = new SNMPVariablePair(
0439: requestedObjectIdentifier, new SNMPNull());
0440: SNMPSequence varList = new SNMPSequence();
0441: varList.addSNMPObject(nextPair);
0442: SNMPPDU pdu = new SNMPPDU(SNMPBERCodec.SNMPGETNEXTREQUEST,
0443: requestID, errorStatus, errorIndex, varList);
0444:
0445: SNMPMessage message = new SNMPMessage(version, community, pdu);
0446:
0447: byte[] messageEncoding = message.getBEREncoding();
0448:
0449: /*
0450: System.out.println("Request Message bytes:");
0451:
0452: for (int i = 0; i < messageEncoding.length; ++i)
0453: System.out.print(hexByte(messageEncoding[i]) + " ");
0454: */
0455:
0456: DatagramPacket outPacket = new DatagramPacket(messageEncoding,
0457: messageEncoding.length, hostAddress, remotePort);
0458:
0459: dSocket.send(outPacket);
0460:
0461: while (true) // wait until receive reply for requestID & OID (or error)
0462: {
0463:
0464: DatagramPacket inPacket = new DatagramPacket(
0465: new byte[receiveBufferSize], receiveBufferSize);
0466:
0467: dSocket.receive(inPacket);
0468:
0469: byte[] encodedMessage = inPacket.getData();
0470:
0471: /*
0472: System.out.println("Message bytes:");
0473:
0474: for (int i = 0; i < encodedMessage.length; ++i)
0475: {
0476: System.out.print(hexByte(encodedMessage[i]) + " ");
0477: }
0478: */
0479:
0480: SNMPMessage receivedMessage = new SNMPMessage(SNMPBERCodec
0481: .extractNextTLV(encodedMessage, 0).value);
0482: SNMPPDU receivedPDU = receivedMessage.getPDU();
0483:
0484: // check request identifier; if incorrect, just ignore packet and continue waiting
0485: if (receivedPDU.getRequestID() == requestID) {
0486:
0487: // check error status; if retrieval problem, throw SNMPGetException
0488: if (receivedPDU.getErrorStatus() != 0)
0489: throw new SNMPGetException("OID " + itemID
0490: + " not available for retrieval",
0491: receivedPDU.getErrorIndex(), receivedPDU
0492: .getErrorStatus());
0493:
0494: varList = receivedPDU.getVarBindList();
0495: SNMPSequence newPair = (SNMPSequence) (varList
0496: .getSNMPObjectAt(0));
0497:
0498: SNMPObjectIdentifier newObjectIdentifier = (SNMPObjectIdentifier) (newPair
0499: .getSNMPObjectAt(0));
0500: SNMPObject newValue = newPair.getSNMPObjectAt(1);
0501:
0502: retrievedVars.addSNMPObject(newPair);
0503:
0504: break;
0505:
0506: }
0507:
0508: }
0509:
0510: requestID++;
0511:
0512: return retrievedVars;
0513:
0514: }
0515:
0516: /**
0517: * Retrieve the MIB variable value corresponding to the object identifiers following those
0518: * given in the itemID array (in dotted-integer notation). Return as SNMPVarBindList object;
0519: * if no such variable (either due to device not supporting it, or community name having
0520: * incorrect access privilege), SNMPGetException thrown
0521: * @throws IOException Thrown when timeout experienced while waiting for response to request.
0522: * @throws SNMPBadValueException
0523: * @throws SNMPGetException Thrown if OID following one of supplied OIDs has value that can't be retrieved
0524: */
0525:
0526: public SNMPVarBindList getNextMIBEntry(String[] itemID)
0527: throws IOException, SNMPBadValueException, SNMPGetException {
0528: // send GetRequest to specified host to retrieve values of specified object identifiers
0529:
0530: SNMPVarBindList retrievedVars = new SNMPVarBindList();
0531: SNMPSequence varList = new SNMPSequence();
0532:
0533: int errorStatus = 0;
0534: int errorIndex = 0;
0535:
0536: for (int i = 0; i < itemID.length; i++) {
0537: SNMPObjectIdentifier requestedObjectIdentifier = new SNMPObjectIdentifier(
0538: itemID[i]);
0539: SNMPVariablePair nextPair = new SNMPVariablePair(
0540: requestedObjectIdentifier, new SNMPNull());
0541: varList.addSNMPObject(nextPair);
0542: }
0543:
0544: SNMPPDU pdu = new SNMPPDU(SNMPBERCodec.SNMPGETNEXTREQUEST,
0545: requestID, errorStatus, errorIndex, varList);
0546: SNMPMessage message = new SNMPMessage(version, community, pdu);
0547:
0548: byte[] messageEncoding = message.getBEREncoding();
0549:
0550: /*
0551: System.out.println("Request Message bytes:");
0552:
0553: for (int i = 0; i < messageEncoding.length; ++i)
0554: System.out.print(hexByte(messageEncoding[i]) + " ");
0555: */
0556:
0557: DatagramPacket outPacket = new DatagramPacket(messageEncoding,
0558: messageEncoding.length, hostAddress, remotePort);
0559:
0560: dSocket.send(outPacket);
0561:
0562: while (true) // wait until receive reply for requestID & OID (or error)
0563: {
0564:
0565: DatagramPacket inPacket = new DatagramPacket(
0566: new byte[receiveBufferSize], receiveBufferSize);
0567:
0568: dSocket.receive(inPacket);
0569:
0570: byte[] encodedMessage = inPacket.getData();
0571:
0572: /*
0573: System.out.println("Message bytes:");
0574:
0575: for (int i = 0; i < encodedMessage.length; ++i)
0576: {
0577: System.out.print(hexByte(encodedMessage[i]) + " ");
0578: }
0579: */
0580:
0581: SNMPMessage receivedMessage = new SNMPMessage(SNMPBERCodec
0582: .extractNextTLV(encodedMessage, 0).value);
0583: SNMPPDU receivedPDU = receivedMessage.getPDU();
0584:
0585: // check request identifier; if incorrect, just ignore packet and continue waiting
0586: if (receivedPDU.getRequestID() == requestID) {
0587:
0588: // check error status; if retrieval problem, throw SNMPGetException
0589: if (receivedPDU.getErrorStatus() != 0) {
0590: // determine error index
0591: errorIndex = receivedPDU.getErrorIndex();
0592: throw new SNMPGetException("OID following "
0593: + itemID[errorIndex - 1]
0594: + " not available for retrieval",
0595: errorIndex, receivedPDU.getErrorStatus());
0596: }
0597:
0598: // copy info from retrieved sequence to var bind list
0599: varList = receivedPDU.getVarBindList();
0600:
0601: for (int i = 0; i < varList.size(); i++) {
0602: SNMPSequence newPair = (SNMPSequence) (varList
0603: .getSNMPObjectAt(i));
0604:
0605: SNMPObjectIdentifier newObjectIdentifier = (SNMPObjectIdentifier) (newPair
0606: .getSNMPObjectAt(0));
0607: SNMPObject newValue = newPair.getSNMPObjectAt(1);
0608:
0609: retrievedVars.addSNMPObject(newPair);
0610:
0611: }
0612:
0613: break;
0614:
0615: }
0616:
0617: }
0618:
0619: requestID++;
0620:
0621: return retrievedVars;
0622:
0623: }
0624:
0625: /**
0626: * Set the MIB variable value of the object identifier
0627: * given in startID (in dotted-integer notation). Return SNMPVarBindList object returned
0628: * by device in its response; can be used to check that setting was successful.
0629: * Uses SNMPGetNextRequests to retrieve variable values in sequence.
0630: * @throws IOException Thrown when timeout experienced while waiting for response to request.
0631: * @throws SNMPBadValueException
0632: */
0633:
0634: public SNMPVarBindList setMIBEntry(String itemID,
0635: SNMPObject newValue) throws IOException,
0636: SNMPBadValueException, SNMPSetException {
0637: // send SetRequest to specified host to set value of specified object identifier
0638:
0639: SNMPVarBindList retrievedVars = new SNMPVarBindList();
0640:
0641: int errorStatus = 0;
0642: int errorIndex = 0;
0643:
0644: SNMPObjectIdentifier requestedObjectIdentifier = new SNMPObjectIdentifier(
0645: itemID);
0646: SNMPVariablePair nextPair = new SNMPVariablePair(
0647: requestedObjectIdentifier, newValue);
0648:
0649: SNMPSequence varList = new SNMPSequence();
0650: varList.addSNMPObject(nextPair);
0651: SNMPPDU pdu = new SNMPPDU(SNMPBERCodec.SNMPSETREQUEST,
0652: requestID, errorStatus, errorIndex, varList);
0653:
0654: SNMPMessage message = new SNMPMessage(version, community, pdu);
0655: byte[] messageEncoding = message.getBEREncoding();
0656:
0657: /*
0658: System.out.println("Message bytes:");
0659:
0660: for (int i = 0; i < messageEncoding.length; ++i)
0661: {
0662: System.out.print(hexByte(messageEncoding[i]) + " ");
0663: }
0664: */
0665:
0666: DatagramPacket outPacket = new DatagramPacket(messageEncoding,
0667: messageEncoding.length, hostAddress, remotePort);
0668:
0669: dSocket.send(outPacket);
0670:
0671: while (true) // wait until receive reply for correct OID (or error)
0672: {
0673:
0674: DatagramPacket inPacket = new DatagramPacket(
0675: new byte[receiveBufferSize], receiveBufferSize);
0676:
0677: dSocket.receive(inPacket);
0678:
0679: byte[] encodedMessage = inPacket.getData();
0680:
0681: /*
0682: System.out.println("Message bytes:");
0683:
0684: for (int i = 0; i < encodedMessage.length; ++i)
0685: {
0686: System.out.print((encodedMessage[i]) + " ");
0687: }
0688: */
0689:
0690: SNMPMessage receivedMessage = new SNMPMessage(SNMPBERCodec
0691: .extractNextTLV(encodedMessage, 0).value);
0692:
0693: SNMPPDU receivedPDU = receivedMessage.getPDU();
0694:
0695: // check request identifier; if incorrect, just ignore packet and continue waiting
0696: if (receivedPDU.getRequestID() == requestID) {
0697:
0698: // check error status; if retrieval problem, throw SNMPGetException
0699: if (receivedPDU.getErrorStatus() != 0) {
0700: switch (receivedPDU.getErrorStatus()) {
0701: case 1:
0702: throw new SNMPSetException(
0703: "Value supplied for OID " + itemID
0704: + " too big.", receivedPDU
0705: .getErrorIndex(), receivedPDU
0706: .getErrorStatus());
0707:
0708: case 2:
0709: throw new SNMPSetException("OID " + itemID
0710: + " not available for setting.",
0711: receivedPDU.getErrorIndex(),
0712: receivedPDU.getErrorStatus());
0713:
0714: case 3:
0715: throw new SNMPSetException(
0716: "Bad value supplied for OID " + itemID
0717: + ".", receivedPDU
0718: .getErrorIndex(), receivedPDU
0719: .getErrorStatus());
0720:
0721: case 4:
0722: throw new SNMPSetException("OID " + itemID
0723: + " read-only.", receivedPDU
0724: .getErrorIndex(), receivedPDU
0725: .getErrorStatus());
0726:
0727: default:
0728: throw new SNMPSetException("Error setting OID "
0729: + itemID + ".", receivedPDU
0730: .getErrorIndex(), receivedPDU
0731: .getErrorStatus());
0732:
0733: }
0734: }
0735:
0736: varList = receivedPDU.getVarBindList();
0737: SNMPSequence newPair = (SNMPSequence) (varList
0738: .getSNMPObjectAt(0));
0739:
0740: // check the object identifier to make sure the correct variable has been received;
0741: // if not, just continue waiting for receive
0742: if (((SNMPObjectIdentifier) newPair.getSNMPObjectAt(0))
0743: .toString().equals(itemID)) {
0744: // got the right one; add it to retrieved var list and break!
0745: retrievedVars.addSNMPObject(newPair);
0746: break;
0747: }
0748:
0749: }
0750:
0751: }
0752:
0753: requestID++;
0754:
0755: return retrievedVars;
0756:
0757: }
0758:
0759: /**
0760: * Set the MIB variable values of the supplied object identifiers given in the
0761: * itemID array (in dotted-integer notation). Return SNMPVarBindList returned
0762: * by device in its response; can be used to check that setting was successful.
0763: * Uses SNMPGetNextRequests to retrieve variable values in sequence.
0764: * @throws IOException Thrown when timeout experienced while waiting for response to request.
0765: * @throws SNMPBadValueException
0766: */
0767:
0768: public SNMPVarBindList setMIBEntry(String[] itemID,
0769: SNMPObject[] newValue) throws IOException,
0770: SNMPBadValueException, SNMPSetException {
0771: // check that OID and value arrays have same size
0772: if (itemID.length != newValue.length) {
0773: throw new SNMPSetException(
0774: "OID and value arrays must have same size", 0,
0775: SNMPRequestException.FAILED);
0776: }
0777:
0778: // send SetRequest to specified host to set values of specified object identifiers
0779:
0780: SNMPVarBindList retrievedVars = new SNMPVarBindList();
0781: SNMPSequence varList = new SNMPSequence();
0782:
0783: int errorStatus = 0;
0784: int errorIndex = 0;
0785:
0786: for (int i = 0; i < itemID.length; i++) {
0787: SNMPObjectIdentifier requestedObjectIdentifier = new SNMPObjectIdentifier(
0788: itemID[i]);
0789: SNMPVariablePair nextPair = new SNMPVariablePair(
0790: requestedObjectIdentifier, newValue[i]);
0791: varList.addSNMPObject(nextPair);
0792: }
0793:
0794: SNMPPDU pdu = new SNMPPDU(SNMPBERCodec.SNMPSETREQUEST,
0795: requestID, errorStatus, errorIndex, varList);
0796: SNMPMessage message = new SNMPMessage(version, community, pdu);
0797:
0798: byte[] messageEncoding = message.getBEREncoding();
0799:
0800: /*
0801: System.out.println("Message bytes:");
0802:
0803: for (int i = 0; i < messageEncoding.length; ++i)
0804: {
0805: System.out.print(getHex(messageEncoding[i]) + " ");
0806: }
0807: */
0808:
0809: DatagramPacket outPacket = new DatagramPacket(messageEncoding,
0810: messageEncoding.length, hostAddress, remotePort);
0811:
0812: dSocket.send(outPacket);
0813:
0814: while (true) // wait until receive reply for correct OID (or error)
0815: {
0816:
0817: DatagramPacket inPacket = new DatagramPacket(
0818: new byte[receiveBufferSize], receiveBufferSize);
0819:
0820: dSocket.receive(inPacket);
0821:
0822: byte[] encodedMessage = inPacket.getData();
0823:
0824: /*
0825: System.out.println("Message bytes:");
0826:
0827: for (int i = 0; i < encodedMessage.length; ++i)
0828: {
0829: System.out.print((encodedMessage[i]) + " ");
0830: }
0831: */
0832:
0833: SNMPMessage receivedMessage = new SNMPMessage(SNMPBERCodec
0834: .extractNextTLV(encodedMessage, 0).value);
0835:
0836: SNMPPDU receivedPDU = receivedMessage.getPDU();
0837:
0838: // check request identifier; if incorrect, just ignore packet and continue waiting
0839: if (receivedPDU.getRequestID() == requestID) {
0840:
0841: // check error status; if retrieval problem, throw SNMPGetException
0842: if (receivedPDU.getErrorStatus() != 0) {
0843: errorIndex = receivedPDU.getErrorIndex();
0844:
0845: switch (receivedPDU.getErrorStatus()) {
0846: case 1:
0847: throw new SNMPSetException(
0848: "Value supplied for OID "
0849: + itemID[errorIndex - 1]
0850: + " too big.", receivedPDU
0851: .getErrorIndex(), receivedPDU
0852: .getErrorStatus());
0853:
0854: case 2:
0855: throw new SNMPSetException("OID "
0856: + itemID[errorIndex - 1]
0857: + " not available for setting.",
0858: receivedPDU.getErrorIndex(),
0859: receivedPDU.getErrorStatus());
0860:
0861: case 3:
0862: throw new SNMPSetException(
0863: "Bad value supplied for OID "
0864: + itemID[errorIndex - 1] + ".",
0865: receivedPDU.getErrorIndex(),
0866: receivedPDU.getErrorStatus());
0867:
0868: case 4:
0869: throw new SNMPSetException("OID "
0870: + itemID[errorIndex - 1]
0871: + " read-only.", receivedPDU
0872: .getErrorIndex(), receivedPDU
0873: .getErrorStatus());
0874:
0875: default:
0876: throw new SNMPSetException("Error setting OID "
0877: + itemID[errorIndex - 1] + ".",
0878: receivedPDU.getErrorIndex(),
0879: receivedPDU.getErrorStatus());
0880:
0881: }
0882: }
0883:
0884: // copy info from retrieved sequence to var bind list
0885: varList = receivedPDU.getVarBindList();
0886:
0887: for (int i = 0; i < varList.size(); i++) {
0888: SNMPSequence newPair = (SNMPSequence) (varList
0889: .getSNMPObjectAt(i));
0890:
0891: SNMPObjectIdentifier newObjectIdentifier = (SNMPObjectIdentifier) (newPair
0892: .getSNMPObjectAt(0));
0893: //SNMPObject receivedValue = newPair.getSNMPObjectAt(1);
0894:
0895: if (newObjectIdentifier.toString()
0896: .equals(itemID[i])) {
0897: retrievedVars.addSNMPObject(newPair);
0898: } else {
0899: // wrong OID; throw GetException
0900: throw new SNMPSetException("OID " + itemID[i]
0901: + " expected at index " + i + ", OID "
0902: + newObjectIdentifier + " received",
0903: i + 1, SNMPRequestException.FAILED);
0904: }
0905: }
0906:
0907: break;
0908:
0909: }
0910:
0911: }
0912:
0913: requestID++;
0914:
0915: return retrievedVars;
0916:
0917: }
0918:
0919: /**
0920: * Retrieve all MIB variable values whose OIDs start with the supplied baseID. Since the entries of
0921: * an SNMP table have the form <baseID>.<tableEntry>.<index>, this will retrieve all of the table
0922: * data as an SNMPVarBindList object consisting of sequence of SNMPVariablePairs.
0923: * Uses SNMPGetNextRequests to retrieve variable values in sequence.
0924: * @throws IOException Thrown when timeout experienced while waiting for response to request.
0925: * @throws SNMPBadValueException
0926: */
0927:
0928: public SNMPVarBindList retrieveMIBTable(String baseID)
0929: throws IOException, SNMPBadValueException, SNMPGetException {
0930: // send GetNextRequests until receive
0931: // an error message or a repeat of the object identifier we sent out
0932: SNMPVarBindList retrievedVars = new SNMPVarBindList();
0933:
0934: int errorStatus = 0;
0935: int errorIndex = 0;
0936:
0937: String currentID = baseID;
0938: SNMPObjectIdentifier requestedObjectIdentifier = new SNMPObjectIdentifier(
0939: currentID);
0940:
0941: while (errorStatus == 0) {
0942:
0943: SNMPVariablePair nextPair = new SNMPVariablePair(
0944: requestedObjectIdentifier, new SNMPNull());
0945: SNMPSequence varList = new SNMPSequence();
0946: varList.addSNMPObject(nextPair);
0947: SNMPPDU pdu = new SNMPPDU(SNMPBERCodec.SNMPGETNEXTREQUEST,
0948: requestID, errorStatus, errorIndex, varList);
0949: SNMPMessage message = new SNMPMessage(version, community,
0950: pdu);
0951: byte[] messageEncoding = message.getBEREncoding();
0952: DatagramPacket outPacket = new DatagramPacket(
0953: messageEncoding, messageEncoding.length,
0954: hostAddress, remotePort);
0955:
0956: /*
0957: System.out.println("Request bytes:");
0958:
0959: for (int i = 0; i < messageEncoding.length; ++i)
0960: {
0961: System.out.print(getHex(messageEncoding[i]) + " ");
0962: }
0963: */
0964:
0965: dSocket.send(outPacket);
0966:
0967: DatagramPacket inPacket = new DatagramPacket(
0968: new byte[receiveBufferSize], receiveBufferSize);
0969:
0970: dSocket.receive(inPacket);
0971:
0972: byte[] encodedMessage = inPacket.getData();
0973:
0974: SNMPMessage receivedMessage = new SNMPMessage(SNMPBERCodec
0975: .extractNextTLV(encodedMessage, 0).value);
0976: SNMPPDU receivedPDU = receivedMessage.getPDU();
0977:
0978: // check request identifier; if incorrect, just ignore packet and continue waiting
0979: if (receivedPDU.getRequestID() == requestID) {
0980:
0981: // check error status; if retrieval problem, just break - could be there are no additional OIDs
0982: if (receivedPDU.getErrorStatus() != 0) {
0983: break;
0984: //throw new SNMPGetException("OID following " + requestedObjectIdentifier + " not available for retrieval");
0985: }
0986:
0987: varList = receivedPDU.getVarBindList();
0988: SNMPSequence newPair = (SNMPSequence) (varList
0989: .getSNMPObjectAt(0));
0990:
0991: SNMPObjectIdentifier newObjectIdentifier = (SNMPObjectIdentifier) (newPair
0992: .getSNMPObjectAt(0));
0993: SNMPObject newValue = newPair.getSNMPObjectAt(1);
0994:
0995: // now see if retrieved ID starts with table base; if not, done with table - break
0996: String newOIDString = (String) newObjectIdentifier
0997: .toString();
0998: if (!newOIDString.startsWith(baseID))
0999: break;
1000:
1001: retrievedVars.addSNMPObject(newPair);
1002:
1003: requestedObjectIdentifier = newObjectIdentifier;
1004:
1005: requestID++;
1006:
1007: }
1008:
1009: }
1010:
1011: return retrievedVars;
1012:
1013: }
1014:
1015: /**
1016: * Retrieve all MIB variable values whose OIDs start with the supplied baseIDs. The normal way for
1017: * this to be used is for the base OID array to consist of the base OIDs of the columns of a table.
1018: * This method will then retrieve all of the entries of the table corresponding to these columns, one
1019: * row at a time (i.e., the entries for each row will be retrieved in a single SNMP request). This
1020: * will retrieve the table data as an SNMPVarBindList object consisting of sequence of SNMPVariablePairs,
1021: * with the entries for each row grouped together. This may provide a more convenient arrangement of
1022: * the table data than the simpler retrieveMIBTable method taking a single OID as argument; in addition,
1023: * it's more efficient, requiring one SNMP request per row rather than one request per entry.
1024: * Uses SNMPGetNextRequests to retrieve variable values for each row in sequence.
1025: * @throws IOException Thrown when timeout experienced while waiting for response to request.
1026: * @throws SNMPBadValueException
1027: * @throws SNMPGetException Thrown if incomplete row retrieved
1028: */
1029:
1030: public SNMPVarBindList retrieveMIBTable(String[] baseID)
1031: throws IOException, SNMPBadValueException, SNMPGetException {
1032: // send GetNextRequests until receive
1033: // an error message or a repeat of the object identifier we sent out
1034: SNMPVarBindList retrievedVars = new SNMPVarBindList();
1035:
1036: int errorStatus = 0;
1037: int errorIndex = 0;
1038:
1039: SNMPObjectIdentifier[] requestedObjectIdentifier = new SNMPObjectIdentifier[baseID.length];
1040: for (int i = 0; i < baseID.length; i++) {
1041: requestedObjectIdentifier[i] = new SNMPObjectIdentifier(
1042: baseID[i]);
1043: }
1044:
1045: retrievalLoop:
1046:
1047: while (errorStatus == 0) {
1048:
1049: SNMPSequence varList = new SNMPSequence();
1050:
1051: for (int i = 0; i < requestedObjectIdentifier.length; i++) {
1052: SNMPVariablePair nextPair = new SNMPVariablePair(
1053: requestedObjectIdentifier[i], new SNMPNull());
1054: varList.addSNMPObject(nextPair);
1055: }
1056:
1057: SNMPPDU pdu = new SNMPPDU(SNMPBERCodec.SNMPGETNEXTREQUEST,
1058: requestID, errorStatus, errorIndex, varList);
1059: SNMPMessage message = new SNMPMessage(version, community,
1060: pdu);
1061:
1062: byte[] messageEncoding = message.getBEREncoding();
1063:
1064: DatagramPacket outPacket = new DatagramPacket(
1065: messageEncoding, messageEncoding.length,
1066: hostAddress, remotePort);
1067:
1068: /*
1069: System.out.println("Request bytes:");
1070:
1071: for (int i = 0; i < messageEncoding.length; ++i)
1072: {
1073: System.out.print(getHex(messageEncoding[i]) + " ");
1074: }
1075: */
1076:
1077: dSocket.send(outPacket);
1078:
1079: DatagramPacket inPacket = new DatagramPacket(
1080: new byte[receiveBufferSize], receiveBufferSize);
1081:
1082: dSocket.receive(inPacket);
1083:
1084: byte[] encodedMessage = inPacket.getData();
1085:
1086: SNMPMessage receivedMessage = new SNMPMessage(SNMPBERCodec
1087: .extractNextTLV(encodedMessage, 0).value);
1088: SNMPPDU receivedPDU = receivedMessage.getPDU();
1089:
1090: // check request identifier; if incorrect, just ignore packet and continue waiting
1091: if (receivedPDU.getRequestID() == requestID) {
1092:
1093: // check error status; if retrieval problem for error index 1, just break - assume there are no additional OIDs
1094: // to retrieve. If index is other than 1, throw exception
1095: if (receivedPDU.getErrorStatus() != 0) {
1096: int retrievedErrorIndex = receivedPDU
1097: .getErrorIndex();
1098:
1099: if (retrievedErrorIndex == 1) {
1100: break retrievalLoop;
1101: } else {
1102: throw new SNMPGetException(
1103: "OID following "
1104: + requestedObjectIdentifier[retrievedErrorIndex - 1]
1105: + " not available for retrieval",
1106: retrievedErrorIndex, receivedPDU
1107: .getErrorStatus());
1108: }
1109: }
1110:
1111: // copy info from retrieved sequence to var bind list
1112: varList = receivedPDU.getVarBindList();
1113:
1114: // make sure got the right number of vars in reply; if not, throw GetException
1115: if (varList.size() != requestedObjectIdentifier.length) {
1116: throw new SNMPGetException(
1117: "Incomplete row of table received", 0,
1118: SNMPRequestException.FAILED);
1119: }
1120:
1121: // copy the retrieved variable pairs into retrievedVars
1122: for (int i = 0; i < varList.size(); i++) {
1123: SNMPSequence newPair = (SNMPSequence) (varList
1124: .getSNMPObjectAt(i));
1125:
1126: SNMPObjectIdentifier newObjectIdentifier = (SNMPObjectIdentifier) (newPair
1127: .getSNMPObjectAt(0));
1128: SNMPObject newValue = newPair.getSNMPObjectAt(1);
1129:
1130: // now see if retrieved ID starts with table base; if not, done with table - break
1131: String newOIDString = (String) newObjectIdentifier
1132: .toString();
1133: if (!newOIDString.startsWith(baseID[i])) {
1134: if (i == 0) {
1135: // it's the first element of the row; just break
1136: break retrievalLoop;
1137: } else {
1138: // it's a subsequent row element; throw exception
1139: throw new SNMPGetException(
1140: "Incomplete row of table received",
1141: i + 1, SNMPRequestException.FAILED);
1142: }
1143: }
1144:
1145: retrievedVars.addSNMPObject(newPair);
1146:
1147: // set requested identifiers array to current identifiers to do get-next for next row
1148: requestedObjectIdentifier[i] = newObjectIdentifier;
1149: }
1150:
1151: requestID++;
1152:
1153: }
1154:
1155: }
1156:
1157: return retrievedVars;
1158:
1159: }
1160:
1161: /**
1162: * Set the size of the buffer used to receive response packets. RFC 1157 stipulates that an SNMP
1163: * implementation must be able to receive packets of at least 484 bytes, so if you try to set the
1164: * size to a value less than this, the receive buffer size will be set to 484 bytes. In addition,
1165: * the maximum size of a UDP packet payload is 65535 bytes, so setting the buffer to a larger size
1166: * will just waste memory. The default value is 512 bytes. The value may need to be increased if
1167: * get-requests are issued for multiple OIDs.
1168: */
1169:
1170: public void setReceiveBufferSize(int receiveBufferSize) {
1171: if (receiveBufferSize >= 484) {
1172: this .receiveBufferSize = receiveBufferSize;
1173: } else {
1174: this .receiveBufferSize = 484;
1175: }
1176: }
1177:
1178: /**
1179: * Returns the current size of the buffer used to receive response packets.
1180: */
1181:
1182: public int getReceiveBufferSize() {
1183: return this.receiveBufferSize;
1184: }
1185:
1186: }
|