1 /* 2 * Copyright (C) 2018 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 #pragma once 18 19 #include <list> 20 #include <map> 21 #include <mutex> 22 #include <vector> 23 24 #include <android-base/result.h> 25 #include <android-base/thread_annotations.h> 26 #include <netdutils/BackoffSequence.h> 27 #include <netdutils/DumpWriter.h> 28 #include <netdutils/InternetAddresses.h> 29 30 #include "DnsTlsServer.h" 31 #include "LockedQueue.h" 32 #include "PrivateDnsValidationObserver.h" 33 34 namespace android { 35 namespace net { 36 37 // TODO: decouple the dependency of DnsTlsServer. 38 struct PrivateDnsStatus { 39 PrivateDnsMode mode; 40 41 // TODO: change the type to std::vector<DnsTlsServer>. 42 std::map<DnsTlsServer, Validation, AddressComparator> serversMap; 43 validatedServersPrivateDnsStatus44 std::list<DnsTlsServer> validatedServers() const { 45 std::list<DnsTlsServer> servers; 46 47 for (const auto& pair : serversMap) { 48 if (pair.second == Validation::success) { 49 servers.push_back(pair.first); 50 } 51 } 52 return servers; 53 } 54 }; 55 56 class PrivateDnsConfiguration { 57 public: 58 struct ServerIdentity { 59 const netdutils::IPSockAddr sockaddr; 60 const std::string provider; 61 ServerIdentityServerIdentity62 explicit ServerIdentity(const IPrivateDnsServer& server) 63 : sockaddr(server.addr()), provider(server.provider()) {} 64 65 bool operator<(const ServerIdentity& other) const { 66 return std::tie(sockaddr, provider) < std::tie(other.sockaddr, other.provider); 67 } 68 bool operator==(const ServerIdentity& other) const { 69 return std::tie(sockaddr, provider) == std::tie(other.sockaddr, other.provider); 70 } 71 }; 72 73 // The only instance of PrivateDnsConfiguration. getInstance()74 static PrivateDnsConfiguration& getInstance() { 75 static PrivateDnsConfiguration instance; 76 return instance; 77 } 78 79 int set(int32_t netId, uint32_t mark, const std::vector<std::string>& servers, 80 const std::string& name, const std::string& caCert) EXCLUDES(mPrivateDnsLock); 81 82 PrivateDnsStatus getStatus(unsigned netId) const EXCLUDES(mPrivateDnsLock); 83 84 void clear(unsigned netId) EXCLUDES(mPrivateDnsLock); 85 86 // Request the server to be revalidated on a connection tagged with |mark|. 87 // Returns a Result to indicate if the request is accepted. 88 base::Result<void> requestValidation(unsigned netId, const ServerIdentity& identity, 89 uint32_t mark) EXCLUDES(mPrivateDnsLock); 90 91 void setObserver(PrivateDnsValidationObserver* observer); 92 93 void dump(netdutils::DumpWriter& dw) const; 94 95 private: 96 typedef std::map<ServerIdentity, std::unique_ptr<IPrivateDnsServer>> PrivateDnsTracker; 97 98 PrivateDnsConfiguration() = default; 99 100 // Launchs a thread to run the validation for |server| on the network |netId|. 101 // |isRevalidation| is true if this call is due to a revalidation request. 102 void startValidation(const ServerIdentity& identity, unsigned netId, bool isRevalidation) 103 REQUIRES(mPrivateDnsLock); 104 105 bool recordPrivateDnsValidation(const ServerIdentity& identity, unsigned netId, bool success, 106 bool isRevalidation) EXCLUDES(mPrivateDnsLock); 107 108 void sendPrivateDnsValidationEvent(const ServerIdentity& identity, unsigned netId, bool success) 109 REQUIRES(mPrivateDnsLock); 110 111 // Decide if a validation for |server| is needed. Note that servers that have failed 112 // multiple validation attempts but for which there is still a validating 113 // thread running are marked as being Validation::in_process. 114 bool needsValidation(const IPrivateDnsServer& server) const REQUIRES(mPrivateDnsLock); 115 116 void updateServerState(const ServerIdentity& identity, Validation state, uint32_t netId) 117 REQUIRES(mPrivateDnsLock); 118 119 // For testing. 120 base::Result<IPrivateDnsServer*> getPrivateDns(const ServerIdentity& identity, unsigned netId) 121 EXCLUDES(mPrivateDnsLock); 122 123 base::Result<IPrivateDnsServer*> getPrivateDnsLocked(const ServerIdentity& identity, 124 unsigned netId) REQUIRES(mPrivateDnsLock); 125 126 mutable std::mutex mPrivateDnsLock; 127 std::map<unsigned, PrivateDnsMode> mPrivateDnsModes GUARDED_BY(mPrivateDnsLock); 128 129 // Contains all servers for a network, along with their current validation status. 130 // In case a server is removed due to a configuration change, it remains in this map, 131 // but is marked inactive. 132 // Any pending validation threads will continue running because we have no way to cancel them. 133 std::map<unsigned, PrivateDnsTracker> mPrivateDnsTransports GUARDED_BY(mPrivateDnsLock); 134 135 void notifyValidationStateUpdate(const netdutils::IPSockAddr& sockaddr, Validation validation, 136 uint32_t netId) const REQUIRES(mPrivateDnsLock); 137 138 // TODO: fix the reentrancy problem. 139 PrivateDnsValidationObserver* mObserver GUARDED_BY(mPrivateDnsLock); 140 141 friend class PrivateDnsConfigurationTest; 142 143 // It's not const because PrivateDnsConfigurationTest needs to override it. 144 // TODO: make it const by dependency injection. 145 netdutils::BackoffSequence<>::Builder mBackoffBuilder = 146 netdutils::BackoffSequence<>::Builder() 147 .withInitialRetransmissionTime(std::chrono::seconds(60)) 148 .withMaximumRetransmissionTime(std::chrono::seconds(3600)); 149 150 struct RecordEntry { RecordEntryRecordEntry151 RecordEntry(uint32_t netId, const ServerIdentity& identity, Validation state) 152 : netId(netId), serverIdentity(identity), state(state) {} 153 154 const uint32_t netId; 155 const ServerIdentity serverIdentity; 156 const Validation state; 157 const std::chrono::system_clock::time_point timestamp = std::chrono::system_clock::now(); 158 }; 159 160 LockedRingBuffer<RecordEntry> mPrivateDnsLog{100}; 161 }; 162 163 } // namespace net 164 } // namespace android 165