Merge "Add Configuration to APF Policy" into oc-dr1-dev
am: 1da6af31ff
Change-Id: I16346bb98a0b9259f7c3f51e318c472cfc1bb492
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a52cd72..f6bbd269 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -291,6 +291,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. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index f0e9398..34a9fb7 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1841,6 +1841,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" />
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index e4c6690..8cb2df7 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -179,6 +179,7 @@
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 @@
private final IpManager.Callback mIpManagerCallback;
private final NetworkInterface mNetworkInterface;
private final IpConnectivityLog mMetricsLog;
+
@VisibleForTesting
byte[] mHardwareAddress;
@VisibleForTesting
@@ -244,6 +246,7 @@
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 @@
@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;
// TODO: ApfFilter should not generate programs until IpManager sends provisioning success.
@@ -885,6 +890,7 @@
/**
* 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,
@@ -906,6 +912,8 @@
// 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:
@@ -916,9 +924,15 @@
// 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);
@@ -1101,7 +1115,7 @@
*/
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) {
@@ -1118,7 +1132,7 @@
return null;
}
return new ApfFilter(apfCapabilities, networkInterface, ipManagerCallback,
- multicastFilter, new IpConnectivityLog());
+ multicastFilter, ieee802_3Filter, new IpConnectivityLog());
}
public synchronized void shutdown() {
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 5aaec9e..46c1292 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -51,6 +51,7 @@
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 @@
@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) {
diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java
index 6bf3b6b..bfbb8cc 100644
--- a/tests/net/java/android/net/apf/ApfTest.java
+++ b/tests/net/java/android/net/apf/ApfTest.java
@@ -92,6 +92,9 @@
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 @@
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 @@
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 @@
@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 @@
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 @@
// 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 @@
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 @@
@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 @@
@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 @@
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 @@
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);