Source code: com/act365/net/icmp/ICMPReader.java
1 /*
2 * JSocket Wrench
3 *
4 * Copyright (C) act365.com October 2003
5 *
6 * Web site: http://www.act365.com/wrench
7 * E-mail: developers@act365.com
8 *
9 * The JSocket Wrench library adds support for low-level Internet protocols
10 * to the Java programming language.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the Free
14 * Software Foundation; either version 2 of the License, or (at your option)
15 * any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
20 * Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * this program; if not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27 package com.act365.net.icmp ;
28
29 import com.act365.net.*;
30
31 import java.io.* ;
32
33 /**
34 ICMPReader reads ICMPMessage objects from a DatagramPacket.
35 */
36
37 public class ICMPReader {
38
39 short identifier ;
40
41 /**
42 Creates a reader to read from DatagramPacket objects.
43 The reader will only accept ICMP packets with the
44 specified identifier.
45 */
46
47 public ICMPReader( short identifier ){
48 this.identifier = identifier ;
49 }
50
51 /**
52 read() constructs an ICMP message from a buffer. An exception will
53 be thrown if the message is not in the ICMP format or if there is a
54 checksum error but the message will simply be ignored should the
55 identifier does not match.
56 @return The ICMPMessage contained in the packet or null if the
57 identifier did not match.
58 */
59
60 public ICMPMessage read( byte[] buffer, int length, int offset, boolean testchecksum ) throws IOException {
61
62 if( length - offset < 8 ) {
63 throw new IOException("ICMP messages must be at least eight bytes long");
64 }
65
66 short checksum ;
67
68 if( testchecksum && ( checksum = SocketUtils.checksum( buffer , length , offset ) ) != 0 ){
69 throw new IOException("Checksum error: " + checksum );
70 }
71
72 ICMPMessage message = new ICMPMessage();
73
74 message.type = buffer[ offset ];
75 message.code = buffer[ offset + 1 ];
76 message.checksum = SocketUtils.shortFromBytes( buffer , offset + 2 );
77
78 boolean isquery ;
79
80 int datastart ;
81
82 switch( message.type ){
83
84 case ICMP.ICMP_ECHOREPLY:
85 case ICMP.ICMP_ECHO:
86 case ICMP.ICMP_ROUTERADVERT:
87 case ICMP.ICMP_ROUTERSOLICIT:
88 case ICMP.ICMP_TIMESTAMP:
89 case ICMP.ICMP_TIMESTAMPREPLY:
90 case ICMP.ICMP_INFO_REQUEST:
91 case ICMP.ICMP_INFO_REPLY:
92 case ICMP.ICMP_ADDRESS:
93 case ICMP.ICMP_ADDRESSREPLY:
94
95 isquery = true ;
96 datastart = 8 ;
97 break;
98
99 case ICMP.ICMP_DEST_UNREACH:
100 case ICMP.ICMP_SOURCE_QUENCH:
101 case ICMP.ICMP_REDIRECT:
102 case ICMP.ICMP_TIME_EXCEEDED:
103 case ICMP.ICMP_PARAMETERPROB:
104
105 isquery = false ;
106 datastart = 4 ;
107 break;
108
109 default:
110
111 return null ;
112 }
113
114 if( isquery ){
115
116 message.identifier = SocketUtils.shortFromBytes( buffer , offset + 4 );
117
118 if( identifier != message.identifier ){
119 return null ;
120 }
121
122 message.sequence_number = SocketUtils.shortFromBytes( buffer , offset + 6 );
123 }
124
125 byte[] data = new byte[ length - offset - datastart ];
126
127 int i = offset + datastart ;
128
129 while( i < length ){
130 data[ i - offset - datastart ] = buffer[i];
131 ++ i ;
132 }
133
134 message.data = data ;
135
136 return message ;
137 }
138 }