blob: 4b80c9478b596352d4c6bbd7ed7e95da96ca041c [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/**
23 * 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);
98 if (payloadData != null)
99 bb.put(payloadData);
100
101 if (this.parent != null && this.parent instanceof IPv4)
Ray Milkey269ffb92014-04-03 14:43:30 -0700102 ((IPv4) this.parent).setProtocol(IPv4.PROTOCOL_ICMP);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800103
104 // compute checksum if needed
105 if (this.checksum == 0) {
106 bb.rewind();
107 int accumulation = 0;
108
109 for (int i = 0; i < length / 2; ++i) {
110 accumulation += 0xffff & bb.getShort();
111 }
112 // pad to an even number of shorts
113 if (length % 2 > 0) {
114 accumulation += (bb.get() & 0xff) << 8;
115 }
116
117 accumulation = ((accumulation >> 16) & 0xffff)
118 + (accumulation & 0xffff);
119 this.checksum = (short) (~accumulation & 0xffff);
120 bb.putShort(2, this.checksum);
121 }
122 return data;
123 }
124
125 /* (non-Javadoc)
126 * @see java.lang.Object#hashCode()
127 */
128 @Override
129 public int hashCode() {
130 final int prime = 5807;
131 int result = super.hashCode();
132 result = prime * result + icmpType;
133 result = prime * result + icmpCode;
134 result = prime * result + checksum;
135 return result;
136 }
137
138 /* (non-Javadoc)
139 * @see java.lang.Object#equals(java.lang.Object)
140 */
141 @Override
142 public boolean equals(Object obj) {
143 if (this == obj)
144 return true;
145 if (!super.equals(obj))
146 return false;
147 if (!(obj instanceof ICMP))
148 return false;
149 ICMP other = (ICMP) obj;
150 if (icmpType != other.icmpType)
151 return false;
152 if (icmpCode != other.icmpCode)
153 return false;
154 if (checksum != other.checksum)
155 return false;
156 return true;
157 }
158
159 @Override
160 public IPacket deserialize(byte[] data, int offset, int length) {
161 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
162 this.icmpType = bb.get();
163 this.icmpCode = bb.get();
164 this.checksum = bb.getShort();
Ray Milkey269ffb92014-04-03 14:43:30 -0700165
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800166 this.payload = new Data();
Ray Milkey269ffb92014-04-03 14:43:30 -0700167 this.payload = payload.deserialize(data, bb.position(), bb.limit() - bb.position());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800168 this.payload.setParent(this);
169 return this;
170 }
171}