Changeset View
Changeset View
Standalone View
Standalone View
src/netaddress.h
// Copyright (c) 2009-2016 The Bitcoin Core developers | // Copyright (c) 2009-2016 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#ifndef BITCOIN_NETADDRESS_H | #ifndef BITCOIN_NETADDRESS_H | ||||
#define BITCOIN_NETADDRESS_H | #define BITCOIN_NETADDRESS_H | ||||
#if defined(HAVE_CONFIG_H) | #if defined(HAVE_CONFIG_H) | ||||
#include <config/bitcoin-config.h> | #include <config/bitcoin-config.h> | ||||
#endif | #endif | ||||
#include <attributes.h> | |||||
#include <compat.h> | #include <compat.h> | ||||
#include <prevector.h> | |||||
#include <serialize.h> | #include <serialize.h> | ||||
#include <array> | |||||
#include <cstdint> | #include <cstdint> | ||||
#include <string> | #include <string> | ||||
#include <vector> | #include <vector> | ||||
/** | /** | ||||
* A network type. | * A network type. | ||||
* @note An address may belong to more than one network, for example `10.0.0.1` | * @note An address may belong to more than one network, for example `10.0.0.1` | ||||
* belongs to both `NET_UNROUTABLE` and `NET_IPV4`. | * belongs to both `NET_UNROUTABLE` and `NET_IPV4`. | ||||
Show All 11 Lines | enum Network { | ||||
NET_IPV4, | NET_IPV4, | ||||
/// IPv6 | /// IPv6 | ||||
NET_IPV6, | NET_IPV6, | ||||
/// TORv2 | /// TORv2 | ||||
NET_ONION, | NET_ONION, | ||||
/// A set of dummy addresses that map a name to an IPv6 address. These | /// A set of addresses that represent the hash of a string or FQDN. We use | ||||
/// addresses belong to RFC4193's fc00::/7 subnet (unique-local addresses). | /// them in CAddrMan to keep track of which DNS seeds were used. | ||||
/// We use them to map a string or FQDN to an IPv6 address in CAddrMan to | |||||
/// keep track of which DNS seeds were used. | |||||
NET_INTERNAL, | NET_INTERNAL, | ||||
/// Dummy value to indicate the number of NET_* constants. | /// Dummy value to indicate the number of NET_* constants. | ||||
NET_MAX, | NET_MAX, | ||||
}; | }; | ||||
/// Prefix of an IPv6 address when it contains an embedded IPv4 address. | |||||
/// Used when (un)serializing addresses in ADDRv1 format (pre-BIP155). | |||||
static const std::array<uint8_t, 12> IPV4_IN_IPV6_PREFIX{ | |||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF}}; | |||||
/// Prefix of an IPv6 address when it contains an embedded TORv2 address. | |||||
/// Used when (un)serializing addresses in ADDRv1 format (pre-BIP155). | |||||
/// Such dummy IPv6 addresses are guaranteed to not be publicly routable as they | |||||
/// fall under RFC4193's fc00::/7 subnet allocated to unique-local addresses. | |||||
static const std::array<uint8_t, 6> TORV2_IN_IPV6_PREFIX{ | |||||
{0xFD, 0x87, 0xD8, 0x7E, 0xEB, 0x43}}; | |||||
/// Prefix of an IPv6 address when it contains an embedded "internal" address. | |||||
/// Used when (un)serializing addresses in ADDRv1 format (pre-BIP155). | |||||
/// The prefix comes from 0xFD + SHA256("bitcoin")[0:5]. | |||||
/// Such dummy IPv6 addresses are guaranteed to not be publicly routable as they | |||||
/// fall under RFC4193's fc00::/7 subnet allocated to unique-local addresses. | |||||
static const std::array<uint8_t, 6> INTERNAL_IN_IPV6_PREFIX{ | |||||
// 0xFD + sha256("bitcoin")[0:5]. | |||||
{0xFD, 0x6B, 0x88, 0xC0, 0x87, 0x24}}; | |||||
/// Size of IPv4 address (in bytes). | |||||
static constexpr size_t ADDR_IPV4_SIZE = 4; | |||||
/// Size of IPv6 address (in bytes). | |||||
static constexpr size_t ADDR_IPV6_SIZE = 16; | |||||
/// Size of TORv2 address (in bytes). | |||||
static constexpr size_t ADDR_TORV2_SIZE = 10; | |||||
/// Size of "internal" (NET_INTERNAL) address (in bytes). | |||||
static constexpr size_t ADDR_INTERNAL_SIZE = 10; | |||||
/** | /** | ||||
* Network address. | * Network address. | ||||
*/ | */ | ||||
class CNetAddr { | class CNetAddr { | ||||
protected: | protected: | ||||
/** | /** | ||||
* Raw representation of the network address. | |||||
* In network byte order (big endian) for IPv4 and IPv6. | |||||
*/ | |||||
prevector<ADDR_IPV6_SIZE, uint8_t> m_addr{ADDR_IPV6_SIZE, 0x0}; | |||||
/** | |||||
* Network to which this address belongs. | * Network to which this address belongs. | ||||
*/ | */ | ||||
Network m_net{NET_IPV6}; | Network m_net{NET_IPV6}; | ||||
// in network byte order | |||||
uint8_t ip[16]; | |||||
// for scoped/link-local ipv6 addresses | // for scoped/link-local ipv6 addresses | ||||
uint32_t scopeId{0}; | uint32_t scopeId{0}; | ||||
public: | public: | ||||
CNetAddr(); | CNetAddr(); | ||||
explicit CNetAddr(const struct in_addr &ipv4Addr); | explicit CNetAddr(const struct in_addr &ipv4Addr); | ||||
void SetIP(const CNetAddr &ip); | void SetIP(const CNetAddr &ip); | ||||
/** | /** | ||||
* Set from a legacy IPv6 address. | * Set from a legacy IPv6 address. | ||||
* Legacy IPv6 address may be a normal IPv6 address, or another address | * Legacy IPv6 address may be a normal IPv6 address, or another address | ||||
* (e.g. IPv4) disguised as IPv6. This encoding is used in the legacy | * (e.g. IPv4) disguised as IPv6. This encoding is used in the legacy | ||||
* `addr` encoding. | * `addr` encoding. | ||||
*/ | */ | ||||
void SetLegacyIPv6(const uint8_t ipv6[16]); | void SetLegacyIPv6(Span<const uint8_t> ipv6); | ||||
/** | |||||
* Set raw IPv4 or IPv6 address (in network byte order) | |||||
* @note Only NET_IPV4 and NET_IPV6 are allowed for network. | |||||
*/ | |||||
void SetRaw(Network network, const uint8_t *data); | |||||
bool SetInternal(const std::string &name); | bool SetInternal(const std::string &name); | ||||
// for Tor addresses | // for Tor addresses | ||||
bool SetSpecial(const std::string &strName); | bool SetSpecial(const std::string &strName); | ||||
// INADDR_ANY equivalent | // INADDR_ANY equivalent | ||||
bool IsBindAny() const; | bool IsBindAny() const; | ||||
// IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0) | // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0) | ||||
Show All 35 Lines | public: | ||||
bool IsTor() const; | bool IsTor() const; | ||||
bool IsLocal() const; | bool IsLocal() const; | ||||
bool IsRoutable() const; | bool IsRoutable() const; | ||||
bool IsInternal() const; | bool IsInternal() const; | ||||
bool IsValid() const; | bool IsValid() const; | ||||
enum Network GetNetwork() const; | enum Network GetNetwork() const; | ||||
std::string ToString() const; | std::string ToString() const; | ||||
std::string ToStringIP() const; | std::string ToStringIP() const; | ||||
unsigned int GetByte(int n) const; | |||||
uint64_t GetHash() const; | uint64_t GetHash() const; | ||||
bool GetInAddr(struct in_addr *pipv4Addr) const; | bool GetInAddr(struct in_addr *pipv4Addr) const; | ||||
uint32_t GetNetClass() const; | uint32_t GetNetClass() const; | ||||
//! For IPv4, mapped IPv4, SIIT translated IPv4, Teredo, 6to4 tunneled | //! For IPv4, mapped IPv4, SIIT translated IPv4, Teredo, 6to4 tunneled | ||||
//! addresses, return the relevant IPv4 address as a uint32. | //! addresses, return the relevant IPv4 address as a uint32. | ||||
uint32_t GetLinkedIPv4() const; | uint32_t GetLinkedIPv4() const; | ||||
//! Whether this address has a linked IPv4 address (see GetLinkedIPv4()). | //! Whether this address has a linked IPv4 address (see GetLinkedIPv4()). | ||||
bool HasLinkedIPv4() const; | bool HasLinkedIPv4() const; | ||||
// The AS on the BGP path to the node we use to diversify | // The AS on the BGP path to the node we use to diversify | ||||
// peers in AddrMan bucketing based on the AS infrastructure. | // peers in AddrMan bucketing based on the AS infrastructure. | ||||
// The ip->AS mapping depends on how asmap is constructed. | // The ip->AS mapping depends on how asmap is constructed. | ||||
uint32_t GetMappedAS(const std::vector<bool> &asmap) const; | uint32_t GetMappedAS(const std::vector<bool> &asmap) const; | ||||
std::vector<uint8_t> GetGroup(const std::vector<bool> &asmap) const; | std::vector<uint8_t> GetGroup(const std::vector<bool> &asmap) const; | ||||
std::vector<uint8_t> GetAddrBytes() const { | std::vector<uint8_t> GetAddrBytes() const; | ||||
return {std::begin(ip), std::end(ip)}; | |||||
} | |||||
int GetReachabilityFrom(const CNetAddr *paddrPartner = nullptr) const; | int GetReachabilityFrom(const CNetAddr *paddrPartner = nullptr) const; | ||||
explicit CNetAddr(const struct in6_addr &pipv6Addr, | explicit CNetAddr(const struct in6_addr &pipv6Addr, | ||||
const uint32_t scope = 0); | const uint32_t scope = 0); | ||||
bool GetIn6Addr(struct in6_addr *pipv6Addr) const; | bool GetIn6Addr(struct in6_addr *pipv6Addr) const; | ||||
friend bool operator==(const CNetAddr &a, const CNetAddr &b); | friend bool operator==(const CNetAddr &a, const CNetAddr &b); | ||||
friend bool operator!=(const CNetAddr &a, const CNetAddr &b) { | friend bool operator!=(const CNetAddr &a, const CNetAddr &b) { | ||||
return !(a == b); | return !(a == b); | ||||
} | } | ||||
friend bool operator<(const CNetAddr &a, const CNetAddr &b); | friend bool operator<(const CNetAddr &a, const CNetAddr &b); | ||||
/** | /** | ||||
* Serialize to a stream. | * Serialize to a stream. | ||||
*/ | */ | ||||
template <typename Stream> void Serialize(Stream &s) const { s << ip; } | template <typename Stream> void Serialize(Stream &s) const { | ||||
SerializeV1Stream(s); | |||||
} | |||||
/** | /** | ||||
* Unserialize from a stream. | * Unserialize from a stream. | ||||
*/ | */ | ||||
template <typename Stream> void Unserialize(Stream &s) { | template <typename Stream> void Unserialize(Stream &s) { | ||||
uint8_t ip_temp[sizeof(ip)]; | UnserializeV1Stream(s); | ||||
s >> ip_temp; | } | ||||
friend class CSubNet; | |||||
private: | |||||
/** | |||||
* Size of CNetAddr when serialized as ADDRv1 (pre-BIP155) (in bytes). | |||||
*/ | |||||
static constexpr size_t V1_SERIALIZATION_SIZE = ADDR_IPV6_SIZE; | |||||
/** | |||||
* Serialize in pre-ADDRv2/BIP155 format to an array. | |||||
* Some addresses (e.g. TORv3) cannot be serialized in pre-BIP155 format. | |||||
*/ | |||||
void SerializeV1Array(uint8_t (&arr)[V1_SERIALIZATION_SIZE]) const { | |||||
size_t prefix_size; | |||||
switch (m_net) { | |||||
case NET_IPV6: | |||||
assert(m_addr.size() == sizeof(arr)); | |||||
memcpy(arr, m_addr.data(), m_addr.size()); | |||||
return; | |||||
case NET_IPV4: | |||||
prefix_size = sizeof(IPV4_IN_IPV6_PREFIX); | |||||
assert(prefix_size + m_addr.size() == sizeof(arr)); | |||||
memcpy(arr, IPV4_IN_IPV6_PREFIX.data(), prefix_size); | |||||
memcpy(arr + prefix_size, m_addr.data(), m_addr.size()); | |||||
return; | |||||
case NET_ONION: | |||||
prefix_size = sizeof(TORV2_IN_IPV6_PREFIX); | |||||
assert(prefix_size + m_addr.size() == sizeof(arr)); | |||||
memcpy(arr, TORV2_IN_IPV6_PREFIX.data(), prefix_size); | |||||
memcpy(arr + prefix_size, m_addr.data(), m_addr.size()); | |||||
return; | |||||
case NET_INTERNAL: | |||||
prefix_size = sizeof(INTERNAL_IN_IPV6_PREFIX); | |||||
assert(prefix_size + m_addr.size() == sizeof(arr)); | |||||
memcpy(arr, INTERNAL_IN_IPV6_PREFIX.data(), prefix_size); | |||||
memcpy(arr + prefix_size, m_addr.data(), m_addr.size()); | |||||
return; | |||||
case NET_UNROUTABLE: | |||||
case NET_MAX: | |||||
assert(false); | |||||
} // no default case, so the compiler can warn about missing cases | |||||
assert(false); | |||||
} | |||||
/** | |||||
* Serialize in pre-ADDRv2/BIP155 format to a stream. | |||||
* Some addresses (e.g. TORv3) cannot be serialized in pre-BIP155 format. | |||||
*/ | |||||
template <typename Stream> void SerializeV1Stream(Stream &s) const { | |||||
uint8_t serialized[V1_SERIALIZATION_SIZE]; | |||||
SerializeV1Array(serialized); | |||||
s << serialized; | |||||
} | |||||
/** | |||||
* Unserialize from a pre-ADDRv2/BIP155 format from an array. | |||||
*/ | |||||
void UnserializeV1Array(uint8_t (&arr)[V1_SERIALIZATION_SIZE]) { | |||||
// Use SetLegacyIPv6() so that m_net is set correctly. For example | // Use SetLegacyIPv6() so that m_net is set correctly. For example | ||||
// ::FFFF:0102:0304 should be set as m_net=NET_IPV4 (1.2.3.4). | // ::FFFF:0102:0304 should be set as m_net=NET_IPV4 (1.2.3.4). | ||||
SetLegacyIPv6(ip_temp); | SetLegacyIPv6(arr); | ||||
} | } | ||||
friend class CSubNet; | /** | ||||
* Unserialize from a pre-ADDRv2/BIP155 format from a stream. | |||||
*/ | |||||
template <typename Stream> void UnserializeV1Stream(Stream &s) { | |||||
uint8_t serialized[V1_SERIALIZATION_SIZE]; | |||||
s >> serialized; | |||||
UnserializeV1Array(serialized); | |||||
} | |||||
}; | }; | ||||
class CSubNet { | class CSubNet { | ||||
protected: | protected: | ||||
/// Network (base) address | /// Network (base) address | ||||
CNetAddr network; | CNetAddr network; | ||||
/// Netmask, in network byte order | /// Netmask, in network byte order | ||||
uint8_t netmask[16]; | uint8_t netmask[16]; | ||||
/// Is this value valid? (only used to signal parse errors) | /// Is this value valid? (only used to signal parse errors) | ||||
bool valid; | bool valid; | ||||
public: | public: | ||||
CSubNet(); | CSubNet(); | ||||
CSubNet(const CNetAddr &addr, int32_t mask); | CSubNet(const CNetAddr &addr, uint8_t mask); | ||||
CSubNet(const CNetAddr &addr, const CNetAddr &mask); | CSubNet(const CNetAddr &addr, const CNetAddr &mask); | ||||
// constructor for single ip subnet (<ipv4>/32 or <ipv6>/128) | // constructor for single ip subnet (<ipv4>/32 or <ipv6>/128) | ||||
explicit CSubNet(const CNetAddr &addr); | explicit CSubNet(const CNetAddr &addr); | ||||
bool Match(const CNetAddr &addr) const; | bool Match(const CNetAddr &addr) const; | ||||
std::string ToString() const; | std::string ToString() const; | ||||
▲ Show 20 Lines • Show All 49 Lines • Show Last 20 Lines |