1 //
2 // This file is part of the OpenNMS(R) Application.
3 //
4 // OpenNMS(R) is Copyright (C) 2002-2003 The OpenNMS Group, Inc.  All rights reserved.
5 // OpenNMS(R) is a derivative work, containing both original code, included code and modified
6 // code that was published under the GNU General Public License. Copyrights for modified
7 // and included code are below.
8 //
9 // OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
10 //
11 // Modifications:
12 //
13 // 2003 Mar 05: Changes to support response times and more platforms.
14 //
15 // Original code base Copyright (C) 1999-2001 Oculan Corp.  All rights reserved.
16 //
17 // This program is free software; you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation; either version 2 of the License, or
20 // (at your option) any later version.
21 //
22 // This program is distributed in the hope that it will be useful,
23 // but WITHOUT ANY WARRANTY; without even the implied warranty of
24 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 // GNU General Public License for more details.
26 //
27 // You should have received a copy of the GNU General Public License
28 // along with this program; if not, write to the Free Software
29 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 //
31 // For more information contact:
32 //      OpenNMS Licensing       <license@opennms.org>
33 //      http://www.opennms.org/
34 //      http://www.opennms.com/
35 //
36 // Tab Size = 8
37 //
38 
39 package org.opennms.protocols.icmp;
40 
41 import org.opennms.protocols.ip.IPHeader;
42 
43 /**
44  * Defines the default error handler object for processing ICMP error messages.
45  * All error messages follow the same format. The first 8 bytes is the ICMP
46  * header. Immediantly after the ICMP header is the IP packet in error,
47  * including any option data. After the IP header is the first 8 bytes of
48  * protocol data. This is enough to hold a UDP header or the first 8 bytes of a
49  * TCP header.
50  *
51  * @author <a href="mailto:weave@oculan.com">Brian Weaver </a>
52  *
53  */
54 public class ErrorMessage extends ICMPHeader {
55     private IPHeader m_iphdr;
56 
57     private byte[] m_protoData;
58 
59     /**
60      * Creates a new ICMP Error Message object.
61      *
62      * @param type
63      *            The ICMP type.
64      * @param code
65      *            The specific code for the message.
66      *
67      */
ErrorMessage(byte type, byte code)68     protected ErrorMessage(byte type, byte code) {
69         super(type, code);
70         m_iphdr = null;
71         m_protoData = null;
72     }
73 
74     /**
75      * Creates a new ICMP timestamp reply from the spcified data at the specific
76      * offset.
77      *
78      * @param buf
79      *            The buffer containing the data.
80      * @param offset
81      *            The start of the icmp data.
82      *
83      * @exception java.lang.IndexOutOfBoundsException
84      *                Thrown if there is not sufficent data in the buffer.
85      */
ErrorMessage(byte[] buf, int offset)86     public ErrorMessage(byte[] buf, int offset) {
87         super();
88         loadFromBuffer(buf, offset);
89     }
90 
91     /**
92      * Reads the ICMP Address Mask Reqeust from the specified buffer and sets
93      * the internal fields equal to the data. If the buffer does not have
94      * sufficent data to restore the header then an IndexOutOfBoundsException is
95      * thrown by the method. If the buffer does not contain an address mask
96      * reqeust then an IllegalArgumentException is thrown.
97      *
98      * @param buf
99      *            The buffer to read the data from.
100      * @param offset
101      *            The offset to start reading data.
102      *
103      * @return The new offset after reading the data.
104      *
105      * @exception java.lang.IndexOutOfBoundsException
106      *                Thrown if there is not sufficent data in the buffer.
107      */
loadFromBuffer(byte[] buf, int offset)108     public final int loadFromBuffer(byte[] buf, int offset) {
109         //
110         // minimum length
111         //
112         if (buf.length < (offset + 36))
113             throw new IndexOutOfBoundsException("Insufficient data to load ICMP error message");
114 
115         offset = super.loadFromBuffer(buf, offset);
116 
117         //
118         // create the header
119         //
120         m_iphdr = new IPHeader(buf, offset);
121 
122         //
123         // check the minimum length again
124         //
125         if (buf.length < (offset + 16 + m_iphdr.getHeaderLength()))
126             throw new IndexOutOfBoundsException("Insufficient data to load ICMP error message");
127 
128         offset += m_iphdr.getHeaderLength();
129 
130         //
131         // load the extra 8-bytes
132         //
133         m_protoData = new byte[8];
134         for (int x = 0; x < 8; x++) {
135             m_protoData[x] = buf[offset++];
136         }
137 
138         return offset;
139     }
140 
141     /**
142      * Used to access the IP Header that caused the ICMP error message to be
143      * generated.
144      *
145      * @return The IP Header in error.
146      *
147      */
getIPHeader()148     public final IPHeader getIPHeader() {
149         return m_iphdr;
150     }
151 
152     /**
153      * Sets the IP header in error.
154      *
155      * @param hdr
156      *            The IP header in error
157      */
setIPHeader(IPHeader hdr)158     protected void setIPHeader(IPHeader hdr) {
159         m_iphdr = hdr;
160     }
161 
162     /**
163      * Retreives the 8 bytes of protocol data that caused the error.
164      *
165      * @return The first 8 bytes of the packet in error.
166      *
167      */
getProtocolData()168     public final byte[] getProtocolData() {
169         return m_protoData;
170     }
171 
172     /**
173      * Sets the protocol data that caused the error.
174      *
175      * @param pd
176      *            The 8 bytes of protocol data.
177      *
178      * @exception java.lang.IndexOutOfBoundsException
179      *                Thrown when pd.length is less than 8.
180      * @exception java.lang.IllegalArgumentException
181      *                Thrown when pd.length is greater than 8.
182      *
183      */
setProtocolData(byte[] pd)184     protected void setProtocolData(byte[] pd) {
185         if (pd.length < 8)
186             throw new IndexOutOfBoundsException("Protocol data must be 8 bytes in length");
187 
188         if (pd.length > 8)
189             throw new IllegalArgumentException("Protocol data cannot be more than 8 bytes in length");
190 
191         m_protoData = pd;
192     }
193 }
194