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}