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

Commit 23ed88ac authored by Erik Kline's avatar Erik Kline Committed by android-build-merger
Browse files

Merge "Move the logic of (re)evaluation of Private DNS"

am: 04233ef1

Change-Id: Ic510dabd6a2d40cd6d33a21e0128d85a0126127f
parents 9473e846 04233ef1
Loading
Loading
Loading
Loading
+47 −92
Original line number Diff line number Diff line
@@ -911,6 +911,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
        mHandler.sendEmptyMessage(EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON);
    }

    // See FakeSettingsProvider comment above.
    @VisibleForTesting
    void updatePrivateDnsSettings() {
        mHandler.sendEmptyMessage(EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
    }

    private void handleMobileDataAlwaysOn() {
        final boolean enable = toBool(Settings.Global.getInt(
                mContext.getContentResolver(), Settings.Global.MOBILE_DATA_ALWAYS_ON, 1));
@@ -940,8 +946,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
    }

    private void registerPrivateDnsSettingsCallbacks() {
        for (Uri u : DnsManager.getPrivateDnsSettingsUris()) {
            mSettingsObserver.observe(u, EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
        for (Uri uri : DnsManager.getPrivateDnsSettingsUris()) {
            mSettingsObserver.observe(uri, EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
        }
    }

@@ -994,8 +1000,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
        if (network == null) {
            return null;
        }
        return getNetworkAgentInfoForNetId(network.netId);
    }

    private NetworkAgentInfo getNetworkAgentInfoForNetId(int netId) {
        synchronized (mNetworkForNetId) {
            return mNetworkForNetId.get(network.netId);
            return mNetworkForNetId.get(netId);
        }
    }

@@ -1135,9 +1145,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
        }
        NetworkAgentInfo nai;
        if (vpnNetId != NETID_UNSET) {
            synchronized (mNetworkForNetId) {
                nai = mNetworkForNetId.get(vpnNetId);
            }
            nai = getNetworkAgentInfoForNetId(vpnNetId);
            if (nai != null) return nai.network;
        }
        nai = getDefaultNetwork();
@@ -2113,41 +2121,21 @@ public class ConnectivityService extends IConnectivityManager.Stub
                default:
                    return false;
                case NetworkMonitor.EVENT_NETWORK_TESTED: {
                    final NetworkAgentInfo nai;
                    synchronized (mNetworkForNetId) {
                        nai = mNetworkForNetId.get(msg.arg2);
                    }
                    final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
                    if (nai == null) break;

                    final boolean valid = (msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
                    final boolean wasValidated = nai.lastValidated;
                    final boolean wasDefault = isDefaultNetwork(nai);

                    final PrivateDnsConfig privateDnsCfg = (msg.obj instanceof PrivateDnsConfig)
                            ? (PrivateDnsConfig) msg.obj : null;
                    final String redirectUrl = (msg.obj instanceof String) ? (String) msg.obj : "";

                    final boolean reevaluationRequired;
                    final String logMsg;
                    if (valid) {
                        reevaluationRequired = updatePrivateDns(nai, privateDnsCfg);
                        logMsg = (DBG && (privateDnsCfg != null))
                                 ? " with " + privateDnsCfg.toString() : "";
                    } else {
                        reevaluationRequired = false;
                        logMsg = (DBG && !TextUtils.isEmpty(redirectUrl))
                                 ? " with redirect to " + redirectUrl : "";
                    }
                    if (DBG) {
                        final String logMsg = !TextUtils.isEmpty(redirectUrl)
                                 ? " with redirect to " + redirectUrl
                                 : "";
                        log(nai.name() + " validation " + (valid ? "passed" : "failed") + logMsg);
                    }
                    // If there is a change in Private DNS configuration,
                    // trigger reevaluation of the network to test it.
                    if (reevaluationRequired) {
                        nai.networkMonitor.sendMessage(
                                NetworkMonitor.CMD_FORCE_REEVALUATION, Process.SYSTEM_UID);
                        break;
                    }
                    if (valid != nai.lastValidated) {
                        if (wasDefault) {
                            metricsLogger().defaultNetworkMetrics().logDefaultNetworkValidity(
@@ -2176,10 +2164,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
                case NetworkMonitor.EVENT_PROVISIONING_NOTIFICATION: {
                    final int netId = msg.arg2;
                    final boolean visible = toBool(msg.arg1);
                    final NetworkAgentInfo nai;
                    synchronized (mNetworkForNetId) {
                        nai = mNetworkForNetId.get(netId);
                    }
                    final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId);
                    // If captive portal status has changed, update capabilities or disconnect.
                    if (nai != null && (visible != nai.lastCaptivePortalDetected)) {
                        final int oldScore = nai.getCurrentScore();
@@ -2210,18 +2195,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
                    break;
                }
                case NetworkMonitor.EVENT_PRIVATE_DNS_CONFIG_RESOLVED: {
                    final NetworkAgentInfo nai;
                    synchronized (mNetworkForNetId) {
                        nai = mNetworkForNetId.get(msg.arg2);
                    }
                    final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
                    if (nai == null) break;

                    final PrivateDnsConfig cfg = (PrivateDnsConfig) msg.obj;
                    final boolean reevaluationRequired = updatePrivateDns(nai, cfg);
                    if (nai.lastValidated && reevaluationRequired) {
                        nai.networkMonitor.sendMessage(
                                NetworkMonitor.CMD_FORCE_REEVALUATION, Process.SYSTEM_UID);
                    }
                    updatePrivateDns(nai, (PrivateDnsConfig) msg.obj);
                    break;
                }
            }
@@ -2259,61 +2236,38 @@ public class ConnectivityService extends IConnectivityManager.Stub
        }
    }

    private boolean networkRequiresValidation(NetworkAgentInfo nai) {
        return NetworkMonitor.isValidationRequired(
                mDefaultRequest.networkCapabilities, nai.networkCapabilities);
    }

    private void handlePrivateDnsSettingsChanged() {
        final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig();

        for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
            handlePerNetworkPrivateDnsConfig(nai, cfg);
        }
    }

    private void handlePerNetworkPrivateDnsConfig(NetworkAgentInfo nai, PrivateDnsConfig cfg) {
        // Private DNS only ever applies to networks that might provide
        // Internet access and therefore also require validation.
            if (!NetworkMonitor.isValidationRequired(
                    mDefaultRequest.networkCapabilities, nai.networkCapabilities)) {
                continue;
            }
        if (!networkRequiresValidation(nai)) return;

        // Notify the NetworkMonitor thread in case it needs to cancel or
        // schedule DNS resolutions. If a DNS resolution is required the
        // result will be sent back to us.
        nai.networkMonitor.notifyPrivateDnsSettingsChanged(cfg);

            if (!cfg.inStrictMode()) {
                // No strict mode hostname DNS resolution needed, so just update
                // DNS settings directly. In opportunistic and "off" modes this
                // just reprograms netd with the network-supplied DNS servers
                // (and of course the boolean of whether or not to attempt TLS).
                //
                // TODO: Consider code flow parity with strict mode, i.e. having
                // NetworkMonitor relay the PrivateDnsConfig back to us and then
                // performing this call at that time.
        // With Private DNS bypass support, we can proceed to update the
        // Private DNS config immediately, even if we're in strict mode
        // and have not yet resolved the provider name into a set of IPs.
        updatePrivateDns(nai, cfg);
    }
        }
    }

    private boolean updatePrivateDns(NetworkAgentInfo nai, PrivateDnsConfig newCfg) {
        final boolean reevaluationRequired = true;
        final boolean dontReevaluate = false;

        final PrivateDnsConfig oldCfg = mDnsManager.updatePrivateDns(nai.network, newCfg);
    private void updatePrivateDns(NetworkAgentInfo nai, PrivateDnsConfig newCfg) {
        mDnsManager.updatePrivateDns(nai.network, newCfg);
        updateDnses(nai.linkProperties, null, nai.network.netId);

        if (newCfg == null) {
            if (oldCfg == null) return dontReevaluate;
            return oldCfg.useTls ? reevaluationRequired : dontReevaluate;
        }

        if (oldCfg == null) {
            return newCfg.useTls ? reevaluationRequired : dontReevaluate;
        }

        if (oldCfg.useTls != newCfg.useTls) {
            return reevaluationRequired;
        }

        if (newCfg.inStrictMode() && !Objects.equals(oldCfg.hostname, newCfg.hostname)) {
            return reevaluationRequired;
        }

        return dontReevaluate;
    }

    private void updateLingerState(NetworkAgentInfo nai, long now) {
@@ -3252,7 +3206,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
        if (isNetworkWithLinkPropertiesBlocked(lp, uid, false)) {
            return;
        }
        nai.networkMonitor.sendMessage(NetworkMonitor.CMD_FORCE_REEVALUATION, uid);
        nai.networkMonitor.forceReevaluation(uid);
    }

    private ProxyInfo getDefaultProxy() {
@@ -4871,7 +4825,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
    }

    public void handleUpdateLinkProperties(NetworkAgentInfo nai, LinkProperties newLp) {
        if (mNetworkForNetId.get(nai.network.netId) != nai) {
        if (getNetworkAgentInfoForNetId(nai.network.netId) != nai) {
            // Ignore updates for disconnected networks
            return;
        }
@@ -5451,6 +5405,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
                Slog.wtf(TAG, networkAgent.name() + " connected with null LinkProperties");
            }

            handlePerNetworkPrivateDnsConfig(networkAgent, mDnsManager.getPrivateDnsConfig());
            updateLinkProperties(networkAgent, null);

            networkAgent.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
+45 −0
Original line number Diff line number Diff line
@@ -61,6 +61,51 @@ import java.util.StringJoiner;
 * This class it NOT designed for concurrent access. Furthermore, all non-static
 * methods MUST be called from ConnectivityService's thread.
 *
 * [ Private DNS ]
 * The code handling Private DNS is spread across several components, but this
 * seems like the least bad place to collect all the observations.
 *
 * Private DNS handling and updating occurs in response to several different
 * events. Each is described here with its corresponding intended handling.
 *
 * [A] Event: A new network comes up.
 * Mechanics:
 *     [1] ConnectivityService gets notifications from NetworkAgents.
 *     [2] in updateNetworkInfo(), the first time the NetworkAgent goes into
 *         into CONNECTED state, the Private DNS configuration is retrieved,
 *         programmed, and strict mode hostname resolution (if applicable) is
 *         enqueued in NetworkAgent's NetworkMonitor, via a call to
 *         handlePerNetworkPrivateDnsConfig().
 *     [3] Re-resolution of strict mode hostnames that fail to return any
 *         IP addresses happens inside NetworkMonitor; it sends itself a
 *         delayed CMD_EVALUATE_PRIVATE_DNS message in a simple backoff
 *         schedule.
 *     [4] Successfully resolved hostnames are sent to ConnectivityService
 *         inside an EVENT_PRIVATE_DNS_CONFIG_RESOLVED message. The resolved
 *         IP addresses are programmed into netd via:
 *
 *             updatePrivateDns() -> updateDnses()
 *
 *         both of which make calls into DnsManager.
 *     [5] Upon a successful hostname resolution NetworkMonitor initiates a
 *         validation attempt in the form of a lookup for a one-time hostname
 *         that uses Private DNS.
 *
 * [B] Event: Private DNS settings are changed.
 * Mechanics:
 *     [1] ConnectivityService gets notifications from its SettingsObserver.
 *     [2] handlePrivateDnsSettingsChanged() is called, which calls
 *         handlePerNetworkPrivateDnsConfig() and the process proceeds
 *         as if from A.3 above.
 *
 * [C] Event: An application calls ConnectivityManager#reportBadNetwork().
 * Mechanics:
 *     [1] NetworkMonitor is notified and initiates a reevaluation, which
 *         always bypasses Private DNS.
 *     [2] Once completed, NetworkMonitor checks if strict mode is in operation
 *         and if so enqueues another evaluation of Private DNS, as if from
 *         step A.5 above.
 *
 * @hide
 */
public class DnsManager {