Merge changes I62771a8f,I5edf0ffb
* changes: PacketBuilderTest: add IPv6 TCP test PacketBuilder: add IPv6 support
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
package com.android.net.module.util;
|
package com.android.net.module.util;
|
||||||
|
|
||||||
import static android.system.OsConstants.IPPROTO_IP;
|
import static android.system.OsConstants.IPPROTO_IP;
|
||||||
|
import static android.system.OsConstants.IPPROTO_IPV6;
|
||||||
import static android.system.OsConstants.IPPROTO_TCP;
|
import static android.system.OsConstants.IPPROTO_TCP;
|
||||||
import static android.system.OsConstants.IPPROTO_UDP;
|
import static android.system.OsConstants.IPPROTO_UDP;
|
||||||
|
|
||||||
@@ -25,6 +26,7 @@ import static com.android.net.module.util.IpUtils.tcpChecksum;
|
|||||||
import static com.android.net.module.util.IpUtils.udpChecksum;
|
import static com.android.net.module.util.IpUtils.udpChecksum;
|
||||||
import static com.android.net.module.util.NetworkStackConstants.IPV4_CHECKSUM_OFFSET;
|
import static com.android.net.module.util.NetworkStackConstants.IPV4_CHECKSUM_OFFSET;
|
||||||
import static com.android.net.module.util.NetworkStackConstants.IPV4_LENGTH_OFFSET;
|
import static com.android.net.module.util.NetworkStackConstants.IPV4_LENGTH_OFFSET;
|
||||||
|
import static com.android.net.module.util.NetworkStackConstants.IPV6_LEN_OFFSET;
|
||||||
import static com.android.net.module.util.NetworkStackConstants.TCP_CHECKSUM_OFFSET;
|
import static com.android.net.module.util.NetworkStackConstants.TCP_CHECKSUM_OFFSET;
|
||||||
import static com.android.net.module.util.NetworkStackConstants.UDP_CHECKSUM_OFFSET;
|
import static com.android.net.module.util.NetworkStackConstants.UDP_CHECKSUM_OFFSET;
|
||||||
import static com.android.net.module.util.NetworkStackConstants.UDP_LENGTH_OFFSET;
|
import static com.android.net.module.util.NetworkStackConstants.UDP_LENGTH_OFFSET;
|
||||||
@@ -35,11 +37,13 @@ import androidx.annotation.NonNull;
|
|||||||
|
|
||||||
import com.android.net.module.util.structs.EthernetHeader;
|
import com.android.net.module.util.structs.EthernetHeader;
|
||||||
import com.android.net.module.util.structs.Ipv4Header;
|
import com.android.net.module.util.structs.Ipv4Header;
|
||||||
|
import com.android.net.module.util.structs.Ipv6Header;
|
||||||
import com.android.net.module.util.structs.TcpHeader;
|
import com.android.net.module.util.structs.TcpHeader;
|
||||||
import com.android.net.module.util.structs.UdpHeader;
|
import com.android.net.module.util.structs.UdpHeader;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.Inet4Address;
|
import java.net.Inet4Address;
|
||||||
|
import java.net.Inet6Address;
|
||||||
import java.nio.BufferOverflowException;
|
import java.nio.BufferOverflowException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
@@ -49,7 +53,7 @@ import java.nio.ByteBuffer;
|
|||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
* | Layer 2 header (EthernetHeader) | (optional)
|
* | Layer 2 header (EthernetHeader) | (optional)
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
* | Layer 3 header (Ipv4Header) |
|
* | Layer 3 header (Ipv4Header, Ipv6Header) |
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
* | Layer 4 header (TcpHeader, UdpHeader) |
|
* | Layer 4 header (TcpHeader, UdpHeader) |
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
@@ -74,11 +78,14 @@ import java.nio.ByteBuffer;
|
|||||||
* sendPacket(buf);
|
* sendPacket(buf);
|
||||||
*/
|
*/
|
||||||
public class PacketBuilder {
|
public class PacketBuilder {
|
||||||
|
private static final int INVALID_OFFSET = -1;
|
||||||
|
|
||||||
private final ByteBuffer mBuffer;
|
private final ByteBuffer mBuffer;
|
||||||
|
|
||||||
private int mIpv4HeaderOffset = -1;
|
private int mIpv4HeaderOffset = INVALID_OFFSET;
|
||||||
private int mTcpHeaderOffset = -1;
|
private int mIpv6HeaderOffset = INVALID_OFFSET;
|
||||||
private int mUdpHeaderOffset = -1;
|
private int mTcpHeaderOffset = INVALID_OFFSET;
|
||||||
|
private int mUdpHeaderOffset = INVALID_OFFSET;
|
||||||
|
|
||||||
public PacketBuilder(@NonNull ByteBuffer buffer) {
|
public PacketBuilder(@NonNull ByteBuffer buffer) {
|
||||||
mBuffer = buffer;
|
mBuffer = buffer;
|
||||||
@@ -129,6 +136,31 @@ public class PacketBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write an IPv6 header.
|
||||||
|
* The IP header length is calculated and written back in #finalizePacket.
|
||||||
|
*
|
||||||
|
* @param vtf version, traffic class and flow label
|
||||||
|
* @param nextHeader the transport layer protocol
|
||||||
|
* @param hopLimit hop limit
|
||||||
|
* @param srcIp source IP address
|
||||||
|
* @param dstIp destination IP address
|
||||||
|
*/
|
||||||
|
public void writeIpv6Header(int vtf, byte nextHeader, short hopLimit,
|
||||||
|
@NonNull final Inet6Address srcIp, @NonNull final Inet6Address dstIp)
|
||||||
|
throws IOException {
|
||||||
|
mIpv6HeaderOffset = mBuffer.position();
|
||||||
|
final Ipv6Header ipv6Header = new Ipv6Header(vtf,
|
||||||
|
(short) 0 /* payloadLength, calculate in #finalizePacket */, nextHeader,
|
||||||
|
hopLimit, srcIp, dstIp);
|
||||||
|
|
||||||
|
try {
|
||||||
|
ipv6Header.writeToByteBuffer(mBuffer);
|
||||||
|
} catch (IllegalArgumentException | BufferOverflowException e) {
|
||||||
|
throw new IOException("Error writing to buffer: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a TCP header.
|
* Write a TCP header.
|
||||||
* The TCP header checksum is calculated and written back in #finalizePacket.
|
* The TCP header checksum is calculated and written back in #finalizePacket.
|
||||||
@@ -186,10 +218,10 @@ public class PacketBuilder {
|
|||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public ByteBuffer finalizePacket() throws IOException {
|
public ByteBuffer finalizePacket() throws IOException {
|
||||||
if (mIpv4HeaderOffset < 0) {
|
// Finalize IPv4 or IPv6 header.
|
||||||
// TODO: add support for IPv6
|
int ipHeaderOffset = INVALID_OFFSET;
|
||||||
throw new IOException("Packet is missing IPv4 header");
|
if (mIpv4HeaderOffset != INVALID_OFFSET) {
|
||||||
}
|
ipHeaderOffset = mIpv4HeaderOffset;
|
||||||
|
|
||||||
// Populate the IPv4 totalLength field.
|
// Populate the IPv4 totalLength field.
|
||||||
mBuffer.putShort(mIpv4HeaderOffset + IPV4_LENGTH_OFFSET,
|
mBuffer.putShort(mIpv4HeaderOffset + IPV4_LENGTH_OFFSET,
|
||||||
@@ -198,20 +230,30 @@ public class PacketBuilder {
|
|||||||
// Populate the IPv4 header checksum field.
|
// Populate the IPv4 header checksum field.
|
||||||
mBuffer.putShort(mIpv4HeaderOffset + IPV4_CHECKSUM_OFFSET,
|
mBuffer.putShort(mIpv4HeaderOffset + IPV4_CHECKSUM_OFFSET,
|
||||||
ipChecksum(mBuffer, mIpv4HeaderOffset /* headerOffset */));
|
ipChecksum(mBuffer, mIpv4HeaderOffset /* headerOffset */));
|
||||||
|
} else if (mIpv6HeaderOffset != INVALID_OFFSET) {
|
||||||
|
ipHeaderOffset = mIpv6HeaderOffset;
|
||||||
|
|
||||||
if (mTcpHeaderOffset > 0) {
|
// Populate the IPv6 payloadLength field.
|
||||||
|
mBuffer.putShort(mIpv6HeaderOffset + IPV6_LEN_OFFSET,
|
||||||
|
(short) (mBuffer.position() - mIpv6HeaderOffset));
|
||||||
|
} else {
|
||||||
|
throw new IOException("Packet is missing neither IPv4 nor IPv6 header");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finalize TCP or UDP header.
|
||||||
|
if (mTcpHeaderOffset != INVALID_OFFSET) {
|
||||||
// Populate the TCP header checksum field.
|
// Populate the TCP header checksum field.
|
||||||
mBuffer.putShort(mTcpHeaderOffset + TCP_CHECKSUM_OFFSET, tcpChecksum(mBuffer,
|
mBuffer.putShort(mTcpHeaderOffset + TCP_CHECKSUM_OFFSET, tcpChecksum(mBuffer,
|
||||||
mIpv4HeaderOffset /* ipOffset */, mTcpHeaderOffset /* transportOffset */,
|
ipHeaderOffset /* ipOffset */, mTcpHeaderOffset /* transportOffset */,
|
||||||
mBuffer.position() - mTcpHeaderOffset /* transportLen */));
|
mBuffer.position() - mTcpHeaderOffset /* transportLen */));
|
||||||
} else if (mUdpHeaderOffset > 0) {
|
} else if (mUdpHeaderOffset != INVALID_OFFSET) {
|
||||||
// Populate the UDP header length field.
|
// Populate the UDP header length field.
|
||||||
mBuffer.putShort(mUdpHeaderOffset + UDP_LENGTH_OFFSET,
|
mBuffer.putShort(mUdpHeaderOffset + UDP_LENGTH_OFFSET,
|
||||||
(short) (mBuffer.position() - mUdpHeaderOffset));
|
(short) (mBuffer.position() - mUdpHeaderOffset));
|
||||||
|
|
||||||
// Populate the UDP header checksum field.
|
// Populate the UDP header checksum field.
|
||||||
mBuffer.putShort(mUdpHeaderOffset + UDP_CHECKSUM_OFFSET, udpChecksum(mBuffer,
|
mBuffer.putShort(mUdpHeaderOffset + UDP_CHECKSUM_OFFSET, udpChecksum(mBuffer,
|
||||||
mIpv4HeaderOffset /* ipOffset */, mUdpHeaderOffset /* transportOffset */));
|
ipHeaderOffset /* ipOffset */, mUdpHeaderOffset /* transportOffset */));
|
||||||
} else {
|
} else {
|
||||||
throw new IOException("Packet is missing neither TCP nor UDP header");
|
throw new IOException("Packet is missing neither TCP nor UDP header");
|
||||||
}
|
}
|
||||||
@@ -225,15 +267,15 @@ public class PacketBuilder {
|
|||||||
*
|
*
|
||||||
* @param hasEther has ethernet header. Set this flag to indicate that the packet has an
|
* @param hasEther has ethernet header. Set this flag to indicate that the packet has an
|
||||||
* ethernet header.
|
* ethernet header.
|
||||||
* @param l3proto the layer 3 protocol. Only {@code IPPROTO_IP} currently supported.
|
* @param l3proto the layer 3 protocol. Only {@code IPPROTO_IP} and {@code IPPROTO_IPV6}
|
||||||
|
* currently supported.
|
||||||
* @param l4proto the layer 4 protocol. Only {@code IPPROTO_TCP} and {@code IPPROTO_UDP}
|
* @param l4proto the layer 4 protocol. Only {@code IPPROTO_TCP} and {@code IPPROTO_UDP}
|
||||||
* currently supported.
|
* currently supported.
|
||||||
* @param payloadLen length of the payload.
|
* @param payloadLen length of the payload.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public static ByteBuffer allocate(boolean hasEther, int l3proto, int l4proto, int payloadLen) {
|
public static ByteBuffer allocate(boolean hasEther, int l3proto, int l4proto, int payloadLen) {
|
||||||
if (l3proto != IPPROTO_IP) {
|
if (l3proto != IPPROTO_IP && l3proto != IPPROTO_IPV6) {
|
||||||
// TODO: add support for IPv6
|
|
||||||
throw new IllegalArgumentException("Unsupported layer 3 protocol " + l3proto);
|
throw new IllegalArgumentException("Unsupported layer 3 protocol " + l3proto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +289,8 @@ public class PacketBuilder {
|
|||||||
|
|
||||||
int packetLen = 0;
|
int packetLen = 0;
|
||||||
if (hasEther) packetLen += Struct.getSize(EthernetHeader.class);
|
if (hasEther) packetLen += Struct.getSize(EthernetHeader.class);
|
||||||
packetLen += Struct.getSize(Ipv4Header.class);
|
packetLen += (l3proto == IPPROTO_IP) ? Struct.getSize(Ipv4Header.class)
|
||||||
|
: Struct.getSize(Ipv6Header.class);
|
||||||
packetLen += (l4proto == IPPROTO_TCP) ? Struct.getSize(TcpHeader.class)
|
packetLen += (l4proto == IPPROTO_TCP) ? Struct.getSize(TcpHeader.class)
|
||||||
: Struct.getSize(UdpHeader.class);
|
: Struct.getSize(UdpHeader.class);
|
||||||
packetLen += payloadLen;
|
packetLen += payloadLen;
|
||||||
|
|||||||
@@ -17,11 +17,14 @@
|
|||||||
package com.android.net.module.util;
|
package com.android.net.module.util;
|
||||||
|
|
||||||
import static android.system.OsConstants.IPPROTO_IP;
|
import static android.system.OsConstants.IPPROTO_IP;
|
||||||
|
import static android.system.OsConstants.IPPROTO_IPV6;
|
||||||
import static android.system.OsConstants.IPPROTO_TCP;
|
import static android.system.OsConstants.IPPROTO_TCP;
|
||||||
import static android.system.OsConstants.IPPROTO_UDP;
|
import static android.system.OsConstants.IPPROTO_UDP;
|
||||||
|
|
||||||
import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV4;
|
import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV4;
|
||||||
|
import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV6;
|
||||||
import static com.android.net.module.util.NetworkStackConstants.IPV4_HEADER_MIN_LEN;
|
import static com.android.net.module.util.NetworkStackConstants.IPV4_HEADER_MIN_LEN;
|
||||||
|
import static com.android.net.module.util.NetworkStackConstants.IPV6_HEADER_LEN;
|
||||||
import static com.android.net.module.util.NetworkStackConstants.TCPHDR_ACK;
|
import static com.android.net.module.util.NetworkStackConstants.TCPHDR_ACK;
|
||||||
import static com.android.net.module.util.NetworkStackConstants.TCP_HEADER_MIN_LEN;
|
import static com.android.net.module.util.NetworkStackConstants.TCP_HEADER_MIN_LEN;
|
||||||
import static com.android.net.module.util.NetworkStackConstants.UDP_HEADER_LEN;
|
import static com.android.net.module.util.NetworkStackConstants.UDP_HEADER_LEN;
|
||||||
@@ -41,6 +44,7 @@ import androidx.test.runner.AndroidJUnit4;
|
|||||||
|
|
||||||
import com.android.net.module.util.structs.EthernetHeader;
|
import com.android.net.module.util.structs.EthernetHeader;
|
||||||
import com.android.net.module.util.structs.Ipv4Header;
|
import com.android.net.module.util.structs.Ipv4Header;
|
||||||
|
import com.android.net.module.util.structs.Ipv6Header;
|
||||||
import com.android.net.module.util.structs.TcpHeader;
|
import com.android.net.module.util.structs.TcpHeader;
|
||||||
import com.android.net.module.util.structs.UdpHeader;
|
import com.android.net.module.util.structs.UdpHeader;
|
||||||
|
|
||||||
@@ -49,6 +53,7 @@ import org.junit.runner.RunWith;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.Inet4Address;
|
import java.net.Inet4Address;
|
||||||
|
import java.net.Inet6Address;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@@ -56,8 +61,10 @@ import java.nio.ByteBuffer;
|
|||||||
public class PacketBuilderTest {
|
public class PacketBuilderTest {
|
||||||
private static final MacAddress SRC_MAC = MacAddress.fromString("11:22:33:44:55:66");
|
private static final MacAddress SRC_MAC = MacAddress.fromString("11:22:33:44:55:66");
|
||||||
private static final MacAddress DST_MAC = MacAddress.fromString("aa:bb:cc:dd:ee:ff");
|
private static final MacAddress DST_MAC = MacAddress.fromString("aa:bb:cc:dd:ee:ff");
|
||||||
private static final Inet4Address IPV4_SRC_ADDR = addr("192.0.2.1");
|
private static final Inet4Address IPV4_SRC_ADDR = addr4("192.0.2.1");
|
||||||
private static final Inet4Address IPV4_DST_ADDR = addr("198.51.100.1");
|
private static final Inet4Address IPV4_DST_ADDR = addr4("198.51.100.1");
|
||||||
|
private static final Inet6Address IPV6_SRC_ADDR = addr6("2001:db8::1");
|
||||||
|
private static final Inet6Address IPV6_DST_ADDR = addr6("2001:db8::2");
|
||||||
private static final short SRC_PORT = 9876;
|
private static final short SRC_PORT = 9876;
|
||||||
private static final short DST_PORT = 433;
|
private static final short DST_PORT = 433;
|
||||||
private static final short SEQ_NO = 13579;
|
private static final short SEQ_NO = 13579;
|
||||||
@@ -68,6 +75,9 @@ public class PacketBuilderTest {
|
|||||||
private static final byte TIME_TO_LIVE = (byte) 0x40;
|
private static final byte TIME_TO_LIVE = (byte) 0x40;
|
||||||
private static final short WINDOW = (short) 0x2000;
|
private static final short WINDOW = (short) 0x2000;
|
||||||
private static final short URGENT_POINTER = 0;
|
private static final short URGENT_POINTER = 0;
|
||||||
|
// version=6, traffic class=0x80, flowlabel=0x515ca;
|
||||||
|
private static final int VERSION_TRAFFICCLASS_FLOWLABEL = 0x680515ca;
|
||||||
|
private static final short HOP_LIMIT = 0x40;
|
||||||
private static final ByteBuffer DATA = ByteBuffer.wrap(new byte[] {
|
private static final ByteBuffer DATA = ByteBuffer.wrap(new byte[] {
|
||||||
(byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef
|
(byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef
|
||||||
});
|
});
|
||||||
@@ -256,15 +266,247 @@ public class PacketBuilderTest {
|
|||||||
(byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef
|
(byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static final byte[] TEST_PACKET_ETHERHDR_IPV6HDR_UDPHDR =
|
||||||
|
new byte[] {
|
||||||
|
// packet = (scapy.Ether(src="11:22:33:44:55:66", dst="aa:bb:cc:dd:ee:ff",
|
||||||
|
// type='IPv6') /
|
||||||
|
// scapy.IPv6(src="2001:db8::1", dst="2001:db8::2", tc=0x80,
|
||||||
|
// fl=0x515ca, plen=48, hlim=0x40) /
|
||||||
|
// scapy.UDP(sport=9876, dport=433))
|
||||||
|
// Note that plen(48) = ipv6hdr(40) + udphdr(8).
|
||||||
|
// Ether header
|
||||||
|
(byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd,
|
||||||
|
(byte) 0xee, (byte) 0xff, (byte) 0x11, (byte) 0x22,
|
||||||
|
(byte) 0x33, (byte) 0x44, (byte) 0x55, (byte) 0x66,
|
||||||
|
(byte) 0x86, (byte) 0xdd,
|
||||||
|
// IP header
|
||||||
|
(byte) 0x68, (byte) 0x05, (byte) 0x15, (byte) 0xca,
|
||||||
|
(byte) 0x00, (byte) 0x30, (byte) 0x11, (byte) 0x40,
|
||||||
|
(byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01,
|
||||||
|
(byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02,
|
||||||
|
// UDP header
|
||||||
|
(byte) 0x26, (byte) 0x94, (byte) 0x01, (byte) 0xb1,
|
||||||
|
(byte) 0x00, (byte) 0x08, (byte) 0x7c, (byte) 0x24
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final byte[] TEST_PACKET_ETHERHDR_IPV6HDR_UDPHDR_DATA =
|
||||||
|
new byte[] {
|
||||||
|
// packet = (scapy.Ether(src="11:22:33:44:55:66", dst="aa:bb:cc:dd:ee:ff",
|
||||||
|
// type='IPv6') /
|
||||||
|
// scapy.IPv6(src="2001:db8::1", dst="2001:db8::2", tc=0x80,
|
||||||
|
// fl=0x515ca, plen=52, hlim=0x40) /
|
||||||
|
// scapy.UDP(sport=9876, dport=433) /
|
||||||
|
// b'\xde\xad\xbe\xef')
|
||||||
|
// Note that plen(52) = ipv6hdr(40) + udphdr(8) + data(4).
|
||||||
|
// Ether header
|
||||||
|
(byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd,
|
||||||
|
(byte) 0xee, (byte) 0xff, (byte) 0x11, (byte) 0x22,
|
||||||
|
(byte) 0x33, (byte) 0x44, (byte) 0x55, (byte) 0x66,
|
||||||
|
(byte) 0x86, (byte) 0xdd,
|
||||||
|
// IP header
|
||||||
|
(byte) 0x68, (byte) 0x05, (byte) 0x15, (byte) 0xca,
|
||||||
|
(byte) 0x00, (byte) 0x34, (byte) 0x11, (byte) 0x40,
|
||||||
|
(byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01,
|
||||||
|
(byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02,
|
||||||
|
// UDP header
|
||||||
|
(byte) 0x26, (byte) 0x94, (byte) 0x01, (byte) 0xb1,
|
||||||
|
(byte) 0x00, (byte) 0x0c, (byte) 0xde, (byte) 0x7e,
|
||||||
|
// Data
|
||||||
|
(byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final byte[] TEST_PACKET_ETHERHDR_IPV6HDR_TCPHDR_DATA =
|
||||||
|
new byte[] {
|
||||||
|
// packet = (scapy.Ether(src="11:22:33:44:55:66", dst="aa:bb:cc:dd:ee:ff",
|
||||||
|
// type='IPv6') /
|
||||||
|
// scapy.IPv6(src="2001:db8::1", dst="2001:db8::2", tc=0x80,
|
||||||
|
// fl=0x515ca, plen=64, hlim=0x40) /
|
||||||
|
// scapy.TCP(sport=9876, dport=433, seq=13579, ack=24680,
|
||||||
|
// flags='A', window=8192, urgptr=0) /
|
||||||
|
// b'\xde\xad\xbe\xef')
|
||||||
|
// Note that plen(64) = ipv6hdr(40) + udphdr(20) + data(4).
|
||||||
|
// Ether header
|
||||||
|
(byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd,
|
||||||
|
(byte) 0xee, (byte) 0xff, (byte) 0x11, (byte) 0x22,
|
||||||
|
(byte) 0x33, (byte) 0x44, (byte) 0x55, (byte) 0x66,
|
||||||
|
(byte) 0x86, (byte) 0xdd,
|
||||||
|
// IPv6 header
|
||||||
|
(byte) 0x68, (byte) 0x05, (byte) 0x15, (byte) 0xca,
|
||||||
|
(byte) 0x00, (byte) 0x40, (byte) 0x06, (byte) 0x40,
|
||||||
|
(byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01,
|
||||||
|
(byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02,
|
||||||
|
// TCP header
|
||||||
|
(byte) 0x26, (byte) 0x94, (byte) 0x01, (byte) 0xb1,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x35, (byte) 0x0b,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x60, (byte) 0x68,
|
||||||
|
(byte) 0x50, (byte) 0x10, (byte) 0x20, (byte) 0x00,
|
||||||
|
(byte) 0xd9, (byte) 0x05, (byte) 0x00, (byte) 0x00,
|
||||||
|
// Data
|
||||||
|
(byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final byte[] TEST_PACKET_ETHERHDR_IPV6HDR_TCPHDR =
|
||||||
|
new byte[] {
|
||||||
|
// packet = (scapy.Ether(src="11:22:33:44:55:66", dst="aa:bb:cc:dd:ee:ff",
|
||||||
|
// type='IPv6') /
|
||||||
|
// scapy.IPv6(src="2001:db8::1", dst="2001:db8::2", tc=0x80,
|
||||||
|
// fl=0x515ca, plen=60, hlim=0x40) /
|
||||||
|
// scapy.TCP(sport=9876, dport=433, seq=13579, ack=24680,
|
||||||
|
// flags='A', window=8192, urgptr=0))
|
||||||
|
// Note that plen(60) = ipv6hdr(40) + udphdr(20).
|
||||||
|
// Ether header
|
||||||
|
(byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd,
|
||||||
|
(byte) 0xee, (byte) 0xff, (byte) 0x11, (byte) 0x22,
|
||||||
|
(byte) 0x33, (byte) 0x44, (byte) 0x55, (byte) 0x66,
|
||||||
|
(byte) 0x86, (byte) 0xdd,
|
||||||
|
// IPv6 header
|
||||||
|
(byte) 0x68, (byte) 0x05, (byte) 0x15, (byte) 0xca,
|
||||||
|
(byte) 0x00, (byte) 0x3c, (byte) 0x06, (byte) 0x40,
|
||||||
|
(byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01,
|
||||||
|
(byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02,
|
||||||
|
// TCP header
|
||||||
|
(byte) 0x26, (byte) 0x94, (byte) 0x01, (byte) 0xb1,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x35, (byte) 0x0b,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x60, (byte) 0x68,
|
||||||
|
(byte) 0x50, (byte) 0x10, (byte) 0x20, (byte) 0x00,
|
||||||
|
(byte) 0x76, (byte) 0xa7, (byte) 0x00, (byte) 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final byte[] TEST_PACKET_IPV6HDR_TCPHDR_DATA =
|
||||||
|
new byte[] {
|
||||||
|
// packet = (scapy.IPv6(src="2001:db8::1", dst="2001:db8::2", tc=0x80,
|
||||||
|
// fl=0x515ca, plen=64, hlim=0x40) /
|
||||||
|
// scapy.TCP(sport=9876, dport=433, seq=13579, ack=24680,
|
||||||
|
// flags='A', window=8192, urgptr=0) /
|
||||||
|
// b'\xde\xad\xbe\xef')
|
||||||
|
// Note that plen(64) = ipv6hdr(40) + udphdr(20) + data(4).
|
||||||
|
// IPv6 header
|
||||||
|
(byte) 0x68, (byte) 0x05, (byte) 0x15, (byte) 0xca,
|
||||||
|
(byte) 0x00, (byte) 0x40, (byte) 0x06, (byte) 0x40,
|
||||||
|
(byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01,
|
||||||
|
(byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02,
|
||||||
|
// TCP header
|
||||||
|
(byte) 0x26, (byte) 0x94, (byte) 0x01, (byte) 0xb1,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x35, (byte) 0x0b,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x60, (byte) 0x68,
|
||||||
|
(byte) 0x50, (byte) 0x10, (byte) 0x20, (byte) 0x00,
|
||||||
|
(byte) 0xd9, (byte) 0x05, (byte) 0x00, (byte) 0x00,
|
||||||
|
// Data
|
||||||
|
(byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final byte[] TEST_PACKET_IPV6HDR_TCPHDR =
|
||||||
|
new byte[] {
|
||||||
|
// packet = (scapy.IPv6(src="2001:db8::1", dst="2001:db8::2", tc=0x80,
|
||||||
|
// fl=0x515ca, plen=60, hlim=0x40) /
|
||||||
|
// scapy.TCP(sport=9876, dport=433, seq=13579, ack=24680,
|
||||||
|
// flags='A', window=8192, urgptr=0))
|
||||||
|
// Note that plen(60) = ipv6hdr(40) + udphdr(20).
|
||||||
|
// IPv6 header
|
||||||
|
(byte) 0x68, (byte) 0x05, (byte) 0x15, (byte) 0xca,
|
||||||
|
(byte) 0x00, (byte) 0x3c, (byte) 0x06, (byte) 0x40,
|
||||||
|
(byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01,
|
||||||
|
(byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02,
|
||||||
|
// TCP header
|
||||||
|
(byte) 0x26, (byte) 0x94, (byte) 0x01, (byte) 0xb1,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x35, (byte) 0x0b,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x60, (byte) 0x68,
|
||||||
|
(byte) 0x50, (byte) 0x10, (byte) 0x20, (byte) 0x00,
|
||||||
|
(byte) 0x76, (byte) 0xa7, (byte) 0x00, (byte) 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final byte[] TEST_PACKET_IPV6HDR_UDPHDR =
|
||||||
|
new byte[] {
|
||||||
|
// packet = (scapy.IPv6(src="2001:db8::1", dst="2001:db8::2", tc=0x80,
|
||||||
|
// fl=0x515ca, plen=48, hlim=0x40) /
|
||||||
|
// scapy.UDP(sport=9876, dport=433))
|
||||||
|
// Note that plen(48) = ipv6hdr(40) + udphdr(8).
|
||||||
|
// IP header
|
||||||
|
(byte) 0x68, (byte) 0x05, (byte) 0x15, (byte) 0xca,
|
||||||
|
(byte) 0x00, (byte) 0x30, (byte) 0x11, (byte) 0x40,
|
||||||
|
(byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01,
|
||||||
|
(byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02,
|
||||||
|
// UDP header
|
||||||
|
(byte) 0x26, (byte) 0x94, (byte) 0x01, (byte) 0xb1,
|
||||||
|
(byte) 0x00, (byte) 0x08, (byte) 0x7c, (byte) 0x24
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final byte[] TEST_PACKET_IPV6HDR_UDPHDR_DATA =
|
||||||
|
new byte[] {
|
||||||
|
// packet = (scapy.IPv6(src="2001:db8::1", dst="2001:db8::2", tc=0x80,
|
||||||
|
// fl=0x515ca, plen=52, hlim=0x40) /
|
||||||
|
// scapy.UDP(sport=9876, dport=433) /
|
||||||
|
// b'\xde\xad\xbe\xef')
|
||||||
|
// Note that plen(52) = ipv6hdr(40) + udphdr(8) + data(4).
|
||||||
|
// IP header
|
||||||
|
(byte) 0x68, (byte) 0x05, (byte) 0x15, (byte) 0xca,
|
||||||
|
(byte) 0x00, (byte) 0x34, (byte) 0x11, (byte) 0x40,
|
||||||
|
(byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01,
|
||||||
|
(byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02,
|
||||||
|
// UDP header
|
||||||
|
(byte) 0x26, (byte) 0x94, (byte) 0x01, (byte) 0xb1,
|
||||||
|
(byte) 0x00, (byte) 0x0c, (byte) 0xde, (byte) 0x7e,
|
||||||
|
// Data
|
||||||
|
(byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build an IPv4 packet which has ether header, IPv4 header, TCP/UDP header and data.
|
* Build a packet which has ether header, IP header, TCP/UDP header and data.
|
||||||
* The ethernet header and data are optional. Note that both source mac address and
|
* The ethernet header and data are optional. Note that both source mac address and
|
||||||
* destination mac address are required for ethernet header.
|
* destination mac address are required for ethernet header.
|
||||||
*
|
*
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
* | Layer 2 header (EthernetHeader) | (optional)
|
* | Layer 2 header (EthernetHeader) | (optional)
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
* | Layer 3 header (Ipv4Header) |
|
* | Layer 3 header (Ipv4Header, Ipv6Header) |
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
* | Layer 4 header (TcpHeader, UdpHeader) |
|
* | Layer 4 header (TcpHeader, UdpHeader) |
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
@@ -273,33 +515,55 @@ public class PacketBuilderTest {
|
|||||||
*
|
*
|
||||||
* @param srcMac source MAC address. used by L2 ether header.
|
* @param srcMac source MAC address. used by L2 ether header.
|
||||||
* @param dstMac destination MAC address. used by L2 ether header.
|
* @param dstMac destination MAC address. used by L2 ether header.
|
||||||
* @param l4proto the layer 4 protocol. support either IPPROTO_TCP or IPPROTO_UDP.
|
* @param l3proto the layer 3 protocol. Only {@code IPPROTO_IP} and {@code IPPROTO_IPV6}
|
||||||
|
* currently supported.
|
||||||
|
* @param l4proto the layer 4 protocol. Only {@code IPPROTO_TCP} and {@code IPPROTO_UDP}
|
||||||
|
* currently supported.
|
||||||
* @param payload the payload.
|
* @param payload the payload.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
private ByteBuffer buildIpv4Packet(@Nullable final MacAddress srcMac,
|
private ByteBuffer buildPacket(@Nullable final MacAddress srcMac,
|
||||||
@Nullable final MacAddress dstMac, final int l4proto,
|
@Nullable final MacAddress dstMac, final int l3proto, final int l4proto,
|
||||||
@Nullable final ByteBuffer payload)
|
@Nullable final ByteBuffer payload)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
if (l3proto != IPPROTO_IP && l3proto != IPPROTO_IPV6) {
|
||||||
|
fail("Unsupported layer 3 protocol " + l3proto);
|
||||||
|
}
|
||||||
|
|
||||||
if (l4proto != IPPROTO_TCP && l4proto != IPPROTO_UDP) {
|
if (l4proto != IPPROTO_TCP && l4proto != IPPROTO_UDP) {
|
||||||
fail("Unsupported layer 4 protocol " + l4proto);
|
fail("Unsupported layer 4 protocol " + l4proto);
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean hasEther = (srcMac != null && dstMac != null);
|
final boolean hasEther = (srcMac != null && dstMac != null);
|
||||||
final int payloadLen = (payload == null) ? 0 : payload.limit();
|
final int payloadLen = (payload == null) ? 0 : payload.limit();
|
||||||
final ByteBuffer buffer = PacketBuilder.allocate(hasEther, IPPROTO_IP, l4proto,
|
final ByteBuffer buffer = PacketBuilder.allocate(hasEther, l3proto, l4proto,
|
||||||
payloadLen);
|
payloadLen);
|
||||||
final PacketBuilder packetBuilder = new PacketBuilder(buffer);
|
final PacketBuilder packetBuilder = new PacketBuilder(buffer);
|
||||||
|
|
||||||
if (hasEther) packetBuilder.writeL2Header(srcMac, dstMac, (short) ETHER_TYPE_IPV4);
|
// [1] Build ether header.
|
||||||
|
if (hasEther) {
|
||||||
|
final int etherType = (l3proto == IPPROTO_IP) ? ETHER_TYPE_IPV4 : ETHER_TYPE_IPV6;
|
||||||
|
packetBuilder.writeL2Header(srcMac, dstMac, (short) etherType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// [2] Build IP header.
|
||||||
|
if (l3proto == IPPROTO_IP) {
|
||||||
packetBuilder.writeIpv4Header(TYPE_OF_SERVICE, ID, FLAGS_AND_FRAGMENT_OFFSET,
|
packetBuilder.writeIpv4Header(TYPE_OF_SERVICE, ID, FLAGS_AND_FRAGMENT_OFFSET,
|
||||||
TIME_TO_LIVE, (byte) l4proto, IPV4_SRC_ADDR, IPV4_DST_ADDR);
|
TIME_TO_LIVE, (byte) l4proto, IPV4_SRC_ADDR, IPV4_DST_ADDR);
|
||||||
|
} else if (l3proto == IPPROTO_IPV6) {
|
||||||
|
packetBuilder.writeIpv6Header(VERSION_TRAFFICCLASS_FLOWLABEL,
|
||||||
|
(byte) l4proto, HOP_LIMIT, IPV6_SRC_ADDR, IPV6_DST_ADDR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// [3] Build TCP or UDP header.
|
||||||
if (l4proto == IPPROTO_TCP) {
|
if (l4proto == IPPROTO_TCP) {
|
||||||
packetBuilder.writeTcpHeader(SRC_PORT, DST_PORT, SEQ_NO, ACK_NO,
|
packetBuilder.writeTcpHeader(SRC_PORT, DST_PORT, SEQ_NO, ACK_NO,
|
||||||
TCPHDR_ACK, WINDOW, URGENT_POINTER);
|
TCPHDR_ACK, WINDOW, URGENT_POINTER);
|
||||||
} else if (l4proto == IPPROTO_UDP) {
|
} else if (l4proto == IPPROTO_UDP) {
|
||||||
packetBuilder.writeUdpHeader(SRC_PORT, DST_PORT);
|
packetBuilder.writeUdpHeader(SRC_PORT, DST_PORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [4] Build payload.
|
||||||
if (payload != null) {
|
if (payload != null) {
|
||||||
buffer.put(payload);
|
buffer.put(payload);
|
||||||
// in case data might be reused by caller, restore the position and
|
// in case data might be reused by caller, restore the position and
|
||||||
@@ -313,19 +577,27 @@ public class PacketBuilderTest {
|
|||||||
/**
|
/**
|
||||||
* Check ethernet header.
|
* Check ethernet header.
|
||||||
*
|
*
|
||||||
|
* @param l3proto the layer 3 protocol. Only {@code IPPROTO_IP} and {@code IPPROTO_IPV6}
|
||||||
|
* currently supported.
|
||||||
* @param actual the packet to check.
|
* @param actual the packet to check.
|
||||||
*/
|
*/
|
||||||
private void checkEtherHeader(final ByteBuffer actual) {
|
private void checkEtherHeader(final int l3proto, final ByteBuffer actual) {
|
||||||
|
if (l3proto != IPPROTO_IP && l3proto != IPPROTO_IPV6) {
|
||||||
|
fail("Unsupported layer 3 protocol " + l3proto);
|
||||||
|
}
|
||||||
|
|
||||||
final EthernetHeader eth = Struct.parse(EthernetHeader.class, actual);
|
final EthernetHeader eth = Struct.parse(EthernetHeader.class, actual);
|
||||||
assertEquals(SRC_MAC, eth.srcMac);
|
assertEquals(SRC_MAC, eth.srcMac);
|
||||||
assertEquals(DST_MAC, eth.dstMac);
|
assertEquals(DST_MAC, eth.dstMac);
|
||||||
assertEquals(ETHER_TYPE_IPV4, eth.etherType);
|
final int expectedEtherType = (l3proto == IPPROTO_IP) ? ETHER_TYPE_IPV4 : ETHER_TYPE_IPV6;
|
||||||
|
assertEquals(expectedEtherType, eth.etherType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check IPv4 header.
|
* Check IPv4 header.
|
||||||
*
|
*
|
||||||
* @param l4proto the layer 4 protocol. support either IPPROTO_TCP or IPPROTO_UDP.
|
* @param l4proto the layer 4 protocol. Only {@code IPPROTO_TCP} and {@code IPPROTO_UDP}
|
||||||
|
* currently supported.
|
||||||
* @param hasData true if the packet has data payload; false otherwise.
|
* @param hasData true if the packet has data payload; false otherwise.
|
||||||
* @param actual the packet to check.
|
* @param actual the packet to check.
|
||||||
*/
|
*/
|
||||||
@@ -359,19 +631,66 @@ public class PacketBuilderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check TCPv4 packet.
|
* Check IPv6 header.
|
||||||
*
|
*
|
||||||
* @param hasEther true if the packet has ether header; false otherwise.
|
* @param l4proto the layer 4 protocol. Only {@code IPPROTO_TCP} and {@code IPPROTO_UDP}
|
||||||
|
* currently supported.
|
||||||
* @param hasData true if the packet has data payload; false otherwise.
|
* @param hasData true if the packet has data payload; false otherwise.
|
||||||
* @param actual the packet to check.
|
* @param actual the packet to check.
|
||||||
*/
|
*/
|
||||||
private void checkTcpv4Packet(final boolean hasEther, final boolean hasData,
|
private void checkIpv6Header(final int l4proto, final boolean hasData,
|
||||||
final ByteBuffer actual) {
|
final ByteBuffer actual) {
|
||||||
if (hasEther) {
|
if (l4proto != IPPROTO_TCP && l4proto != IPPROTO_UDP) {
|
||||||
checkEtherHeader(actual);
|
fail("Unsupported layer 4 protocol " + l4proto);
|
||||||
}
|
}
|
||||||
checkIpv4Header(IPPROTO_TCP, hasData, actual);
|
|
||||||
|
|
||||||
|
final Ipv6Header ipv6Header = Struct.parse(Ipv6Header.class, actual);
|
||||||
|
|
||||||
|
assertEquals(VERSION_TRAFFICCLASS_FLOWLABEL, ipv6Header.vtf);
|
||||||
|
assertEquals(HOP_LIMIT, ipv6Header.hopLimit);
|
||||||
|
assertEquals(IPV6_SRC_ADDR, ipv6Header.srcIp);
|
||||||
|
assertEquals(IPV6_DST_ADDR, ipv6Header.dstIp);
|
||||||
|
|
||||||
|
final int dataLength = hasData ? DATA.limit() : 0;
|
||||||
|
if (l4proto == IPPROTO_TCP) {
|
||||||
|
assertEquals(IPV6_HEADER_LEN + TCP_HEADER_MIN_LEN + dataLength,
|
||||||
|
ipv6Header.payloadLength);
|
||||||
|
assertEquals((byte) IPPROTO_TCP, ipv6Header.nextHeader);
|
||||||
|
} else if (l4proto == IPPROTO_UDP) {
|
||||||
|
assertEquals(IPV6_HEADER_LEN + UDP_HEADER_LEN + dataLength,
|
||||||
|
ipv6Header.payloadLength);
|
||||||
|
assertEquals((byte) IPPROTO_UDP, ipv6Header.nextHeader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check TCP packet.
|
||||||
|
*
|
||||||
|
* @param hasEther true if the packet has ether header; false otherwise.
|
||||||
|
* @param l3proto the layer 3 protocol. Only {@code IPPROTO_IP} and {@code IPPROTO_IPV6}
|
||||||
|
* currently supported.
|
||||||
|
* @param hasData true if the packet has data payload; false otherwise.
|
||||||
|
* @param actual the packet to check.
|
||||||
|
*/
|
||||||
|
private void checkTcpPacket(final boolean hasEther, final int l3proto, final boolean hasData,
|
||||||
|
final ByteBuffer actual) {
|
||||||
|
if (l3proto != IPPROTO_IP && l3proto != IPPROTO_IPV6) {
|
||||||
|
fail("Unsupported layer 3 protocol " + l3proto);
|
||||||
|
}
|
||||||
|
|
||||||
|
// [1] Check ether header.
|
||||||
|
if (hasEther) {
|
||||||
|
checkEtherHeader(l3proto, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
// [2] Check IP header.
|
||||||
|
if (l3proto == IPPROTO_IP) {
|
||||||
|
checkIpv4Header(IPPROTO_TCP, hasData, actual);
|
||||||
|
} else if (l3proto == IPPROTO_IPV6) {
|
||||||
|
checkIpv6Header(IPPROTO_TCP, hasData, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
// [3] Check TCP header.
|
||||||
final TcpHeader tcpHeader = Struct.parse(TcpHeader.class, actual);
|
final TcpHeader tcpHeader = Struct.parse(TcpHeader.class, actual);
|
||||||
assertEquals(SRC_PORT, tcpHeader.srcPort);
|
assertEquals(SRC_PORT, tcpHeader.srcPort);
|
||||||
assertEquals(DST_PORT, tcpHeader.dstPort);
|
assertEquals(DST_PORT, tcpHeader.dstPort);
|
||||||
@@ -380,35 +699,59 @@ public class PacketBuilderTest {
|
|||||||
assertEquals((short) 0x5010 /* offset=5(*4bytes), control bits=ACK */,
|
assertEquals((short) 0x5010 /* offset=5(*4bytes), control bits=ACK */,
|
||||||
tcpHeader.dataOffsetAndControlBits);
|
tcpHeader.dataOffsetAndControlBits);
|
||||||
assertEquals(WINDOW, tcpHeader.window);
|
assertEquals(WINDOW, tcpHeader.window);
|
||||||
assertEquals(hasData ? (short) 0x4844 : (short) 0xe5e5, tcpHeader.checksum);
|
|
||||||
assertEquals(URGENT_POINTER, tcpHeader.urgentPointer);
|
assertEquals(URGENT_POINTER, tcpHeader.urgentPointer);
|
||||||
|
if (l3proto == IPPROTO_IP) {
|
||||||
|
assertEquals(hasData ? (short) 0x4844 : (short) 0xe5e5, tcpHeader.checksum);
|
||||||
|
} else if (l3proto == IPPROTO_IPV6) {
|
||||||
|
assertEquals(hasData ? (short) 0xd905 : (short) 0x76a7, tcpHeader.checksum);
|
||||||
|
}
|
||||||
|
|
||||||
|
// [4] Check payload.
|
||||||
if (hasData) {
|
if (hasData) {
|
||||||
assertEquals(0xdeadbeef, actual.getInt());
|
assertEquals(0xdeadbeef, actual.getInt());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check UDPv4 packet.
|
* Check UDP packet.
|
||||||
*
|
*
|
||||||
* @param hasEther true if the packet has ether header; false otherwise.
|
* @param hasEther true if the packet has ether header; false otherwise.
|
||||||
|
* @param l3proto the layer 3 protocol. Only {@code IPPROTO_IP} and {@code IPPROTO_IPV6}
|
||||||
|
* currently supported.
|
||||||
* @param hasData true if the packet has data payload; false otherwise.
|
* @param hasData true if the packet has data payload; false otherwise.
|
||||||
* @param actual the packet to check.
|
* @param actual the packet to check.
|
||||||
*/
|
*/
|
||||||
private void checkUdpv4Packet(final boolean hasEther, final boolean hasData,
|
private void checkUdpPacket(final boolean hasEther, final int l3proto, final boolean hasData,
|
||||||
final ByteBuffer actual) {
|
final ByteBuffer actual) {
|
||||||
if (hasEther) {
|
if (l3proto != IPPROTO_IP && l3proto != IPPROTO_IPV6) {
|
||||||
checkEtherHeader(actual);
|
fail("Unsupported layer 3 protocol " + l3proto);
|
||||||
}
|
}
|
||||||
checkIpv4Header(IPPROTO_UDP, hasData, actual);
|
|
||||||
|
|
||||||
|
// [1] Check ether header.
|
||||||
|
if (hasEther) {
|
||||||
|
checkEtherHeader(l3proto, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
// [2] Check IP header.
|
||||||
|
if (l3proto == IPPROTO_IP) {
|
||||||
|
checkIpv4Header(IPPROTO_UDP, hasData, actual);
|
||||||
|
} else if (l3proto == IPPROTO_IPV6) {
|
||||||
|
checkIpv6Header(IPPROTO_UDP, hasData, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
// [3] Check UDP header.
|
||||||
final UdpHeader udpHeader = Struct.parse(UdpHeader.class, actual);
|
final UdpHeader udpHeader = Struct.parse(UdpHeader.class, actual);
|
||||||
assertEquals(SRC_PORT, udpHeader.srcPort);
|
assertEquals(SRC_PORT, udpHeader.srcPort);
|
||||||
assertEquals(DST_PORT, udpHeader.dstPort);
|
assertEquals(DST_PORT, udpHeader.dstPort);
|
||||||
final int dataLength = hasData ? DATA.limit() : 0;
|
final int dataLength = hasData ? DATA.limit() : 0;
|
||||||
assertEquals(UDP_HEADER_LEN + dataLength, udpHeader.length);
|
assertEquals(UDP_HEADER_LEN + dataLength, udpHeader.length);
|
||||||
|
if (l3proto == IPPROTO_IP) {
|
||||||
assertEquals(hasData ? (short) 0x4dbd : (short) 0xeb62, udpHeader.checksum);
|
assertEquals(hasData ? (short) 0x4dbd : (short) 0xeb62, udpHeader.checksum);
|
||||||
|
} else if (l3proto == IPPROTO_IPV6) {
|
||||||
|
assertEquals(hasData ? (short) 0xde7e : (short) 0x7c24, udpHeader.checksum);
|
||||||
|
}
|
||||||
|
|
||||||
|
// [4] Check payload.
|
||||||
if (hasData) {
|
if (hasData) {
|
||||||
assertEquals(0xdeadbeef, actual.getInt());
|
assertEquals(0xdeadbeef, actual.getInt());
|
||||||
}
|
}
|
||||||
@@ -416,65 +759,132 @@ public class PacketBuilderTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuildPacketEtherIPv4Tcp() throws Exception {
|
public void testBuildPacketEtherIPv4Tcp() throws Exception {
|
||||||
final ByteBuffer packet = buildIpv4Packet(SRC_MAC, DST_MAC, IPPROTO_TCP, null /* data */);
|
final ByteBuffer packet = buildPacket(SRC_MAC, DST_MAC, IPPROTO_IP, IPPROTO_TCP,
|
||||||
checkTcpv4Packet(true /* hasEther */, false /* hasData */, packet);
|
null /* data */);
|
||||||
|
checkTcpPacket(true /* hasEther */, IPPROTO_IP, false /* hasData */, packet);
|
||||||
assertArrayEquals(TEST_PACKET_ETHERHDR_IPV4HDR_TCPHDR, packet.array());
|
assertArrayEquals(TEST_PACKET_ETHERHDR_IPV4HDR_TCPHDR, packet.array());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuildPacketEtherIPv4TcpData() throws Exception {
|
public void testBuildPacketEtherIPv4TcpData() throws Exception {
|
||||||
final ByteBuffer packet = buildIpv4Packet(SRC_MAC, DST_MAC, IPPROTO_TCP, DATA);
|
final ByteBuffer packet = buildPacket(SRC_MAC, DST_MAC, IPPROTO_IP, IPPROTO_TCP, DATA);
|
||||||
checkTcpv4Packet(true /* hasEther */, true /* hasData */, packet);
|
checkTcpPacket(true /* hasEther */, IPPROTO_IP, true /* hasData */, packet);
|
||||||
assertArrayEquals(TEST_PACKET_ETHERHDR_IPV4HDR_TCPHDR_DATA,
|
assertArrayEquals(TEST_PACKET_ETHERHDR_IPV4HDR_TCPHDR_DATA,
|
||||||
packet.array());
|
packet.array());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuildPacketIPv4Tcp() throws Exception {
|
public void testBuildPacketIPv4Tcp() throws Exception {
|
||||||
final ByteBuffer packet = buildIpv4Packet(null /* srcMac */, null /* dstMac */,
|
final ByteBuffer packet = buildPacket(null /* srcMac */, null /* dstMac */,
|
||||||
IPPROTO_TCP, null /* data */);
|
IPPROTO_IP, IPPROTO_TCP, null /* data */);
|
||||||
checkTcpv4Packet(false /* hasEther */, false /* hasData */, packet);
|
checkTcpPacket(false /* hasEther */, IPPROTO_IP, false /* hasData */, packet);
|
||||||
assertArrayEquals(TEST_PACKET_IPV4HDR_TCPHDR, packet.array());
|
assertArrayEquals(TEST_PACKET_IPV4HDR_TCPHDR, packet.array());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuildPacketIPv4TcpData() throws Exception {
|
public void testBuildPacketIPv4TcpData() throws Exception {
|
||||||
final ByteBuffer packet = buildIpv4Packet(null /* srcMac */, null /* dstMac */,
|
final ByteBuffer packet = buildPacket(null /* srcMac */, null /* dstMac */,
|
||||||
IPPROTO_TCP, DATA);
|
IPPROTO_IP, IPPROTO_TCP, DATA);
|
||||||
checkTcpv4Packet(false /* hasEther */, true /* hasData */, packet);
|
checkTcpPacket(false /* hasEther */, IPPROTO_IP, true /* hasData */, packet);
|
||||||
assertArrayEquals(TEST_PACKET_IPV4HDR_TCPHDR_DATA, packet.array());
|
assertArrayEquals(TEST_PACKET_IPV4HDR_TCPHDR_DATA, packet.array());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuildPacketEtherIPv4Udp() throws Exception {
|
public void testBuildPacketEtherIPv4Udp() throws Exception {
|
||||||
final ByteBuffer packet = buildIpv4Packet(SRC_MAC, DST_MAC, IPPROTO_UDP, null /* data */);
|
final ByteBuffer packet = buildPacket(SRC_MAC, DST_MAC, IPPROTO_IP, IPPROTO_UDP,
|
||||||
checkUdpv4Packet(true /* hasEther */, false /* hasData */, packet);
|
null /* data */);
|
||||||
|
checkUdpPacket(true /* hasEther */, IPPROTO_IP, false /* hasData */, packet);
|
||||||
assertArrayEquals(TEST_PACKET_ETHERHDR_IPV4HDR_UDPHDR, packet.array());
|
assertArrayEquals(TEST_PACKET_ETHERHDR_IPV4HDR_UDPHDR, packet.array());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuildPacketEtherIPv4UdpData() throws Exception {
|
public void testBuildPacketEtherIPv4UdpData() throws Exception {
|
||||||
final ByteBuffer packet = buildIpv4Packet(SRC_MAC, DST_MAC, IPPROTO_UDP, DATA);
|
final ByteBuffer packet = buildPacket(SRC_MAC, DST_MAC, IPPROTO_IP, IPPROTO_UDP, DATA);
|
||||||
checkUdpv4Packet(true /* hasEther */, true /* hasData */, packet);
|
checkUdpPacket(true /* hasEther */, IPPROTO_IP, true /* hasData */, packet);
|
||||||
assertArrayEquals(TEST_PACKET_ETHERHDR_IPV4HDR_UDPHDR_DATA, packet.array());
|
assertArrayEquals(TEST_PACKET_ETHERHDR_IPV4HDR_UDPHDR_DATA, packet.array());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuildPacketIPv4Udp() throws Exception {
|
public void testBuildPacketIPv4Udp() throws Exception {
|
||||||
final ByteBuffer packet = buildIpv4Packet(null /* srcMac */, null /* dstMac */,
|
final ByteBuffer packet = buildPacket(null /* srcMac */, null /* dstMac */,
|
||||||
IPPROTO_UDP, null /*data*/);
|
IPPROTO_IP, IPPROTO_UDP, null /*data*/);
|
||||||
checkUdpv4Packet(false /* hasEther */, false /* hasData */, packet);
|
checkUdpPacket(false /* hasEther */, IPPROTO_IP, false /* hasData */, packet);
|
||||||
assertArrayEquals(TEST_PACKET_IPV4HDR_UDPHDR, packet.array());
|
assertArrayEquals(TEST_PACKET_IPV4HDR_UDPHDR, packet.array());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuildPacketIPv4UdpData() throws Exception {
|
public void testBuildPacketIPv4UdpData() throws Exception {
|
||||||
final ByteBuffer packet = buildIpv4Packet(null /* srcMac */, null /* dstMac */,
|
final ByteBuffer packet = buildPacket(null /* srcMac */, null /* dstMac */,
|
||||||
IPPROTO_UDP, DATA);
|
IPPROTO_IP, IPPROTO_UDP, DATA);
|
||||||
checkUdpv4Packet(false /* hasEther */, true /* hasData */, packet);
|
checkUdpPacket(false /* hasEther */, IPPROTO_IP, true /* hasData */, packet);
|
||||||
assertArrayEquals(TEST_PACKET_IPV4HDR_UDPHDR_DATA, packet.array());
|
assertArrayEquals(TEST_PACKET_IPV4HDR_UDPHDR_DATA, packet.array());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuildPacketEtherIPv6TcpData() throws Exception {
|
||||||
|
final ByteBuffer packet = buildPacket(SRC_MAC, DST_MAC, IPPROTO_IPV6, IPPROTO_TCP, DATA);
|
||||||
|
checkTcpPacket(true /* hasEther */, IPPROTO_IPV6, true /* hasData */, packet);
|
||||||
|
assertArrayEquals(TEST_PACKET_ETHERHDR_IPV6HDR_TCPHDR_DATA,
|
||||||
|
packet.array());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuildPacketEtherIPv6Tcp() throws Exception {
|
||||||
|
final ByteBuffer packet = buildPacket(SRC_MAC, DST_MAC, IPPROTO_IPV6, IPPROTO_TCP,
|
||||||
|
null /*data*/);
|
||||||
|
checkTcpPacket(true /* hasEther */, IPPROTO_IPV6, false /* hasData */, packet);
|
||||||
|
assertArrayEquals(TEST_PACKET_ETHERHDR_IPV6HDR_TCPHDR,
|
||||||
|
packet.array());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuildPacketIPv6TcpData() throws Exception {
|
||||||
|
final ByteBuffer packet = buildPacket(null /* srcMac */, null /* dstMac */, IPPROTO_IPV6,
|
||||||
|
IPPROTO_TCP, DATA);
|
||||||
|
checkTcpPacket(false /* hasEther */, IPPROTO_IPV6, true /* hasData */, packet);
|
||||||
|
assertArrayEquals(TEST_PACKET_IPV6HDR_TCPHDR_DATA, packet.array());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuildPacketIPv6Tcp() throws Exception {
|
||||||
|
final ByteBuffer packet = buildPacket(null /* srcMac */, null /* dstMac */, IPPROTO_IPV6,
|
||||||
|
IPPROTO_TCP, null /*data*/);
|
||||||
|
checkTcpPacket(false /* hasEther */, IPPROTO_IPV6, false /* hasData */, packet);
|
||||||
|
assertArrayEquals(TEST_PACKET_IPV6HDR_TCPHDR, packet.array());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuildPacketEtherIPv6Udp() throws Exception {
|
||||||
|
final ByteBuffer packet = buildPacket(SRC_MAC, DST_MAC, IPPROTO_IPV6, IPPROTO_UDP,
|
||||||
|
null /* data */);
|
||||||
|
checkUdpPacket(true /* hasEther */, IPPROTO_IPV6, false /* hasData */, packet);
|
||||||
|
assertArrayEquals(TEST_PACKET_ETHERHDR_IPV6HDR_UDPHDR, packet.array());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuildPacketEtherIPv6UdpData() throws Exception {
|
||||||
|
final ByteBuffer packet = buildPacket(SRC_MAC, DST_MAC, IPPROTO_IPV6, IPPROTO_UDP,
|
||||||
|
DATA);
|
||||||
|
checkUdpPacket(true /* hasEther */, IPPROTO_IPV6, true /* hasData */, packet);
|
||||||
|
assertArrayEquals(TEST_PACKET_ETHERHDR_IPV6HDR_UDPHDR_DATA, packet.array());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuildPacketIPv6Udp() throws Exception {
|
||||||
|
final ByteBuffer packet = buildPacket(null /* srcMac */, null /* dstMac */,
|
||||||
|
IPPROTO_IPV6, IPPROTO_UDP, null /*data*/);
|
||||||
|
checkUdpPacket(false /* hasEther */, IPPROTO_IPV6, false /* hasData */, packet);
|
||||||
|
assertArrayEquals(TEST_PACKET_IPV6HDR_UDPHDR, packet.array());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuildPacketIPv6UdpData() throws Exception {
|
||||||
|
final ByteBuffer packet = buildPacket(null /* srcMac */, null /* dstMac */,
|
||||||
|
IPPROTO_IPV6, IPPROTO_UDP, DATA);
|
||||||
|
checkUdpPacket(false /* hasEther */, IPPROTO_IPV6, true /* hasData */, packet);
|
||||||
|
assertArrayEquals(TEST_PACKET_IPV6HDR_UDPHDR_DATA, packet.array());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFinalizePacketWithoutIpv4Header() throws Exception {
|
public void testFinalizePacketWithoutIpv4Header() throws Exception {
|
||||||
final ByteBuffer buffer = PacketBuilder.allocate(false /* hasEther */, IPPROTO_IP,
|
final ByteBuffer buffer = PacketBuilder.allocate(false /* hasEther */, IPPROTO_IP,
|
||||||
@@ -526,7 +936,11 @@ public class PacketBuilderTest {
|
|||||||
assertThrows(IOException.class, () -> packetBuilder.writeUdpHeader(SRC_PORT, DST_PORT));
|
assertThrows(IOException.class, () -> packetBuilder.writeUdpHeader(SRC_PORT, DST_PORT));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Inet4Address addr(String addr) {
|
private static Inet4Address addr4(String addr) {
|
||||||
return (Inet4Address) InetAddresses.parseNumericAddress(addr);
|
return (Inet4Address) InetAddresses.parseNumericAddress(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Inet6Address addr6(String addr) {
|
||||||
|
return (Inet6Address) InetAddresses.parseNumericAddress(addr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user