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

Commit 967dec79 authored by Joel Scherpelz's avatar Joel Scherpelz
Browse files

Ignore flow label when comparing RAs in APF

This change modifies the RA filter generation code to ignore bytes 1-3
of the IPv6 header. It also updates testApfFilterRa such that it fails
without the updates to ApfFilter.

Test: as follows
        - built
        - flashed
        - booted
        - sent RAs from OS X with differing flow labels and observed
	      that they were filtered
	- ApfTest passes
Bug: 31166495

(cherry picked from commit 7006bd4fe5eba4b6fad43dd28d9cad2d26ce140a)

Change-Id: I32153238193ac13a0e59be1875d983a0567c41c7
parent 65d3a457
Loading
Loading
Loading
Loading
+22 −2
Original line number Diff line number Diff line
@@ -193,6 +193,11 @@ public class ApfFilter {
    private static final int IPV4_ANY_HOST_ADDRESS = 0;
    private static final int IPV4_BROADCAST_ADDRESS = -1; // 255.255.255.255

    // Traffic class and Flow label are not byte aligned. Luckily we
    // don't care about either value so we'll consider bytes 1-3 of the
    // IPv6 header as don't care.
    private static final int IPV6_FLOW_LABEL_OFFSET = ETH_HEADER_LEN + 1;
    private static final int IPV6_FLOW_LABEL_LEN = 3;
    private static final int IPV6_NEXT_HEADER_OFFSET = ETH_HEADER_LEN + 6;
    private static final int IPV6_SRC_ADDR_OFFSET = ETH_HEADER_LEN + 8;
    private static final int IPV6_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 24;
@@ -472,8 +477,13 @@ public class ApfFilter {

            RaEvent.Builder builder = new RaEvent.Builder();

            // Ignore the checksum.
            // Ignore the flow label and low 4 bits of traffic class.
            int lastNonLifetimeStart = addNonLifetime(0,
                    IPV6_FLOW_LABEL_OFFSET,
                    IPV6_FLOW_LABEL_LEN);

            // Ignore the checksum.
            lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
                    ICMP6_RA_CHECKSUM_OFFSET,
                    ICMP6_RA_CHECKSUM_LEN);

@@ -564,6 +574,11 @@ public class ApfFilter {
            for (int i = 0; (i + 1) < mNonLifetimes.size(); i++) {
                int offset = mNonLifetimes.get(i).first + mNonLifetimes.get(i).second;

                // The flow label is in mNonLifetimes, but it's not a lifetime.
                if (offset == IPV6_FLOW_LABEL_OFFSET) {
                    continue;
                }

                // The checksum is in mNonLifetimes, but it's not a lifetime.
                if (offset == ICMP6_RA_CHECKSUM_OFFSET) {
                    continue;
@@ -628,6 +643,11 @@ public class ApfFilter {
                if ((i + 1) < mNonLifetimes.size()) {
                    Pair<Integer, Integer> nextNonLifetime = mNonLifetimes.get(i + 1);
                    int offset = nonLifetime.first + nonLifetime.second;

                    // Skip the Flow label.
                    if (offset == IPV6_FLOW_LABEL_OFFSET) {
                        continue;
                    }
                    // Skip the checksum.
                    if (offset == ICMP6_RA_CHECKSUM_OFFSET) {
                        continue;
+13 −0
Original line number Diff line number Diff line
@@ -1066,10 +1066,15 @@ public class ApfTest extends AndroidTestCase {
        final int ROUTE_LIFETIME  = 400;
        // Note that lifetime of 2000 will be ignored in favor of shorter route lifetime of 1000.
        final int DNSSL_LIFETIME  = 2000;
        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;

        // 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);
@@ -1080,6 +1085,13 @@ public class ApfTest extends AndroidTestCase {
        testRaLifetime(apfFilter, ipManagerCallback, basePacket, ROUTER_LIFETIME);
        verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, -1));

        ByteBuffer newFlowLabelPacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
        basePacket.clear();
        newFlowLabelPacket.put(basePacket);
        // Check that changes are ignored in every byte of the flow label.
        newFlowLabelPacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
                VERSION_TRAFFIC_CLASS_FLOW_LABEL + 0x11111);

        // Ensure zero-length options cause the packet to be silently skipped.
        // Do this before we test other packets. http://b/29586253
        ByteBuffer zeroLengthOptionPacket = ByteBuffer.wrap(
@@ -1145,6 +1157,7 @@ public class ApfTest extends AndroidTestCase {
        // Verify that current program filters all five RAs:
        program = ipManagerCallback.getApfProgram();
        verifyRaLifetime(program, basePacket, ROUTER_LIFETIME);
        verifyRaLifetime(program, newFlowLabelPacket, ROUTER_LIFETIME);
        verifyRaLifetime(program, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
        verifyRaLifetime(program, rdnssOptionPacket, RDNSS_LIFETIME);
        verifyRaLifetime(program, routeInfoOptionPacket, ROUTE_LIFETIME);