blob: 6e6dd5f8aa6c887c41fcd6aebf5d6b8d4f01e416 [file] [log] [blame]
Thomas Vachuska24c849c2014-10-27 09:53:05 -07001/*
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07002 * Copyright 2014 Open Networking Laboratory
alshabibc4901cd2014-09-05 16:50:40 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
alshabibc4901cd2014-09-05 16:50:40 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska24c849c2014-10-27 09:53:05 -070015 */
16
17
alshabibc4901cd2014-09-05 16:50:40 -070018
19package org.onlab.packet;
20
21import java.nio.ByteBuffer;
22
23/**
24 * Implements ICMP packet format.
25 *
alshabibc4901cd2014-09-05 16:50:40 -070026 */
27public class ICMP extends BasePacket {
28 protected byte icmpType;
29 protected byte icmpCode;
30 protected short checksum;
31
32 /**
33 * @return the icmpType
34 */
35 public byte getIcmpType() {
36 return this.icmpType;
37 }
38
39 /**
40 * @param icmpType
41 * to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -080042 * @return this
alshabibc4901cd2014-09-05 16:50:40 -070043 */
44 public ICMP setIcmpType(final byte icmpType) {
45 this.icmpType = icmpType;
46 return this;
47 }
48
49 /**
50 * @return the icmp code
51 */
52 public byte getIcmpCode() {
53 return this.icmpCode;
54 }
55
56 /**
57 * @param icmpCode
58 * code to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -080059 * @return this
alshabibc4901cd2014-09-05 16:50:40 -070060 */
61 public ICMP setIcmpCode(final byte icmpCode) {
62 this.icmpCode = icmpCode;
63 return this;
64 }
65
66 /**
67 * @return the checksum
68 */
69 public short getChecksum() {
70 return this.checksum;
71 }
72
73 /**
74 * @param checksum
75 * the checksum to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -080076 * @return this
alshabibc4901cd2014-09-05 16:50:40 -070077 */
78 public ICMP setChecksum(final short checksum) {
79 this.checksum = checksum;
80 return this;
81 }
82
83 /**
84 * Serializes the packet. Will compute and set the following fields if they
85 * are set to specific values at the time serialize is called: -checksum : 0
86 * -length : 0
87 */
88 @Override
89 public byte[] serialize() {
90 int length = 4;
91 byte[] payloadData = null;
92 if (this.payload != null) {
93 this.payload.setParent(this);
94 payloadData = this.payload.serialize();
95 length += payloadData.length;
96 }
97
98 final byte[] data = new byte[length];
99 final ByteBuffer bb = ByteBuffer.wrap(data);
100
101 bb.put(this.icmpType);
102 bb.put(this.icmpCode);
103 bb.putShort(this.checksum);
104 if (payloadData != null) {
105 bb.put(payloadData);
106 }
107
108 if (this.parent != null && this.parent instanceof IPv4) {
109 ((IPv4) this.parent).setProtocol(IPv4.PROTOCOL_ICMP);
110 }
111
112 // compute checksum if needed
113 if (this.checksum == 0) {
114 bb.rewind();
115 int accumulation = 0;
116
117 for (int i = 0; i < length / 2; ++i) {
118 accumulation += 0xffff & bb.getShort();
119 }
120 // pad to an even number of shorts
121 if (length % 2 > 0) {
122 accumulation += (bb.get() & 0xff) << 8;
123 }
124
125 accumulation = (accumulation >> 16 & 0xffff)
126 + (accumulation & 0xffff);
127 this.checksum = (short) (~accumulation & 0xffff);
128 bb.putShort(2, this.checksum);
129 }
130 return data;
131 }
132
133 /*
134 * (non-Javadoc)
135 *
136 * @see java.lang.Object#hashCode()
137 */
138 @Override
139 public int hashCode() {
140 final int prime = 5807;
141 int result = super.hashCode();
142 result = prime * result + this.icmpType;
143 result = prime * result + this.icmpCode;
144 result = prime * result + this.checksum;
145 return result;
146 }
147
148 /*
149 * (non-Javadoc)
150 *
151 * @see java.lang.Object#equals(java.lang.Object)
152 */
153 @Override
154 public boolean equals(final Object obj) {
155 if (this == obj) {
156 return true;
157 }
158 if (!super.equals(obj)) {
159 return false;
160 }
161 if (!(obj instanceof ICMP)) {
162 return false;
163 }
164 final ICMP other = (ICMP) obj;
165 if (this.icmpType != other.icmpType) {
166 return false;
167 }
168 if (this.icmpCode != other.icmpCode) {
169 return false;
170 }
171 if (this.checksum != other.checksum) {
172 return false;
173 }
174 return true;
175 }
176
177 @Override
178 public IPacket deserialize(final byte[] data, final int offset,
179 final int length) {
180 final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
181 this.icmpType = bb.get();
182 this.icmpCode = bb.get();
183 this.checksum = bb.getShort();
184
185 this.payload = new Data();
186 this.payload = this.payload.deserialize(data, bb.position(), bb.limit()
187 - bb.position());
188 this.payload.setParent(this);
189 return this;
190 }
191}