blob: d75b50a20416a15b11988e7d83ba6bccafc06ef8 [file] [log] [blame]
Thomas Vachuska24c849c2014-10-27 09:53:05 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 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
Jonathan Hart2a655752015-04-07 16:46:33 -070028import static org.onlab.packet.PacketUtils.*;
29
alshabibc4901cd2014-09-05 16:50:40 -070030/**
alshabibc4901cd2014-09-05 16:50:40 -070031 *
32 */
33public class IPv4 extends BasePacket {
34 public static final byte PROTOCOL_ICMP = 0x1;
Rusty Eddy1da61a22015-09-01 00:48:58 +000035 public static final byte PROTOCOL_IGMP = 0x2;
alshabibc4901cd2014-09-05 16:50:40 -070036 public static final byte PROTOCOL_TCP = 0x6;
37 public static final byte PROTOCOL_UDP = 0x11;
Jonathan Hart2a655752015-04-07 16:46:33 -070038 public static final Map<Byte, Deserializer<? extends IPacket>> PROTOCOL_DESERIALIZER_MAP =
Ray Milkey241b96a2014-11-17 13:08:20 -080039 new HashMap<>();
alshabibc4901cd2014-09-05 16:50:40 -070040
41 static {
Jonathan Hart2a655752015-04-07 16:46:33 -070042 IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_ICMP, ICMP.deserializer());
Rusty Eddy1da61a22015-09-01 00:48:58 +000043 IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_IGMP, IGMP.deserializer());
Jonathan Hart2a655752015-04-07 16:46:33 -070044 IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_TCP, TCP.deserializer());
45 IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_UDP, UDP.deserializer());
alshabibc4901cd2014-09-05 16:50:40 -070046 }
47
Pavlin Radoslavovbf23c552015-02-20 14:20:30 -080048 private static final byte DSCP_MASK = 0x3f;
49 private static final byte DSCP_OFFSET = 2;
50 private static final byte ECN_MASK = 0x3;
51
Jonathan Hart2a655752015-04-07 16:46:33 -070052 private static final short HEADER_LENGTH = 20;
53
alshabibc4901cd2014-09-05 16:50:40 -070054 protected byte version;
55 protected byte headerLength;
56 protected byte diffServ;
57 protected short totalLength;
58 protected short identification;
59 protected byte flags;
60 protected short fragmentOffset;
61 protected byte ttl;
62 protected byte protocol;
63 protected short checksum;
64 protected int sourceAddress;
65 protected int destinationAddress;
66 protected byte[] options;
67
68 protected boolean isTruncated;
69
70 /**
71 * Default constructor that sets the version to 4.
72 */
73 public IPv4() {
74 super();
75 this.version = 4;
76 this.isTruncated = false;
77 }
78
79 /**
80 * @return the version
81 */
82 public byte getVersion() {
83 return this.version;
84 }
85
86 /**
87 * @param version
88 * the version to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -080089 * @return this
alshabibc4901cd2014-09-05 16:50:40 -070090 */
91 public IPv4 setVersion(final byte version) {
92 this.version = version;
93 return this;
94 }
95
96 /**
97 * @return the headerLength
98 */
99 public byte getHeaderLength() {
100 return this.headerLength;
101 }
102
103 /**
Pavlin Radoslavovbf23c552015-02-20 14:20:30 -0800104 * Gets the DSCP value (6 bits).
105 *
106 * @return the DSCP value (6 bits)
107 */
108 public byte getDscp() {
109 return (byte) ((this.diffServ >>> DSCP_OFFSET) & DSCP_MASK);
110 }
111
112 /**
113 * Sets the DSCP value (6 bits).
114 *
115 * @param dscp the DSCP value (6 bits)
116 * @return this
117 */
118 public IPv4 setDscp(byte dscp) {
119 this.diffServ &= ~(DSCP_MASK << DSCP_OFFSET);
120 this.diffServ |= (dscp & DSCP_MASK) << DSCP_OFFSET;
121 return this;
122 }
123
124 /**
125 * Gets the ECN value (2 bits).
126 *
127 * @return the ECN value (2 bits)
128 */
129 public byte getEcn() {
130 return (byte) (this.diffServ & ECN_MASK);
131 }
132
133 /**
134 * Sets the ECN value (2 bits).
135 *
136 * @param ecn the ECN value (2 bits)
137 * @return this
138 */
139 public IPv4 setEcn(byte ecn) {
140 this.diffServ &= ~ECN_MASK;
141 this.diffServ |= (ecn & ECN_MASK);
142 return this;
143 }
144
145 /**
146 * Gets the DiffServ octet (including the DSCP and ECN bits).
147 *
148 * @return the diffServ octet (including the DSCP and ECN bits)
alshabibc4901cd2014-09-05 16:50:40 -0700149 */
150 public byte getDiffServ() {
151 return this.diffServ;
152 }
153
154 /**
Pavlin Radoslavovbf23c552015-02-20 14:20:30 -0800155 * Sets the DiffServ octet (including the DSCP and ECN bits).
156 *
157 * @param diffServ the diffServ octet to set (including the DSCP and ECN
158 * bits)
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800159 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700160 */
161 public IPv4 setDiffServ(final byte diffServ) {
162 this.diffServ = diffServ;
163 return this;
164 }
165
166 /**
167 * @return the totalLength
168 */
169 public short getTotalLength() {
170 return this.totalLength;
171 }
172
173 /**
174 * @return the identification
175 */
176 public short getIdentification() {
177 return this.identification;
178 }
179
180 public boolean isTruncated() {
181 return this.isTruncated;
182 }
183
184 public void setTruncated(final boolean isTruncated) {
185 this.isTruncated = isTruncated;
186 }
187
188 /**
189 * @param identification
190 * the identification to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800191 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700192 */
193 public IPv4 setIdentification(final short identification) {
194 this.identification = identification;
195 return this;
196 }
197
198 /**
199 * @return the flags
200 */
201 public byte getFlags() {
202 return this.flags;
203 }
204
205 /**
206 * @param flags
207 * the flags to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800208 * @return this
209s */
alshabibc4901cd2014-09-05 16:50:40 -0700210 public IPv4 setFlags(final byte flags) {
211 this.flags = flags;
212 return this;
213 }
214
215 /**
216 * @return the fragmentOffset
217 */
218 public short getFragmentOffset() {
219 return this.fragmentOffset;
220 }
221
222 /**
223 * @param fragmentOffset
224 * the fragmentOffset to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800225 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700226 */
227 public IPv4 setFragmentOffset(final short fragmentOffset) {
228 this.fragmentOffset = fragmentOffset;
229 return this;
230 }
231
232 /**
233 * @return the ttl
234 */
235 public byte getTtl() {
236 return this.ttl;
237 }
238
239 /**
240 * @param ttl
241 * the ttl to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800242 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700243 */
244 public IPv4 setTtl(final byte ttl) {
245 this.ttl = ttl;
246 return this;
247 }
248
249 /**
250 * @return the protocol
251 */
252 public byte getProtocol() {
253 return this.protocol;
254 }
255
256 /**
257 * @param protocol
258 * the protocol to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800259 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700260 */
261 public IPv4 setProtocol(final byte protocol) {
262 this.protocol = protocol;
263 return this;
264 }
265
266 /**
267 * @return the checksum
268 */
269 public short getChecksum() {
270 return this.checksum;
271 }
272
273 /**
274 * @param checksum
275 * the checksum to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800276 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700277 */
278 public IPv4 setChecksum(final short checksum) {
279 this.checksum = checksum;
280 return this;
281 }
282
283 @Override
284 public void resetChecksum() {
285 this.checksum = 0;
286 super.resetChecksum();
287 }
288
289 /**
290 * @return the sourceAddress
291 */
292 public int getSourceAddress() {
293 return this.sourceAddress;
294 }
295
296 /**
297 * @param sourceAddress
298 * the sourceAddress to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800299 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700300 */
301 public IPv4 setSourceAddress(final int sourceAddress) {
302 this.sourceAddress = sourceAddress;
303 return this;
304 }
305
306 /**
307 * @param sourceAddress
308 * the sourceAddress to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800309 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700310 */
311 public IPv4 setSourceAddress(final String sourceAddress) {
312 this.sourceAddress = IPv4.toIPv4Address(sourceAddress);
313 return this;
314 }
315
316 /**
317 * @return the destinationAddress
318 */
319 public int getDestinationAddress() {
320 return this.destinationAddress;
321 }
322
323 /**
324 * @param destinationAddress
325 * the destinationAddress to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800326 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700327 */
328 public IPv4 setDestinationAddress(final int destinationAddress) {
329 this.destinationAddress = destinationAddress;
330 return this;
331 }
332
333 /**
334 * @param destinationAddress
335 * the destinationAddress to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800336 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700337 */
338 public IPv4 setDestinationAddress(final String destinationAddress) {
339 this.destinationAddress = IPv4.toIPv4Address(destinationAddress);
340 return this;
341 }
342
343 /**
344 * @return the options
345 */
346 public byte[] getOptions() {
347 return this.options;
348 }
349
350 /**
351 * @param options
352 * the options to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800353 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700354 */
355 public IPv4 setOptions(final byte[] options) {
356 if (options != null && options.length % 4 > 0) {
357 throw new IllegalArgumentException(
358 "Options length must be a multiple of 4");
359 }
360 this.options = options;
361 return this;
362 }
363
364 /**
365 * Serializes the packet. Will compute and set the following fields if they
366 * are set to specific values at the time serialize is called: -checksum : 0
367 * -headerLength : 0 -totalLength : 0
368 */
369 @Override
370 public byte[] serialize() {
371 byte[] payloadData = null;
372 if (this.payload != null) {
373 this.payload.setParent(this);
374 payloadData = this.payload.serialize();
375 }
376
377 int optionsLength = 0;
378 if (this.options != null) {
379 optionsLength = this.options.length / 4;
380 }
381 this.headerLength = (byte) (5 + optionsLength);
382
383 this.totalLength = (short) (this.headerLength * 4 + (payloadData == null ? 0
384 : payloadData.length));
385
386 final byte[] data = new byte[this.totalLength];
387 final ByteBuffer bb = ByteBuffer.wrap(data);
388
389 bb.put((byte) ((this.version & 0xf) << 4 | this.headerLength & 0xf));
390 bb.put(this.diffServ);
391 bb.putShort(this.totalLength);
392 bb.putShort(this.identification);
393 bb.putShort((short) ((this.flags & 0x7) << 13 | this.fragmentOffset & 0x1fff));
394 bb.put(this.ttl);
395 bb.put(this.protocol);
396 bb.putShort(this.checksum);
397 bb.putInt(this.sourceAddress);
398 bb.putInt(this.destinationAddress);
399 if (this.options != null) {
400 bb.put(this.options);
401 }
402 if (payloadData != null) {
403 bb.put(payloadData);
404 }
405
406 // compute checksum if needed
407 if (this.checksum == 0) {
408 bb.rewind();
409 int accumulation = 0;
410 for (int i = 0; i < this.headerLength * 2; ++i) {
411 accumulation += 0xffff & bb.getShort();
412 }
413 accumulation = (accumulation >> 16 & 0xffff)
414 + (accumulation & 0xffff);
415 this.checksum = (short) (~accumulation & 0xffff);
416 bb.putShort(10, this.checksum);
417 }
418 return data;
419 }
420
421 @Override
422 public IPacket deserialize(final byte[] data, final int offset,
Jonathan Hart2a655752015-04-07 16:46:33 -0700423 final int length) {
alshabibc4901cd2014-09-05 16:50:40 -0700424 final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
425 short sscratch;
426
427 this.version = bb.get();
428 this.headerLength = (byte) (this.version & 0xf);
429 this.version = (byte) (this.version >> 4 & 0xf);
430 this.diffServ = bb.get();
431 this.totalLength = bb.getShort();
432 this.identification = bb.getShort();
433 sscratch = bb.getShort();
434 this.flags = (byte) (sscratch >> 13 & 0x7);
435 this.fragmentOffset = (short) (sscratch & 0x1fff);
436 this.ttl = bb.get();
437 this.protocol = bb.get();
438 this.checksum = bb.getShort();
439 this.sourceAddress = bb.getInt();
440 this.destinationAddress = bb.getInt();
441
442 if (this.headerLength > 5) {
443 final int optionsLength = (this.headerLength - 5) * 4;
444 this.options = new byte[optionsLength];
445 bb.get(this.options);
446 }
447
alshabibc4901cd2014-09-05 16:50:40 -0700448 if (this.totalLength != length) {
449 this.isTruncated = true;
450 } else {
451 this.isTruncated = false;
452 }
453
Jonathan Hart2a655752015-04-07 16:46:33 -0700454 Deserializer<? extends IPacket> deserializer;
455 if (IPv4.PROTOCOL_DESERIALIZER_MAP.containsKey(this.protocol)) {
456 deserializer = IPv4.PROTOCOL_DESERIALIZER_MAP.get(this.protocol);
457 } else {
458 deserializer = Data.deserializer();
459 }
460 try {
461 this.payload = deserializer.deserialize(data, bb.position(),
462 bb.limit() - bb.position());
463 this.payload.setParent(this);
464 } catch (DeserializationException e) {
465 return this;
466 }
467
alshabibc4901cd2014-09-05 16:50:40 -0700468 return this;
469 }
470
471 /**
472 * Accepts an IPv4 address of the form xxx.xxx.xxx.xxx, ie 192.168.0.1 and
473 * returns the corresponding 32 bit integer.
474 *
tom5f18cf32014-09-13 14:10:57 -0700475 * @param ipAddress ip address in string form
476 * @return int ip address value
alshabibc4901cd2014-09-05 16:50:40 -0700477 */
478 public static int toIPv4Address(final String ipAddress) {
479 if (ipAddress == null) {
480 throw new IllegalArgumentException("Specified IPv4 address must"
481 + "contain 4 sets of numerical digits separated by periods");
482 }
483 final String[] octets = ipAddress.split("\\.");
484 if (octets.length != 4) {
485 throw new IllegalArgumentException("Specified IPv4 address must"
486 + "contain 4 sets of numerical digits separated by periods");
487 }
488
489 int result = 0;
490 for (int i = 0; i < 4; ++i) {
Yuta HIGUCHIe5ca93b2014-10-23 09:49:00 -0700491 result |= Integer.parseInt(octets[i]) << (3 - i) * 8;
alshabibc4901cd2014-09-05 16:50:40 -0700492 }
493 return result;
494 }
495
496 /**
497 * Accepts an IPv4 address in a byte array and returns the corresponding
498 * 32-bit integer value.
499 *
tom5f18cf32014-09-13 14:10:57 -0700500 * @param ipAddress ip address in byte form
501 * @return int ip address value
alshabibc4901cd2014-09-05 16:50:40 -0700502 */
503 public static int toIPv4Address(final byte[] ipAddress) {
504 int ip = 0;
505 for (int i = 0; i < 4; i++) {
506 final int t = (ipAddress[i] & 0xff) << (3 - i) * 8;
507 ip |= t;
508 }
509 return ip;
510 }
511
512 /**
513 * Accepts an IPv4 address and returns of string of the form xxx.xxx.xxx.xxx,
514 * e.g., 192.168.0.1.
515 *
tom5f18cf32014-09-13 14:10:57 -0700516 * @param ipAddress ip address in form
517 * @return string form of ip address
alshabibc4901cd2014-09-05 16:50:40 -0700518 */
519 public static String fromIPv4Address(final int ipAddress) {
520 final StringBuffer sb = new StringBuffer();
521 int result = 0;
522 for (int i = 0; i < 4; ++i) {
523 result = ipAddress >> (3 - i) * 8 & 0xff;
Yuta HIGUCHIe5ca93b2014-10-23 09:49:00 -0700524 sb.append(result);
alshabib638dc712014-09-05 18:03:45 -0700525 if (i != 3) {
526 sb.append(".");
527 }
alshabibc4901cd2014-09-05 16:50:40 -0700528 }
529 return sb.toString();
530 }
531
532 /**
533 * Accepts a collection of IPv4 addresses as integers and returns a single
534 * String useful in toString method's containing collections of IP
535 * addresses.
536 *
537 * @param ipAddresses
538 * collection
tom5f18cf32014-09-13 14:10:57 -0700539 * @return ip addresses in comma-separated string form
alshabibc4901cd2014-09-05 16:50:40 -0700540 */
541 public static String fromIPv4AddressCollection(
542 final Collection<Integer> ipAddresses) {
543 if (ipAddresses == null) {
544 return "null";
545 }
546 final StringBuffer sb = new StringBuffer();
547 sb.append("[");
548 for (final Integer ip : ipAddresses) {
549 sb.append(IPv4.fromIPv4Address(ip));
550 sb.append(",");
551 }
552 sb.replace(sb.length() - 1, sb.length(), "]");
553 return sb.toString();
554 }
555
556 /**
557 * Accepts an IPv4 address of the form xxx.xxx.xxx.xxx, ie 192.168.0.1 and
558 * returns the corresponding byte array.
559 *
560 * @param ipAddress
561 * The IP address in the form xx.xxx.xxx.xxx.
562 * @return The IP address separated into bytes
563 */
564 public static byte[] toIPv4AddressBytes(final String ipAddress) {
565 final String[] octets = ipAddress.split("\\.");
566 if (octets.length != 4) {
567 throw new IllegalArgumentException("Specified IPv4 address must"
568 + "contain 4 sets of numerical digits separated by periods");
569 }
570
571 final byte[] result = new byte[4];
572 for (int i = 0; i < 4; ++i) {
573 result[i] = Integer.valueOf(octets[i]).byteValue();
574 }
575 return result;
576 }
577
578 /**
579 * Accepts an IPv4 address in the form of an integer and returns the
580 * corresponding byte array.
581 *
582 * @param ipAddress
583 * The IP address as an integer.
584 * @return The IP address separated into bytes.
585 */
586 public static byte[] toIPv4AddressBytes(final int ipAddress) {
587 return new byte[] {(byte) (ipAddress >>> 24),
588 (byte) (ipAddress >>> 16), (byte) (ipAddress >>> 8),
589 (byte) ipAddress};
590 }
591
592 /*
593 * (non-Javadoc)
594 *
595 * @see java.lang.Object#hashCode()
596 */
597 @Override
598 public int hashCode() {
599 final int prime = 2521;
600 int result = super.hashCode();
601 result = prime * result + this.checksum;
602 result = prime * result + this.destinationAddress;
603 result = prime * result + this.diffServ;
604 result = prime * result + this.flags;
605 result = prime * result + this.fragmentOffset;
606 result = prime * result + this.headerLength;
607 result = prime * result + this.identification;
608 result = prime * result + Arrays.hashCode(this.options);
609 result = prime * result + this.protocol;
610 result = prime * result + this.sourceAddress;
611 result = prime * result + this.totalLength;
612 result = prime * result + this.ttl;
613 result = prime * result + this.version;
614 return result;
615 }
616
617 /*
618 * (non-Javadoc)
619 *
620 * @see java.lang.Object#equals(java.lang.Object)
621 */
622 @Override
623 public boolean equals(final Object obj) {
624 if (this == obj) {
625 return true;
626 }
627 if (!super.equals(obj)) {
628 return false;
629 }
630 if (!(obj instanceof IPv4)) {
631 return false;
632 }
633 final IPv4 other = (IPv4) obj;
634 if (this.checksum != other.checksum) {
635 return false;
636 }
637 if (this.destinationAddress != other.destinationAddress) {
638 return false;
639 }
640 if (this.diffServ != other.diffServ) {
641 return false;
642 }
643 if (this.flags != other.flags) {
644 return false;
645 }
646 if (this.fragmentOffset != other.fragmentOffset) {
647 return false;
648 }
649 if (this.headerLength != other.headerLength) {
650 return false;
651 }
652 if (this.identification != other.identification) {
653 return false;
654 }
655 if (!Arrays.equals(this.options, other.options)) {
656 return false;
657 }
658 if (this.protocol != other.protocol) {
659 return false;
660 }
661 if (this.sourceAddress != other.sourceAddress) {
662 return false;
663 }
664 if (this.totalLength != other.totalLength) {
665 return false;
666 }
667 if (this.ttl != other.ttl) {
668 return false;
669 }
670 if (this.version != other.version) {
671 return false;
672 }
673 return true;
674 }
Jonathan Hart2a655752015-04-07 16:46:33 -0700675
676 /**
677 * Deserializer function for IPv4 packets.
678 *
679 * @return deserializer function
680 */
681 public static Deserializer<IPv4> deserializer() {
682 return (data, offset, length) -> {
683 checkInput(data, offset, length, HEADER_LENGTH);
684
685 IPv4 ipv4 = new IPv4();
686
687 final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
688
689 byte versionByte = bb.get();
690 ipv4.headerLength = (byte) (versionByte & 0xf);
691 ipv4.setVersion((byte) (versionByte >> 4 & 0xf));
692 ipv4.setDiffServ(bb.get());
693 ipv4.totalLength = bb.getShort();
694 ipv4.identification = bb.getShort();
695 short flagsFragment = bb.getShort();
696 ipv4.flags = (byte) (flagsFragment >> 13 & 0x7);
697 ipv4.fragmentOffset = (short) (flagsFragment & 0x1fff);
698 ipv4.ttl = bb.get();
699 ipv4.protocol = bb.get();
700 ipv4.checksum = bb.getShort();
701 ipv4.sourceAddress = bb.getInt();
702 ipv4.destinationAddress = bb.getInt();
703
704 if (ipv4.headerLength > 5) {
705 checkHeaderLength(length, ipv4.headerLength * 4);
706
707 int optionsLength = (ipv4.headerLength - 5) * 4;
708 ipv4.options = new byte[optionsLength];
709 bb.get(ipv4.options);
710 }
711
712 Deserializer<? extends IPacket> deserializer;
713 if (IPv4.PROTOCOL_DESERIALIZER_MAP.containsKey(ipv4.protocol)) {
714 deserializer = IPv4.PROTOCOL_DESERIALIZER_MAP.get(ipv4.protocol);
715 } else {
716 deserializer = Data.deserializer();
717 }
718 ipv4.payload = deserializer.deserialize(data, bb.position(),
719 bb.limit() - bb.position());
720 ipv4.payload.setParent(ipv4);
721
722 if (ipv4.totalLength != length) {
723 ipv4.isTruncated = true;
724 } else {
725 ipv4.isTruncated = false;
726 }
727
728 return ipv4;
729 };
730 }
alshabibc4901cd2014-09-05 16:50:40 -0700731}