Set the explicit bit on DNS queries when it is safe to do so.

Generally, it is not safe to set the explicit bit on DNS queries
due to the presence of (split tunnel) VPNs. However, the vast
majority of DNS queries occur without a VPN, and in these cases
it is safe to set the explicit bit.

Setting the explicit bit on DNS queries allows us to use upstream
DNS servers even in the case that we have a route to them in the
local_network table. This is the case, for example, when
tethering an Android device to a hotspot created by another
Android device.

Bug: 70673901
Test: marlin builds, boots
Test: netd_{unit,integration}_test pass
Change-Id: Ic24e3df9ca47b54256f012aee0facfcd410ce541
diff --git a/server/NetworkController.cpp b/server/NetworkController.cpp
index 5b2cd89..87ad1bd 100644
--- a/server/NetworkController.cpp
+++ b/server/NetworkController.cpp
@@ -192,6 +192,19 @@
     Fwmark fwmark;
     fwmark.protectedFromVpn = true;
     fwmark.permission = PERMISSION_SYSTEM;
+
+    // Common case: there is no VPN that applies to the user, and the query did not specify a netId.
+    // Therefore, it is safe to set the explicit bit on this query and skip all the complex logic
+    // below. While this looks like a special case, it is actually the one that handles the vast
+    // majority of DNS queries.
+    // TODO: untangle this code.
+    if (*netId == NETID_UNSET && getVirtualNetworkForUserLocked(uid) == nullptr) {
+        *netId = mDefaultNetId;
+        fwmark.netId = *netId;
+        fwmark.explicitlySelected = true;
+        return fwmark.intValue;
+    }
+
     if (checkUserNetworkAccessLocked(uid, *netId) == 0) {
         // If a non-zero NetId was explicitly specified, and the user has permission for that
         // network, use that network's DNS servers. Do not fall through to the default network even
@@ -210,7 +223,8 @@
     } else {
         // If the user is subject to a VPN and the VPN provides DNS servers, use those servers
         // (possibly falling through to the default network if the VPN doesn't provide a route to
-        // them). Otherwise, use the default network's DNS servers.
+        // them). Otherwise, use the default network's DNS servers. We cannot set the explicit bit
+        // because we need to be able to fall through a split tunnel to the default network.
         VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid);
         if (virtualNetwork && virtualNetwork->getHasDns()) {
             *netId = virtualNetwork->getNetId();