You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
5.0 KiB
135 lines
5.0 KiB
/*
|
|
* 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>
|
|
#include <utils/RefBase.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 : virtual public RefBase {
|
|
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_
|