blob: 846352bbd8f52f9c9588b207afa6472c1166cf49 [file] [log] [blame]
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001/**
Ray Milkey269ffb92014-04-03 14:43:30 -07002 * Copyright 2011, Big Switch Networks, Inc.
3 * Originally created by David Erickson, Stanford University
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 * not use this file except in compliance with the License. You may obtain
7 * a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations
15 * under the License.
16 **/
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080017
Jonathan Hartdeda0ba2014-04-03 11:14:12 -070018package net.onrc.onos.core.packet;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080019
20import java.nio.ByteBuffer;
21
22/**
Ray Milkeyb41100a2014-04-10 10:42:15 -070023 * Implements ICMP packet format.
Yuta HIGUCHIaa132f52014-06-26 10:18:39 -070024 * <!-- CHECKSTYLE IGNORE WriteTag FOR NEXT 1 LINES -->
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080025 * @author shudong.zhou@bigswitch.com
26 */
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 icmpType;
37 }
38
39 /**
40 * @param icmpType to set
41 */
42 public ICMP setIcmpType(byte icmpType) {
43 this.icmpType = icmpType;
44 return this;
45 }
46
47 /**
48 * @return the icmp code
49 */
50 public byte getIcmpCode() {
51 return icmpCode;
52 }
53
54 /**
55 * @param icmpCode code to set
56 */
57 public ICMP setIcmpCode(byte icmpCode) {
58 this.icmpCode = icmpCode;
59 return this;
60 }
61
62 /**
63 * @return the checksum
64 */
65 public short getChecksum() {
66 return checksum;
67 }
68
69 /**
70 * @param checksum the checksum to set
71 */
72 public ICMP setChecksum(short checksum) {
73 this.checksum = checksum;
74 return this;
75 }
76
77 /**
78 * Serializes the packet. Will compute and set the following fields if they
79 * are set to specific values at the time serialize is called:
Ray Milkey269ffb92014-04-03 14:43:30 -070080 * -checksum : 0
81 * -length : 0
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080082 */
Yuta HIGUCHIaa132f52014-06-26 10:18:39 -070083 @Override
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080084 public byte[] serialize() {
85 int length = 4;
86 byte[] payloadData = null;
87 if (payload != null) {
88 payload.setParent(this);
89 payloadData = payload.serialize();
90 length += payloadData.length;
91 }
92
93 byte[] data = new byte[length];
94 ByteBuffer bb = ByteBuffer.wrap(data);
95
96 bb.put(this.icmpType);
97 bb.put(this.icmpCode);
98 bb.putShort(this.checksum);
Ray Milkeyb29e6262014-04-09 16:02:14 -070099 if (payloadData != null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800100 bb.put(payloadData);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700101 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800102
Ray Milkeyb29e6262014-04-09 16:02:14 -0700103 if (this.parent != null && this.parent instanceof IPv4) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700104 ((IPv4) this.parent).setProtocol(IPv4.PROTOCOL_ICMP);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700105 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800106
107 // compute checksum if needed
108 if (this.checksum == 0) {
109 bb.rewind();
110 int accumulation = 0;
111
112 for (int i = 0; i < length / 2; ++i) {
113 accumulation += 0xffff & bb.getShort();
114 }
115 // pad to an even number of shorts
116 if (length % 2 > 0) {
117 accumulation += (bb.get() & 0xff) << 8;
118 }
119
120 accumulation = ((accumulation >> 16) & 0xffff)
121 + (accumulation & 0xffff);
122 this.checksum = (short) (~accumulation & 0xffff);
123 bb.putShort(2, this.checksum);
124 }
125 return data;
126 }
127
128 /* (non-Javadoc)
129 * @see java.lang.Object#hashCode()
130 */
131 @Override
132 public int hashCode() {
133 final int prime = 5807;
134 int result = super.hashCode();
135 result = prime * result + icmpType;
136 result = prime * result + icmpCode;
137 result = prime * result + checksum;
138 return result;
139 }
140
141 /* (non-Javadoc)
142 * @see java.lang.Object#equals(java.lang.Object)
143 */
144 @Override
145 public boolean equals(Object obj) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700146 if (this == obj) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800147 return true;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700148 }
149 if (!super.equals(obj)) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800150 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700151 }
152 if (!(obj instanceof ICMP)) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800153 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700154 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800155 ICMP other = (ICMP) obj;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700156 if (icmpType != other.icmpType) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800157 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700158 }
159 if (icmpCode != other.icmpCode) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800160 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700161 }
162 if (checksum != other.checksum) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800163 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700164 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800165 return true;
166 }
167
168 @Override
169 public IPacket deserialize(byte[] data, int offset, int length) {
170 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
171 this.icmpType = bb.get();
172 this.icmpCode = bb.get();
173 this.checksum = bb.getShort();
Ray Milkey269ffb92014-04-03 14:43:30 -0700174
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800175 this.payload = new Data();
Ray Milkey269ffb92014-04-03 14:43:30 -0700176 this.payload = payload.deserialize(data, bb.position(), bb.limit() - bb.position());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800177 this.payload.setParent(this);
178 return this;
179 }
180}