blob: dc516891e7ed33008e67329876996a16d8247c42 [file] [log] [blame]
Thomas Vachuska24c849c2014-10-27 09:53:05 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2014-present Open Networking Laboratory
alshabibc4901cd2014-09-05 16:50:40 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
alshabibc4901cd2014-09-05 16:50:40 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Thomas Vachuska24c849c2014-10-27 09:53:05 -070015 */
alshabibc4901cd2014-09-05 16:50:40 -070016
17/**
18 *
19 */
20package org.onlab.packet;
21
22import java.nio.ByteBuffer;
23import java.util.Arrays;
24import java.util.Collection;
25import java.util.HashMap;
26import java.util.Map;
27
Jian Li5fc14292015-12-04 11:30:46 -080028import static com.google.common.base.MoreObjects.toStringHelper;
Jonathan Hart2a655752015-04-07 16:46:33 -070029import static org.onlab.packet.PacketUtils.*;
30
alshabibc4901cd2014-09-05 16:50:40 -070031/**
Jian Li5fc14292015-12-04 11:30:46 -080032 * Implements IPv4 packet format.
alshabibc4901cd2014-09-05 16:50:40 -070033 */
34public class IPv4 extends BasePacket {
35 public static final byte PROTOCOL_ICMP = 0x1;
Rusty Eddy1da61a22015-09-01 00:48:58 +000036 public static final byte PROTOCOL_IGMP = 0x2;
alshabibc4901cd2014-09-05 16:50:40 -070037 public static final byte PROTOCOL_TCP = 0x6;
38 public static final byte PROTOCOL_UDP = 0x11;
Rusty Eddy80f12522015-09-03 22:42:02 +000039 public static final byte PROTOCOL_PIM = 0x67;
Jonathan Hart2a655752015-04-07 16:46:33 -070040 public static final Map<Byte, Deserializer<? extends IPacket>> PROTOCOL_DESERIALIZER_MAP =
Ray Milkey241b96a2014-11-17 13:08:20 -080041 new HashMap<>();
alshabibc4901cd2014-09-05 16:50:40 -070042
43 static {
Jonathan Hart2a655752015-04-07 16:46:33 -070044 IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_ICMP, ICMP.deserializer());
Rusty Eddy1da61a22015-09-01 00:48:58 +000045 IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_IGMP, IGMP.deserializer());
Jonathan Hart2a655752015-04-07 16:46:33 -070046 IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_TCP, TCP.deserializer());
47 IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_UDP, UDP.deserializer());
Rusty Eddy80f12522015-09-03 22:42:02 +000048 IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_PIM, PIM.deserializer());
alshabibc4901cd2014-09-05 16:50:40 -070049 }
50
Pavlin Radoslavovbf23c552015-02-20 14:20:30 -080051 private static final byte DSCP_MASK = 0x3f;
52 private static final byte DSCP_OFFSET = 2;
53 private static final byte ECN_MASK = 0x3;
54
Jonathan Hart2a655752015-04-07 16:46:33 -070055 private static final short HEADER_LENGTH = 20;
56
alshabibc4901cd2014-09-05 16:50:40 -070057 protected byte version;
58 protected byte headerLength;
59 protected byte diffServ;
60 protected short totalLength;
61 protected short identification;
62 protected byte flags;
63 protected short fragmentOffset;
64 protected byte ttl;
65 protected byte protocol;
66 protected short checksum;
67 protected int sourceAddress;
68 protected int destinationAddress;
69 protected byte[] options;
70
71 protected boolean isTruncated;
72
73 /**
74 * Default constructor that sets the version to 4.
75 */
76 public IPv4() {
77 super();
78 this.version = 4;
79 this.isTruncated = false;
80 }
81
82 /**
83 * @return the version
84 */
85 public byte getVersion() {
86 return this.version;
87 }
88
89 /**
90 * @param version
91 * the version to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -080092 * @return this
alshabibc4901cd2014-09-05 16:50:40 -070093 */
94 public IPv4 setVersion(final byte version) {
95 this.version = version;
96 return this;
97 }
98
99 /**
100 * @return the headerLength
101 */
102 public byte getHeaderLength() {
103 return this.headerLength;
104 }
105
106 /**
Pavlin Radoslavovbf23c552015-02-20 14:20:30 -0800107 * Gets the DSCP value (6 bits).
108 *
109 * @return the DSCP value (6 bits)
110 */
111 public byte getDscp() {
112 return (byte) ((this.diffServ >>> DSCP_OFFSET) & DSCP_MASK);
113 }
114
115 /**
116 * Sets the DSCP value (6 bits).
117 *
118 * @param dscp the DSCP value (6 bits)
119 * @return this
120 */
121 public IPv4 setDscp(byte dscp) {
122 this.diffServ &= ~(DSCP_MASK << DSCP_OFFSET);
123 this.diffServ |= (dscp & DSCP_MASK) << DSCP_OFFSET;
124 return this;
125 }
126
127 /**
128 * Gets the ECN value (2 bits).
129 *
130 * @return the ECN value (2 bits)
131 */
132 public byte getEcn() {
133 return (byte) (this.diffServ & ECN_MASK);
134 }
135
136 /**
137 * Sets the ECN value (2 bits).
138 *
139 * @param ecn the ECN value (2 bits)
140 * @return this
141 */
142 public IPv4 setEcn(byte ecn) {
143 this.diffServ &= ~ECN_MASK;
144 this.diffServ |= (ecn & ECN_MASK);
145 return this;
146 }
147
148 /**
149 * Gets the DiffServ octet (including the DSCP and ECN bits).
150 *
151 * @return the diffServ octet (including the DSCP and ECN bits)
alshabibc4901cd2014-09-05 16:50:40 -0700152 */
153 public byte getDiffServ() {
154 return this.diffServ;
155 }
156
157 /**
Pavlin Radoslavovbf23c552015-02-20 14:20:30 -0800158 * Sets the DiffServ octet (including the DSCP and ECN bits).
159 *
160 * @param diffServ the diffServ octet to set (including the DSCP and ECN
161 * bits)
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800162 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700163 */
164 public IPv4 setDiffServ(final byte diffServ) {
165 this.diffServ = diffServ;
166 return this;
167 }
168
169 /**
170 * @return the totalLength
171 */
172 public short getTotalLength() {
173 return this.totalLength;
174 }
175
176 /**
177 * @return the identification
178 */
179 public short getIdentification() {
180 return this.identification;
181 }
182
183 public boolean isTruncated() {
184 return this.isTruncated;
185 }
186
187 public void setTruncated(final boolean isTruncated) {
188 this.isTruncated = isTruncated;
189 }
190
191 /**
192 * @param identification
193 * the identification to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800194 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700195 */
196 public IPv4 setIdentification(final short identification) {
197 this.identification = identification;
198 return this;
199 }
200
201 /**
202 * @return the flags
203 */
204 public byte getFlags() {
205 return this.flags;
206 }
207
208 /**
209 * @param flags
210 * the flags to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800211 * @return this
212s */
alshabibc4901cd2014-09-05 16:50:40 -0700213 public IPv4 setFlags(final byte flags) {
214 this.flags = flags;
215 return this;
216 }
217
218 /**
219 * @return the fragmentOffset
220 */
221 public short getFragmentOffset() {
222 return this.fragmentOffset;
223 }
224
225 /**
226 * @param fragmentOffset
227 * the fragmentOffset to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800228 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700229 */
230 public IPv4 setFragmentOffset(final short fragmentOffset) {
231 this.fragmentOffset = fragmentOffset;
232 return this;
233 }
234
235 /**
236 * @return the ttl
237 */
238 public byte getTtl() {
239 return this.ttl;
240 }
241
242 /**
243 * @param ttl
244 * the ttl to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800245 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700246 */
247 public IPv4 setTtl(final byte ttl) {
248 this.ttl = ttl;
249 return this;
250 }
251
252 /**
253 * @return the protocol
254 */
255 public byte getProtocol() {
256 return this.protocol;
257 }
258
259 /**
260 * @param protocol
261 * the protocol to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800262 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700263 */
264 public IPv4 setProtocol(final byte protocol) {
265 this.protocol = protocol;
266 return this;
267 }
268
269 /**
270 * @return the checksum
271 */
272 public short getChecksum() {
273 return this.checksum;
274 }
275
276 /**
277 * @param checksum
278 * the checksum to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800279 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700280 */
281 public IPv4 setChecksum(final short checksum) {
282 this.checksum = checksum;
283 return this;
284 }
285
286 @Override
287 public void resetChecksum() {
288 this.checksum = 0;
289 super.resetChecksum();
290 }
291
292 /**
293 * @return the sourceAddress
294 */
295 public int getSourceAddress() {
296 return this.sourceAddress;
297 }
298
299 /**
300 * @param sourceAddress
301 * the sourceAddress to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800302 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700303 */
304 public IPv4 setSourceAddress(final int sourceAddress) {
305 this.sourceAddress = sourceAddress;
306 return this;
307 }
308
309 /**
310 * @param sourceAddress
311 * the sourceAddress to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800312 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700313 */
314 public IPv4 setSourceAddress(final String sourceAddress) {
315 this.sourceAddress = IPv4.toIPv4Address(sourceAddress);
316 return this;
317 }
318
319 /**
320 * @return the destinationAddress
321 */
322 public int getDestinationAddress() {
323 return this.destinationAddress;
324 }
325
326 /**
327 * @param destinationAddress
328 * the destinationAddress to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800329 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700330 */
331 public IPv4 setDestinationAddress(final int destinationAddress) {
332 this.destinationAddress = destinationAddress;
333 return this;
334 }
335
336 /**
337 * @param destinationAddress
338 * the destinationAddress to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800339 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700340 */
341 public IPv4 setDestinationAddress(final String destinationAddress) {
342 this.destinationAddress = IPv4.toIPv4Address(destinationAddress);
343 return this;
344 }
345
346 /**
347 * @return the options
348 */
349 public byte[] getOptions() {
350 return this.options;
351 }
352
353 /**
354 * @param options
355 * the options to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800356 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700357 */
358 public IPv4 setOptions(final byte[] options) {
359 if (options != null && options.length % 4 > 0) {
360 throw new IllegalArgumentException(
361 "Options length must be a multiple of 4");
362 }
363 this.options = options;
364 return this;
365 }
366
367 /**
368 * Serializes the packet. Will compute and set the following fields if they
369 * are set to specific values at the time serialize is called: -checksum : 0
370 * -headerLength : 0 -totalLength : 0
371 */
372 @Override
373 public byte[] serialize() {
374 byte[] payloadData = null;
375 if (this.payload != null) {
376 this.payload.setParent(this);
377 payloadData = this.payload.serialize();
378 }
379
380 int optionsLength = 0;
381 if (this.options != null) {
382 optionsLength = this.options.length / 4;
383 }
384 this.headerLength = (byte) (5 + optionsLength);
385
386 this.totalLength = (short) (this.headerLength * 4 + (payloadData == null ? 0
387 : payloadData.length));
388
389 final byte[] data = new byte[this.totalLength];
390 final ByteBuffer bb = ByteBuffer.wrap(data);
391
392 bb.put((byte) ((this.version & 0xf) << 4 | this.headerLength & 0xf));
393 bb.put(this.diffServ);
394 bb.putShort(this.totalLength);
395 bb.putShort(this.identification);
396 bb.putShort((short) ((this.flags & 0x7) << 13 | this.fragmentOffset & 0x1fff));
397 bb.put(this.ttl);
398 bb.put(this.protocol);
399 bb.putShort(this.checksum);
400 bb.putInt(this.sourceAddress);
401 bb.putInt(this.destinationAddress);
402 if (this.options != null) {
403 bb.put(this.options);
404 }
405 if (payloadData != null) {
406 bb.put(payloadData);
407 }
408
409 // compute checksum if needed
410 if (this.checksum == 0) {
411 bb.rewind();
412 int accumulation = 0;
413 for (int i = 0; i < this.headerLength * 2; ++i) {
414 accumulation += 0xffff & bb.getShort();
415 }
416 accumulation = (accumulation >> 16 & 0xffff)
417 + (accumulation & 0xffff);
418 this.checksum = (short) (~accumulation & 0xffff);
419 bb.putShort(10, this.checksum);
420 }
421 return data;
422 }
423
424 @Override
425 public IPacket deserialize(final byte[] data, final int offset,
Jonathan Hart2a655752015-04-07 16:46:33 -0700426 final int length) {
alshabibc4901cd2014-09-05 16:50:40 -0700427 final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
428 short sscratch;
429
430 this.version = bb.get();
431 this.headerLength = (byte) (this.version & 0xf);
432 this.version = (byte) (this.version >> 4 & 0xf);
433 this.diffServ = bb.get();
434 this.totalLength = bb.getShort();
435 this.identification = bb.getShort();
436 sscratch = bb.getShort();
437 this.flags = (byte) (sscratch >> 13 & 0x7);
438 this.fragmentOffset = (short) (sscratch & 0x1fff);
439 this.ttl = bb.get();
440 this.protocol = bb.get();
441 this.checksum = bb.getShort();
442 this.sourceAddress = bb.getInt();
443 this.destinationAddress = bb.getInt();
444
445 if (this.headerLength > 5) {
446 final int optionsLength = (this.headerLength - 5) * 4;
447 this.options = new byte[optionsLength];
448 bb.get(this.options);
449 }
450
alshabibc4901cd2014-09-05 16:50:40 -0700451 if (this.totalLength != length) {
452 this.isTruncated = true;
453 } else {
454 this.isTruncated = false;
455 }
456
Jonathan Hart2a655752015-04-07 16:46:33 -0700457 Deserializer<? extends IPacket> deserializer;
458 if (IPv4.PROTOCOL_DESERIALIZER_MAP.containsKey(this.protocol)) {
459 deserializer = IPv4.PROTOCOL_DESERIALIZER_MAP.get(this.protocol);
460 } else {
461 deserializer = Data.deserializer();
462 }
463 try {
464 this.payload = deserializer.deserialize(data, bb.position(),
465 bb.limit() - bb.position());
466 this.payload.setParent(this);
467 } catch (DeserializationException e) {
468 return this;
469 }
470
alshabibc4901cd2014-09-05 16:50:40 -0700471 return this;
472 }
473
474 /**
475 * Accepts an IPv4 address of the form xxx.xxx.xxx.xxx, ie 192.168.0.1 and
476 * returns the corresponding 32 bit integer.
477 *
tom5f18cf32014-09-13 14:10:57 -0700478 * @param ipAddress ip address in string form
479 * @return int ip address value
alshabibc4901cd2014-09-05 16:50:40 -0700480 */
481 public static int toIPv4Address(final String ipAddress) {
482 if (ipAddress == null) {
483 throw new IllegalArgumentException("Specified IPv4 address must"
484 + "contain 4 sets of numerical digits separated by periods");
485 }
486 final String[] octets = ipAddress.split("\\.");
487 if (octets.length != 4) {
488 throw new IllegalArgumentException("Specified IPv4 address must"
489 + "contain 4 sets of numerical digits separated by periods");
490 }
491
492 int result = 0;
493 for (int i = 0; i < 4; ++i) {
Yuta HIGUCHIe5ca93b2014-10-23 09:49:00 -0700494 result |= Integer.parseInt(octets[i]) << (3 - i) * 8;
alshabibc4901cd2014-09-05 16:50:40 -0700495 }
496 return result;
497 }
498
499 /**
500 * Accepts an IPv4 address in a byte array and returns the corresponding
501 * 32-bit integer value.
502 *
tom5f18cf32014-09-13 14:10:57 -0700503 * @param ipAddress ip address in byte form
504 * @return int ip address value
alshabibc4901cd2014-09-05 16:50:40 -0700505 */
506 public static int toIPv4Address(final byte[] ipAddress) {
507 int ip = 0;
508 for (int i = 0; i < 4; i++) {
509 final int t = (ipAddress[i] & 0xff) << (3 - i) * 8;
510 ip |= t;
511 }
512 return ip;
513 }
514
515 /**
516 * Accepts an IPv4 address and returns of string of the form xxx.xxx.xxx.xxx,
517 * e.g., 192.168.0.1.
518 *
tom5f18cf32014-09-13 14:10:57 -0700519 * @param ipAddress ip address in form
520 * @return string form of ip address
alshabibc4901cd2014-09-05 16:50:40 -0700521 */
522 public static String fromIPv4Address(final int ipAddress) {
523 final StringBuffer sb = new StringBuffer();
524 int result = 0;
525 for (int i = 0; i < 4; ++i) {
526 result = ipAddress >> (3 - i) * 8 & 0xff;
Yuta HIGUCHIe5ca93b2014-10-23 09:49:00 -0700527 sb.append(result);
alshabib638dc712014-09-05 18:03:45 -0700528 if (i != 3) {
529 sb.append(".");
530 }
alshabibc4901cd2014-09-05 16:50:40 -0700531 }
532 return sb.toString();
533 }
534
535 /**
536 * Accepts a collection of IPv4 addresses as integers and returns a single
537 * String useful in toString method's containing collections of IP
538 * addresses.
539 *
540 * @param ipAddresses
541 * collection
tom5f18cf32014-09-13 14:10:57 -0700542 * @return ip addresses in comma-separated string form
alshabibc4901cd2014-09-05 16:50:40 -0700543 */
544 public static String fromIPv4AddressCollection(
545 final Collection<Integer> ipAddresses) {
546 if (ipAddresses == null) {
547 return "null";
548 }
549 final StringBuffer sb = new StringBuffer();
550 sb.append("[");
551 for (final Integer ip : ipAddresses) {
552 sb.append(IPv4.fromIPv4Address(ip));
553 sb.append(",");
554 }
555 sb.replace(sb.length() - 1, sb.length(), "]");
556 return sb.toString();
557 }
558
559 /**
560 * Accepts an IPv4 address of the form xxx.xxx.xxx.xxx, ie 192.168.0.1 and
561 * returns the corresponding byte array.
562 *
563 * @param ipAddress
564 * The IP address in the form xx.xxx.xxx.xxx.
565 * @return The IP address separated into bytes
566 */
567 public static byte[] toIPv4AddressBytes(final String ipAddress) {
568 final String[] octets = ipAddress.split("\\.");
569 if (octets.length != 4) {
570 throw new IllegalArgumentException("Specified IPv4 address must"
571 + "contain 4 sets of numerical digits separated by periods");
572 }
573
574 final byte[] result = new byte[4];
575 for (int i = 0; i < 4; ++i) {
576 result[i] = Integer.valueOf(octets[i]).byteValue();
577 }
578 return result;
579 }
580
581 /**
582 * Accepts an IPv4 address in the form of an integer and returns the
583 * corresponding byte array.
584 *
585 * @param ipAddress
586 * The IP address as an integer.
587 * @return The IP address separated into bytes.
588 */
589 public static byte[] toIPv4AddressBytes(final int ipAddress) {
590 return new byte[] {(byte) (ipAddress >>> 24),
591 (byte) (ipAddress >>> 16), (byte) (ipAddress >>> 8),
592 (byte) ipAddress};
593 }
594
595 /*
596 * (non-Javadoc)
597 *
598 * @see java.lang.Object#hashCode()
599 */
600 @Override
601 public int hashCode() {
602 final int prime = 2521;
603 int result = super.hashCode();
604 result = prime * result + this.checksum;
605 result = prime * result + this.destinationAddress;
606 result = prime * result + this.diffServ;
607 result = prime * result + this.flags;
608 result = prime * result + this.fragmentOffset;
609 result = prime * result + this.headerLength;
610 result = prime * result + this.identification;
611 result = prime * result + Arrays.hashCode(this.options);
612 result = prime * result + this.protocol;
613 result = prime * result + this.sourceAddress;
614 result = prime * result + this.totalLength;
615 result = prime * result + this.ttl;
616 result = prime * result + this.version;
617 return result;
618 }
619
620 /*
621 * (non-Javadoc)
622 *
623 * @see java.lang.Object#equals(java.lang.Object)
624 */
625 @Override
626 public boolean equals(final Object obj) {
627 if (this == obj) {
628 return true;
629 }
630 if (!super.equals(obj)) {
631 return false;
632 }
633 if (!(obj instanceof IPv4)) {
634 return false;
635 }
636 final IPv4 other = (IPv4) obj;
637 if (this.checksum != other.checksum) {
638 return false;
639 }
640 if (this.destinationAddress != other.destinationAddress) {
641 return false;
642 }
643 if (this.diffServ != other.diffServ) {
644 return false;
645 }
646 if (this.flags != other.flags) {
647 return false;
648 }
649 if (this.fragmentOffset != other.fragmentOffset) {
650 return false;
651 }
652 if (this.headerLength != other.headerLength) {
653 return false;
654 }
655 if (this.identification != other.identification) {
656 return false;
657 }
658 if (!Arrays.equals(this.options, other.options)) {
659 return false;
660 }
661 if (this.protocol != other.protocol) {
662 return false;
663 }
664 if (this.sourceAddress != other.sourceAddress) {
665 return false;
666 }
667 if (this.totalLength != other.totalLength) {
668 return false;
669 }
670 if (this.ttl != other.ttl) {
671 return false;
672 }
673 if (this.version != other.version) {
674 return false;
675 }
676 return true;
677 }
Jonathan Hart2a655752015-04-07 16:46:33 -0700678
679 /**
680 * Deserializer function for IPv4 packets.
681 *
682 * @return deserializer function
683 */
684 public static Deserializer<IPv4> deserializer() {
685 return (data, offset, length) -> {
686 checkInput(data, offset, length, HEADER_LENGTH);
687
688 IPv4 ipv4 = new IPv4();
689
690 final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
691
692 byte versionByte = bb.get();
693 ipv4.headerLength = (byte) (versionByte & 0xf);
694 ipv4.setVersion((byte) (versionByte >> 4 & 0xf));
695 ipv4.setDiffServ(bb.get());
696 ipv4.totalLength = bb.getShort();
697 ipv4.identification = bb.getShort();
698 short flagsFragment = bb.getShort();
699 ipv4.flags = (byte) (flagsFragment >> 13 & 0x7);
700 ipv4.fragmentOffset = (short) (flagsFragment & 0x1fff);
701 ipv4.ttl = bb.get();
702 ipv4.protocol = bb.get();
703 ipv4.checksum = bb.getShort();
704 ipv4.sourceAddress = bb.getInt();
705 ipv4.destinationAddress = bb.getInt();
706
707 if (ipv4.headerLength > 5) {
708 checkHeaderLength(length, ipv4.headerLength * 4);
709
710 int optionsLength = (ipv4.headerLength - 5) * 4;
711 ipv4.options = new byte[optionsLength];
712 bb.get(ipv4.options);
713 }
714
715 Deserializer<? extends IPacket> deserializer;
716 if (IPv4.PROTOCOL_DESERIALIZER_MAP.containsKey(ipv4.protocol)) {
717 deserializer = IPv4.PROTOCOL_DESERIALIZER_MAP.get(ipv4.protocol);
718 } else {
719 deserializer = Data.deserializer();
720 }
721 ipv4.payload = deserializer.deserialize(data, bb.position(),
722 bb.limit() - bb.position());
723 ipv4.payload.setParent(ipv4);
724
725 if (ipv4.totalLength != length) {
726 ipv4.isTruncated = true;
727 } else {
728 ipv4.isTruncated = false;
729 }
730
731 return ipv4;
732 };
733 }
Jian Li5fc14292015-12-04 11:30:46 -0800734
735 @Override
736 public String toString() {
737 return toStringHelper(getClass())
738 .add("version", Byte.toString(version))
739 .add("headerLength", Byte.toString(headerLength))
740 .add("diffServ", Byte.toString(diffServ))
741 .add("totalLength", Short.toString(totalLength))
742 .add("identification", Short.toString(identification))
743 .add("flags", Byte.toString(flags))
744 .add("fragmentOffset", Short.toString(fragmentOffset))
745 .add("ttl", Byte.toString(ttl))
746 .add("protocol", Byte.toString(protocol))
747 .add("checksum", Short.toString(checksum))
748 .add("sourceAddress", Integer.toString(sourceAddress))
749 .add("destinationAddress", Integer.toString(destinationAddress))
750 .add("options", Arrays.toString(options))
751 .add("isTruncated", Boolean.toString(isTruncated))
752 .toString();
753 }
alshabibc4901cd2014-09-05 16:50:40 -0700754}