summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/net/java/android/net/apf/ApfFilter.java53
-rw-r--r--services/tests/servicestests/src/android/net/apf/ApfTest.java53
2 files changed, 59 insertions, 47 deletions
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index 538e8f879a3d..485f2f5318f4 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -597,12 +597,13 @@ public class ApfFilter {
private void generateIPv4FilterLocked(ApfGenerator gen) throws IllegalInstructionException {
// Here's a basic summary of what the IPv4 filter program does:
//
- // if it's multicast and we're dropping multicast:
- // drop
- // if it's not broadcast:
- // pass
- // if it's not DHCP destined to our MAC:
- // drop
+ // if filtering multicast (i.e. multicast lock not held):
+ // if it's multicast:
+ // drop
+ // if it's not broadcast:
+ // pass
+ // if it's not DHCP destined to our MAC:
+ // drop
// pass
if (mMulticastFilter) {
@@ -610,27 +611,27 @@ public class ApfFilter {
gen.addLoad8(Register.R0, IPV4_DEST_ADDR_OFFSET);
gen.addAnd(0xf0);
gen.addJumpIfR0Equals(0xe0, gen.DROP_LABEL);
- }
- // Drop all broadcasts besides DHCP addressed to us
- // If not a broadcast packet, pass
- gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
- gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, gen.PASS_LABEL);
- // If not UDP, drop
- gen.addLoad8(Register.R0, IPV4_PROTOCOL_OFFSET);
- gen.addJumpIfR0NotEquals(IPPROTO_UDP, gen.DROP_LABEL);
- // If fragment, drop. This matches the BPF filter installed by the DHCP client.
- gen.addLoad16(Register.R0, IPV4_FRAGMENT_OFFSET_OFFSET);
- gen.addJumpIfR0AnyBitsSet(IPV4_FRAGMENT_OFFSET_MASK, gen.DROP_LABEL);
- // If not to DHCP client port, drop
- gen.addLoadFromMemory(Register.R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
- gen.addLoad16Indexed(Register.R0, UDP_DESTINATION_PORT_OFFSET);
- gen.addJumpIfR0NotEquals(DHCP_CLIENT_PORT, gen.DROP_LABEL);
- // If not DHCP to our MAC address, drop
- gen.addLoadImmediate(Register.R0, DHCP_CLIENT_MAC_OFFSET);
- // NOTE: Relies on R1 containing IPv4 header offset.
- gen.addAddR1();
- gen.addJumpIfBytesNotEqual(Register.R0, mHardwareAddress, gen.DROP_LABEL);
+ // Drop all broadcasts besides DHCP addressed to us
+ // If not a broadcast packet, pass
+ gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
+ gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, gen.PASS_LABEL);
+ // If not UDP, drop
+ gen.addLoad8(Register.R0, IPV4_PROTOCOL_OFFSET);
+ gen.addJumpIfR0NotEquals(IPPROTO_UDP, gen.DROP_LABEL);
+ // If fragment, drop. This matches the BPF filter installed by the DHCP client.
+ gen.addLoad16(Register.R0, IPV4_FRAGMENT_OFFSET_OFFSET);
+ gen.addJumpIfR0AnyBitsSet(IPV4_FRAGMENT_OFFSET_MASK, gen.DROP_LABEL);
+ // If not to DHCP client port, drop
+ gen.addLoadFromMemory(Register.R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
+ gen.addLoad16Indexed(Register.R0, UDP_DESTINATION_PORT_OFFSET);
+ gen.addJumpIfR0NotEquals(DHCP_CLIENT_PORT, gen.DROP_LABEL);
+ // If not DHCP to our MAC address, drop
+ gen.addLoadImmediate(Register.R0, DHCP_CLIENT_MAC_OFFSET);
+ // NOTE: Relies on R1 containing IPv4 header offset.
+ gen.addAddR1();
+ gen.addJumpIfBytesNotEqual(Register.R0, mHardwareAddress, gen.DROP_LABEL);
+ }
// Otherwise, pass
gen.addJump(gen.PASS_LABEL);
diff --git a/services/tests/servicestests/src/android/net/apf/ApfTest.java b/services/tests/servicestests/src/android/net/apf/ApfTest.java
index 9e04d2301ad9..fae82ca4e7a3 100644
--- a/services/tests/servicestests/src/android/net/apf/ApfTest.java
+++ b/services/tests/servicestests/src/android/net/apf/ApfTest.java
@@ -663,7 +663,7 @@ public class ApfTest extends AndroidTestCase {
@LargeTest
public void testApfFilterIPv4() throws Exception {
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
- ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, false /* multicastFilter */);
+ ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, true /* multicastFilter */);
byte[] program = ipManagerCallback.getApfProgram();
// Verify empty packet of 100 zero bytes is passed
@@ -726,46 +726,57 @@ public class ApfTest extends AndroidTestCase {
byte[] program = ipManagerCallback.getApfProgram();
// Construct IPv4 and IPv6 multicast packets.
- ByteBuffer v4packet = ByteBuffer.wrap(new byte[100]);
- v4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
- v4packet.position(IPV4_DEST_ADDR_OFFSET);
- v4packet.put(new byte[]{(byte)224,0,0,1});
-
- ByteBuffer v6packet = ByteBuffer.wrap(new byte[100]);
- v6packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
- v6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_UDP);
- v6packet.position(IPV6_DEST_ADDR_OFFSET);
- v6packet.put(new byte[]{(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb});
+ 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});
+
+ 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});
+
+ // 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});
// Verify initially disabled multicast filter is off
- assertPass(program, v4packet.array(), 0);
- assertPass(program, v6packet.array(), 0);
+ assertPass(program, bcastv4packet.array(), 0);
+ assertPass(program, mcastv4packet.array(), 0);
+ assertPass(program, mcastv6packet.array(), 0);
// Turn on multicast filter and verify it works
ipManagerCallback.resetApfProgramWait();
apfFilter.setMulticastFilter(true);
program = ipManagerCallback.getApfProgram();
- assertDrop(program, v4packet.array(), 0);
- assertDrop(program, v6packet.array(), 0);
+ assertDrop(program, bcastv4packet.array(), 0);
+ assertDrop(program, mcastv4packet.array(), 0);
+ assertDrop(program, mcastv6packet.array(), 0);
// Turn off multicast filter and verify it's off
ipManagerCallback.resetApfProgramWait();
apfFilter.setMulticastFilter(false);
program = ipManagerCallback.getApfProgram();
- assertPass(program, v4packet.array(), 0);
- assertPass(program, v6packet.array(), 0);
+ assertPass(program, bcastv4packet.array(), 0);
+ assertPass(program, mcastv4packet.array(), 0);
+ assertPass(program, mcastv6packet.array(), 0);
// Verify it can be initialized to on
ipManagerCallback.resetApfProgramWait();
apfFilter.shutdown();
apfFilter = new TestApfFilter(ipManagerCallback, true /* multicastFilter */);
program = ipManagerCallback.getApfProgram();
- assertDrop(program, v4packet.array(), 0);
- assertDrop(program, v6packet.array(), 0);
+ assertDrop(program, bcastv4packet.array(), 0);
+ assertDrop(program, mcastv4packet.array(), 0);
+ assertDrop(program, mcastv6packet.array(), 0);
// Verify that ICMPv6 multicast is not dropped.
- v6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
- assertPass(program, v6packet.array(), 0);
+ mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
+ assertPass(program, mcastv6packet.array(), 0);
apfFilter.shutdown();
}