Merge "Support IPv6 multicast filtering in APF." into nyc-dev am: d954c6368f
am: 50282f0cb7
* commit '50282f0cb7bbdd117cb31db3b127adb0f4f196a0':
Support IPv6 multicast filtering in APF.
Change-Id: I58cb62ff0bb5304d614b8eb61da148c6a5d94bed
This commit is contained in:
@@ -648,14 +648,31 @@ public class ApfFilter {
|
|||||||
// Here's a basic summary of what the IPv6 filter program does:
|
// Here's a basic summary of what the IPv6 filter program does:
|
||||||
//
|
//
|
||||||
// if it's not ICMPv6:
|
// if it's not ICMPv6:
|
||||||
|
// if it's multicast and we're dropping multicast:
|
||||||
|
// drop
|
||||||
// pass
|
// pass
|
||||||
// if it's ICMPv6 NA to ff02::1:
|
// if it's ICMPv6 NA to ff02::1:
|
||||||
// drop
|
// drop
|
||||||
|
|
||||||
// If not ICMPv6, pass
|
|
||||||
gen.addLoad8(Register.R0, IPV6_NEXT_HEADER_OFFSET);
|
gen.addLoad8(Register.R0, IPV6_NEXT_HEADER_OFFSET);
|
||||||
// TODO: Drop multicast if the multicast filter is enabled.
|
|
||||||
gen.addJumpIfR0NotEquals(IPPROTO_ICMPV6, gen.PASS_LABEL);
|
// Drop multicast if the multicast filter is enabled.
|
||||||
|
if (mMulticastFilter) {
|
||||||
|
// Don't touch ICMPv6 multicast here, we deal with it in more detail later.
|
||||||
|
String skipIpv6MulticastFilterLabel = "skipIPv6MulticastFilter";
|
||||||
|
gen.addJumpIfR0Equals(IPPROTO_ICMPV6, skipIpv6MulticastFilterLabel);
|
||||||
|
|
||||||
|
// Drop all other packets sent to ff00::/8.
|
||||||
|
gen.addLoad8(Register.R0, IPV6_DEST_ADDR_OFFSET);
|
||||||
|
gen.addJumpIfR0Equals(0xff, gen.DROP_LABEL);
|
||||||
|
// Not multicast and not ICMPv6. Pass.
|
||||||
|
gen.addJump(gen.PASS_LABEL);
|
||||||
|
gen.defineLabel(skipIpv6MulticastFilterLabel);
|
||||||
|
} else {
|
||||||
|
// If not ICMPv6, pass.
|
||||||
|
gen.addJumpIfR0NotEquals(IPPROTO_ICMPV6, gen.PASS_LABEL);
|
||||||
|
}
|
||||||
|
|
||||||
// Add unsolicited multicast neighbor announcements filter
|
// Add unsolicited multicast neighbor announcements filter
|
||||||
String skipUnsolicitedMulticastNALabel = "skipUnsolicitedMulticastNA";
|
String skipUnsolicitedMulticastNALabel = "skipUnsolicitedMulticastNA";
|
||||||
// If not neighbor announcements, skip unsolicited multicast NA filter
|
// If not neighbor announcements, skip unsolicited multicast NA filter
|
||||||
|
|||||||
@@ -720,36 +720,52 @@ public class ApfTest extends AndroidTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@LargeTest
|
@LargeTest
|
||||||
public void testApfFilterIPv4Multicast() throws Exception {
|
public void testApfFilterMulticast() throws Exception {
|
||||||
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
|
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
|
||||||
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, false /* multicastFilter */);
|
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, false /* multicastFilter */);
|
||||||
byte[] program = ipManagerCallback.getApfProgram();
|
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});
|
||||||
|
|
||||||
// Verify initially disabled multicast filter is off
|
// Verify initially disabled multicast filter is off
|
||||||
ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
|
assertPass(program, v4packet.array(), 0);
|
||||||
packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
|
assertPass(program, v6packet.array(), 0);
|
||||||
packet.position(IPV4_DEST_ADDR_OFFSET);
|
|
||||||
packet.put(new byte[]{(byte)224,0,0,1});
|
|
||||||
assertPass(program, packet.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, packet.array(), 0);
|
assertDrop(program, v4packet.array(), 0);
|
||||||
|
assertDrop(program, v6packet.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, packet.array(), 0);
|
assertPass(program, v4packet.array(), 0);
|
||||||
|
assertPass(program, v6packet.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, packet.array(), 0);
|
assertDrop(program, v4packet.array(), 0);
|
||||||
|
assertDrop(program, v6packet.array(), 0);
|
||||||
|
|
||||||
|
// Verify that ICMPv6 multicast is not dropped.
|
||||||
|
v6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
|
||||||
|
assertPass(program, v6packet.array(), 0);
|
||||||
|
|
||||||
apfFilter.shutdown();
|
apfFilter.shutdown();
|
||||||
}
|
}
|
||||||
@@ -839,7 +855,7 @@ public class ApfTest extends AndroidTestCase {
|
|||||||
@LargeTest
|
@LargeTest
|
||||||
public void testApfFilterRa() throws Exception {
|
public void testApfFilterRa() throws Exception {
|
||||||
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
|
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
|
||||||
TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, false /* multicastFilter */);
|
TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, true /* multicastFilter */);
|
||||||
byte[] program = ipManagerCallback.getApfProgram();
|
byte[] program = ipManagerCallback.getApfProgram();
|
||||||
|
|
||||||
// Verify RA is passed the first time
|
// Verify RA is passed the first time
|
||||||
@@ -848,6 +864,8 @@ public class ApfTest extends AndroidTestCase {
|
|||||||
basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
|
basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
|
||||||
basePacket.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_ADVERTISEMENT);
|
basePacket.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_ADVERTISEMENT);
|
||||||
basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short)1000);
|
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(), 0);
|
||||||
|
|
||||||
testRaLifetime(apfFilter, ipManagerCallback, basePacket, 1000);
|
testRaLifetime(apfFilter, ipManagerCallback, basePacket, 1000);
|
||||||
|
|||||||
Reference in New Issue
Block a user