blob: bdfc5c7aa4545d4c7ac22a0658ddd974cd789943 [file] [log] [blame]
Thomas Vachuska24c849c2014-10-27 09:53:05 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
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
alshabibc4901cd2014-09-05 16:50:40 -070017package org.onlab.packet;
18
19import java.nio.ByteBuffer;
20import java.util.Arrays;
21import java.util.Collection;
alshabibc4901cd2014-09-05 16:50:40 -070022import java.util.Map;
23
Yuta HIGUCHIbfc2e922017-06-07 21:46:05 -070024import com.google.common.collect.ImmutableMap;
25
Jian Li5fc14292015-12-04 11:30:46 -080026import static com.google.common.base.MoreObjects.toStringHelper;
Jonathan Hart2a655752015-04-07 16:46:33 -070027import static org.onlab.packet.PacketUtils.*;
28
alshabibc4901cd2014-09-05 16:50:40 -070029/**
Jian Li5fc14292015-12-04 11:30:46 -080030 * Implements IPv4 packet format.
alshabibc4901cd2014-09-05 16:50:40 -070031 */
Jian Li1270aea2016-09-15 13:32:24 +090032public class IPv4 extends IP {
alshabibc4901cd2014-09-05 16:50:40 -070033 public static final byte PROTOCOL_ICMP = 0x1;
Rusty Eddy1da61a22015-09-01 00:48:58 +000034 public static final byte PROTOCOL_IGMP = 0x2;
alshabibc4901cd2014-09-05 16:50:40 -070035 public static final byte PROTOCOL_TCP = 0x6;
36 public static final byte PROTOCOL_UDP = 0x11;
Rusty Eddy80f12522015-09-03 22:42:02 +000037 public static final byte PROTOCOL_PIM = 0x67;
Jonathan Hart2a655752015-04-07 16:46:33 -070038 public static final Map<Byte, Deserializer<? extends IPacket>> PROTOCOL_DESERIALIZER_MAP =
Yuta HIGUCHIbfc2e922017-06-07 21:46:05 -070039 ImmutableMap.<Byte, Deserializer<? extends IPacket>>builder()
40 .put(IPv4.PROTOCOL_ICMP, ICMP.deserializer())
41 .put(IPv4.PROTOCOL_IGMP, IGMP.deserializer())
42 .put(IPv4.PROTOCOL_TCP, TCP.deserializer())
43 .put(IPv4.PROTOCOL_UDP, UDP.deserializer())
44 .put(IPv4.PROTOCOL_PIM, PIM.deserializer())
45 .build();
alshabibc4901cd2014-09-05 16:50:40 -070046
alshabibc4901cd2014-09-05 16:50:40 -070047
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
Jian Li1270aea2016-09-15 13:32:24 +090079 @Override
alshabibc4901cd2014-09-05 16:50:40 -070080 public byte getVersion() {
81 return this.version;
82 }
83
Jian Li1270aea2016-09-15 13:32:24 +090084 @Override
alshabibc4901cd2014-09-05 16:50:40 -070085 public IPv4 setVersion(final byte version) {
86 this.version = version;
87 return this;
88 }
89
90 /**
91 * @return the headerLength
92 */
93 public byte getHeaderLength() {
94 return this.headerLength;
95 }
96
97 /**
Pavlin Radoslavovbf23c552015-02-20 14:20:30 -080098 * Gets the DSCP value (6 bits).
99 *
100 * @return the DSCP value (6 bits)
101 */
102 public byte getDscp() {
103 return (byte) ((this.diffServ >>> DSCP_OFFSET) & DSCP_MASK);
104 }
105
106 /**
107 * Sets the DSCP value (6 bits).
108 *
109 * @param dscp the DSCP value (6 bits)
110 * @return this
111 */
112 public IPv4 setDscp(byte dscp) {
113 this.diffServ &= ~(DSCP_MASK << DSCP_OFFSET);
114 this.diffServ |= (dscp & DSCP_MASK) << DSCP_OFFSET;
115 return this;
116 }
117
118 /**
119 * Gets the ECN value (2 bits).
120 *
121 * @return the ECN value (2 bits)
122 */
123 public byte getEcn() {
124 return (byte) (this.diffServ & ECN_MASK);
125 }
126
127 /**
128 * Sets the ECN value (2 bits).
129 *
130 * @param ecn the ECN value (2 bits)
131 * @return this
132 */
133 public IPv4 setEcn(byte ecn) {
134 this.diffServ &= ~ECN_MASK;
135 this.diffServ |= (ecn & ECN_MASK);
136 return this;
137 }
138
139 /**
140 * Gets the DiffServ octet (including the DSCP and ECN bits).
141 *
142 * @return the diffServ octet (including the DSCP and ECN bits)
alshabibc4901cd2014-09-05 16:50:40 -0700143 */
144 public byte getDiffServ() {
145 return this.diffServ;
146 }
147
148 /**
Pavlin Radoslavovbf23c552015-02-20 14:20:30 -0800149 * Sets the DiffServ octet (including the DSCP and ECN bits).
150 *
151 * @param diffServ the diffServ octet to set (including the DSCP and ECN
152 * bits)
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800153 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700154 */
155 public IPv4 setDiffServ(final byte diffServ) {
156 this.diffServ = diffServ;
157 return this;
158 }
159
160 /**
161 * @return the totalLength
162 */
163 public short getTotalLength() {
164 return this.totalLength;
165 }
166
167 /**
168 * @return the identification
169 */
170 public short getIdentification() {
171 return this.identification;
172 }
173
174 public boolean isTruncated() {
175 return this.isTruncated;
176 }
177
178 public void setTruncated(final boolean isTruncated) {
179 this.isTruncated = isTruncated;
180 }
181
182 /**
183 * @param identification
184 * the identification to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800185 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700186 */
187 public IPv4 setIdentification(final short identification) {
188 this.identification = identification;
189 return this;
190 }
191
192 /**
193 * @return the flags
194 */
195 public byte getFlags() {
196 return this.flags;
197 }
198
199 /**
200 * @param flags
201 * the flags to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800202 * @return this
203s */
alshabibc4901cd2014-09-05 16:50:40 -0700204 public IPv4 setFlags(final byte flags) {
205 this.flags = flags;
206 return this;
207 }
208
209 /**
210 * @return the fragmentOffset
211 */
212 public short getFragmentOffset() {
213 return this.fragmentOffset;
214 }
215
216 /**
217 * @param fragmentOffset
218 * the fragmentOffset to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800219 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700220 */
221 public IPv4 setFragmentOffset(final short fragmentOffset) {
222 this.fragmentOffset = fragmentOffset;
223 return this;
224 }
225
226 /**
227 * @return the ttl
228 */
229 public byte getTtl() {
230 return this.ttl;
231 }
232
233 /**
234 * @param ttl
235 * the ttl to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800236 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700237 */
238 public IPv4 setTtl(final byte ttl) {
239 this.ttl = ttl;
240 return this;
241 }
242
243 /**
244 * @return the protocol
245 */
246 public byte getProtocol() {
247 return this.protocol;
248 }
249
250 /**
251 * @param protocol
252 * the protocol to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800253 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700254 */
255 public IPv4 setProtocol(final byte protocol) {
256 this.protocol = protocol;
257 return this;
258 }
259
260 /**
261 * @return the checksum
262 */
263 public short getChecksum() {
264 return this.checksum;
265 }
266
267 /**
268 * @param checksum
269 * the checksum to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800270 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700271 */
272 public IPv4 setChecksum(final short checksum) {
273 this.checksum = checksum;
274 return this;
275 }
276
277 @Override
278 public void resetChecksum() {
279 this.checksum = 0;
280 super.resetChecksum();
281 }
282
283 /**
284 * @return the sourceAddress
285 */
286 public int getSourceAddress() {
287 return this.sourceAddress;
288 }
289
290 /**
291 * @param sourceAddress
292 * the sourceAddress to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800293 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700294 */
295 public IPv4 setSourceAddress(final int sourceAddress) {
296 this.sourceAddress = sourceAddress;
297 return this;
298 }
299
300 /**
301 * @param sourceAddress
302 * the sourceAddress to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800303 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700304 */
305 public IPv4 setSourceAddress(final String sourceAddress) {
306 this.sourceAddress = IPv4.toIPv4Address(sourceAddress);
307 return this;
308 }
309
310 /**
311 * @return the destinationAddress
312 */
313 public int getDestinationAddress() {
314 return this.destinationAddress;
315 }
316
317 /**
318 * @param destinationAddress
319 * the destinationAddress to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800320 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700321 */
322 public IPv4 setDestinationAddress(final int destinationAddress) {
323 this.destinationAddress = destinationAddress;
324 return this;
325 }
326
327 /**
328 * @param destinationAddress
329 * the destinationAddress to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800330 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700331 */
332 public IPv4 setDestinationAddress(final String destinationAddress) {
333 this.destinationAddress = IPv4.toIPv4Address(destinationAddress);
334 return this;
335 }
336
337 /**
338 * @return the options
339 */
340 public byte[] getOptions() {
341 return this.options;
342 }
343
344 /**
345 * @param options
346 * the options to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800347 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700348 */
349 public IPv4 setOptions(final byte[] options) {
350 if (options != null && options.length % 4 > 0) {
351 throw new IllegalArgumentException(
352 "Options length must be a multiple of 4");
353 }
354 this.options = options;
355 return this;
356 }
357
358 /**
359 * Serializes the packet. Will compute and set the following fields if they
360 * are set to specific values at the time serialize is called: -checksum : 0
361 * -headerLength : 0 -totalLength : 0
362 */
363 @Override
364 public byte[] serialize() {
365 byte[] payloadData = null;
366 if (this.payload != null) {
367 this.payload.setParent(this);
368 payloadData = this.payload.serialize();
369 }
370
371 int optionsLength = 0;
372 if (this.options != null) {
373 optionsLength = this.options.length / 4;
374 }
375 this.headerLength = (byte) (5 + optionsLength);
376
377 this.totalLength = (short) (this.headerLength * 4 + (payloadData == null ? 0
378 : payloadData.length));
379
380 final byte[] data = new byte[this.totalLength];
381 final ByteBuffer bb = ByteBuffer.wrap(data);
382
383 bb.put((byte) ((this.version & 0xf) << 4 | this.headerLength & 0xf));
384 bb.put(this.diffServ);
385 bb.putShort(this.totalLength);
386 bb.putShort(this.identification);
387 bb.putShort((short) ((this.flags & 0x7) << 13 | this.fragmentOffset & 0x1fff));
388 bb.put(this.ttl);
389 bb.put(this.protocol);
390 bb.putShort(this.checksum);
391 bb.putInt(this.sourceAddress);
392 bb.putInt(this.destinationAddress);
393 if (this.options != null) {
394 bb.put(this.options);
395 }
396 if (payloadData != null) {
397 bb.put(payloadData);
398 }
399
400 // compute checksum if needed
401 if (this.checksum == 0) {
402 bb.rewind();
403 int accumulation = 0;
404 for (int i = 0; i < this.headerLength * 2; ++i) {
405 accumulation += 0xffff & bb.getShort();
406 }
407 accumulation = (accumulation >> 16 & 0xffff)
408 + (accumulation & 0xffff);
409 this.checksum = (short) (~accumulation & 0xffff);
410 bb.putShort(10, this.checksum);
411 }
412 return data;
413 }
414
alshabibc4901cd2014-09-05 16:50:40 -0700415
416 /**
417 * Accepts an IPv4 address of the form xxx.xxx.xxx.xxx, ie 192.168.0.1 and
418 * returns the corresponding 32 bit integer.
419 *
tom5f18cf32014-09-13 14:10:57 -0700420 * @param ipAddress ip address in string form
421 * @return int ip address value
alshabibc4901cd2014-09-05 16:50:40 -0700422 */
423 public static int toIPv4Address(final String ipAddress) {
424 if (ipAddress == null) {
425 throw new IllegalArgumentException("Specified IPv4 address must"
426 + "contain 4 sets of numerical digits separated by periods");
427 }
428 final String[] octets = ipAddress.split("\\.");
429 if (octets.length != 4) {
430 throw new IllegalArgumentException("Specified IPv4 address must"
431 + "contain 4 sets of numerical digits separated by periods");
432 }
433
434 int result = 0;
435 for (int i = 0; i < 4; ++i) {
Yuta HIGUCHIe5ca93b2014-10-23 09:49:00 -0700436 result |= Integer.parseInt(octets[i]) << (3 - i) * 8;
alshabibc4901cd2014-09-05 16:50:40 -0700437 }
438 return result;
439 }
440
441 /**
442 * Accepts an IPv4 address in a byte array and returns the corresponding
443 * 32-bit integer value.
444 *
tom5f18cf32014-09-13 14:10:57 -0700445 * @param ipAddress ip address in byte form
446 * @return int ip address value
alshabibc4901cd2014-09-05 16:50:40 -0700447 */
448 public static int toIPv4Address(final byte[] ipAddress) {
449 int ip = 0;
450 for (int i = 0; i < 4; i++) {
451 final int t = (ipAddress[i] & 0xff) << (3 - i) * 8;
452 ip |= t;
453 }
454 return ip;
455 }
456
457 /**
458 * Accepts an IPv4 address and returns of string of the form xxx.xxx.xxx.xxx,
459 * e.g., 192.168.0.1.
460 *
tom5f18cf32014-09-13 14:10:57 -0700461 * @param ipAddress ip address in form
462 * @return string form of ip address
alshabibc4901cd2014-09-05 16:50:40 -0700463 */
464 public static String fromIPv4Address(final int ipAddress) {
Yuta HIGUCHI2dce08a2017-04-20 21:57:48 -0700465 final StringBuilder sb = new StringBuilder();
alshabibc4901cd2014-09-05 16:50:40 -0700466 int result = 0;
467 for (int i = 0; i < 4; ++i) {
468 result = ipAddress >> (3 - i) * 8 & 0xff;
Yuta HIGUCHIe5ca93b2014-10-23 09:49:00 -0700469 sb.append(result);
alshabib638dc712014-09-05 18:03:45 -0700470 if (i != 3) {
471 sb.append(".");
472 }
alshabibc4901cd2014-09-05 16:50:40 -0700473 }
474 return sb.toString();
475 }
476
477 /**
478 * Accepts a collection of IPv4 addresses as integers and returns a single
479 * String useful in toString method's containing collections of IP
480 * addresses.
481 *
482 * @param ipAddresses
483 * collection
tom5f18cf32014-09-13 14:10:57 -0700484 * @return ip addresses in comma-separated string form
alshabibc4901cd2014-09-05 16:50:40 -0700485 */
486 public static String fromIPv4AddressCollection(
487 final Collection<Integer> ipAddresses) {
488 if (ipAddresses == null) {
489 return "null";
490 }
Yuta HIGUCHI2dce08a2017-04-20 21:57:48 -0700491 final StringBuilder sb = new StringBuilder();
alshabibc4901cd2014-09-05 16:50:40 -0700492 sb.append("[");
493 for (final Integer ip : ipAddresses) {
494 sb.append(IPv4.fromIPv4Address(ip));
495 sb.append(",");
496 }
497 sb.replace(sb.length() - 1, sb.length(), "]");
498 return sb.toString();
499 }
500
501 /**
502 * Accepts an IPv4 address of the form xxx.xxx.xxx.xxx, ie 192.168.0.1 and
503 * returns the corresponding byte array.
504 *
505 * @param ipAddress
506 * The IP address in the form xx.xxx.xxx.xxx.
507 * @return The IP address separated into bytes
508 */
509 public static byte[] toIPv4AddressBytes(final String ipAddress) {
510 final String[] octets = ipAddress.split("\\.");
511 if (octets.length != 4) {
512 throw new IllegalArgumentException("Specified IPv4 address must"
513 + "contain 4 sets of numerical digits separated by periods");
514 }
515
516 final byte[] result = new byte[4];
517 for (int i = 0; i < 4; ++i) {
518 result[i] = Integer.valueOf(octets[i]).byteValue();
519 }
520 return result;
521 }
522
523 /**
524 * Accepts an IPv4 address in the form of an integer and returns the
525 * corresponding byte array.
526 *
527 * @param ipAddress
528 * The IP address as an integer.
529 * @return The IP address separated into bytes.
530 */
531 public static byte[] toIPv4AddressBytes(final int ipAddress) {
532 return new byte[] {(byte) (ipAddress >>> 24),
533 (byte) (ipAddress >>> 16), (byte) (ipAddress >>> 8),
534 (byte) ipAddress};
535 }
536
537 /*
538 * (non-Javadoc)
539 *
540 * @see java.lang.Object#hashCode()
541 */
542 @Override
543 public int hashCode() {
544 final int prime = 2521;
545 int result = super.hashCode();
546 result = prime * result + this.checksum;
547 result = prime * result + this.destinationAddress;
548 result = prime * result + this.diffServ;
549 result = prime * result + this.flags;
550 result = prime * result + this.fragmentOffset;
551 result = prime * result + this.headerLength;
552 result = prime * result + this.identification;
553 result = prime * result + Arrays.hashCode(this.options);
554 result = prime * result + this.protocol;
555 result = prime * result + this.sourceAddress;
556 result = prime * result + this.totalLength;
557 result = prime * result + this.ttl;
558 result = prime * result + this.version;
559 return result;
560 }
561
562 /*
563 * (non-Javadoc)
564 *
565 * @see java.lang.Object#equals(java.lang.Object)
566 */
567 @Override
568 public boolean equals(final Object obj) {
569 if (this == obj) {
570 return true;
571 }
572 if (!super.equals(obj)) {
573 return false;
574 }
575 if (!(obj instanceof IPv4)) {
576 return false;
577 }
578 final IPv4 other = (IPv4) obj;
579 if (this.checksum != other.checksum) {
580 return false;
581 }
582 if (this.destinationAddress != other.destinationAddress) {
583 return false;
584 }
585 if (this.diffServ != other.diffServ) {
586 return false;
587 }
588 if (this.flags != other.flags) {
589 return false;
590 }
591 if (this.fragmentOffset != other.fragmentOffset) {
592 return false;
593 }
594 if (this.headerLength != other.headerLength) {
595 return false;
596 }
597 if (this.identification != other.identification) {
598 return false;
599 }
600 if (!Arrays.equals(this.options, other.options)) {
601 return false;
602 }
603 if (this.protocol != other.protocol) {
604 return false;
605 }
606 if (this.sourceAddress != other.sourceAddress) {
607 return false;
608 }
609 if (this.totalLength != other.totalLength) {
610 return false;
611 }
612 if (this.ttl != other.ttl) {
613 return false;
614 }
615 if (this.version != other.version) {
616 return false;
617 }
618 return true;
619 }
Jonathan Hart2a655752015-04-07 16:46:33 -0700620
621 /**
622 * Deserializer function for IPv4 packets.
623 *
624 * @return deserializer function
625 */
626 public static Deserializer<IPv4> deserializer() {
627 return (data, offset, length) -> {
628 checkInput(data, offset, length, HEADER_LENGTH);
629
630 IPv4 ipv4 = new IPv4();
631
632 final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
633
634 byte versionByte = bb.get();
635 ipv4.headerLength = (byte) (versionByte & 0xf);
636 ipv4.setVersion((byte) (versionByte >> 4 & 0xf));
637 ipv4.setDiffServ(bb.get());
638 ipv4.totalLength = bb.getShort();
639 ipv4.identification = bb.getShort();
640 short flagsFragment = bb.getShort();
641 ipv4.flags = (byte) (flagsFragment >> 13 & 0x7);
642 ipv4.fragmentOffset = (short) (flagsFragment & 0x1fff);
643 ipv4.ttl = bb.get();
644 ipv4.protocol = bb.get();
645 ipv4.checksum = bb.getShort();
646 ipv4.sourceAddress = bb.getInt();
647 ipv4.destinationAddress = bb.getInt();
648
649 if (ipv4.headerLength > 5) {
650 checkHeaderLength(length, ipv4.headerLength * 4);
651
652 int optionsLength = (ipv4.headerLength - 5) * 4;
653 ipv4.options = new byte[optionsLength];
654 bb.get(ipv4.options);
655 }
656
657 Deserializer<? extends IPacket> deserializer;
658 if (IPv4.PROTOCOL_DESERIALIZER_MAP.containsKey(ipv4.protocol)) {
659 deserializer = IPv4.PROTOCOL_DESERIALIZER_MAP.get(ipv4.protocol);
660 } else {
661 deserializer = Data.deserializer();
662 }
Charles Chan89c4a642017-04-13 17:43:52 -0700663
664 int remainingLength = bb.limit() - bb.position();
665 int payloadLength = ipv4.totalLength - ipv4.headerLength * 4;
666 int bytesToRead = (payloadLength <= remainingLength) ?
667 payloadLength : remainingLength;
668 ipv4.payload = deserializer.deserialize(data, bb.position(), bytesToRead);
Jonathan Hart2a655752015-04-07 16:46:33 -0700669 ipv4.payload.setParent(ipv4);
670
671 if (ipv4.totalLength != length) {
672 ipv4.isTruncated = true;
673 } else {
674 ipv4.isTruncated = false;
675 }
676
677 return ipv4;
678 };
679 }
Jian Li5fc14292015-12-04 11:30:46 -0800680
681 @Override
682 public String toString() {
683 return toStringHelper(getClass())
684 .add("version", Byte.toString(version))
685 .add("headerLength", Byte.toString(headerLength))
686 .add("diffServ", Byte.toString(diffServ))
687 .add("totalLength", Short.toString(totalLength))
688 .add("identification", Short.toString(identification))
689 .add("flags", Byte.toString(flags))
690 .add("fragmentOffset", Short.toString(fragmentOffset))
691 .add("ttl", Byte.toString(ttl))
692 .add("protocol", Byte.toString(protocol))
693 .add("checksum", Short.toString(checksum))
694 .add("sourceAddress", Integer.toString(sourceAddress))
695 .add("destinationAddress", Integer.toString(destinationAddress))
696 .add("options", Arrays.toString(options))
697 .add("isTruncated", Boolean.toString(isTruncated))
698 .toString();
699 }
alshabibc4901cd2014-09-05 16:50:40 -0700700}