Better IPv4 multicast coverage in ApfTest

This patch improves the test coverage of ApfFilter for IPv4 broadcast and
multicast traffic.

Bug: 30231088
Change-Id: I2e1d5d5a7cbae17f3d5978a4cf5f10666b5c6104
This commit is contained in:
Hugo Benichi
2016-09-02 11:04:34 +09:00
parent b2e0ed8772
commit 961ca49fd6
2 changed files with 149 additions and 86 deletions

View File

@@ -171,8 +171,8 @@ public class ApfFilter {
private static final int ETH_HEADER_LEN = 14;
private static final int ETH_DEST_ADDR_OFFSET = 0;
private static final int ETH_ETHERTYPE_OFFSET = 12;
private static final byte[] ETH_BROADCAST_MAC_ADDRESS = new byte[]{
(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
private static final byte[] ETH_BROADCAST_MAC_ADDRESS =
{(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
// TODO: Make these offsets relative to end of link-layer header; don't include ETH_HEADER_LEN.
private static final int IPV4_FRAGMENT_OFFSET_OFFSET = ETH_HEADER_LEN + 6;
// Endianness is not an issue for this constant because the APF interpreter always operates in
@@ -188,7 +188,7 @@ public class ApfFilter {
private static final int IPV6_HEADER_LEN = 40;
// The IPv6 all nodes address ff02::1
private static final byte[] IPV6_ALL_NODES_ADDRESS =
new byte[]{ (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
{ (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;
@@ -206,7 +206,7 @@ public class ApfFilter {
private static final int ARP_OPCODE_OFFSET = ARP_HEADER_OFFSET + 6;
private static final short ARP_OPCODE_REQUEST = 1;
private static final short ARP_OPCODE_REPLY = 2;
private static final byte[] ARP_IPV4_HEADER = new byte[]{
private static final byte[] ARP_IPV4_HEADER = {
0, 1, // Hardware type: Ethernet (1)
8, 0, // Protocol type: IP (0x0800)
6, // Hardware size: 6

View File

@@ -61,7 +61,7 @@ import libcore.io.Streams;
* Tests for APF program generator and interpreter.
*
* Build, install and run with:
* runtest frameworks-services -c com.android.server.ApfTest
* runtest frameworks-services -c android.net.apf.ApfTest
*/
public class ApfTest extends AndroidTestCase {
private static final int TIMEOUT_MS = 500;
@@ -86,21 +86,45 @@ public class ApfTest extends AndroidTestCase {
private final static boolean DROP_MULTICAST = true;
private final static boolean ALLOW_MULTICAST = false;
private static String label(int code) {
switch (code) {
case PASS: return "PASS";
case DROP: return "DROP";
default: return "UNKNOWN";
}
}
private static void assertReturnCodesEqual(int expected, int got) {
assertEquals(label(expected), label(got));
}
private void assertVerdict(int expected, byte[] program, byte[] packet, int filterAge) {
assertEquals(expected, apfSimulate(program, packet, filterAge));
assertReturnCodesEqual(expected, apfSimulate(program, packet, filterAge));
}
private void assertVerdict(int expected, byte[] program, byte[] packet) {
assertReturnCodesEqual(expected, apfSimulate(program, packet, 0));
}
private void assertPass(byte[] program, byte[] packet, int filterAge) {
assertVerdict(PASS, program, packet, filterAge);
}
private void assertPass(byte[] program, byte[] packet) {
assertVerdict(PASS, program, packet);
}
private void assertDrop(byte[] program, byte[] packet, int filterAge) {
assertVerdict(DROP, program, packet, filterAge);
}
private void assertDrop(byte[] program, byte[] packet) {
assertVerdict(DROP, program, packet);
}
private void assertVerdict(int expected, ApfGenerator gen, byte[] packet, int filterAge)
throws IllegalInstructionException {
assertEquals(expected, apfSimulate(gen.generate(), packet, filterAge));
assertReturnCodesEqual(expected, apfSimulate(gen.generate(), packet, filterAge));
}
private void assertPass(ApfGenerator gen, byte[] packet, int filterAge)
@@ -516,7 +540,7 @@ public class ApfTest extends AndroidTestCase {
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
byte[] packet123 = new byte[]{0,123,0,0,0,0,0,0,0,0,0,0,0,0,0};
byte[] packet123 = {0,123,0,0,0,0,0,0,0,0,0,0,0,0,0};
assertPass(gen, packet123, 0);
gen = new ApfGenerator();
gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
@@ -524,7 +548,7 @@ public class ApfTest extends AndroidTestCase {
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,30,4,5}, gen.DROP_LABEL);
byte[] packet12345 = new byte[]{0,1,2,3,4,5,0,0,0,0,0,0,0,0,0};
byte[] packet12345 = {0,1,2,3,4,5,0,0,0,0,0,0,0,0,0};
assertDrop(gen, packet12345, 0);
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1);
@@ -575,7 +599,7 @@ public class ApfTest extends AndroidTestCase {
}
private static class TestApfFilter extends ApfFilter {
public final static byte[] MOCK_MAC_ADDR = new byte[]{1,2,3,4,5,6};
public final static byte[] MOCK_MAC_ADDR = {1,2,3,4,5,6};
private FileDescriptor mWriteSocket;
public TestApfFilter(IpManager.Callback ipManagerCallback, boolean multicastFilter,
@@ -620,19 +644,21 @@ public class ApfTest extends AndroidTestCase {
private static final int ETH_HEADER_LEN = 14;
private static final int ETH_DEST_ADDR_OFFSET = 0;
private static final int ETH_ETHERTYPE_OFFSET = 12;
private static final byte[] ETH_BROADCAST_MAC_ADDRESS = new byte[]{
(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
private static final byte[] ETH_BROADCAST_MAC_ADDRESS =
{(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
private static final int IPV4_VERSION_IHL_OFFSET = ETH_HEADER_LEN + 0;
private static final int IPV4_PROTOCOL_OFFSET = ETH_HEADER_LEN + 9;
private static final int IPV4_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 16;
private static final byte[] IPV4_BROADCAST_ADDRESS =
{(byte) 255, (byte) 255, (byte) 255, (byte) 255};
private static final int IPV6_NEXT_HEADER_OFFSET = ETH_HEADER_LEN + 6;
private static final int IPV6_HEADER_LEN = 40;
private static final int IPV6_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 24;
// The IPv6 all nodes address ff02::1
private static final byte[] IPV6_ALL_NODES_ADDRESS =
new byte[]{ (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
{ (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
private static final int ICMP6_ROUTER_ADVERTISEMENT = 134;
@@ -670,14 +696,14 @@ public class ApfTest extends AndroidTestCase {
private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 48;
private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN;
private static final byte[] ARP_IPV4_REQUEST_HEADER = new byte[]{
private static final byte[] ARP_IPV4_REQUEST_HEADER = {
0, 1, // Hardware type: Ethernet (1)
8, 0, // Protocol type: IP (0x0800)
6, // Hardware size: 6
4, // Protocol size: 4
0, 1 // Opcode: request (1)
};
private static final byte[] ARP_IPV4_REPLY_HEADER = new byte[]{
private static final byte[] ARP_IPV4_REPLY_HEADER = {
0, 1, // Hardware type: Ethernet (1)
8, 0, // Protocol type: IP (0x0800)
6, // Hardware size: 6
@@ -686,9 +712,11 @@ public class ApfTest extends AndroidTestCase {
};
private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24;
private static final byte[] MOCK_IPV4_ADDR = new byte[]{10, 0, 0, 1};
private static final byte[] ANOTHER_IPV4_ADDR = new byte[]{10, 0, 0, 2};
private static final byte[] IPV4_ANY_HOST_ADDR = new byte[]{0, 0, 0, 0};
private static final byte[] MOCK_IPV4_ADDR = {10, 0, 0, 1};
private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, (byte) 255, (byte) 255};
private static final byte[] MOCK_MULTICAST_IPV4_ADDR = {(byte) 224, 0, 0, 1};
private static final byte[] ANOTHER_IPV4_ADDR = {10, 0, 0, 2};
private static final byte[] IPV4_ANY_HOST_ADDR = {0, 0, 0, 0};
@LargeTest
public void testApfFilterIPv4() throws Exception {
@@ -698,26 +726,43 @@ public class ApfTest extends AndroidTestCase {
// Verify empty packet of 100 zero bytes is passed
ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
assertPass(program, packet.array(), 0);
assertPass(program, packet.array());
// Verify unicast IPv4 packet is passed
put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
assertPass(program, packet.array(), 0);
put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_IPV4_ADDR);
assertPass(program, packet.array());
// Verify broadcast IPv4, not DHCP to us, is dropped
packet.put(ETH_BROADCAST_MAC_ADDRESS);
assertDrop(program, packet.array(), 0);
// Verify L2 unicast to IPv4 broadcast addresses is passed (b/30231088)
put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
assertPass(program, packet.array());
put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
assertPass(program, packet.array());
// Verify multicast/broadcast IPv4, not DHCP to us, is dropped
put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
assertDrop(program, packet.array());
packet.put(IPV4_VERSION_IHL_OFFSET, (byte)0x45);
assertDrop(program, packet.array(), 0);
assertDrop(program, packet.array());
packet.put(IPV4_PROTOCOL_OFFSET, (byte)IPPROTO_UDP);
assertDrop(program, packet.array(), 0);
assertDrop(program, packet.array());
packet.putShort(UDP_DESTINATION_PORT_OFFSET, (short)DHCP_CLIENT_PORT);
assertDrop(program, packet.array(), 0);
assertDrop(program, packet.array());
put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_MULTICAST_IPV4_ADDR);
assertDrop(program, packet.array());
put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
assertDrop(program, packet.array());
put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
assertDrop(program, packet.array());
// Verify broadcast IPv4 DHCP to us is passed
packet.position(DHCP_CLIENT_MAC_OFFSET);
packet.put(TestApfFilter.MOCK_MAC_ADDR);
assertPass(program, packet.array(), 0);
put(packet, DHCP_CLIENT_MAC_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
assertPass(program, packet.array());
// Verify unicast IPv4 DHCP to us is passed
put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
assertPass(program, packet.array());
apfFilter.shutdown();
}
@@ -731,20 +776,19 @@ public class ApfTest extends AndroidTestCase {
// Verify empty IPv6 packet is passed
ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
assertPass(program, packet.array(), 0);
assertPass(program, packet.array());
// Verify empty ICMPv6 packet is passed
packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
assertPass(program, packet.array(), 0);
assertPass(program, packet.array());
// Verify empty ICMPv6 NA packet is passed
packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_NEIGHBOR_ANNOUNCEMENT);
assertPass(program, packet.array(), 0);
assertPass(program, packet.array());
// Verify ICMPv6 NA to ff02::1 is dropped
packet.position(IPV6_DEST_ADDR_OFFSET);
packet.put(IPV6_ALL_NODES_ADDRESS);
assertDrop(program, packet.array(), 0);
put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_NODES_ADDRESS);
assertDrop(program, packet.array());
apfFilter.shutdown();
}
@@ -755,58 +799,78 @@ public class ApfTest extends AndroidTestCase {
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
byte[] program = ipManagerCallback.getApfProgram();
final byte[] unicastIpv4Addr = {(byte)192,0,2,63};
final byte[] broadcastIpv4Addr = {(byte)192,0,(byte)255,(byte)255};
final byte[] multicastIpv4Addr = {(byte)224,0,0,1};
final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
// Construct IPv4 and IPv6 multicast packets.
ByteBuffer mcastv4packet = ByteBuffer.wrap(new byte[100]);
mcastv4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
mcastv4packet.position(IPV4_DEST_ADDR_OFFSET);
mcastv4packet.put(new byte[]{(byte)224,0,0,1});
put(mcastv4packet, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
ByteBuffer mcastv6packet = ByteBuffer.wrap(new byte[100]);
mcastv6packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_UDP);
mcastv6packet.position(IPV6_DEST_ADDR_OFFSET);
mcastv6packet.put(new byte[]{(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb});
put(mcastv6packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr);
// Construct IPv4 broadcast packet.
ByteBuffer bcastv4packet = ByteBuffer.wrap(new byte[100]);
bcastv4packet.put(ETH_BROADCAST_MAC_ADDRESS);
bcastv4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
bcastv4packet.position(IPV4_DEST_ADDR_OFFSET);
bcastv4packet.put(new byte[]{(byte)192,(byte)0,(byte)2,(byte)63});
ByteBuffer bcastv4packet1 = ByteBuffer.wrap(new byte[100]);
bcastv4packet1.put(ETH_BROADCAST_MAC_ADDRESS);
bcastv4packet1.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
put(bcastv4packet1, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
ByteBuffer bcastv4packet2 = ByteBuffer.wrap(new byte[100]);
bcastv4packet2.put(ETH_BROADCAST_MAC_ADDRESS);
bcastv4packet2.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
put(bcastv4packet2, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
// Construct IPv4 broadcast with L2 unicast address packet (b/30231088).
ByteBuffer bcastv4unicastl2packet = ByteBuffer.wrap(new byte[100]);
bcastv4unicastl2packet.put(TestApfFilter.MOCK_MAC_ADDR);
bcastv4unicastl2packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
put(bcastv4unicastl2packet, IPV4_DEST_ADDR_OFFSET, broadcastIpv4Addr);
// Verify initially disabled multicast filter is off
assertPass(program, bcastv4packet.array(), 0);
assertPass(program, mcastv4packet.array(), 0);
assertPass(program, mcastv6packet.array(), 0);
assertPass(program, mcastv4packet.array());
assertPass(program, mcastv6packet.array());
assertPass(program, bcastv4packet1.array());
assertPass(program, bcastv4packet2.array());
assertPass(program, bcastv4unicastl2packet.array());
// Turn on multicast filter and verify it works
ipManagerCallback.resetApfProgramWait();
apfFilter.setMulticastFilter(true);
program = ipManagerCallback.getApfProgram();
assertDrop(program, bcastv4packet.array(), 0);
assertDrop(program, mcastv4packet.array(), 0);
assertDrop(program, mcastv6packet.array(), 0);
assertDrop(program, mcastv4packet.array());
assertDrop(program, mcastv6packet.array());
assertDrop(program, bcastv4packet1.array());
assertDrop(program, bcastv4packet2.array());
assertPass(program, bcastv4unicastl2packet.array());
// Turn off multicast filter and verify it's off
ipManagerCallback.resetApfProgramWait();
apfFilter.setMulticastFilter(false);
program = ipManagerCallback.getApfProgram();
assertPass(program, bcastv4packet.array(), 0);
assertPass(program, mcastv4packet.array(), 0);
assertPass(program, mcastv6packet.array(), 0);
assertPass(program, mcastv4packet.array());
assertPass(program, mcastv6packet.array());
assertPass(program, bcastv4packet1.array());
assertPass(program, bcastv4packet2.array());
assertPass(program, bcastv4unicastl2packet.array());
// Verify it can be initialized to on
ipManagerCallback.resetApfProgramWait();
apfFilter.shutdown();
apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
program = ipManagerCallback.getApfProgram();
assertDrop(program, bcastv4packet.array(), 0);
assertDrop(program, mcastv4packet.array(), 0);
assertDrop(program, mcastv6packet.array(), 0);
assertDrop(program, mcastv4packet.array());
assertDrop(program, mcastv6packet.array());
assertDrop(program, bcastv4packet1.array());
assertPass(program, bcastv4unicastl2packet.array());
// Verify that ICMPv6 multicast is not dropped.
mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
assertPass(program, mcastv6packet.array(), 0);
assertPass(program, mcastv6packet.array());
apfFilter.shutdown();
}
@@ -819,17 +883,17 @@ public class ApfTest extends AndroidTestCase {
private void verifyArpFilter(byte[] program, int filterResult) {
// Verify ARP request packet
assertPass(program, arpRequestBroadcast(MOCK_IPV4_ADDR), 0);
assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR), 0);
assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR), 0);
assertPass(program, arpRequestBroadcast(MOCK_IPV4_ADDR));
assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR));
assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR));
// Verify unicast ARP reply packet is always accepted.
assertPass(program, arpReplyUnicast(MOCK_IPV4_ADDR), 0);
assertPass(program, arpReplyUnicast(ANOTHER_IPV4_ADDR), 0);
assertPass(program, arpReplyUnicast(IPV4_ANY_HOST_ADDR), 0);
assertPass(program, arpReplyUnicast(MOCK_IPV4_ADDR));
assertPass(program, arpReplyUnicast(ANOTHER_IPV4_ADDR));
assertPass(program, arpReplyUnicast(IPV4_ANY_HOST_ADDR));
// Verify GARP reply packets are always filtered
assertDrop(program, garpReply(), 0);
assertDrop(program, garpReply());
}
@LargeTest
@@ -855,34 +919,26 @@ public class ApfTest extends AndroidTestCase {
private static byte[] arpRequestBroadcast(byte[] tip) {
ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
packet.position(ETH_DEST_ADDR_OFFSET);
packet.put(ETH_BROADCAST_MAC_ADDRESS);
packet.position(ARP_HEADER_OFFSET);
packet.put(ARP_IPV4_REQUEST_HEADER);
packet.position(ARP_TARGET_IP_ADDRESS_OFFSET);
packet.put(tip);
put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
return packet.array();
}
private static byte[] arpReplyUnicast(byte[] tip) {
ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
packet.position(ARP_HEADER_OFFSET);
packet.put(ARP_IPV4_REPLY_HEADER);
packet.position(ARP_TARGET_IP_ADDRESS_OFFSET);
packet.put(tip);
put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
return packet.array();
}
private static byte[] garpReply() {
ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
packet.position(ETH_DEST_ADDR_OFFSET);
packet.put(ETH_BROADCAST_MAC_ADDRESS);
packet.position(ARP_HEADER_OFFSET);
packet.put(ARP_IPV4_REPLY_HEADER);
packet.position(ARP_TARGET_IP_ADDRESS_OFFSET);
packet.put(IPV4_ANY_HOST_ADDR);
put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, IPV4_ANY_HOST_ADDR);
return packet.array();
}
@@ -893,22 +949,22 @@ public class ApfTest extends AndroidTestCase {
byte[] program = ipManagerCallback.getApfProgram();
// Verify new program should drop RA for 1/6th its lifetime
assertDrop(program, packet.array(), 0);
assertDrop(program, packet.array());
assertDrop(program, packet.array(), lifetime/6);
assertPass(program, packet.array(), lifetime/6 + 1);
assertPass(program, packet.array(), lifetime);
// Verify RA checksum is ignored
packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)12345);
assertDrop(program, packet.array(), 0);
assertDrop(program, packet.array());
packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)-12345);
assertDrop(program, packet.array(), 0);
assertDrop(program, packet.array());
// Verify other changes to RA make it not match filter
packet.put(0, (byte)-1);
assertPass(program, packet.array(), 0);
assertPass(program, packet.array());
packet.put(0, (byte)0);
assertDrop(program, packet.array(), 0);
assertDrop(program, packet.array());
}
// Test that when ApfFilter is shown the given packet, it generates a program to filter it
@@ -973,7 +1029,7 @@ public class ApfTest extends AndroidTestCase {
basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short)1000);
basePacket.position(IPV6_DEST_ADDR_OFFSET);
basePacket.put(IPV6_ALL_NODES_ADDRESS);
assertPass(program, basePacket.array(), 0);
assertPass(program, basePacket.array());
testRaLifetime(apfFilter, ipManagerCallback, basePacket, 1000);
verifyRaEvent(new RaEvent(1000, -1, -1, -1, -1, -1));
@@ -1069,6 +1125,13 @@ public class ApfTest extends AndroidTestCase {
return file.getAbsolutePath();
}
private static void put(ByteBuffer buffer, int position, byte[] bytes) {
final int original = buffer.position();
buffer.position(position);
buffer.put(bytes);
buffer.position(original);
}
/**
* Call the APF interpreter the run {@code program} on {@code packet} pretending the
* filter was installed {@code filter_age} seconds ago.