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/thread_annotations.h>
25 
26 #include "DnsTlsServer.h"
27 
28 namespace android {
29 namespace net {
30 
31 // The DNS over TLS mode on a specific netId.
32 enum class PrivateDnsMode : uint8_t { OFF, OPPORTUNISTIC, STRICT };
33 
34 // Validation status of a DNS over TLS server (on a specific netId).
35 enum class Validation : uint8_t { in_process, success, fail, unknown_server, unknown_netid };
36 
37 struct PrivateDnsStatus {
38     PrivateDnsMode mode;
39     std::map<DnsTlsServer, Validation, AddressComparator> serversMap;
40 
validatedServersPrivateDnsStatus41     std::list<DnsTlsServer> validatedServers() const {
42         std::list<DnsTlsServer> servers;
43 
44         for (const auto& pair : serversMap) {
45             if (pair.second == Validation::success) {
46                 servers.push_back(pair.first);
47             }
48         }
49         return servers;
50     }
51 };
52 
53 class PrivateDnsConfiguration {
54   public:
55     int set(int32_t netId, uint32_t mark, const std::vector<std::string>& servers,
56             const std::string& name, const std::string& caCert) EXCLUDES(mPrivateDnsLock);
57 
58     PrivateDnsStatus getStatus(unsigned netId) EXCLUDES(mPrivateDnsLock);
59 
60     void clear(unsigned netId) EXCLUDES(mPrivateDnsLock);
61 
62   private:
63     typedef std::map<DnsTlsServer, Validation, AddressComparator> PrivateDnsTracker;
64     typedef std::set<DnsTlsServer, AddressComparator> ThreadTracker;
65 
66     void validatePrivateDnsProvider(const DnsTlsServer& server, PrivateDnsTracker& tracker,
67                                     unsigned netId, uint32_t mark) REQUIRES(mPrivateDnsLock);
68 
69     bool recordPrivateDnsValidation(const DnsTlsServer& server, unsigned netId, bool success);
70 
71     bool needValidateThread(const DnsTlsServer& server, unsigned netId) REQUIRES(mPrivateDnsLock);
72     void cleanValidateThreadTracker(const DnsTlsServer& server, unsigned netId);
73 
74     // Start validation for newly added servers as well as any servers that have
75     // landed in Validation::fail state. Note that servers that have failed
76     // multiple validation attempts but for which there is still a validating
77     // thread running are marked as being Validation::in_process.
78     bool needsValidation(const PrivateDnsTracker& tracker, const DnsTlsServer& server);
79 
80     std::mutex mPrivateDnsLock;
81     std::map<unsigned, PrivateDnsMode> mPrivateDnsModes GUARDED_BY(mPrivateDnsLock);
82     // Structure for tracking the validation status of servers on a specific netId.
83     // Using the AddressComparator ensures at most one entry per IP address.
84     std::map<unsigned, PrivateDnsTracker> mPrivateDnsTransports GUARDED_BY(mPrivateDnsLock);
85     std::map<unsigned, ThreadTracker> mPrivateDnsValidateThreads GUARDED_BY(mPrivateDnsLock);
86 };
87 
88 extern PrivateDnsConfiguration gPrivateDnsConfiguration;
89 
90 }  // namespace net
91 }  // namespace android
92