99#include < config/bitcoin-config.h>
1010#endif
1111
12+ #include < attributes.h>
1213#include < compat.h>
14+ #include < prevector.h>
1315#include < serialize.h>
1416
17+ #include < array>
1518#include < cstdint>
1619#include < string>
1720#include < vector>
@@ -39,28 +42,66 @@ enum Network
3942 // / TORv2
4043 NET_ONION,
4144
42- // / A set of dummy addresses that map a name to an IPv6 address. These
43- // / addresses belong to RFC4193's fc00::/7 subnet (unique-local addresses).
44- // / We use them to map a string or FQDN to an IPv6 address in CAddrMan to
45- // / keep track of which DNS seeds were used.
45+ // / A set of addresses that represent the hash of a string or FQDN. We use
46+ // / them in CAddrMan to keep track of which DNS seeds were used.
4647 NET_INTERNAL,
4748
4849 // / Dummy value to indicate the number of NET_* constants.
4950 NET_MAX,
5051};
5152
53+ // / Prefix of an IPv6 address when it contains an embedded IPv4 address.
54+ // / Used when (un)serializing addresses in ADDRv1 format (pre-BIP155).
55+ static const std::array<uint8_t , 12 > IPV4_IN_IPV6_PREFIX{
56+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xFF , 0xFF
57+ };
58+
59+ // / Prefix of an IPv6 address when it contains an embedded TORv2 address.
60+ // / Used when (un)serializing addresses in ADDRv1 format (pre-BIP155).
61+ // / Such dummy IPv6 addresses are guaranteed to not be publicly routable as they
62+ // / fall under RFC4193's fc00::/7 subnet allocated to unique-local addresses.
63+ static const std::array<uint8_t , 6 > TORV2_IN_IPV6_PREFIX{
64+ 0xFD , 0x87 , 0xD8 , 0x7E , 0xEB , 0x43
65+ };
66+
67+ // / Prefix of an IPv6 address when it contains an embedded "internal" address.
68+ // / Used when (un)serializing addresses in ADDRv1 format (pre-BIP155).
69+ // / The prefix comes from 0xFD + SHA256("bitcoin")[0:5].
70+ // / Such dummy IPv6 addresses are guaranteed to not be publicly routable as they
71+ // / fall under RFC4193's fc00::/7 subnet allocated to unique-local addresses.
72+ static const std::array<uint8_t , 6 > INTERNAL_IN_IPV6_PREFIX{
73+ 0xFD , 0x6B , 0x88 , 0xC0 , 0x87 , 0x24 // 0xFD + sha256("bitcoin")[0:5].
74+ };
75+
76+ // / Size of IPv4 address (in bytes).
77+ static constexpr size_t ADDR_IPV4_SIZE = 4 ;
78+
79+ // / Size of IPv6 address (in bytes).
80+ static constexpr size_t ADDR_IPV6_SIZE = 16 ;
81+
82+ // / Size of TORv2 address (in bytes).
83+ static constexpr size_t ADDR_TORV2_SIZE = 10 ;
84+
85+ // / Size of "internal" (NET_INTERNAL) address (in bytes).
86+ static constexpr size_t ADDR_INTERNAL_SIZE = 10 ;
87+
5288/* *
5389 * Network address.
5490 */
5591class CNetAddr
5692{
5793 protected:
94+ /* *
95+ * Raw representation of the network address.
96+ * In network byte order (big endian) for IPv4 and IPv6.
97+ */
98+ prevector<ADDR_IPV6_SIZE, uint8_t > m_addr{ADDR_IPV6_SIZE, 0x0 };
99+
58100 /* *
59101 * Network to which this address belongs.
60102 */
61103 Network m_net{NET_IPV6};
62104
63- unsigned char ip[16 ]; // in network byte order
64105 uint32_t scopeId{0 }; // for scoped/link-local ipv6 addresses
65106
66107 public:
@@ -74,13 +115,7 @@ class CNetAddr
74115 * (e.g. IPv4) disguised as IPv6. This encoding is used in the legacy
75116 * `addr` encoding.
76117 */
77- void SetLegacyIPv6 (const uint8_t ipv6[16 ]);
78-
79- /* *
80- * Set raw IPv4 or IPv6 address (in network byte order)
81- * @note Only NET_IPV4 and NET_IPV6 are allowed for network.
82- */
83- void SetRaw (Network network, const uint8_t *data);
118+ void SetLegacyIPv6 (Span<const uint8_t > ipv6);
84119
85120 bool SetInternal (const std::string& name);
86121
@@ -111,7 +146,6 @@ class CNetAddr
111146 enum Network GetNetwork () const ;
112147 std::string ToString () const ;
113148 std::string ToStringIP () const ;
114- unsigned int GetByte (int n) const ;
115149 uint64_t GetHash () const ;
116150 bool GetInAddr (struct in_addr * pipv4Addr) const ;
117151 uint32_t GetNetClass () const ;
@@ -127,7 +161,7 @@ class CNetAddr
127161 uint32_t GetMappedAS (const std::vector<bool > &asmap) const ;
128162
129163 std::vector<unsigned char > GetGroup (const std::vector<bool > &asmap) const ;
130- std::vector<unsigned char > GetAddrBytes () const { return { std::begin (ip), std::end (ip)}; }
164+ std::vector<unsigned char > GetAddrBytes () const ;
131165 int GetReachabilityFrom (const CNetAddr *paddrPartner = nullptr ) const ;
132166
133167 explicit CNetAddr (const struct in6_addr & pipv6Addr, const uint32_t scope = 0 );
@@ -143,7 +177,7 @@ class CNetAddr
143177 template <typename Stream>
144178 void Serialize (Stream& s) const
145179 {
146- s << ip ;
180+ SerializeV1Stream (s) ;
147181 }
148182
149183 /* *
@@ -152,14 +186,92 @@ class CNetAddr
152186 template <typename Stream>
153187 void Unserialize (Stream& s)
154188 {
155- unsigned char ip_temp[sizeof (ip)];
156- s >> ip_temp;
189+ UnserializeV1Stream (s);
190+ }
191+
192+ friend class CSubNet ;
193+
194+ private:
195+ /* *
196+ * Size of CNetAddr when serialized as ADDRv1 (pre-BIP155) (in bytes).
197+ */
198+ static constexpr size_t V1_SERIALIZATION_SIZE = ADDR_IPV6_SIZE;
199+
200+ /* *
201+ * Serialize in pre-ADDRv2/BIP155 format to an array.
202+ * Some addresses (e.g. TORv3) cannot be serialized in pre-BIP155 format.
203+ */
204+ void SerializeV1Array (uint8_t (&arr)[V1_SERIALIZATION_SIZE]) const
205+ {
206+ size_t prefix_size;
207+
208+ switch (m_net) {
209+ case NET_IPV6:
210+ assert (m_addr.size () == sizeof (arr));
211+ memcpy (arr, m_addr.data (), m_addr.size ());
212+ return ;
213+ case NET_IPV4:
214+ prefix_size = sizeof (IPV4_IN_IPV6_PREFIX);
215+ assert (prefix_size + m_addr.size () == sizeof (arr));
216+ memcpy (arr, IPV4_IN_IPV6_PREFIX.data (), prefix_size);
217+ memcpy (arr + prefix_size, m_addr.data (), m_addr.size ());
218+ return ;
219+ case NET_ONION:
220+ prefix_size = sizeof (TORV2_IN_IPV6_PREFIX);
221+ assert (prefix_size + m_addr.size () == sizeof (arr));
222+ memcpy (arr, TORV2_IN_IPV6_PREFIX.data (), prefix_size);
223+ memcpy (arr + prefix_size, m_addr.data (), m_addr.size ());
224+ return ;
225+ case NET_INTERNAL:
226+ prefix_size = sizeof (INTERNAL_IN_IPV6_PREFIX);
227+ assert (prefix_size + m_addr.size () == sizeof (arr));
228+ memcpy (arr, INTERNAL_IN_IPV6_PREFIX.data (), prefix_size);
229+ memcpy (arr + prefix_size, m_addr.data (), m_addr.size ());
230+ return ;
231+ case NET_UNROUTABLE:
232+ case NET_MAX:
233+ assert (false );
234+ } // no default case, so the compiler can warn about missing cases
235+
236+ assert (false );
237+ }
238+
239+ /* *
240+ * Serialize in pre-ADDRv2/BIP155 format to a stream.
241+ * Some addresses (e.g. TORv3) cannot be serialized in pre-BIP155 format.
242+ */
243+ template <typename Stream>
244+ void SerializeV1Stream (Stream& s) const
245+ {
246+ uint8_t serialized[V1_SERIALIZATION_SIZE];
247+
248+ SerializeV1Array (serialized);
249+
250+ s << serialized;
251+ }
252+
253+ /* *
254+ * Unserialize from a pre-ADDRv2/BIP155 format from an array.
255+ */
256+ void UnserializeV1Array (uint8_t (&arr)[V1_SERIALIZATION_SIZE])
257+ {
157258 // Use SetLegacyIPv6() so that m_net is set correctly. For example
158259 // ::FFFF:0102:0304 should be set as m_net=NET_IPV4 (1.2.3.4).
159- SetLegacyIPv6 (ip_temp );
260+ SetLegacyIPv6 (arr );
160261 }
161262
162- friend class CSubNet ;
263+ /* *
264+ * Unserialize from a pre-ADDRv2/BIP155 format from a stream.
265+ */
266+ template <typename Stream>
267+ void UnserializeV1Stream (Stream& s)
268+ {
269+ uint8_t serialized[V1_SERIALIZATION_SIZE];
270+
271+ s >> serialized;
272+
273+ UnserializeV1Array (serialized);
274+ }
163275};
164276
165277class CSubNet
@@ -174,11 +286,11 @@ class CSubNet
174286
175287 public:
176288 CSubNet ();
177- CSubNet (const CNetAddr & addr, int32_t mask);
178- CSubNet (const CNetAddr & addr, const CNetAddr & mask);
289+ CSubNet (const CNetAddr& addr, uint8_t mask);
290+ CSubNet (const CNetAddr& addr, const CNetAddr& mask);
179291
180292 // constructor for single ip subnet (<ipv4>/32 or <ipv6>/128)
181- explicit CSubNet (const CNetAddr & addr);
293+ explicit CSubNet (const CNetAddr& addr);
182294
183295 bool Match (const CNetAddr &addr) const ;
184296
0 commit comments