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

Commit d954c636 authored by Lorenzo Colitti's avatar Lorenzo Colitti Committed by Android (Google) Code Review
Browse files

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

parents eb50a39e 11e13e21
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);