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:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user