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