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

Commit dfc4f7c2 authored by Lorenzo Colitti's avatar Lorenzo Colitti Committed by Gerrit Code Review
Browse files

Merge "Fix RAs with different retansmission timer would be dropped by apf"

parents c4f88900 e17d9966
Loading
Loading
Loading
Loading
+6 −5
Original line number Diff line number Diff line
@@ -514,9 +514,9 @@ public class ApfFilter {
        public final Type type;
        /** Offset into the packet at which this section begins. */
        public final int start;
        /** Length of this section. */
        /** Length of this section in bytes. */
        public final int length;
        /** If this is a lifetime, the ICMP option that the defined it. 0 for router lifetime. */
        /** If this is a lifetime, the ICMP option that defined it. 0 for router lifetime. */
        public final int option;
        /** If this is a lifetime, the lifetime value. */
        public final long lifetime;
@@ -785,8 +785,9 @@ public class ApfFilter {
            addLifetimeSection(ICMP6_RA_ROUTER_LIFETIME_LEN, 0, routerLifetime);
            builder.updateRouterLifetime(routerLifetime);

            // Ensures that the RA is not truncated.
            mPacket.position(ICMP6_RA_OPTION_OFFSET);
            // Add remaining fields (reachable time and retransmission timer) to match section.
            addMatchUntil(ICMP6_RA_OPTION_OFFSET);

            while (mPacket.hasRemaining()) {
                final int position = mPacket.position();
                final int optionType = getUint8(mPacket, position);
@@ -797,7 +798,7 @@ public class ApfFilter {
                        mPrefixOptionOffsets.add(position);

                        // Parse valid lifetime
                        addMatchSection(ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN);
                        addMatchSection(ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET);
                        lifetime = getUint32(mPacket, mPacket.position());
                        addLifetimeSection(ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN,
                                ICMP6_PREFIX_OPTION_TYPE, lifetime);
+76 −11
Original line number Diff line number Diff line
@@ -1056,10 +1056,14 @@ public class ApfTest {
    private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;

    private static final int ICMP6_RA_HEADER_LEN = 16;
    private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET =
            IP_HEADER_OFFSET + IPV6_HEADER_LEN + 6;
    private static final int ICMP6_RA_CHECKSUM_OFFSET =
            IP_HEADER_OFFSET + IPV6_HEADER_LEN + 2;
    private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET =
            IP_HEADER_OFFSET + IPV6_HEADER_LEN + 6;
    private static final int ICMP6_RA_REACHABLE_TIME_OFFSET =
            IP_HEADER_OFFSET + IPV6_HEADER_LEN + 8;
    private static final int ICMP6_RA_RETRANSMISSION_TIMER_OFFSET =
            IP_HEADER_OFFSET + IPV6_HEADER_LEN + 12;
    private static final int ICMP6_RA_OPTION_OFFSET =
            IP_HEADER_OFFSET + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN;

@@ -2000,6 +2004,25 @@ public class ApfTest {
        ipClientCallback.assertNoProgramUpdate();
    }

    private ByteBuffer makeBaseRaPacket() {
        ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
        final int ROUTER_LIFETIME = 1000;
        final int VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET = ETH_HEADER_LEN;
        // IPv6, traffic class = 0, flow label = 0x12345
        final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345;

        basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IPV6);
        basePacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
                VERSION_TRAFFIC_CLASS_FLOW_LABEL);
        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) ROUTER_LIFETIME);
        basePacket.position(IPV6_DEST_ADDR_OFFSET);
        basePacket.put(IPV6_ALL_NODES_ADDRESS);

        return basePacket;
    }

    @Test
    public void testApfFilterRa() throws Exception {
        MockIpClientCallback ipClientCallback = new MockIpClientCallback();
@@ -2021,15 +2044,7 @@ public class ApfTest {
        final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345;

        // Verify RA is passed the first time
        ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
        basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
        basePacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
                VERSION_TRAFFIC_CLASS_FLOW_LABEL);
        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)ROUTER_LIFETIME);
        basePacket.position(IPV6_DEST_ADDR_OFFSET);
        basePacket.put(IPV6_ALL_NODES_ADDRESS);
        ByteBuffer basePacket = makeBaseRaPacket();
        assertPass(program, basePacket.array());

        verifyRaLifetime(apfFilter, ipClientCallback, basePacket, ROUTER_LIFETIME);
@@ -2083,6 +2098,16 @@ public class ApfTest {
        verifyRaLifetime(apfFilter, ipClientCallback, routeInfoOptionPacket, ROUTE_LIFETIME);
        verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, ROUTE_LIFETIME, -1, -1));

        // Check that RIOs differing only in the first 4 bytes are different.
        ByteBuffer similarRouteInfoOptionPacket = ByteBuffer.wrap(
                new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN + IPV6_ADDR_LEN]);
        basePacket.clear();
        similarRouteInfoOptionPacket.put(basePacket);
        addRioOption(similarRouteInfoOptionPacket, ROUTE_LIFETIME, "64:ff9b::/64");
        // Packet should be passed because it is different.
        program = ipClientCallback.getApfProgram();
        assertPass(program, similarRouteInfoOptionPacket.array());

        ByteBuffer dnsslOptionPacket = ByteBuffer.wrap(
                new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
        basePacket.clear();
@@ -2111,6 +2136,46 @@ public class ApfTest {
        apfFilter.shutdown();
    }

    @Test
    public void testRaWithDifferentReachableTimeAndRetransTimer() throws Exception {
        final MockIpClientCallback ipClientCallback = new MockIpClientCallback();
        final ApfConfiguration config = getDefaultConfig();
        config.multicastFilter = DROP_MULTICAST;
        config.ieee802_3Filter = DROP_802_3_FRAMES;
        final TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
        byte[] program = ipClientCallback.getApfProgram();
        final int RA_REACHABLE_TIME = 1800;
        final int RA_RETRANSMISSION_TIMER = 1234;

        // Create an Ra packet without options
        // Reachable time = 1800, retransmission timer = 1234
        ByteBuffer raPacket = makeBaseRaPacket();
        raPacket.position(ICMP6_RA_REACHABLE_TIME_OFFSET);
        raPacket.putInt(RA_REACHABLE_TIME);
        raPacket.putInt(RA_RETRANSMISSION_TIMER);
        // First RA passes filter
        assertPass(program, raPacket.array());

        // Assume apf is shown the given RA, it generates program to filter it.
        ipClientCallback.resetApfProgramWait();
        apfFilter.pretendPacketReceived(raPacket.array());
        program = ipClientCallback.getApfProgram();
        assertDrop(program, raPacket.array());

        // A packet with different reachable time should be passed.
        // Reachable time = 2300, retransmission timer = 1234
        raPacket.clear();
        raPacket.putInt(ICMP6_RA_REACHABLE_TIME_OFFSET, RA_REACHABLE_TIME + 500);
        assertPass(program, raPacket.array());

        // A packet with different retransmission timer should be passed.
        // Reachable time = 1800, retransmission timer = 2234
        raPacket.clear();
        raPacket.putInt(ICMP6_RA_REACHABLE_TIME_OFFSET, RA_REACHABLE_TIME);
        raPacket.putInt(ICMP6_RA_RETRANSMISSION_TIMER_OFFSET, RA_RETRANSMISSION_TIMER + 1000);
        assertPass(program, raPacket.array());
    }

    /**
     * Stage a file for testing, i.e. make it native accessible. Given a resource ID,
     * copy that resource into the app's data directory and return the path to it.