Merge "Don\'t drop IPv4 broadcast packets when WiFi multicast lock is held" into nyc-dev am: 83e50327fc
am: ae8f345d15
* commit 'ae8f345d155a9aa29bce107c6675e2da8ed61a8b':
Don't drop IPv4 broadcast packets when WiFi multicast lock is held
Change-Id: I5b544fe6e52a41d508932c2747294b20862d7ffe
This commit is contained in:
@@ -597,12 +597,13 @@ public class ApfFilter {
|
|||||||
private void generateIPv4FilterLocked(ApfGenerator gen) throws IllegalInstructionException {
|
private void generateIPv4FilterLocked(ApfGenerator gen) throws IllegalInstructionException {
|
||||||
// Here's a basic summary of what the IPv4 filter program does:
|
// Here's a basic summary of what the IPv4 filter program does:
|
||||||
//
|
//
|
||||||
// if it's multicast and we're dropping multicast:
|
// if filtering multicast (i.e. multicast lock not held):
|
||||||
// drop
|
// if it's multicast:
|
||||||
// if it's not broadcast:
|
// drop
|
||||||
// pass
|
// if it's not broadcast:
|
||||||
// if it's not DHCP destined to our MAC:
|
// pass
|
||||||
// drop
|
// if it's not DHCP destined to our MAC:
|
||||||
|
// drop
|
||||||
// pass
|
// pass
|
||||||
|
|
||||||
if (mMulticastFilter) {
|
if (mMulticastFilter) {
|
||||||
@@ -610,27 +611,27 @@ public class ApfFilter {
|
|||||||
gen.addLoad8(Register.R0, IPV4_DEST_ADDR_OFFSET);
|
gen.addLoad8(Register.R0, IPV4_DEST_ADDR_OFFSET);
|
||||||
gen.addAnd(0xf0);
|
gen.addAnd(0xf0);
|
||||||
gen.addJumpIfR0Equals(0xe0, gen.DROP_LABEL);
|
gen.addJumpIfR0Equals(0xe0, gen.DROP_LABEL);
|
||||||
}
|
|
||||||
|
|
||||||
// Drop all broadcasts besides DHCP addressed to us
|
// Drop all broadcasts besides DHCP addressed to us
|
||||||
// If not a broadcast packet, pass
|
// If not a broadcast packet, pass
|
||||||
gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
|
gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
|
||||||
gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, gen.PASS_LABEL);
|
gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, gen.PASS_LABEL);
|
||||||
// If not UDP, drop
|
// If not UDP, drop
|
||||||
gen.addLoad8(Register.R0, IPV4_PROTOCOL_OFFSET);
|
gen.addLoad8(Register.R0, IPV4_PROTOCOL_OFFSET);
|
||||||
gen.addJumpIfR0NotEquals(IPPROTO_UDP, gen.DROP_LABEL);
|
gen.addJumpIfR0NotEquals(IPPROTO_UDP, gen.DROP_LABEL);
|
||||||
// If fragment, drop. This matches the BPF filter installed by the DHCP client.
|
// If fragment, drop. This matches the BPF filter installed by the DHCP client.
|
||||||
gen.addLoad16(Register.R0, IPV4_FRAGMENT_OFFSET_OFFSET);
|
gen.addLoad16(Register.R0, IPV4_FRAGMENT_OFFSET_OFFSET);
|
||||||
gen.addJumpIfR0AnyBitsSet(IPV4_FRAGMENT_OFFSET_MASK, gen.DROP_LABEL);
|
gen.addJumpIfR0AnyBitsSet(IPV4_FRAGMENT_OFFSET_MASK, gen.DROP_LABEL);
|
||||||
// If not to DHCP client port, drop
|
// If not to DHCP client port, drop
|
||||||
gen.addLoadFromMemory(Register.R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
|
gen.addLoadFromMemory(Register.R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
|
||||||
gen.addLoad16Indexed(Register.R0, UDP_DESTINATION_PORT_OFFSET);
|
gen.addLoad16Indexed(Register.R0, UDP_DESTINATION_PORT_OFFSET);
|
||||||
gen.addJumpIfR0NotEquals(DHCP_CLIENT_PORT, gen.DROP_LABEL);
|
gen.addJumpIfR0NotEquals(DHCP_CLIENT_PORT, gen.DROP_LABEL);
|
||||||
// If not DHCP to our MAC address, drop
|
// If not DHCP to our MAC address, drop
|
||||||
gen.addLoadImmediate(Register.R0, DHCP_CLIENT_MAC_OFFSET);
|
gen.addLoadImmediate(Register.R0, DHCP_CLIENT_MAC_OFFSET);
|
||||||
// NOTE: Relies on R1 containing IPv4 header offset.
|
// NOTE: Relies on R1 containing IPv4 header offset.
|
||||||
gen.addAddR1();
|
gen.addAddR1();
|
||||||
gen.addJumpIfBytesNotEqual(Register.R0, mHardwareAddress, gen.DROP_LABEL);
|
gen.addJumpIfBytesNotEqual(Register.R0, mHardwareAddress, gen.DROP_LABEL);
|
||||||
|
}
|
||||||
|
|
||||||
// Otherwise, pass
|
// Otherwise, pass
|
||||||
gen.addJump(gen.PASS_LABEL);
|
gen.addJump(gen.PASS_LABEL);
|
||||||
|
|||||||
@@ -663,7 +663,7 @@ public class ApfTest extends AndroidTestCase {
|
|||||||
@LargeTest
|
@LargeTest
|
||||||
public void testApfFilterIPv4() throws Exception {
|
public void testApfFilterIPv4() throws Exception {
|
||||||
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
|
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
|
||||||
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, false /* multicastFilter */);
|
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, true /* multicastFilter */);
|
||||||
byte[] program = ipManagerCallback.getApfProgram();
|
byte[] program = ipManagerCallback.getApfProgram();
|
||||||
|
|
||||||
// Verify empty packet of 100 zero bytes is passed
|
// Verify empty packet of 100 zero bytes is passed
|
||||||
@@ -726,46 +726,57 @@ public class ApfTest extends AndroidTestCase {
|
|||||||
byte[] program = ipManagerCallback.getApfProgram();
|
byte[] program = ipManagerCallback.getApfProgram();
|
||||||
|
|
||||||
// Construct IPv4 and IPv6 multicast packets.
|
// Construct IPv4 and IPv6 multicast packets.
|
||||||
ByteBuffer v4packet = ByteBuffer.wrap(new byte[100]);
|
ByteBuffer mcastv4packet = ByteBuffer.wrap(new byte[100]);
|
||||||
v4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
|
mcastv4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
|
||||||
v4packet.position(IPV4_DEST_ADDR_OFFSET);
|
mcastv4packet.position(IPV4_DEST_ADDR_OFFSET);
|
||||||
v4packet.put(new byte[]{(byte)224,0,0,1});
|
mcastv4packet.put(new byte[]{(byte)224,0,0,1});
|
||||||
|
|
||||||
ByteBuffer v6packet = ByteBuffer.wrap(new byte[100]);
|
ByteBuffer mcastv6packet = ByteBuffer.wrap(new byte[100]);
|
||||||
v6packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
|
mcastv6packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
|
||||||
v6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_UDP);
|
mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_UDP);
|
||||||
v6packet.position(IPV6_DEST_ADDR_OFFSET);
|
mcastv6packet.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});
|
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
|
// Verify initially disabled multicast filter is off
|
||||||
assertPass(program, v4packet.array(), 0);
|
assertPass(program, bcastv4packet.array(), 0);
|
||||||
assertPass(program, v6packet.array(), 0);
|
assertPass(program, mcastv4packet.array(), 0);
|
||||||
|
assertPass(program, mcastv6packet.array(), 0);
|
||||||
|
|
||||||
// Turn on multicast filter and verify it works
|
// Turn on multicast filter and verify it works
|
||||||
ipManagerCallback.resetApfProgramWait();
|
ipManagerCallback.resetApfProgramWait();
|
||||||
apfFilter.setMulticastFilter(true);
|
apfFilter.setMulticastFilter(true);
|
||||||
program = ipManagerCallback.getApfProgram();
|
program = ipManagerCallback.getApfProgram();
|
||||||
assertDrop(program, v4packet.array(), 0);
|
assertDrop(program, bcastv4packet.array(), 0);
|
||||||
assertDrop(program, v6packet.array(), 0);
|
assertDrop(program, mcastv4packet.array(), 0);
|
||||||
|
assertDrop(program, mcastv6packet.array(), 0);
|
||||||
|
|
||||||
// Turn off multicast filter and verify it's off
|
// Turn off multicast filter and verify it's off
|
||||||
ipManagerCallback.resetApfProgramWait();
|
ipManagerCallback.resetApfProgramWait();
|
||||||
apfFilter.setMulticastFilter(false);
|
apfFilter.setMulticastFilter(false);
|
||||||
program = ipManagerCallback.getApfProgram();
|
program = ipManagerCallback.getApfProgram();
|
||||||
assertPass(program, v4packet.array(), 0);
|
assertPass(program, bcastv4packet.array(), 0);
|
||||||
assertPass(program, v6packet.array(), 0);
|
assertPass(program, mcastv4packet.array(), 0);
|
||||||
|
assertPass(program, mcastv6packet.array(), 0);
|
||||||
|
|
||||||
// Verify it can be initialized to on
|
// Verify it can be initialized to on
|
||||||
ipManagerCallback.resetApfProgramWait();
|
ipManagerCallback.resetApfProgramWait();
|
||||||
apfFilter.shutdown();
|
apfFilter.shutdown();
|
||||||
apfFilter = new TestApfFilter(ipManagerCallback, true /* multicastFilter */);
|
apfFilter = new TestApfFilter(ipManagerCallback, true /* multicastFilter */);
|
||||||
program = ipManagerCallback.getApfProgram();
|
program = ipManagerCallback.getApfProgram();
|
||||||
assertDrop(program, v4packet.array(), 0);
|
assertDrop(program, bcastv4packet.array(), 0);
|
||||||
assertDrop(program, v6packet.array(), 0);
|
assertDrop(program, mcastv4packet.array(), 0);
|
||||||
|
assertDrop(program, mcastv6packet.array(), 0);
|
||||||
|
|
||||||
// Verify that ICMPv6 multicast is not dropped.
|
// Verify that ICMPv6 multicast is not dropped.
|
||||||
v6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
|
mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
|
||||||
assertPass(program, v6packet.array(), 0);
|
assertPass(program, mcastv6packet.array(), 0);
|
||||||
|
|
||||||
apfFilter.shutdown();
|
apfFilter.shutdown();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user