Luke Huang | 7b26b20 | 2019-03-28 14:09:24 +0800 | [diff] [blame] | 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> |
Luke Huang | 9d2d25b | 2019-06-14 00:34:05 +0800 | [diff] [blame] | 27 | #include <netdutils/DumpWriter.h> |
| 28 | #include <netdutils/InternetAddresses.h> |
Luke Huang | 7b26b20 | 2019-03-28 14:09:24 +0800 | [diff] [blame] | 29 | |
| 30 | struct android_net_context; |
| 31 | |
| 32 | namespace android { |
| 33 | namespace 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 | */ |
| 50 | class 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 | |
| 85 | void dump(netdutils::DumpWriter& dw, unsigned netId); |
| 86 | |
| 87 | private: |
| 88 | struct Dns64Config { |
| 89 | Dns64Config(unsigned pseudoRandomId, unsigned network) |
| 90 | : discoveryId(pseudoRandomId), netId(network) {} |
| 91 | |
| 92 | const unsigned int discoveryId; |
| 93 | const unsigned int netId; |
| 94 | netdutils::IPPrefix prefix64{}; |
| 95 | }; |
| 96 | |
| 97 | enum { PREFIX_REMOVED, PREFIX_ADDED }; |
| 98 | |
| 99 | static bool doRfc7050PrefixDiscovery(const android_net_context& netcontext, Dns64Config* cfg); |
| 100 | |
| 101 | unsigned getNextId() REQUIRES(mMutex) { return mNextId++; } |
| 102 | netdutils::IPPrefix getPrefix64Locked(unsigned netId) const REQUIRES(mMutex); |
| 103 | bool isDiscoveryInProgress(const Dns64Config& cfg) const REQUIRES(mMutex); |
| 104 | bool reportNat64PrefixStatus(unsigned netId, bool added, const netdutils::IPPrefix& pfx) |
| 105 | REQUIRES(mMutex); |
| 106 | |
| 107 | bool shouldContinueDiscovery(const Dns64Config& cfg); |
| 108 | void recordDns64Config(const Dns64Config& cfg); |
| 109 | void removeDns64Config(unsigned netId) REQUIRES(mMutex); |
| 110 | |
| 111 | mutable std::mutex mMutex; |
| 112 | std::condition_variable mCv; |
| 113 | unsigned int mNextId GUARDED_BY(mMutex); |
| 114 | std::unordered_map<unsigned, Dns64Config> mDns64Configs GUARDED_BY(mMutex); |
| 115 | const GetNetworkContextCallback mGetNetworkContextCallback; |
| 116 | const Nat64PrefixCallback mPrefixCallback; |
| 117 | }; |
| 118 | |
| 119 | } // namespace net |
| 120 | } // namespace android |
| 121 | |
| 122 | #endif // DNS_DNS64CONFIGURATION_H_ |