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