blob: f4f8667174def262b3b126fd30370a238b40ddfb [file] [log] [blame]
alshabibc4901cd2014-09-05 16:50:40 -07001/*******************************************************************************
2 * Copyright 2014 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 ******************************************************************************/
16/**
17 * Copyright 2011, Big Switch Networks, Inc.
18 * Originally created by David Erickson, Stanford University
19 *
20 * Licensed under the Apache License, Version 2.0 (the "License"); you may
21 * not use this file except in compliance with the License. You may obtain
22 * a copy of the License at
23 *
24 * http://www.apache.org/licenses/LICENSE-2.0
25 *
26 * Unless required by applicable law or agreed to in writing, software
27 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29 * License for the specific language governing permissions and limitations
30 * under the License.
31 **/
32
33package org.onlab.packet;
34
35import java.nio.ByteBuffer;
36
37/**
38 * Implements ICMP packet format.
39 *
alshabibc4901cd2014-09-05 16:50:40 -070040 */
41public class ICMP extends BasePacket {
42 protected byte icmpType;
43 protected byte icmpCode;
44 protected short checksum;
45
46 /**
47 * @return the icmpType
48 */
49 public byte getIcmpType() {
50 return this.icmpType;
51 }
52
53 /**
54 * @param icmpType
55 * to set
56 */
57 public ICMP setIcmpType(final byte icmpType) {
58 this.icmpType = icmpType;
59 return this;
60 }
61
62 /**
63 * @return the icmp code
64 */
65 public byte getIcmpCode() {
66 return this.icmpCode;
67 }
68
69 /**
70 * @param icmpCode
71 * code to set
72 */
73 public ICMP setIcmpCode(final byte icmpCode) {
74 this.icmpCode = icmpCode;
75 return this;
76 }
77
78 /**
79 * @return the checksum
80 */
81 public short getChecksum() {
82 return this.checksum;
83 }
84
85 /**
86 * @param checksum
87 * the checksum to set
88 */
89 public ICMP setChecksum(final short checksum) {
90 this.checksum = checksum;
91 return this;
92 }
93
94 /**
95 * Serializes the packet. Will compute and set the following fields if they
96 * are set to specific values at the time serialize is called: -checksum : 0
97 * -length : 0
98 */
99 @Override
100 public byte[] serialize() {
101 int length = 4;
102 byte[] payloadData = null;
103 if (this.payload != null) {
104 this.payload.setParent(this);
105 payloadData = this.payload.serialize();
106 length += payloadData.length;
107 }
108
109 final byte[] data = new byte[length];
110 final ByteBuffer bb = ByteBuffer.wrap(data);
111
112 bb.put(this.icmpType);
113 bb.put(this.icmpCode);
114 bb.putShort(this.checksum);
115 if (payloadData != null) {
116 bb.put(payloadData);
117 }
118
119 if (this.parent != null && this.parent instanceof IPv4) {
120 ((IPv4) this.parent).setProtocol(IPv4.PROTOCOL_ICMP);
121 }
122
123 // compute checksum if needed
124 if (this.checksum == 0) {
125 bb.rewind();
126 int accumulation = 0;
127
128 for (int i = 0; i < length / 2; ++i) {
129 accumulation += 0xffff & bb.getShort();
130 }
131 // pad to an even number of shorts
132 if (length % 2 > 0) {
133 accumulation += (bb.get() & 0xff) << 8;
134 }
135
136 accumulation = (accumulation >> 16 & 0xffff)
137 + (accumulation & 0xffff);
138 this.checksum = (short) (~accumulation & 0xffff);
139 bb.putShort(2, this.checksum);
140 }
141 return data;
142 }
143
144 /*
145 * (non-Javadoc)
146 *
147 * @see java.lang.Object#hashCode()
148 */
149 @Override
150 public int hashCode() {
151 final int prime = 5807;
152 int result = super.hashCode();
153 result = prime * result + this.icmpType;
154 result = prime * result + this.icmpCode;
155 result = prime * result + this.checksum;
156 return result;
157 }
158
159 /*
160 * (non-Javadoc)
161 *
162 * @see java.lang.Object#equals(java.lang.Object)
163 */
164 @Override
165 public boolean equals(final Object obj) {
166 if (this == obj) {
167 return true;
168 }
169 if (!super.equals(obj)) {
170 return false;
171 }
172 if (!(obj instanceof ICMP)) {
173 return false;
174 }
175 final ICMP other = (ICMP) obj;
176 if (this.icmpType != other.icmpType) {
177 return false;
178 }
179 if (this.icmpCode != other.icmpCode) {
180 return false;
181 }
182 if (this.checksum != other.checksum) {
183 return false;
184 }
185 return true;
186 }
187
188 @Override
189 public IPacket deserialize(final byte[] data, final int offset,
190 final int length) {
191 final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
192 this.icmpType = bb.get();
193 this.icmpCode = bb.get();
194 this.checksum = bb.getShort();
195
196 this.payload = new Data();
197 this.payload = this.payload.deserialize(data, bb.position(), bb.limit()
198 - bb.position());
199 this.payload.setParent(this);
200 return this;
201 }
202}