Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 09a2690f authored by Lorenzo Colitti's avatar Lorenzo Colitti Committed by android-build-merger
Browse files

Merge "Support IPv6 multicast filtering in APF." into nyc-dev

am: d954c636

* commit 'd954c636':
  Support IPv6 multicast filtering in APF.

Change-Id: I6123c2390aa9641652fd200adcc16f9724799aab
parents c6a35031 d954c636
Loading
Loading
Loading
Loading
+20 −3
Original line number Diff line number Diff line
@@ -648,14 +648,31 @@ public class ApfFilter {
        // Here's a basic summary of what the IPv6 filter program does:
        //
        // if it's not ICMPv6:
        //   if it's multicast and we're dropping multicast:
        //     drop
        //   pass
        // if it's ICMPv6 NA to ff02::1:
        //   drop

        // If not ICMPv6, pass
        gen.addLoad8(Register.R0, IPV6_NEXT_HEADER_OFFSET);
        // TODO: Drop multicast if the multicast filter is enabled.

        // 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
        String skipUnsolicitedMulticastNALabel = "skipUnsolicitedMulticastNA";
        // If not neighbor announcements, skip unsolicited multicast NA filter
+28 −10
Original line number Diff line number Diff line
@@ -720,36 +720,52 @@ public class ApfTest extends AndroidTestCase {
    }

    @LargeTest
    public void testApfFilterIPv4Multicast() throws Exception {
    public void testApfFilterMulticast() throws Exception {
        MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, false /* multicastFilter */);
        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
        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
        packet.position(IPV4_DEST_ADDR_OFFSET);
        packet.put(new byte[]{(byte)224,0,0,1});
        assertPass(program, packet.array(), 0);
        assertPass(program, v4packet.array(), 0);
        assertPass(program, v6packet.array(), 0);

        // Turn on multicast filter and verify it works
        ipManagerCallback.resetApfProgramWait();
        apfFilter.setMulticastFilter(true);
        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
        ipManagerCallback.resetApfProgramWait();
        apfFilter.setMulticastFilter(false);
        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
        ipManagerCallback.resetApfProgramWait();
        apfFilter.shutdown();
        apfFilter = new TestApfFilter(ipManagerCallback, true /* multicastFilter */);
        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();
    }
@@ -839,7 +855,7 @@ public class ApfTest extends AndroidTestCase {
    @LargeTest
    public void testApfFilterRa() throws Exception {
        MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
        TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, false /* multicastFilter */);
        TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, true /* multicastFilter */);
        byte[] program = ipManagerCallback.getApfProgram();

        // 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(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_ADVERTISEMENT);
        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);

        testRaLifetime(apfFilter, ipManagerCallback, basePacket, 1000);