1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef _DNS_DNSTLSDISPATCHER_H 18 #define _DNS_DNSTLSDISPATCHER_H 19 20 #include <list> 21 #include <map> 22 #include <memory> 23 #include <mutex> 24 25 #include <android-base/thread_annotations.h> 26 #include <netdutils/Slice.h> 27 28 #include "DnsTlsServer.h" 29 #include "DnsTlsTransport.h" 30 #include "IDnsTlsSocketFactory.h" 31 #include "PrivateDnsValidationObserver.h" 32 #include "resolv_private.h" 33 34 namespace android { 35 namespace net { 36 37 // This is a singleton class that manages the collection of active DnsTlsTransports. 38 // Queries made here are dispatched to an existing or newly constructed DnsTlsTransport. 39 // TODO: PrivateDnsValidationObserver is not implemented in this class. Remove it. 40 class DnsTlsDispatcher : public PrivateDnsValidationObserver { 41 public: 42 // Constructor with dependency injection for testing. DnsTlsDispatcher(std::unique_ptr<IDnsTlsSocketFactory> factory)43 explicit DnsTlsDispatcher(std::unique_ptr<IDnsTlsSocketFactory> factory) 44 : mFactory(std::move(factory)) {} 45 46 static DnsTlsDispatcher& getInstance(); 47 48 // Enqueues |query| for resolution via the given |tlsServers| on the 49 // network indicated by |mark|; writes the response into |ans|, and stores 50 // the count of bytes written in |resplen|. Returns a success or error code. 51 // The order in which servers from |tlsServers| are queried may not be the 52 // order passed in by the caller. 53 DnsTlsTransport::Response query(const std::list<DnsTlsServer>& tlsServers, 54 ResState* _Nonnull statp, const netdutils::Slice query, 55 const netdutils::Slice ans, int* _Nonnull resplen, 56 bool dotQuickFallback); 57 58 // Given a |query|, sends it to the server on the network indicated by |mark|, 59 // and writes the response into |ans|, and indicates the number of bytes written in |resplen|. 60 // If the whole procedure above triggers (or experiences) any new connection, |connectTriggered| 61 // is set. Returns a success or error code. 62 DnsTlsTransport::Response query(const DnsTlsServer& server, unsigned netId, unsigned mark, 63 const netdutils::Slice query, const netdutils::Slice ans, 64 int* _Nonnull resplen, bool* _Nonnull connectTriggered); 65 66 // Implement PrivateDnsValidationObserver. onValidationStateUpdate(const std::string &,Validation,uint32_t)67 void onValidationStateUpdate(const std::string&, Validation, uint32_t) override{}; 68 69 void forceCleanup(unsigned netId) EXCLUDES(sLock); 70 71 private: 72 DnsTlsDispatcher(); 73 74 // This lock is static so that it can be used to annotate the Transport struct. 75 // DnsTlsDispatcher is a singleton in practice, so making this static does not change 76 // the locking behavior. 77 static std::mutex sLock; 78 79 // Key = <mark, server> 80 typedef std::pair<unsigned, const DnsTlsServer> Key; 81 82 // Transport is a thin wrapper around DnsTlsTransport, adding reference counting and 83 // usage monitoring so we can expire idle sessions from the cache. 84 struct Transport { TransportTransport85 Transport(const DnsTlsServer& server, unsigned mark, unsigned netId, 86 IDnsTlsSocketFactory* _Nonnull factory, bool revalidationEnabled, int triggerThr, 87 int unusableThr, int timeout) 88 : transport(server, mark, factory), 89 mNetId(netId), 90 revalidationEnabled(revalidationEnabled), 91 triggerThreshold(triggerThr), 92 unusableThreshold(unusableThr), 93 mTimeout(timeout) {} 94 95 // DnsTlsTransport is thread-safe, so it doesn't need to be guarded. 96 DnsTlsTransport transport; 97 98 // The expected network, assigned from dns_netid, to which Transport will send DNS packets. 99 const unsigned mNetId; 100 101 // This use counter and timestamp are used to ensure that only idle sessions are 102 // destroyed. 103 int useCount GUARDED_BY(sLock) = 0; 104 // lastUsed is only guaranteed to be meaningful after useCount is decremented to zero. 105 std::chrono::time_point<std::chrono::steady_clock> lastUsed GUARDED_BY(sLock); 106 107 // If DoT revalidation is disabled, it returns true; otherwise, it returns 108 // whether or not this Transport is usable. 109 bool usable() const REQUIRES(sLock); 110 111 bool checkRevalidationNecessary(DnsTlsTransport::Response code) REQUIRES(sLock); 112 timeoutTransport113 std::chrono::milliseconds timeout() const { return mTimeout; } 114 115 static constexpr int kDotRevalidationThreshold = -1; 116 static constexpr int kDotXportUnusableThreshold = -1; 117 static constexpr int kDotQueryTimeoutMs = -1; 118 119 private: 120 // Used to track if this Transport is usable. 121 int continuousfailureCount GUARDED_BY(sLock) = 0; 122 123 // Used to indicate whether DoT revalidation is enabled for this Transport. 124 // The value is set to true only if: 125 // 1. both triggerThreshold and unusableThreshold are positive values. 126 // 2. private DNS mode is opportunistic. 127 const bool revalidationEnabled; 128 129 // The number of continuous failures to trigger a validation. It takes effect when DoT 130 // revalidation is on. If the value is not a positive value, DoT revalidation is disabled. 131 // Note that it must be at least 10, or it breaks ConnectTlsServerTimeout_ConcurrentQueries 132 // test. 133 const int triggerThreshold; 134 135 // The threshold to determine if this Transport is considered unusable. 136 // If continuousfailureCount reaches this value, this Transport is no longer used. It 137 // takes effect when DoT revalidation is on. If the value is not a positive value, DoT 138 // revalidation is disabled. 139 const int unusableThreshold; 140 141 // The time to await a future (the result of a DNS request) from the DnsTlsTransport 142 // of this Transport. 143 // To set an infinite timeout, assign the value to -1. 144 const std::chrono::milliseconds mTimeout; 145 }; 146 147 Transport* _Nullable addTransport(const DnsTlsServer& server, unsigned mark, unsigned netId) 148 REQUIRES(sLock); 149 Transport* _Nullable getTransport(const Key& key) REQUIRES(sLock); 150 151 // Cache of reusable DnsTlsTransports. Transports stay in cache as long as 152 // they are in use and for a few minutes after. 153 std::map<Key, std::unique_ptr<Transport>> mStore GUARDED_BY(sLock); 154 155 // The last time we did a cleanup. For efficiency, we only perform a cleanup once every 156 // few minutes. 157 std::chrono::time_point<std::chrono::steady_clock> mLastCleanup GUARDED_BY(sLock); 158 159 DnsTlsTransport::Result queryInternal(Transport& transport, const netdutils::Slice query) 160 EXCLUDES(sLock); 161 162 // Drop any cache entries whose useCount is zero and which have not been used recently. 163 // This function performs a linear scan of mStore. 164 void cleanup(std::chrono::time_point<std::chrono::steady_clock> now) REQUIRES(sLock); 165 166 // Force dropping any Transports whose useCount is zero. 167 void forceCleanupLocked(unsigned netId) REQUIRES(sLock); 168 169 // Return a sorted list of usable DnsTlsServers in preference order. 170 std::list<DnsTlsServer> getOrderedAndUsableServerList(const std::list<DnsTlsServer>& tlsServers, 171 unsigned netId, unsigned mark); 172 173 // Trivial factory for DnsTlsSockets. Dependency injection is only used for testing. 174 std::unique_ptr<IDnsTlsSocketFactory> mFactory; 175 }; 176 177 } // end of namespace net 178 } // end of namespace android 179 180 #endif // _DNS_DNSTLSDISPATCHER_H 181