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

Commit d27a6d62 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Add Configuration to APF Policy"

parents 826eafd9 8537c58c
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -288,6 +288,11 @@
    <!-- Mask to use when checking skb mark defined in config_networkWakeupPacketMark above. -->
    <integer name="config_networkWakeupPacketMask">0</integer>

    <!-- Whether the APF Filter in the device should filter out IEEE 802.3 Frames
         Those frames are identified by the field Eth-type having values
         less than 0x600 -->
    <bool translatable="false" name="config_apfDrop802_3Frames">true</bool>

    <!-- Default value for ConnectivityManager.getMultipathPreference() on metered networks. Actual
         device behaviour is controlled by Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE.
         This is the default value of that setting. -->
+1 −0
Original line number Diff line number Diff line
@@ -1790,6 +1790,7 @@
  <java-symbol type="integer" name="config_networkAvoidBadWifi" />
  <java-symbol type="integer" name="config_networkWakeupPacketMark" />
  <java-symbol type="integer" name="config_networkWakeupPacketMask" />
  <java-symbol type="bool" name="config_apfDrop802_3Frames" />
  <java-symbol type="integer" name="config_networkMeteredMultipathPreference" />
  <java-symbol type="integer" name="config_notificationsBatteryFullARGB" />
  <java-symbol type="integer" name="config_notificationsBatteryLedOff" />
+18 −4
Original line number Diff line number Diff line
@@ -181,6 +181,7 @@ public class ApfFilter {
    private static final int ETH_HEADER_LEN = 14;
    private static final int ETH_DEST_ADDR_OFFSET = 0;
    private static final int ETH_ETHERTYPE_OFFSET = 12;
    private static final int ETH_TYPE_MIN = 0x0600;
    private static final byte[] ETH_BROADCAST_MAC_ADDRESS =
            {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
    // TODO: Make these offsets relative to end of link-layer header; don't include ETH_HEADER_LEN.
@@ -236,6 +237,7 @@ public class ApfFilter {
    private final IpManager.Callback mIpManagerCallback;
    private final NetworkInterface mNetworkInterface;
    private final IpConnectivityLog mMetricsLog;

    @VisibleForTesting
    byte[] mHardwareAddress;
    @VisibleForTesting
@@ -244,6 +246,7 @@ public class ApfFilter {
    private long mUniqueCounter;
    @GuardedBy("this")
    private boolean mMulticastFilter;
    private final boolean mDrop802_3Frames;
    // Our IPv4 address, if we have just one, otherwise null.
    @GuardedBy("this")
    private byte[] mIPv4Address;
@@ -253,11 +256,13 @@ public class ApfFilter {

    @VisibleForTesting
    ApfFilter(ApfCapabilities apfCapabilities, NetworkInterface networkInterface,
            IpManager.Callback ipManagerCallback, boolean multicastFilter, IpConnectivityLog log) {
            IpManager.Callback ipManagerCallback, boolean multicastFilter,
            boolean ieee802_3Filter, IpConnectivityLog log) {
        mApfCapabilities = apfCapabilities;
        mIpManagerCallback = ipManagerCallback;
        mNetworkInterface = networkInterface;
        mMulticastFilter = multicastFilter;
        mDrop802_3Frames = ieee802_3Filter;
        mMetricsLog = log;

        maybeStartFilter();
@@ -879,6 +884,7 @@ public class ApfFilter {
    /**
     * Begin generating an APF program to:
     * <ul>
     * <li>Drop/Pass 802.3 frames (based on policy)
     * <li>Drop ARP requests not for us, if mIPv4Address is set,
     * <li>Drop IPv4 broadcast packets, except DHCP destined to our MAC,
     * <li>Drop IPv4 multicast packets, if mMulticastFilter,
@@ -900,6 +906,8 @@ public class ApfFilter {

        // Here's a basic summary of what the initial program does:
        //
        // if it's a 802.3 Frame (ethtype < 0x0600):
        //    drop or pass based on configurations
        // if it's ARP:
        //   insert ARP filter to drop or pass these appropriately
        // if it's IPv4:
@@ -910,9 +918,15 @@ public class ApfFilter {
        //   pass
        // insert IPv6 filter to drop, pass, or fall off the end for ICMPv6 packets

        gen.addLoad16(Register.R0, ETH_ETHERTYPE_OFFSET);

        if (mDrop802_3Frames) {
            // drop 802.3 frames (ethtype < 0x0600)
            gen.addJumpIfR0LessThan(ETH_TYPE_MIN, gen.DROP_LABEL);
        }

        // Add ARP filters:
        String skipArpFiltersLabel = "skipArpFilters";
        gen.addLoad16(Register.R0, ETH_ETHERTYPE_OFFSET);
        gen.addJumpIfR0NotEquals(ETH_P_ARP, skipArpFiltersLabel);
        generateArpFilterLocked(gen);
        gen.defineLabel(skipArpFiltersLabel);
@@ -1077,7 +1091,7 @@ public class ApfFilter {
     */
    public static ApfFilter maybeCreate(ApfCapabilities apfCapabilities,
            NetworkInterface networkInterface, IpManager.Callback ipManagerCallback,
            boolean multicastFilter) {
            boolean multicastFilter, boolean ieee802_3Filter) {
        if (apfCapabilities == null || networkInterface == null) return null;
        if (apfCapabilities.apfVersionSupported == 0) return null;
        if (apfCapabilities.maximumApfProgramSize < 512) {
@@ -1094,7 +1108,7 @@ public class ApfFilter {
            return null;
        }
        return new ApfFilter(apfCapabilities, networkInterface, ipManagerCallback,
                multicastFilter, new IpConnectivityLog());
                multicastFilter, ieee802_3Filter, new IpConnectivityLog());
    }

    public synchronized void shutdown() {
+6 −1
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import android.util.Log;
import android.util.SparseArray;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.R;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.IState;
import com.android.internal.util.Preconditions;
@@ -1418,8 +1419,12 @@ public class IpManager extends StateMachine {

        @Override
        public void enter() {
            // Get the Configuration for ApfFilter from Context
            boolean filter802_3Frames =
                    mContext.getResources().getBoolean(R.bool.config_apfDrop802_3Frames);

            mApfFilter = ApfFilter.maybeCreate(mConfiguration.mApfCapabilities, mNetworkInterface,
                    mCallback, mMulticastFiltering);
                    mCallback, mMulticastFiltering, filter802_3Frames);
            // TODO: investigate the effects of any multicast filtering racing/interfering with the
            // rest of this IP configuration startup.
            if (mApfFilter == null) {
+71 −10
Original line number Diff line number Diff line
@@ -92,6 +92,9 @@ public class ApfTest extends AndroidTestCase {
    private final static boolean DROP_MULTICAST = true;
    private final static boolean ALLOW_MULTICAST = false;

    private final static boolean DROP_802_3_FRAMES = true;
    private final static boolean ALLOW_802_3_FRAMES = false;

    private static String label(int code) {
        switch (code) {
            case PASS: return "PASS";
@@ -611,9 +614,9 @@ public class ApfTest extends AndroidTestCase {
        private final long mFixedTimeMs = SystemClock.elapsedRealtime();

        public TestApfFilter(IpManager.Callback ipManagerCallback, boolean multicastFilter,
                IpConnectivityLog log) throws Exception {
                boolean ieee802_3Filter, IpConnectivityLog log) throws Exception {
            super(new ApfCapabilities(2, 1700, ARPHRD_ETHER), NetworkInterface.getByName("lo"),
                    ipManagerCallback, multicastFilter, log);
                    ipManagerCallback, multicastFilter, ieee802_3Filter, log);
        }

        // Pretend an RA packet has been received and show it to ApfFilter.
@@ -742,7 +745,8 @@ public class ApfTest extends AndroidTestCase {
        LinkProperties lp = new LinkProperties();
        lp.addLinkAddress(link);

        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST,
                ALLOW_802_3_FRAMES, mLog);
        apfFilter.setLinkProperties(lp);

        byte[] program = ipManagerCallback.getApfProgram();
@@ -793,7 +797,8 @@ public class ApfTest extends AndroidTestCase {
    @SmallTest
    public void testApfFilterIPv6() throws Exception {
        MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
                ALLOW_802_3_FRAMES, mLog);
        byte[] program = ipManagerCallback.getApfProgram();

        // Verify empty IPv6 packet is passed
@@ -834,7 +839,8 @@ public class ApfTest extends AndroidTestCase {
        LinkProperties lp = new LinkProperties();
        lp.addLinkAddress(link);

        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
                DROP_802_3_FRAMES, mLog);
        apfFilter.setLinkProperties(lp);

        byte[] program = ipManagerCallback.getApfProgram();
@@ -896,7 +902,8 @@ public class ApfTest extends AndroidTestCase {
        // Verify it can be initialized to on
        ipManagerCallback.resetApfProgramWait();
        apfFilter.shutdown();
        apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
        apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST,
                DROP_802_3_FRAMES, mLog);
        apfFilter.setLinkProperties(lp);
        program = ipManagerCallback.getApfProgram();
        assertDrop(program, mcastv4packet.array());
@@ -911,6 +918,56 @@ public class ApfTest extends AndroidTestCase {
        apfFilter.shutdown();
    }

    @SmallTest
    public void testApfFilter802_3() throws Exception {
        MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
        LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
        LinkProperties lp = new LinkProperties();
        lp.addLinkAddress(link);

        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
                ALLOW_802_3_FRAMES, mLog);
        apfFilter.setLinkProperties(lp);

        byte[] program = ipManagerCallback.getApfProgram();

        // Verify empty packet of 100 zero bytes is passed
        // Note that eth-type = 0 makes it an IEEE802.3 frame
        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
        assertPass(program, packet.array());

        // Verify empty packet with IPv4 is passed
        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
        assertPass(program, packet.array());

        // Verify empty IPv6 packet is passed
        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
        assertPass(program, packet.array());

        // Now turn on the filter
        ipManagerCallback.resetApfProgramWait();
        apfFilter.shutdown();
        apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
                DROP_802_3_FRAMES, mLog);
        apfFilter.setLinkProperties(lp);
        program = ipManagerCallback.getApfProgram();

        // Verify that IEEE802.3 frame is dropped
        // In this case ethtype is used for payload length
        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)(100 - 14));
        assertDrop(program, packet.array());

        // Verify that IPv4 (as example of Ethernet II) frame will pass
        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
        assertPass(program, packet.array());

        // Verify that IPv6 (as example of Ethernet II) frame will pass
        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
        assertPass(program, packet.array());

        apfFilter.shutdown();
    }

    private byte[] getProgram(MockIpManagerCallback cb, ApfFilter filter, LinkProperties lp) {
        cb.resetApfProgramWait();
        filter.setLinkProperties(lp);
@@ -935,7 +992,8 @@ public class ApfTest extends AndroidTestCase {
    @SmallTest
    public void testApfFilterArp() throws Exception {
        MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
                DROP_802_3_FRAMES, mLog);

        // Verify initially ARP request filter is off, and GARP filter is on.
        verifyArpFilter(ipManagerCallback.getApfProgram(), PASS);
@@ -1056,7 +1114,8 @@ public class ApfTest extends AndroidTestCase {
    @SmallTest
    public void testApfFilterRa() throws Exception {
        MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
        TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
        TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST,
                DROP_802_3_FRAMES, mLog);
        byte[] program = ipManagerCallback.getApfProgram();

        final int ROUTER_LIFETIME = 1000;
@@ -1198,7 +1257,8 @@ public class ApfTest extends AndroidTestCase {
        final int maxRandomPacketSize = 512;
        final Random r = new Random();
        MockIpManagerCallback cb = new MockIpManagerCallback();
        TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST, mLog);
        TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST,
                DROP_802_3_FRAMES, mLog);
        for (int i = 0; i < 1000; i++) {
            byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
            r.nextBytes(packet);
@@ -1216,7 +1276,8 @@ public class ApfTest extends AndroidTestCase {
        final int maxRandomPacketSize = 512;
        final Random r = new Random();
        MockIpManagerCallback cb = new MockIpManagerCallback();
        TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST, mLog);
        TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST,
                DROP_802_3_FRAMES, mLog);
        for (int i = 0; i < 1000; i++) {
            byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
            r.nextBytes(packet);