blob: d208727dd797a427314d49a5c00c4a539a391f0f [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
42 */
43 public ICMP setIcmpType(final byte icmpType) {
44 this.icmpType = icmpType;
45 return this;
46 }
47
48 /**
49 * @return the icmp code
50 */
51 public byte getIcmpCode() {
52 return this.icmpCode;
53 }
54
55 /**
56 * @param icmpCode
57 * code to set
58 */
59 public ICMP setIcmpCode(final byte icmpCode) {
60 this.icmpCode = icmpCode;
61 return this;
62 }
63
64 /**
65 * @return the checksum
66 */
67 public short getChecksum() {
68 return this.checksum;
69 }
70
71 /**
72 * @param checksum
73 * the checksum to set
74 */
75 public ICMP setChecksum(final short checksum) {
76 this.checksum = checksum;
77 return this;
78 }
79
80 /**
81 * Serializes the packet. Will compute and set the following fields if they
82 * are set to specific values at the time serialize is called: -checksum : 0
83 * -length : 0
84 */
85 @Override
86 public byte[] serialize() {
87 int length = 4;
88 byte[] payloadData = null;
89 if (this.payload != null) {
90 this.payload.setParent(this);
91 payloadData = this.payload.serialize();
92 length += payloadData.length;
93 }
94
95 final byte[] data = new byte[length];
96 final ByteBuffer bb = ByteBuffer.wrap(data);
97
98 bb.put(this.icmpType);
99 bb.put(this.icmpCode);
100 bb.putShort(this.checksum);
101 if (payloadData != null) {
102 bb.put(payloadData);
103 }
104
105 if (this.parent != null && this.parent instanceof IPv4) {
106 ((IPv4) this.parent).setProtocol(IPv4.PROTOCOL_ICMP);
107 }
108
109 // compute checksum if needed
110 if (this.checksum == 0) {
111 bb.rewind();
112 int accumulation = 0;
113
114 for (int i = 0; i < length / 2; ++i) {
115 accumulation += 0xffff & bb.getShort();
116 }
117 // pad to an even number of shorts
118 if (length % 2 > 0) {
119 accumulation += (bb.get() & 0xff) << 8;
120 }
121
122 accumulation = (accumulation >> 16 & 0xffff)
123 + (accumulation & 0xffff);
124 this.checksum = (short) (~accumulation & 0xffff);
125 bb.putShort(2, this.checksum);
126 }
127 return data;
128 }
129
130 /*
131 * (non-Javadoc)
132 *
133 * @see java.lang.Object#hashCode()
134 */
135 @Override
136 public int hashCode() {
137 final int prime = 5807;
138 int result = super.hashCode();
139 result = prime * result + this.icmpType;
140 result = prime * result + this.icmpCode;
141 result = prime * result + this.checksum;
142 return result;
143 }
144
145 /*
146 * (non-Javadoc)
147 *
148 * @see java.lang.Object#equals(java.lang.Object)
149 */
150 @Override
151 public boolean equals(final Object obj) {
152 if (this == obj) {
153 return true;
154 }
155 if (!super.equals(obj)) {
156 return false;
157 }
158 if (!(obj instanceof ICMP)) {
159 return false;
160 }
161 final ICMP other = (ICMP) obj;
162 if (this.icmpType != other.icmpType) {
163 return false;
164 }
165 if (this.icmpCode != other.icmpCode) {
166 return false;
167 }
168 if (this.checksum != other.checksum) {
169 return false;
170 }
171 return true;
172 }
173
174 @Override
175 public IPacket deserialize(final byte[] data, final int offset,
176 final int length) {
177 final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
178 this.icmpType = bb.get();
179 this.icmpCode = bb.get();
180 this.checksum = bb.getShort();
181
182 this.payload = new Data();
183 this.payload = this.payload.deserialize(data, bb.position(), bb.limit()
184 - bb.position());
185 this.payload.setParent(this);
186 return this;
187 }
188}