summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/android/net/apf/ApfFilter.java26
-rw-r--r--src/android/net/ip/IpClient.java30
-rw-r--r--src/android/net/ip/IpClientLinkObserver.java28
3 files changed, 76 insertions, 8 deletions
diff --git a/src/android/net/apf/ApfFilter.java b/src/android/net/apf/ApfFilter.java
index 75a737d..165e37b 100644
--- a/src/android/net/apf/ApfFilter.java
+++ b/src/android/net/apf/ApfFilter.java
@@ -105,6 +105,7 @@ public class ApfFilter {
public boolean multicastFilter;
public boolean ieee802_3Filter;
public int[] ethTypeBlackList;
+ public int minRdnssLifetimeSec;
}
// Enums describing the outcome of receiving an RA packet.
@@ -358,6 +359,9 @@ public class ApfFilter {
private final boolean mDrop802_3Frames;
private final int[] mEthTypeBlackList;
+ // Ignore non-zero RDNSS lifetimes below this value.
+ private final int mMinRdnssLifetimeSec;
+
// Detects doze mode state transitions.
private final BroadcastReceiver mDeviceIdleReceiver = new BroadcastReceiver() {
@Override
@@ -388,6 +392,7 @@ public class ApfFilter {
mInterfaceParams = ifParams;
mMulticastFilter = config.multicastFilter;
mDrop802_3Frames = config.ieee802_3Filter;
+ mMinRdnssLifetimeSec = config.minRdnssLifetimeSec;
mContext = context;
if (mApfCapabilities.hasDataAccess()) {
@@ -748,6 +753,19 @@ public class ApfFilter {
return lifetime;
}
+ // http://b/66928272 http://b/65056012
+ // DnsServerRepository ignores RDNSS servers with lifetimes that are too low. Ignore these
+ // lifetimes for the purpose of filter lifetime calculations.
+ private boolean shouldIgnoreLifetime(int optionType, long lifetime) {
+ return optionType == ICMP6_RDNSS_OPTION_TYPE
+ && lifetime != 0 && lifetime < mMinRdnssLifetimeSec;
+ }
+
+ private boolean isRelevantLifetime(PacketSection section) {
+ return section.type == PacketSection.Type.LIFETIME
+ && !shouldIgnoreLifetime(section.option, section.lifetime);
+ }
+
// Note that this parses RA and may throw InvalidRaException (from
// Buffer.position(int) or due to an invalid-length option) or IndexOutOfBoundsException
// (from ByteBuffer.get(int) ) if parsing encounters something non-compliant with
@@ -862,7 +880,7 @@ public class ApfFilter {
long minLifetime() {
long minLifetime = Long.MAX_VALUE;
for (PacketSection section : mPacketSections) {
- if (section.type == PacketSection.Type.LIFETIME) {
+ if (isRelevantLifetime(section)) {
minLifetime = Math.min(minLifetime, section.lifetime);
}
}
@@ -902,9 +920,10 @@ public class ApfFilter {
section.start + section.length),
nextFilterLabel);
}
+
// Generate code to test the lifetimes haven't gone down too far.
- // The packet is accepted if any of its lifetimes are lower than filterLifetime.
- if (section.type == PacketSection.Type.LIFETIME) {
+ // The packet is accepted if any non-ignored lifetime is lower than filterLifetime.
+ if (isRelevantLifetime(section)) {
switch (section.length) {
case 4: gen.addLoad32(Register.R0, section.start); break;
case 2: gen.addLoad16(Register.R0, section.start); break;
@@ -1913,6 +1932,7 @@ public class ApfFilter {
pw.println("Capabilities: " + mApfCapabilities);
pw.println("Receive thread: " + (mReceiveThread != null ? "RUNNING" : "STOPPED"));
pw.println("Multicast: " + (mMulticastFilter ? "DROP" : "ALLOW"));
+ pw.println("Minimum RDNSS lifetime: " + mMinRdnssLifetimeSec);
try {
pw.println("IPv4 address: " + InetAddress.getByAddress(mIPv4Address).getHostAddress());
} catch (UnknownHostException|NullPointerException e) {}
diff --git a/src/android/net/ip/IpClient.java b/src/android/net/ip/IpClient.java
index 9f1f17c..8808ee2 100644
--- a/src/android/net/ip/IpClient.java
+++ b/src/android/net/ip/IpClient.java
@@ -18,6 +18,7 @@ package android.net.ip;
import static android.net.RouteInfo.RTN_UNICAST;
import static android.net.shared.IpConfigurationParcelableUtil.toStableParcelable;
+import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
import static com.android.server.util.PermissionUtil.enforceNetworkStackCallingPermission;
@@ -42,7 +43,9 @@ import android.net.metrics.IpManagerEvent;
import android.net.shared.InitialConfiguration;
import android.net.shared.ProvisioningConfiguration;
import android.net.util.InterfaceParams;
+import android.net.util.NetworkStackUtils;
import android.net.util.SharedLog;
+import android.os.Build;
import android.os.ConditionVariable;
import android.os.IBinder;
import android.os.Message;
@@ -65,6 +68,7 @@ import com.android.internal.util.Preconditions;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.internal.util.WakeupMessage;
+import com.android.networkstack.apishim.ShimUtils;
import com.android.server.NetworkObserverRegistry;
import com.android.server.NetworkStackService.NetworkStackServiceManager;
@@ -313,9 +317,15 @@ public class IpClient extends StateMachine {
// IpClient shares a handler with DhcpClient: commands must not overlap
public static final int DHCPCLIENT_CMD_BASE = 1000;
+ // Settings and default values.
private static final int MAX_LOG_RECORDS = 500;
private static final int MAX_PACKET_RECORDS = 100;
+ @VisibleForTesting
+ static final String CONFIG_MIN_RDNSS_LIFETIME = "ipclient_min_rdnss_lifetime";
+ private static final int DEFAULT_MIN_RDNSS_LIFETIME =
+ ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q) ? 120 : 0;
+
private static final boolean NO_CALLBACKS = false;
private static final boolean SEND_CALLBACKS = true;
@@ -355,6 +365,9 @@ public class IpClient extends StateMachine {
private final IpConnectivityLog mMetricsLog = new IpConnectivityLog();
private final InterfaceController mInterfaceCtrl;
+ // Ignore nonzero RDNSS option lifetimes below this value. 0 = disabled.
+ private final int mMinRdnssLifetimeSec;
+
private InterfaceParams mInterfaceParams;
/**
@@ -411,6 +424,14 @@ public class IpClient extends StateMachine {
NetworkStackIpMemoryStore ipMemoryStore) {
return new DhcpClient.Dependencies(ipMemoryStore);
}
+
+ /**
+ * Read an integer DeviceConfig property.
+ */
+ public int getDeviceConfigPropertyInt(String name, int defaultValue) {
+ return NetworkStackUtils.getDeviceConfigPropertyInt(NAMESPACE_CONNECTIVITY, name,
+ defaultValue);
+ }
}
public IpClient(Context context, String ifName, IIpClientCallbacks callback,
@@ -449,9 +470,15 @@ public class IpClient extends StateMachine {
mNetd = deps.getNetd(mContext);
mInterfaceCtrl = new InterfaceController(mInterfaceName, mNetd, mLog);
+ mMinRdnssLifetimeSec = mDependencies.getDeviceConfigPropertyInt(
+ CONFIG_MIN_RDNSS_LIFETIME, DEFAULT_MIN_RDNSS_LIFETIME);
+
+ IpClientLinkObserver.Configuration config = new IpClientLinkObserver.Configuration(
+ mMinRdnssLifetimeSec);
+
mLinkObserver = new IpClientLinkObserver(
mInterfaceName,
- () -> sendMessage(EVENT_NETLINK_LINKPROPERTIES_CHANGED)) {
+ () -> sendMessage(EVENT_NETLINK_LINKPROPERTIES_CHANGED), config) {
@Override
public void onInterfaceAdded(String iface) {
super.onInterfaceAdded(iface);
@@ -1500,6 +1527,7 @@ public class IpClient extends StateMachine {
// Get the Configuration for ApfFilter from Context
apfConfig.ieee802_3Filter = ApfCapabilities.getApfDrop8023Frames();
apfConfig.ethTypeBlackList = ApfCapabilities.getApfEtherTypeBlackList();
+ apfConfig.minRdnssLifetimeSec = mMinRdnssLifetimeSec;
mApfFilter = ApfFilter.maybeCreate(mContext, apfConfig, mInterfaceParams, mCallback);
// TODO: investigate the effects of any multicast filtering racing/interfering with the
// rest of this IP configuration startup.
diff --git a/src/android/net/ip/IpClientLinkObserver.java b/src/android/net/ip/IpClientLinkObserver.java
index 3f399e9..02bf5f0 100644
--- a/src/android/net/ip/IpClientLinkObserver.java
+++ b/src/android/net/ip/IpClientLinkObserver.java
@@ -71,20 +71,31 @@ public class IpClientLinkObserver implements NetworkObserver {
void update();
}
+ /** Configuration parameters for IpClientLinkObserver. */
+ public static class Configuration {
+ public final int minRdnssLifetime;
+
+ public Configuration(int minRdnssLifetime) {
+ this.minRdnssLifetime = minRdnssLifetime;
+ }
+ }
+
private final String mInterfaceName;
private final Callback mCallback;
private final LinkProperties mLinkProperties;
private DnsServerRepository mDnsServerRepository;
+ private final Configuration mConfig;
private static final boolean DBG = false;
- public IpClientLinkObserver(String iface, Callback callback) {
+ public IpClientLinkObserver(String iface, Callback callback, Configuration config) {
mTag = "NetlinkTracker/" + iface;
mInterfaceName = iface;
mCallback = callback;
mLinkProperties = new LinkProperties();
mLinkProperties.setInterfaceName(mInterfaceName);
- mDnsServerRepository = new DnsServerRepository();
+ mConfig = config;
+ mDnsServerRepository = new DnsServerRepository(config.minRdnssLifetime);
}
private void maybeLog(String operation, String iface, LinkAddress address) {
@@ -197,7 +208,7 @@ public class IpClientLinkObserver implements NetworkObserver {
// Clear the repository before clearing mLinkProperties. That way, if a clear() happens
// while interfaceDnsServerInfo() is being called, we'll end up with no DNS servers in
// mLinkProperties, as desired.
- mDnsServerRepository = new DnsServerRepository();
+ mDnsServerRepository = new DnsServerRepository(mConfig.minRdnssLifetime);
mLinkProperties.clear();
mLinkProperties.setInterfaceName(mInterfaceName);
}
@@ -260,10 +271,16 @@ public class IpClientLinkObserver implements NetworkObserver {
*/
private HashMap<InetAddress, DnsServerEntry> mIndex;
- DnsServerRepository() {
+ /**
+ * Minimum (non-zero) RDNSS lifetime to accept.
+ */
+ private final int mMinLifetime;
+
+ DnsServerRepository(int minLifetime) {
mCurrentServers = new HashSet<>();
mAllServers = new ArrayList<>(NUM_SERVERS);
mIndex = new HashMap<>(NUM_SERVERS);
+ mMinLifetime = minLifetime;
}
/** Sets the DNS servers of the provided LinkProperties object to the current servers. */
@@ -277,6 +294,9 @@ public class IpClientLinkObserver implements NetworkObserver {
* @param addresses the string representations of the IP addresses of DNS servers to use.
*/
public synchronized boolean addServers(long lifetime, String[] addresses) {
+ // If the servers are below the minimum lifetime, don't change anything.
+ if (lifetime != 0 && lifetime < mMinLifetime) return false;
+
// The lifetime is actually an unsigned 32-bit number, but Java doesn't have unsigned.
// Technically 0xffffffff (the maximum) is special and means "forever", but 2^32 seconds
// (136 years) is close enough.