IPv4 extends BasePacket { @Override public IPacket deserialize(byte[] data, int offset, int length) throws PacketParsingException { ByteBuffer bb = ByteBuffer.wrap(data, offset, length); short sscratch; this.version = bb.get(); this.headerLength = (byte) (this.version & 0xf); this.version = (byte) ((this.version >> 4) & 0xf); if (this.version != 4) { throw new PacketParsingException( "Invalid version for IPv4 packet: " + this.version); } this.diffServ = bb.get(); this.totalLength = bb.getShort(); this.identification = bb.getShort(); sscratch = bb.getShort(); this.flags = (byte) ((sscratch >> IPV4_FLAGS_SHIFT) & IPV4_FLAGS_MASK); this.fragmentOffset = (short) (sscratch & IPV4_OFFSET_MASK); this.ttl = bb.get(); this.protocol = IpProtocol.of(U8.f(bb.get())); this.checksum = bb.getShort(); this.sourceAddress = IPv4Address.of(bb.getInt()); this.destinationAddress = IPv4Address.of(bb.getInt()); if (this.headerLength > 5) { int optionsLength = (this.headerLength - 5) * 4; this.options = new byte[optionsLength]; bb.get(this.options); } IPacket payload; isFragment = ((this.flags & IPV4_FLAGS_DONTFRAG) == 0) && ((this.flags & IPV4_FLAGS_MOREFRAG) != 0 || this.fragmentOffset != 0); if (!isFragment && IPv4.protocolClassMap.containsKey(this.protocol)) { Class<? extends IPacket> clazz = IPv4.protocolClassMap.get(this.protocol); try { payload = clazz.newInstance(); } catch (Exception e) { throw new RuntimeException("Error parsing payload for IPv4 packet", e); } } else { if (log.isTraceEnabled() && isFragment) { log.trace("IPv4 fragment detected {}->{}, forward using IP header only", this.sourceAddress.toString(), this.destinationAddress.toString()); } payload = new Data(); } int payloadLength = this.totalLength - this.headerLength * 4; int remLength = bb.limit()-bb.position(); if (remLength < payloadLength) payloadLength = bb.limit()-bb.position(); this.payload = payload.deserialize(data, bb.position(), payloadLength); this.payload.setParent(this); if (this.totalLength > length) this.isTruncated = true; else this.isTruncated = false; return this; } IPv4(); byte getVersion(); IPv4 setVersion(byte version); byte getHeaderLength(); byte getDiffServ(); IPv4 setDiffServ(byte diffServ); short getTotalLength(); short getIdentification(); boolean isTruncated(); void setTruncated(boolean isTruncated); boolean isFragment(); void setFragment(boolean isFrag); IPv4 setIdentification(short identification); byte getFlags(); IPv4 setFlags(byte flags); short getFragmentOffset(); IPv4 setFragmentOffset(short fragmentOffset); byte getTtl(); IPv4 setTtl(byte ttl); IpProtocol getProtocol(); IPv4 setProtocol(IpProtocol protocol); short getChecksum(); IPv4 setChecksum(short checksum); @Override void resetChecksum(); IPv4Address getSourceAddress(); IPv4 setSourceAddress(IPv4Address sourceAddress); IPv4 setSourceAddress(int sourceAddress); IPv4 setSourceAddress(String sourceAddress); IPv4Address getDestinationAddress(); IPv4 setDestinationAddress(IPv4Address destinationAddress); IPv4 setDestinationAddress(int destinationAddress); IPv4 setDestinationAddress(String destinationAddress); byte[] getOptions(); IPv4 setOptions(byte[] options); @Override byte[] serialize(); @Override IPacket deserialize(byte[] data, int offset, int length); static int toIPv4Address(String ipAddress); static int toIPv4Address(byte[] ipAddress); static String fromIPv4Address(int ipAddress); static String fromIPv4AddressCollection(Collection<Integer> ipAddresses); static byte[] toIPv4AddressBytes(String ipAddress); static byte[] toIPv4AddressBytes(int ipAddress); @Override int hashCode(); @Override boolean equals(Object obj); static Map<IpProtocol, Class<? extends IPacket>> protocolClassMap; static final byte IPV4_FLAGS_MOREFRAG; static final byte IPV4_FLAGS_DONTFRAG; static final byte IPV4_FLAGS_MASK; static final byte IPV4_FLAGS_SHIFT; static final short IPV4_OFFSET_MASK; }
@Test public void testDeserialize() throws Exception { IPv4 packet = new IPv4(); packet.deserialize(pktSerialized, 0, pktSerialized.length); byte[] pktSerialized1 = packet.serialize(); assertTrue(Arrays.equals(pktSerialized, pktSerialized1)); }