134 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			134 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * 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_
 |