| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef DNS_DNS64CONFIGURATION_H_ |
| #define DNS_DNS64CONFIGURATION_H_ |
| |
| #include <netinet/in.h> |
| #include <condition_variable> |
| #include <cstdlib> |
| #include <mutex> |
| #include <unordered_map> |
| |
| #include <android-base/thread_annotations.h> |
| #include <netdutils/DumpWriter.h> |
| #include <netdutils/InternetAddresses.h> |
| |
| struct android_net_context; |
| |
| namespace android { |
| namespace net { |
| |
| /** |
| * This class handles RFC 7050 -style DNS64 prefix discovery. |
| * |
| * The ResolverController starts DNS64 prefix discovery when it observes a |
| * a network with only IPv6 nameservers. (It stops discovery whenever an IPv4 |
| * nameserver is added or the network is deleted.) |
| * |
| * Each time prefix discovery is started, a new discoveryId is generated so |
| * that running resolution threads can notice they are no longer the most |
| * recent resolution attempt. This results in the backoff schedule of resolution |
| * being reset. |
| * |
| * Thread-safety: All public methods in this class MUST be thread-safe. |
| * (In other words: this class handles all its locking privately.) |
| */ |
| class Dns64Configuration { |
| public: |
| // Simple data struct for passing back packet NAT64 prefix event information to the |
| // Dns64PrefixCallback callback. |
| struct Nat64PrefixInfo { |
| unsigned netId; |
| bool added; |
| std::string prefixString; |
| uint8_t prefixLength; |
| }; |
| |
| // Callback that is triggered for every NAT64 prefix event. |
| using Nat64PrefixCallback = std::function<void(const Nat64PrefixInfo&)>; |
| |
| using GetNetworkContextCallback = std::function<void(uint32_t, uint32_t, android_net_context*)>; |
| |
| // Parameters from RFC 7050 section 8. |
| static const char kIPv4OnlyHost[]; // "ipv4only.arpa." |
| static const char kIPv4Literal1[]; // 192.0.0.170 |
| static const char kIPv4Literal2[]; // 192.0.0.171 |
| |
| Dns64Configuration() = delete; |
| Dns64Configuration(GetNetworkContextCallback getNetworkCallback, |
| Nat64PrefixCallback prefixCallback) |
| : mGetNetworkContextCallback(std::move(getNetworkCallback)), |
| mPrefixCallback(std::move(prefixCallback)) {} |
| Dns64Configuration(const Dns64Configuration&) = delete; |
| Dns64Configuration(Dns64Configuration&&) = delete; |
| Dns64Configuration& operator=(const Dns64Configuration&) = delete; |
| Dns64Configuration& operator=(Dns64Configuration&&) = delete; |
| |
| void startPrefixDiscovery(unsigned netId); |
| void stopPrefixDiscovery(unsigned netId); |
| netdutils::IPPrefix getPrefix64(unsigned netId) const; |
| |
| int setPrefix64(unsigned netId, const netdutils::IPPrefix& pfx) EXCLUDES(mMutex); |
| int clearPrefix64(unsigned netId) EXCLUDES(mMutex); |
| |
| void dump(netdutils::DumpWriter& dw, unsigned netId); |
| |
| private: |
| struct Dns64Config { |
| Dns64Config(unsigned pseudoRandomId, unsigned network) |
| : discoveryId(pseudoRandomId), netId(network) {} |
| |
| // ID of the discovery operation, or kNoDiscoveryId if no discovery was performed (i.e., the |
| // prefix was discovered and passed in via setPrefix64). |
| const unsigned int discoveryId; |
| const unsigned int netId; |
| netdutils::IPPrefix prefix64{}; |
| |
| bool isFromPrefixDiscovery() const { return discoveryId != kNoDiscoveryId; } |
| }; |
| |
| static constexpr int kNoDiscoveryId = 0; |
| |
| enum { PREFIX_REMOVED, PREFIX_ADDED }; |
| |
| static bool doRfc7050PrefixDiscovery(const android_net_context& netcontext, Dns64Config* cfg); |
| |
| // Picks the next discovery ID. Never returns kNoDiscoveryId. |
| unsigned getNextId() REQUIRES(mMutex) { return ++mNextId ? mNextId : ++mNextId; } |
| |
| netdutils::IPPrefix getPrefix64Locked(unsigned netId) const REQUIRES(mMutex); |
| bool isDiscoveryInProgress(const Dns64Config& cfg) const REQUIRES(mMutex); |
| bool reportNat64PrefixStatus(unsigned netId, bool added, const netdutils::IPPrefix& pfx) |
| REQUIRES(mMutex); |
| |
| bool shouldContinueDiscovery(const Dns64Config& cfg); |
| void recordDns64Config(const Dns64Config& cfg); |
| void removeDns64Config(unsigned netId) REQUIRES(mMutex); |
| |
| mutable std::mutex mMutex; |
| std::condition_variable mCv; |
| unsigned int mNextId GUARDED_BY(mMutex); |
| std::unordered_map<unsigned, Dns64Config> mDns64Configs GUARDED_BY(mMutex); |
| const GetNetworkContextCallback mGetNetworkContextCallback; |
| const Nat64PrefixCallback mPrefixCallback; |
| }; |
| |
| } // namespace net |
| } // namespace android |
| |
| #endif // DNS_DNS64CONFIGURATION_H_ |