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 java.util.Date;
42 
43 import org.opennms.protocols.ip.OC16ChecksumProducer;
44 
45 /**
46  * This is the implementation of an ICMP timestamp reply object. The object can
47  * be stored in a buffer to send or loaded from a received buffer. The class is
48  * marked final since it is not intended to be extended.
49  *
50  * @version 0.1
51  * @author Brian Weaver <weave@oculan.com>
52  *
53  */
54 public final class TimestampReply extends ICMPHeader {
55     private int m_origStamp;
56 
57     private int m_recvStamp;
58 
59     private int m_xmitStamp;
60 
61     /**
62      * Creates a new ICMP Timestamp Reply object.
63      *
64      */
TimestampReply()65     public TimestampReply() {
66         super(ICMPHeader.TYPE_TIMESTAMP_REPLY, (byte) 0);
67         m_origStamp = (int) ((new Date()).getTime() & 0xffffffff);
68         m_recvStamp = m_origStamp;
69         m_xmitStamp = m_origStamp;
70     }
71 
72     /**
73      * Creates a new ICMP timestamp reply from the spcified data at the specific
74      * offset.
75      *
76      * @param buf
77      *            The buffer containing the data.
78      * @param offset
79      *            The start of the icmp data.
80      *
81      * @exception java.lang.IndexOutOfBoundsException
82      *                Thrown if there is not sufficent data in the buffer.
83      * @exception java.lang.IllegalArgumentException
84      *                Thrown if the ICMP type is not an Timestamp Reply.
85      */
TimestampReply(byte[] buf, int offset)86     public TimestampReply(byte[] buf, int offset) {
87         super();
88         loadFromBuffer(buf, offset);
89     }
90 
91     /**
92      * Computes the ones compliment 16-bit checksum for the ICMP message.
93      *
94      */
computeChecksum()95     public final void computeChecksum() {
96         OC16ChecksumProducer summer = new OC16ChecksumProducer();
97         super.computeChecksum(summer);
98 
99         summer.add(m_origStamp);
100         summer.add(m_recvStamp);
101         summer.add(m_xmitStamp);
102         setChecksum(summer.getChecksum());
103     }
104 
105     /**
106      * Writes the ICMP address mask reply out to the specified buffer at the
107      * starting offset. If the buffer does not have sufficent data to store the
108      * information then an IndexOutOfBoundsException is thrown.
109      *
110      * @param buf
111      *            The storage buffer.
112      * @param offset
113      *            The location to start in buf.
114      *
115      * @return The new offset after storing to the buffer.
116      *
117      * @exception java.lang.IndexOutOfBoundsException
118      *                Thrown if the buffer does not have enough storage space.
119      *
120      */
storeToBuffer(byte[] buf, int offset)121     public final int storeToBuffer(byte[] buf, int offset) {
122         if (buf.length < (offset + 20))
123             throw new IndexOutOfBoundsException("Array index overflow in buffer build");
124 
125         computeChecksum();
126         offset = super.storeToBuffer(buf, offset);
127 
128         //
129         // store the current timestamp
130         //
131         buf[offset++] = (byte) ((m_origStamp >> 24) & 0xff);
132         buf[offset++] = (byte) ((m_origStamp >> 16) & 0xff);
133         buf[offset++] = (byte) ((m_origStamp >> 8) & 0xff);
134         buf[offset++] = (byte) (m_origStamp & 0xff);
135 
136         buf[offset++] = (byte) ((m_recvStamp >> 24) & 0xff);
137         buf[offset++] = (byte) ((m_recvStamp >> 16) & 0xff);
138         buf[offset++] = (byte) ((m_recvStamp >> 8) & 0xff);
139         buf[offset++] = (byte) (m_recvStamp & 0xff);
140 
141         buf[offset++] = (byte) ((m_xmitStamp >> 24) & 0xff);
142         buf[offset++] = (byte) ((m_xmitStamp >> 16) & 0xff);
143         buf[offset++] = (byte) ((m_xmitStamp >> 8) & 0xff);
144         buf[offset++] = (byte) (m_xmitStamp & 0xff);
145 
146         return offset;
147     }
148 
149     /**
150      * Reads the ICMP Address Mask Reqeust from the specified buffer and sets
151      * the internal fields equal to the data. If the buffer does not have
152      * sufficent data to restore the header then an IndexOutOfBoundsException is
153      * thrown by the method. If the buffer does not contain an address mask
154      * reqeust then an IllegalArgumentException is thrown.
155      *
156      * @param buf
157      *            The buffer to read the data from.
158      * @param offset
159      *            The offset to start reading data.
160      *
161      * @return The new offset after reading the data.
162      *
163      * @exception java.lang.IndexOutOfBoundsException
164      *                Thrown if there is not sufficent data in the buffer.
165      * @exception java.lang.IllegalArgumentException
166      *                Thrown if the ICMP type is not an Timestamp Reply.
167      */
loadFromBuffer(byte[] buf, int offset)168     public final int loadFromBuffer(byte[] buf, int offset) {
169         if (buf.length < (offset + 20))
170             throw new IndexOutOfBoundsException("Insufficient data to load ICMP header");
171 
172         offset = super.loadFromBuffer(buf, offset);
173 
174         if (getType() != TYPE_TIMESTAMP_REPLY)
175             throw new IllegalArgumentException("The buffer did not contain an Timestamp Reply");
176 
177         m_origStamp = byteToInt(buf[offset++]) << 24 | byteToInt(buf[offset++]) << 16 | byteToInt(buf[offset++]) << 8 | byteToInt(buf[offset++]);
178 
179         m_recvStamp = byteToInt(buf[offset++]) << 24 | byteToInt(buf[offset++]) << 16 | byteToInt(buf[offset++]) << 8 | byteToInt(buf[offset++]);
180 
181         m_xmitStamp = byteToInt(buf[offset++]) << 24 | byteToInt(buf[offset++]) << 16 | byteToInt(buf[offset++]) << 8 | byteToInt(buf[offset++]);
182 
183         return offset;
184     }
185 
186     /**
187      * Sets the originate timestamp to the current date in millisecond
188      * resolution.
189      *
190      * @see java.util.Date#getTime
191      *
192      */
setOriginateTS()193     public final void setOriginateTS() {
194         m_origStamp = (int) ((new Date()).getTime() & 0xffffffff);
195     }
196 
197     /**
198      * Sets the originate timestamp to the passed value.
199      *
200      * @param ts
201      *            The timestamp in milliseconds
202      *
203      */
setOriginateTS(int ts)204     public final void setOriginateTS(int ts) {
205         m_origStamp = ts;
206     }
207 
208     /**
209      * Retreives the current timestamp of the reqeust object.
210      *
211      * @return The 32-bit timestamp in milliseconds.
212      *
213      */
getOriginateTS()214     public final int getOriginateTS() {
215         return m_origStamp;
216     }
217 
218     /**
219      * Sets the receive timestamp to the current date in millisecond resolution.
220      *
221      * @see java.util.Date#getTime
222      *
223      */
setReceiveTS()224     public final void setReceiveTS() {
225         m_recvStamp = (int) ((new Date()).getTime() & 0xffffffff);
226     }
227 
228     /**
229      * Sets the receive timestamp to the passed value.
230      *
231      * @param ts
232      *            The timestamp in milliseconds
233      *
234      */
setReceiveTS(int ts)235     public final void setReceiveTS(int ts) {
236         m_recvStamp = ts;
237     }
238 
239     /**
240      * Retreives the current received timestamp of the reqeust object.
241      *
242      * @return The 32-bit timestamp in milliseconds.
243      *
244      */
getReceiveTS()245     public final int getReceiveTS() {
246         return m_recvStamp;
247     }
248 
249     /**
250      * Sets the transmit timestamp to the current date in millisecond
251      * resolution.
252      *
253      * @see java.util.Date#getTime
254      *
255      */
setTransmitTS()256     public final void setTransmitTS() {
257         m_xmitStamp = (int) ((new Date()).getTime() & 0xffffffff);
258     }
259 
260     /**
261      * Sets the tranmit timestamp to the passed value.
262      *
263      * @param ts
264      *            The timestamp in milliseconds
265      *
266      */
setTransmitTS(int ts)267     public final void setTransmitTS(int ts) {
268         m_xmitStamp = ts;
269     }
270 
271     /**
272      * Retreives the current transmit timestamp of the reply object.
273      *
274      * @return The 32-bit timestamp in milliseconds.
275      *
276      */
getTransmitTS()277     public final int getTransmitTS() {
278         return m_xmitStamp;
279     }
280 
281     /**
282      * Converts the object to an array of bytes.
283      *
284      */
toBytes()285     public final byte[] toBytes() {
286         byte[] b = new byte[20];
287         storeToBuffer(b, 0);
288         return b;
289     }
290 }
291