• 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 #ifndef DNS_DNS64CONFIGURATION_H_
18 #define DNS_DNS64CONFIGURATION_H_
19 
20 #include <netinet/in.h>
21 #include <condition_variable>
22 #include <cstdlib>
23 #include <mutex>
24 #include <unordered_map>
25 
26 #include <android-base/thread_annotations.h>
27 #include <netdutils/DumpWriter.h>
28 #include <netdutils/InternetAddresses.h>
29 #include <utils/RefBase.h>
30 
31 struct android_net_context;
32 
33 namespace android {
34 namespace net {
35 
36 /**
37  * This class handles RFC 7050 -style DNS64 prefix discovery.
38  *
39  * The ResolverController starts DNS64 prefix discovery when it observes a
40  * a network with only IPv6 nameservers. (It stops discovery whenever an IPv4
41  * nameserver is added or the network is deleted.)
42  *
43  * Each time prefix discovery is started, a new discoveryId is generated so
44  * that running resolution threads can notice they are no longer the most
45  * recent resolution attempt. This results in the backoff schedule of resolution
46  * being reset.
47  *
48  * Thread-safety: All public methods in this class MUST be thread-safe.
49  * (In other words: this class handles all its locking privately.)
50  */
51 class Dns64Configuration : virtual public RefBase {
52   public:
53     // Simple data struct for passing back packet NAT64 prefix event information to the
54     // Dns64PrefixCallback callback.
55     struct Nat64PrefixInfo {
56         unsigned netId;
57         bool added;
58         std::string prefixString;
59         uint8_t prefixLength;
60     };
61 
62     // Callback that is triggered for every NAT64 prefix event.
63     using Nat64PrefixCallback = std::function<void(const Nat64PrefixInfo&)>;
64 
65     using GetNetworkContextCallback = std::function<void(uint32_t, uint32_t, android_net_context*)>;
66 
67     // Parameters from RFC 7050 section 8.
68     static const char kIPv4OnlyHost[];  // "ipv4only.arpa."
69     static const char kIPv4Literal1[];  // 192.0.0.170
70     static const char kIPv4Literal2[];  // 192.0.0.171
71 
72     Dns64Configuration() = delete;
Dns64Configuration(GetNetworkContextCallback getNetworkCallback,Nat64PrefixCallback prefixCallback)73     Dns64Configuration(GetNetworkContextCallback getNetworkCallback,
74                        Nat64PrefixCallback prefixCallback)
75         : mGetNetworkContextCallback(std::move(getNetworkCallback)),
76           mPrefixCallback(std::move(prefixCallback)) {}
77     Dns64Configuration(const Dns64Configuration&) = delete;
78     Dns64Configuration(Dns64Configuration&&) = delete;
79     Dns64Configuration& operator=(const Dns64Configuration&) = delete;
80     Dns64Configuration& operator=(Dns64Configuration&&) = delete;
81 
82     void startPrefixDiscovery(unsigned netId);
83     void stopPrefixDiscovery(unsigned netId);
84     netdutils::IPPrefix getPrefix64(unsigned netId) const;
85 
86     int setPrefix64(unsigned netId, const netdutils::IPPrefix& pfx) EXCLUDES(mMutex);
87     int clearPrefix64(unsigned netId) EXCLUDES(mMutex);
88 
89     void dump(netdutils::DumpWriter& dw, unsigned netId);
90 
91   private:
92     struct Dns64Config {
Dns64ConfigDns64Config93         Dns64Config(unsigned pseudoRandomId, unsigned network)
94             : discoveryId(pseudoRandomId), netId(network) {}
95 
96         // ID of the discovery operation, or kNoDiscoveryId if no discovery was performed (i.e., the
97         // prefix was discovered and passed in via setPrefix64).
98         const unsigned int discoveryId;
99         const unsigned int netId;
100         netdutils::IPPrefix prefix64{};
101 
isFromPrefixDiscoveryDns64Config102         bool isFromPrefixDiscovery() const { return discoveryId != kNoDiscoveryId; }
103     };
104 
105     static constexpr int kNoDiscoveryId = 0;
106 
107     enum { PREFIX_REMOVED, PREFIX_ADDED };
108 
109     static bool doRfc7050PrefixDiscovery(const android_net_context& netcontext, Dns64Config* cfg);
110 
111     // Picks the next discovery ID. Never returns kNoDiscoveryId.
getNextId()112     unsigned getNextId() REQUIRES(mMutex) { return ++mNextId ? mNextId : ++mNextId; }
113 
114     netdutils::IPPrefix getPrefix64Locked(unsigned netId) const REQUIRES(mMutex);
115     bool isDiscoveryInProgress(const Dns64Config& cfg) const REQUIRES(mMutex);
116     bool reportNat64PrefixStatus(unsigned netId, bool added, const netdutils::IPPrefix& pfx)
117             REQUIRES(mMutex);
118 
119     bool shouldContinueDiscovery(const Dns64Config& cfg);
120     void recordDns64Config(const Dns64Config& cfg);
121     void removeDns64Config(unsigned netId) REQUIRES(mMutex);
122 
123     mutable std::mutex mMutex;
124     std::condition_variable mCv;
125     unsigned int mNextId GUARDED_BY(mMutex);
126     std::unordered_map<unsigned, Dns64Config> mDns64Configs GUARDED_BY(mMutex);
127     const GetNetworkContextCallback mGetNetworkContextCallback;
128     const Nat64PrefixCallback mPrefixCallback;
129 };
130 
131 }  // namespace net
132 }  // namespace android
133 
134 #endif  // DNS_DNS64CONFIGURATION_H_
135