Switch to a new way of activating DNS-over-TLS

This change removes the global database of potential DNS-over-TLS
servers from Netd, and makes pinned or named servers mandatory-TLS,
not opportunistic.

Bug: 64753847
Change-Id: I226ffec3f59593bc40cd9019095c5261aae55fa0
Test: Tests pass.  Normal browsing continues to work normally.
diff --git a/server/dns/DnsTlsTransport.cpp b/server/dns/DnsTlsTransport.cpp
index 4cedac9..b369022 100644
--- a/server/dns/DnsTlsTransport.cpp
+++ b/server/dns/DnsTlsTransport.cpp
@@ -16,6 +16,8 @@
 
 #include "dns/DnsTlsTransport.h"
 
+#include <algorithm>
+#include <iterator>
 #include <arpa/inet.h>
 #include <arpa/nameser.h>
 #include <errno.h>
@@ -32,6 +34,72 @@
 #include "NetdConstants.h"
 #include "Permission.h"
 
+namespace {
+
+// Returns a tuple of references to the elements of a.
+auto make_tie(const sockaddr_in& a) {
+    return std::tie(a.sin_port, a.sin_addr.s_addr);
+}
+
+// Returns a tuple of references to the elements of a.
+auto make_tie(const sockaddr_in6& a) {
+    // Skip flowinfo, which is not relevant.
+    return std::tie(
+        a.sin6_port,
+        a.sin6_addr,
+        a.sin6_scope_id
+    );
+}
+
+} // namespace
+
+// These binary operators make sockaddr_storage comparable.  They need to be
+// in the global namespace so that the std::tuple < and == operators can see them.
+static bool operator <(const in6_addr& x, const in6_addr& y) {
+    return std::lexicographical_compare(
+            std::begin(x.s6_addr), std::end(x.s6_addr),
+            std::begin(y.s6_addr), std::end(y.s6_addr));
+}
+
+static bool operator ==(const in6_addr& x, const in6_addr& y) {
+    return std::equal(
+            std::begin(x.s6_addr), std::end(x.s6_addr),
+            std::begin(y.s6_addr), std::end(y.s6_addr));
+}
+
+static bool operator <(const sockaddr_storage& x, const sockaddr_storage& y) {
+    if (x.ss_family != y.ss_family) {
+        return x.ss_family < y.ss_family;
+    }
+    // Same address family.
+    if (x.ss_family == AF_INET) {
+        const sockaddr_in& x_sin = reinterpret_cast<const sockaddr_in&>(x);
+        const sockaddr_in& y_sin = reinterpret_cast<const sockaddr_in&>(y);
+        return make_tie(x_sin) < make_tie(y_sin);
+    } else if (x.ss_family == AF_INET6) {
+        const sockaddr_in6& x_sin6 = reinterpret_cast<const sockaddr_in6&>(x);
+        const sockaddr_in6& y_sin6 = reinterpret_cast<const sockaddr_in6&>(y);
+        return make_tie(x_sin6) < make_tie(y_sin6);
+    }
+    return false;  // Unknown address type.  This is an error.
+}
+
+static bool operator ==(const sockaddr_storage& x, const sockaddr_storage& y) {
+    if (x.ss_family != y.ss_family) {
+        return false;
+    }
+    // Same address family.
+    if (x.ss_family == AF_INET) {
+        const sockaddr_in& x_sin = reinterpret_cast<const sockaddr_in&>(x);
+        const sockaddr_in& y_sin = reinterpret_cast<const sockaddr_in&>(y);
+        return make_tie(x_sin) == make_tie(y_sin);
+    } else if (x.ss_family == AF_INET6) {
+        const sockaddr_in6& x_sin6 = reinterpret_cast<const sockaddr_in6&>(x);
+        const sockaddr_in6& y_sin6 = reinterpret_cast<const sockaddr_in6&>(y);
+        return make_tie(x_sin6) == make_tie(y_sin6);
+    }
+    return false;  // Unknown address type.  This is an error.
+}
 
 namespace android {
 namespace net {
@@ -125,6 +193,44 @@
     return true;
 }
 
+// This comparison ignores ports and fingerprints.
+// TODO: respect IPv6 scope id (e.g. link-local addresses).
+bool AddressComparator::operator() (const DnsTlsTransport::Server& x,
+        const DnsTlsTransport::Server& y) const {
+    if (x.ss.ss_family != y.ss.ss_family) {
+        return x.ss.ss_family < y.ss.ss_family;
+    }
+    // Same address family.
+    if (x.ss.ss_family == AF_INET) {
+        const sockaddr_in& x_sin = reinterpret_cast<const sockaddr_in&>(x.ss);
+        const sockaddr_in& y_sin = reinterpret_cast<const sockaddr_in&>(y.ss);
+        return x_sin.sin_addr.s_addr < y_sin.sin_addr.s_addr;
+    } else if (x.ss.ss_family == AF_INET6) {
+        const sockaddr_in6& x_sin6 = reinterpret_cast<const sockaddr_in6&>(x.ss);
+        const sockaddr_in6& y_sin6 = reinterpret_cast<const sockaddr_in6&>(y.ss);
+        return x_sin6.sin6_addr < y_sin6.sin6_addr;
+    }
+    return false;  // Unknown address type.  This is an error.
+}
+
+// Returns a tuple of references to the elements of s.
+auto make_tie(const DnsTlsTransport::Server& s) {
+    return std::tie(
+        s.ss,
+        s.name,
+        s.fingerprints,
+        s.protocol
+    );
+}
+
+bool DnsTlsTransport::Server::operator <(const DnsTlsTransport::Server& other) const {
+    return make_tie(*this) < make_tie(other);
+}
+
+bool DnsTlsTransport::Server::operator ==(const DnsTlsTransport::Server& other) const {
+    return make_tie(*this) == make_tie(other);
+}
+
 SSL* DnsTlsTransport::sslConnect(int fd) {
     if (fd < 0) {
         ALOGD("%u makeConnectedSocket() failed with: %s", mMark, strerror(errno));
@@ -140,7 +246,8 @@
     }
 
     bssl::UniquePtr<SSL> ssl(SSL_new(ssl_ctx.get()));
-    bssl::UniquePtr<BIO> bio(BIO_new_socket(fd, BIO_CLOSE));
+    // This file descriptor is owned by a unique_fd, so don't let libssl close it.
+    bssl::UniquePtr<BIO> bio(BIO_new_socket(fd, BIO_NOCLOSE));
     SSL_set_bio(ssl.get(), bio.get(), bio.get());
     bio.release();