9
9
#include < config/bitcoin-config.h>
10
10
#endif
11
11
12
+ #include < attributes.h>
12
13
#include < compat.h>
14
+ #include < prevector.h>
13
15
#include < serialize.h>
14
16
17
+ #include < array>
15
18
#include < cstdint>
16
19
#include < string>
17
20
#include < vector>
@@ -39,28 +42,66 @@ enum Network
39
42
// / TORv2
40
43
NET_ONION,
41
44
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.
46
47
NET_INTERNAL,
47
48
48
49
// / Dummy value to indicate the number of NET_* constants.
49
50
NET_MAX,
50
51
};
51
52
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
+
52
88
/* *
53
89
* Network address.
54
90
*/
55
91
class CNetAddr
56
92
{
57
93
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
+
58
100
/* *
59
101
* Network to which this address belongs.
60
102
*/
61
103
Network m_net{NET_IPV6};
62
104
63
- unsigned char ip[16 ]; // in network byte order
64
105
uint32_t scopeId{0 }; // for scoped/link-local ipv6 addresses
65
106
66
107
public:
@@ -74,13 +115,7 @@ class CNetAddr
74
115
* (e.g. IPv4) disguised as IPv6. This encoding is used in the legacy
75
116
* `addr` encoding.
76
117
*/
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);
84
119
85
120
bool SetInternal (const std::string& name);
86
121
@@ -111,7 +146,6 @@ class CNetAddr
111
146
enum Network GetNetwork () const ;
112
147
std::string ToString () const ;
113
148
std::string ToStringIP () const ;
114
- unsigned int GetByte (int n) const ;
115
149
uint64_t GetHash () const ;
116
150
bool GetInAddr (struct in_addr * pipv4Addr) const ;
117
151
uint32_t GetNetClass () const ;
@@ -127,7 +161,7 @@ class CNetAddr
127
161
uint32_t GetMappedAS (const std::vector<bool > &asmap) const ;
128
162
129
163
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 ;
131
165
int GetReachabilityFrom (const CNetAddr *paddrPartner = nullptr ) const ;
132
166
133
167
explicit CNetAddr (const struct in6_addr & pipv6Addr, const uint32_t scope = 0 );
@@ -143,7 +177,7 @@ class CNetAddr
143
177
template <typename Stream>
144
178
void Serialize (Stream& s) const
145
179
{
146
- s << ip ;
180
+ SerializeV1Stream (s) ;
147
181
}
148
182
149
183
/* *
@@ -152,14 +186,92 @@ class CNetAddr
152
186
template <typename Stream>
153
187
void Unserialize (Stream& s)
154
188
{
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
+ {
157
258
// Use SetLegacyIPv6() so that m_net is set correctly. For example
158
259
// ::FFFF:0102:0304 should be set as m_net=NET_IPV4 (1.2.3.4).
159
- SetLegacyIPv6 (ip_temp );
260
+ SetLegacyIPv6 (arr );
160
261
}
161
262
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
+ }
163
275
};
164
276
165
277
class CSubNet
@@ -174,11 +286,11 @@ class CSubNet
174
286
175
287
public:
176
288
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);
179
291
180
292
// constructor for single ip subnet (<ipv4>/32 or <ipv6>/128)
181
- explicit CSubNet (const CNetAddr & addr);
293
+ explicit CSubNet (const CNetAddr& addr);
182
294
183
295
bool Match (const CNetAddr &addr) const ;
184
296
0 commit comments