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