• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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