blob: 492b2f1b5e435aabab806a615e28bb316c9357a9 [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
18/**
Ray Milkey269ffb92014-04-03 14:43:30 -070019 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080020 */
Jonathan Hartdeda0ba2014-04-03 11:14:12 -070021package net.onrc.onos.core.packet;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080022
23import java.nio.ByteBuffer;
24import java.util.Arrays;
25import java.util.Collection;
26import java.util.HashMap;
27import java.util.Map;
28
Yuta HIGUCHI498e1532014-08-20 21:30:28 -070029import org.apache.commons.lang3.ArrayUtils;
Pavlin Radoslavov1d595c02014-04-16 14:11:54 -070030
Yuta HIGUCHIaa132f52014-06-26 10:18:39 -070031// CHECKSTYLE IGNORE WriteTag FOR NEXT 2 LINES
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080032/**
33 * @author David Erickson (daviderickson@cs.stanford.edu)
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080034 */
35public class IPv4 extends BasePacket {
Ray Milkey269ffb92014-04-03 14:43:30 -070036 public static final int ADDRESS_LENGTH = 4;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080037 public static final byte PROTOCOL_ICMP = 0x1;
38 public static final byte PROTOCOL_TCP = 0x6;
39 public static final byte PROTOCOL_UDP = 0x11;
Pavlin Radoslavov608fac32014-04-09 12:40:24 -070040 public static final Map<Byte, Class<? extends IPacket>> PROTOCOL_CLASS_MAP;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080041
42 static {
Pavlin Radoslavov608fac32014-04-09 12:40:24 -070043 PROTOCOL_CLASS_MAP = new HashMap<Byte, Class<? extends IPacket>>();
44 PROTOCOL_CLASS_MAP.put(PROTOCOL_ICMP, ICMP.class);
45 PROTOCOL_CLASS_MAP.put(PROTOCOL_TCP, TCP.class);
46 PROTOCOL_CLASS_MAP.put(PROTOCOL_UDP, UDP.class);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080047 }
48
49 protected byte version;
50 protected byte headerLength;
51 protected byte diffServ;
52 protected short totalLength;
53 protected short identification;
54 protected byte flags;
55 protected short fragmentOffset;
56 protected byte ttl;
57 protected byte protocol;
58 protected short checksum;
59 protected int sourceAddress;
60 protected int destinationAddress;
61 protected byte[] options;
62
63 protected boolean isTruncated;
64
65 /**
66 * Default constructor that sets the version to 4.
67 */
68 public IPv4() {
69 super();
70 this.version = 4;
71 isTruncated = false;
72 }
73
74 /**
75 * @return the version
76 */
77 public byte getVersion() {
78 return version;
79 }
80
81 /**
82 * @param version the version to set
83 */
84 public IPv4 setVersion(byte version) {
85 this.version = version;
86 return this;
87 }
88
89 /**
90 * @return the headerLength
91 */
92 public byte getHeaderLength() {
93 return headerLength;
94 }
95
96 /**
97 * @return the diffServ
98 */
99 public byte getDiffServ() {
100 return diffServ;
101 }
102
103 /**
104 * @param diffServ the diffServ to set
105 */
106 public IPv4 setDiffServ(byte diffServ) {
107 this.diffServ = diffServ;
108 return this;
109 }
110
111 /**
112 * @return the totalLength
113 */
114 public short getTotalLength() {
115 return totalLength;
116 }
117
118 /**
119 * @return the identification
120 */
121 public short getIdentification() {
122 return identification;
123 }
124
125 public boolean isTruncated() {
126 return isTruncated;
127 }
128
129 public void setTruncated(boolean isTruncated) {
130 this.isTruncated = isTruncated;
131 }
132
133 /**
134 * @param identification the identification to set
135 */
136 public IPv4 setIdentification(short identification) {
137 this.identification = identification;
138 return this;
139 }
140
141 /**
142 * @return the flags
143 */
144 public byte getFlags() {
145 return flags;
146 }
147
148 /**
149 * @param flags the flags to set
150 */
151 public IPv4 setFlags(byte flags) {
152 this.flags = flags;
153 return this;
154 }
155
156 /**
157 * @return the fragmentOffset
158 */
159 public short getFragmentOffset() {
160 return fragmentOffset;
161 }
162
163 /**
164 * @param fragmentOffset the fragmentOffset to set
165 */
166 public IPv4 setFragmentOffset(short fragmentOffset) {
167 this.fragmentOffset = fragmentOffset;
168 return this;
169 }
170
171 /**
172 * @return the ttl
173 */
174 public byte getTtl() {
175 return ttl;
176 }
177
178 /**
179 * @param ttl the ttl to set
180 */
181 public IPv4 setTtl(byte ttl) {
182 this.ttl = ttl;
183 return this;
184 }
185
186 /**
187 * @return the protocol
188 */
189 public byte getProtocol() {
190 return protocol;
191 }
192
193 /**
194 * @param protocol the protocol to set
195 */
196 public IPv4 setProtocol(byte protocol) {
197 this.protocol = protocol;
198 return this;
199 }
200
201 /**
202 * @return the checksum
203 */
204 public short getChecksum() {
205 return checksum;
206 }
207
208 /**
209 * @param checksum the checksum to set
210 */
211 public IPv4 setChecksum(short checksum) {
212 this.checksum = checksum;
213 return this;
214 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700215
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800216 @Override
217 public void resetChecksum() {
218 this.checksum = 0;
219 super.resetChecksum();
220 }
221
222 /**
223 * @return the sourceAddress
224 */
225 public int getSourceAddress() {
226 return sourceAddress;
227 }
228
229 /**
230 * @param sourceAddress the sourceAddress to set
231 */
232 public IPv4 setSourceAddress(int sourceAddress) {
233 this.sourceAddress = sourceAddress;
234 return this;
235 }
236
237 /**
238 * @param sourceAddress the sourceAddress to set
239 */
240 public IPv4 setSourceAddress(String sourceAddress) {
241 this.sourceAddress = IPv4.toIPv4Address(sourceAddress);
242 return this;
243 }
244
245 /**
246 * @return the destinationAddress
247 */
248 public int getDestinationAddress() {
249 return destinationAddress;
250 }
251
252 /**
253 * @param destinationAddress the destinationAddress to set
254 */
255 public IPv4 setDestinationAddress(int destinationAddress) {
256 this.destinationAddress = destinationAddress;
257 return this;
258 }
259
260 /**
261 * @param destinationAddress the destinationAddress to set
262 */
263 public IPv4 setDestinationAddress(String destinationAddress) {
264 this.destinationAddress = IPv4.toIPv4Address(destinationAddress);
265 return this;
266 }
267
268 /**
269 * @return the options
270 */
271 public byte[] getOptions() {
Pavlin Radoslavov1d595c02014-04-16 14:11:54 -0700272 return ArrayUtils.clone(this.options);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800273 }
274
275 /**
276 * @param options the options to set
277 */
278 public IPv4 setOptions(byte[] options) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700279 if (options != null && (options.length % 4) > 0) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800280 throw new IllegalArgumentException(
281 "Options length must be a multiple of 4");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700282 }
Pavlin Radoslavov1d595c02014-04-16 14:11:54 -0700283 this.options = ArrayUtils.clone(options);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800284 return this;
285 }
286
287 /**
288 * Serializes the packet. Will compute and set the following fields if they
289 * are set to specific values at the time serialize is called:
Ray Milkey269ffb92014-04-03 14:43:30 -0700290 * -checksum : 0
291 * -headerLength : 0
292 * -totalLength : 0
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800293 */
Yuta HIGUCHI0fe749a2014-05-27 09:35:16 -0700294 @Override
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800295 public byte[] serialize() {
296 byte[] payloadData = null;
297 if (payload != null) {
298 payload.setParent(this);
299 payloadData = payload.serialize();
300 }
301
302 int optionsLength = 0;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700303 if (this.options != null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800304 optionsLength = this.options.length / 4;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700305 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800306 this.headerLength = (byte) (5 + optionsLength);
307
308 this.totalLength = (short) (this.headerLength * 4 + ((payloadData == null) ? 0
309 : payloadData.length));
310
311 byte[] data = new byte[this.totalLength];
312 ByteBuffer bb = ByteBuffer.wrap(data);
313
314 bb.put((byte) (((this.version & 0xf) << 4) | (this.headerLength & 0xf)));
315 bb.put(this.diffServ);
316 bb.putShort(this.totalLength);
317 bb.putShort(this.identification);
318 bb.putShort((short) (((this.flags & 0x7) << 13) | (this.fragmentOffset & 0x1fff)));
319 bb.put(this.ttl);
320 bb.put(this.protocol);
321 bb.putShort(this.checksum);
322 bb.putInt(this.sourceAddress);
323 bb.putInt(this.destinationAddress);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700324 if (this.options != null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800325 bb.put(this.options);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700326 }
327 if (payloadData != null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800328 bb.put(payloadData);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700329 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800330
331 // compute checksum if needed
332 if (this.checksum == 0) {
333 bb.rewind();
334 int accumulation = 0;
335 for (int i = 0; i < this.headerLength * 2; ++i) {
336 accumulation += 0xffff & bb.getShort();
337 }
338 accumulation = ((accumulation >> 16) & 0xffff)
339 + (accumulation & 0xffff);
340 this.checksum = (short) (~accumulation & 0xffff);
341 bb.putShort(10, this.checksum);
342 }
343 return data;
344 }
345
346 @Override
347 public IPacket deserialize(byte[] data, int offset, int length) {
348 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
349 short sscratch;
350
351 this.version = bb.get();
352 this.headerLength = (byte) (this.version & 0xf);
353 this.version = (byte) ((this.version >> 4) & 0xf);
354 this.diffServ = bb.get();
355 this.totalLength = bb.getShort();
356 this.identification = bb.getShort();
357 sscratch = bb.getShort();
358 this.flags = (byte) ((sscratch >> 13) & 0x7);
359 this.fragmentOffset = (short) (sscratch & 0x1fff);
360 this.ttl = bb.get();
361 this.protocol = bb.get();
362 this.checksum = bb.getShort();
363 this.sourceAddress = bb.getInt();
364 this.destinationAddress = bb.getInt();
365
366 if (this.headerLength > 5) {
367 int optionsLength = (this.headerLength - 5) * 4;
368 this.options = new byte[optionsLength];
369 bb.get(this.options);
370 }
371
372 IPacket payload;
Pavlin Radoslavov608fac32014-04-09 12:40:24 -0700373 if (IPv4.PROTOCOL_CLASS_MAP.containsKey(this.protocol)) {
374 Class<? extends IPacket> clazz = IPv4.PROTOCOL_CLASS_MAP.get(this.protocol);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800375 try {
376 payload = clazz.newInstance();
377 } catch (Exception e) {
378 throw new RuntimeException("Error parsing payload for IPv4 packet", e);
379 }
380 } else {
381 payload = new Data();
382 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700383 this.payload = payload.deserialize(data, bb.position(), bb.limit() - bb.position());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800384 this.payload.setParent(this);
385
Ray Milkeyb29e6262014-04-09 16:02:14 -0700386 if (this.totalLength != length) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800387 this.isTruncated = true;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700388 } else {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800389 this.isTruncated = false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700390 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800391
392 return this;
393 }
394
395 /**
396 * Accepts an IPv4 address of the form xxx.xxx.xxx.xxx, ie 192.168.0.1 and
397 * returns the corresponding 32 bit integer.
Ray Milkey269ffb92014-04-03 14:43:30 -0700398 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800399 * @param ipAddress
Jonathan Hart99ff20a2014-06-15 16:53:00 -0700400 * @return the IPv4 address as an integer
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800401 */
402 public static int toIPv4Address(String ipAddress) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700403 if (ipAddress == null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800404 throw new IllegalArgumentException("Specified IPv4 address must" +
Ray Milkey269ffb92014-04-03 14:43:30 -0700405 "contain 4 sets of numerical digits separated by periods");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700406 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800407 String[] octets = ipAddress.split("\\.");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700408 if (octets.length != 4) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800409 throw new IllegalArgumentException("Specified IPv4 address must" +
Ray Milkey269ffb92014-04-03 14:43:30 -0700410 "contain 4 sets of numerical digits separated by periods");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700411 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800412
413 int result = 0;
414 for (int i = 0; i < 4; ++i) {
Yuta HIGUCHI0fe749a2014-05-27 09:35:16 -0700415 result |= Integer.parseInt(octets[i]) << ((3 - i) * 8);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800416 }
417 return result;
418 }
419
420 /**
421 * Accepts an IPv4 address in a byte array and returns the corresponding
422 * 32-bit integer value.
Ray Milkey269ffb92014-04-03 14:43:30 -0700423 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800424 * @param ipAddress
Jonathan Hart99ff20a2014-06-15 16:53:00 -0700425 * @return the IPv4 address as an integer
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800426 */
427 public static int toIPv4Address(byte[] ipAddress) {
428 int ip = 0;
429 for (int i = 0; i < 4; i++) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700430 int t = (ipAddress[i] & 0xff) << ((3 - i) * 8);
431 ip |= t;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800432 }
433 return ip;
434 }
435
436 /**
437 * Accepts an IPv4 address and returns of string of the form xxx.xxx.xxx.xxx
Ray Milkeyb41100a2014-04-10 10:42:15 -0700438 * ie 192.168.0.1.
Ray Milkey269ffb92014-04-03 14:43:30 -0700439 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800440 * @param ipAddress
Jonathan Hart99ff20a2014-06-15 16:53:00 -0700441 * @return the IPv4 address as a String
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800442 */
443 public static String fromIPv4Address(int ipAddress) {
444 StringBuffer sb = new StringBuffer();
445 int result = 0;
446 for (int i = 0; i < 4; ++i) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700447 result = (ipAddress >> ((3 - i) * 8)) & 0xff;
Yuta HIGUCHI0fe749a2014-05-27 09:35:16 -0700448 sb.append(Integer.toString(result));
Ray Milkeyb29e6262014-04-09 16:02:14 -0700449 if (i != 3) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800450 sb.append(".");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700451 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800452 }
453 return sb.toString();
454 }
455
456 /**
457 * Accepts a collection of IPv4 addresses as integers and returns a single
458 * String useful in toString method's containing collections of IP
459 * addresses.
Ray Milkey269ffb92014-04-03 14:43:30 -0700460 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800461 * @param ipAddresses collection
Jonathan Hart99ff20a2014-06-15 16:53:00 -0700462 * @return the IPv4 addresses in a String
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800463 */
464 public static String fromIPv4AddressCollection(Collection<Integer> ipAddresses) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700465 if (ipAddresses == null) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800466 return "null";
Ray Milkeyb29e6262014-04-09 16:02:14 -0700467 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800468 StringBuffer sb = new StringBuffer();
469 sb.append("[");
470 for (Integer ip : ipAddresses) {
471 sb.append(fromIPv4Address(ip));
472 sb.append(",");
473 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700474 sb.replace(sb.length() - 1, sb.length(), "]");
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800475 return sb.toString();
476 }
477
478 /**
479 * Accepts an IPv4 address of the form xxx.xxx.xxx.xxx, ie 192.168.0.1 and
480 * returns the corresponding byte array.
Ray Milkey269ffb92014-04-03 14:43:30 -0700481 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800482 * @param ipAddress The IP address in the form xx.xxx.xxx.xxx.
483 * @return The IP address separated into bytes
484 */
485 public static byte[] toIPv4AddressBytes(String ipAddress) {
486 String[] octets = ipAddress.split("\\.");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700487 if (octets.length != 4) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800488 throw new IllegalArgumentException("Specified IPv4 address must" +
Ray Milkey269ffb92014-04-03 14:43:30 -0700489 "contain 4 sets of numerical digits separated by periods");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700490 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800491
492 byte[] result = new byte[4];
493 for (int i = 0; i < 4; ++i) {
494 result[i] = Integer.valueOf(octets[i]).byteValue();
495 }
496 return result;
497 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700498
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800499 /**
500 * Accepts an IPv4 address in the form of an integer and
501 * returns the corresponding byte array.
Ray Milkey269ffb92014-04-03 14:43:30 -0700502 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800503 * @param ipAddress The IP address as an integer.
504 * @return The IP address separated into bytes.
505 */
506 public static byte[] toIPv4AddressBytes(int ipAddress) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700507 return new byte[]{
508 (byte) (ipAddress >>> 24),
509 (byte) (ipAddress >>> 16),
510 (byte) (ipAddress >>> 8),
511 (byte) ipAddress};
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800512 }
513
514 /* (non-Javadoc)
515 * @see java.lang.Object#hashCode()
516 */
517 @Override
518 public int hashCode() {
519 final int prime = 2521;
520 int result = super.hashCode();
521 result = prime * result + checksum;
522 result = prime * result + destinationAddress;
523 result = prime * result + diffServ;
524 result = prime * result + flags;
525 result = prime * result + fragmentOffset;
526 result = prime * result + headerLength;
527 result = prime * result + identification;
528 result = prime * result + Arrays.hashCode(options);
529 result = prime * result + protocol;
530 result = prime * result + sourceAddress;
531 result = prime * result + totalLength;
532 result = prime * result + ttl;
533 result = prime * result + version;
534 return result;
535 }
536
537 /* (non-Javadoc)
538 * @see java.lang.Object#equals(java.lang.Object)
539 */
540 @Override
541 public boolean equals(Object obj) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700542 if (this == obj) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800543 return true;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700544 }
545 if (!super.equals(obj)) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800546 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700547 }
548 if (!(obj instanceof IPv4)) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800549 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700550 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800551 IPv4 other = (IPv4) obj;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700552 if (checksum != other.checksum) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800553 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700554 }
555 if (destinationAddress != other.destinationAddress) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800556 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700557 }
558 if (diffServ != other.diffServ) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800559 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700560 }
561 if (flags != other.flags) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800562 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700563 }
564 if (fragmentOffset != other.fragmentOffset) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800565 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700566 }
567 if (headerLength != other.headerLength) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800568 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700569 }
570 if (identification != other.identification) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800571 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700572 }
573 if (!Arrays.equals(options, other.options)) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800574 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700575 }
576 if (protocol != other.protocol) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800577 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700578 }
579 if (sourceAddress != other.sourceAddress) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800580 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700581 }
582 if (totalLength != other.totalLength) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800583 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700584 }
585 if (ttl != other.ttl) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800586 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700587 }
588 if (version != other.version) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800589 return false;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700590 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800591 return true;
592 }
593}