/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ipnet-2.12.0/src/ipnet.rs
Line | Count | Source |
1 | | use alloc::vec::Vec; |
2 | | use core::cmp::{min, max}; |
3 | | use core::cmp::Ordering::{Less, Equal}; |
4 | | use core::convert::From; |
5 | | use core::fmt; |
6 | | use core::iter::FusedIterator; |
7 | | use core::option::Option::{Some, None}; |
8 | | #[cfg(not(feature = "std"))] |
9 | | use core::error::Error; |
10 | | #[cfg(feature = "std")] |
11 | | use std::error::Error; |
12 | | #[cfg(not(feature = "std"))] |
13 | | use core::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
14 | | #[cfg(feature = "std")] |
15 | | use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
16 | | |
17 | | use crate::ipext::{IpAdd, IpSub, IpStep, IpAddrRange, Ipv4AddrRange, Ipv6AddrRange}; |
18 | | use crate::mask::{ip_mask_to_prefix, ipv4_mask_to_prefix, ipv6_mask_to_prefix}; |
19 | | |
20 | | /// An IP network address, either IPv4 or IPv6. |
21 | | /// |
22 | | /// This enum can contain either an [`Ipv4Net`] or an [`Ipv6Net`]. A |
23 | | /// [`From`] implementation is provided to convert these into an |
24 | | /// `IpNet`. |
25 | | /// |
26 | | /// # Textual representation |
27 | | /// |
28 | | /// `IpNet` provides a [`FromStr`] implementation for parsing network |
29 | | /// addresses represented in CIDR notation. See [IETF RFC 4632] for the |
30 | | /// CIDR notation. |
31 | | /// |
32 | | /// [`Ipv4Net`]: struct.Ipv4Net.html |
33 | | /// [`Ipv6Net`]: struct.Ipv6Net.html |
34 | | /// [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html |
35 | | /// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html |
36 | | /// [IETF RFC 4632]: https://tools.ietf.org/html/rfc4632 |
37 | | /// |
38 | | /// # Examples |
39 | | /// |
40 | | /// ``` |
41 | | /// use std::net::IpAddr; |
42 | | /// use ipnet::IpNet; |
43 | | /// |
44 | | /// let net: IpNet = "10.1.1.0/24".parse().unwrap(); |
45 | | /// assert_eq!(Ok(net.network()), "10.1.1.0".parse()); |
46 | | /// |
47 | | /// let net: IpNet = "fd00::/32".parse().unwrap(); |
48 | | /// assert_eq!(Ok(net.network()), "fd00::".parse()); |
49 | | /// ``` |
50 | | #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] |
51 | | pub enum IpNet { |
52 | | V4(Ipv4Net), |
53 | | V6(Ipv6Net), |
54 | | } |
55 | | |
56 | | /// An IPv4 network address. |
57 | | /// |
58 | | /// See [`IpNet`] for a type encompassing both IPv4 and IPv6 network |
59 | | /// addresses. |
60 | | /// |
61 | | /// # Textual representation |
62 | | /// |
63 | | /// `Ipv4Net` provides a [`FromStr`] implementation for parsing network |
64 | | /// addresses represented in CIDR notation. See [IETF RFC 4632] for the |
65 | | /// CIDR notation. |
66 | | /// |
67 | | /// [`IpNet`]: enum.IpNet.html |
68 | | /// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html |
69 | | /// [IETF RFC 4632]: https://tools.ietf.org/html/rfc4632 |
70 | | /// |
71 | | /// # Examples |
72 | | /// |
73 | | /// ``` |
74 | | /// # #[cfg(feature = "std")] |
75 | | /// # use std::net::Ipv6Addr; |
76 | | /// # #[cfg(not(feature = "std"))] |
77 | | /// # use core::net::Ipv6Addr; |
78 | | /// use ipnet::Ipv4Net; |
79 | | /// |
80 | | /// let net: Ipv4Net = "10.1.1.0/24".parse().unwrap(); |
81 | | /// assert_eq!(Ok(net.network()), "10.1.1.0".parse()); |
82 | | /// ``` |
83 | | #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] |
84 | | pub struct Ipv4Net { |
85 | | addr: Ipv4Addr, |
86 | | prefix_len: u8, |
87 | | } |
88 | | |
89 | | /// An IPv6 network address. |
90 | | /// |
91 | | /// See [`IpNet`] for a type encompassing both IPv4 and IPv6 network |
92 | | /// addresses. |
93 | | /// |
94 | | /// # Textual representation |
95 | | /// |
96 | | /// `Ipv6Net` provides a [`FromStr`] implementation for parsing network |
97 | | /// addresses represented in CIDR notation. See [IETF RFC 4632] for the |
98 | | /// CIDR notation. |
99 | | /// |
100 | | /// [`IpNet`]: enum.IpNet.html |
101 | | /// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html |
102 | | /// [IETF RFC 4632]: https://tools.ietf.org/html/rfc4632 |
103 | | /// |
104 | | /// # Examples |
105 | | /// |
106 | | /// ``` |
107 | | /// use std::net::Ipv6Addr; |
108 | | /// use ipnet::Ipv6Net; |
109 | | /// |
110 | | /// let net: Ipv6Net = "fd00::/32".parse().unwrap(); |
111 | | /// assert_eq!(Ok(net.network()), "fd00::".parse()); |
112 | | /// ``` |
113 | | #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] |
114 | | pub struct Ipv6Net { |
115 | | addr: Ipv6Addr, |
116 | | prefix_len: u8, |
117 | | } |
118 | | |
119 | | /// An error which can be returned when the prefix length is invalid. |
120 | | /// |
121 | | /// Valid prefix lengths are 0 to 32 for IPv4 and 0 to 128 for IPv6. |
122 | | #[derive(Debug, Clone, PartialEq, Eq)] |
123 | | pub struct PrefixLenError; |
124 | | |
125 | | impl fmt::Display for PrefixLenError { |
126 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
127 | 0 | fmt.write_str("invalid IP prefix length") |
128 | 0 | } |
129 | | } |
130 | | |
131 | | impl Error for PrefixLenError {} |
132 | | |
133 | | impl IpNet { |
134 | | /// Creates a new IP network address from an `IpAddr` and prefix |
135 | | /// length. |
136 | | /// |
137 | | /// # Examples |
138 | | /// |
139 | | /// ``` |
140 | | /// use std::net::Ipv6Addr; |
141 | | /// use ipnet::{IpNet, PrefixLenError}; |
142 | | /// |
143 | | /// let net = IpNet::new(Ipv6Addr::LOCALHOST.into(), 48); |
144 | | /// assert!(net.is_ok()); |
145 | | /// |
146 | | /// let bad_prefix_len = IpNet::new(Ipv6Addr::LOCALHOST.into(), 129); |
147 | | /// assert_eq!(bad_prefix_len, Err(PrefixLenError)); |
148 | | /// ``` |
149 | 0 | pub fn new(ip: IpAddr, prefix_len: u8) -> Result<IpNet, PrefixLenError> { |
150 | 0 | Ok(match ip { |
151 | 0 | IpAddr::V4(a) => Ipv4Net::new(a, prefix_len)?.into(), |
152 | 0 | IpAddr::V6(a) => Ipv6Net::new(a, prefix_len)?.into(), |
153 | | }) |
154 | 0 | } |
155 | | |
156 | | /// Creates a new IP network address from an `IpAddr` and prefix |
157 | | /// length. If called from a const context it will verify prefix length |
158 | | /// at compile time. Otherwise it will panic at runtime if prefix length |
159 | | /// is incorrect for a given IpAddr type. |
160 | | /// |
161 | | /// # Examples |
162 | | /// |
163 | | /// ``` |
164 | | /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
165 | | /// use ipnet::{IpNet}; |
166 | | /// |
167 | | /// // This code is verified at compile time: |
168 | | /// const NET: IpNet = IpNet::new_assert(IpAddr::V4(Ipv4Addr::new(10, 1, 1, 0)), 24); |
169 | | /// assert_eq!(NET.prefix_len(), 24); |
170 | | /// |
171 | | /// // This code is verified at runtime: |
172 | | /// let net = IpNet::new_assert(Ipv6Addr::LOCALHOST.into(), 24); |
173 | | /// assert_eq!(net.prefix_len(), 24); |
174 | | /// |
175 | | /// // This code does not compile: |
176 | | /// // const BAD_PREFIX_LEN: IpNet = IpNet::new_assert(IpAddr::V4(Ipv4Addr::new(10, 1, 1, 0)), 33); |
177 | | /// |
178 | | /// // This code panics at runtime: |
179 | | /// // let bad_prefix_len = IpNet::new_assert(Ipv6Addr::LOCALHOST.into(), 129); |
180 | | /// ``` |
181 | 0 | pub const fn new_assert(ip: IpAddr, prefix_len: u8) -> IpNet { |
182 | 0 | match ip { |
183 | 0 | IpAddr::V4(a) => IpNet::V4(Ipv4Net::new_assert(a, prefix_len)), |
184 | 0 | IpAddr::V6(a) => IpNet::V6(Ipv6Net::new_assert(a, prefix_len)), |
185 | | } |
186 | 0 | } |
187 | | |
188 | | /// Creates a new IP network address from an `IpAddr` and netmask. |
189 | | /// |
190 | | /// # Examples |
191 | | /// |
192 | | /// ``` |
193 | | /// use std::net::Ipv6Addr; |
194 | | /// use ipnet::{IpNet, PrefixLenError}; |
195 | | /// |
196 | | /// let net = IpNet::with_netmask(Ipv6Addr::LOCALHOST.into(), Ipv6Addr::from(0xffff_ffff_ffff_0000_0000_0000_0000_0000).into()); |
197 | | /// assert!(net.is_ok()); |
198 | | /// |
199 | | /// let bad_prefix_len = IpNet::with_netmask(Ipv6Addr::LOCALHOST.into(), Ipv6Addr::from(0xffff_ffff_ffff_0000_0001_0000_0000_0000).into()); |
200 | | /// assert_eq!(bad_prefix_len, Err(PrefixLenError)); |
201 | | /// ``` |
202 | 0 | pub fn with_netmask(ip: IpAddr, netmask: IpAddr) -> Result<IpNet, PrefixLenError> { |
203 | 0 | let prefix = ip_mask_to_prefix(netmask)?; |
204 | 0 | Self::new(ip, prefix) |
205 | 0 | } |
206 | | |
207 | | /// Returns a copy of the network with the address truncated to the |
208 | | /// prefix length. |
209 | | /// |
210 | | /// # Examples |
211 | | /// |
212 | | /// ``` |
213 | | /// # use ipnet::IpNet; |
214 | | /// # |
215 | | /// assert_eq!( |
216 | | /// "192.168.12.34/16".parse::<IpNet>().unwrap().trunc(), |
217 | | /// "192.168.0.0/16".parse().unwrap() |
218 | | /// ); |
219 | | /// |
220 | | /// assert_eq!( |
221 | | /// "fd00::1:2:3:4/16".parse::<IpNet>().unwrap().trunc(), |
222 | | /// "fd00::/16".parse().unwrap() |
223 | | /// ); |
224 | | /// ``` |
225 | 0 | pub fn trunc(&self) -> IpNet { |
226 | 0 | match *self { |
227 | 0 | IpNet::V4(ref a) => IpNet::V4(a.trunc()), |
228 | 0 | IpNet::V6(ref a) => IpNet::V6(a.trunc()), |
229 | | } |
230 | 0 | } |
231 | | |
232 | | /// Returns the address. |
233 | 0 | pub fn addr(&self) -> IpAddr { |
234 | 0 | match *self { |
235 | 0 | IpNet::V4(ref a) => IpAddr::V4(a.addr), |
236 | 0 | IpNet::V6(ref a) => IpAddr::V6(a.addr), |
237 | | } |
238 | 0 | } |
239 | | |
240 | | /// Returns the prefix length. |
241 | 0 | pub fn prefix_len(&self) -> u8 { |
242 | 0 | match *self { |
243 | 0 | IpNet::V4(ref a) => a.prefix_len(), |
244 | 0 | IpNet::V6(ref a) => a.prefix_len(), |
245 | | } |
246 | 0 | } |
247 | | |
248 | | /// Returns the maximum valid prefix length. |
249 | 0 | pub fn max_prefix_len(&self) -> u8 { |
250 | 0 | match *self { |
251 | 0 | IpNet::V4(ref a) => a.max_prefix_len(), |
252 | 0 | IpNet::V6(ref a) => a.max_prefix_len(), |
253 | | } |
254 | 0 | } |
255 | | |
256 | | /// Returns the network mask. |
257 | | /// |
258 | | /// # Examples |
259 | | /// |
260 | | /// ``` |
261 | | /// # use std::net::IpAddr; |
262 | | /// # use ipnet::IpNet; |
263 | | /// # |
264 | | /// let net: IpNet = "10.1.0.0/20".parse().unwrap(); |
265 | | /// assert_eq!(Ok(net.netmask()), "255.255.240.0".parse()); |
266 | | /// |
267 | | /// let net: IpNet = "fd00::/24".parse().unwrap(); |
268 | | /// assert_eq!(Ok(net.netmask()), "ffff:ff00::".parse()); |
269 | | /// ``` |
270 | 0 | pub fn netmask(&self) -> IpAddr { |
271 | 0 | match *self { |
272 | 0 | IpNet::V4(ref a) => IpAddr::V4(a.netmask()), |
273 | 0 | IpNet::V6(ref a) => IpAddr::V6(a.netmask()), |
274 | | } |
275 | 0 | } |
276 | | |
277 | | /// Returns the host mask. |
278 | | /// |
279 | | /// # Examples |
280 | | /// |
281 | | /// ``` |
282 | | /// # use std::net::IpAddr; |
283 | | /// # use ipnet::IpNet; |
284 | | /// # |
285 | | /// let net: IpNet = "10.1.0.0/20".parse().unwrap(); |
286 | | /// assert_eq!(Ok(net.hostmask()), "0.0.15.255".parse()); |
287 | | /// |
288 | | /// let net: IpNet = "fd00::/24".parse().unwrap(); |
289 | | /// assert_eq!(Ok(net.hostmask()), "::ff:ffff:ffff:ffff:ffff:ffff:ffff".parse()); |
290 | | /// ``` |
291 | 0 | pub fn hostmask(&self) -> IpAddr { |
292 | 0 | match *self { |
293 | 0 | IpNet::V4(ref a) => IpAddr::V4(a.hostmask()), |
294 | 0 | IpNet::V6(ref a) => IpAddr::V6(a.hostmask()), |
295 | | } |
296 | 0 | } |
297 | | |
298 | | /// Returns the network address. |
299 | | /// |
300 | | /// # Examples |
301 | | /// |
302 | | /// ``` |
303 | | /// # use std::net::IpAddr; |
304 | | /// # use ipnet::IpNet; |
305 | | /// # |
306 | | /// let net: IpNet = "172.16.123.123/16".parse().unwrap(); |
307 | | /// assert_eq!(Ok(net.network()), "172.16.0.0".parse()); |
308 | | /// |
309 | | /// let net: IpNet = "fd00:1234:5678::/24".parse().unwrap(); |
310 | | /// assert_eq!(Ok(net.network()), "fd00:1200::".parse()); |
311 | | /// ``` |
312 | 0 | pub fn network(&self) -> IpAddr { |
313 | 0 | match *self { |
314 | 0 | IpNet::V4(ref a) => IpAddr::V4(a.network()), |
315 | 0 | IpNet::V6(ref a) => IpAddr::V6(a.network()), |
316 | | } |
317 | 0 | } |
318 | | |
319 | | /// Returns the broadcast address. |
320 | | /// |
321 | | /// # Examples |
322 | | /// |
323 | | /// ``` |
324 | | /// # use std::net::IpAddr; |
325 | | /// # use ipnet::IpNet; |
326 | | /// # |
327 | | /// let net: IpNet = "172.16.0.0/22".parse().unwrap(); |
328 | | /// assert_eq!(Ok(net.broadcast()), "172.16.3.255".parse()); |
329 | | /// |
330 | | /// let net: IpNet = "fd00:1234:5678::/24".parse().unwrap(); |
331 | | /// assert_eq!(Ok(net.broadcast()), "fd00:12ff:ffff:ffff:ffff:ffff:ffff:ffff".parse()); |
332 | | /// ``` |
333 | 0 | pub fn broadcast(&self) -> IpAddr { |
334 | 0 | match *self { |
335 | 0 | IpNet::V4(ref a) => IpAddr::V4(a.broadcast()), |
336 | 0 | IpNet::V6(ref a) => IpAddr::V6(a.broadcast()), |
337 | | } |
338 | 0 | } |
339 | | |
340 | | /// Returns the `IpNet` that contains this one. |
341 | | /// |
342 | | /// # Examples |
343 | | /// |
344 | | /// ``` |
345 | | /// # use ipnet::IpNet; |
346 | | /// # |
347 | | /// let n1: IpNet = "172.16.1.0/24".parse().unwrap(); |
348 | | /// let n2: IpNet = "172.16.0.0/23".parse().unwrap(); |
349 | | /// let n3: IpNet = "172.16.0.0/0".parse().unwrap(); |
350 | | /// |
351 | | /// assert_eq!(n1.supernet().unwrap(), n2); |
352 | | /// assert_eq!(n3.supernet(), None); |
353 | | /// |
354 | | /// let n1: IpNet = "fd00:ff00::/24".parse().unwrap(); |
355 | | /// let n2: IpNet = "fd00:fe00::/23".parse().unwrap(); |
356 | | /// let n3: IpNet = "fd00:fe00::/0".parse().unwrap(); |
357 | | /// |
358 | | /// assert_eq!(n1.supernet().unwrap(), n2); |
359 | | /// assert_eq!(n3.supernet(), None); |
360 | | /// ``` |
361 | 0 | pub fn supernet(&self) -> Option<IpNet> { |
362 | 0 | match *self { |
363 | 0 | IpNet::V4(ref a) => a.supernet().map(IpNet::V4), |
364 | 0 | IpNet::V6(ref a) => a.supernet().map(IpNet::V6), |
365 | | } |
366 | 0 | } |
367 | | |
368 | | /// Returns `true` if this network and the given network are |
369 | | /// children of the same supernet. |
370 | | /// |
371 | | /// # Examples |
372 | | /// |
373 | | /// ``` |
374 | | /// # use ipnet::IpNet; |
375 | | /// # |
376 | | /// let n4_1: IpNet = "10.1.0.0/24".parse().unwrap(); |
377 | | /// let n4_2: IpNet = "10.1.1.0/24".parse().unwrap(); |
378 | | /// let n4_3: IpNet = "10.1.2.0/24".parse().unwrap(); |
379 | | /// let n6_1: IpNet = "fd00::/18".parse().unwrap(); |
380 | | /// let n6_2: IpNet = "fd00:4000::/18".parse().unwrap(); |
381 | | /// let n6_3: IpNet = "fd00:8000::/18".parse().unwrap(); |
382 | | /// |
383 | | /// assert!( n4_1.is_sibling(&n4_2)); |
384 | | /// assert!(!n4_2.is_sibling(&n4_3)); |
385 | | /// assert!( n6_1.is_sibling(&n6_2)); |
386 | | /// assert!(!n6_2.is_sibling(&n6_3)); |
387 | | /// assert!(!n4_1.is_sibling(&n6_2)); |
388 | | /// ``` |
389 | 0 | pub fn is_sibling(&self, other: &IpNet) -> bool { |
390 | 0 | match (*self, *other) { |
391 | 0 | (IpNet::V4(ref a), IpNet::V4(ref b)) => a.is_sibling(b), |
392 | 0 | (IpNet::V6(ref a), IpNet::V6(ref b)) => a.is_sibling(b), |
393 | 0 | _ => false, |
394 | | } |
395 | 0 | } |
396 | | |
397 | | /// Return an `Iterator` over the host addresses in this network. |
398 | | /// |
399 | | /// # Examples |
400 | | /// |
401 | | /// ``` |
402 | | /// # use std::net::IpAddr; |
403 | | /// # use ipnet::IpNet; |
404 | | /// # |
405 | | /// let net: IpNet = "10.0.0.0/30".parse().unwrap(); |
406 | | /// assert_eq!(net.hosts().collect::<Vec<IpAddr>>(), vec![ |
407 | | /// "10.0.0.1".parse::<IpAddr>().unwrap(), |
408 | | /// "10.0.0.2".parse().unwrap(), |
409 | | /// ]); |
410 | | /// |
411 | | /// let net: IpNet = "10.0.0.0/31".parse().unwrap(); |
412 | | /// assert_eq!(net.hosts().collect::<Vec<IpAddr>>(), vec![ |
413 | | /// "10.0.0.0".parse::<IpAddr>().unwrap(), |
414 | | /// "10.0.0.1".parse().unwrap(), |
415 | | /// ]); |
416 | | /// |
417 | | /// let net: IpNet = "fd00::/126".parse().unwrap(); |
418 | | /// assert_eq!(net.hosts().collect::<Vec<IpAddr>>(), vec![ |
419 | | /// "fd00::".parse::<IpAddr>().unwrap(), |
420 | | /// "fd00::1".parse().unwrap(), |
421 | | /// "fd00::2".parse().unwrap(), |
422 | | /// "fd00::3".parse().unwrap(), |
423 | | /// ]); |
424 | | /// ``` |
425 | 0 | pub fn hosts(&self) -> IpAddrRange { |
426 | 0 | match *self { |
427 | 0 | IpNet::V4(ref a) => IpAddrRange::V4(a.hosts()), |
428 | 0 | IpNet::V6(ref a) => IpAddrRange::V6(a.hosts()), |
429 | | } |
430 | 0 | } |
431 | | |
432 | | /// Returns an `Iterator` over the subnets of this network with the |
433 | | /// given prefix length. |
434 | | /// |
435 | | /// # Examples |
436 | | /// |
437 | | /// ``` |
438 | | /// # use ipnet::{IpNet, PrefixLenError}; |
439 | | /// # |
440 | | /// let net: IpNet = "10.0.0.0/24".parse().unwrap(); |
441 | | /// assert_eq!(net.subnets(26).unwrap().collect::<Vec<IpNet>>(), vec![ |
442 | | /// "10.0.0.0/26".parse::<IpNet>().unwrap(), |
443 | | /// "10.0.0.64/26".parse().unwrap(), |
444 | | /// "10.0.0.128/26".parse().unwrap(), |
445 | | /// "10.0.0.192/26".parse().unwrap(), |
446 | | /// ]); |
447 | | /// |
448 | | /// let net: IpNet = "fd00::/16".parse().unwrap(); |
449 | | /// assert_eq!(net.subnets(18).unwrap().collect::<Vec<IpNet>>(), vec![ |
450 | | /// "fd00::/18".parse::<IpNet>().unwrap(), |
451 | | /// "fd00:4000::/18".parse().unwrap(), |
452 | | /// "fd00:8000::/18".parse().unwrap(), |
453 | | /// "fd00:c000::/18".parse().unwrap(), |
454 | | /// ]); |
455 | | /// |
456 | | /// let net: IpNet = "10.0.0.0/24".parse().unwrap(); |
457 | | /// assert_eq!(net.subnets(23), Err(PrefixLenError)); |
458 | | /// |
459 | | /// let net: IpNet = "10.0.0.0/24".parse().unwrap(); |
460 | | /// assert_eq!(net.subnets(33), Err(PrefixLenError)); |
461 | | /// |
462 | | /// let net: IpNet = "fd00::/16".parse().unwrap(); |
463 | | /// assert_eq!(net.subnets(15), Err(PrefixLenError)); |
464 | | /// |
465 | | /// let net: IpNet = "fd00::/16".parse().unwrap(); |
466 | | /// assert_eq!(net.subnets(129), Err(PrefixLenError)); |
467 | | /// ``` |
468 | 0 | pub fn subnets(&self, new_prefix_len: u8) -> Result<IpSubnets, PrefixLenError> { |
469 | 0 | match *self { |
470 | 0 | IpNet::V4(ref a) => a.subnets(new_prefix_len).map(IpSubnets::V4), |
471 | 0 | IpNet::V6(ref a) => a.subnets(new_prefix_len).map(IpSubnets::V6), |
472 | | } |
473 | 0 | } |
474 | | |
475 | | /// Test if a network address contains either another network |
476 | | /// address or an IP address. |
477 | | /// |
478 | | /// # Examples |
479 | | /// |
480 | | /// ``` |
481 | | /// # use std::net::IpAddr; |
482 | | /// # use ipnet::IpNet; |
483 | | /// # |
484 | | /// let net4: IpNet = "192.168.0.0/24".parse().unwrap(); |
485 | | /// let net4_yes: IpNet = "192.168.0.0/25".parse().unwrap(); |
486 | | /// let net4_no: IpNet = "192.168.0.0/23".parse().unwrap(); |
487 | | /// let ip4_yes: IpAddr = "192.168.0.1".parse().unwrap(); |
488 | | /// let ip4_no: IpAddr = "192.168.1.0".parse().unwrap(); |
489 | | /// |
490 | | /// assert!(net4.contains(&net4)); |
491 | | /// assert!(net4.contains(&net4_yes)); |
492 | | /// assert!(!net4.contains(&net4_no)); |
493 | | /// assert!(net4.contains(&ip4_yes)); |
494 | | /// assert!(!net4.contains(&ip4_no)); |
495 | | /// |
496 | | /// |
497 | | /// let net6: IpNet = "fd00::/16".parse().unwrap(); |
498 | | /// let net6_yes: IpNet = "fd00::/17".parse().unwrap(); |
499 | | /// let net6_no: IpNet = "fd00::/15".parse().unwrap(); |
500 | | /// let ip6_yes: IpAddr = "fd00::1".parse().unwrap(); |
501 | | /// let ip6_no: IpAddr = "fd01::".parse().unwrap(); |
502 | | /// |
503 | | /// assert!(net6.contains(&net6)); |
504 | | /// assert!(net6.contains(&net6_yes)); |
505 | | /// assert!(!net6.contains(&net6_no)); |
506 | | /// assert!(net6.contains(&ip6_yes)); |
507 | | /// assert!(!net6.contains(&ip6_no)); |
508 | | /// |
509 | | /// assert!(!net4.contains(&net6)); |
510 | | /// assert!(!net6.contains(&net4)); |
511 | | /// assert!(!net4.contains(&ip6_no)); |
512 | | /// assert!(!net6.contains(&ip4_no)); |
513 | | /// ``` |
514 | 0 | pub fn contains<T>(&self, other: T) -> bool where Self: Contains<T> { |
515 | 0 | Contains::contains(self, other) |
516 | 0 | } |
517 | | |
518 | | /// Aggregate a `Vec` of `IpNet`s and return the result as a new |
519 | | /// `Vec`. |
520 | | /// |
521 | | /// # Examples |
522 | | /// |
523 | | /// ``` |
524 | | /// # use ipnet::IpNet; |
525 | | /// # |
526 | | /// let nets = vec![ |
527 | | /// "10.0.0.0/24".parse::<IpNet>().unwrap(), |
528 | | /// "10.0.1.0/24".parse().unwrap(), |
529 | | /// "10.0.2.0/24".parse().unwrap(), |
530 | | /// "fd00::/18".parse().unwrap(), |
531 | | /// "fd00:4000::/18".parse().unwrap(), |
532 | | /// "fd00:8000::/18".parse().unwrap(), |
533 | | /// ]; |
534 | | /// |
535 | | /// assert_eq!(IpNet::aggregate(&nets), vec![ |
536 | | /// "10.0.0.0/23".parse::<IpNet>().unwrap(), |
537 | | /// "10.0.2.0/24".parse().unwrap(), |
538 | | /// "fd00::/17".parse().unwrap(), |
539 | | /// "fd00:8000::/18".parse().unwrap(), |
540 | | /// ]); |
541 | | /// ``` |
542 | 0 | pub fn aggregate(networks: &Vec<IpNet>) -> Vec<IpNet> { |
543 | | // It's 2.5x faster to split the input up and run them using the |
544 | | // specific IPv4 and IPV6 implementations. merge_intervals() and |
545 | | // the comparisons are much faster running over integers. |
546 | 0 | let mut ipv4nets: Vec<Ipv4Net> = Vec::new(); |
547 | 0 | let mut ipv6nets: Vec<Ipv6Net> = Vec::new(); |
548 | | |
549 | 0 | for n in networks { |
550 | 0 | match *n { |
551 | 0 | IpNet::V4(x) => ipv4nets.push(x), |
552 | 0 | IpNet::V6(x) => ipv6nets.push(x), |
553 | | } |
554 | | } |
555 | | |
556 | 0 | let mut res: Vec<IpNet> = Vec::new(); |
557 | 0 | let ipv4aggs = Ipv4Net::aggregate(&ipv4nets); |
558 | 0 | let ipv6aggs = Ipv6Net::aggregate(&ipv6nets); |
559 | 0 | res.extend::<Vec<IpNet>>(ipv4aggs.into_iter().map(IpNet::V4).collect::<Vec<IpNet>>()); |
560 | 0 | res.extend::<Vec<IpNet>>(ipv6aggs.into_iter().map(IpNet::V6).collect::<Vec<IpNet>>()); |
561 | 0 | res |
562 | 0 | } |
563 | | } |
564 | | |
565 | | impl Default for IpNet { |
566 | 0 | fn default() -> Self { |
567 | 0 | Self::V4(Ipv4Net::default()) |
568 | 0 | } |
569 | | } |
570 | | |
571 | | impl fmt::Debug for IpNet { |
572 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
573 | 0 | fmt::Display::fmt(self, fmt) |
574 | 0 | } |
575 | | } |
576 | | |
577 | | impl fmt::Display for IpNet { |
578 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
579 | 0 | match *self { |
580 | 0 | IpNet::V4(ref a) => a.fmt(fmt), |
581 | 0 | IpNet::V6(ref a) => a.fmt(fmt), |
582 | | } |
583 | 0 | } |
584 | | } |
585 | | |
586 | | impl From<Ipv4Net> for IpNet { |
587 | 0 | fn from(net: Ipv4Net) -> IpNet { |
588 | 0 | IpNet::V4(net) |
589 | 0 | } |
590 | | } |
591 | | |
592 | | impl From<Ipv6Net> for IpNet { |
593 | 0 | fn from(net: Ipv6Net) -> IpNet { |
594 | 0 | IpNet::V6(net) |
595 | 0 | } |
596 | | } |
597 | | |
598 | | impl From<IpAddr> for IpNet { |
599 | 0 | fn from(addr: IpAddr) -> IpNet { |
600 | 0 | match addr { |
601 | 0 | IpAddr::V4(a) => IpNet::V4(a.into()), |
602 | 0 | IpAddr::V6(a) => IpNet::V6(a.into()), |
603 | | } |
604 | 0 | } |
605 | | } |
606 | | |
607 | | impl Ipv4Net { |
608 | | /// Creates a new IPv4 network address from an `Ipv4Addr` and prefix |
609 | | /// length. |
610 | | /// |
611 | | /// # Examples |
612 | | /// |
613 | | /// ``` |
614 | | /// use std::net::Ipv4Addr; |
615 | | /// use ipnet::{Ipv4Net, PrefixLenError}; |
616 | | /// |
617 | | /// let net = Ipv4Net::new(Ipv4Addr::new(10, 1, 1, 0), 24); |
618 | | /// assert!(net.is_ok()); |
619 | | /// |
620 | | /// let bad_prefix_len = Ipv4Net::new(Ipv4Addr::new(10, 1, 1, 0), 33); |
621 | | /// assert_eq!(bad_prefix_len, Err(PrefixLenError)); |
622 | | /// ``` |
623 | | #[inline] |
624 | 0 | pub const fn new(ip: Ipv4Addr, prefix_len: u8) -> Result<Ipv4Net, PrefixLenError> { |
625 | 0 | if prefix_len > 32 { |
626 | 0 | return Err(PrefixLenError); |
627 | 0 | } |
628 | 0 | Ok(Ipv4Net { addr: ip, prefix_len: prefix_len }) |
629 | 0 | } Unexecuted instantiation: <ipnet::ipnet::Ipv4Net>::new Unexecuted instantiation: <ipnet::ipnet::Ipv4Net>::new |
630 | | |
631 | | /// Creates a new IPv4 network address from an `Ipv4Addr` and prefix |
632 | | /// length. If called from a const context it will verify prefix length |
633 | | /// at compile time. Otherwise it will panic at runtime if prefix length |
634 | | /// is not less then or equal to 32. |
635 | | /// |
636 | | /// # Examples |
637 | | /// |
638 | | /// ``` |
639 | | /// use std::net::Ipv4Addr; |
640 | | /// use ipnet::{Ipv4Net}; |
641 | | /// |
642 | | /// // This code is verified at compile time: |
643 | | /// const NET: Ipv4Net = Ipv4Net::new_assert(Ipv4Addr::new(10, 1, 1, 0), 24); |
644 | | /// assert_eq!(NET.prefix_len(), 24); |
645 | | /// |
646 | | /// // This code is verified at runtime: |
647 | | /// let net = Ipv4Net::new_assert(Ipv4Addr::new(10, 1, 1, 0), 24); |
648 | | /// assert_eq!(NET.prefix_len(), 24); |
649 | | /// |
650 | | /// // This code does not compile: |
651 | | /// // const BAD_PREFIX_LEN: Ipv4Net = Ipv4Net::new_assert(Ipv4Addr::new(10, 1, 1, 0), 33); |
652 | | /// |
653 | | /// // This code panics at runtime: |
654 | | /// // let bad_prefix_len = Ipv4Net::new_assert(Ipv4Addr::new(10, 1, 1, 0), 33); |
655 | | /// ``` |
656 | | #[inline] |
657 | 0 | pub const fn new_assert(ip: Ipv4Addr, prefix_len: u8) -> Ipv4Net { |
658 | 0 | assert!(prefix_len <= 32, "PREFIX_LEN must be less then or equal to 32 for Ipv4Net"); |
659 | 0 | Ipv4Net { addr: ip, prefix_len: prefix_len } |
660 | 0 | } |
661 | | |
662 | | /// Creates a new IPv4 network address from an `Ipv4Addr` and netmask. |
663 | | /// |
664 | | /// # Examples |
665 | | /// |
666 | | /// ``` |
667 | | /// use std::net::Ipv4Addr; |
668 | | /// use ipnet::{Ipv4Net, PrefixLenError}; |
669 | | /// |
670 | | /// let net = Ipv4Net::with_netmask(Ipv4Addr::new(10, 1, 1, 0), Ipv4Addr::new(255, 255, 255, 0)); |
671 | | /// assert!(net.is_ok()); |
672 | | /// |
673 | | /// let bad_prefix_len = Ipv4Net::with_netmask(Ipv4Addr::new(10, 1, 1, 0), Ipv4Addr::new(255, 255, 0, 1)); |
674 | | /// assert_eq!(bad_prefix_len, Err(PrefixLenError)); |
675 | | /// ``` |
676 | 0 | pub fn with_netmask(ip: Ipv4Addr, netmask: Ipv4Addr) -> Result<Ipv4Net, PrefixLenError> { |
677 | 0 | let prefix = ipv4_mask_to_prefix(netmask)?; |
678 | 0 | Self::new(ip, prefix) |
679 | 0 | } |
680 | | |
681 | | /// Returns a copy of the network with the address truncated to the |
682 | | /// prefix length. |
683 | | /// |
684 | | /// # Examples |
685 | | /// |
686 | | /// ``` |
687 | | /// # use ipnet::Ipv4Net; |
688 | | /// # |
689 | | /// assert_eq!( |
690 | | /// "192.168.12.34/16".parse::<Ipv4Net>().unwrap().trunc(), |
691 | | /// "192.168.0.0/16".parse().unwrap() |
692 | | /// ); |
693 | | /// ``` |
694 | 0 | pub fn trunc(&self) -> Ipv4Net { |
695 | 0 | Ipv4Net::new(self.network(), self.prefix_len).unwrap() |
696 | 0 | } |
697 | | |
698 | | /// Returns the address. |
699 | | #[inline] |
700 | 0 | pub const fn addr(&self) -> Ipv4Addr { |
701 | 0 | self.addr |
702 | 0 | } |
703 | | |
704 | | /// Returns the prefix length. |
705 | | #[inline] |
706 | 0 | pub const fn prefix_len(&self) -> u8 { |
707 | 0 | self.prefix_len |
708 | 0 | } |
709 | | |
710 | | /// Returns the maximum valid prefix length. |
711 | | #[inline] |
712 | 0 | pub const fn max_prefix_len(&self) -> u8 { |
713 | 0 | 32 |
714 | 0 | } |
715 | | |
716 | | /// Returns the network mask. |
717 | | /// |
718 | | /// # Examples |
719 | | /// |
720 | | /// ``` |
721 | | /// # use std::net::Ipv4Addr; |
722 | | /// # use ipnet::Ipv4Net; |
723 | | /// # |
724 | | /// let net: Ipv4Net = "10.1.0.0/20".parse().unwrap(); |
725 | | /// assert_eq!(Ok(net.netmask()), "255.255.240.0".parse()); |
726 | | /// ``` |
727 | 0 | pub fn netmask(&self) -> Ipv4Addr { |
728 | 0 | Ipv4Addr::from(self.netmask_u32()) |
729 | 0 | } |
730 | | |
731 | 0 | fn netmask_u32(&self) -> u32 { |
732 | 0 | u32::max_value().checked_shl(32 - self.prefix_len as u32).unwrap_or(0) |
733 | 0 | } |
734 | | |
735 | | /// Returns the host mask. |
736 | | /// |
737 | | /// # Examples |
738 | | /// |
739 | | /// ``` |
740 | | /// # use std::net::Ipv4Addr; |
741 | | /// # use ipnet::Ipv4Net; |
742 | | /// # |
743 | | /// let net: Ipv4Net = "10.1.0.0/20".parse().unwrap(); |
744 | | /// assert_eq!(Ok(net.hostmask()), "0.0.15.255".parse()); |
745 | | /// ``` |
746 | 0 | pub fn hostmask(&self) -> Ipv4Addr { |
747 | 0 | Ipv4Addr::from(self.hostmask_u32()) |
748 | 0 | } |
749 | | |
750 | 0 | fn hostmask_u32(&self) -> u32 { |
751 | 0 | u32::max_value().checked_shr(self.prefix_len as u32).unwrap_or(0) |
752 | 0 | } |
753 | | |
754 | | /// Returns the network address. |
755 | | /// |
756 | | /// # Examples |
757 | | /// |
758 | | /// ``` |
759 | | /// # use std::net::Ipv4Addr; |
760 | | /// # use ipnet::Ipv4Net; |
761 | | /// # |
762 | | /// let net: Ipv4Net = "172.16.123.123/16".parse().unwrap(); |
763 | | /// assert_eq!(Ok(net.network()), "172.16.0.0".parse()); |
764 | | /// ``` |
765 | 0 | pub fn network(&self) -> Ipv4Addr { |
766 | 0 | Ipv4Addr::from(u32::from(self.addr) & self.netmask_u32()) |
767 | 0 | } |
768 | | |
769 | | /// Returns the broadcast address. |
770 | | /// |
771 | | /// # Examples |
772 | | /// |
773 | | /// ``` |
774 | | /// # use std::net::Ipv4Addr; |
775 | | /// # use ipnet::Ipv4Net; |
776 | | /// # |
777 | | /// let net: Ipv4Net = "172.16.0.0/22".parse().unwrap(); |
778 | | /// assert_eq!(Ok(net.broadcast()), "172.16.3.255".parse()); |
779 | | /// ``` |
780 | 0 | pub fn broadcast(&self) -> Ipv4Addr { |
781 | 0 | Ipv4Addr::from(u32::from(self.addr) | self.hostmask_u32()) |
782 | 0 | } |
783 | | |
784 | | /// Returns the `Ipv4Net` that contains this one. |
785 | | /// |
786 | | /// # Examples |
787 | | /// |
788 | | /// ``` |
789 | | /// # use ipnet::Ipv4Net; |
790 | | /// # |
791 | | /// let n1: Ipv4Net = "172.16.1.0/24".parse().unwrap(); |
792 | | /// let n2: Ipv4Net = "172.16.0.0/23".parse().unwrap(); |
793 | | /// let n3: Ipv4Net = "172.16.0.0/0".parse().unwrap(); |
794 | | /// |
795 | | /// assert_eq!(n1.supernet().unwrap(), n2); |
796 | | /// assert_eq!(n3.supernet(), None); |
797 | | /// ``` |
798 | 0 | pub fn supernet(&self) -> Option<Ipv4Net> { |
799 | 0 | Ipv4Net::new(self.addr, self.prefix_len.wrapping_sub(1)).map(|n| n.trunc()).ok() |
800 | 0 | } |
801 | | |
802 | | /// Returns `true` if this network and the given network are |
803 | | /// children of the same supernet. |
804 | | /// |
805 | | /// # Examples |
806 | | /// |
807 | | /// ``` |
808 | | /// # use ipnet::Ipv4Net; |
809 | | /// # |
810 | | /// let n1: Ipv4Net = "10.1.0.0/24".parse().unwrap(); |
811 | | /// let n2: Ipv4Net = "10.1.1.0/24".parse().unwrap(); |
812 | | /// let n3: Ipv4Net = "10.1.2.0/24".parse().unwrap(); |
813 | | /// |
814 | | /// assert!(n1.is_sibling(&n2)); |
815 | | /// assert!(!n2.is_sibling(&n3)); |
816 | | /// ``` |
817 | 0 | pub fn is_sibling(&self, other: &Ipv4Net) -> bool { |
818 | 0 | self.prefix_len > 0 && |
819 | 0 | self.prefix_len == other.prefix_len && |
820 | 0 | self.supernet().unwrap().contains(other) |
821 | 0 | } |
822 | | |
823 | | /// Return an `Iterator` over the host addresses in this network. |
824 | | /// |
825 | | /// If the prefix length is less than 31 both the network address |
826 | | /// and broadcast address are excluded. These are only valid host |
827 | | /// addresses when the prefix length is 31. |
828 | | /// |
829 | | /// # Examples |
830 | | /// |
831 | | /// ``` |
832 | | /// # use std::net::Ipv4Addr; |
833 | | /// # use ipnet::Ipv4Net; |
834 | | /// # |
835 | | /// let net: Ipv4Net = "10.0.0.0/30".parse().unwrap(); |
836 | | /// assert_eq!(net.hosts().collect::<Vec<Ipv4Addr>>(), vec![ |
837 | | /// "10.0.0.1".parse::<Ipv4Addr>().unwrap(), |
838 | | /// "10.0.0.2".parse().unwrap(), |
839 | | /// ]); |
840 | | /// |
841 | | /// let net: Ipv4Net = "10.0.0.0/31".parse().unwrap(); |
842 | | /// assert_eq!(net.hosts().collect::<Vec<Ipv4Addr>>(), vec![ |
843 | | /// "10.0.0.0".parse::<Ipv4Addr>().unwrap(), |
844 | | /// "10.0.0.1".parse().unwrap(), |
845 | | /// ]); |
846 | | /// ``` |
847 | 0 | pub fn hosts(&self) -> Ipv4AddrRange { |
848 | 0 | let mut start = self.network(); |
849 | 0 | let mut end = self.broadcast(); |
850 | | |
851 | 0 | if self.prefix_len < 31 { |
852 | 0 | start = start.saturating_add(1); |
853 | 0 | end = end.saturating_sub(1); |
854 | 0 | } |
855 | | |
856 | 0 | Ipv4AddrRange::new(start, end) |
857 | 0 | } |
858 | | |
859 | | /// Returns an `Iterator` over the subnets of this network with the |
860 | | /// given prefix length. |
861 | | /// |
862 | | /// # Examples |
863 | | /// |
864 | | /// ``` |
865 | | /// # use ipnet::{Ipv4Net, PrefixLenError}; |
866 | | /// # |
867 | | /// let net: Ipv4Net = "10.0.0.0/24".parse().unwrap(); |
868 | | /// assert_eq!(net.subnets(26).unwrap().collect::<Vec<Ipv4Net>>(), vec![ |
869 | | /// "10.0.0.0/26".parse::<Ipv4Net>().unwrap(), |
870 | | /// "10.0.0.64/26".parse().unwrap(), |
871 | | /// "10.0.0.128/26".parse().unwrap(), |
872 | | /// "10.0.0.192/26".parse().unwrap(), |
873 | | /// ]); |
874 | | /// |
875 | | /// let net: Ipv4Net = "10.0.0.0/30".parse().unwrap(); |
876 | | /// assert_eq!(net.subnets(32).unwrap().collect::<Vec<Ipv4Net>>(), vec![ |
877 | | /// "10.0.0.0/32".parse::<Ipv4Net>().unwrap(), |
878 | | /// "10.0.0.1/32".parse().unwrap(), |
879 | | /// "10.0.0.2/32".parse().unwrap(), |
880 | | /// "10.0.0.3/32".parse().unwrap(), |
881 | | /// ]); |
882 | | /// |
883 | | /// let net: Ipv4Net = "10.0.0.0/24".parse().unwrap(); |
884 | | /// assert_eq!(net.subnets(23), Err(PrefixLenError)); |
885 | | /// |
886 | | /// let net: Ipv4Net = "10.0.0.0/24".parse().unwrap(); |
887 | | /// assert_eq!(net.subnets(33), Err(PrefixLenError)); |
888 | | /// ``` |
889 | 0 | pub fn subnets(&self, new_prefix_len: u8) -> Result<Ipv4Subnets, PrefixLenError> { |
890 | 0 | if self.prefix_len > new_prefix_len || new_prefix_len > 32 { |
891 | 0 | return Err(PrefixLenError); |
892 | 0 | } |
893 | | |
894 | 0 | Ok(Ipv4Subnets::new( |
895 | 0 | self.network(), |
896 | 0 | self.broadcast(), |
897 | 0 | new_prefix_len, |
898 | 0 | )) |
899 | 0 | } |
900 | | |
901 | | /// Test if a network address contains either another network |
902 | | /// address or an IP address. |
903 | | /// |
904 | | /// # Examples |
905 | | /// |
906 | | /// ``` |
907 | | /// # use std::net::Ipv4Addr; |
908 | | /// # use ipnet::Ipv4Net; |
909 | | /// # |
910 | | /// let net: Ipv4Net = "192.168.0.0/24".parse().unwrap(); |
911 | | /// let net_yes: Ipv4Net = "192.168.0.0/25".parse().unwrap(); |
912 | | /// let net_no: Ipv4Net = "192.168.0.0/23".parse().unwrap(); |
913 | | /// let ip_yes: Ipv4Addr = "192.168.0.1".parse().unwrap(); |
914 | | /// let ip_no: Ipv4Addr = "192.168.1.0".parse().unwrap(); |
915 | | /// |
916 | | /// assert!(net.contains(&net)); |
917 | | /// assert!(net.contains(&net_yes)); |
918 | | /// assert!(!net.contains(&net_no)); |
919 | | /// assert!(net.contains(&ip_yes)); |
920 | | /// assert!(!net.contains(&ip_no)); |
921 | | /// ``` |
922 | 0 | pub fn contains<T>(&self, other: T) -> bool where Self: Contains<T> { |
923 | 0 | Contains::contains(self, other) |
924 | 0 | } Unexecuted instantiation: <ipnet::ipnet::Ipv4Net>::contains::<&ipnet::ipnet::Ipv4Net> Unexecuted instantiation: <ipnet::ipnet::Ipv4Net>::contains::<&core::net::ip_addr::Ipv4Addr> |
925 | | |
926 | | // It is significantly faster to work on u32 than Ipv4Addr. |
927 | 0 | fn interval(&self) -> (u32, u32) { |
928 | 0 | ( |
929 | 0 | u32::from(self.network()), |
930 | 0 | u32::from(self.broadcast()).saturating_add(1), |
931 | 0 | ) |
932 | 0 | } |
933 | | |
934 | | /// Aggregate a `Vec` of `Ipv4Net`s and return the result as a new |
935 | | /// `Vec`. |
936 | | /// |
937 | | /// # Examples |
938 | | /// |
939 | | /// ``` |
940 | | /// # use ipnet::Ipv4Net; |
941 | | /// # |
942 | | /// let nets = vec![ |
943 | | /// "10.0.0.0/24".parse::<Ipv4Net>().unwrap(), |
944 | | /// "10.0.1.0/24".parse().unwrap(), |
945 | | /// "10.0.2.0/24".parse().unwrap(), |
946 | | /// ]; |
947 | | /// |
948 | | /// assert_eq!(Ipv4Net::aggregate(&nets), vec![ |
949 | | /// "10.0.0.0/23".parse::<Ipv4Net>().unwrap(), |
950 | | /// "10.0.2.0/24".parse().unwrap(), |
951 | | /// ]); |
952 | 0 | pub fn aggregate(networks: &Vec<Ipv4Net>) -> Vec<Ipv4Net> { |
953 | 0 | let mut intervals: Vec<(_, _)> = networks.iter().map(|n| n.interval()).collect(); |
954 | 0 | intervals = merge_intervals(intervals); |
955 | 0 | let mut res: Vec<Ipv4Net> = Vec::new(); |
956 | | |
957 | 0 | for (start, mut end) in intervals { |
958 | 0 | if end != core::u32::MAX { |
959 | 0 | end = end.saturating_sub(1) |
960 | 0 | } |
961 | 0 | let iter = Ipv4Subnets::new(start.into(), end.into(), 0); |
962 | 0 | res.extend(iter); |
963 | | } |
964 | 0 | res |
965 | 0 | } |
966 | | } |
967 | | |
968 | | impl Default for Ipv4Net { |
969 | 0 | fn default() -> Self { |
970 | 0 | Self { |
971 | 0 | addr: Ipv4Addr::from(0), |
972 | 0 | prefix_len: 0, |
973 | 0 | } |
974 | 0 | } |
975 | | } |
976 | | |
977 | | impl fmt::Debug for Ipv4Net { |
978 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
979 | 0 | fmt::Display::fmt(self, fmt) |
980 | 0 | } |
981 | | } |
982 | | |
983 | | impl fmt::Display for Ipv4Net { |
984 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
985 | 0 | write!(fmt, "{}/{}", self.addr, self.prefix_len) |
986 | 0 | } |
987 | | } |
988 | | |
989 | | impl From<Ipv4Addr> for Ipv4Net { |
990 | 0 | fn from(addr: Ipv4Addr) -> Ipv4Net { |
991 | 0 | Ipv4Net { addr, prefix_len: 32 } |
992 | 0 | } |
993 | | } |
994 | | |
995 | | impl Ipv6Net { |
996 | | /// Creates a new IPv6 network address from an `Ipv6Addr` and prefix |
997 | | /// length. |
998 | | /// |
999 | | /// # Examples |
1000 | | /// |
1001 | | /// ``` |
1002 | | /// use std::net::Ipv6Addr; |
1003 | | /// use ipnet::{Ipv6Net, PrefixLenError}; |
1004 | | /// |
1005 | | /// let net = Ipv6Net::new(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), 24); |
1006 | | /// assert!(net.is_ok()); |
1007 | | /// |
1008 | | /// let bad_prefix_len = Ipv6Net::new(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), 129); |
1009 | | /// assert_eq!(bad_prefix_len, Err(PrefixLenError)); |
1010 | | /// ``` |
1011 | | #[inline] |
1012 | 0 | pub const fn new(ip: Ipv6Addr, prefix_len: u8) -> Result<Ipv6Net, PrefixLenError> { |
1013 | 0 | if prefix_len > 128 { |
1014 | 0 | return Err(PrefixLenError); |
1015 | 0 | } |
1016 | 0 | Ok(Ipv6Net { addr: ip, prefix_len: prefix_len }) |
1017 | 0 | } Unexecuted instantiation: <ipnet::ipnet::Ipv6Net>::new Unexecuted instantiation: <ipnet::ipnet::Ipv6Net>::new |
1018 | | |
1019 | | /// Creates a new IPv6 network address from an `Ipv6Addr` and prefix |
1020 | | /// length. If called from a const context it will verify prefix length |
1021 | | /// at compile time. Otherwise it will panic at runtime if prefix length |
1022 | | /// is not less then or equal to 128. |
1023 | | /// |
1024 | | /// # Examples |
1025 | | /// |
1026 | | /// ``` |
1027 | | /// use std::net::Ipv6Addr; |
1028 | | /// use ipnet::{Ipv6Net}; |
1029 | | /// |
1030 | | /// // This code is verified at compile time: |
1031 | | /// const NET: Ipv6Net = Ipv6Net::new_assert(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), 24); |
1032 | | /// assert_eq!(NET.prefix_len(), 24); |
1033 | | /// |
1034 | | /// // This code is verified at runtime: |
1035 | | /// let net = Ipv6Net::new_assert(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), 24); |
1036 | | /// assert_eq!(net.prefix_len(), 24); |
1037 | | /// |
1038 | | /// // This code does not compile: |
1039 | | /// // const BAD_PREFIX_LEN: Ipv6Net = Ipv6Net::new_assert(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), 129); |
1040 | | /// |
1041 | | /// // This code panics at runtime: |
1042 | | /// // let bad_prefix_len = Ipv6Addr::new_assert(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), 129); |
1043 | | /// ``` |
1044 | | #[inline] |
1045 | 0 | pub const fn new_assert(ip: Ipv6Addr, prefix_len: u8) -> Ipv6Net { |
1046 | 0 | assert!(prefix_len <= 128, "PREFIX_LEN must be less then or equal to 128 for Ipv6Net"); |
1047 | 0 | Ipv6Net { addr: ip, prefix_len: prefix_len } |
1048 | 0 | } |
1049 | | |
1050 | | /// Creates a new IPv6 network address from an `Ipv6Addr` and netmask. |
1051 | | /// |
1052 | | /// # Examples |
1053 | | /// |
1054 | | /// ``` |
1055 | | /// use std::net::Ipv6Addr; |
1056 | | /// use ipnet::{Ipv6Net, PrefixLenError}; |
1057 | | /// |
1058 | | /// let net = Ipv6Net::with_netmask(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), Ipv6Addr::from(0xffff_ff00_0000_0000_0000_0000_0000_0000)); |
1059 | | /// assert!(net.is_ok()); |
1060 | | /// |
1061 | | /// let bad_prefix_len = Ipv6Net::with_netmask(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), Ipv6Addr::from(0xffff_ff00_0000_0000_0001_0000_0000_0000)); |
1062 | | /// assert_eq!(bad_prefix_len, Err(PrefixLenError)); |
1063 | | /// ``` |
1064 | 0 | pub fn with_netmask(ip: Ipv6Addr, netmask: Ipv6Addr) -> Result<Ipv6Net, PrefixLenError> { |
1065 | 0 | let prefix = ipv6_mask_to_prefix(netmask)?; |
1066 | 0 | Self::new(ip, prefix) |
1067 | 0 | } |
1068 | | |
1069 | | /// Returns a copy of the network with the address truncated to the |
1070 | | /// prefix length. |
1071 | | /// |
1072 | | /// # Examples |
1073 | | /// |
1074 | | /// ``` |
1075 | | /// # use ipnet::Ipv6Net; |
1076 | | /// # |
1077 | | /// assert_eq!( |
1078 | | /// "fd00::1:2:3:4/16".parse::<Ipv6Net>().unwrap().trunc(), |
1079 | | /// "fd00::/16".parse().unwrap() |
1080 | | /// ); |
1081 | | /// ``` |
1082 | 0 | pub fn trunc(&self) -> Ipv6Net { |
1083 | 0 | Ipv6Net::new(self.network(), self.prefix_len).unwrap() |
1084 | 0 | } |
1085 | | |
1086 | | /// Returns the address. |
1087 | | #[inline] |
1088 | 0 | pub const fn addr(&self) -> Ipv6Addr { |
1089 | 0 | self.addr |
1090 | 0 | } |
1091 | | |
1092 | | /// Returns the prefix length. |
1093 | | #[inline] |
1094 | 0 | pub const fn prefix_len(&self) -> u8 { |
1095 | 0 | self.prefix_len |
1096 | 0 | } |
1097 | | |
1098 | | /// Returns the maximum valid prefix length. |
1099 | | #[inline] |
1100 | 0 | pub const fn max_prefix_len(&self) -> u8 { |
1101 | 0 | 128 |
1102 | 0 | } |
1103 | | |
1104 | | /// Returns the network mask. |
1105 | | /// |
1106 | | /// # Examples |
1107 | | /// |
1108 | | /// ``` |
1109 | | /// # use std::net::Ipv6Addr; |
1110 | | /// # use ipnet::Ipv6Net; |
1111 | | /// # |
1112 | | /// let net: Ipv6Net = "fd00::/24".parse().unwrap(); |
1113 | | /// assert_eq!(Ok(net.netmask()), "ffff:ff00::".parse()); |
1114 | | /// ``` |
1115 | 0 | pub fn netmask(&self) -> Ipv6Addr { |
1116 | 0 | self.netmask_u128().into() |
1117 | 0 | } |
1118 | | |
1119 | 0 | fn netmask_u128(&self) -> u128 { |
1120 | 0 | u128::max_value().checked_shl((128 - self.prefix_len) as u32).unwrap_or(u128::min_value()) |
1121 | 0 | } |
1122 | | |
1123 | | /// Returns the host mask. |
1124 | | /// |
1125 | | /// # Examples |
1126 | | /// |
1127 | | /// ``` |
1128 | | /// # use std::net::Ipv6Addr; |
1129 | | /// # use ipnet::Ipv6Net; |
1130 | | /// # |
1131 | | /// let net: Ipv6Net = "fd00::/24".parse().unwrap(); |
1132 | | /// assert_eq!(Ok(net.hostmask()), "::ff:ffff:ffff:ffff:ffff:ffff:ffff".parse()); |
1133 | | /// ``` |
1134 | 0 | pub fn hostmask(&self) -> Ipv6Addr { |
1135 | 0 | self.hostmask_u128().into() |
1136 | 0 | } |
1137 | | |
1138 | 0 | fn hostmask_u128(&self) -> u128 { |
1139 | 0 | u128::max_value().checked_shr(self.prefix_len as u32).unwrap_or(u128::min_value()) |
1140 | 0 | } |
1141 | | |
1142 | | /// Returns the network address. |
1143 | | /// |
1144 | | /// # Examples |
1145 | | /// |
1146 | | /// ``` |
1147 | | /// # use std::net::Ipv6Addr; |
1148 | | /// # use ipnet::Ipv6Net; |
1149 | | /// # |
1150 | | /// let net: Ipv6Net = "fd00:1234:5678::/24".parse().unwrap(); |
1151 | | /// assert_eq!(Ok(net.network()), "fd00:1200::".parse()); |
1152 | | /// ``` |
1153 | 0 | pub fn network(&self) -> Ipv6Addr { |
1154 | 0 | (u128::from(self.addr) & self.netmask_u128()).into() |
1155 | 0 | } |
1156 | | |
1157 | | /// Returns the last address. |
1158 | | /// |
1159 | | /// Technically there is no such thing as a broadcast address for |
1160 | | /// IPv6. The name is used for consistency with colloquial usage. |
1161 | | /// |
1162 | | /// # Examples |
1163 | | /// |
1164 | | /// ``` |
1165 | | /// # use std::net::Ipv6Addr; |
1166 | | /// # use ipnet::Ipv6Net; |
1167 | | /// # |
1168 | | /// let net: Ipv6Net = "fd00:1234:5678::/24".parse().unwrap(); |
1169 | | /// assert_eq!(Ok(net.broadcast()), "fd00:12ff:ffff:ffff:ffff:ffff:ffff:ffff".parse()); |
1170 | | /// ``` |
1171 | 0 | pub fn broadcast(&self) -> Ipv6Addr { |
1172 | 0 | (u128::from(self.addr) | self.hostmask_u128()).into() |
1173 | 0 | } |
1174 | | |
1175 | | /// Returns the `Ipv6Net` that contains this one. |
1176 | | /// |
1177 | | /// # Examples |
1178 | | /// |
1179 | | /// ``` |
1180 | | /// # use std::str::FromStr; |
1181 | | /// # use ipnet::Ipv6Net; |
1182 | | /// # |
1183 | | /// let n1: Ipv6Net = "fd00:ff00::/24".parse().unwrap(); |
1184 | | /// let n2: Ipv6Net = "fd00:fe00::/23".parse().unwrap(); |
1185 | | /// let n3: Ipv6Net = "fd00:fe00::/0".parse().unwrap(); |
1186 | | /// |
1187 | | /// assert_eq!(n1.supernet().unwrap(), n2); |
1188 | | /// assert_eq!(n3.supernet(), None); |
1189 | | /// ``` |
1190 | 0 | pub fn supernet(&self) -> Option<Ipv6Net> { |
1191 | 0 | Ipv6Net::new(self.addr, self.prefix_len.wrapping_sub(1)).map(|n| n.trunc()).ok() |
1192 | 0 | } |
1193 | | |
1194 | | /// Returns `true` if this network and the given network are |
1195 | | /// children of the same supernet. |
1196 | | /// |
1197 | | /// # Examples |
1198 | | /// |
1199 | | /// ``` |
1200 | | /// # use ipnet::Ipv6Net; |
1201 | | /// # |
1202 | | /// let n1: Ipv6Net = "fd00::/18".parse().unwrap(); |
1203 | | /// let n2: Ipv6Net = "fd00:4000::/18".parse().unwrap(); |
1204 | | /// let n3: Ipv6Net = "fd00:8000::/18".parse().unwrap(); |
1205 | | /// |
1206 | | /// assert!(n1.is_sibling(&n2)); |
1207 | | /// assert!(!n2.is_sibling(&n3)); |
1208 | | /// ``` |
1209 | 0 | pub fn is_sibling(&self, other: &Ipv6Net) -> bool { |
1210 | 0 | self.prefix_len > 0 && |
1211 | 0 | self.prefix_len == other.prefix_len && |
1212 | 0 | self.supernet().unwrap().contains(other) |
1213 | 0 | } |
1214 | | |
1215 | | /// Return an `Iterator` over the host addresses in this network. |
1216 | | /// |
1217 | | /// # Examples |
1218 | | /// |
1219 | | /// ``` |
1220 | | /// # use std::net::Ipv6Addr; |
1221 | | /// # use ipnet::Ipv6Net; |
1222 | | /// # |
1223 | | /// let net: Ipv6Net = "fd00::/126".parse().unwrap(); |
1224 | | /// assert_eq!(net.hosts().collect::<Vec<Ipv6Addr>>(), vec![ |
1225 | | /// "fd00::".parse::<Ipv6Addr>().unwrap(), |
1226 | | /// "fd00::1".parse().unwrap(), |
1227 | | /// "fd00::2".parse().unwrap(), |
1228 | | /// "fd00::3".parse().unwrap(), |
1229 | | /// ]); |
1230 | | /// ``` |
1231 | 0 | pub fn hosts(&self) -> Ipv6AddrRange { |
1232 | 0 | Ipv6AddrRange::new(self.network(), self.broadcast()) |
1233 | 0 | } |
1234 | | |
1235 | | /// Returns an `Iterator` over the subnets of this network with the |
1236 | | /// given prefix length. |
1237 | | /// |
1238 | | /// # Examples |
1239 | | /// |
1240 | | /// ``` |
1241 | | /// # use ipnet::{Ipv6Net, PrefixLenError}; |
1242 | | /// # |
1243 | | /// let net: Ipv6Net = "fd00::/16".parse().unwrap(); |
1244 | | /// assert_eq!(net.subnets(18).unwrap().collect::<Vec<Ipv6Net>>(), vec![ |
1245 | | /// "fd00::/18".parse::<Ipv6Net>().unwrap(), |
1246 | | /// "fd00:4000::/18".parse().unwrap(), |
1247 | | /// "fd00:8000::/18".parse().unwrap(), |
1248 | | /// "fd00:c000::/18".parse().unwrap(), |
1249 | | /// ]); |
1250 | | /// |
1251 | | /// let net: Ipv6Net = "fd00::/126".parse().unwrap(); |
1252 | | /// assert_eq!(net.subnets(128).unwrap().collect::<Vec<Ipv6Net>>(), vec![ |
1253 | | /// "fd00::/128".parse::<Ipv6Net>().unwrap(), |
1254 | | /// "fd00::1/128".parse().unwrap(), |
1255 | | /// "fd00::2/128".parse().unwrap(), |
1256 | | /// "fd00::3/128".parse().unwrap(), |
1257 | | /// ]); |
1258 | | /// |
1259 | | /// let net: Ipv6Net = "fd00::/16".parse().unwrap(); |
1260 | | /// assert_eq!(net.subnets(15), Err(PrefixLenError)); |
1261 | | /// |
1262 | | /// let net: Ipv6Net = "fd00::/16".parse().unwrap(); |
1263 | | /// assert_eq!(net.subnets(129), Err(PrefixLenError)); |
1264 | | /// ``` |
1265 | 0 | pub fn subnets(&self, new_prefix_len: u8) -> Result<Ipv6Subnets, PrefixLenError> { |
1266 | 0 | if self.prefix_len > new_prefix_len || new_prefix_len > 128 { |
1267 | 0 | return Err(PrefixLenError); |
1268 | 0 | } |
1269 | | |
1270 | 0 | Ok(Ipv6Subnets::new( |
1271 | 0 | self.network(), |
1272 | 0 | self.broadcast(), |
1273 | 0 | new_prefix_len, |
1274 | 0 | )) |
1275 | 0 | } |
1276 | | |
1277 | | /// Test if a network address contains either another network |
1278 | | /// address or an IP address. |
1279 | | /// |
1280 | | /// # Examples |
1281 | | /// |
1282 | | /// ``` |
1283 | | /// # use std::net::Ipv6Addr; |
1284 | | /// # use ipnet::Ipv6Net; |
1285 | | /// # |
1286 | | /// let net: Ipv6Net = "fd00::/16".parse().unwrap(); |
1287 | | /// let net_yes: Ipv6Net = "fd00::/17".parse().unwrap(); |
1288 | | /// let net_no: Ipv6Net = "fd00::/15".parse().unwrap(); |
1289 | | /// let ip_yes: Ipv6Addr = "fd00::1".parse().unwrap(); |
1290 | | /// let ip_no: Ipv6Addr = "fd01::".parse().unwrap(); |
1291 | | /// |
1292 | | /// assert!(net.contains(&net)); |
1293 | | /// assert!(net.contains(&net_yes)); |
1294 | | /// assert!(!net.contains(&net_no)); |
1295 | | /// assert!(net.contains(&ip_yes)); |
1296 | | /// assert!(!net.contains(&ip_no)); |
1297 | | /// ``` |
1298 | 0 | pub fn contains<T>(&self, other: T) -> bool where Self: Contains<T> { |
1299 | 0 | Contains::contains(self, other) |
1300 | 0 | } Unexecuted instantiation: <ipnet::ipnet::Ipv6Net>::contains::<&ipnet::ipnet::Ipv6Net> Unexecuted instantiation: <ipnet::ipnet::Ipv6Net>::contains::<&core::net::ip_addr::Ipv6Addr> |
1301 | | |
1302 | | // It is significantly faster to work on u128 that Ipv6Addr. |
1303 | 0 | fn interval(&self) -> (u128, u128) { |
1304 | 0 | ( |
1305 | 0 | u128::from(self.network()), |
1306 | 0 | u128::from(self.broadcast()).saturating_add(1), |
1307 | 0 | ) |
1308 | 0 | } |
1309 | | |
1310 | | /// Aggregate a `Vec` of `Ipv6Net`s and return the result as a new |
1311 | | /// `Vec`. |
1312 | | /// |
1313 | | /// # Examples |
1314 | | /// |
1315 | | /// ``` |
1316 | | /// # use ipnet::Ipv6Net; |
1317 | | /// # |
1318 | | /// let nets = vec![ |
1319 | | /// "fd00::/18".parse::<Ipv6Net>().unwrap(), |
1320 | | /// "fd00:4000::/18".parse().unwrap(), |
1321 | | /// "fd00:8000::/18".parse().unwrap(), |
1322 | | /// ]; |
1323 | | /// assert_eq!(Ipv6Net::aggregate(&nets), vec![ |
1324 | | /// "fd00::/17".parse::<Ipv6Net>().unwrap(), |
1325 | | /// "fd00:8000::/18".parse().unwrap(), |
1326 | | /// ]); |
1327 | | /// ``` |
1328 | 0 | pub fn aggregate(networks: &Vec<Ipv6Net>) -> Vec<Ipv6Net> { |
1329 | 0 | let mut intervals: Vec<(_, _)> = networks.iter().map(|n| n.interval()).collect(); |
1330 | 0 | intervals = merge_intervals(intervals); |
1331 | 0 | let mut res: Vec<Ipv6Net> = Vec::new(); |
1332 | | |
1333 | 0 | for (start, mut end) in intervals { |
1334 | 0 | if end != core::u128::MAX { |
1335 | 0 | end = end.saturating_sub(1) |
1336 | 0 | } |
1337 | 0 | let iter = Ipv6Subnets::new(start.into(), end.into(), 0); |
1338 | 0 | res.extend(iter); |
1339 | | } |
1340 | 0 | res |
1341 | 0 | } |
1342 | | } |
1343 | | |
1344 | | impl Default for Ipv6Net { |
1345 | 0 | fn default() -> Self { |
1346 | 0 | Self { |
1347 | 0 | addr: Ipv6Addr::from(0), |
1348 | 0 | prefix_len: 0, |
1349 | 0 | } |
1350 | 0 | } |
1351 | | } |
1352 | | |
1353 | | impl fmt::Debug for Ipv6Net { |
1354 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
1355 | 0 | fmt::Display::fmt(self, fmt) |
1356 | 0 | } |
1357 | | } |
1358 | | |
1359 | | impl fmt::Display for Ipv6Net { |
1360 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
1361 | 0 | write!(fmt, "{}/{}", self.addr, self.prefix_len) |
1362 | 0 | } |
1363 | | } |
1364 | | |
1365 | | impl From<Ipv6Addr> for Ipv6Net { |
1366 | 0 | fn from(addr: Ipv6Addr) -> Ipv6Net { |
1367 | 0 | Ipv6Net { addr, prefix_len: 128 } |
1368 | 0 | } |
1369 | | } |
1370 | | |
1371 | | /// Provides a method to test if a network address contains either |
1372 | | /// another network address or an IP address. |
1373 | | /// |
1374 | | /// # Examples |
1375 | | /// |
1376 | | /// ``` |
1377 | | /// # use std::net::IpAddr; |
1378 | | /// # use ipnet::IpNet; |
1379 | | /// # |
1380 | | /// let n4_1: IpNet = "10.1.1.0/24".parse().unwrap(); |
1381 | | /// let n4_2: IpNet = "10.1.1.0/26".parse().unwrap(); |
1382 | | /// let n4_3: IpNet = "10.1.2.0/26".parse().unwrap(); |
1383 | | /// let ip4_1: IpAddr = "10.1.1.1".parse().unwrap(); |
1384 | | /// let ip4_2: IpAddr = "10.1.2.1".parse().unwrap(); |
1385 | | /// |
1386 | | /// let n6_1: IpNet = "fd00::/16".parse().unwrap(); |
1387 | | /// let n6_2: IpNet = "fd00::/17".parse().unwrap(); |
1388 | | /// let n6_3: IpNet = "fd01::/17".parse().unwrap(); |
1389 | | /// let ip6_1: IpAddr = "fd00::1".parse().unwrap(); |
1390 | | /// let ip6_2: IpAddr = "fd01::1".parse().unwrap(); |
1391 | | /// |
1392 | | /// assert!(n4_1.contains(&n4_2)); |
1393 | | /// assert!(!n4_1.contains(&n4_3)); |
1394 | | /// assert!(n4_1.contains(&ip4_1)); |
1395 | | /// assert!(!n4_1.contains(&ip4_2)); |
1396 | | /// |
1397 | | /// assert!(n6_1.contains(&n6_2)); |
1398 | | /// assert!(!n6_1.contains(&n6_3)); |
1399 | | /// assert!(n6_1.contains(&ip6_1)); |
1400 | | /// assert!(!n6_1.contains(&ip6_2)); |
1401 | | /// |
1402 | | /// assert!(!n4_1.contains(&n6_1) && !n6_1.contains(&n4_1)); |
1403 | | /// assert!(!n4_1.contains(&ip6_1) && !n6_1.contains(&ip4_1)); |
1404 | | /// ``` |
1405 | | pub trait Contains<T> { |
1406 | | fn contains(&self, other: T) -> bool; |
1407 | | } |
1408 | | |
1409 | | impl<'a> Contains<&'a IpNet> for IpNet { |
1410 | 0 | fn contains(&self, other: &IpNet) -> bool { |
1411 | 0 | match (*self, *other) { |
1412 | 0 | (IpNet::V4(ref a), IpNet::V4(ref b)) => a.contains(b), |
1413 | 0 | (IpNet::V6(ref a), IpNet::V6(ref b)) => a.contains(b), |
1414 | 0 | _ => false, |
1415 | | } |
1416 | 0 | } |
1417 | | } |
1418 | | |
1419 | | impl<'a> Contains<&'a IpAddr> for IpNet { |
1420 | 0 | fn contains(&self, other: &IpAddr) -> bool { |
1421 | 0 | match (*self, *other) { |
1422 | 0 | (IpNet::V4(ref a), IpAddr::V4(ref b)) => a.contains(b), |
1423 | 0 | (IpNet::V6(ref a), IpAddr::V6(ref b)) => a.contains(b), |
1424 | 0 | _ => false, |
1425 | | } |
1426 | 0 | } |
1427 | | } |
1428 | | |
1429 | | impl<'a> Contains<&'a Ipv4Net> for Ipv4Net { |
1430 | 0 | fn contains(&self, other: &'a Ipv4Net) -> bool { |
1431 | 0 | self.network() <= other.network() && other.broadcast() <= self.broadcast() |
1432 | 0 | } |
1433 | | } |
1434 | | |
1435 | | impl<'a> Contains<&'a Ipv4Addr> for Ipv4Net { |
1436 | 0 | fn contains(&self, other: &'a Ipv4Addr) -> bool { |
1437 | 0 | self.network() <= *other && *other <= self.broadcast() |
1438 | 0 | } |
1439 | | } |
1440 | | |
1441 | | impl<'a> Contains<&'a Ipv6Net> for Ipv6Net { |
1442 | 0 | fn contains(&self, other: &'a Ipv6Net) -> bool { |
1443 | 0 | self.network() <= other.network() && other.broadcast() <= self.broadcast() |
1444 | 0 | } |
1445 | | } |
1446 | | |
1447 | | impl<'a> Contains<&'a Ipv6Addr> for Ipv6Net { |
1448 | 0 | fn contains(&self, other: &'a Ipv6Addr) -> bool { |
1449 | 0 | self.network() <= *other && *other <= self.broadcast() |
1450 | 0 | } |
1451 | | } |
1452 | | |
1453 | | /// An `Iterator` that generates IP network addresses, either IPv4 or |
1454 | | /// IPv6. |
1455 | | /// |
1456 | | /// Generates the subnets between the provided `start` and `end` IP |
1457 | | /// addresses inclusive of `end`. Each iteration generates the next |
1458 | | /// network address of the largest valid size it can, while using a |
1459 | | /// prefix length not less than `min_prefix_len`. |
1460 | | /// |
1461 | | /// # Examples |
1462 | | /// |
1463 | | /// ``` |
1464 | | /// # use std::net::{Ipv4Addr, Ipv6Addr}; |
1465 | | /// # use std::str::FromStr; |
1466 | | /// # use ipnet::{IpNet, IpSubnets, Ipv4Subnets, Ipv6Subnets}; |
1467 | | /// let subnets = IpSubnets::from(Ipv4Subnets::new( |
1468 | | /// "10.0.0.0".parse().unwrap(), |
1469 | | /// "10.0.0.239".parse().unwrap(), |
1470 | | /// 26, |
1471 | | /// )); |
1472 | | /// |
1473 | | /// assert_eq!(subnets.collect::<Vec<IpNet>>(), vec![ |
1474 | | /// "10.0.0.0/26".parse().unwrap(), |
1475 | | /// "10.0.0.64/26".parse().unwrap(), |
1476 | | /// "10.0.0.128/26".parse().unwrap(), |
1477 | | /// "10.0.0.192/27".parse().unwrap(), |
1478 | | /// "10.0.0.224/28".parse().unwrap(), |
1479 | | /// ]); |
1480 | | /// |
1481 | | /// let subnets = IpSubnets::from(Ipv6Subnets::new( |
1482 | | /// "fd00::".parse().unwrap(), |
1483 | | /// "fd00:ef:ffff:ffff:ffff:ffff:ffff:ffff".parse().unwrap(), |
1484 | | /// 26, |
1485 | | /// )); |
1486 | | /// |
1487 | | /// assert_eq!(subnets.collect::<Vec<IpNet>>(), vec![ |
1488 | | /// "fd00::/26".parse().unwrap(), |
1489 | | /// "fd00:40::/26".parse().unwrap(), |
1490 | | /// "fd00:80::/26".parse().unwrap(), |
1491 | | /// "fd00:c0::/27".parse().unwrap(), |
1492 | | /// "fd00:e0::/28".parse().unwrap(), |
1493 | | /// ]); |
1494 | | /// ``` |
1495 | | #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] |
1496 | | pub enum IpSubnets { |
1497 | | V4(Ipv4Subnets), |
1498 | | V6(Ipv6Subnets), |
1499 | | } |
1500 | | |
1501 | | /// An `Iterator` that generates IPv4 network addresses. |
1502 | | /// |
1503 | | /// Generates the subnets between the provided `start` and `end` IP |
1504 | | /// addresses inclusive of `end`. Each iteration generates the next |
1505 | | /// network address of the largest valid size it can, while using a |
1506 | | /// prefix length not less than `min_prefix_len`. |
1507 | | /// |
1508 | | /// # Examples |
1509 | | /// |
1510 | | /// ``` |
1511 | | /// # use std::net::Ipv4Addr; |
1512 | | /// # use std::str::FromStr; |
1513 | | /// # use ipnet::{Ipv4Net, Ipv4Subnets}; |
1514 | | /// let subnets = Ipv4Subnets::new( |
1515 | | /// "10.0.0.0".parse().unwrap(), |
1516 | | /// "10.0.0.239".parse().unwrap(), |
1517 | | /// 26, |
1518 | | /// ); |
1519 | | /// |
1520 | | /// assert_eq!(subnets.collect::<Vec<Ipv4Net>>(), vec![ |
1521 | | /// "10.0.0.0/26".parse().unwrap(), |
1522 | | /// "10.0.0.64/26".parse().unwrap(), |
1523 | | /// "10.0.0.128/26".parse().unwrap(), |
1524 | | /// "10.0.0.192/27".parse().unwrap(), |
1525 | | /// "10.0.0.224/28".parse().unwrap(), |
1526 | | /// ]); |
1527 | | /// ``` |
1528 | | #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] |
1529 | | pub struct Ipv4Subnets { |
1530 | | start: Ipv4Addr, |
1531 | | end: Ipv4Addr, // end is inclusive |
1532 | | min_prefix_len: u8, |
1533 | | } |
1534 | | |
1535 | | /// An `Iterator` that generates IPv6 network addresses. |
1536 | | /// |
1537 | | /// Generates the subnets between the provided `start` and `end` IP |
1538 | | /// addresses inclusive of `end`. Each iteration generates the next |
1539 | | /// network address of the largest valid size it can, while using a |
1540 | | /// prefix length not less than `min_prefix_len`. |
1541 | | /// |
1542 | | /// # Examples |
1543 | | /// |
1544 | | /// ``` |
1545 | | /// # use std::net::Ipv6Addr; |
1546 | | /// # use std::str::FromStr; |
1547 | | /// # use ipnet::{Ipv6Net, Ipv6Subnets}; |
1548 | | /// let subnets = Ipv6Subnets::new( |
1549 | | /// "fd00::".parse().unwrap(), |
1550 | | /// "fd00:ef:ffff:ffff:ffff:ffff:ffff:ffff".parse().unwrap(), |
1551 | | /// 26, |
1552 | | /// ); |
1553 | | /// |
1554 | | /// assert_eq!(subnets.collect::<Vec<Ipv6Net>>(), vec![ |
1555 | | /// "fd00::/26".parse().unwrap(), |
1556 | | /// "fd00:40::/26".parse().unwrap(), |
1557 | | /// "fd00:80::/26".parse().unwrap(), |
1558 | | /// "fd00:c0::/27".parse().unwrap(), |
1559 | | /// "fd00:e0::/28".parse().unwrap(), |
1560 | | /// ]); |
1561 | | /// ``` |
1562 | | #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] |
1563 | | pub struct Ipv6Subnets { |
1564 | | start: Ipv6Addr, |
1565 | | end: Ipv6Addr, // end is inclusive |
1566 | | min_prefix_len: u8, |
1567 | | } |
1568 | | |
1569 | | impl Ipv4Subnets { |
1570 | 0 | pub fn new(start: Ipv4Addr, end: Ipv4Addr, min_prefix_len: u8) -> Self { |
1571 | 0 | Ipv4Subnets { |
1572 | 0 | start: start, |
1573 | 0 | end: end, |
1574 | 0 | min_prefix_len: min_prefix_len, |
1575 | 0 | } |
1576 | 0 | } |
1577 | | } |
1578 | | |
1579 | | impl Ipv6Subnets { |
1580 | 0 | pub fn new(start: Ipv6Addr, end: Ipv6Addr, min_prefix_len: u8) -> Self { |
1581 | 0 | Ipv6Subnets { |
1582 | 0 | start: start, |
1583 | 0 | end: end, |
1584 | 0 | min_prefix_len: min_prefix_len, |
1585 | 0 | } |
1586 | 0 | } |
1587 | | } |
1588 | | |
1589 | | impl From<Ipv4Subnets> for IpSubnets { |
1590 | 0 | fn from(i: Ipv4Subnets) -> IpSubnets { |
1591 | 0 | IpSubnets::V4(i) |
1592 | 0 | } |
1593 | | } |
1594 | | |
1595 | | impl From<Ipv6Subnets> for IpSubnets { |
1596 | 0 | fn from(i: Ipv6Subnets) -> IpSubnets { |
1597 | 0 | IpSubnets::V6(i) |
1598 | 0 | } |
1599 | | } |
1600 | | |
1601 | | impl Iterator for IpSubnets { |
1602 | | type Item = IpNet; |
1603 | | |
1604 | 0 | fn next(&mut self) -> Option<Self::Item> { |
1605 | 0 | match *self { |
1606 | 0 | IpSubnets::V4(ref mut a) => a.next().map(IpNet::V4), |
1607 | 0 | IpSubnets::V6(ref mut a) => a.next().map(IpNet::V6), |
1608 | | } |
1609 | 0 | } |
1610 | | } |
1611 | | |
1612 | 0 | fn next_ipv4_subnet(start: Ipv4Addr, end: Ipv4Addr, min_prefix_len: u8) -> Ipv4Net { |
1613 | 0 | let range = end.saturating_sub(start).saturating_add(1); |
1614 | 0 | if range == core::u32::MAX && min_prefix_len == 0 { |
1615 | 0 | Ipv4Net::new(start, min_prefix_len).unwrap() |
1616 | | } |
1617 | | else { |
1618 | 0 | let range_bits = 32u32.saturating_sub(range.leading_zeros()).saturating_sub(1); |
1619 | 0 | let start_tz = u32::from(start).trailing_zeros(); |
1620 | 0 | let new_prefix_len = 32 - min(range_bits, start_tz); |
1621 | 0 | let next_prefix_len = max(new_prefix_len as u8, min_prefix_len); |
1622 | 0 | Ipv4Net::new(start, next_prefix_len).unwrap() |
1623 | | } |
1624 | 0 | } |
1625 | | |
1626 | 0 | fn next_ipv6_subnet(start: Ipv6Addr, end: Ipv6Addr, min_prefix_len: u8) -> Ipv6Net { |
1627 | 0 | let range = end.saturating_sub(start).saturating_add(1); |
1628 | 0 | if range == core::u128::MAX && min_prefix_len == 0 { |
1629 | 0 | Ipv6Net::new(start, min_prefix_len).unwrap() |
1630 | | } |
1631 | | else { |
1632 | 0 | let range = end.saturating_sub(start).saturating_add(1); |
1633 | 0 | let range_bits = 128u32.saturating_sub(range.leading_zeros()).saturating_sub(1); |
1634 | 0 | let start_tz = u128::from(start).trailing_zeros(); |
1635 | 0 | let new_prefix_len = 128 - min(range_bits, start_tz); |
1636 | 0 | let next_prefix_len = max(new_prefix_len as u8, min_prefix_len); |
1637 | 0 | Ipv6Net::new(start, next_prefix_len).unwrap() |
1638 | | } |
1639 | 0 | } |
1640 | | |
1641 | | impl Iterator for Ipv4Subnets { |
1642 | | type Item = Ipv4Net; |
1643 | | |
1644 | 0 | fn next(&mut self) -> Option<Self::Item> { |
1645 | 0 | match self.start.partial_cmp(&self.end) { |
1646 | | Some(Less) => { |
1647 | 0 | let next = next_ipv4_subnet(self.start, self.end, self.min_prefix_len); |
1648 | 0 | self.start = next.broadcast().saturating_add(1); |
1649 | | |
1650 | | // Stop the iterator if we saturated self.start. This |
1651 | | // check worsens performance slightly but overall this |
1652 | | // approach of operating on Ipv4Addr types is faster |
1653 | | // than what we were doing before using Ipv4Net. |
1654 | 0 | if self.start == next.broadcast() { |
1655 | 0 | self.end.replace_zero(); |
1656 | 0 | } |
1657 | 0 | Some(next) |
1658 | | }, |
1659 | | Some(Equal) => { |
1660 | 0 | let next = next_ipv4_subnet(self.start, self.end, self.min_prefix_len); |
1661 | 0 | self.start = next.broadcast().saturating_add(1); |
1662 | 0 | self.end.replace_zero(); |
1663 | 0 | Some(next) |
1664 | | }, |
1665 | 0 | _ => None, |
1666 | | } |
1667 | 0 | } |
1668 | | } |
1669 | | |
1670 | | impl Iterator for Ipv6Subnets { |
1671 | | type Item = Ipv6Net; |
1672 | | |
1673 | 0 | fn next(&mut self) -> Option<Self::Item> { |
1674 | 0 | match self.start.partial_cmp(&self.end) { |
1675 | | Some(Less) => { |
1676 | 0 | let next = next_ipv6_subnet(self.start, self.end, self.min_prefix_len); |
1677 | 0 | self.start = next.broadcast().saturating_add(1); |
1678 | | |
1679 | | // Stop the iterator if we saturated self.start. This |
1680 | | // check worsens performance slightly but overall this |
1681 | | // approach of operating on Ipv6Addr types is faster |
1682 | | // than what we were doing before using Ipv6Net. |
1683 | 0 | if self.start == next.broadcast() { |
1684 | 0 | self.end.replace_zero(); |
1685 | 0 | } |
1686 | 0 | Some(next) |
1687 | | }, |
1688 | | Some(Equal) => { |
1689 | 0 | let next = next_ipv6_subnet(self.start, self.end, self.min_prefix_len); |
1690 | 0 | self.start = next.broadcast().saturating_add(1); |
1691 | 0 | self.end.replace_zero(); |
1692 | 0 | Some(next) |
1693 | | }, |
1694 | 0 | _ => None, |
1695 | | } |
1696 | 0 | } |
1697 | | } |
1698 | | |
1699 | | impl FusedIterator for IpSubnets {} |
1700 | | impl FusedIterator for Ipv4Subnets {} |
1701 | | impl FusedIterator for Ipv6Subnets {} |
1702 | | |
1703 | | // Generic function for merging a vector of intervals. |
1704 | 0 | fn merge_intervals<T: Copy + Ord>(mut intervals: Vec<(T, T)>) -> Vec<(T, T)> { |
1705 | 0 | if intervals.len() == 0 { |
1706 | 0 | return intervals; |
1707 | 0 | } |
1708 | | |
1709 | 0 | intervals.sort(); |
1710 | 0 | let mut res: Vec<(T, T)> = Vec::new(); |
1711 | 0 | let (mut start, mut end) = intervals[0]; |
1712 | | |
1713 | 0 | let mut i = 1; |
1714 | 0 | let len = intervals.len(); |
1715 | 0 | while i < len { |
1716 | 0 | let (next_start, next_end) = intervals[i]; |
1717 | 0 | if end >= next_start { |
1718 | 0 | start = min(start, next_start); |
1719 | 0 | end = max(end, next_end); |
1720 | 0 | } |
1721 | 0 | else { |
1722 | 0 | res.push((start, end)); |
1723 | 0 | start = next_start; |
1724 | 0 | end = next_end; |
1725 | 0 | } |
1726 | 0 | i += 1; |
1727 | | } |
1728 | | |
1729 | 0 | res.push((start, end)); |
1730 | 0 | res |
1731 | 0 | } Unexecuted instantiation: ipnet::ipnet::merge_intervals::<u32> Unexecuted instantiation: ipnet::ipnet::merge_intervals::<u128> |
1732 | | |
1733 | | #[cfg(test)] |
1734 | | mod tests { |
1735 | | use super::*; |
1736 | | |
1737 | | macro_rules! make_ipnet_vec { |
1738 | | ($($x:expr),*) => ( vec![$($x.parse::<IpNet>().unwrap(),)*] ); |
1739 | | ($($x:expr,)*) => ( make_ipnet_vec![$($x),*] ); |
1740 | | } |
1741 | | |
1742 | | #[test] |
1743 | | fn test_make_ipnet_vec() { |
1744 | | assert_eq!( |
1745 | | make_ipnet_vec![ |
1746 | | "10.1.1.1/32", "10.2.2.2/24", "10.3.3.3/16", |
1747 | | "fd00::1/128", "fd00::2/127", "fd00::3/126", |
1748 | | ], |
1749 | | vec![ |
1750 | | "10.1.1.1/32".parse().unwrap(), |
1751 | | "10.2.2.2/24".parse().unwrap(), |
1752 | | "10.3.3.3/16".parse().unwrap(), |
1753 | | "fd00::1/128".parse().unwrap(), |
1754 | | "fd00::2/127".parse().unwrap(), |
1755 | | "fd00::3/126".parse().unwrap(), |
1756 | | ] |
1757 | | ); |
1758 | | } |
1759 | | |
1760 | | #[test] |
1761 | | fn test_merge_intervals() { |
1762 | | let v = vec![ |
1763 | | (0, 1), (1, 2), (2, 3), |
1764 | | (11, 12), (13, 14), (10, 15), (11, 13), |
1765 | | (20, 25), (24, 29), |
1766 | | ]; |
1767 | | |
1768 | | let v_ok = vec![ |
1769 | | (0, 3), |
1770 | | (10, 15), |
1771 | | (20, 29), |
1772 | | ]; |
1773 | | |
1774 | | let vv = vec![ |
1775 | | ([0, 1], [0, 2]), ([0, 2], [0, 3]), ([0, 0], [0, 1]), |
1776 | | ([10, 15], [11, 0]), ([10, 0], [10, 16]), |
1777 | | ]; |
1778 | | |
1779 | | let vv_ok = vec![ |
1780 | | ([0, 0], [0, 3]), |
1781 | | ([10, 0], [11, 0]), |
1782 | | ]; |
1783 | | |
1784 | | assert_eq!(merge_intervals(v), v_ok); |
1785 | | assert_eq!(merge_intervals(vv), vv_ok); |
1786 | | } |
1787 | | |
1788 | | macro_rules! make_ipv4_subnets_test { |
1789 | | ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr),*) => ( |
1790 | | #[test] |
1791 | | fn $name() { |
1792 | | let subnets = IpSubnets::from(Ipv4Subnets::new( |
1793 | | $start.parse().unwrap(), |
1794 | | $end.parse().unwrap(), |
1795 | | $min_prefix_len, |
1796 | | )); |
1797 | | let results = make_ipnet_vec![$($x),*]; |
1798 | | assert_eq!(subnets.collect::<Vec<IpNet>>(), results); |
1799 | | } |
1800 | | ); |
1801 | | ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr,)*) => ( |
1802 | | make_ipv4_subnets_test!($name, $start, $end, $min_prefix_len, $($x),*); |
1803 | | ); |
1804 | | } |
1805 | | |
1806 | | macro_rules! make_ipv6_subnets_test { |
1807 | | ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr),*) => ( |
1808 | | #[test] |
1809 | | fn $name() { |
1810 | | let subnets = IpSubnets::from(Ipv6Subnets::new( |
1811 | | $start.parse().unwrap(), |
1812 | | $end.parse().unwrap(), |
1813 | | $min_prefix_len, |
1814 | | )); |
1815 | | let results = make_ipnet_vec![$($x),*]; |
1816 | | assert_eq!(subnets.collect::<Vec<IpNet>>(), results); |
1817 | | } |
1818 | | ); |
1819 | | ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr,)*) => ( |
1820 | | make_ipv6_subnets_test!($name, $start, $end, $min_prefix_len, $($x),*); |
1821 | | ); |
1822 | | } |
1823 | | |
1824 | | make_ipv4_subnets_test!( |
1825 | | test_ipv4_subnets_zero_zero, |
1826 | | "0.0.0.0", "0.0.0.0", 0, |
1827 | | "0.0.0.0/32", |
1828 | | ); |
1829 | | |
1830 | | make_ipv4_subnets_test!( |
1831 | | test_ipv4_subnets_zero_max, |
1832 | | "0.0.0.0", "255.255.255.255", 0, |
1833 | | "0.0.0.0/0", |
1834 | | ); |
1835 | | |
1836 | | make_ipv4_subnets_test!( |
1837 | | test_ipv4_subnets_max_max, |
1838 | | "255.255.255.255", "255.255.255.255", 0, |
1839 | | "255.255.255.255/32", |
1840 | | ); |
1841 | | |
1842 | | make_ipv4_subnets_test!( |
1843 | | test_ipv4_subnets_none, |
1844 | | "0.0.0.1", "0.0.0.0", 0, |
1845 | | ); |
1846 | | |
1847 | | make_ipv4_subnets_test!( |
1848 | | test_ipv4_subnets_one, |
1849 | | "0.0.0.0", "0.0.0.1", 0, |
1850 | | "0.0.0.0/31", |
1851 | | ); |
1852 | | |
1853 | | make_ipv4_subnets_test!( |
1854 | | test_ipv4_subnets_two, |
1855 | | "0.0.0.0", "0.0.0.2", 0, |
1856 | | "0.0.0.0/31", |
1857 | | "0.0.0.2/32", |
1858 | | ); |
1859 | | |
1860 | | make_ipv4_subnets_test!( |
1861 | | test_ipv4_subnets_taper, |
1862 | | "0.0.0.0", "0.0.0.10", 30, |
1863 | | "0.0.0.0/30", |
1864 | | "0.0.0.4/30", |
1865 | | "0.0.0.8/31", |
1866 | | "0.0.0.10/32", |
1867 | | ); |
1868 | | |
1869 | | make_ipv6_subnets_test!( |
1870 | | test_ipv6_subnets_zero_zero, |
1871 | | "::", "::", 0, |
1872 | | "::/128", |
1873 | | ); |
1874 | | |
1875 | | make_ipv6_subnets_test!( |
1876 | | test_ipv6_subnets_zero_max, |
1877 | | "::", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, |
1878 | | "::/0", |
1879 | | ); |
1880 | | |
1881 | | make_ipv6_subnets_test!( |
1882 | | test_ipv6_subnets_max_max, |
1883 | | "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, |
1884 | | "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128", |
1885 | | ); |
1886 | | |
1887 | | make_ipv6_subnets_test!( |
1888 | | test_ipv6_subnets_none, |
1889 | | "::1", "::", 0, |
1890 | | ); |
1891 | | |
1892 | | make_ipv6_subnets_test!( |
1893 | | test_ipv6_subnets_one, |
1894 | | "::", "::1", 0, |
1895 | | "::/127", |
1896 | | ); |
1897 | | |
1898 | | make_ipv6_subnets_test!( |
1899 | | test_ipv6_subnets_two, |
1900 | | "::", "::2", 0, |
1901 | | "::/127", |
1902 | | "::2/128", |
1903 | | ); |
1904 | | |
1905 | | make_ipv6_subnets_test!( |
1906 | | test_ipv6_subnets_taper, |
1907 | | "::", "::a", 126, |
1908 | | "::/126", |
1909 | | "::4/126", |
1910 | | "::8/127", |
1911 | | "::a/128", |
1912 | | ); |
1913 | | |
1914 | | #[test] |
1915 | | fn test_aggregate() { |
1916 | | let ip_nets = make_ipnet_vec![ |
1917 | | "10.0.0.0/24", "10.0.1.0/24", "10.0.1.1/24", "10.0.1.2/24", |
1918 | | "10.0.2.0/24", |
1919 | | "10.1.0.0/24", "10.1.1.0/24", |
1920 | | "192.168.0.0/24", "192.168.1.0/24", "192.168.2.0/24", "192.168.3.0/24", |
1921 | | "fd00::/32", "fd00:1::/32", |
1922 | | "fd00:2::/32", |
1923 | | ]; |
1924 | | |
1925 | | let ip_aggs = make_ipnet_vec![ |
1926 | | "10.0.0.0/23", |
1927 | | "10.0.2.0/24", |
1928 | | "10.1.0.0/23", |
1929 | | "192.168.0.0/22", |
1930 | | "fd00::/31", |
1931 | | "fd00:2::/32", |
1932 | | ]; |
1933 | | |
1934 | | let ipv4_nets: Vec<Ipv4Net> = ip_nets.iter().filter_map(|p| if let IpNet::V4(x) = *p { Some(x) } else { None }).collect(); |
1935 | | let ipv4_aggs: Vec<Ipv4Net> = ip_aggs.iter().filter_map(|p| if let IpNet::V4(x) = *p { Some(x) } else { None }).collect(); |
1936 | | let ipv6_nets: Vec<Ipv6Net> = ip_nets.iter().filter_map(|p| if let IpNet::V6(x) = *p { Some(x) } else { None }).collect(); |
1937 | | let ipv6_aggs: Vec<Ipv6Net> = ip_aggs.iter().filter_map(|p| if let IpNet::V6(x) = *p { Some(x) } else { None }).collect(); |
1938 | | |
1939 | | assert_eq!(IpNet::aggregate(&ip_nets), ip_aggs); |
1940 | | assert_eq!(Ipv4Net::aggregate(&ipv4_nets), ipv4_aggs); |
1941 | | assert_eq!(Ipv6Net::aggregate(&ipv6_nets), ipv6_aggs); |
1942 | | } |
1943 | | |
1944 | | #[test] |
1945 | | fn test_aggregate_issue44() { |
1946 | | let nets: Vec<Ipv4Net> = vec!["128.0.0.0/1".parse().unwrap()]; |
1947 | | assert_eq!(Ipv4Net::aggregate(&nets), nets); |
1948 | | |
1949 | | let nets: Vec<Ipv4Net> = vec!["0.0.0.0/1".parse().unwrap(), "128.0.0.0/1".parse().unwrap()]; |
1950 | | assert_eq!(Ipv4Net::aggregate(&nets), vec!["0.0.0.0/0".parse().unwrap()]); |
1951 | | |
1952 | | let nets: Vec<Ipv6Net> = vec!["8000::/1".parse().unwrap()]; |
1953 | | assert_eq!(Ipv6Net::aggregate(&nets), nets); |
1954 | | |
1955 | | let nets: Vec<Ipv6Net> = vec!["::/1".parse().unwrap(), "8000::/1".parse().unwrap()]; |
1956 | | assert_eq!(Ipv6Net::aggregate(&nets), vec!["::/0".parse().unwrap()]); |
1957 | | } |
1958 | | |
1959 | | #[test] |
1960 | | fn ipnet_default() { |
1961 | | let ipnet: IpNet = "0.0.0.0/0".parse().unwrap(); |
1962 | | assert_eq!(ipnet, IpNet::default()); |
1963 | | } |
1964 | | |
1965 | | #[test] |
1966 | | fn ipv4net_default() { |
1967 | | let ipnet: Ipv4Net = "0.0.0.0/0".parse().unwrap(); |
1968 | | assert_eq!(ipnet, Ipv4Net::default()); |
1969 | | } |
1970 | | |
1971 | | #[test] |
1972 | | fn ipv6net_default() { |
1973 | | let ipnet: Ipv6Net = "::/0".parse().unwrap(); |
1974 | | assert_eq!(ipnet, Ipv6Net::default()); |
1975 | | } |
1976 | | |
1977 | | #[test] |
1978 | | fn new_assert() { |
1979 | | const _: Ipv4Net = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 0); |
1980 | | const _: Ipv4Net = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 32); |
1981 | | const _: Ipv6Net = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 0); |
1982 | | const _: Ipv6Net = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 128); |
1983 | | |
1984 | | let _ = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 0); |
1985 | | let _ = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 32); |
1986 | | let _ = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 0); |
1987 | | let _ = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 128); |
1988 | | } |
1989 | | |
1990 | | #[test] |
1991 | | #[should_panic] |
1992 | | fn ipv4net_new_assert_panics() { |
1993 | | let _ = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 33); |
1994 | | } |
1995 | | |
1996 | | #[test] |
1997 | | #[should_panic] |
1998 | | fn ipv6net_new_assert_panics() { |
1999 | | let _ = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 129); |
2000 | | } |
2001 | | } |