0N/A/*
2362N/A * Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage com.sun.jmx.snmp;
0N/A
0N/Aimport com.sun.jmx.snmp.SnmpSecurityParameters;
0N/A// java imports
0N/A//
0N/Aimport java.util.Vector;
0N/Aimport java.net.InetAddress;
0N/A
0N/A
0N/Aimport com.sun.jmx.snmp.SnmpStatusException;
0N/A/**
0N/A * A partially decoded representation of an SNMP packet. It contains
0N/A * the information contained in any SNMP message (SNMPv1, SNMPv2 or
0N/A * SNMPv3).
0N/A * <p><b>This API is a Sun Microsystems internal API and is subject
0N/A * to change without notice.</b></p>
0N/A * @since 1.5
0N/A */
0N/Apublic abstract class SnmpMsg implements SnmpDefinitions {
0N/A /**
0N/A * The protocol version.
0N/A * <P><CODE>decodeMessage</CODE> and <CODE>encodeMessage</CODE> do not
0N/A * perform any check on this value.
0N/A * <BR><CODE>decodeSnmpPdu</CODE> and <CODE>encodeSnmpPdu</CODE> only
0N/A * accept the values 0 (for SNMPv1), 1 (for SNMPv2) and 3 (for SNMPv3).
0N/A */
0N/A public int version = 0;
0N/A
0N/A /**
0N/A * Encoding of the PDU.
0N/A * <P>This is usually the BER encoding of the PDU's syntax
0N/A * defined in RFC1157 and RFC1902. However, this can be authenticated
0N/A * or encrypted data (but you need to implemented your own
0N/A * <CODE>SnmpPduFactory</CODE> class).
0N/A */
0N/A public byte[] data = null;
0N/A
0N/A /**
0N/A * Number of useful bytes in the <CODE>data</CODE> field.
0N/A */
0N/A public int dataLength = 0;
0N/A
0N/A /**
0N/A * Source or destination address.
0N/A * <BR>For an incoming message it's the source.
0N/A * For an outgoing message it's the destination.
0N/A */
0N/A public InetAddress address = null;
0N/A
0N/A /**
0N/A * Source or destination port.
0N/A * <BR>For an incoming message it's the source.
0N/A * For an outgoing message it's the destination.
0N/A */
0N/A public int port = 0;
0N/A /**
0N/A * Security parameters. Contain informations according to Security Model (Usm, community string based, ...).
0N/A */
0N/A public SnmpSecurityParameters securityParameters = null;
0N/A /**
0N/A * Returns the encoded SNMP version present in the passed byte array.
0N/A * @param data The unmarshalled SNMP message.
0N/A * @return The SNMP version (0, 1 or 3).
0N/A */
0N/A public static int getProtocolVersion(byte[] data)
0N/A throws SnmpStatusException {
0N/A int version = 0;
0N/A BerDecoder bdec = null;
0N/A try {
0N/A bdec = new BerDecoder(data);
0N/A bdec.openSequence();
0N/A version = bdec.fetchInteger();
0N/A }
0N/A catch(BerException x) {
0N/A throw new SnmpStatusException("Invalid encoding") ;
0N/A }
0N/A try {
0N/A bdec.closeSequence();
0N/A }
0N/A catch(BerException x) {
0N/A }
0N/A return version;
0N/A }
0N/A
0N/A /**
0N/A * Returns the associated request ID.
0N/A * @param data The flat message.
0N/A * @return The request ID.
0N/A */
0N/A public abstract int getRequestId(byte[] data) throws SnmpStatusException;
0N/A
0N/A /**
0N/A * Encodes this message and puts the result in the specified byte array.
0N/A * For internal use only.
0N/A *
0N/A * @param outputBytes An array to receive the resulting encoding.
0N/A *
0N/A * @exception ArrayIndexOutOfBoundsException If the result does not fit
0N/A * into the specified array.
0N/A */
0N/A public abstract int encodeMessage(byte[] outputBytes)
0N/A throws SnmpTooBigException;
0N/A
0N/A /**
0N/A * Decodes the specified bytes and initializes this message.
0N/A * For internal use only.
0N/A *
0N/A * @param inputBytes The bytes to be decoded.
0N/A *
0N/A * @exception SnmpStatusException If the specified bytes are not a valid encoding.
0N/A */
0N/A public abstract void decodeMessage(byte[] inputBytes, int byteCount)
0N/A throws SnmpStatusException;
0N/A
0N/A /**
0N/A * Initializes this message with the specified <CODE>pdu</CODE>.
0N/A * <P>
0N/A * This method initializes the data field with an array of
0N/A * <CODE>maxDataLength</CODE> bytes. It encodes the <CODE>pdu</CODE>.
0N/A * The resulting encoding is stored in the data field
0N/A * and the length of the encoding is stored in <CODE>dataLength</CODE>.
0N/A * <p>
0N/A * If the encoding length exceeds <CODE>maxDataLength</CODE>,
0N/A * the method throws an exception.
0N/A *
0N/A * @param pdu The PDU to be encoded.
0N/A * @param maxDataLength The maximum length permitted for the data field.
0N/A *
0N/A * @exception SnmpStatusException If the specified <CODE>pdu</CODE> is not valid.
0N/A * @exception SnmpTooBigException If the resulting encoding does not fit
0N/A * into <CODE>maxDataLength</CODE> bytes.
0N/A * @exception ArrayIndexOutOfBoundsException If the encoding exceeds <CODE>maxDataLength</CODE>.
0N/A */
0N/A public abstract void encodeSnmpPdu(SnmpPdu pdu, int maxDataLength)
0N/A throws SnmpStatusException, SnmpTooBigException;
0N/A
0N/A
0N/A /**
0N/A * Gets the PDU encoded in this message.
0N/A * <P>
0N/A * This method decodes the data field and returns the resulting PDU.
0N/A *
0N/A * @return The resulting PDU.
0N/A * @exception SnmpStatusException If the encoding is not valid.
0N/A */
0N/A public abstract SnmpPdu decodeSnmpPdu()
0N/A throws SnmpStatusException;
0N/A
0N/A /**
0N/A * Dumps the content of a byte buffer using hexadecimal form.
0N/A *
0N/A * @param b The buffer to dump.
0N/A * @param offset The position of the first byte to be dumped.
0N/A * @param len The number of bytes to be dumped starting from offset.
0N/A *
0N/A * @return The string containing the dump.
0N/A */
0N/A public static String dumpHexBuffer(byte [] b, int offset, int len) {
0N/A StringBuffer buf = new StringBuffer(len << 1) ;
0N/A int k = 1 ;
0N/A int flen = offset + len ;
0N/A
0N/A for (int i = offset; i < flen ; i++) {
0N/A int j = b[i] & 0xFF ;
0N/A buf.append(Character.forDigit((j >>> 4) , 16)) ;
0N/A buf.append(Character.forDigit((j & 0x0F), 16)) ;
0N/A k++ ;
0N/A if (k%16 == 0) {
0N/A buf.append('\n') ;
0N/A k = 1 ;
0N/A } else
0N/A buf.append(' ') ;
0N/A }
0N/A return buf.toString() ;
0N/A }
0N/A
0N/A /**
0N/A * Dumps this message in a string.
0N/A *
0N/A * @return The string containing the dump.
0N/A */
0N/A public String printMessage() {
0N/A StringBuffer sb = new StringBuffer() ;
0N/A sb.append("Version: ") ;
0N/A sb.append(version) ;
0N/A sb.append("\n") ;
0N/A if (data == null) {
0N/A sb.append("Data: null") ;
0N/A }
0N/A else {
0N/A sb.append("Data: {\n") ;
0N/A sb.append(dumpHexBuffer(data, 0, dataLength)) ;
0N/A sb.append("\n}\n") ;
0N/A }
0N/A
0N/A return sb.toString() ;
0N/A }
0N/A
0N/A /**
0N/A * For SNMP Runtime private use only.
0N/A */
0N/A public void encodeVarBindList(BerEncoder benc,
0N/A SnmpVarBind[] varBindList)
0N/A throws SnmpStatusException, SnmpTooBigException {
0N/A //
0N/A // Remember: the encoder does backward encoding
0N/A //
0N/A int encodedVarBindCount = 0 ;
0N/A try {
0N/A benc.openSequence() ;
0N/A if (varBindList != null) {
0N/A for (int i = varBindList.length - 1 ; i >= 0 ; i--) {
0N/A SnmpVarBind bind = varBindList[i] ;
0N/A if (bind != null) {
0N/A benc.openSequence() ;
0N/A encodeVarBindValue(benc, bind.value) ;
0N/A benc.putOid(bind.oid.longValue()) ;
0N/A benc.closeSequence() ;
0N/A encodedVarBindCount++ ;
0N/A }
0N/A }
0N/A }
0N/A benc.closeSequence() ;
0N/A }
0N/A catch(ArrayIndexOutOfBoundsException x) {
0N/A throw new SnmpTooBigException(encodedVarBindCount) ;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * For SNMP Runtime private use only.
0N/A */
0N/A void encodeVarBindValue(BerEncoder benc,
0N/A SnmpValue v)throws SnmpStatusException {
0N/A if (v == null) {
0N/A benc.putNull() ;
0N/A }
0N/A else if (v instanceof SnmpIpAddress) {
0N/A benc.putOctetString(((SnmpIpAddress)v).byteValue(), SnmpValue.IpAddressTag) ;
0N/A }
0N/A else if (v instanceof SnmpCounter) {
0N/A benc.putInteger(((SnmpCounter)v).longValue(), SnmpValue.CounterTag) ;
0N/A }
0N/A else if (v instanceof SnmpGauge) {
0N/A benc.putInteger(((SnmpGauge)v).longValue(), SnmpValue.GaugeTag) ;
0N/A }
0N/A else if (v instanceof SnmpTimeticks) {
0N/A benc.putInteger(((SnmpTimeticks)v).longValue(), SnmpValue.TimeticksTag) ;
0N/A }
0N/A else if (v instanceof SnmpOpaque) {
0N/A benc.putOctetString(((SnmpOpaque)v).byteValue(), SnmpValue.OpaqueTag) ;
0N/A }
0N/A else if (v instanceof SnmpInt) {
0N/A benc.putInteger(((SnmpInt)v).intValue()) ;
0N/A }
0N/A else if (v instanceof SnmpString) {
0N/A benc.putOctetString(((SnmpString)v).byteValue()) ;
0N/A }
0N/A else if (v instanceof SnmpOid) {
0N/A benc.putOid(((SnmpOid)v).longValue()) ;
0N/A }
0N/A else if (v instanceof SnmpCounter64) {
0N/A if (version == snmpVersionOne) {
0N/A throw new SnmpStatusException("Invalid value for SNMP v1 : " + v) ;
0N/A }
0N/A benc.putInteger(((SnmpCounter64)v).longValue(), SnmpValue.Counter64Tag) ;
0N/A }
0N/A else if (v instanceof SnmpNull) {
0N/A int tag = ((SnmpNull)v).getTag() ;
0N/A if ((version == snmpVersionOne) && (tag != SnmpValue.NullTag)) {
0N/A throw new SnmpStatusException("Invalid value for SNMP v1 : " + v) ;
0N/A }
0N/A if ((version == snmpVersionTwo) &&
0N/A (tag != SnmpValue.NullTag) &&
0N/A (tag != SnmpVarBind.errNoSuchObjectTag) &&
0N/A (tag != SnmpVarBind.errNoSuchInstanceTag) &&
0N/A (tag != SnmpVarBind.errEndOfMibViewTag)) {
0N/A throw new SnmpStatusException("Invalid value " + v) ;
0N/A }
0N/A benc.putNull(tag) ;
0N/A }
0N/A else {
0N/A throw new SnmpStatusException("Invalid value " + v) ;
0N/A }
0N/A
0N/A }
0N/A
0N/A
0N/A /**
0N/A * For SNMP Runtime private use only.
0N/A */
0N/A public SnmpVarBind[] decodeVarBindList(BerDecoder bdec)
0N/A throws BerException {
0N/A bdec.openSequence() ;
0N/A Vector<SnmpVarBind> tmp = new Vector<SnmpVarBind>() ;
0N/A while (bdec.cannotCloseSequence()) {
0N/A SnmpVarBind bind = new SnmpVarBind() ;
0N/A bdec.openSequence() ;
0N/A bind.oid = new SnmpOid(bdec.fetchOid()) ;
0N/A bind.setSnmpValue(decodeVarBindValue(bdec)) ;
0N/A bdec.closeSequence() ;
0N/A tmp.addElement(bind) ;
0N/A }
0N/A bdec.closeSequence() ;
0N/A SnmpVarBind[] varBindList= new SnmpVarBind[tmp.size()] ;
0N/A tmp.copyInto(varBindList);
0N/A return varBindList ;
0N/A }
0N/A
0N/A
0N/A /**
0N/A * For SNMP Runtime private use only.
0N/A */
0N/A SnmpValue decodeVarBindValue(BerDecoder bdec)
0N/A throws BerException {
0N/A SnmpValue result = null ;
0N/A int tag = bdec.getTag() ;
0N/A
0N/A // bugId 4641696 : RuntimeExceptions must be transformed in
0N/A // BerException.
0N/A switch(tag) {
0N/A
0N/A //
0N/A // Simple syntax
0N/A //
0N/A case BerDecoder.IntegerTag :
0N/A try {
0N/A result = new SnmpInt(bdec.fetchInteger()) ;
0N/A } catch(RuntimeException r) {
0N/A throw new BerException();
0N/A // BerException("Can't build SnmpInt from decoded value.");
0N/A }
0N/A break ;
0N/A case BerDecoder.OctetStringTag :
0N/A try {
0N/A result = new SnmpString(bdec.fetchOctetString()) ;
0N/A } catch(RuntimeException r) {
0N/A throw new BerException();
0N/A // BerException("Can't build SnmpString from decoded value.");
0N/A }
0N/A break ;
0N/A case BerDecoder.OidTag :
0N/A try {
0N/A result = new SnmpOid(bdec.fetchOid()) ;
0N/A } catch(RuntimeException r) {
0N/A throw new BerException();
0N/A // BerException("Can't build SnmpOid from decoded value.");
0N/A }
0N/A break ;
0N/A case BerDecoder.NullTag :
0N/A bdec.fetchNull() ;
0N/A try {
0N/A result = new SnmpNull() ;
0N/A } catch(RuntimeException r) {
0N/A throw new BerException();
0N/A // BerException("Can't build SnmpNull from decoded value.");
0N/A }
0N/A break ;
0N/A
0N/A //
0N/A // Application syntax
0N/A //
0N/A case SnmpValue.IpAddressTag :
0N/A try {
0N/A result = new SnmpIpAddress(bdec.fetchOctetString(tag)) ;
0N/A } catch (RuntimeException r) {
0N/A throw new BerException();
0N/A // BerException("Can't build SnmpIpAddress from decoded value.");
0N/A }
0N/A break ;
0N/A case SnmpValue.CounterTag :
0N/A try {
0N/A result = new SnmpCounter(bdec.fetchIntegerAsLong(tag)) ;
0N/A } catch(RuntimeException r) {
0N/A throw new BerException();
0N/A // BerException("Can't build SnmpCounter from decoded value.");
0N/A }
0N/A break ;
0N/A case SnmpValue.GaugeTag :
0N/A try {
0N/A result = new SnmpGauge(bdec.fetchIntegerAsLong(tag)) ;
0N/A } catch(RuntimeException r) {
0N/A throw new BerException();
0N/A // BerException("Can't build SnmpGauge from decoded value.");
0N/A }
0N/A break ;
0N/A case SnmpValue.TimeticksTag :
0N/A try {
0N/A result = new SnmpTimeticks(bdec.fetchIntegerAsLong(tag)) ;
0N/A } catch(RuntimeException r) {
0N/A throw new BerException();
0N/A // BerException("Can't build SnmpTimeticks from decoded value.");
0N/A }
0N/A break ;
0N/A case SnmpValue.OpaqueTag :
0N/A try {
0N/A result = new SnmpOpaque(bdec.fetchOctetString(tag)) ;
0N/A } catch(RuntimeException r) {
0N/A throw new BerException();
0N/A // BerException("Can't build SnmpOpaque from decoded value.");
0N/A }
0N/A break ;
0N/A
0N/A //
0N/A // V2 syntaxes
0N/A //
0N/A case SnmpValue.Counter64Tag :
0N/A if (version == snmpVersionOne) {
0N/A throw new BerException(BerException.BAD_VERSION) ;
0N/A }
0N/A try {
0N/A result = new SnmpCounter64(bdec.fetchIntegerAsLong(tag)) ;
0N/A } catch(RuntimeException r) {
0N/A throw new BerException();
0N/A // BerException("Can't build SnmpCounter64 from decoded value.");
0N/A }
0N/A break ;
0N/A
0N/A case SnmpVarBind.errNoSuchObjectTag :
0N/A if (version == snmpVersionOne) {
0N/A throw new BerException(BerException.BAD_VERSION) ;
0N/A }
0N/A bdec.fetchNull(tag) ;
0N/A result = SnmpVarBind.noSuchObject ;
0N/A break ;
0N/A
0N/A case SnmpVarBind.errNoSuchInstanceTag :
0N/A if (version == snmpVersionOne) {
0N/A throw new BerException(BerException.BAD_VERSION) ;
0N/A }
0N/A bdec.fetchNull(tag) ;
0N/A result = SnmpVarBind.noSuchInstance ;
0N/A break ;
0N/A
0N/A case SnmpVarBind.errEndOfMibViewTag :
0N/A if (version == snmpVersionOne) {
0N/A throw new BerException(BerException.BAD_VERSION) ;
0N/A }
0N/A bdec.fetchNull(tag) ;
0N/A result = SnmpVarBind.endOfMibView ;
0N/A break ;
0N/A
0N/A default:
0N/A throw new BerException() ;
0N/A
0N/A }
0N/A
0N/A return result ;
0N/A }
0N/A
0N/A}