bitcoin_subnet/subnet.rs
1crate::ix!();
2
3///--------------------
4#[derive(Hash,Clone)]
5pub struct SubNet {
6
7 /**
8 | Network (base) address
9 |
10 */
11 network: NetAddr,
12
13 /**
14 | Netmask, in network byte order
15 |
16 */
17 netmask: [u8; 16],
18
19 /**
20 | Is this value valid? (only used to signal
21 | parse errors)
22 |
23 */
24 valid: bool,
25}
26
27impl SubNet {
28
29 /**
30 | Construct from a given network start
31 | and number of bits (CIDR mask).
32 |
33 | -----------
34 | @param[in] addr
35 |
36 | Network start. Must be IPv4 or IPv6,
37 | otherwise an invalid subnet is created.
38 | ----------
39 | @param[in] mask
40 |
41 | CIDR mask, must be in [0, 32] for IPv4
42 | addresses and in [0, 128] for
43 |
44 | IPv6 addresses. Otherwise an invalid
45 | subnet is created.
46 |
47 */
48 pub fn new_from_net_addr(
49 addr: &NetAddr,
50 mask: Option<u8>) -> Self {
51
52 todo!();
53 /*
54 : sub_net(),
55
56 valid = (addr.IsIPv4() && mask <= ADDR_IPV4_SIZE * 8) ||
57 (addr.IsIPv6() && mask <= ADDR_IPV6_SIZE * 8);
58 if (!valid) {
59 return;
60 }
61
62 assert(mask <= sizeof(netmask) * 8);
63
64 network = addr;
65
66 uint8_t n = mask;
67 for (size_t i = 0; i < network.m_addr.size(); ++i) {
68 const uint8_t bits = n < 8 ? n : 8;
69 netmask[i] = (uint8_t)((uint8_t)0xFF << (8 - bits)); // Set first bits.
70 network.m_addr[i] &= netmask[i]; // Normalize network according to netmask.
71 n -= bits;
72 }
73 */
74 }
75
76 /**
77 | Construct from a given network start
78 | and mask.
79 |
80 | -----------
81 | @param[in] addr
82 |
83 | Network start. Must be IPv4 or IPv6,
84 | otherwise an invalid subnet is created.
85 | ----------
86 | @param[in] mask
87 |
88 | Network mask, must be of the same type
89 | as `addr` and not contain 0-bits followed
90 | by 1-bits. Otherwise an invalid subnet
91 | is created.
92 |
93 */
94 pub fn new_from_net_addr_and_mask(
95 addr: &NetAddr,
96 mask: &NetAddr) -> Self {
97
98 todo!();
99 /*
100 : sub_net(),
101
102 valid = (addr.IsIPv4() || addr.IsIPv6()) && addr.m_net == mask.m_net;
103 if (!valid) {
104 return;
105 }
106 // Check if `mask` contains 1-bits after 0-bits (which is an invalid netmask).
107 bool zeros_found = false;
108 for (auto b : mask.m_addr) {
109 const int num_bits = NetmaskBits(b);
110 if (num_bits == -1 || (zeros_found && num_bits != 0)) {
111 valid = false;
112 return;
113 }
114 if (num_bits < 8) {
115 zeros_found = true;
116 }
117 }
118
119 assert(mask.m_addr.size() <= sizeof(netmask));
120
121 memcpy(netmask, mask.m_addr.data(), mask.m_addr.size());
122
123 network = addr;
124
125 // Normalize network according to netmask
126 for (size_t x = 0; x < network.m_addr.size(); ++x) {
127 network.m_addr[x] &= netmask[x];
128 }
129 */
130 }
131
132 /**
133 | @return
134 |
135 | True if this subnet is valid, the specified
136 | address is valid, and the specified
137 | address belongs in this subnet.
138 |
139 */
140 pub fn match_(&self, addr: &NetAddr) -> bool {
141
142 todo!();
143 /*
144 if (!valid || !addr.IsValid() || network.m_net != addr.m_net)
145 return false;
146
147 switch (network.m_net) {
148 case NET_IPV4:
149 case NET_IPV6:
150 break;
151 case NET_ONION:
152 case NET_I2P:
153 case NET_CJDNS:
154 case NET_INTERNAL:
155 return addr == network;
156 case NET_UNROUTABLE:
157 case NET_MAX:
158 return false;
159 }
160
161 assert(network.m_addr.size() == addr.m_addr.size());
162 for (size_t x = 0; x < addr.m_addr.size(); ++x) {
163 if ((addr.m_addr[x] & netmask[x]) != network.m_addr[x]) {
164 return false;
165 }
166 }
167 return true;
168 */
169 }
170
171 pub fn to_string(&self) -> String {
172
173 todo!();
174 /*
175 std::string suffix;
176
177 switch (network.m_net) {
178 case NET_IPV4:
179 case NET_IPV6: {
180 assert(network.m_addr.size() <= sizeof(netmask));
181
182 uint8_t cidr = 0;
183
184 for (size_t i = 0; i < network.m_addr.size(); ++i) {
185 if (netmask[i] == 0x00) {
186 break;
187 }
188 cidr += NetmaskBits(netmask[i]);
189 }
190
191 suffix = strprintf("/%u", cidr);
192 break;
193 }
194 case NET_ONION:
195 case NET_I2P:
196 case NET_CJDNS:
197 case NET_INTERNAL:
198 case NET_UNROUTABLE:
199 case NET_MAX:
200 break;
201 }
202
203 return network.ToString() + suffix;
204 */
205 }
206
207 pub fn is_valid(&self) -> bool {
208
209 todo!();
210 /*
211 return valid;
212 */
213 }
214
215 pub fn sanity_check(&self) -> bool {
216
217 todo!();
218 /*
219 switch (network.m_net) {
220 case NET_IPV4:
221 case NET_IPV6:
222 break;
223 case NET_ONION:
224 case NET_I2P:
225 case NET_CJDNS:
226 return true;
227 case NET_INTERNAL:
228 case NET_UNROUTABLE:
229 case NET_MAX:
230 return false;
231 }
232
233 for (size_t x = 0; x < network.m_addr.size(); ++x) {
234 if (network.m_addr[x] & ~netmask[x]) return false;
235 }
236
237 return true;
238 */
239 }
240}
241
242///---------------------
243impl PartialEq<SubNet> for SubNet {
244
245 #[inline] fn eq(&self, other: &SubNet) -> bool {
246 todo!();
247 /*
248 return a.valid == b.valid && a.network == b.network && !memcmp(a.netmask, b.netmask, 16);
249 */
250 }
251}
252
253impl Eq for SubNet {}
254
255impl Ord for SubNet {
256
257 #[inline] fn cmp(&self, other: &SubNet) -> Ordering {
258 todo!();
259 /*
260 return (a.network < b.network || (a.network == b.network && memcmp(a.netmask, b.netmask, 16) < 0));
261 */
262 }
263}
264
265impl PartialOrd<SubNet> for SubNet {
266 #[inline] fn partial_cmp(&self, other: &SubNet) -> Option<Ordering> {
267 Some(self.cmp(other))
268 }
269}
270
271impl From<&NetAddr> for SubNet {
272
273 /**
274 | Construct a single-host subnet.
275 |
276 | -----------
277 | @param[in] addr
278 |
279 | The sole address to be contained in the
280 | subnet, can also be non-IPv[46].
281 |
282 */
283 fn from(addr: &NetAddr) -> Self {
284
285 todo!();
286 /*
287 : sub_net(),
288
289 switch (addr.m_net) {
290 case NET_IPV4:
291 case NET_IPV6:
292 valid = true;
293 assert(addr.m_addr.size() <= sizeof(netmask));
294 memset(netmask, 0xFF, addr.m_addr.size());
295 break;
296 case NET_ONION:
297 case NET_I2P:
298 case NET_CJDNS:
299 valid = true;
300 break;
301 case NET_INTERNAL:
302 case NET_UNROUTABLE:
303 case NET_MAX:
304 return;
305 }
306
307 network = addr;
308 */
309 }
310}
311
312impl Default for SubNet {
313
314 /**
315 | Construct an invalid subnet (empty,
316 | `Match()` always returns false).
317 |
318 */
319 fn default() -> Self {
320
321 todo!();
322 /*
323 : valid(false),
324
325 memset(netmask, 0, sizeof(netmask));
326 */
327 }
328}