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