Merge "Add integration test to verify the incomplete IPv6 neighbors." into main
diff --git a/Android.bp b/Android.bp
index 5d5202a..d4008aa 100644
--- a/Android.bp
+++ b/Android.bp
@@ -414,7 +414,7 @@
name: "ApfGeneratorLib",
defaults: ["NetworkStackReleaseApiLevel"],
srcs: [
- "src/android/net/apf/ApfConstant.java",
+ "src/android/net/apf/ApfConstants.java",
"src/android/net/apf/ApfCounterTracker.java",
"src/android/net/apf/ApfV4Generator.java",
"src/android/net/apf/ApfV4GeneratorBase.java",
diff --git a/src/android/net/apf/ApfConstant.java b/src/android/net/apf/ApfConstants.java
similarity index 98%
rename from src/android/net/apf/ApfConstant.java
rename to src/android/net/apf/ApfConstants.java
index 68580be..f5f083e 100644
--- a/src/android/net/apf/ApfConstant.java
+++ b/src/android/net/apf/ApfConstants.java
@@ -18,9 +18,9 @@
/**
* The class which declares constants used in ApfFilter and unit tests.
*/
-public final class ApfConstant {
+public final class ApfConstants {
- private ApfConstant() {}
+ private ApfConstants() {}
public static final int ETH_HEADER_LEN = 14;
public static final int ETH_DEST_ADDR_OFFSET = 0;
public static final int ETH_ETHERTYPE_OFFSET = 12;
diff --git a/src/android/net/apf/ApfFilter.java b/src/android/net/apf/ApfFilter.java
index 6679793..ef77db6 100644
--- a/src/android/net/apf/ApfFilter.java
+++ b/src/android/net/apf/ApfFilter.java
@@ -16,47 +16,47 @@
package android.net.apf;
-import static android.net.apf.ApfConstant.APF_MAX_ETH_TYPE_BLACK_LIST_LEN;
-import static android.net.apf.ApfConstant.ARP_HEADER_OFFSET;
-import static android.net.apf.ApfConstant.ARP_IPV4_HEADER;
-import static android.net.apf.ApfConstant.ARP_OPCODE_OFFSET;
-import static android.net.apf.ApfConstant.ARP_OPCODE_REPLY;
-import static android.net.apf.ApfConstant.ARP_OPCODE_REQUEST;
-import static android.net.apf.ApfConstant.ARP_SOURCE_IP_ADDRESS_OFFSET;
-import static android.net.apf.ApfConstant.ARP_TARGET_IP_ADDRESS_OFFSET;
-import static android.net.apf.ApfConstant.DHCP_CLIENT_MAC_OFFSET;
-import static android.net.apf.ApfConstant.DHCP_CLIENT_PORT;
-import static android.net.apf.ApfConstant.ECHO_PORT;
-import static android.net.apf.ApfConstant.ETH_DEST_ADDR_OFFSET;
-import static android.net.apf.ApfConstant.ETH_ETHERTYPE_OFFSET;
-import static android.net.apf.ApfConstant.ETH_HEADER_LEN;
-import static android.net.apf.ApfConstant.ETH_MULTICAST_MDNS_V4_MAC_ADDRESS;
-import static android.net.apf.ApfConstant.ETH_MULTICAST_MDNS_V6_MAC_ADDRESS;
-import static android.net.apf.ApfConstant.ETH_TYPE_MAX;
-import static android.net.apf.ApfConstant.ETH_TYPE_MIN;
-import static android.net.apf.ApfConstant.FIXED_ARP_REPLY_HEADER;
-import static android.net.apf.ApfConstant.ICMP6_TYPE_OFFSET;
-import static android.net.apf.ApfConstant.IPPROTO_HOPOPTS;
-import static android.net.apf.ApfConstant.IPV4_ANY_HOST_ADDRESS;
-import static android.net.apf.ApfConstant.IPV4_BROADCAST_ADDRESS;
-import static android.net.apf.ApfConstant.IPV4_DEST_ADDR_OFFSET;
-import static android.net.apf.ApfConstant.IPV4_FRAGMENT_MORE_FRAGS_MASK;
-import static android.net.apf.ApfConstant.IPV4_FRAGMENT_OFFSET_MASK;
-import static android.net.apf.ApfConstant.IPV4_FRAGMENT_OFFSET_OFFSET;
-import static android.net.apf.ApfConstant.IPV4_PROTOCOL_OFFSET;
-import static android.net.apf.ApfConstant.IPV4_TOTAL_LENGTH_OFFSET;
-import static android.net.apf.ApfConstant.IPV6_ALL_NODES_ADDRESS;
-import static android.net.apf.ApfConstant.IPV6_DEST_ADDR_OFFSET;
-import static android.net.apf.ApfConstant.IPV6_FLOW_LABEL_LEN;
-import static android.net.apf.ApfConstant.IPV6_FLOW_LABEL_OFFSET;
-import static android.net.apf.ApfConstant.IPV6_HEADER_LEN;
-import static android.net.apf.ApfConstant.IPV6_NEXT_HEADER_OFFSET;
-import static android.net.apf.ApfConstant.IPV6_SRC_ADDR_OFFSET;
-import static android.net.apf.ApfConstant.MDNS_PORT;
-import static android.net.apf.ApfConstant.MDNS_QDCOUNT_OFFSET;
-import static android.net.apf.ApfConstant.MDNS_QNAME_OFFSET;
-import static android.net.apf.ApfConstant.TCP_HEADER_SIZE_OFFSET;
-import static android.net.apf.ApfConstant.TCP_UDP_DESTINATION_PORT_OFFSET;
+import static android.net.apf.ApfConstants.APF_MAX_ETH_TYPE_BLACK_LIST_LEN;
+import static android.net.apf.ApfConstants.ARP_HEADER_OFFSET;
+import static android.net.apf.ApfConstants.ARP_IPV4_HEADER;
+import static android.net.apf.ApfConstants.ARP_OPCODE_OFFSET;
+import static android.net.apf.ApfConstants.ARP_OPCODE_REPLY;
+import static android.net.apf.ApfConstants.ARP_OPCODE_REQUEST;
+import static android.net.apf.ApfConstants.ARP_SOURCE_IP_ADDRESS_OFFSET;
+import static android.net.apf.ApfConstants.ARP_TARGET_IP_ADDRESS_OFFSET;
+import static android.net.apf.ApfConstants.DHCP_CLIENT_MAC_OFFSET;
+import static android.net.apf.ApfConstants.DHCP_CLIENT_PORT;
+import static android.net.apf.ApfConstants.ECHO_PORT;
+import static android.net.apf.ApfConstants.ETH_DEST_ADDR_OFFSET;
+import static android.net.apf.ApfConstants.ETH_ETHERTYPE_OFFSET;
+import static android.net.apf.ApfConstants.ETH_HEADER_LEN;
+import static android.net.apf.ApfConstants.ETH_MULTICAST_MDNS_V4_MAC_ADDRESS;
+import static android.net.apf.ApfConstants.ETH_MULTICAST_MDNS_V6_MAC_ADDRESS;
+import static android.net.apf.ApfConstants.ETH_TYPE_MAX;
+import static android.net.apf.ApfConstants.ETH_TYPE_MIN;
+import static android.net.apf.ApfConstants.FIXED_ARP_REPLY_HEADER;
+import static android.net.apf.ApfConstants.ICMP6_TYPE_OFFSET;
+import static android.net.apf.ApfConstants.IPPROTO_HOPOPTS;
+import static android.net.apf.ApfConstants.IPV4_ANY_HOST_ADDRESS;
+import static android.net.apf.ApfConstants.IPV4_BROADCAST_ADDRESS;
+import static android.net.apf.ApfConstants.IPV4_DEST_ADDR_OFFSET;
+import static android.net.apf.ApfConstants.IPV4_FRAGMENT_MORE_FRAGS_MASK;
+import static android.net.apf.ApfConstants.IPV4_FRAGMENT_OFFSET_MASK;
+import static android.net.apf.ApfConstants.IPV4_FRAGMENT_OFFSET_OFFSET;
+import static android.net.apf.ApfConstants.IPV4_PROTOCOL_OFFSET;
+import static android.net.apf.ApfConstants.IPV4_TOTAL_LENGTH_OFFSET;
+import static android.net.apf.ApfConstants.IPV6_ALL_NODES_ADDRESS;
+import static android.net.apf.ApfConstants.IPV6_DEST_ADDR_OFFSET;
+import static android.net.apf.ApfConstants.IPV6_FLOW_LABEL_LEN;
+import static android.net.apf.ApfConstants.IPV6_FLOW_LABEL_OFFSET;
+import static android.net.apf.ApfConstants.IPV6_HEADER_LEN;
+import static android.net.apf.ApfConstants.IPV6_NEXT_HEADER_OFFSET;
+import static android.net.apf.ApfConstants.IPV6_SRC_ADDR_OFFSET;
+import static android.net.apf.ApfConstants.MDNS_PORT;
+import static android.net.apf.ApfConstants.MDNS_QDCOUNT_OFFSET;
+import static android.net.apf.ApfConstants.MDNS_QNAME_OFFSET;
+import static android.net.apf.ApfConstants.TCP_HEADER_SIZE_OFFSET;
+import static android.net.apf.ApfConstants.TCP_UDP_DESTINATION_PORT_OFFSET;
import static android.net.apf.BaseApfGenerator.MemorySlot;
import static android.net.apf.BaseApfGenerator.Register.R0;
import static android.net.apf.BaseApfGenerator.Register.R1;
@@ -1974,7 +1974,7 @@
ApfV4GeneratorBase<?> gen;
if (SdkLevel.isAtLeastV()
&& ApfV6Generator.supportsVersion(mApfCapabilities.apfVersionSupported)) {
- gen = new ApfV6Generator();
+ gen = new ApfV6Generator(mApfCapabilities.maximumApfProgramSize);
} else {
gen = new ApfV4Generator(mApfCapabilities.apfVersionSupported);
}
diff --git a/src/android/net/apf/ApfV4Generator.java b/src/android/net/apf/ApfV4Generator.java
index 84824b2..6892d2c 100644
--- a/src/android/net/apf/ApfV4Generator.java
+++ b/src/android/net/apf/ApfV4Generator.java
@@ -15,6 +15,7 @@
*/
package android.net.apf;
+import static android.net.apf.BaseApfGenerator.Rbit.Rbit1;
import static android.net.apf.BaseApfGenerator.Register.R0;
import static android.net.apf.BaseApfGenerator.Register.R1;
@@ -73,8 +74,8 @@
}
@Override
- void addArithR1(Opcodes opcode) {
- append(new Instruction(opcode, R1));
+ void addR0ArithR1(Opcodes opcode) {
+ append(new Instruction(opcode, Rbit1)); // APFv2/4: R0 op= R1
}
/**
@@ -88,7 +89,7 @@
@Override
public ApfV4Generator addCountAndPass(ApfCounterTracker.Counter counter) {
checkPassCounterRange(counter);
- return maybeAddLoadR1CounterOffset(counter).addJump(mCountAndPassLabel);
+ return maybeAddLoadCounterOffset(R1, counter).addJump(mCountAndPassLabel);
}
/**
@@ -102,31 +103,31 @@
@Override
public ApfV4Generator addCountAndDrop(ApfCounterTracker.Counter counter) {
checkDropCounterRange(counter);
- return maybeAddLoadR1CounterOffset(counter).addJump(mCountAndDropLabel);
+ return maybeAddLoadCounterOffset(R1, counter).addJump(mCountAndDropLabel);
}
@Override
public ApfV4Generator addCountAndDropIfR0Equals(long val, ApfCounterTracker.Counter cnt) {
checkDropCounterRange(cnt);
- return maybeAddLoadR1CounterOffset(cnt).addJumpIfR0Equals(val, mCountAndDropLabel);
+ return maybeAddLoadCounterOffset(R1, cnt).addJumpIfR0Equals(val, mCountAndDropLabel);
}
@Override
public ApfV4Generator addCountAndPassIfR0Equals(long val, ApfCounterTracker.Counter cnt) {
checkPassCounterRange(cnt);
- return maybeAddLoadR1CounterOffset(cnt).addJumpIfR0Equals(val, mCountAndPassLabel);
+ return maybeAddLoadCounterOffset(R1, cnt).addJumpIfR0Equals(val, mCountAndPassLabel);
}
@Override
public ApfV4Generator addCountAndDropIfR0NotEquals(long val, ApfCounterTracker.Counter cnt) {
checkDropCounterRange(cnt);
- return maybeAddLoadR1CounterOffset(cnt).addJumpIfR0NotEquals(val, mCountAndDropLabel);
+ return maybeAddLoadCounterOffset(R1, cnt).addJumpIfR0NotEquals(val, mCountAndDropLabel);
}
@Override
public ApfV4Generator addCountAndPassIfR0NotEquals(long val, ApfCounterTracker.Counter cnt) {
checkPassCounterRange(cnt);
- return maybeAddLoadR1CounterOffset(cnt).addJumpIfR0NotEquals(val, mCountAndPassLabel);
+ return maybeAddLoadCounterOffset(R1, cnt).addJumpIfR0NotEquals(val, mCountAndPassLabel);
}
@Override
@@ -135,7 +136,7 @@
if (val <= 0) {
throw new IllegalArgumentException("val must > 0, current val: " + val);
}
- return maybeAddLoadR1CounterOffset(cnt).addJumpIfR0LessThan(val, mCountAndDropLabel);
+ return maybeAddLoadCounterOffset(R1, cnt).addJumpIfR0LessThan(val, mCountAndDropLabel);
}
@Override
@@ -144,14 +145,14 @@
if (val <= 0) {
throw new IllegalArgumentException("val must > 0, current val: " + val);
}
- return maybeAddLoadR1CounterOffset(cnt).addJumpIfR0LessThan(val, mCountAndPassLabel);
+ return maybeAddLoadCounterOffset(R1, cnt).addJumpIfR0LessThan(val, mCountAndPassLabel);
}
@Override
public ApfV4Generator addCountAndDropIfBytesAtR0NotEqual(byte[] bytes,
ApfCounterTracker.Counter cnt) throws IllegalInstructionException {
checkDropCounterRange(cnt);
- return maybeAddLoadR1CounterOffset(cnt).addJumpIfBytesAtR0NotEqual(bytes,
+ return maybeAddLoadCounterOffset(R1, cnt).addJumpIfBytesAtR0NotEqual(bytes,
mCountAndDropLabel);
}
@@ -159,7 +160,7 @@
public ApfV4Generator addCountAndPassIfBytesAtR0NotEqual(byte[] bytes,
ApfCounterTracker.Counter cnt) throws IllegalInstructionException {
checkPassCounterRange(cnt);
- return maybeAddLoadR1CounterOffset(cnt).addJumpIfBytesAtR0NotEqual(bytes,
+ return maybeAddLoadCounterOffset(R1, cnt).addJumpIfBytesAtR0NotEqual(bytes,
mCountAndPassLabel);
}
@@ -224,12 +225,14 @@
.addJump(DROP_LABEL);
}
+ /**
+ * This function is no-op in APFv4
+ */
+ @Override
+ void updateExceptionBufferSize(int programSize) { }
+
private ApfV4Generator maybeAddLoadCounterOffset(Register reg, ApfCounterTracker.Counter cnt) {
if (mVersion < 4) return self();
return addLoadImmediate(reg, cnt.offset());
}
-
- private ApfV4Generator maybeAddLoadR1CounterOffset(ApfCounterTracker.Counter counter) {
- return maybeAddLoadCounterOffset(R1, counter);
- }
}
diff --git a/src/android/net/apf/ApfV4GeneratorBase.java b/src/android/net/apf/ApfV4GeneratorBase.java
index be3da08..6dcc338 100644
--- a/src/android/net/apf/ApfV4GeneratorBase.java
+++ b/src/android/net/apf/ApfV4GeneratorBase.java
@@ -218,14 +218,14 @@
return addLeftShift(-val);
}
- // Argument should be one of Opcodes.{ADD,MUL,DIV,AND,OR,SH}
- abstract void addArithR1(Opcodes opcode);
+ // R0 op= R1, where op should be one of Opcodes.{ADD,MUL,DIV,AND,OR,SH}
+ abstract void addR0ArithR1(Opcodes opcode);
/**
* Add an instruction to the end of the program to add register R1 to register R0.
*/
public final Type addAddR1ToR0() {
- addArithR1(Opcodes.ADD);
+ addR0ArithR1(Opcodes.ADD); // R0 += R1
return self();
}
@@ -233,7 +233,7 @@
* Add an instruction to the end of the program to multiply register R0 by register R1.
*/
public final Type addMulR0ByR1() {
- addArithR1(Opcodes.MUL);
+ addR0ArithR1(Opcodes.MUL); // R0 *= R1
return self();
}
@@ -241,7 +241,7 @@
* Add an instruction to the end of the program to divide register R0 by register R1.
*/
public final Type addDivR0ByR1() {
- addArithR1(Opcodes.DIV);
+ addR0ArithR1(Opcodes.DIV); // R0 /= R1
return self();
}
@@ -250,7 +250,7 @@
* and store the result back into register R0.
*/
public final Type addAndR0WithR1() {
- addArithR1(Opcodes.AND);
+ addR0ArithR1(Opcodes.AND); // R0 &= R1
return self();
}
@@ -259,7 +259,7 @@
* and store the result back into register R0.
*/
public final Type addOrR0WithR1() {
- addArithR1(Opcodes.OR);
+ addR0ArithR1(Opcodes.OR); // R0 |= R1
return self();
}
@@ -268,7 +268,7 @@
* register R1.
*/
public final Type addLeftShiftR0ByR1() {
- addArithR1(Opcodes.SH);
+ addR0ArithR1(Opcodes.SH); // R0 <<= R1
return self();
}
diff --git a/src/android/net/apf/ApfV6Generator.java b/src/android/net/apf/ApfV6Generator.java
index 141cf8b..d425907 100644
--- a/src/android/net/apf/ApfV6Generator.java
+++ b/src/android/net/apf/ApfV6Generator.java
@@ -33,22 +33,28 @@
}
/**
- * Creates an ApfV6Generator instance which is able to emit instructions for APFv6.
+ * Creates an ApfV6Generator instance which emits instructions for APFv6.
*/
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public ApfV6Generator() throws IllegalInstructionException {
- super();
- addData(new byte[0]);
+ public ApfV6Generator(int maximumApfProgramSize) throws IllegalInstructionException {
+ this(new byte[0], maximumApfProgramSize);
+ }
+
+ @Override
+ void updateExceptionBufferSize(int programSize) throws IllegalInstructionException {
+ mInstructions.get(1).updateExceptionBufferSize(
+ mMaximumApfProgramSize - ApfCounterTracker.Counter.totalSize() - programSize);
}
/**
- * Creates an ApfV6Generator instance which is able to emit instructions APFv6.
+ * Creates an ApfV6Generator instance which emits instructions APFv6.
* Initializes the data region with {@code bytes}.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public ApfV6Generator(byte[] bytes) throws IllegalInstructionException {
- super();
+ public ApfV6Generator(byte[] bytes, int maximumApfProgramSize)
+ throws IllegalInstructionException {
+ super(maximumApfProgramSize);
Objects.requireNonNull(bytes);
addData(bytes);
+ addExceptionBuffer(0);
}
}
diff --git a/src/android/net/apf/ApfV6GeneratorBase.java b/src/android/net/apf/ApfV6GeneratorBase.java
index 9cfbdd2..b8359ec 100644
--- a/src/android/net/apf/ApfV6GeneratorBase.java
+++ b/src/android/net/apf/ApfV6GeneratorBase.java
@@ -17,6 +17,7 @@
import static android.net.apf.BaseApfGenerator.Rbit.Rbit0;
import static android.net.apf.BaseApfGenerator.Rbit.Rbit1;
+import static android.net.apf.BaseApfGenerator.Register.R0;
import static android.net.apf.BaseApfGenerator.Register.R1;
import androidx.annotation.NonNull;
@@ -41,14 +42,17 @@
public abstract class ApfV6GeneratorBase<Type extends ApfV6GeneratorBase<Type>> extends
ApfV4GeneratorBase<Type> {
+ final int mMaximumApfProgramSize;
+
/**
* Creates an ApfV6GeneratorBase instance which is able to emit instructions for the specified
* {@code version} of the APF interpreter. Throws {@code IllegalInstructionException} if
* the requested version is unsupported.
*
*/
- public ApfV6GeneratorBase() throws IllegalInstructionException {
+ public ApfV6GeneratorBase(int maximumApfProgramSize) throws IllegalInstructionException {
super(APF_VERSION_6, false);
+ this.mMaximumApfProgramSize = maximumApfProgramSize;
}
/**
@@ -126,6 +130,14 @@
}
/**
+ * Add an instruction to the end of the program to set the exception buffer size.
+ * @param bufSize the exception buffer size
+ */
+ public final Type addExceptionBuffer(int bufSize) throws IllegalInstructionException {
+ return append(new Instruction(ExtendedOpcodes.EXCEPTIONBUFFER).addU16(bufSize));
+ }
+
+ /**
* Add an instruction to the end of the program to transmit the allocated buffer without
* checksum.
*/
@@ -599,8 +611,8 @@
}
@Override
- void addArithR1(Opcodes opcode) {
- append(new Instruction(opcode, R1));
+ void addR0ArithR1(Opcodes opcode) {
+ append(new Instruction(opcode, R0)); // APFv6+: R0 op= R1
}
/**
diff --git a/src/android/net/apf/BaseApfGenerator.java b/src/android/net/apf/BaseApfGenerator.java
index cbcc125..a53913b 100644
--- a/src/android/net/apf/BaseApfGenerator.java
+++ b/src/android/net/apf/BaseApfGenerator.java
@@ -184,7 +184,12 @@
// middle 2 bits - 1..4 length of immediates - 1
// bottom 1 bit - =0 jmp if in set, =1 if not in set
// imm4(imm3 * 1/2/3/4 bytes): the *UNIQUE* values to compare against
- JONEOF(47);
+ JONEOF(47),
+ /* Specify length of exception buffer, which is populated on abnormal program termination.
+ * imm1: Extended opcode
+ * imm2(u16): Length of exception buffer (located *immediately* after the program itself)
+ */
+ EXCEPTIONBUFFER(48);
final int value;
@@ -505,6 +510,22 @@
}
/**
+ * Updates exception buffer size.
+ * @param bufSize the new exception buffer size
+ */
+ void updateExceptionBufferSize(int bufSize) throws IllegalInstructionException {
+ if (mOpcode != Opcodes.EXT || mIntImms.get(0).mValue
+ != ExtendedOpcodes.EXCEPTIONBUFFER.value) {
+ throw new IllegalInstructionException(
+ "updateExceptionBuffer() is only valid for EXCEPTIONBUFFER opcode");
+ }
+ // Update the buffer size immediate (second imm) value. Due to mValue within
+ // IntImmediate being final, we must remove and re-add the value to apply changes.
+ mIntImms.remove(1);
+ addU16(bufSize);
+ }
+
+ /**
* @return size of instruction in bytes.
*/
int size() {
@@ -727,6 +748,11 @@
}
/**
+ * Updates the exception buffer size.
+ */
+ abstract void updateExceptionBufferSize(int programSize) throws IllegalInstructionException;
+
+ /**
* Generate the bytecode for the APF program.
* @return the bytecode.
* @throws IllegalStateException if a label is referenced but not defined.
@@ -765,6 +791,7 @@
} while (shrunk);
// Generate bytecode for instructions.
byte[] bytecode = new byte[total_size];
+ updateExceptionBufferSize(total_size);
for (Instruction instruction : mInstructions) {
instruction.generate(bytecode);
}
diff --git a/tests/unit/src/android/net/apf/ApfStandaloneTest.kt b/tests/unit/src/android/net/apf/ApfStandaloneTest.kt
index 6012ed1..1a2307d 100644
--- a/tests/unit/src/android/net/apf/ApfStandaloneTest.kt
+++ b/tests/unit/src/android/net/apf/ApfStandaloneTest.kt
@@ -15,15 +15,15 @@
*/
package android.net.apf
-import android.net.apf.ApfConstant.DHCP_SERVER_PORT
-import android.net.apf.ApfConstant.ETH_HEADER_LEN
-import android.net.apf.ApfConstant.ICMP6_TYPE_OFFSET
-import android.net.apf.ApfConstant.IPV4_BROADCAST_ADDRESS
-import android.net.apf.ApfConstant.IPV4_DEST_ADDR_OFFSET
-import android.net.apf.ApfConstant.IPV4_PROTOCOL_OFFSET
-import android.net.apf.ApfConstant.IPV4_SRC_ADDR_OFFSET
-import android.net.apf.ApfConstant.IPV6_NEXT_HEADER_OFFSET
-import android.net.apf.ApfConstant.TCP_UDP_DESTINATION_PORT_OFFSET
+import android.net.apf.ApfConstants.DHCP_SERVER_PORT
+import android.net.apf.ApfConstants.ETH_HEADER_LEN
+import android.net.apf.ApfConstants.ICMP6_TYPE_OFFSET
+import android.net.apf.ApfConstants.IPV4_BROADCAST_ADDRESS
+import android.net.apf.ApfConstants.IPV4_DEST_ADDR_OFFSET
+import android.net.apf.ApfConstants.IPV4_PROTOCOL_OFFSET
+import android.net.apf.ApfConstants.IPV4_SRC_ADDR_OFFSET
+import android.net.apf.ApfConstants.IPV6_NEXT_HEADER_OFFSET
+import android.net.apf.ApfConstants.TCP_UDP_DESTINATION_PORT_OFFSET
import android.net.apf.BaseApfGenerator.APF_VERSION_4
import android.net.apf.BaseApfGenerator.MemorySlot
import android.net.apf.BaseApfGenerator.Register.R0
diff --git a/tests/unit/src/android/net/apf/ApfTest.java b/tests/unit/src/android/net/apf/ApfTest.java
index df8bad0..871a431 100644
--- a/tests/unit/src/android/net/apf/ApfTest.java
+++ b/tests/unit/src/android/net/apf/ApfTest.java
@@ -3531,7 +3531,7 @@
@Test
public void testApfGeneratorPropagation() throws IllegalInstructionException {
ApfV4Generator v4Gen = new ApfV4Generator(APF_VERSION_4);
- ApfV6Generator v6Gen = new ApfV6Generator();
+ ApfV6Generator v6Gen = new ApfV6Generator(1024);
assertEquals(4, deriveApfGeneratorVersion(v4Gen));
assertEquals(6, deriveApfGeneratorVersion(v6Gen));
}
diff --git a/tests/unit/src/android/net/apf/ApfV5Test.kt b/tests/unit/src/android/net/apf/ApfV5Test.kt
index 4107198..435dcf7 100644
--- a/tests/unit/src/android/net/apf/ApfV5Test.kt
+++ b/tests/unit/src/android/net/apf/ApfV5Test.kt
@@ -92,6 +92,8 @@
@Mock
private lateinit var dependencies: Dependencies
+ private val defaultMaximumApfProgramSize = 2048
+
private val testPacket = byteArrayOf(1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 13, 14, 15, 16)
private val hostIpv4Address = byteArrayOf(10, 0, 0, 1)
@@ -114,15 +116,17 @@
@Test
fun testDataInstructionMustComeFirst() {
- var gen = ApfV6Generator()
+ var gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addAllocateR0()
assertFailsWith<IllegalInstructionException> { gen.addData(ByteArray(3) { 0x01 }) }
}
@Test
fun testApfInstructionEncodingSizeCheck() {
- var gen = ApfV6Generator()
- assertFailsWith<IllegalArgumentException> { ApfV6Generator(ByteArray(65536) { 0x01 }) }
+ var gen = ApfV6Generator(defaultMaximumApfProgramSize)
+ assertFailsWith<IllegalArgumentException> {
+ ApfV6Generator(ByteArray(65536) { 0x01 }, defaultMaximumApfProgramSize)
+ }
assertFailsWith<IllegalArgumentException> { gen.addAllocate(65536) }
assertFailsWith<IllegalArgumentException> { gen.addAllocate(-1) }
assertFailsWith<IllegalArgumentException> { gen.addDataCopy(-1, 1) }
@@ -355,7 +359,7 @@
fun testValidateDnsNames() {
// '%' is a valid label character in mDNS subtype
// byte == 0xff means it is a '*' wildcard, which is a valid encoding.
- val program = ApfV6Generator().addJumpIfPktAtR0ContainDnsQ(
+ val program = ApfV6Generator(defaultMaximumApfProgramSize).addJumpIfPktAtR0ContainDnsQ(
byteArrayOf(1, '%'.code.toByte(), 0, 0),
1,
DROP_LABEL
@@ -380,9 +384,9 @@
ApfJniUtils.disassembleApf(program).map { it.trim() }
)
- var gen = ApfV6Generator()
+ var gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addDrop()
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
// encoding DROP opcode: opcode=0, imm_len=0, R=1
assertContentEquals(
byteArrayOf(encodeInstruction(opcode = 0, immLength = 0, register = 1)),
@@ -393,9 +397,9 @@
ApfJniUtils.disassembleApf(program).map { it.trim() }
)
- gen = ApfV6Generator()
+ gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addCountAndPass(129)
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
// encoding COUNT(PASS) opcode: opcode=0, imm_len=size_of(imm), R=0, imm=counterNumber
assertContentEquals(
byteArrayOf(
@@ -409,9 +413,9 @@
ApfJniUtils.disassembleApf(program).map { it.trim() }
)
- gen = ApfV6Generator()
+ gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addCountAndDrop(1000)
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
// encoding COUNT(DROP) opcode: opcode=0, imm_len=size_of(imm), R=1, imm=counterNumber
assertContentEquals(
byteArrayOf(
@@ -426,9 +430,9 @@
ApfJniUtils.disassembleApf(program).map { it.trim() }
)
- gen = ApfV6Generator()
+ gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addCountAndPass(PASSED_ARP)
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
// encoding COUNT(PASS) opcode: opcode=0, imm_len=size_of(imm), R=0, imm=counterNumber
assertContentEquals(
byteArrayOf(
@@ -442,9 +446,9 @@
ApfJniUtils.disassembleApf(program).map { it.trim() }
)
- gen = ApfV6Generator()
+ gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addCountAndDrop(DROPPED_ETHERTYPE_DENYLISTED)
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
// encoding COUNT(DROP) opcode: opcode=0, imm_len=size_of(imm), R=1, imm=counterNumber
assertContentEquals(
byteArrayOf(
@@ -458,10 +462,10 @@
ApfJniUtils.disassembleApf(program).map { it.trim() }
)
- gen = ApfV6Generator()
+ gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addAllocateR0()
gen.addAllocate(1500)
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
// encoding ALLOC opcode: opcode=21(EXT opcode number), imm=36(TRANS opcode number).
// R=0 means length stored in R0. R=1 means the length stored in imm1.
assertContentEquals(
@@ -480,10 +484,10 @@
"2: allocate 1500"
), ApfJniUtils.disassembleApf(program).map { it.trim() })
- gen = ApfV6Generator()
+ gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addTransmitWithoutChecksum()
gen.addTransmitL4(30, 40, 50, 256, true)
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
// encoding TRANSMIT opcode: opcode=21(EXT opcode number),
// imm=37(TRANSMIT opcode number),
assertContentEquals(byteArrayOf(
@@ -497,23 +501,25 @@
), ApfJniUtils.disassembleApf(program).map { it.trim() })
val largeByteArray = ByteArray(256) { 0x01 }
- gen = ApfV6Generator(largeByteArray)
+ gen = ApfV6Generator(largeByteArray, defaultMaximumApfProgramSize)
program = gen.generate()
- // encoding DATA opcode: opcode=14(JMP), R=1
assertContentEquals(
byteArrayOf(
- encodeInstruction(opcode = 14, immLength = 2, register = 1),
- 0x01,
- 0x00
- ) + largeByteArray,
+ encodeInstruction(opcode = 14, immLength = 2, register = 1), 1, 0
+ ) + largeByteArray + byteArrayOf(
+ encodeInstruction(opcode = 21, immLength = 1, register = 0), 48, 6, 49
+ ),
program
)
assertContentEquals(
- listOf("0: data 256, " + "01".repeat(256) ),
+ listOf(
+ "0: data 256, " + "01".repeat(256),
+ "259: debugbuf size=1585"
+ ),
ApfJniUtils.disassembleApf(program).map { it.trim() }
)
- gen = ApfV6Generator()
+ gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addWriteU8(0x01)
gen.addWriteU16(0x0102)
gen.addWriteU32(0x01020304)
@@ -525,7 +531,7 @@
gen.addWriteU32(0x80000000)
gen.addWrite32(-2)
gen.addWrite32(byteArrayOf(0xff.toByte(), 0xfe.toByte(), 0xfd.toByte(), 0xfc.toByte()))
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
assertContentEquals(byteArrayOf(
encodeInstruction(24, 1, 0), 0x01,
encodeInstruction(24, 2, 0), 0x01, 0x02,
@@ -554,14 +560,14 @@
"35: write 0xfffefdfc"
), ApfJniUtils.disassembleApf(program).map { it.trim() })
- gen = ApfV6Generator()
+ gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addWriteU8(R0)
gen.addWriteU16(R0)
gen.addWriteU32(R0)
gen.addWriteU8(R1)
gen.addWriteU16(R1)
gen.addWriteU32(R1)
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
assertContentEquals(byteArrayOf(
encodeInstruction(21, 1, 0), 38,
encodeInstruction(21, 1, 0), 39,
@@ -579,11 +585,11 @@
"10: ewrite4 r1"
), ApfJniUtils.disassembleApf(program).map { it.trim() })
- gen = ApfV6Generator()
+ gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addDataCopy(0, 10)
gen.addDataCopy(1, 5)
gen.addPacketCopy(1000, 255)
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
assertContentEquals(byteArrayOf(
encodeInstruction(25, 0, 1), 10,
encodeInstruction(25, 1, 1), 1, 5,
@@ -596,12 +602,12 @@
"5: pktcopy src=1000, len=255"
), ApfJniUtils.disassembleApf(program).map { it.trim() })
- gen = ApfV6Generator()
+ gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addDataCopyFromR0(5)
gen.addPacketCopyFromR0(5)
gen.addDataCopyFromR0LenR1()
gen.addPacketCopyFromR0LenR1()
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
assertContentEquals(byteArrayOf(
encodeInstruction(21, 1, 1), 41, 5,
encodeInstruction(21, 1, 0), 41, 5,
@@ -615,9 +621,9 @@
"8: epktcopy src=r0, len=r1"
), ApfJniUtils.disassembleApf(program).map{ it.trim() })
- gen = ApfV6Generator()
+ gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addJumpIfBytesAtR0Equal(byteArrayOf('a'.code.toByte()), ApfV4Generator.DROP_LABEL)
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
assertContentEquals(byteArrayOf(
encodeInstruction(opcode = 20, immLength = 1, register = 1),
1,
@@ -629,10 +635,10 @@
), ApfJniUtils.disassembleApf(program).map{ it.trim() })
val qnames = byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte(), 0, 0)
- gen = ApfV6Generator()
+ gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addJumpIfPktAtR0DoesNotContainDnsQ(qnames, 0x0c, ApfV4Generator.DROP_LABEL)
gen.addJumpIfPktAtR0ContainDnsQ(qnames, 0x0c, ApfV4Generator.DROP_LABEL)
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
assertContentEquals(byteArrayOf(
encodeInstruction(21, 1, 0), 43, 11, 0x0c.toByte(),
) + qnames + byteArrayOf(
@@ -643,10 +649,10 @@
"10: jdnsqeq r0, DROP, 12, (1)A(1)B(0)(0)"
), ApfJniUtils.disassembleApf(program).map{ it.trim() })
- gen = ApfV6Generator()
+ gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addJumpIfPktAtR0DoesNotContainDnsQSafe(qnames, 0x0c, ApfV4Generator.DROP_LABEL)
gen.addJumpIfPktAtR0ContainDnsQSafe(qnames, 0x0c, ApfV4Generator.DROP_LABEL)
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
assertContentEquals(byteArrayOf(
encodeInstruction(21, 1, 0), 45, 11, 0x0c.toByte(),
) + qnames + byteArrayOf(
@@ -657,10 +663,10 @@
"10: jdnsqeqsafe r0, DROP, 12, (1)A(1)B(0)(0)"
), ApfJniUtils.disassembleApf(program).map{ it.trim() })
- gen = ApfV6Generator()
+ gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addJumpIfPktAtR0DoesNotContainDnsA(qnames, ApfV4Generator.DROP_LABEL)
gen.addJumpIfPktAtR0ContainDnsA(qnames, ApfV4Generator.DROP_LABEL)
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
assertContentEquals(byteArrayOf(
encodeInstruction(21, 1, 0), 44, 10,
) + qnames + byteArrayOf(
@@ -671,10 +677,10 @@
"9: jdnsaeq r0, DROP, (1)A(1)B(0)(0)"
), ApfJniUtils.disassembleApf(program).map{ it.trim() })
- gen = ApfV6Generator()
+ gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addJumpIfPktAtR0DoesNotContainDnsASafe(qnames, ApfV4Generator.DROP_LABEL)
gen.addJumpIfPktAtR0ContainDnsASafe(qnames, ApfV4Generator.DROP_LABEL)
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
assertContentEquals(byteArrayOf(
encodeInstruction(21, 1, 0), 46, 10,
) + qnames + byteArrayOf(
@@ -685,11 +691,11 @@
"9: jdnsaeqsafe r0, DROP, (1)A(1)B(0)(0)"
), ApfJniUtils.disassembleApf(program).map{ it.trim() })
- gen = ApfV6Generator()
+ gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addJumpIfOneOf(R1, List(32) { (it + 1).toLong() }.toSet(), DROP_LABEL)
gen.addJumpIfOneOf(R0, setOf(0, 257, 65536), DROP_LABEL)
gen.addJumpIfNoneOf(R0, setOf(1, 2, 3), DROP_LABEL)
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
assertContentEquals(byteArrayOf(
encodeInstruction(21, 1, 1), 47, 24, -16, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
@@ -699,20 +705,20 @@
encodeInstruction(21, 1, 0), 47, 1, 9, 1, 2, 3
), program)
- gen = ApfV6Generator()
+ gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addJumpIfOneOf(R0, setOf(0, 128, 256, 65536), DROP_LABEL)
gen.addJumpIfNoneOf(R1, setOf(0, 128, 256, 65536), DROP_LABEL)
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
assertContentEquals(listOf(
"0: joneof r0, DROP, { 0, 128, 256, 65536 }",
"20: jnoneof r1, DROP, { 0, 128, 256, 65536 }"
), ApfJniUtils.disassembleApf(program).map{ it.trim() })
- gen = ApfV6Generator()
+ gen = ApfV6Generator(defaultMaximumApfProgramSize)
gen.addJumpIfBytesAtR0EqualsAnyOf(listOf(byteArrayOf(1, 2), byteArrayOf(3, 4)), DROP_LABEL)
gen.addJumpIfBytesAtR0EqualNoneOf(listOf(byteArrayOf(1, 2), byteArrayOf(3, 4)), DROP_LABEL)
gen.addJumpIfBytesAtR0EqualNoneOf(listOf(byteArrayOf(1, 1), byteArrayOf(1, 1)), DROP_LABEL)
- program = gen.generate().skipEmptyData()
+ program = gen.generate().skipDataAndDebug()
assertContentEquals(byteArrayOf(
encodeInstruction(opcode = 20, immLength = 2, register = 1),
0, 15, 8, 2, 1, 2, 3, 4,
@@ -730,7 +736,7 @@
@Test
fun testWriteToTxBuffer() {
- var program = ApfV6Generator()
+ var program = ApfV6Generator(defaultMaximumApfProgramSize)
.addAllocate(14)
.addWriteU8(0x01)
.addWriteU16(0x0203)
@@ -757,7 +763,7 @@
@Test
fun testCopyToTxBuffer() {
- var program = ApfV6Generator(byteArrayOf(33, 34, 35))
+ var program = ApfV6Generator(byteArrayOf(33, 34, 35), defaultMaximumApfProgramSize)
.addAllocate(14)
.addDataCopy(3, 2) // arg1=src, arg2=len
.addDataCopy(5, 1) // arg1=src, arg2=len
@@ -784,7 +790,7 @@
@Test
fun testCopyContentToTxBuffer() {
- val program = ApfV6Generator()
+ val program = ApfV6Generator(defaultMaximumApfProgramSize)
.addAllocate(18)
.addDataCopy(HexDump.hexStringToByteArray("112233445566"))
.addDataCopy(HexDump.hexStringToByteArray("223344"))
@@ -794,12 +800,13 @@
.generate()
assertContentEquals(listOf(
"0: data 9, 112233445566778899",
- "12: allocate 18",
- "16: datacopy src=3, len=6",
- "19: datacopy src=4, len=3",
- "22: datacopy src=9, len=3",
- "25: datacopy src=3, len=6",
- "28: transmit ip_ofs=255"
+ "12: debugbuf size=1812",
+ "16: allocate 18",
+ "20: datacopy src=3, len=6",
+ "23: datacopy src=4, len=3",
+ "26: datacopy src=9, len=3",
+ "29: datacopy src=3, len=6",
+ "32: transmit ip_ofs=255"
), ApfJniUtils.disassembleApf(program).map{ it.trim() })
assertPass(APF_VERSION_6, program, testPacket)
val transmitPkt = HexDump.toHexString(ApfJniUtils.getTransmittedPacket())
@@ -808,14 +815,14 @@
@Test
fun testPassDrop() {
- var program = ApfV6Generator()
+ var program = ApfV6Generator(defaultMaximumApfProgramSize)
.addDrop()
.addPass()
.generate()
assertDrop(APF_VERSION_6, program, testPacket)
var dataRegion = ByteArray(Counter.totalSize()) { 0 }
- program = ApfV6Generator()
+ program = ApfV6Generator(defaultMaximumApfProgramSize)
.addCountAndDrop(Counter.DROPPED_ETH_BROADCAST)
.generate()
assertVerdict(APF_VERSION_6, DROP, program, testPacket, dataRegion)
@@ -826,7 +833,7 @@
), counterMap)
dataRegion = ByteArray(Counter.totalSize()) { 0 }
- program = ApfV6Generator()
+ program = ApfV6Generator(defaultMaximumApfProgramSize)
.addCountAndPass(Counter.PASSED_ARP)
.generate()
assertVerdict(APF_VERSION_6, PASS, program, testPacket, dataRegion)
@@ -845,7 +852,7 @@
)
doTestLoadStoreCounter (
{ mutableMapOf(TOTAL_PACKETS to 1) },
- { ApfV6Generator() }
+ { ApfV6Generator(defaultMaximumApfProgramSize) }
)
}
@@ -873,7 +880,7 @@
)
doTestCountAndPassDropCompareR0(
{ mutableMapOf(Counter.TOTAL_PACKETS to 1) },
- { ApfV6Generator() }
+ { ApfV6Generator(defaultMaximumApfProgramSize) }
)
}
@@ -1034,7 +1041,7 @@
@Test
fun testAllocateFailure() {
- val program = ApfV6Generator()
+ val program = ApfV6Generator(defaultMaximumApfProgramSize)
// allocate size: 65535 > sizeof(apf_test_buffer): 1514, trigger allocate failure.
.addAllocate(65535)
.addDrop()
@@ -1050,7 +1057,7 @@
@Test
fun testTransmitFailure() {
- val program = ApfV6Generator()
+ val program = ApfV6Generator(defaultMaximumApfProgramSize)
.addAllocate(14)
// len: 13 is less than ETH_HLEN, trigger transmit failure.
.addLoadImmediate(R0, 13)
@@ -1092,7 +1099,7 @@
0x00, 0x00, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x04, 0xc0, 0xa8, 0x01,
0x09,
).map { it.toByte() }.toByteArray()
- val program = ApfV6Generator(etherIpv4UdpPacket)
+ val program = ApfV6Generator(etherIpv4UdpPacket, defaultMaximumApfProgramSize)
.addAllocate(etherIpv4UdpPacket.size)
.addDataCopy(3, etherIpv4UdpPacket.size) // arg1=src, arg2=len
.addTransmitL4(
@@ -1138,28 +1145,28 @@
0x00, 0x01, 0x00, 0x01 // type = A, class = 0x0001
).map { it.toByte() }.toByteArray()
- var program = ApfV6Generator()
+ var program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 0)
.addJumpIfPktAtR0ContainDnsQ(needlesMatch, 0x01, DROP_LABEL) // arg2=qtype
.addPass()
.generate()
assertDrop(APF_VERSION_6, program, udpPayload)
- program = ApfV6Generator()
+ program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 0)
.addJumpIfPktAtR0ContainDnsQSafe(needlesMatch, 0x01, DROP_LABEL)
.addPass()
.generate()
assertDrop(APF_VERSION_6, program, udpPayload)
- program = ApfV6Generator()
+ program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 0)
.addJumpIfPktAtR0DoesNotContainDnsQ(needlesMatch, 0x01, DROP_LABEL) // arg2=qtype
.addPass()
.generate()
assertPass(APF_VERSION_6, program, udpPayload)
- program = ApfV6Generator()
+ program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 0)
.addJumpIfPktAtR0DoesNotContainDnsQSafe(needlesMatch, 0x01, DROP_LABEL) // arg2=qtype
.addPass()
@@ -1181,7 +1188,7 @@
0x00, 0x01, 0x00, 0x01 // type = A, class = 0x0001
).map { it.toByte() }.toByteArray()
- program = ApfV6Generator()
+ program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 0)
.addJumpIfPktAtR0ContainDnsQ(needlesMatch, 0x01, DROP_LABEL) // arg2=qtype
.addPass()
@@ -1194,7 +1201,7 @@
Counter.CORRUPT_DNS_PACKET to 1
), counterMap)
- program = ApfV6Generator()
+ program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 0)
.addJumpIfPktAtR0ContainDnsQSafe(needlesMatch, 0x01, DROP_LABEL) // arg2=qtype
.addPass()
@@ -1239,28 +1246,28 @@
0x00, 0x04, 0xc0, 0xa8, 0x01, 0x09 // rdlengh = 4, rdata = 192.168.1.9
).map { it.toByte() }.toByteArray()
- var program = ApfV6Generator()
+ var program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 0)
.addJumpIfPktAtR0ContainDnsA(needlesMatch, DROP_LABEL)
.addPass()
.generate()
assertDrop(APF_VERSION_6, program, udpPayload)
- program = ApfV6Generator()
+ program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 0)
.addJumpIfPktAtR0ContainDnsASafe(needlesMatch, DROP_LABEL)
.addPass()
.generate()
assertDrop(APF_VERSION_6, program, udpPayload)
- program = ApfV6Generator()
+ program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 0)
.addJumpIfPktAtR0DoesNotContainDnsA(needlesMatch, DROP_LABEL)
.addPass()
.generate()
assertPass(APF_VERSION_6, program, udpPayload)
- program = ApfV6Generator()
+ program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 0)
.addJumpIfPktAtR0DoesNotContainDnsASafe(needlesMatch, DROP_LABEL)
.addPass()
@@ -1286,7 +1293,7 @@
0x00, 0x04, 0xc0, 0xa8, 0x01, 0x09 // rdlengh = 4, rdata = 192.168.1.9
).map { it.toByte() }.toByteArray()
- program = ApfV6Generator()
+ program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 0)
.addJumpIfPktAtR0ContainDnsA(needlesMatch, DROP_LABEL)
.addPass()
@@ -1299,7 +1306,7 @@
Counter.CORRUPT_DNS_PACKET to 1
), counterMap)
- program = ApfV6Generator()
+ program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 0)
.addJumpIfPktAtR0ContainDnsASafe(needlesMatch, DROP_LABEL)
.addPass()
@@ -1322,7 +1329,7 @@
@Test
fun testJumpMultipleByteSequencesMatch() {
- var program = ApfV6Generator()
+ var program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 0)
.addJumpIfBytesAtR0EqualsAnyOf(
listOf(byteArrayOf(1, 2, 3), byteArrayOf(6, 5, 4)),
@@ -1332,7 +1339,7 @@
.generate()
assertDrop(APF_VERSION_6, program, testPacket)
- program = ApfV6Generator()
+ program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 2)
.addJumpIfBytesAtR0EqualsAnyOf(
listOf(byteArrayOf(1, 2, 3), byteArrayOf(6, 5, 4)),
@@ -1342,7 +1349,7 @@
.generate()
assertPass(APF_VERSION_6, program, testPacket)
- program = ApfV6Generator()
+ program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 1)
.addJumpIfBytesAtR0EqualNoneOf(
listOf(byteArrayOf(1, 2, 3), byteArrayOf(6, 5, 4)),
@@ -1352,7 +1359,7 @@
.generate()
assertDrop(APF_VERSION_6, program, testPacket)
- program = ApfV6Generator()
+ program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 0)
.addJumpIfBytesAtR0EqualNoneOf(
listOf(byteArrayOf(1, 2, 3), byteArrayOf(6, 5, 4)),
@@ -1365,28 +1372,28 @@
@Test
fun testJumpOneOf() {
- var program = ApfV6Generator()
+ var program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 255)
.addJumpIfOneOf(R0, setOf(1, 2, 3, 128, 255), DROP_LABEL)
.addPass()
.generate()
assertDrop(APF_VERSION_6, program, testPacket)
- program = ApfV6Generator()
+ program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 254)
.addJumpIfOneOf(R0, setOf(1, 2, 3, 128, 255), DROP_LABEL)
.addPass()
.generate()
assertPass(APF_VERSION_6, program, testPacket)
- program = ApfV6Generator()
+ program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 254)
.addJumpIfNoneOf(R0, setOf(1, 2, 3, 128, 255), DROP_LABEL)
.addPass()
.generate()
assertDrop(APF_VERSION_6, program, testPacket)
- program = ApfV6Generator()
+ program = ApfV6Generator(defaultMaximumApfProgramSize)
.addLoadImmediate(R0, 255)
.addJumpIfNoneOf(R0, setOf(1, 2, 3, 128, 255), DROP_LABEL)
.addPass()
@@ -1394,6 +1401,18 @@
assertPass(APF_VERSION_6, program, testPacket)
}
+ @Test
+ fun testDebugBuffer() {
+ val program = ApfV6Generator(defaultMaximumApfProgramSize)
+ .addLoad8(R0, 255)
+ .generate()
+ val dataRegion = ByteArray(defaultMaximumApfProgramSize - program.size) { 0 }
+
+ assertVerdict(APF_VERSION_6, PASS, program, testPacket, dataRegion)
+ // offset 3 in the data region should contain if the interpreter is APFv6 mode or not
+ assertEquals(1, dataRegion[3])
+ }
+
// The APFv6 code path is only turned on in V+
@IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@Test
@@ -1470,12 +1489,19 @@
return opcode.shl(3).or(immLengthEncoding.shl(1)).or(register).toByte()
}
- private fun ByteArray.skipEmptyData(): ByteArray {
+ private fun ByteArray.skipDataAndDebug(): ByteArray {
assertEquals(
- listOf(encodeInstruction(14, 2, 1), 0, 0),
- this.take(3)
+ listOf(
+ encodeInstruction(14, 2, 1),
+ 0,
+ 0,
+ encodeInstruction(21, 1, 0),
+ 48
+ // the actual exception buffer size is not checked here.
+ ),
+ this.take(5)
)
- return this.drop(3).toByteArray()
+ return this.drop(7).toByteArray()
}
private fun getDefaultConfig(): ApfFilter.ApfConfiguration {