blob: a5c5f4f1c66921371a8af86c9f02af303f5f8574 [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;
Rusty Eddy80f12522015-09-03 22:42:02 +000038 public static final byte PROTOCOL_PIM = 0x67;
Jonathan Hart2a655752015-04-07 16:46:33 -070039 public static final Map<Byte, Deserializer<? extends IPacket>> PROTOCOL_DESERIALIZER_MAP =
Ray Milkey241b96a2014-11-17 13:08:20 -080040 new HashMap<>();
alshabibc4901cd2014-09-05 16:50:40 -070041
42 static {
Jonathan Hart2a655752015-04-07 16:46:33 -070043 IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_ICMP, ICMP.deserializer());
Rusty Eddy1da61a22015-09-01 00:48:58 +000044 IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_IGMP, IGMP.deserializer());
Jonathan Hart2a655752015-04-07 16:46:33 -070045 IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_TCP, TCP.deserializer());
46 IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_UDP, UDP.deserializer());
Rusty Eddy80f12522015-09-03 22:42:02 +000047 IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_PIM, PIM.deserializer());
alshabibc4901cd2014-09-05 16:50:40 -070048 }
49
Pavlin Radoslavovbf23c552015-02-20 14:20:30 -080050 private static final byte DSCP_MASK = 0x3f;
51 private static final byte DSCP_OFFSET = 2;
52 private static final byte ECN_MASK = 0x3;
53
Jonathan Hart2a655752015-04-07 16:46:33 -070054 private static final short HEADER_LENGTH = 20;
55
alshabibc4901cd2014-09-05 16:50:40 -070056 protected byte version;
57 protected byte headerLength;
58 protected byte diffServ;
59 protected short totalLength;
60 protected short identification;
61 protected byte flags;
62 protected short fragmentOffset;
63 protected byte ttl;
64 protected byte protocol;
65 protected short checksum;
66 protected int sourceAddress;
67 protected int destinationAddress;
68 protected byte[] options;
69
70 protected boolean isTruncated;
71
72 /**
73 * Default constructor that sets the version to 4.
74 */
75 public IPv4() {
76 super();
77 this.version = 4;
78 this.isTruncated = false;
79 }
80
81 /**
82 * @return the version
83 */
84 public byte getVersion() {
85 return this.version;
86 }
87
88 /**
89 * @param version
90 * the version to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -080091 * @return this
alshabibc4901cd2014-09-05 16:50:40 -070092 */
93 public IPv4 setVersion(final byte version) {
94 this.version = version;
95 return this;
96 }
97
98 /**
99 * @return the headerLength
100 */
101 public byte getHeaderLength() {
102 return this.headerLength;
103 }
104
105 /**
Pavlin Radoslavovbf23c552015-02-20 14:20:30 -0800106 * Gets the DSCP value (6 bits).
107 *
108 * @return the DSCP value (6 bits)
109 */
110 public byte getDscp() {
111 return (byte) ((this.diffServ >>> DSCP_OFFSET) & DSCP_MASK);
112 }
113
114 /**
115 * Sets the DSCP value (6 bits).
116 *
117 * @param dscp the DSCP value (6 bits)
118 * @return this
119 */
120 public IPv4 setDscp(byte dscp) {
121 this.diffServ &= ~(DSCP_MASK << DSCP_OFFSET);
122 this.diffServ |= (dscp & DSCP_MASK) << DSCP_OFFSET;
123 return this;
124 }
125
126 /**
127 * Gets the ECN value (2 bits).
128 *
129 * @return the ECN value (2 bits)
130 */
131 public byte getEcn() {
132 return (byte) (this.diffServ & ECN_MASK);
133 }
134
135 /**
136 * Sets the ECN value (2 bits).
137 *
138 * @param ecn the ECN value (2 bits)
139 * @return this
140 */
141 public IPv4 setEcn(byte ecn) {
142 this.diffServ &= ~ECN_MASK;
143 this.diffServ |= (ecn & ECN_MASK);
144 return this;
145 }
146
147 /**
148 * Gets the DiffServ octet (including the DSCP and ECN bits).
149 *
150 * @return the diffServ octet (including the DSCP and ECN bits)
alshabibc4901cd2014-09-05 16:50:40 -0700151 */
152 public byte getDiffServ() {
153 return this.diffServ;
154 }
155
156 /**
Pavlin Radoslavovbf23c552015-02-20 14:20:30 -0800157 * Sets the DiffServ octet (including the DSCP and ECN bits).
158 *
159 * @param diffServ the diffServ octet to set (including the DSCP and ECN
160 * bits)
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800161 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700162 */
163 public IPv4 setDiffServ(final byte diffServ) {
164 this.diffServ = diffServ;
165 return this;
166 }
167
168 /**
169 * @return the totalLength
170 */
171 public short getTotalLength() {
172 return this.totalLength;
173 }
174
175 /**
176 * @return the identification
177 */
178 public short getIdentification() {
179 return this.identification;
180 }
181
182 public boolean isTruncated() {
183 return this.isTruncated;
184 }
185
186 public void setTruncated(final boolean isTruncated) {
187 this.isTruncated = isTruncated;
188 }
189
190 /**
191 * @param identification
192 * the identification to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800193 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700194 */
195 public IPv4 setIdentification(final short identification) {
196 this.identification = identification;
197 return this;
198 }
199
200 /**
201 * @return the flags
202 */
203 public byte getFlags() {
204 return this.flags;
205 }
206
207 /**
208 * @param flags
209 * the flags to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800210 * @return this
211s */
alshabibc4901cd2014-09-05 16:50:40 -0700212 public IPv4 setFlags(final byte flags) {
213 this.flags = flags;
214 return this;
215 }
216
217 /**
218 * @return the fragmentOffset
219 */
220 public short getFragmentOffset() {
221 return this.fragmentOffset;
222 }
223
224 /**
225 * @param fragmentOffset
226 * the fragmentOffset to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800227 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700228 */
229 public IPv4 setFragmentOffset(final short fragmentOffset) {
230 this.fragmentOffset = fragmentOffset;
231 return this;
232 }
233
234 /**
235 * @return the ttl
236 */
237 public byte getTtl() {
238 return this.ttl;
239 }
240
241 /**
242 * @param ttl
243 * the ttl to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800244 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700245 */
246 public IPv4 setTtl(final byte ttl) {
247 this.ttl = ttl;
248 return this;
249 }
250
251 /**
252 * @return the protocol
253 */
254 public byte getProtocol() {
255 return this.protocol;
256 }
257
258 /**
259 * @param protocol
260 * the protocol to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800261 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700262 */
263 public IPv4 setProtocol(final byte protocol) {
264 this.protocol = protocol;
265 return this;
266 }
267
268 /**
269 * @return the checksum
270 */
271 public short getChecksum() {
272 return this.checksum;
273 }
274
275 /**
276 * @param checksum
277 * the checksum to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800278 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700279 */
280 public IPv4 setChecksum(final short checksum) {
281 this.checksum = checksum;
282 return this;
283 }
284
285 @Override
286 public void resetChecksum() {
287 this.checksum = 0;
288 super.resetChecksum();
289 }
290
291 /**
292 * @return the sourceAddress
293 */
294 public int getSourceAddress() {
295 return this.sourceAddress;
296 }
297
298 /**
299 * @param sourceAddress
300 * the sourceAddress to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800301 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700302 */
303 public IPv4 setSourceAddress(final int sourceAddress) {
304 this.sourceAddress = sourceAddress;
305 return this;
306 }
307
308 /**
309 * @param sourceAddress
310 * the sourceAddress to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800311 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700312 */
313 public IPv4 setSourceAddress(final String sourceAddress) {
314 this.sourceAddress = IPv4.toIPv4Address(sourceAddress);
315 return this;
316 }
317
318 /**
319 * @return the destinationAddress
320 */
321 public int getDestinationAddress() {
322 return this.destinationAddress;
323 }
324
325 /**
326 * @param destinationAddress
327 * the destinationAddress to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800328 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700329 */
330 public IPv4 setDestinationAddress(final int destinationAddress) {
331 this.destinationAddress = destinationAddress;
332 return this;
333 }
334
335 /**
336 * @param destinationAddress
337 * the destinationAddress to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800338 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700339 */
340 public IPv4 setDestinationAddress(final String destinationAddress) {
341 this.destinationAddress = IPv4.toIPv4Address(destinationAddress);
342 return this;
343 }
344
345 /**
346 * @return the options
347 */
348 public byte[] getOptions() {
349 return this.options;
350 }
351
352 /**
353 * @param options
354 * the options to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800355 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700356 */
357 public IPv4 setOptions(final byte[] options) {
358 if (options != null && options.length % 4 > 0) {
359 throw new IllegalArgumentException(
360 "Options length must be a multiple of 4");
361 }
362 this.options = options;
363 return this;
364 }
365
366 /**
367 * Serializes the packet. Will compute and set the following fields if they
368 * are set to specific values at the time serialize is called: -checksum : 0
369 * -headerLength : 0 -totalLength : 0
370 */
371 @Override
372 public byte[] serialize() {
373 byte[] payloadData = null;
374 if (this.payload != null) {
375 this.payload.setParent(this);
376 payloadData = this.payload.serialize();
377 }
378
379 int optionsLength = 0;
380 if (this.options != null) {
381 optionsLength = this.options.length / 4;
382 }
383 this.headerLength = (byte) (5 + optionsLength);
384
385 this.totalLength = (short) (this.headerLength * 4 + (payloadData == null ? 0
386 : payloadData.length));
387
388 final byte[] data = new byte[this.totalLength];
389 final ByteBuffer bb = ByteBuffer.wrap(data);
390
391 bb.put((byte) ((this.version & 0xf) << 4 | this.headerLength & 0xf));
392 bb.put(this.diffServ);
393 bb.putShort(this.totalLength);
394 bb.putShort(this.identification);
395 bb.putShort((short) ((this.flags & 0x7) << 13 | this.fragmentOffset & 0x1fff));
396 bb.put(this.ttl);
397 bb.put(this.protocol);
398 bb.putShort(this.checksum);
399 bb.putInt(this.sourceAddress);
400 bb.putInt(this.destinationAddress);
401 if (this.options != null) {
402 bb.put(this.options);
403 }
404 if (payloadData != null) {
405 bb.put(payloadData);
406 }
407
408 // compute checksum if needed
409 if (this.checksum == 0) {
410 bb.rewind();
411 int accumulation = 0;
412 for (int i = 0; i < this.headerLength * 2; ++i) {
413 accumulation += 0xffff & bb.getShort();
414 }
415 accumulation = (accumulation >> 16 & 0xffff)
416 + (accumulation & 0xffff);
417 this.checksum = (short) (~accumulation & 0xffff);
418 bb.putShort(10, this.checksum);
419 }
420 return data;
421 }
422
423 @Override
424 public IPacket deserialize(final byte[] data, final int offset,
Jonathan Hart2a655752015-04-07 16:46:33 -0700425 final int length) {
alshabibc4901cd2014-09-05 16:50:40 -0700426 final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
427 short sscratch;
428
429 this.version = bb.get();
430 this.headerLength = (byte) (this.version & 0xf);
431 this.version = (byte) (this.version >> 4 & 0xf);
432 this.diffServ = bb.get();
433 this.totalLength = bb.getShort();
434 this.identification = bb.getShort();
435 sscratch = bb.getShort();
436 this.flags = (byte) (sscratch >> 13 & 0x7);
437 this.fragmentOffset = (short) (sscratch & 0x1fff);
438 this.ttl = bb.get();
439 this.protocol = bb.get();
440 this.checksum = bb.getShort();
441 this.sourceAddress = bb.getInt();
442 this.destinationAddress = bb.getInt();
443
444 if (this.headerLength > 5) {
445 final int optionsLength = (this.headerLength - 5) * 4;
446 this.options = new byte[optionsLength];
447 bb.get(this.options);
448 }
449
alshabibc4901cd2014-09-05 16:50:40 -0700450 if (this.totalLength != length) {
451 this.isTruncated = true;
452 } else {
453 this.isTruncated = false;
454 }
455
Jonathan Hart2a655752015-04-07 16:46:33 -0700456 Deserializer<? extends IPacket> deserializer;
457 if (IPv4.PROTOCOL_DESERIALIZER_MAP.containsKey(this.protocol)) {
458 deserializer = IPv4.PROTOCOL_DESERIALIZER_MAP.get(this.protocol);
459 } else {
460 deserializer = Data.deserializer();
461 }
462 try {
463 this.payload = deserializer.deserialize(data, bb.position(),
464 bb.limit() - bb.position());
465 this.payload.setParent(this);
466 } catch (DeserializationException e) {
467 return this;
468 }
469
alshabibc4901cd2014-09-05 16:50:40 -0700470 return this;
471 }
472
473 /**
474 * Accepts an IPv4 address of the form xxx.xxx.xxx.xxx, ie 192.168.0.1 and
475 * returns the corresponding 32 bit integer.
476 *
tom5f18cf32014-09-13 14:10:57 -0700477 * @param ipAddress ip address in string form
478 * @return int ip address value
alshabibc4901cd2014-09-05 16:50:40 -0700479 */
480 public static int toIPv4Address(final String ipAddress) {
481 if (ipAddress == null) {
482 throw new IllegalArgumentException("Specified IPv4 address must"
483 + "contain 4 sets of numerical digits separated by periods");
484 }
485 final String[] octets = ipAddress.split("\\.");
486 if (octets.length != 4) {
487 throw new IllegalArgumentException("Specified IPv4 address must"
488 + "contain 4 sets of numerical digits separated by periods");
489 }
490
491 int result = 0;
492 for (int i = 0; i < 4; ++i) {
Yuta HIGUCHIe5ca93b2014-10-23 09:49:00 -0700493 result |= Integer.parseInt(octets[i]) << (3 - i) * 8;
alshabibc4901cd2014-09-05 16:50:40 -0700494 }
495 return result;
496 }
497
498 /**
499 * Accepts an IPv4 address in a byte array and returns the corresponding
500 * 32-bit integer value.
501 *
tom5f18cf32014-09-13 14:10:57 -0700502 * @param ipAddress ip address in byte form
503 * @return int ip address value
alshabibc4901cd2014-09-05 16:50:40 -0700504 */
505 public static int toIPv4Address(final byte[] ipAddress) {
506 int ip = 0;
507 for (int i = 0; i < 4; i++) {
508 final int t = (ipAddress[i] & 0xff) << (3 - i) * 8;
509 ip |= t;
510 }
511 return ip;
512 }
513
514 /**
515 * Accepts an IPv4 address and returns of string of the form xxx.xxx.xxx.xxx,
516 * e.g., 192.168.0.1.
517 *
tom5f18cf32014-09-13 14:10:57 -0700518 * @param ipAddress ip address in form
519 * @return string form of ip address
alshabibc4901cd2014-09-05 16:50:40 -0700520 */
521 public static String fromIPv4Address(final int ipAddress) {
522 final StringBuffer sb = new StringBuffer();
523 int result = 0;
524 for (int i = 0; i < 4; ++i) {
525 result = ipAddress >> (3 - i) * 8 & 0xff;
Yuta HIGUCHIe5ca93b2014-10-23 09:49:00 -0700526 sb.append(result);
alshabib638dc712014-09-05 18:03:45 -0700527 if (i != 3) {
528 sb.append(".");
529 }
alshabibc4901cd2014-09-05 16:50:40 -0700530 }
531 return sb.toString();
532 }
533
534 /**
535 * Accepts a collection of IPv4 addresses as integers and returns a single
536 * String useful in toString method's containing collections of IP
537 * addresses.
538 *
539 * @param ipAddresses
540 * collection
tom5f18cf32014-09-13 14:10:57 -0700541 * @return ip addresses in comma-separated string form
alshabibc4901cd2014-09-05 16:50:40 -0700542 */
543 public static String fromIPv4AddressCollection(
544 final Collection<Integer> ipAddresses) {
545 if (ipAddresses == null) {
546 return "null";
547 }
548 final StringBuffer sb = new StringBuffer();
549 sb.append("[");
550 for (final Integer ip : ipAddresses) {
551 sb.append(IPv4.fromIPv4Address(ip));
552 sb.append(",");
553 }
554 sb.replace(sb.length() - 1, sb.length(), "]");
555 return sb.toString();
556 }
557
558 /**
559 * Accepts an IPv4 address of the form xxx.xxx.xxx.xxx, ie 192.168.0.1 and
560 * returns the corresponding byte array.
561 *
562 * @param ipAddress
563 * The IP address in the form xx.xxx.xxx.xxx.
564 * @return The IP address separated into bytes
565 */
566 public static byte[] toIPv4AddressBytes(final String ipAddress) {
567 final String[] octets = ipAddress.split("\\.");
568 if (octets.length != 4) {
569 throw new IllegalArgumentException("Specified IPv4 address must"
570 + "contain 4 sets of numerical digits separated by periods");
571 }
572
573 final byte[] result = new byte[4];
574 for (int i = 0; i < 4; ++i) {
575 result[i] = Integer.valueOf(octets[i]).byteValue();
576 }
577 return result;
578 }
579
580 /**
581 * Accepts an IPv4 address in the form of an integer and returns the
582 * corresponding byte array.
583 *
584 * @param ipAddress
585 * The IP address as an integer.
586 * @return The IP address separated into bytes.
587 */
588 public static byte[] toIPv4AddressBytes(final int ipAddress) {
589 return new byte[] {(byte) (ipAddress >>> 24),
590 (byte) (ipAddress >>> 16), (byte) (ipAddress >>> 8),
591 (byte) ipAddress};
592 }
593
594 /*
595 * (non-Javadoc)
596 *
597 * @see java.lang.Object#hashCode()
598 */
599 @Override
600 public int hashCode() {
601 final int prime = 2521;
602 int result = super.hashCode();
603 result = prime * result + this.checksum;
604 result = prime * result + this.destinationAddress;
605 result = prime * result + this.diffServ;
606 result = prime * result + this.flags;
607 result = prime * result + this.fragmentOffset;
608 result = prime * result + this.headerLength;
609 result = prime * result + this.identification;
610 result = prime * result + Arrays.hashCode(this.options);
611 result = prime * result + this.protocol;
612 result = prime * result + this.sourceAddress;
613 result = prime * result + this.totalLength;
614 result = prime * result + this.ttl;
615 result = prime * result + this.version;
616 return result;
617 }
618
619 /*
620 * (non-Javadoc)
621 *
622 * @see java.lang.Object#equals(java.lang.Object)
623 */
624 @Override
625 public boolean equals(final Object obj) {
626 if (this == obj) {
627 return true;
628 }
629 if (!super.equals(obj)) {
630 return false;
631 }
632 if (!(obj instanceof IPv4)) {
633 return false;
634 }
635 final IPv4 other = (IPv4) obj;
636 if (this.checksum != other.checksum) {
637 return false;
638 }
639 if (this.destinationAddress != other.destinationAddress) {
640 return false;
641 }
642 if (this.diffServ != other.diffServ) {
643 return false;
644 }
645 if (this.flags != other.flags) {
646 return false;
647 }
648 if (this.fragmentOffset != other.fragmentOffset) {
649 return false;
650 }
651 if (this.headerLength != other.headerLength) {
652 return false;
653 }
654 if (this.identification != other.identification) {
655 return false;
656 }
657 if (!Arrays.equals(this.options, other.options)) {
658 return false;
659 }
660 if (this.protocol != other.protocol) {
661 return false;
662 }
663 if (this.sourceAddress != other.sourceAddress) {
664 return false;
665 }
666 if (this.totalLength != other.totalLength) {
667 return false;
668 }
669 if (this.ttl != other.ttl) {
670 return false;
671 }
672 if (this.version != other.version) {
673 return false;
674 }
675 return true;
676 }
Jonathan Hart2a655752015-04-07 16:46:33 -0700677
678 /**
679 * Deserializer function for IPv4 packets.
680 *
681 * @return deserializer function
682 */
683 public static Deserializer<IPv4> deserializer() {
684 return (data, offset, length) -> {
685 checkInput(data, offset, length, HEADER_LENGTH);
686
687 IPv4 ipv4 = new IPv4();
688
689 final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
690
691 byte versionByte = bb.get();
692 ipv4.headerLength = (byte) (versionByte & 0xf);
693 ipv4.setVersion((byte) (versionByte >> 4 & 0xf));
694 ipv4.setDiffServ(bb.get());
695 ipv4.totalLength = bb.getShort();
696 ipv4.identification = bb.getShort();
697 short flagsFragment = bb.getShort();
698 ipv4.flags = (byte) (flagsFragment >> 13 & 0x7);
699 ipv4.fragmentOffset = (short) (flagsFragment & 0x1fff);
700 ipv4.ttl = bb.get();
701 ipv4.protocol = bb.get();
702 ipv4.checksum = bb.getShort();
703 ipv4.sourceAddress = bb.getInt();
704 ipv4.destinationAddress = bb.getInt();
705
706 if (ipv4.headerLength > 5) {
707 checkHeaderLength(length, ipv4.headerLength * 4);
708
709 int optionsLength = (ipv4.headerLength - 5) * 4;
710 ipv4.options = new byte[optionsLength];
711 bb.get(ipv4.options);
712 }
713
714 Deserializer<? extends IPacket> deserializer;
715 if (IPv4.PROTOCOL_DESERIALIZER_MAP.containsKey(ipv4.protocol)) {
716 deserializer = IPv4.PROTOCOL_DESERIALIZER_MAP.get(ipv4.protocol);
717 } else {
718 deserializer = Data.deserializer();
719 }
720 ipv4.payload = deserializer.deserialize(data, bb.position(),
721 bb.limit() - bb.position());
722 ipv4.payload.setParent(ipv4);
723
724 if (ipv4.totalLength != length) {
725 ipv4.isTruncated = true;
726 } else {
727 ipv4.isTruncated = false;
728 }
729
730 return ipv4;
731 };
732 }
alshabibc4901cd2014-09-05 16:50:40 -0700733}