- /*
- * @(#)file SnmpMessage.java
- * @(#)author Sun Microsystems, Inc.
- * @(#)version 4.31
- * @(#)date 04/09/15
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- *
- */
-
-
- package com.sun.jmx.snmp;
-
-
- // "@(#)SnmpMessage.java 1.1 98/07/23 SMI"
-
- // java imports
- //
- import java.util.Vector;
- import java.net.InetAddress;
-
- // import debug stuff
- //
- import com.sun.jmx.trace.Trace;
-
- /**
- * Is a partially decoded representation of an SNMP packet.
- * <P>
- * You will not normally need to use this class unless you decide to
- * implement your own {@link com.sun.jmx.snmp.SnmpPduFactory SnmpPduFactory} object.
- * <P>
- * The <CODE>SnmpMessage</CODE> class is directly mapped onto the
- * <CODE>Message</CODE> syntax defined in RFC1157 and RFC1902.
- * <BLOCKQUOTE>
- * <PRE>
- * Message ::= SEQUENCE {
- * version INTEGER { version(1) }, -- for SNMPv2
- * community OCTET STRING, -- community name
- * data ANY -- an SNMPv2 PDU
- * }
- * </PRE>
- * </BLOCKQUOTE>
- *
- * <p><b>This API is a Sun Microsystems internal API and is subject
- * to change without notice.</b></p>
- * @see SnmpPduFactory
- * @see SnmpPduPacket
- *
- * @version 1.1 07/23/98
- * @author Sun Microsystems, Inc
- */
-
- public class SnmpMessage extends SnmpMsg implements SnmpDefinitions {
- /**
- * Community name.
- */
- public byte[] community ;
-
- /**
- * Encodes this message and puts the result in the specified byte array.
- * For internal use only.
- *
- * @param outputBytes An array to receive the resulting encoding.
- *
- * @exception ArrayIndexOutOfBoundsException If the result does not fit
- * into the specified array.
- */
- public int encodeMessage(byte[] outputBytes) throws SnmpTooBigException {
- int encodingLength = 0 ;
- if (data == null)
- throw new IllegalArgumentException("Data field is null") ;
-
- //
- // Reminder: BerEncoder does backward encoding !
- //
- try {
- BerEncoder benc = new BerEncoder(outputBytes) ;
- benc.openSequence() ;
- benc.putAny(data, dataLength) ;
- benc.putOctetString((community != null) ? community : new byte[0]) ;
- benc.putInteger(version) ;
- benc.closeSequence() ;
- encodingLength = benc.trim() ;
- }
- catch(ArrayIndexOutOfBoundsException x) {
- throw new SnmpTooBigException() ;
- }
-
- return encodingLength ;
- }
- /**
- * Returns the associated request ID.
- * @param inputBytes The flat message.
- * @return The request ID.
- *
- * @since 1.5
- */
- public int getRequestId(byte[] inputBytes) throws SnmpStatusException {
- int requestId = 0;
- BerDecoder bdec = null;
- BerDecoder bdec2 = null;
- byte[] any = null;
- try {
- bdec = new BerDecoder(inputBytes);
- bdec.openSequence();
- bdec.fetchInteger();
- bdec.fetchOctetString();
- any = bdec.fetchAny();
- bdec2 = new BerDecoder(any);
- int type = bdec2.getTag();
- bdec2.openSequence(type);
- requestId = bdec2.fetchInteger();
- }
- catch(BerException x) {
- throw new SnmpStatusException("Invalid encoding") ;
- }
- try {
- bdec.closeSequence();
- }
- catch(BerException x) {
- }
- try {
- bdec2.closeSequence();
- }
- catch(BerException x) {
- }
- return requestId;
- }
- /**
- * Decodes the specified bytes and initializes this message.
- * For internal use only.
- *
- * @param inputBytes The bytes to be decoded.
- *
- * @exception SnmpStatusException If the specified bytes are not a valid encoding.
- */
- public void decodeMessage(byte[] inputBytes, int byteCount)
- throws SnmpStatusException {
- try {
- BerDecoder bdec = new BerDecoder(inputBytes/*, byteCount */) ; // FIXME
- bdec.openSequence() ;
- version = bdec.fetchInteger() ;
- community = bdec.fetchOctetString() ;
- data = bdec.fetchAny() ;
- dataLength = data.length ;
- bdec.closeSequence() ;
- }
- catch(BerException x) {
- throw new SnmpStatusException("Invalid encoding") ;
- }
- }
-
- /**
- * Initializes this message with the specified <CODE>pdu</CODE>.
- * <P>
- * This method initializes the data field with an array of
- * <CODE>maxDataLength</CODE> bytes. It encodes the <CODE>pdu</CODE>.
- * The resulting encoding is stored in the data field
- * and the length of the encoding is stored in <CODE>dataLength</CODE>.
- * <p>
- * If the encoding length exceeds <CODE>maxDataLength</CODE>,
- * the method throws an exception.
- *
- * @param pdu The PDU to be encoded.
- * @param maxDataLength The maximum length permitted for the data field.
- *
- * @exception SnmpStatusException If the specified <CODE>pdu</CODE> is not valid.
- * @exception SnmpTooBigException If the resulting encoding does not fit
- * into <CODE>maxDataLength</CODE> bytes.
- * @exception ArrayIndexOutOfBoundsException If the encoding exceeds <CODE>maxDataLength</CODE>.
- *
- * @since 1.5
- */
- public void encodeSnmpPdu(SnmpPdu pdu, int maxDataLength)
- throws SnmpStatusException, SnmpTooBigException {
- //
- // The easy work
- //
- SnmpPduPacket pdupacket = (SnmpPduPacket) pdu;
- version = pdupacket.version ;
- community = pdupacket.community ;
- address = pdupacket.address ;
- port = pdupacket.port ;
-
- //
- // Allocate the array to receive the encoding.
- //
- data = new byte[maxDataLength] ;
-
- //
- // Encode the pdupacket
- // Reminder: BerEncoder does backward encoding !
- //
-
- try {
- BerEncoder benc = new BerEncoder(data) ;
- benc.openSequence() ;
- encodeVarBindList(benc, pdupacket.varBindList) ;
-
- switch(pdupacket.type) {
-
- case pduGetRequestPdu :
- case pduGetNextRequestPdu :
- case pduInformRequestPdu :
- case pduGetResponsePdu :
- case pduSetRequestPdu :
- case pduV2TrapPdu :
- case pduReportPdu :
- SnmpPduRequest reqPdu = (SnmpPduRequest)pdupacket ;
- benc.putInteger(reqPdu.errorIndex) ;
- benc.putInteger(reqPdu.errorStatus) ;
- benc.putInteger(reqPdu.requestId) ;
- break ;
-
- case pduGetBulkRequestPdu :
- SnmpPduBulk bulkPdu = (SnmpPduBulk)pdupacket ;
- benc.putInteger(bulkPdu.maxRepetitions) ;
- benc.putInteger(bulkPdu.nonRepeaters) ;
- benc.putInteger(bulkPdu.requestId) ;
- break ;
-
- case pduV1TrapPdu :
- SnmpPduTrap trapPdu = (SnmpPduTrap)pdupacket ;
- benc.putInteger(trapPdu.timeStamp, SnmpValue.TimeticksTag) ;
- benc.putInteger(trapPdu.specificTrap) ;
- benc.putInteger(trapPdu.genericTrap) ;
- if(trapPdu.agentAddr != null)
- benc.putOctetString(trapPdu.agentAddr.byteValue(), SnmpValue.IpAddressTag) ;
- else
- benc.putOctetString(new byte[0], SnmpValue.IpAddressTag);
- benc.putOid(trapPdu.enterprise.longValue()) ;
- break ;
-
- default:
- throw new SnmpStatusException("Invalid pdu type " + String.valueOf(pdupacket.type)) ;
- }
- benc.closeSequence(pdupacket.type) ;
- dataLength = benc.trim() ;
- }
- catch(ArrayIndexOutOfBoundsException x) {
- throw new SnmpTooBigException() ;
- }
- }
- /**
- * Gets the PDU encoded in this message.
- * <P>
- * This method decodes the data field and returns the resulting PDU.
- *
- * @return The resulting PDU.
- * @exception SnmpStatusException If the encoding is not valid.
- *
- * @since 1.5
- */
- public SnmpPdu decodeSnmpPdu()
- throws SnmpStatusException {
- //
- // Decode the pdu
- //
- SnmpPduPacket pdu = null ;
- BerDecoder bdec = new BerDecoder(data) ;
- try {
- int type = bdec.getTag() ;
- bdec.openSequence(type) ;
- switch(type) {
-
- case pduGetRequestPdu :
- case pduGetNextRequestPdu :
- case pduInformRequestPdu :
- case pduGetResponsePdu :
- case pduSetRequestPdu :
- case pduV2TrapPdu :
- case pduReportPdu :
- SnmpPduRequest reqPdu = new SnmpPduRequest() ;
- reqPdu.requestId = bdec.fetchInteger() ;
- reqPdu.errorStatus = bdec.fetchInteger() ;
- reqPdu.errorIndex = bdec.fetchInteger() ;
- pdu = reqPdu ;
- break ;
-
- case pduGetBulkRequestPdu :
- SnmpPduBulk bulkPdu = new SnmpPduBulk() ;
- bulkPdu.requestId = bdec.fetchInteger() ;
- bulkPdu.nonRepeaters = bdec.fetchInteger() ;
- bulkPdu.maxRepetitions = bdec.fetchInteger() ;
- pdu = bulkPdu ;
- break ;
-
- case pduV1TrapPdu :
- SnmpPduTrap trapPdu = new SnmpPduTrap() ;
- trapPdu.enterprise = new SnmpOid(bdec.fetchOid()) ;
- byte []b = bdec.fetchOctetString(SnmpValue.IpAddressTag);
- if(b.length != 0)
- trapPdu.agentAddr = new SnmpIpAddress(b) ;
- else
- trapPdu.agentAddr = null;
- trapPdu.genericTrap = bdec.fetchInteger() ;
- trapPdu.specificTrap = bdec.fetchInteger() ;
- trapPdu.timeStamp = bdec.fetchInteger(SnmpValue.TimeticksTag) ;
- pdu = trapPdu ;
- break ;
-
- default:
- throw new SnmpStatusException(snmpRspWrongEncoding) ;
- }
- pdu.type = type ;
- pdu.varBindList = decodeVarBindList(bdec) ;
- bdec.closeSequence() ;
- } catch(BerException e) {
- if (isDebugOn()) {
- debug("decodeSnmpPdu", e);
- }
- throw new SnmpStatusException(snmpRspWrongEncoding);
- } catch(IllegalArgumentException e) {
- // bug id 4654066
- if (isDebugOn()) {
- debug("decodeSnmpPdu", e);
- }
- throw new SnmpStatusException(snmpRspWrongEncoding);
- }
-
- //
- // The easy work
- //
- pdu.version = version ;
- pdu.community = community ;
- pdu.address = address ;
- pdu.port = port ;
-
- return pdu;
- }
- /**
- * Dumps this message in a string.
- *
- * @return The string containing the dump.
- */
- public String printMessage() {
- StringBuffer sb = new StringBuffer();
- if (community == null) {
- sb.append("Community: null") ;
- }
- else {
- sb.append("Community: {\n") ;
- sb.append(dumpHexBuffer(community, 0, community.length)) ;
- sb.append("\n}\n") ;
- }
- return sb.append(super.printMessage()).toString();
- }
- // TRACES & DEBUG
- //---------------
-
- boolean isTraceOn() {
- return Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_SNMP);
- }
-
- void trace(String clz, String func, String info) {
- Trace.send(Trace.LEVEL_TRACE, Trace.INFO_SNMP, clz, func, info);
- }
-
- void trace(String func, String info) {
- trace(dbgTag, func, info);
- }
-
- boolean isDebugOn() {
- return Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_SNMP);
- }
-
- void debug(String clz, String func, String info) {
- Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_SNMP, clz, func, info);
- }
-
- void debug(String clz, String func, Throwable exception) {
- Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_SNMP, clz, func, exception);
- }
-
- void debug(String func, String info) {
- debug(dbgTag, func, info);
- }
-
- void debug(String func, Throwable exception) {
- debug(dbgTag, func, exception);
- }
-
- String dbgTag = "SnmpMessage";
- }
-
-
-
-