blob: c1a0883c52159b5cf9a6a252fd079bcd72ed703e [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.
Ray Milkey269ffb92014-04-03 14:43:30 -070024 *
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 */
83 public byte[] serialize() {
84 int length = 4;
85 byte[] payloadData = null;
86 if (payload != null) {
87 payload.setParent(this);
88 payloadData = payload.serialize();
89 length += payloadData.length;
90 }
91
92 byte[] data = new byte[length];
93 ByteBuffer bb = ByteBuffer.wrap(data);
94
95 bb.put(this.icmpType);
96 bb.put(this.icmpCode);
97 bb.putShort(this.checksum);
Ray Milkeyb29e6262014-04-09 16:02:14 -070098 if (payloadData != null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080099 bb.put(payloadData);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700100 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800101
Ray Milkeyb29e6262014-04-09 16:02:14 -0700102 if (this.parent != null && this.parent instanceof IPv4) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700103 ((IPv4) this.parent).setProtocol(IPv4.PROTOCOL_ICMP);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700104 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800105
106 // compute checksum if needed
107 if (this.checksum == 0) {
108 bb.rewind();
109 int accumulation = 0;
110
111 for (int i = 0; i < length / 2; ++i) {
112 accumulation += 0xffff & bb.getShort();
113 }
114 // pad to an even number of shorts
115 if (length % 2 > 0) {
116 accumulation += (bb.get() & 0xff) << 8;
117 }
118
119 accumulation = ((accumulation >> 16) & 0xffff)
120 + (accumulation & 0xffff);
121 this.checksum = (short) (~accumulation & 0xffff);
122 bb.putShort(2, this.checksum);
123 }
124 return data;
125 }
126
127 /* (non-Javadoc)
128 * @see java.lang.Object#hashCode()
129 */
130 @Override
131 public int hashCode() {
132 final int prime = 5807;
133 int result = super.hashCode();
134 result = prime * result + icmpType;
135 result = prime * result + icmpCode;
136 result = prime * result + checksum;
137 return result;
138 }
139
140 /* (non-Javadoc)
141 * @see java.lang.Object#equals(java.lang.Object)
142 */
143 @Override
144 public boolean equals(Object obj) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700145 if (this == obj) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800146 return true;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700147 }
148 if (!super.equals(obj)) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800149 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700150 }
151 if (!(obj instanceof ICMP)) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800152 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700153 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800154 ICMP other = (ICMP) obj;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700155 if (icmpType != other.icmpType) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800156 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700157 }
158 if (icmpCode != other.icmpCode) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800159 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700160 }
161 if (checksum != other.checksum) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800162 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700163 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800164 return true;
165 }
166
167 @Override
168 public IPacket deserialize(byte[] data, int offset, int length) {
169 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
170 this.icmpType = bb.get();
171 this.icmpCode = bb.get();
172 this.checksum = bb.getShort();
Ray Milkey269ffb92014-04-03 14:43:30 -0700173
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800174 this.payload = new Data();
Ray Milkey269ffb92014-04-03 14:43:30 -0700175 this.payload = payload.deserialize(data, bb.position(), bb.limit() - bb.position());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800176 this.payload.setParent(this);
177 return this;
178 }
179}